| 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 // This file implements the LinearScan class, which performs the | 10 // This file implements the LinearScan class, which performs the |
| (...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 134 // * We don't need to renumber instructions before computing live | 134 // * We don't need to renumber instructions before computing live |
| 135 // ranges because all the high-level ICE instructions are deleted | 135 // ranges because all the high-level ICE instructions are deleted |
| 136 // prior to lowering, and the low-level instructions are added in | 136 // prior to lowering, and the low-level instructions are added in |
| 137 // monotonically increasing order. | 137 // monotonically increasing order. |
| 138 // | 138 // |
| 139 // * There are no opportunities for register preference or allowing | 139 // * There are no opportunities for register preference or allowing |
| 140 // overlap. | 140 // overlap. |
| 141 // | 141 // |
| 142 // Some properties we aren't (yet) taking advantage of: | 142 // Some properties we aren't (yet) taking advantage of: |
| 143 // | 143 // |
| 144 // * Because live ranges are a single segment, the Unhandled set will | 144 // * Because live ranges are a single segment, the Inactive set will |
| 145 // always be empty, and the live range trimming operation is | 145 // always be empty, and the live range trimming operation is |
| 146 // unnecessary. | 146 // unnecessary. |
| 147 // | 147 // |
| 148 // * Calculating overlap of single-segment live ranges could be | 148 // * Calculating overlap of single-segment live ranges could be |
| 149 // optimized a bit. | 149 // optimized a bit. |
| 150 void LinearScan::initForInfOnly() { | 150 void LinearScan::initForInfOnly() { |
| 151 TimerMarker T(TimerStack::TT_initUnhandled, Func); | 151 TimerMarker T(TimerStack::TT_initUnhandled, Func); |
| 152 FindPreference = false; | 152 FindPreference = false; |
| 153 FindOverlap = false; | 153 FindOverlap = false; |
| 154 SizeT NumVars = 0; | 154 SizeT NumVars = 0; |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 251 // Register Allocation in the Context of SSA Form and Register | 251 // Register Allocation in the Context of SSA Form and Register |
| 252 // Constraints" by Hanspeter Mössenböck and Michael Pfeiffer, | 252 // Constraints" by Hanspeter Mössenböck and Michael Pfeiffer, |
| 253 // ftp://ftp.ssw.uni-linz.ac.at/pub/Papers/Moe02.PDF . This | 253 // ftp://ftp.ssw.uni-linz.ac.at/pub/Papers/Moe02.PDF . This |
| 254 // implementation is modified to take affinity into account and allow | 254 // implementation is modified to take affinity into account and allow |
| 255 // two interfering variables to share the same register in certain | 255 // two interfering variables to share the same register in certain |
| 256 // cases. | 256 // cases. |
| 257 // | 257 // |
| 258 // Requires running Cfg::liveness(Liveness_Intervals) in | 258 // Requires running Cfg::liveness(Liveness_Intervals) in |
| 259 // preparation. Results are assigned to Variable::RegNum for each | 259 // preparation. Results are assigned to Variable::RegNum for each |
| 260 // Variable. | 260 // Variable. |
| 261 void LinearScan::scan(const llvm::SmallBitVector &RegMaskFull) { | 261 void LinearScan::scan(const llvm::SmallBitVector &RegMaskFull, |
| 262 bool Randomized) { |
| 262 TimerMarker T(TimerStack::TT_linearScan, Func); | 263 TimerMarker T(TimerStack::TT_linearScan, Func); |
| 263 assert(RegMaskFull.any()); // Sanity check | 264 assert(RegMaskFull.any()); // Sanity check |
| 264 Ostream &Str = Func->getContext()->getStrDump(); | 265 Ostream &Str = Func->getContext()->getStrDump(); |
| 265 const bool Verbose = | 266 const bool Verbose = |
| 266 ALLOW_DUMP && Func->getContext()->isVerbose(IceV_LinearScan); | 267 ALLOW_DUMP && Func->getContext()->isVerbose(IceV_LinearScan); |
| 267 Func->resetCurrentNode(); | 268 Func->resetCurrentNode(); |
| 268 VariablesMetadata *VMetadata = Func->getVMetadata(); | 269 VariablesMetadata *VMetadata = Func->getVMetadata(); |
| 270 const size_t NumRegisters = RegMaskFull.size(); |
| 271 llvm::SmallBitVector PreDefinedRegisters(NumRegisters); |
| 272 if (Randomized) { |
| 273 for (Variable *Var : UnhandledPrecolored) { |
| 274 PreDefinedRegisters[Var->getRegNum()] = true; |
| 275 } |
| 276 } |
| 269 | 277 |
| 270 // Build a LiveRange representing the Kills list. | 278 // Build a LiveRange representing the Kills list. |
| 271 LiveRange KillsRange(Kills); | 279 LiveRange KillsRange(Kills); |
| 272 KillsRange.untrim(); | 280 KillsRange.untrim(); |
| 273 | 281 |
| 274 // RegUses[I] is the number of live ranges (variables) that register | 282 // RegUses[I] is the number of live ranges (variables) that register |
| 275 // I is currently assigned to. It can be greater than 1 as a result | 283 // I is currently assigned to. It can be greater than 1 as a result |
| 276 // of AllowOverlap inference below. | 284 // of AllowOverlap inference below. |
| 277 std::vector<int> RegUses(RegMaskFull.size()); | 285 std::vector<int> RegUses(NumRegisters); |
| 278 // Unhandled is already set to all ranges in increasing order of | 286 // Unhandled is already set to all ranges in increasing order of |
| 279 // start points. | 287 // start points. |
| 280 assert(Active.empty()); | 288 assert(Active.empty()); |
| 281 assert(Inactive.empty()); | 289 assert(Inactive.empty()); |
| 282 assert(Handled.empty()); | 290 assert(Handled.empty()); |
| 283 const TargetLowering::RegSetMask RegsInclude = | 291 const TargetLowering::RegSetMask RegsInclude = |
| 284 TargetLowering::RegSet_CallerSave; | 292 TargetLowering::RegSet_CallerSave; |
| 285 const TargetLowering::RegSetMask RegsExclude = TargetLowering::RegSet_None; | 293 const TargetLowering::RegSetMask RegsExclude = TargetLowering::RegSet_None; |
| 286 const llvm::SmallBitVector KillsMask = | 294 const llvm::SmallBitVector KillsMask = |
| 287 Func->getTarget()->getRegisterSet(RegsInclude, RegsExclude); | 295 Func->getTarget()->getRegisterSet(RegsInclude, RegsExclude); |
| (...skipping 367 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 655 } | 663 } |
| 656 // Move anything Active or Inactive to Handled for easier handling. | 664 // Move anything Active or Inactive to Handled for easier handling. |
| 657 for (Variable *I : Active) | 665 for (Variable *I : Active) |
| 658 Handled.push_back(I); | 666 Handled.push_back(I); |
| 659 Active.clear(); | 667 Active.clear(); |
| 660 for (Variable *I : Inactive) | 668 for (Variable *I : Inactive) |
| 661 Handled.push_back(I); | 669 Handled.push_back(I); |
| 662 Inactive.clear(); | 670 Inactive.clear(); |
| 663 dump(Func); | 671 dump(Func); |
| 664 | 672 |
| 665 // Finish up by assigning RegNumTmp->RegNum for each Variable. | 673 // TODO(stichnot): Statically choose the size based on the target |
| 674 // being compiled. |
| 675 const size_t REGS_SIZE = 32; |
| 676 llvm::SmallVector<int32_t, REGS_SIZE> Permutation(NumRegisters); |
| 677 if (Randomized) { |
| 678 Func->getTarget()->makeRandomRegisterPermutation( |
| 679 Permutation, PreDefinedRegisters | ~RegMaskFull); |
| 680 } |
| 681 |
| 682 // Finish up by assigning RegNumTmp->RegNum (or a random permutation |
| 683 // thereof) for each Variable. |
| 666 for (Variable *Item : Handled) { | 684 for (Variable *Item : Handled) { |
| 667 int32_t RegNum = Item->getRegNumTmp(); | 685 int32_t RegNum = Item->getRegNumTmp(); |
| 686 int32_t AssignedRegNum = RegNum; |
| 687 |
| 688 if (Randomized && Item->hasRegTmp() && !Item->hasReg()) { |
| 689 AssignedRegNum = Permutation[RegNum]; |
| 690 } |
| 668 if (Verbose) { | 691 if (Verbose) { |
| 669 if (!Item->hasRegTmp()) { | 692 if (!Item->hasRegTmp()) { |
| 670 Str << "Not assigning "; | 693 Str << "Not assigning "; |
| 671 Item->dump(Func); | 694 Item->dump(Func); |
| 672 Str << "\n"; | 695 Str << "\n"; |
| 673 } else { | 696 } else { |
| 674 Str << (RegNum == Item->getRegNum() ? "Reassigning " : "Assigning ") | 697 Str << (AssignedRegNum == Item->getRegNum() ? "Reassigning " |
| 675 << Func->getTarget()->getRegName(RegNum, IceType_i32) << "(r" | 698 : "Assigning ") |
| 676 << RegNum << ") to "; | 699 << Func->getTarget()->getRegName(AssignedRegNum, IceType_i32) |
| 700 << "(r" << AssignedRegNum << ") to "; |
| 677 Item->dump(Func); | 701 Item->dump(Func); |
| 678 Str << "\n"; | 702 Str << "\n"; |
| 679 } | 703 } |
| 680 } | 704 } |
| 681 Item->setRegNum(Item->getRegNumTmp()); | 705 Item->setRegNum(AssignedRegNum); |
| 682 } | 706 } |
| 683 | 707 |
| 684 // TODO: Consider running register allocation one more time, with | 708 // TODO: Consider running register allocation one more time, with |
| 685 // infinite registers, for two reasons. First, evicted live ranges | 709 // infinite registers, for two reasons. First, evicted live ranges |
| 686 // get a second chance for a register. Second, it allows coalescing | 710 // get a second chance for a register. Second, it allows coalescing |
| 687 // of stack slots. If there is no time budget for the second | 711 // of stack slots. If there is no time budget for the second |
| 688 // register allocation run, each unallocated variable just gets its | 712 // register allocation run, each unallocated variable just gets its |
| 689 // own slot. | 713 // own slot. |
| 690 // | 714 // |
| 691 // Another idea for coalescing stack slots is to initialize the | 715 // Another idea for coalescing stack slots is to initialize the |
| (...skipping 27 matching lines...) Expand all Loading... |
| 719 Str << "\n"; | 743 Str << "\n"; |
| 720 } | 744 } |
| 721 Str << "++++++ Inactive:\n"; | 745 Str << "++++++ Inactive:\n"; |
| 722 for (const Variable *Item : Inactive) { | 746 for (const Variable *Item : Inactive) { |
| 723 dumpLiveRange(Item, Func); | 747 dumpLiveRange(Item, Func); |
| 724 Str << "\n"; | 748 Str << "\n"; |
| 725 } | 749 } |
| 726 } | 750 } |
| 727 | 751 |
| 728 } // end of namespace Ice | 752 } // end of namespace Ice |
| OLD | NEW |