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

Side by Side Diff: src/IceRegAlloc.cpp

Issue 1319203005: Subzero. Changes the Register Allocator so that it is aware of register (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: make format Created 5 years, 3 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
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 /// \file 10 /// \file
(...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after
218 } 218 }
219 219
220 void LinearScan::init(RegAllocKind Kind) { 220 void LinearScan::init(RegAllocKind Kind) {
221 this->Kind = Kind; 221 this->Kind = Kind;
222 Unhandled.clear(); 222 Unhandled.clear();
223 UnhandledPrecolored.clear(); 223 UnhandledPrecolored.clear();
224 Handled.clear(); 224 Handled.clear();
225 Inactive.clear(); 225 Inactive.clear();
226 Active.clear(); 226 Active.clear();
227 227
228 TargetLowering *Target = Func->getTarget();
Jim Stichnoth 2015/09/03 17:48:49 I think maybe it's about time to make TargetLoweri
John 2015/09/03 22:38:24 Done.
229 SizeT NumRegs = Target->getNumRegisters();
230 RegAliases.resize(NumRegs);
231 for (SizeT Reg = 0; Reg < NumRegs; ++Reg) {
232 RegAliases[Reg] = &Target->getAliasesForRegister(Reg);
Jim Stichnoth 2015/09/03 17:48:49 Would it be easier/cleaner to just call something
John 2015/09/03 22:38:24 As we spoke offline, the underlying types holding
233 }
234
228 switch (Kind) { 235 switch (Kind) {
229 case RAK_Unknown: 236 case RAK_Unknown:
230 llvm::report_fatal_error("Invalid RAK_Unknown"); 237 llvm::report_fatal_error("Invalid RAK_Unknown");
231 break; 238 break;
232 case RAK_Global: 239 case RAK_Global:
233 case RAK_Phi: 240 case RAK_Phi:
234 initForGlobal(); 241 initForGlobal();
235 break; 242 break;
236 case RAK_InfOnly: 243 case RAK_InfOnly:
237 initForInfOnly(); 244 initForInfOnly();
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
333 Moved = true; 340 Moved = true;
334 } else if (!Item->rangeOverlapsStart(Cur)) { 341 } else if (!Item->rangeOverlapsStart(Cur)) {
335 // Move Item from Active to Inactive list. 342 // Move Item from Active to Inactive list.
336 dumpLiveRangeTrace("Inactivating ", Cur); 343 dumpLiveRangeTrace("Inactivating ", Cur);
337 moveItem(Active, Index, Inactive); 344 moveItem(Active, Index, Inactive);
338 Moved = true; 345 Moved = true;
339 } 346 }
340 if (Moved) { 347 if (Moved) {
341 // Decrement Item from RegUses[]. 348 // Decrement Item from RegUses[].
342 assert(Item->hasRegTmp()); 349 assert(Item->hasRegTmp());
343 int32_t RegNum = Item->getRegNumTmp(); 350 const llvm::SmallBitVector &Aliases = *RegAliases[Item->getRegNumTmp()];
344 --RegUses[RegNum]; 351 for (int32_t RegNum = Aliases.find_first(); RegNum >= 0;
Jim Stichnoth 2015/09/03 17:48:49 This repeated loop pattern uses 4 different variab
John 2015/09/03 22:38:24 Done.
345 assert(RegUses[RegNum] >= 0); 352 RegNum = Aliases.find_next(RegNum)) {
353 --RegUses[RegNum];
354 assert(RegUses[RegNum] >= 0);
355 }
346 } 356 }
347 } 357 }
348 } 358 }
349 359
350 void LinearScan::handleInactiveRangeExpiredOrReactivated(const Variable *Cur) { 360 void LinearScan::handleInactiveRangeExpiredOrReactivated(const Variable *Cur) {
351 for (SizeT I = Inactive.size(); I > 0; --I) { 361 for (SizeT I = Inactive.size(); I > 0; --I) {
352 const SizeT Index = I - 1; 362 const SizeT Index = I - 1;
353 Variable *Item = Inactive[Index]; 363 Variable *Item = Inactive[Index];
354 Item->trimLiveRange(Cur->getLiveRange().getStart()); 364 Item->trimLiveRange(Cur->getLiveRange().getStart());
355 if (Item->rangeEndsBefore(Cur)) { 365 if (Item->rangeEndsBefore(Cur)) {
356 // Move Item from Inactive to Handled list. 366 // Move Item from Inactive to Handled list.
357 dumpLiveRangeTrace("Expiring ", Cur); 367 dumpLiveRangeTrace("Expiring ", Cur);
358 moveItem(Inactive, Index, Handled); 368 moveItem(Inactive, Index, Handled);
359 } else if (Item->rangeOverlapsStart(Cur)) { 369 } else if (Item->rangeOverlapsStart(Cur)) {
360 // Move Item from Inactive to Active list. 370 // Move Item from Inactive to Active list.
361 dumpLiveRangeTrace("Reactivating ", Cur); 371 dumpLiveRangeTrace("Reactivating ", Cur);
362 moveItem(Inactive, Index, Active); 372 moveItem(Inactive, Index, Active);
363 // Increment Item in RegUses[]. 373 // Increment Item in RegUses[].
364 assert(Item->hasRegTmp()); 374 assert(Item->hasRegTmp());
365 int32_t RegNum = Item->getRegNumTmp(); 375 const llvm::SmallBitVector &Aliases = *RegAliases[Item->getRegNumTmp()];
366 assert(RegUses[RegNum] >= 0); 376 for (int32_t RegNum = Aliases.find_first(); RegNum >= 0;
367 ++RegUses[RegNum]; 377 RegNum = Aliases.find_next(RegNum)) {
378 assert(RegUses[RegNum] >= 0);
379 ++RegUses[RegNum];
380 }
368 } 381 }
369 } 382 }
370 } 383 }
371 384
372 // Infer register preference and allowable overlap. Only form a preference when 385 // Infer register preference and allowable overlap. Only form a preference when
373 // the current Variable has an unambiguous "first" definition. The preference 386 // the current Variable has an unambiguous "first" definition. The preference
374 // is some source Variable of the defining instruction that either is assigned 387 // is some source Variable of the defining instruction that either is assigned
375 // a register that is currently free, or that is assigned a register that is 388 // a register that is currently free, or that is assigned a register that is
376 // not free but overlap is allowed. Overlap is allowed when the Variable under 389 // not free but overlap is allowed. Overlap is allowed when the Variable under
377 // consideration is single-definition, and its definition is a simple 390 // consideration is single-definition, and its definition is a simple
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
452 // overlaps with the current range, and set those registers to infinite weight 465 // overlaps with the current range, and set those registers to infinite weight
453 // so that they aren't candidates for eviction. Cur->rangeEndsBefore(Item) is 466 // so that they aren't candidates for eviction. Cur->rangeEndsBefore(Item) is
454 // an early exit check that turns a guaranteed O(N^2) algorithm into expected 467 // an early exit check that turns a guaranteed O(N^2) algorithm into expected
455 // linear complexity. 468 // linear complexity.
456 void LinearScan::filterFreeWithPrecoloredRanges(IterationState &Iter) { 469 void LinearScan::filterFreeWithPrecoloredRanges(IterationState &Iter) {
457 for (Variable *Item : reverse_range(UnhandledPrecolored)) { 470 for (Variable *Item : reverse_range(UnhandledPrecolored)) {
458 assert(Item->hasReg()); 471 assert(Item->hasReg());
459 if (Iter.Cur->rangeEndsBefore(Item)) 472 if (Iter.Cur->rangeEndsBefore(Item))
460 break; 473 break;
461 if (Item->rangeOverlaps(Iter.Cur)) { 474 if (Item->rangeOverlaps(Iter.Cur)) {
462 int32_t ItemReg = Item->getRegNum(); // Note: not getRegNumTmp() 475 const llvm::SmallBitVector &Aliases =
463 Iter.Weights[ItemReg].setWeight(RegWeight::Inf); 476 *RegAliases[Item->getRegNum()]; // Note: not getRegNumTmp()
464 Iter.Free[ItemReg] = false; 477 for (int32_t ItemReg = Aliases.find_first(); ItemReg >= 0;
465 Iter.PrecoloredUnhandledMask[ItemReg] = true; 478 ItemReg = Aliases.find_next(ItemReg)) {
466 // Disable Iter.AllowOverlap if the preferred register is one of these 479 // TODO(jpp): This loop should not update the weight of "parent" (i.e.,
Jim Stichnoth 2015/09/03 17:48:49 I don't understand this TODO. The purpose of this
John 2015/09/03 22:38:24 Misplaced TODO.
467 // pre-colored unhandled overlapping ranges. 480 // larger) registers if its current weight is more than the new weight.
468 if (Iter.AllowOverlap && ItemReg == Iter.PreferReg) { 481 Iter.Weights[ItemReg].setWeight(RegWeight::Inf);
469 Iter.AllowOverlap = false; 482 Iter.Free[ItemReg] = false;
470 dumpDisableOverlap(Func, Item, "PrecoloredUnhandled"); 483 Iter.PrecoloredUnhandledMask[ItemReg] = true;
484 // Disable Iter.AllowOverlap if the preferred register is one of these
485 // pre-colored unhandled overlapping ranges.
486 if (Iter.AllowOverlap && ItemReg == Iter.PreferReg) {
487 Iter.AllowOverlap = false;
488 dumpDisableOverlap(Func, Item, "PrecoloredUnhandled");
489 }
471 } 490 }
472 } 491 }
473 } 492 }
474 } 493 }
475 494
476 void LinearScan::allocatePrecoloredRegister(Variable *Cur) { 495 void LinearScan::allocatePrecoloredRegister(Variable *Cur) {
477 int32_t RegNum = Cur->getRegNum(); 496 int32_t RegNum = Cur->getRegNum();
478 // RegNumTmp should have already been set above. 497 // RegNumTmp should have already been set above.
479 assert(Cur->getRegNumTmp() == RegNum); 498 assert(Cur->getRegNumTmp() == RegNum);
480 dumpLiveRangeTrace("Precoloring ", Cur); 499 dumpLiveRangeTrace("Precoloring ", Cur);
481 Active.push_back(Cur); 500 Active.push_back(Cur);
482 assert(RegUses[RegNum] >= 0); 501 const llvm::SmallBitVector &Aliases = *RegAliases[RegNum];
483 ++RegUses[RegNum]; 502 for (int32_t RegAlias = Aliases.find_first(); RegAlias >= 0;
503 RegAlias = Aliases.find_next(RegAlias)) {
504 assert(RegUses[RegAlias] >= 0);
505 ++RegUses[RegAlias];
506 }
484 assert(!UnhandledPrecolored.empty()); 507 assert(!UnhandledPrecolored.empty());
485 assert(UnhandledPrecolored.back() == Cur); 508 assert(UnhandledPrecolored.back() == Cur);
486 UnhandledPrecolored.pop_back(); 509 UnhandledPrecolored.pop_back();
487 } 510 }
488 511
489 void LinearScan::allocatePreferredRegister(IterationState &Iter) { 512 void LinearScan::allocatePreferredRegister(IterationState &Iter) {
490 Iter.Cur->setRegNumTmp(Iter.PreferReg); 513 Iter.Cur->setRegNumTmp(Iter.PreferReg);
491 dumpLiveRangeTrace("Preferring ", Iter.Cur); 514 dumpLiveRangeTrace("Preferring ", Iter.Cur);
492 assert(RegUses[Iter.PreferReg] >= 0); 515 const llvm::SmallBitVector &Aliases = *RegAliases[Iter.PreferReg];
493 ++RegUses[Iter.PreferReg]; 516 for (int32_t RegAlias = Aliases.find_first(); RegAlias >= 0;
517 RegAlias = Aliases.find_next(RegAlias)) {
518 assert(RegUses[RegAlias] >= 0);
519 ++RegUses[RegAlias];
520 }
494 Active.push_back(Iter.Cur); 521 Active.push_back(Iter.Cur);
495 } 522 }
496 523
497 void LinearScan::allocateFreeRegister(IterationState &Iter) { 524 void LinearScan::allocateFreeRegister(IterationState &Iter) {
498 int32_t RegNum = Iter.Free.find_first(); 525 int32_t RegNum = Iter.Free.find_first();
499 Iter.Cur->setRegNumTmp(RegNum); 526 Iter.Cur->setRegNumTmp(RegNum);
500 dumpLiveRangeTrace("Allocating ", Iter.Cur); 527 dumpLiveRangeTrace("Allocating ", Iter.Cur);
501 assert(RegUses[RegNum] >= 0); 528 const llvm::SmallBitVector &Aliases = *RegAliases[RegNum];
502 ++RegUses[RegNum]; 529 for (int32_t RegAlias = Aliases.find_first(); RegAlias >= 0;
530 RegAlias = Aliases.find_next(RegAlias)) {
531 assert(RegUses[RegAlias] >= 0);
532 ++RegUses[RegAlias];
533 }
503 Active.push_back(Iter.Cur); 534 Active.push_back(Iter.Cur);
504 } 535 }
505 536
506 void LinearScan::handleNoFreeRegisters(IterationState &Iter) { 537 void LinearScan::handleNoFreeRegisters(IterationState &Iter) {
507 // Check Active ranges. 538 // Check Active ranges.
508 for (const Variable *Item : Active) { 539 for (const Variable *Item : Active) {
509 assert(Item->rangeOverlaps(Iter.Cur)); 540 assert(Item->rangeOverlaps(Iter.Cur));
510 int32_t RegNum = Item->getRegNumTmp(); 541 RegWeight W;
511 assert(Item->hasRegTmp()); 542 const llvm::SmallBitVector &Aliases = *RegAliases[Item->getRegNumTmp()];
512 Iter.Weights[RegNum].addWeight(Item->getWeight(Func)); 543 for (int32_t RegNum = Aliases.find_first(); RegNum >= 0;
544 RegNum = Aliases.find_next(RegNum)) {
545 assert(Item->hasRegTmp());
546 RegWeight Tmp = Item->getWeight(Func);
547 if (W < Tmp)
548 W = Tmp;
549 }
550 Iter.Weights[Item->getRegNumTmp()].addWeight(W);
Jim Stichnoth 2015/09/03 17:48:49 Should probably drop a TODO here about the fact th
John 2015/09/03 22:38:25 Done.
513 } 551 }
514 // Same as above, but check Inactive ranges instead of Active. 552 // Same as above, but check Inactive ranges instead of Active.
515 for (const Variable *Item : Inactive) { 553 for (const Variable *Item : Inactive) {
516 int32_t RegNum = Item->getRegNumTmp(); 554 bool HasWeight = false;
517 assert(Item->hasRegTmp()); 555 RegWeight W;
518 if (Item->rangeOverlaps(Iter.Cur)) 556 const llvm::SmallBitVector &Aliases = *RegAliases[Item->getRegNumTmp()];
519 Iter.Weights[RegNum].addWeight(Item->getWeight(Func)); 557 for (int32_t RegNum = Aliases.find_first(); RegNum >= 0;
558 RegNum = Aliases.find_next(RegNum)) {
559 assert(Item->hasRegTmp());
560 if (Item->rangeOverlaps(Iter.Cur)) {
561 HasWeight = true;
562 RegWeight Tmp = Item->getWeight(Func);
563 if (W < Tmp)
564 W = Tmp;
565 }
566 }
567 if (HasWeight) {
568 Iter.Weights[Item->getRegNumTmp()].addWeight(W);
569 }
520 } 570 }
521 571
522 // All the weights are now calculated. Find the register with smallest 572 // All the weights are now calculated. Find the register with smallest
523 // weight. 573 // weight.
524 int32_t MinWeightIndex = Iter.RegMask.find_first(); 574 int32_t MinWeightIndex = Iter.RegMask.find_first();
525 // MinWeightIndex must be valid because of the initial RegMask.any() test. 575 // MinWeightIndex must be valid because of the initial RegMask.any() test.
526 assert(MinWeightIndex >= 0); 576 assert(MinWeightIndex >= 0);
527 for (SizeT i = MinWeightIndex + 1; i < Iter.Weights.size(); ++i) { 577 for (SizeT i = MinWeightIndex + 1; i < Iter.Weights.size(); ++i) {
528 if (Iter.RegMask[i] && Iter.Weights[i] < Iter.Weights[MinWeightIndex]) 578 if (Iter.RegMask[i] && Iter.Weights[i] < Iter.Weights[MinWeightIndex])
529 MinWeightIndex = i; 579 MinWeightIndex = i;
(...skipping 11 matching lines...) Expand all
541 "infinite-weight live range"); 591 "infinite-weight live range");
542 } 592 }
543 } else { 593 } else {
544 // Evict all live ranges in Active that register number MinWeightIndex is 594 // Evict all live ranges in Active that register number MinWeightIndex is
545 // assigned to. 595 // assigned to.
546 for (SizeT I = Active.size(); I > 0; --I) { 596 for (SizeT I = Active.size(); I > 0; --I) {
547 const SizeT Index = I - 1; 597 const SizeT Index = I - 1;
548 Variable *Item = Active[Index]; 598 Variable *Item = Active[Index];
549 if (Item->getRegNumTmp() == MinWeightIndex) { 599 if (Item->getRegNumTmp() == MinWeightIndex) {
550 dumpLiveRangeTrace("Evicting ", Item); 600 dumpLiveRangeTrace("Evicting ", Item);
551 --RegUses[MinWeightIndex]; 601 const llvm::SmallBitVector &Aliases = *RegAliases[MinWeightIndex];
552 assert(RegUses[MinWeightIndex] >= 0); 602 for (int32_t Reg = Aliases.find_first(); Reg >= 0;
603 Reg = Aliases.find_next(Reg)) {
604 --RegUses[Reg];
605 assert(RegUses[Reg] >= 0);
606 }
553 Item->setRegNumTmp(Variable::NoRegister); 607 Item->setRegNumTmp(Variable::NoRegister);
554 moveItem(Active, Index, Handled); 608 moveItem(Active, Index, Handled);
555 } 609 }
556 } 610 }
557 // Do the same for Inactive. 611 // Do the same for Inactive.
558 for (SizeT I = Inactive.size(); I > 0; --I) { 612 for (SizeT I = Inactive.size(); I > 0; --I) {
559 const SizeT Index = I - 1; 613 const SizeT Index = I - 1;
560 Variable *Item = Inactive[Index]; 614 Variable *Item = Inactive[Index];
561 // Note: The Item->rangeOverlaps(Cur) clause is not part of the 615 // Note: The Item->rangeOverlaps(Cur) clause is not part of the
562 // description of AssignMemLoc() in the original paper. But there 616 // description of AssignMemLoc() in the original paper. But there
563 // doesn't seem to be any need to evict an inactive live range that 617 // doesn't seem to be any need to evict an inactive live range that
564 // doesn't overlap with the live range currently being considered. It's 618 // doesn't overlap with the live range currently being considered. It's
565 // especially bad if we would end up evicting an infinite-weight but 619 // especially bad if we would end up evicting an infinite-weight but
566 // currently-inactive live range. The most common situation for this 620 // currently-inactive live range. The most common situation for this
567 // would be a scratch register kill set for call instructions. 621 // would be a scratch register kill set for call instructions.
568 if (Item->getRegNumTmp() == MinWeightIndex && 622 if (Item->getRegNumTmp() == MinWeightIndex &&
569 Item->rangeOverlaps(Iter.Cur)) { 623 Item->rangeOverlaps(Iter.Cur)) {
570 dumpLiveRangeTrace("Evicting ", Item); 624 dumpLiveRangeTrace("Evicting ", Item);
571 Item->setRegNumTmp(Variable::NoRegister); 625 Item->setRegNumTmp(Variable::NoRegister);
572 moveItem(Inactive, Index, Handled); 626 moveItem(Inactive, Index, Handled);
573 } 627 }
574 } 628 }
575 // Assign the register to Cur. 629 // Assign the register to Cur.
576 Iter.Cur->setRegNumTmp(MinWeightIndex); 630 Iter.Cur->setRegNumTmp(MinWeightIndex);
577 assert(RegUses[MinWeightIndex] >= 0); 631 const llvm::SmallBitVector &Aliases = *RegAliases[MinWeightIndex];
578 ++RegUses[MinWeightIndex]; 632 for (int32_t Reg = Aliases.find_first(); Reg >= 0;
633 Reg = Aliases.find_next(Reg)) {
634 assert(RegUses[Reg] >= 0);
635 ++RegUses[Reg];
636 }
579 Active.push_back(Iter.Cur); 637 Active.push_back(Iter.Cur);
580 dumpLiveRangeTrace("Allocating ", Iter.Cur); 638 dumpLiveRangeTrace("Allocating ", Iter.Cur);
581 } 639 }
582 } 640 }
583 641
584 void LinearScan::assignFinalRegisters( 642 void LinearScan::assignFinalRegisters(
585 const llvm::SmallBitVector &RegMaskFull, 643 const llvm::SmallBitVector &RegMaskFull,
586 const llvm::SmallBitVector &PreDefinedRegisters, bool Randomized) { 644 const llvm::SmallBitVector &PreDefinedRegisters, bool Randomized) {
587 const size_t NumRegisters = RegMaskFull.size(); 645 const size_t NumRegisters = RegMaskFull.size();
588 llvm::SmallVector<int32_t, REGS_SIZE> Permutation(NumRegisters); 646 llvm::SmallVector<int32_t, REGS_SIZE> Permutation(NumRegisters);
(...skipping 239 matching lines...) Expand 10 before | Expand all | Expand 10 after
828 Str << "\n"; 886 Str << "\n";
829 } 887 }
830 Str << "++++++ Inactive:\n"; 888 Str << "++++++ Inactive:\n";
831 for (const Variable *Item : Inactive) { 889 for (const Variable *Item : Inactive) {
832 dumpLiveRange(Item, Func); 890 dumpLiveRange(Item, Func);
833 Str << "\n"; 891 Str << "\n";
834 } 892 }
835 } 893 }
836 894
837 } // end of namespace Ice 895 } // end of namespace Ice
OLDNEW
« no previous file with comments | « src/IceRegAlloc.h ('k') | src/IceTargetLowering.h » ('j') | src/IceTargetLoweringX8632Traits.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698