Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(460)

Side by Side Diff: src/IceRegAlloc.cpp

Issue 619893002: Subzero: Auto-awesome iterators. (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: Use AsmCodeByte instead of uint8_t Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/IceOperand.cpp ('k') | src/IceTargetLowering.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 //===- subzero/src/IceRegAlloc.cpp - Linear-scan implementation -----------===// 1 //===- subzero/src/IceRegAlloc.cpp - Linear-scan implementation -----------===//
2 // 2 //
3 // The Subzero Code Generator 3 // The Subzero Code Generator
4 // 4 //
5 // This file is distributed under the University of Illinois Open Source 5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details. 6 // License. See LICENSE.TXT for details.
7 // 7 //
8 //===----------------------------------------------------------------------===// 8 //===----------------------------------------------------------------------===//
9 // 9 //
10 // This file implements the LinearScan class, which performs the 10 // This file implements the LinearScan class, which performs the
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
81 // balanced binary tree, so inserting live ranges for N variables is 81 // balanced binary tree, so inserting live ranges for N variables is
82 // O(N log N) complexity. N may be proportional to the number of 82 // O(N log N) complexity. N may be proportional to the number of
83 // instructions, thanks to temporary generation during lowering. As 83 // instructions, thanks to temporary generation during lowering. As
84 // a result, it may be useful to design a better data structure for 84 // a result, it may be useful to design a better data structure for
85 // storing Func->getVariables(). 85 // storing Func->getVariables().
86 const VarList &Vars = Func->getVariables(); 86 const VarList &Vars = Func->getVariables();
87 { 87 {
88 static TimerIdT IDinitUnhandled = 88 static TimerIdT IDinitUnhandled =
89 GlobalContext::getTimerID("initUnhandled"); 89 GlobalContext::getTimerID("initUnhandled");
90 TimerMarker T(IDinitUnhandled, Func->getContext()); 90 TimerMarker T(IDinitUnhandled, Func->getContext());
91 for (VarList::const_iterator I = Vars.begin(), E = Vars.end(); I != E; 91 for (Variable *Var : Vars) {
92 ++I) {
93 Variable *Var = *I;
94 // Explicitly don't consider zero-weight variables, which are 92 // Explicitly don't consider zero-weight variables, which are
95 // meant to be spill slots. 93 // meant to be spill slots.
96 if (Var->getWeight() == RegWeight::Zero) 94 if (Var->getWeight() == RegWeight::Zero)
97 continue; 95 continue;
98 // Don't bother if the variable has a null live range, which means 96 // Don't bother if the variable has a null live range, which means
99 // it was never referenced. 97 // it was never referenced.
100 if (Var->getLiveRange().isEmpty()) 98 if (Var->getLiveRange().isEmpty())
101 continue; 99 continue;
102 Unhandled.insert(LiveRangeWrapper(Var)); 100 Unhandled.insert(LiveRangeWrapper(Var));
103 if (Var->hasReg()) { 101 if (Var->hasReg()) {
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
144 Cur.dump(Func); 142 Cur.dump(Func);
145 Str << "\n"; 143 Str << "\n";
146 } 144 }
147 Active.push_back(Cur); 145 Active.push_back(Cur);
148 assert(RegUses[RegNum] >= 0); 146 assert(RegUses[RegNum] >= 0);
149 ++RegUses[RegNum]; 147 ++RegUses[RegNum];
150 continue; 148 continue;
151 } 149 }
152 150
153 // Check for active ranges that have expired or become inactive. 151 // Check for active ranges that have expired or become inactive.
154 for (UnorderedRanges::iterator I = Active.begin(), E = Active.end(); I != E; 152 for (auto I = Active.begin(), E = Active.end(); I != E; I = Next) {
155 I = Next) {
156 Next = I; 153 Next = I;
157 ++Next; 154 ++Next;
158 LiveRangeWrapper Item = *I; 155 LiveRangeWrapper Item = *I;
159 bool Moved = false; 156 bool Moved = false;
160 if (Item.endsBefore(Cur)) { 157 if (Item.endsBefore(Cur)) {
161 // Move Item from Active to Handled list. 158 // Move Item from Active to Handled list.
162 if (Verbose) { 159 if (Verbose) {
163 Str << "Expiring "; 160 Str << "Expiring ";
164 Item.dump(Func); 161 Item.dump(Func);
165 Str << "\n"; 162 Str << "\n";
(...skipping 15 matching lines...) Expand all
181 if (Moved) { 178 if (Moved) {
182 // Decrement Item from RegUses[]. 179 // Decrement Item from RegUses[].
183 assert(Item.Var->hasRegTmp()); 180 assert(Item.Var->hasRegTmp());
184 int32_t RegNum = Item.Var->getRegNumTmp(); 181 int32_t RegNum = Item.Var->getRegNumTmp();
185 --RegUses[RegNum]; 182 --RegUses[RegNum];
186 assert(RegUses[RegNum] >= 0); 183 assert(RegUses[RegNum] >= 0);
187 } 184 }
188 } 185 }
189 186
190 // Check for inactive ranges that have expired or reactivated. 187 // Check for inactive ranges that have expired or reactivated.
191 for (UnorderedRanges::iterator I = Inactive.begin(), E = Inactive.end(); 188 for (auto I = Inactive.begin(), E = Inactive.end(); I != E; I = Next) {
192 I != E; I = Next) {
193 Next = I; 189 Next = I;
194 ++Next; 190 ++Next;
195 LiveRangeWrapper Item = *I; 191 LiveRangeWrapper Item = *I;
196 if (Item.endsBefore(Cur)) { 192 if (Item.endsBefore(Cur)) {
197 // Move Item from Inactive to Handled list. 193 // Move Item from Inactive to Handled list.
198 if (Verbose) { 194 if (Verbose) {
199 Str << "Expiring "; 195 Str << "Expiring ";
200 Item.dump(Func); 196 Item.dump(Func);
201 Str << "\n"; 197 Str << "\n";
202 } 198 }
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
273 if (Verbose) { 269 if (Verbose) {
274 if (Prefer) { 270 if (Prefer) {
275 Str << "Initial Prefer=" << *Prefer << " R=" << PreferReg 271 Str << "Initial Prefer=" << *Prefer << " R=" << PreferReg
276 << " LIVE=" << Prefer->getLiveRange() << " Overlap=" << AllowOverlap 272 << " LIVE=" << Prefer->getLiveRange() << " Overlap=" << AllowOverlap
277 << "\n"; 273 << "\n";
278 } 274 }
279 } 275 }
280 276
281 // Remove registers from the Free[] list where an Inactive range 277 // Remove registers from the Free[] list where an Inactive range
282 // overlaps with the current range. 278 // overlaps with the current range.
283 for (UnorderedRanges::const_iterator I = Inactive.begin(), 279 for (const LiveRangeWrapper &Item : Inactive) {
284 E = Inactive.end();
285 I != E; ++I) {
286 LiveRangeWrapper Item = *I;
287 if (Item.overlaps(Cur)) { 280 if (Item.overlaps(Cur)) {
288 int32_t RegNum = Item.Var->getRegNumTmp(); 281 int32_t RegNum = Item.Var->getRegNumTmp();
289 // Don't assert(Free[RegNum]) because in theory (though 282 // Don't assert(Free[RegNum]) because in theory (though
290 // probably never in practice) there could be two inactive 283 // probably never in practice) there could be two inactive
291 // variables that were marked with AllowOverlap. 284 // variables that were marked with AllowOverlap.
292 Free[RegNum] = false; 285 Free[RegNum] = false;
293 // Disable AllowOverlap if an Inactive variable, which is not 286 // Disable AllowOverlap if an Inactive variable, which is not
294 // Prefer, shares Prefer's register, and has a definition 287 // Prefer, shares Prefer's register, and has a definition
295 // within Cur's live range. 288 // within Cur's live range.
296 if (AllowOverlap && Item.Var != Prefer && RegNum == PreferReg && 289 if (AllowOverlap && Item.Var != Prefer && RegNum == PreferReg &&
297 overlapsDefs(Func, Cur, Item.Var)) { 290 overlapsDefs(Func, Cur, Item.Var)) {
298 AllowOverlap = false; 291 AllowOverlap = false;
299 dumpDisableOverlap(Func, Item.Var, "Inactive"); 292 dumpDisableOverlap(Func, Item.Var, "Inactive");
300 } 293 }
301 } 294 }
302 } 295 }
303 296
304 // Disable AllowOverlap if an Active variable, which is not 297 // Disable AllowOverlap if an Active variable, which is not
305 // Prefer, shares Prefer's register, and has a definition within 298 // Prefer, shares Prefer's register, and has a definition within
306 // Cur's live range. 299 // Cur's live range.
307 for (UnorderedRanges::iterator I = Active.begin(), E = Active.end(); 300 for (const LiveRangeWrapper &Item : Active) {
308 AllowOverlap && I != E; ++I) {
309 LiveRangeWrapper Item = *I;
310 int32_t RegNum = Item.Var->getRegNumTmp(); 301 int32_t RegNum = Item.Var->getRegNumTmp();
311 if (Item.Var != Prefer && RegNum == PreferReg && 302 if (Item.Var != Prefer && RegNum == PreferReg &&
312 overlapsDefs(Func, Cur, Item.Var)) { 303 overlapsDefs(Func, Cur, Item.Var)) {
313 AllowOverlap = false; 304 AllowOverlap = false;
314 dumpDisableOverlap(Func, Item.Var, "Active"); 305 dumpDisableOverlap(Func, Item.Var, "Active");
315 } 306 }
316 } 307 }
317 308
318 // Remove registers from the Free[] list where an Unhandled range 309 // Remove registers from the Free[] list where an Unhandled range
319 // overlaps with the current range and is precolored. 310 // overlaps with the current range and is precolored.
320 // Cur.endsBefore(*I) is an early exit check that turns a 311 // Cur.endsBefore(Item) is an early exit check that turns a
321 // guaranteed O(N^2) algorithm into expected linear complexity. 312 // guaranteed O(N^2) algorithm into expected linear complexity.
322 llvm::SmallBitVector PrecoloredUnhandled(RegMask.size()); 313 llvm::SmallBitVector PrecoloredUnhandled(RegMask.size());
323 // Note: PrecoloredUnhandled is only used for dumping. 314 // Note: PrecoloredUnhandled is only used for dumping.
324 for (OrderedRanges::const_iterator I = Unhandled.begin(), 315 for (const LiveRangeWrapper &Item : Unhandled) {
325 E = Unhandled.end(); 316 if (Cur.endsBefore(Item))
326 I != E && !Cur.endsBefore(*I); ++I) { 317 break;
327 LiveRangeWrapper Item = *I;
328 if (Item.Var->hasReg() && Item.overlaps(Cur)) { 318 if (Item.Var->hasReg() && Item.overlaps(Cur)) {
329 int32_t ItemReg = Item.Var->getRegNum(); // Note: not getRegNumTmp() 319 int32_t ItemReg = Item.Var->getRegNum(); // Note: not getRegNumTmp()
330 Free[ItemReg] = false; 320 Free[ItemReg] = false;
331 PrecoloredUnhandled[ItemReg] = true; 321 PrecoloredUnhandled[ItemReg] = true;
332 // Disable AllowOverlap if the preferred register is one of 322 // Disable AllowOverlap if the preferred register is one of
333 // these precolored unhandled overlapping ranges. 323 // these precolored unhandled overlapping ranges.
334 if (AllowOverlap && ItemReg == PreferReg) { 324 if (AllowOverlap && ItemReg == PreferReg) {
335 AllowOverlap = false; 325 AllowOverlap = false;
336 dumpDisableOverlap(Func, Item.Var, "PrecoloredUnhandled"); 326 dumpDisableOverlap(Func, Item.Var, "PrecoloredUnhandled");
337 } 327 }
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
374 Str << "\n"; 364 Str << "\n";
375 } 365 }
376 assert(RegUses[RegNum] >= 0); 366 assert(RegUses[RegNum] >= 0);
377 ++RegUses[RegNum]; 367 ++RegUses[RegNum];
378 Active.push_back(Cur); 368 Active.push_back(Cur);
379 } else { 369 } else {
380 // Fallback: there are no free registers, so we look for the 370 // Fallback: there are no free registers, so we look for the
381 // lowest-weight register and see if Cur has higher weight. 371 // lowest-weight register and see if Cur has higher weight.
382 std::vector<RegWeight> Weights(RegMask.size()); 372 std::vector<RegWeight> Weights(RegMask.size());
383 // Check Active ranges. 373 // Check Active ranges.
384 for (UnorderedRanges::const_iterator I = Active.begin(), E = Active.end(); 374 for (const LiveRangeWrapper &Item : Active) {
385 I != E; ++I) {
386 LiveRangeWrapper Item = *I;
387 assert(Item.overlaps(Cur)); 375 assert(Item.overlaps(Cur));
388 int32_t RegNum = Item.Var->getRegNumTmp(); 376 int32_t RegNum = Item.Var->getRegNumTmp();
389 assert(Item.Var->hasRegTmp()); 377 assert(Item.Var->hasRegTmp());
390 Weights[RegNum].addWeight(Item.range().getWeight()); 378 Weights[RegNum].addWeight(Item.range().getWeight());
391 } 379 }
392 // Same as above, but check Inactive ranges instead of Active. 380 // Same as above, but check Inactive ranges instead of Active.
393 for (UnorderedRanges::const_iterator I = Inactive.begin(), 381 for (const LiveRangeWrapper &Item : Inactive) {
394 E = Inactive.end();
395 I != E; ++I) {
396 LiveRangeWrapper Item = *I;
397 int32_t RegNum = Item.Var->getRegNumTmp(); 382 int32_t RegNum = Item.Var->getRegNumTmp();
398 assert(Item.Var->hasRegTmp()); 383 assert(Item.Var->hasRegTmp());
399 if (Item.overlaps(Cur)) 384 if (Item.overlaps(Cur))
400 Weights[RegNum].addWeight(Item.range().getWeight()); 385 Weights[RegNum].addWeight(Item.range().getWeight());
401 } 386 }
402 // Check Unhandled ranges that overlap Cur and are precolored. 387 // Check Unhandled ranges that overlap Cur and are precolored.
403 // Cur.endsBefore(*I) is an early exit check that turns a 388 // Cur.endsBefore(*I) is an early exit check that turns a
404 // guaranteed O(N^2) algorithm into expected linear complexity. 389 // guaranteed O(N^2) algorithm into expected linear complexity.
405 for (OrderedRanges::const_iterator I = Unhandled.begin(), 390 for (const LiveRangeWrapper &Item : Unhandled) {
406 E = Unhandled.end(); 391 if (Cur.endsBefore(Item))
407 I != E && !Cur.endsBefore(*I); ++I) { 392 break;
408 LiveRangeWrapper Item = *I;
409 int32_t RegNum = Item.Var->getRegNumTmp(); 393 int32_t RegNum = Item.Var->getRegNumTmp();
410 if (RegNum < 0) 394 if (RegNum < 0)
411 continue; 395 continue;
412 if (Item.overlaps(Cur)) 396 if (Item.overlaps(Cur))
413 Weights[RegNum].setWeight(RegWeight::Inf); 397 Weights[RegNum].setWeight(RegWeight::Inf);
414 } 398 }
415 399
416 // All the weights are now calculated. Find the register with 400 // All the weights are now calculated. Find the register with
417 // smallest weight. 401 // smallest weight.
418 int32_t MinWeightIndex = RegMask.find_first(); 402 int32_t MinWeightIndex = RegMask.find_first();
(...skipping 10 matching lines...) Expand all
429 // don't allocate any register to it, and move it to the 413 // don't allocate any register to it, and move it to the
430 // Handled state. 414 // Handled state.
431 Handled.push_back(Cur); 415 Handled.push_back(Cur);
432 if (Cur.range().getWeight().isInf()) { 416 if (Cur.range().getWeight().isInf()) {
433 Func->setError("Unable to find a physical register for an " 417 Func->setError("Unable to find a physical register for an "
434 "infinite-weight live range"); 418 "infinite-weight live range");
435 } 419 }
436 } else { 420 } else {
437 // Evict all live ranges in Active that register number 421 // Evict all live ranges in Active that register number
438 // MinWeightIndex is assigned to. 422 // MinWeightIndex is assigned to.
439 for (UnorderedRanges::iterator I = Active.begin(), E = Active.end(); 423 for (auto I = Active.begin(), E = Active.end(); I != E; I = Next) {
440 I != E; I = Next) {
441 Next = I; 424 Next = I;
442 ++Next; 425 ++Next;
443 LiveRangeWrapper Item = *I; 426 LiveRangeWrapper Item = *I;
444 if (Item.Var->getRegNumTmp() == MinWeightIndex) { 427 if (Item.Var->getRegNumTmp() == MinWeightIndex) {
445 if (Verbose) { 428 if (Verbose) {
446 Str << "Evicting "; 429 Str << "Evicting ";
447 Item.dump(Func); 430 Item.dump(Func);
448 Str << "\n"; 431 Str << "\n";
449 } 432 }
450 --RegUses[MinWeightIndex]; 433 --RegUses[MinWeightIndex];
451 assert(RegUses[MinWeightIndex] >= 0); 434 assert(RegUses[MinWeightIndex] >= 0);
452 Item.Var->setRegNumTmp(Variable::NoRegister); 435 Item.Var->setRegNumTmp(Variable::NoRegister);
453 Active.erase(I); 436 Active.erase(I);
454 Handled.push_back(Item); 437 Handled.push_back(Item);
455 } 438 }
456 } 439 }
457 // Do the same for Inactive. 440 // Do the same for Inactive.
458 for (UnorderedRanges::iterator I = Inactive.begin(), E = Inactive.end(); 441 for (auto I = Inactive.begin(), E = Inactive.end(); I != E; I = Next) {
459 I != E; I = Next) {
460 Next = I; 442 Next = I;
461 ++Next; 443 ++Next;
462 LiveRangeWrapper Item = *I; 444 LiveRangeWrapper Item = *I;
463 // Note: The Item.overlaps(Cur) clause is not part of the 445 // Note: The Item.overlaps(Cur) clause is not part of the
464 // description of AssignMemLoc() in the original paper. But 446 // description of AssignMemLoc() in the original paper. But
465 // there doesn't seem to be any need to evict an inactive 447 // there doesn't seem to be any need to evict an inactive
466 // live range that doesn't overlap with the live range 448 // live range that doesn't overlap with the live range
467 // currently being considered. It's especially bad if we 449 // currently being considered. It's especially bad if we
468 // would end up evicting an infinite-weight but 450 // would end up evicting an infinite-weight but
469 // currently-inactive live range. The most common situation 451 // currently-inactive live range. The most common situation
(...skipping 19 matching lines...) Expand all
489 if (Verbose) { 471 if (Verbose) {
490 Str << "Allocating "; 472 Str << "Allocating ";
491 Cur.dump(Func); 473 Cur.dump(Func);
492 Str << "\n"; 474 Str << "\n";
493 } 475 }
494 } 476 }
495 } 477 }
496 dump(Func); 478 dump(Func);
497 } 479 }
498 // Move anything Active or Inactive to Handled for easier handling. 480 // Move anything Active or Inactive to Handled for easier handling.
499 for (UnorderedRanges::iterator I = Active.begin(), E = Active.end(); I != E; 481 for (const LiveRangeWrapper &I : Active)
500 I = Next) { 482 Handled.push_back(I);
501 Next = I; 483 Active.clear();
502 ++Next; 484 for (const LiveRangeWrapper &I : Inactive)
503 Handled.push_back(*I); 485 Handled.push_back(I);
504 Active.erase(I); 486 Inactive.clear();
505 }
506 for (UnorderedRanges::iterator I = Inactive.begin(), E = Inactive.end();
507 I != E; I = Next) {
508 Next = I;
509 ++Next;
510 Handled.push_back(*I);
511 Inactive.erase(I);
512 }
513 dump(Func); 487 dump(Func);
514 488
515 // Finish up by assigning RegNumTmp->RegNum for each Variable. 489 // Finish up by assigning RegNumTmp->RegNum for each Variable.
516 for (UnorderedRanges::const_iterator I = Handled.begin(), E = Handled.end(); 490 for (const LiveRangeWrapper &Item : Handled) {
517 I != E; ++I) {
518 LiveRangeWrapper Item = *I;
519 int32_t RegNum = Item.Var->getRegNumTmp(); 491 int32_t RegNum = Item.Var->getRegNumTmp();
520 if (Verbose) { 492 if (Verbose) {
521 if (!Item.Var->hasRegTmp()) { 493 if (!Item.Var->hasRegTmp()) {
522 Str << "Not assigning "; 494 Str << "Not assigning ";
523 Item.Var->dump(Func); 495 Item.Var->dump(Func);
524 Str << "\n"; 496 Str << "\n";
525 } else { 497 } else {
526 Str << (RegNum == Item.Var->getRegNum() ? "Reassigning " : "Assigning ") 498 Str << (RegNum == Item.Var->getRegNum() ? "Reassigning " : "Assigning ")
527 << Func->getTarget()->getRegName(RegNum, IceType_i32) << "(r" 499 << Func->getTarget()->getRegName(RegNum, IceType_i32) << "(r"
528 << RegNum << ") to "; 500 << RegNum << ") to ";
(...skipping 28 matching lines...) Expand all
557 Str << " Range=" << range(); 529 Str << " Range=" << range();
558 } 530 }
559 531
560 void LinearScan::dump(Cfg *Func) const { 532 void LinearScan::dump(Cfg *Func) const {
561 Ostream &Str = Func->getContext()->getStrDump(); 533 Ostream &Str = Func->getContext()->getStrDump();
562 if (!Func->getContext()->isVerbose(IceV_LinearScan)) 534 if (!Func->getContext()->isVerbose(IceV_LinearScan))
563 return; 535 return;
564 Func->resetCurrentNode(); 536 Func->resetCurrentNode();
565 Str << "**** Current regalloc state:\n"; 537 Str << "**** Current regalloc state:\n";
566 Str << "++++++ Handled:\n"; 538 Str << "++++++ Handled:\n";
567 for (UnorderedRanges::const_iterator I = Handled.begin(), E = Handled.end(); 539 for (const LiveRangeWrapper &Item : Handled) {
568 I != E; ++I) { 540 Item.dump(Func);
569 I->dump(Func);
570 Str << "\n"; 541 Str << "\n";
571 } 542 }
572 Str << "++++++ Unhandled:\n"; 543 Str << "++++++ Unhandled:\n";
573 for (OrderedRanges::const_iterator I = Unhandled.begin(), E = Unhandled.end(); 544 for (const LiveRangeWrapper &Item : Unhandled) {
574 I != E; ++I) { 545 Item.dump(Func);
575 I->dump(Func);
576 Str << "\n"; 546 Str << "\n";
577 } 547 }
578 Str << "++++++ Active:\n"; 548 Str << "++++++ Active:\n";
579 for (UnorderedRanges::const_iterator I = Active.begin(), E = Active.end(); 549 for (const LiveRangeWrapper &Item : Active) {
580 I != E; ++I) { 550 Item.dump(Func);
581 I->dump(Func);
582 Str << "\n"; 551 Str << "\n";
583 } 552 }
584 Str << "++++++ Inactive:\n"; 553 Str << "++++++ Inactive:\n";
585 for (UnorderedRanges::const_iterator I = Inactive.begin(), E = Inactive.end(); 554 for (const LiveRangeWrapper &Item : Inactive) {
586 I != E; ++I) { 555 Item.dump(Func);
587 I->dump(Func);
588 Str << "\n"; 556 Str << "\n";
589 } 557 }
590 } 558 }
591 559
592 } // end of namespace Ice 560 } // end of namespace Ice
OLDNEW
« no previous file with comments | « src/IceOperand.cpp ('k') | src/IceTargetLowering.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698