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 |