| OLD | NEW |
| 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 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 69 if (!BuildDefs::dump()) | 69 if (!BuildDefs::dump()) |
| 70 return; | 70 return; |
| 71 Ostream &Str = Func->getContext()->getStrDump(); | 71 Ostream &Str = Func->getContext()->getStrDump(); |
| 72 char buf[30]; | 72 char buf[30]; |
| 73 snprintf(buf, llvm::array_lengthof(buf), "%2d", Var->getRegNumTmp()); | 73 snprintf(buf, llvm::array_lengthof(buf), "%2d", Var->getRegNumTmp()); |
| 74 Str << "R=" << buf << " V="; | 74 Str << "R=" << buf << " V="; |
| 75 Var->dump(Func); | 75 Var->dump(Func); |
| 76 Str << " Range=" << Var->getLiveRange(); | 76 Str << " Range=" << Var->getLiveRange(); |
| 77 } | 77 } |
| 78 | 78 |
| 79 int32_t findMinWeightIndex( |
| 80 const llvm::SmallBitVector &RegMask, |
| 81 const llvm::SmallVector<RegWeight, LinearScan::REGS_SIZE> &Weights) { |
| 82 int32_t MinWeightIndex = RegMask.find_first(); |
| 83 assert(MinWeightIndex >= 0); |
| 84 for (int32_t i = RegMask.find_next(MinWeightIndex); i != -1; |
| 85 i = RegMask.find_next(i)) { |
| 86 if (Weights[i] < Weights[MinWeightIndex]) |
| 87 MinWeightIndex = i; |
| 88 } |
| 89 return MinWeightIndex; |
| 90 } |
| 91 |
| 79 } // end of anonymous namespace | 92 } // end of anonymous namespace |
| 80 | 93 |
| 81 LinearScan::LinearScan(Cfg *Func) | 94 LinearScan::LinearScan(Cfg *Func) |
| 82 : Func(Func), Ctx(Func->getContext()), Target(Func->getTarget()), | 95 : Func(Func), Ctx(Func->getContext()), Target(Func->getTarget()), |
| 83 Verbose(BuildDefs::dump() && Func->isVerbose(IceV_LinearScan)) {} | 96 Verbose(BuildDefs::dump() && Func->isVerbose(IceV_LinearScan)), |
| 97 UseReserve(Ctx->getFlags().getRegAllocReserve()) {} |
| 84 | 98 |
| 85 // Prepare for full register allocation of all variables. We depend on liveness | 99 // Prepare for full register allocation of all variables. We depend on liveness |
| 86 // analysis to have calculated live ranges. | 100 // analysis to have calculated live ranges. |
| 87 void LinearScan::initForGlobal() { | 101 void LinearScan::initForGlobal() { |
| 88 TimerMarker T(TimerStack::TT_initUnhandled, Func); | 102 TimerMarker T(TimerStack::TT_initUnhandled, Func); |
| 89 FindPreference = true; | 103 FindPreference = true; |
| 90 // For full register allocation, normally we want to enable FindOverlap | 104 // For full register allocation, normally we want to enable FindOverlap |
| 91 // (meaning we look for opportunities for two overlapping live ranges to | 105 // (meaning we look for opportunities for two overlapping live ranges to |
| 92 // safely share the same register). However, we disable it for phi-lowering | 106 // safely share the same register). However, we disable it for phi-lowering |
| 93 // register allocation since no overlap opportunities should be available and | 107 // register allocation since no overlap opportunities should be available and |
| (...skipping 444 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 538 } | 552 } |
| 539 if (BuildDefs::dump() && Verbose && Iter.Prefer) { | 553 if (BuildDefs::dump() && Verbose && Iter.Prefer) { |
| 540 Ostream &Str = Ctx->getStrDump(); | 554 Ostream &Str = Ctx->getStrDump(); |
| 541 Str << "Initial Iter.Prefer="; | 555 Str << "Initial Iter.Prefer="; |
| 542 Iter.Prefer->dump(Func); | 556 Iter.Prefer->dump(Func); |
| 543 Str << " R=" << Iter.PreferReg << " LIVE=" << Iter.Prefer->getLiveRange() | 557 Str << " R=" << Iter.PreferReg << " LIVE=" << Iter.Prefer->getLiveRange() |
| 544 << " Overlap=" << Iter.AllowOverlap << "\n"; | 558 << " Overlap=" << Iter.AllowOverlap << "\n"; |
| 545 } | 559 } |
| 546 } | 560 } |
| 547 | 561 |
| 548 // Remove registers from the Free[] list where an Inactive range overlaps with | 562 // Remove registers from the Iter.Free[] list where an Inactive range overlaps |
| 549 // the current range. | 563 // with the current range. |
| 550 void LinearScan::filterFreeWithInactiveRanges(IterationState &Iter) { | 564 void LinearScan::filterFreeWithInactiveRanges(IterationState &Iter) { |
| 551 for (const Variable *Item : Inactive) { | 565 for (const Variable *Item : Inactive) { |
| 552 if (!Item->rangeOverlaps(Iter.Cur)) | 566 if (!Item->rangeOverlaps(Iter.Cur)) |
| 553 continue; | 567 continue; |
| 554 const llvm::SmallBitVector &Aliases = *RegAliases[Item->getRegNumTmp()]; | 568 const llvm::SmallBitVector &Aliases = *RegAliases[Item->getRegNumTmp()]; |
| 555 // TODO(stichnot): Do this with bitvector ops, not a loop, for efficiency. | 569 // TODO(stichnot): Do this with bitvector ops, not a loop, for efficiency. |
| 556 for (int32_t RegAlias = Aliases.find_first(); RegAlias >= 0; | 570 for (int32_t RegAlias = Aliases.find_first(); RegAlias >= 0; |
| 557 RegAlias = Aliases.find_next(RegAlias)) { | 571 RegAlias = Aliases.find_next(RegAlias)) { |
| 558 // Don't assert(Free[RegNum]) because in theory (though probably never in | 572 // Don't assert(Iter.Free[RegNum]) because in theory (though probably |
| 559 // practice) there could be two inactive variables that were marked with | 573 // never in practice) there could be two inactive variables that were |
| 560 // AllowOverlap. | 574 // marked with AllowOverlap. |
| 561 Iter.Free[RegAlias] = false; | 575 Iter.Free[RegAlias] = false; |
| 576 Iter.FreeUnfiltered[RegAlias] = false; |
| 562 // Disable AllowOverlap if an Inactive variable, which is not Prefer, | 577 // Disable AllowOverlap if an Inactive variable, which is not Prefer, |
| 563 // shares Prefer's register, and has a definition within Cur's live range. | 578 // shares Prefer's register, and has a definition within Cur's live range. |
| 564 if (Iter.AllowOverlap && Item != Iter.Prefer && | 579 if (Iter.AllowOverlap && Item != Iter.Prefer && |
| 565 RegAlias == Iter.PreferReg && overlapsDefs(Func, Iter.Cur, Item)) { | 580 RegAlias == Iter.PreferReg && overlapsDefs(Func, Iter.Cur, Item)) { |
| 566 Iter.AllowOverlap = false; | 581 Iter.AllowOverlap = false; |
| 567 dumpDisableOverlap(Func, Item, "Inactive"); | 582 dumpDisableOverlap(Func, Item, "Inactive"); |
| 568 } | 583 } |
| 569 } | 584 } |
| 570 } | 585 } |
| 571 } | 586 } |
| 572 | 587 |
| 573 // Remove registers from the Free[] list where an Unhandled pre-colored range | 588 // Remove registers from the Iter.Free[] list where an Unhandled pre-colored |
| 574 // overlaps with the current range, and set those registers to infinite weight | 589 // range overlaps with the current range, and set those registers to infinite |
| 575 // so that they aren't candidates for eviction. Cur->rangeEndsBefore(Item) is an | 590 // weight so that they aren't candidates for eviction. |
| 576 // early exit check that turns a guaranteed O(N^2) algorithm into expected | 591 // Cur->rangeEndsBefore(Item) is an early exit check that turns a guaranteed |
| 577 // linear complexity. | 592 // O(N^2) algorithm into expected linear complexity. |
| 578 void LinearScan::filterFreeWithPrecoloredRanges(IterationState &Iter) { | 593 void LinearScan::filterFreeWithPrecoloredRanges(IterationState &Iter) { |
| 579 // TODO(stichnot): Partition UnhandledPrecolored according to register class, | 594 // TODO(stichnot): Partition UnhandledPrecolored according to register class, |
| 580 // to restrict the number of overlap comparisons needed. | 595 // to restrict the number of overlap comparisons needed. |
| 581 for (Variable *Item : reverse_range(UnhandledPrecolored)) { | 596 for (Variable *Item : reverse_range(UnhandledPrecolored)) { |
| 582 assert(Item->hasReg()); | 597 assert(Item->hasReg()); |
| 583 if (Iter.Cur->rangeEndsBefore(Item)) | 598 if (Iter.Cur->rangeEndsBefore(Item)) |
| 584 break; | 599 break; |
| 585 if (!Item->rangeOverlaps(Iter.Cur)) | 600 if (!Item->rangeOverlaps(Iter.Cur)) |
| 586 continue; | 601 continue; |
| 587 const llvm::SmallBitVector &Aliases = | 602 const llvm::SmallBitVector &Aliases = |
| 588 *RegAliases[Item->getRegNum()]; // Note: not getRegNumTmp() | 603 *RegAliases[Item->getRegNum()]; // Note: not getRegNumTmp() |
| 589 for (int32_t RegAlias = Aliases.find_first(); RegAlias >= 0; | 604 for (int32_t RegAlias = Aliases.find_first(); RegAlias >= 0; |
| 590 RegAlias = Aliases.find_next(RegAlias)) { | 605 RegAlias = Aliases.find_next(RegAlias)) { |
| 591 Iter.Weights[RegAlias].setWeight(RegWeight::Inf); | 606 Iter.Weights[RegAlias].setWeight(RegWeight::Inf); |
| 592 Iter.Free[RegAlias] = false; | 607 Iter.Free[RegAlias] = false; |
| 608 Iter.FreeUnfiltered[RegAlias] = false; |
| 593 Iter.PrecoloredUnhandledMask[RegAlias] = true; | 609 Iter.PrecoloredUnhandledMask[RegAlias] = true; |
| 594 // Disable Iter.AllowOverlap if the preferred register is one of these | 610 // Disable Iter.AllowOverlap if the preferred register is one of these |
| 595 // pre-colored unhandled overlapping ranges. | 611 // pre-colored unhandled overlapping ranges. |
| 596 if (Iter.AllowOverlap && RegAlias == Iter.PreferReg) { | 612 if (Iter.AllowOverlap && RegAlias == Iter.PreferReg) { |
| 597 Iter.AllowOverlap = false; | 613 Iter.AllowOverlap = false; |
| 598 dumpDisableOverlap(Func, Item, "PrecoloredUnhandled"); | 614 dumpDisableOverlap(Func, Item, "PrecoloredUnhandled"); |
| 599 } | 615 } |
| 600 } | 616 } |
| 601 } | 617 } |
| 602 } | 618 } |
| (...skipping 20 matching lines...) Expand all Loading... |
| 623 dumpLiveRangeTrace("Preferring ", Iter.Cur); | 639 dumpLiveRangeTrace("Preferring ", Iter.Cur); |
| 624 const llvm::SmallBitVector &Aliases = *RegAliases[Iter.PreferReg]; | 640 const llvm::SmallBitVector &Aliases = *RegAliases[Iter.PreferReg]; |
| 625 for (int32_t RegAlias = Aliases.find_first(); RegAlias >= 0; | 641 for (int32_t RegAlias = Aliases.find_first(); RegAlias >= 0; |
| 626 RegAlias = Aliases.find_next(RegAlias)) { | 642 RegAlias = Aliases.find_next(RegAlias)) { |
| 627 assert(RegUses[RegAlias] >= 0); | 643 assert(RegUses[RegAlias] >= 0); |
| 628 ++RegUses[RegAlias]; | 644 ++RegUses[RegAlias]; |
| 629 } | 645 } |
| 630 Active.push_back(Iter.Cur); | 646 Active.push_back(Iter.Cur); |
| 631 } | 647 } |
| 632 | 648 |
| 633 void LinearScan::allocateFreeRegister(IterationState &Iter) { | 649 void LinearScan::allocateFreeRegister(IterationState &Iter, bool Filtered) { |
| 634 int32_t RegNum = Iter.Free.find_first(); | 650 const int32_t RegNum = |
| 651 Filtered ? Iter.Free.find_first() : Iter.FreeUnfiltered.find_first(); |
| 635 Iter.Cur->setRegNumTmp(RegNum); | 652 Iter.Cur->setRegNumTmp(RegNum); |
| 636 dumpLiveRangeTrace("Allocating ", Iter.Cur); | 653 if (Filtered) |
| 654 dumpLiveRangeTrace("Allocating ", Iter.Cur); |
| 655 else |
| 656 dumpLiveRangeTrace("Allocating X ", Iter.Cur); |
| 637 const llvm::SmallBitVector &Aliases = *RegAliases[RegNum]; | 657 const llvm::SmallBitVector &Aliases = *RegAliases[RegNum]; |
| 638 for (int32_t RegAlias = Aliases.find_first(); RegAlias >= 0; | 658 for (int32_t RegAlias = Aliases.find_first(); RegAlias >= 0; |
| 639 RegAlias = Aliases.find_next(RegAlias)) { | 659 RegAlias = Aliases.find_next(RegAlias)) { |
| 640 assert(RegUses[RegAlias] >= 0); | 660 assert(RegUses[RegAlias] >= 0); |
| 641 ++RegUses[RegAlias]; | 661 ++RegUses[RegAlias]; |
| 642 } | 662 } |
| 643 Active.push_back(Iter.Cur); | 663 Active.push_back(Iter.Cur); |
| 644 } | 664 } |
| 645 | 665 |
| 646 void LinearScan::handleNoFreeRegisters(IterationState &Iter) { | 666 void LinearScan::handleNoFreeRegisters(IterationState &Iter) { |
| (...skipping 18 matching lines...) Expand all Loading... |
| 665 assert(Item->hasRegTmp()); | 685 assert(Item->hasRegTmp()); |
| 666 const llvm::SmallBitVector &Aliases = *RegAliases[Item->getRegNumTmp()]; | 686 const llvm::SmallBitVector &Aliases = *RegAliases[Item->getRegNumTmp()]; |
| 667 RegWeight W = Item->getWeight(Func); | 687 RegWeight W = Item->getWeight(Func); |
| 668 for (int32_t RegAlias = Aliases.find_first(); RegAlias >= 0; | 688 for (int32_t RegAlias = Aliases.find_first(); RegAlias >= 0; |
| 669 RegAlias = Aliases.find_next(RegAlias)) { | 689 RegAlias = Aliases.find_next(RegAlias)) { |
| 670 Iter.Weights[RegAlias].addWeight(W); | 690 Iter.Weights[RegAlias].addWeight(W); |
| 671 } | 691 } |
| 672 } | 692 } |
| 673 | 693 |
| 674 // All the weights are now calculated. Find the register with smallest weight. | 694 // All the weights are now calculated. Find the register with smallest weight. |
| 675 int32_t MinWeightIndex = Iter.RegMask.find_first(); | 695 int32_t MinWeightIndex = findMinWeightIndex(Iter.RegMask, Iter.Weights); |
| 676 // MinWeightIndex must be valid because of the initial RegMask.any() test. | 696 |
| 677 assert(MinWeightIndex >= 0); | 697 if (Iter.Cur->getWeight(Func) <= Iter.Weights[MinWeightIndex]) { |
| 678 for (SizeT i = MinWeightIndex + 1; i < Iter.Weights.size(); ++i) { | 698 if (!Iter.Cur->mustHaveReg()) { |
| 679 if (Iter.RegMask[i] && Iter.Weights[i] < Iter.Weights[MinWeightIndex]) | 699 // Iter.Cur doesn't have priority over any other live ranges, so don't |
| 680 MinWeightIndex = i; | 700 // allocate any register to it, and move it to the Handled state. |
| 701 Handled.push_back(Iter.Cur); |
| 702 return; |
| 703 } |
| 704 if (Kind == RAK_Phi) { |
| 705 // Iter.Cur is infinite-weight but all physical registers are already |
| 706 // taken, so we need to force one to be temporarily available. |
| 707 addSpillFill(Iter); |
| 708 Handled.push_back(Iter.Cur); |
| 709 return; |
| 710 } |
| 711 // The remaining portion of the enclosing "if" block should only be |
| 712 // reachable if we are manually limiting physical registers for testing. |
| 713 if (UseReserve) { |
| 714 if (Iter.FreeUnfiltered.any()) { |
| 715 // There is some available physical register held in reserve, so use it. |
| 716 constexpr bool NotFiltered = false; |
| 717 allocateFreeRegister(Iter, NotFiltered); |
| 718 // Iter.Cur is now on the Active list. |
| 719 return; |
| 720 } |
| 721 // At this point, we need to find some reserve register that is already |
| 722 // assigned to a non-infinite-weight variable. This could happen if some |
| 723 // variable was previously assigned an alias of such a register. |
| 724 MinWeightIndex = findMinWeightIndex(Iter.RegMaskUnfiltered, Iter.Weights); |
| 725 } |
| 726 if (Iter.Cur->getWeight(Func) <= Iter.Weights[MinWeightIndex]) { |
| 727 dumpLiveRangeTrace("Failing ", Iter.Cur); |
| 728 Func->setError("Unable to find a physical register for an " |
| 729 "infinite-weight live range " |
| 730 "(consider using -reg-reserve): " + |
| 731 Iter.Cur->getName(Func)); |
| 732 Handled.push_back(Iter.Cur); |
| 733 return; |
| 734 } |
| 735 // At this point, MinWeightIndex points to a valid reserve register to |
| 736 // reallocate to Iter.Cur, so drop into the eviction code. |
| 681 } | 737 } |
| 682 | 738 |
| 683 if (Iter.Cur->getWeight(Func) <= Iter.Weights[MinWeightIndex]) { | 739 // Evict all live ranges in Active that register number MinWeightIndex is |
| 684 // Cur doesn't have priority over any other live ranges, so don't allocate | 740 // assigned to. |
| 685 // any register to it, and move it to the Handled state. | 741 const llvm::SmallBitVector &Aliases = *RegAliases[MinWeightIndex]; |
| 686 Handled.push_back(Iter.Cur); | 742 for (SizeT I = Active.size(); I > 0; --I) { |
| 687 if (Iter.Cur->mustHaveReg()) { | 743 const SizeT Index = I - 1; |
| 688 if (Kind == RAK_Phi) { | 744 Variable *Item = Active[Index]; |
| 689 addSpillFill(Iter); | 745 int32_t RegNum = Item->getRegNumTmp(); |
| 690 } else { | 746 if (Aliases[RegNum]) { |
| 691 dumpLiveRangeTrace("Failing ", Iter.Cur); | 747 dumpLiveRangeTrace("Evicting A ", Item); |
| 692 Func->setError("Unable to find a physical register for an " | 748 const llvm::SmallBitVector &Aliases = *RegAliases[RegNum]; |
| 693 "infinite-weight live range: " + | 749 for (int32_t RegAlias = Aliases.find_first(); RegAlias >= 0; |
| 694 Iter.Cur->getName(Func)); | 750 RegAlias = Aliases.find_next(RegAlias)) { |
| 751 --RegUses[RegAlias]; |
| 752 assert(RegUses[RegAlias] >= 0); |
| 695 } | 753 } |
| 754 Item->setRegNumTmp(Variable::NoRegister); |
| 755 moveItem(Active, Index, Handled); |
| 756 Evicted.push_back(Item); |
| 696 } | 757 } |
| 697 } else { | 758 } |
| 698 // Evict all live ranges in Active that register number MinWeightIndex is | 759 // Do the same for Inactive. |
| 699 // assigned to. | 760 for (SizeT I = Inactive.size(); I > 0; --I) { |
| 700 const llvm::SmallBitVector &Aliases = *RegAliases[MinWeightIndex]; | 761 const SizeT Index = I - 1; |
| 701 for (SizeT I = Active.size(); I > 0; --I) { | 762 Variable *Item = Inactive[Index]; |
| 702 const SizeT Index = I - 1; | 763 // Note: The Item->rangeOverlaps(Cur) clause is not part of the description |
| 703 Variable *Item = Active[Index]; | 764 // of AssignMemLoc() in the original paper. But there doesn't seem to be any |
| 704 int32_t RegNum = Item->getRegNumTmp(); | 765 // need to evict an inactive live range that doesn't overlap with the live |
| 705 if (Aliases[RegNum]) { | 766 // range currently being considered. It's especially bad if we would end up |
| 706 dumpLiveRangeTrace("Evicting A ", Item); | 767 // evicting an infinite-weight but currently-inactive live range. The most |
| 707 const llvm::SmallBitVector &Aliases = *RegAliases[RegNum]; | 768 // common situation for this would be a scratch register kill set for call |
| 708 for (int32_t RegAlias = Aliases.find_first(); RegAlias >= 0; | 769 // instructions. |
| 709 RegAlias = Aliases.find_next(RegAlias)) { | 770 if (Aliases[Item->getRegNumTmp()] && Item->rangeOverlaps(Iter.Cur)) { |
| 710 --RegUses[RegAlias]; | 771 dumpLiveRangeTrace("Evicting I ", Item); |
| 711 assert(RegUses[RegAlias] >= 0); | 772 Item->setRegNumTmp(Variable::NoRegister); |
| 712 } | 773 moveItem(Inactive, Index, Handled); |
| 713 Item->setRegNumTmp(Variable::NoRegister); | 774 Evicted.push_back(Item); |
| 714 moveItem(Active, Index, Handled); | |
| 715 Evicted.push_back(Item); | |
| 716 } | |
| 717 } | 775 } |
| 718 // Do the same for Inactive. | |
| 719 for (SizeT I = Inactive.size(); I > 0; --I) { | |
| 720 const SizeT Index = I - 1; | |
| 721 Variable *Item = Inactive[Index]; | |
| 722 // Note: The Item->rangeOverlaps(Cur) clause is not part of the | |
| 723 // description of AssignMemLoc() in the original paper. But there doesn't | |
| 724 // seem to be any need to evict an inactive live range that doesn't | |
| 725 // overlap with the live range currently being considered. It's especially | |
| 726 // bad if we would end up evicting an infinite-weight but | |
| 727 // currently-inactive live range. The most common situation for this would | |
| 728 // be a scratch register kill set for call instructions. | |
| 729 if (Aliases[Item->getRegNumTmp()] && Item->rangeOverlaps(Iter.Cur)) { | |
| 730 dumpLiveRangeTrace("Evicting I ", Item); | |
| 731 Item->setRegNumTmp(Variable::NoRegister); | |
| 732 moveItem(Inactive, Index, Handled); | |
| 733 Evicted.push_back(Item); | |
| 734 } | |
| 735 } | |
| 736 // Assign the register to Cur. | |
| 737 Iter.Cur->setRegNumTmp(MinWeightIndex); | |
| 738 for (int32_t RegAlias = Aliases.find_first(); RegAlias >= 0; | |
| 739 RegAlias = Aliases.find_next(RegAlias)) { | |
| 740 assert(RegUses[RegAlias] >= 0); | |
| 741 ++RegUses[RegAlias]; | |
| 742 } | |
| 743 Active.push_back(Iter.Cur); | |
| 744 dumpLiveRangeTrace("Allocating ", Iter.Cur); | |
| 745 } | 776 } |
| 777 // Assign the register to Cur. |
| 778 Iter.Cur->setRegNumTmp(MinWeightIndex); |
| 779 for (int32_t RegAlias = Aliases.find_first(); RegAlias >= 0; |
| 780 RegAlias = Aliases.find_next(RegAlias)) { |
| 781 assert(RegUses[RegAlias] >= 0); |
| 782 ++RegUses[RegAlias]; |
| 783 } |
| 784 Active.push_back(Iter.Cur); |
| 785 dumpLiveRangeTrace("Allocating ", Iter.Cur); |
| 746 } | 786 } |
| 747 | 787 |
| 748 void LinearScan::assignFinalRegisters( | 788 void LinearScan::assignFinalRegisters( |
| 749 const llvm::SmallBitVector &RegMaskFull, | 789 const llvm::SmallBitVector &RegMaskFull, |
| 750 const llvm::SmallBitVector &PreDefinedRegisters, bool Randomized) { | 790 const llvm::SmallBitVector &PreDefinedRegisters, bool Randomized) { |
| 751 const size_t NumRegisters = RegMaskFull.size(); | 791 const size_t NumRegisters = RegMaskFull.size(); |
| 752 llvm::SmallVector<int32_t, REGS_SIZE> Permutation(NumRegisters); | 792 llvm::SmallVector<int32_t, REGS_SIZE> Permutation(NumRegisters); |
| 753 if (Randomized) { | 793 if (Randomized) { |
| 754 // Create a random number generator for regalloc randomization. Merge | 794 // Create a random number generator for regalloc randomization. Merge |
| 755 // function's sequence and Kind value as the Salt. Because regAlloc() is | 795 // function's sequence and Kind value as the Salt. Because regAlloc() is |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 836 IterationState Iter; | 876 IterationState Iter; |
| 837 Iter.Weights.reserve(NumRegisters); | 877 Iter.Weights.reserve(NumRegisters); |
| 838 Iter.PrecoloredUnhandledMask.reserve(NumRegisters); | 878 Iter.PrecoloredUnhandledMask.reserve(NumRegisters); |
| 839 | 879 |
| 840 while (!Unhandled.empty()) { | 880 while (!Unhandled.empty()) { |
| 841 Iter.Cur = Unhandled.back(); | 881 Iter.Cur = Unhandled.back(); |
| 842 Unhandled.pop_back(); | 882 Unhandled.pop_back(); |
| 843 dumpLiveRangeTrace("\nConsidering ", Iter.Cur); | 883 dumpLiveRangeTrace("\nConsidering ", Iter.Cur); |
| 844 assert(Target->getRegistersForVariable(Iter.Cur).any()); | 884 assert(Target->getRegistersForVariable(Iter.Cur).any()); |
| 845 Iter.RegMask = RegMaskFull & Target->getRegistersForVariable(Iter.Cur); | 885 Iter.RegMask = RegMaskFull & Target->getRegistersForVariable(Iter.Cur); |
| 886 Iter.RegMaskUnfiltered = |
| 887 RegMaskFull & Target->getAllRegistersForVariable(Iter.Cur); |
| 846 KillsRange.trim(Iter.Cur->getLiveRange().getStart()); | 888 KillsRange.trim(Iter.Cur->getLiveRange().getStart()); |
| 847 | 889 |
| 848 // Check for pre-colored ranges. If Cur is pre-colored, it definitely gets | 890 // Check for pre-colored ranges. If Cur is pre-colored, it definitely gets |
| 849 // that register. Previously processed live ranges would have avoided that | 891 // that register. Previously processed live ranges would have avoided that |
| 850 // register due to it being pre-colored. Future processed live ranges won't | 892 // register due to it being pre-colored. Future processed live ranges won't |
| 851 // evict that register because the live range has infinite weight. | 893 // evict that register because the live range has infinite weight. |
| 852 if (Iter.Cur->hasReg()) { | 894 if (Iter.Cur->hasReg()) { |
| 853 allocatePrecoloredRegister(Iter.Cur); | 895 allocatePrecoloredRegister(Iter.Cur); |
| 854 continue; | 896 continue; |
| 855 } | 897 } |
| 856 | 898 |
| 857 handleActiveRangeExpiredOrInactive(Iter.Cur); | 899 handleActiveRangeExpiredOrInactive(Iter.Cur); |
| 858 handleInactiveRangeExpiredOrReactivated(Iter.Cur); | 900 handleInactiveRangeExpiredOrReactivated(Iter.Cur); |
| 859 | 901 |
| 860 // Calculate available registers into Free[]. | 902 // Calculate available registers into Iter.Free[] and Iter.FreeUnfiltered[]. |
| 861 Iter.Free = Iter.RegMask; | 903 Iter.Free = Iter.RegMask; |
| 904 Iter.FreeUnfiltered = Iter.RegMaskUnfiltered; |
| 862 for (SizeT i = 0; i < Iter.RegMask.size(); ++i) { | 905 for (SizeT i = 0; i < Iter.RegMask.size(); ++i) { |
| 863 if (RegUses[i] > 0) | 906 if (RegUses[i] > 0) { |
| 864 Iter.Free[i] = false; | 907 Iter.Free[i] = false; |
| 908 Iter.FreeUnfiltered[i] = false; |
| 909 } |
| 865 } | 910 } |
| 866 | 911 |
| 867 findRegisterPreference(Iter); | 912 findRegisterPreference(Iter); |
| 868 filterFreeWithInactiveRanges(Iter); | 913 filterFreeWithInactiveRanges(Iter); |
| 869 | 914 |
| 870 // Disable AllowOverlap if an Active variable, which is not Prefer, shares | 915 // Disable AllowOverlap if an Active variable, which is not Prefer, shares |
| 871 // Prefer's register, and has a definition within Cur's live range. | 916 // Prefer's register, and has a definition within Cur's live range. |
| 872 if (Iter.AllowOverlap) { | 917 if (Iter.AllowOverlap) { |
| 873 const llvm::SmallBitVector &Aliases = *RegAliases[Iter.PreferReg]; | 918 const llvm::SmallBitVector &Aliases = *RegAliases[Iter.PreferReg]; |
| 874 for (const Variable *Item : Active) { | 919 for (const Variable *Item : Active) { |
| 875 int32_t RegNum = Item->getRegNumTmp(); | 920 int32_t RegNum = Item->getRegNumTmp(); |
| 876 if (Item != Iter.Prefer && Aliases[RegNum] && | 921 if (Item != Iter.Prefer && Aliases[RegNum] && |
| 877 overlapsDefs(Func, Iter.Cur, Item)) { | 922 overlapsDefs(Func, Iter.Cur, Item)) { |
| 878 Iter.AllowOverlap = false; | 923 Iter.AllowOverlap = false; |
| 879 dumpDisableOverlap(Func, Item, "Active"); | 924 dumpDisableOverlap(Func, Item, "Active"); |
| 880 } | 925 } |
| 881 } | 926 } |
| 882 } | 927 } |
| 883 | 928 |
| 884 Iter.Weights.resize(Iter.RegMask.size()); | 929 Iter.Weights.resize(Iter.RegMask.size()); |
| 885 std::fill(Iter.Weights.begin(), Iter.Weights.end(), RegWeight()); | 930 std::fill(Iter.Weights.begin(), Iter.Weights.end(), RegWeight()); |
| 886 | 931 |
| 887 Iter.PrecoloredUnhandledMask.resize(Iter.RegMask.size()); | 932 Iter.PrecoloredUnhandledMask.resize(Iter.RegMask.size()); |
| 888 Iter.PrecoloredUnhandledMask.reset(); | 933 Iter.PrecoloredUnhandledMask.reset(); |
| 889 | 934 |
| 890 filterFreeWithPrecoloredRanges(Iter); | 935 filterFreeWithPrecoloredRanges(Iter); |
| 891 | 936 |
| 892 // Remove scratch registers from the Free[] list, and mark their Weights[] | 937 // Remove scratch registers from the Iter.Free[] list, and mark their |
| 893 // as infinite, if KillsRange overlaps Cur's live range. | 938 // Iter.Weights[] as infinite, if KillsRange overlaps Cur's live range. |
| 894 constexpr bool UseTrimmed = true; | 939 constexpr bool UseTrimmed = true; |
| 895 if (Iter.Cur->getLiveRange().overlaps(KillsRange, UseTrimmed)) { | 940 if (Iter.Cur->getLiveRange().overlaps(KillsRange, UseTrimmed)) { |
| 896 Iter.Free.reset(KillsMask); | 941 Iter.Free.reset(KillsMask); |
| 942 Iter.FreeUnfiltered.reset(KillsMask); |
| 897 for (int i = KillsMask.find_first(); i != -1; | 943 for (int i = KillsMask.find_first(); i != -1; |
| 898 i = KillsMask.find_next(i)) { | 944 i = KillsMask.find_next(i)) { |
| 899 Iter.Weights[i].setWeight(RegWeight::Inf); | 945 Iter.Weights[i].setWeight(RegWeight::Inf); |
| 900 if (Iter.PreferReg == i) | 946 if (Iter.PreferReg == i) |
| 901 Iter.AllowOverlap = false; | 947 Iter.AllowOverlap = false; |
| 902 } | 948 } |
| 903 } | 949 } |
| 904 | 950 |
| 905 // Print info about physical register availability. | 951 // Print info about physical register availability. |
| 906 if (BuildDefs::dump() && Verbose) { | 952 if (BuildDefs::dump() && Verbose) { |
| 907 Ostream &Str = Ctx->getStrDump(); | 953 Ostream &Str = Ctx->getStrDump(); |
| 908 for (SizeT i = 0; i < Iter.RegMask.size(); ++i) { | 954 for (SizeT i = 0; i < Iter.RegMask.size(); ++i) { |
| 909 if (Iter.RegMask[i]) { | 955 if (Iter.RegMaskUnfiltered[i]) { |
| 910 Str << Target->getRegName(i, Iter.Cur->getType()) | 956 Str << Target->getRegName(i, Iter.Cur->getType()) |
| 911 << "(U=" << RegUses[i] << ",F=" << Iter.Free[i] | 957 << "(U=" << RegUses[i] << ",F=" << Iter.Free[i] |
| 912 << ",P=" << Iter.PrecoloredUnhandledMask[i] << ") "; | 958 << ",P=" << Iter.PrecoloredUnhandledMask[i] << ") "; |
| 913 } | 959 } |
| 914 } | 960 } |
| 915 Str << "\n"; | 961 Str << "\n"; |
| 916 } | 962 } |
| 917 | 963 |
| 918 if (Iter.Prefer && (Iter.AllowOverlap || Iter.Free[Iter.PreferReg])) { | 964 if (Iter.Prefer && (Iter.AllowOverlap || Iter.Free[Iter.PreferReg])) { |
| 919 // First choice: a preferred register that is either free or is allowed to | 965 // First choice: a preferred register that is either free or is allowed to |
| 920 // overlap with its linked variable. | 966 // overlap with its linked variable. |
| 921 allocatePreferredRegister(Iter); | 967 allocatePreferredRegister(Iter); |
| 922 } else if (Iter.Free.any()) { | 968 } else if (Iter.Free.any()) { |
| 923 // Second choice: any free register. | 969 // Second choice: any free register. |
| 924 allocateFreeRegister(Iter); | 970 constexpr bool Filtered = true; |
| 971 allocateFreeRegister(Iter, Filtered); |
| 925 } else { | 972 } else { |
| 926 // Fallback: there are no free registers, so we look for the lowest-weight | 973 // Fallback: there are no free registers, so we look for the lowest-weight |
| 927 // register and see if Cur has higher weight. | 974 // register and see if Cur has higher weight. |
| 928 handleNoFreeRegisters(Iter); | 975 handleNoFreeRegisters(Iter); |
| 929 } | 976 } |
| 930 dump(Func); | 977 dump(Func); |
| 931 } | 978 } |
| 932 | 979 |
| 933 // Move anything Active or Inactive to Handled for easier handling. | 980 // Move anything Active or Inactive to Handled for easier handling. |
| 934 Handled.insert(Handled.end(), Active.begin(), Active.end()); | 981 Handled.insert(Handled.end(), Active.begin(), Active.end()); |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 981 Str << "\n"; | 1028 Str << "\n"; |
| 982 } | 1029 } |
| 983 Str << "++++++ Inactive:\n"; | 1030 Str << "++++++ Inactive:\n"; |
| 984 for (const Variable *Item : Inactive) { | 1031 for (const Variable *Item : Inactive) { |
| 985 dumpLiveRange(Item, Func); | 1032 dumpLiveRange(Item, Func); |
| 986 Str << "\n"; | 1033 Str << "\n"; |
| 987 } | 1034 } |
| 988 } | 1035 } |
| 989 | 1036 |
| 990 } // end of namespace Ice | 1037 } // end of namespace Ice |
| OLD | NEW |