| 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 19 matching lines...) Expand all Loading... |
| 30 // being compiled. | 30 // being compiled. |
| 31 constexpr size_t REGS_SIZE = 32; | 31 constexpr size_t REGS_SIZE = 32; |
| 32 | 32 |
| 33 // Returns true if Var has any definitions within Item's live range. | 33 // Returns true if Var has any definitions within Item's live range. |
| 34 // TODO(stichnot): Consider trimming the Definitions list similar to | 34 // TODO(stichnot): Consider trimming the Definitions list similar to |
| 35 // how the live ranges are trimmed, since all the overlapsDefs() tests | 35 // how the live ranges are trimmed, since all the overlapsDefs() tests |
| 36 // are whether some variable's definitions overlap Cur, and trimming | 36 // are whether some variable's definitions overlap Cur, and trimming |
| 37 // is with respect Cur.start. Initial tests show no measurable | 37 // is with respect Cur.start. Initial tests show no measurable |
| 38 // performance difference, so we'll keep the code simple for now. | 38 // performance difference, so we'll keep the code simple for now. |
| 39 bool overlapsDefs(const Cfg *Func, const Variable *Item, const Variable *Var) { | 39 bool overlapsDefs(const Cfg *Func, const Variable *Item, const Variable *Var) { |
| 40 const bool UseTrimmed = true; | 40 constexpr bool UseTrimmed = true; |
| 41 VariablesMetadata *VMetadata = Func->getVMetadata(); | 41 VariablesMetadata *VMetadata = Func->getVMetadata(); |
| 42 if (const Inst *FirstDef = VMetadata->getFirstDefinition(Var)) | 42 if (const Inst *FirstDef = VMetadata->getFirstDefinition(Var)) |
| 43 if (Item->getLiveRange().overlapsInst(FirstDef->getNumber(), UseTrimmed)) | 43 if (Item->getLiveRange().overlapsInst(FirstDef->getNumber(), UseTrimmed)) |
| 44 return true; | 44 return true; |
| 45 const InstDefList &Defs = VMetadata->getLatterDefinitions(Var); | 45 const InstDefList &Defs = VMetadata->getLatterDefinitions(Var); |
| 46 for (size_t i = 0; i < Defs.size(); ++i) { | 46 for (size_t i = 0; i < Defs.size(); ++i) { |
| 47 if (Item->getLiveRange().overlapsInst(Defs[i]->getNumber(), UseTrimmed)) | 47 if (Item->getLiveRange().overlapsInst(Defs[i]->getNumber(), UseTrimmed)) |
| 48 return true; | 48 return true; |
| 49 } | 49 } |
| 50 return false; | 50 return false; |
| (...skipping 15 matching lines...) Expand all Loading... |
| 66 Str << "," << Defs[i]->getNumber(); | 66 Str << "," << Defs[i]->getNumber(); |
| 67 } | 67 } |
| 68 Str << "\n"; | 68 Str << "\n"; |
| 69 } | 69 } |
| 70 } | 70 } |
| 71 | 71 |
| 72 void dumpLiveRange(const Variable *Var, const Cfg *Func) { | 72 void dumpLiveRange(const Variable *Var, const Cfg *Func) { |
| 73 if (!BuildDefs::dump()) | 73 if (!BuildDefs::dump()) |
| 74 return; | 74 return; |
| 75 Ostream &Str = Func->getContext()->getStrDump(); | 75 Ostream &Str = Func->getContext()->getStrDump(); |
| 76 const static size_t BufLen = 30; | 76 char buf[30]; |
| 77 char buf[BufLen]; | 77 snprintf(buf, llvm::array_lengthof(buf), "%2d", Var->getRegNumTmp()); |
| 78 snprintf(buf, BufLen, "%2d", Var->getRegNumTmp()); | |
| 79 Str << "R=" << buf << " V="; | 78 Str << "R=" << buf << " V="; |
| 80 Var->dump(Func); | 79 Var->dump(Func); |
| 81 Str << " Range=" << Var->getLiveRange(); | 80 Str << " Range=" << Var->getLiveRange(); |
| 82 } | 81 } |
| 83 | 82 |
| 84 } // end of anonymous namespace | 83 } // end of anonymous namespace |
| 85 | 84 |
| 86 // Prepare for full register allocation of all variables. We depend | 85 // Prepare for full register allocation of all variables. We depend |
| 87 // on liveness analysis to have calculated live ranges. | 86 // on liveness analysis to have calculated live ranges. |
| 88 void LinearScan::initForGlobal() { | 87 void LinearScan::initForGlobal() { |
| 89 TimerMarker T(TimerStack::TT_initUnhandled, Func); | 88 TimerMarker T(TimerStack::TT_initUnhandled, Func); |
| 90 FindPreference = true; | 89 FindPreference = true; |
| 91 FindOverlap = true; | 90 // For full register allocation, normally we want to enable FindOverlap |
| 91 // (meaning we look for opportunities for two overlapping live ranges to |
| 92 // safely share the same register). However, we disable it for phi-lowering |
| 93 // register allocation since no overlap opportunities should be available and |
| 94 // it's more expensive to look for opportunities. |
| 95 FindOverlap = (Kind != RAK_Phi); |
| 92 const VarList &Vars = Func->getVariables(); | 96 const VarList &Vars = Func->getVariables(); |
| 93 Unhandled.reserve(Vars.size()); | 97 Unhandled.reserve(Vars.size()); |
| 94 UnhandledPrecolored.reserve(Vars.size()); | 98 UnhandledPrecolored.reserve(Vars.size()); |
| 95 // Gather the live ranges of all variables and add them to the | 99 // Gather the live ranges of all variables and add them to the |
| 96 // Unhandled set. | 100 // Unhandled set. |
| 97 for (Variable *Var : Vars) { | 101 for (Variable *Var : Vars) { |
| 98 // Explicitly don't consider zero-weight variables, which are | 102 // Explicitly don't consider zero-weight variables, which are |
| 99 // meant to be spill slots. | 103 // meant to be spill slots. |
| 100 if (Var->getWeight().isZero()) | 104 if (Var->getWeight().isZero()) |
| 101 continue; | 105 continue; |
| 102 // Don't bother if the variable has a null live range, which means | 106 // Don't bother if the variable has a null live range, which means |
| 103 // it was never referenced. | 107 // it was never referenced. |
| 104 if (Var->getLiveRange().isEmpty()) | 108 if (Var->getLiveRange().isEmpty()) |
| 105 continue; | 109 continue; |
| 110 // Post phi lowering register allocation is only concerned with variables |
| 111 // that are infinite-weight or pre-colored. |
| 112 if (Kind == RAK_Phi && !Var->getWeight().isInf() && !Var->hasReg()) |
| 113 continue; |
| 106 Var->untrimLiveRange(); | 114 Var->untrimLiveRange(); |
| 107 Unhandled.push_back(Var); | 115 Unhandled.push_back(Var); |
| 108 if (Var->hasReg()) { | 116 if (Var->hasReg()) { |
| 109 Var->setRegNumTmp(Var->getRegNum()); | 117 Var->setRegNumTmp(Var->getRegNum()); |
| 110 Var->setLiveRangeInfiniteWeight(); | 118 Var->setLiveRangeInfiniteWeight(); |
| 111 UnhandledPrecolored.push_back(Var); | 119 UnhandledPrecolored.push_back(Var); |
| 112 } | 120 } |
| 113 } | 121 } |
| 114 | 122 |
| 115 // Build the (ordered) list of FakeKill instruction numbers. | 123 // Build the (ordered) list of FakeKill instruction numbers. |
| 116 Kills.clear(); | 124 Kills.clear(); |
| 125 // Phi lowering should not be creating new call instructions, so there should |
| 126 // be no infinite-weight not-yet-colored live ranges that span a call |
| 127 // instruction, hence no need to construct the Kills list. |
| 128 if (Kind == RAK_Phi) |
| 129 return; |
| 117 for (CfgNode *Node : Func->getNodes()) { | 130 for (CfgNode *Node : Func->getNodes()) { |
| 118 for (Inst &I : Node->getInsts()) { | 131 for (Inst &I : Node->getInsts()) { |
| 119 if (auto Kill = llvm::dyn_cast<InstFakeKill>(&I)) { | 132 if (auto Kill = llvm::dyn_cast<InstFakeKill>(&I)) { |
| 120 if (!Kill->isDeleted() && !Kill->getLinked()->isDeleted()) | 133 if (!Kill->isDeleted() && !Kill->getLinked()->isDeleted()) |
| 121 Kills.push_back(I.getNumber()); | 134 Kills.push_back(I.getNumber()); |
| 122 } | 135 } |
| 123 } | 136 } |
| 124 } | 137 } |
| 125 } | 138 } |
| 126 | 139 |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 189 } | 202 } |
| 190 | 203 |
| 191 Unhandled.reserve(NumVars); | 204 Unhandled.reserve(NumVars); |
| 192 UnhandledPrecolored.reserve(NumVars); | 205 UnhandledPrecolored.reserve(NumVars); |
| 193 for (SizeT i = 0; i < Vars.size(); ++i) { | 206 for (SizeT i = 0; i < Vars.size(); ++i) { |
| 194 Variable *Var = Vars[i]; | 207 Variable *Var = Vars[i]; |
| 195 if (LRBegin[i] != Inst::NumberSentinel) { | 208 if (LRBegin[i] != Inst::NumberSentinel) { |
| 196 assert(LREnd[i] != Inst::NumberSentinel); | 209 assert(LREnd[i] != Inst::NumberSentinel); |
| 197 Unhandled.push_back(Var); | 210 Unhandled.push_back(Var); |
| 198 Var->resetLiveRange(); | 211 Var->resetLiveRange(); |
| 199 const uint32_t WeightDelta = 1; | 212 constexpr uint32_t WeightDelta = 1; |
| 200 Var->addLiveRange(LRBegin[i], LREnd[i], WeightDelta); | 213 Var->addLiveRange(LRBegin[i], LREnd[i], WeightDelta); |
| 201 Var->untrimLiveRange(); | 214 Var->untrimLiveRange(); |
| 202 if (Var->hasReg()) { | 215 if (Var->hasReg()) { |
| 203 Var->setRegNumTmp(Var->getRegNum()); | 216 Var->setRegNumTmp(Var->getRegNum()); |
| 204 Var->setLiveRangeInfiniteWeight(); | 217 Var->setLiveRangeInfiniteWeight(); |
| 205 UnhandledPrecolored.push_back(Var); | 218 UnhandledPrecolored.push_back(Var); |
| 206 } | 219 } |
| 207 --NumVars; | 220 --NumVars; |
| 208 } | 221 } |
| 209 } | 222 } |
| 210 // This isn't actually a fatal condition, but it would be nice to | 223 // This isn't actually a fatal condition, but it would be nice to |
| 211 // know if we somehow pre-calculated Unhandled's size wrong. | 224 // know if we somehow pre-calculated Unhandled's size wrong. |
| 212 assert(NumVars == 0); | 225 assert(NumVars == 0); |
| 213 | 226 |
| 214 // Don't build up the list of Kills because we know that no | 227 // Don't build up the list of Kills because we know that no |
| 215 // infinite-weight Variable has a live range spanning a call. | 228 // infinite-weight Variable has a live range spanning a call. |
| 216 Kills.clear(); | 229 Kills.clear(); |
| 217 } | 230 } |
| 218 | 231 |
| 219 void LinearScan::init(RegAllocKind Kind) { | 232 void LinearScan::init(RegAllocKind Kind) { |
| 233 this->Kind = Kind; |
| 220 Unhandled.clear(); | 234 Unhandled.clear(); |
| 221 UnhandledPrecolored.clear(); | 235 UnhandledPrecolored.clear(); |
| 222 Handled.clear(); | 236 Handled.clear(); |
| 223 Inactive.clear(); | 237 Inactive.clear(); |
| 224 Active.clear(); | 238 Active.clear(); |
| 225 | 239 |
| 226 switch (Kind) { | 240 switch (Kind) { |
| 241 case RAK_Unknown: |
| 242 llvm::report_fatal_error("Invalid RAK_Unknown"); |
| 243 break; |
| 227 case RAK_Global: | 244 case RAK_Global: |
| 245 case RAK_Phi: |
| 228 initForGlobal(); | 246 initForGlobal(); |
| 229 break; | 247 break; |
| 230 case RAK_InfOnly: | 248 case RAK_InfOnly: |
| 231 initForInfOnly(); | 249 initForInfOnly(); |
| 232 break; | 250 break; |
| 233 } | 251 } |
| 234 | 252 |
| 235 struct CompareRanges { | 253 struct CompareRanges { |
| 236 bool operator()(const Variable *L, const Variable *R) { | 254 bool operator()(const Variable *L, const Variable *R) { |
| 237 InstNumberT Lstart = L->getLiveRange().getStart(); | 255 InstNumberT Lstart = L->getLiveRange().getStart(); |
| 238 InstNumberT Rstart = R->getLiveRange().getStart(); | 256 InstNumberT Rstart = R->getLiveRange().getStart(); |
| 239 if (Lstart == Rstart) | 257 if (Lstart == Rstart) |
| 240 return L->getIndex() < R->getIndex(); | 258 return L->getIndex() < R->getIndex(); |
| 241 return Lstart < Rstart; | 259 return Lstart < Rstart; |
| 242 } | 260 } |
| 243 }; | 261 }; |
| 244 // Do a reverse sort so that erasing elements (from the end) is fast. | 262 // Do a reverse sort so that erasing elements (from the end) is fast. |
| 245 std::sort(Unhandled.rbegin(), Unhandled.rend(), CompareRanges()); | 263 std::sort(Unhandled.rbegin(), Unhandled.rend(), CompareRanges()); |
| 246 std::sort(UnhandledPrecolored.rbegin(), UnhandledPrecolored.rend(), | 264 std::sort(UnhandledPrecolored.rbegin(), UnhandledPrecolored.rend(), |
| 247 CompareRanges()); | 265 CompareRanges()); |
| 248 | 266 |
| 249 Handled.reserve(Unhandled.size()); | 267 Handled.reserve(Unhandled.size()); |
| 250 Inactive.reserve(Unhandled.size()); | 268 Inactive.reserve(Unhandled.size()); |
| 251 Active.reserve(Unhandled.size()); | 269 Active.reserve(Unhandled.size()); |
| 252 } | 270 } |
| 253 | 271 |
| 272 // This is called when Cur must be allocated a register but no registers are |
| 273 // available across Cur's live range. To handle this, we find a register that |
| 274 // is not explicitly used during Cur's live range, spill that register to a |
| 275 // stack location right before Cur's live range begins, and fill (reload) the |
| 276 // register from the stack location right after Cur's live range ends. |
| 277 void LinearScan::addSpillFill(Variable *Cur, llvm::SmallBitVector RegMask) { |
| 278 // Identify the actual instructions that begin and end Cur's live range. |
| 279 // Iterate through Cur's node's instruction list until we find the actual |
| 280 // instructions with instruction numbers corresponding to Cur's recorded live |
| 281 // range endpoints. This sounds inefficient but shouldn't be a problem in |
| 282 // practice because: |
| 283 // (1) This function is almost never called in practice. |
| 284 // (2) Since this register over-subscription problem happens only for |
| 285 // phi-lowered instructions, the number of instructions in the node is |
| 286 // proportional to the number of phi instructions in the original node, |
| 287 // which is never very large in practice. |
| 288 // (3) We still have to iterate through all instructions of Cur's live range |
| 289 // to find all explicitly used registers (though the live range is usually |
| 290 // only 2-3 instructions), so the main cost that could be avoided would be |
| 291 // finding the instruction that begin's Cur's live range. |
| 292 assert(!Cur->getLiveRange().isEmpty()); |
| 293 InstNumberT Start = Cur->getLiveRange().getStart(); |
| 294 InstNumberT End = Cur->getLiveRange().getEnd(); |
| 295 CfgNode *Node = Func->getVMetadata()->getLocalUseNode(Cur); |
| 296 assert(Node); |
| 297 InstList &Insts = Node->getInsts(); |
| 298 InstList::iterator SpillPoint = Insts.end(); |
| 299 InstList::iterator FillPoint = Insts.end(); |
| 300 // Stop searching after we have found both the SpillPoint and the FillPoint. |
| 301 for (auto I = Insts.begin(), E = Insts.end(); |
| 302 I != E && (SpillPoint == E || FillPoint == E); ++I) { |
| 303 if (I->getNumber() == Start) |
| 304 SpillPoint = I; |
| 305 if (I->getNumber() == End) |
| 306 FillPoint = I; |
| 307 if (SpillPoint != E) { |
| 308 // Remove from RegMask any physical registers referenced during Cur's live |
| 309 // range. Start looking after SpillPoint gets set, i.e. once Cur's live |
| 310 // range begins. |
| 311 for (SizeT i = 0; i < I->getSrcSize(); ++i) { |
| 312 Operand *Src = I->getSrc(i); |
| 313 SizeT NumVars = Src->getNumVars(); |
| 314 for (SizeT j = 0; j < NumVars; ++j) { |
| 315 const Variable *Var = Src->getVar(j); |
| 316 if (Var->hasRegTmp()) |
| 317 RegMask[Var->getRegNumTmp()] = false; |
| 318 } |
| 319 } |
| 320 } |
| 321 } |
| 322 assert(SpillPoint != Insts.end()); |
| 323 assert(FillPoint != Insts.end()); |
| 324 ++FillPoint; |
| 325 // TODO(stichnot): Randomize instead of find_first(). |
| 326 int32_t RegNum = RegMask.find_first(); |
| 327 assert(RegNum != -1); |
| 328 Cur->setRegNumTmp(RegNum); |
| 329 TargetLowering *Target = Func->getTarget(); |
| 330 Variable *Preg = Target->getPhysicalRegister(RegNum, Cur->getType()); |
| 331 // TODO(stichnot): Add SpillLoc to VariablesMetadata tracking so that SpillLoc |
| 332 // is correctly identified as !isMultiBlock(), reducing stack frame size. |
| 333 Variable *SpillLoc = Func->makeVariable(Cur->getType()); |
| 334 // Add "reg=FakeDef;spill=reg" before SpillPoint |
| 335 Target->lowerInst(Node, SpillPoint, InstFakeDef::create(Func, Preg)); |
| 336 Target->lowerInst(Node, SpillPoint, InstAssign::create(Func, SpillLoc, Preg)); |
| 337 // add "reg=spill;FakeUse(reg)" before FillPoint |
| 338 Target->lowerInst(Node, FillPoint, InstAssign::create(Func, Preg, SpillLoc)); |
| 339 Target->lowerInst(Node, FillPoint, InstFakeUse::create(Func, Preg)); |
| 340 } |
| 341 |
| 254 // Implements the linear-scan algorithm. Based on "Linear Scan | 342 // Implements the linear-scan algorithm. Based on "Linear Scan |
| 255 // Register Allocation in the Context of SSA Form and Register | 343 // Register Allocation in the Context of SSA Form and Register |
| 256 // Constraints" by Hanspeter Mössenböck and Michael Pfeiffer, | 344 // Constraints" by Hanspeter Mössenböck and Michael Pfeiffer, |
| 257 // ftp://ftp.ssw.uni-linz.ac.at/pub/Papers/Moe02.PDF . This | 345 // ftp://ftp.ssw.uni-linz.ac.at/pub/Papers/Moe02.PDF . This |
| 258 // implementation is modified to take affinity into account and allow | 346 // implementation is modified to take affinity into account and allow |
| 259 // two interfering variables to share the same register in certain | 347 // two interfering variables to share the same register in certain |
| 260 // cases. | 348 // cases. |
| 261 // | 349 // |
| 262 // Requires running Cfg::liveness(Liveness_Intervals) in | 350 // Requires running Cfg::liveness(Liveness_Intervals) in |
| 263 // preparation. Results are assigned to Variable::RegNum for each | 351 // preparation. Results are assigned to Variable::RegNum for each |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 305 if (Verbose) { | 393 if (Verbose) { |
| 306 Ostream &Str = Ctx->getStrDump(); | 394 Ostream &Str = Ctx->getStrDump(); |
| 307 Str << "\nConsidering "; | 395 Str << "\nConsidering "; |
| 308 dumpLiveRange(Cur, Func); | 396 dumpLiveRange(Cur, Func); |
| 309 Str << "\n"; | 397 Str << "\n"; |
| 310 } | 398 } |
| 311 const llvm::SmallBitVector RegMask = | 399 const llvm::SmallBitVector RegMask = |
| 312 RegMaskFull & Func->getTarget()->getRegisterSetForType(Cur->getType()); | 400 RegMaskFull & Func->getTarget()->getRegisterSetForType(Cur->getType()); |
| 313 KillsRange.trim(Cur->getLiveRange().getStart()); | 401 KillsRange.trim(Cur->getLiveRange().getStart()); |
| 314 | 402 |
| 315 // Check for precolored ranges. If Cur is precolored, it | 403 // Check for pre-colored ranges. If Cur is pre-colored, it |
| 316 // definitely gets that register. Previously processed live | 404 // definitely gets that register. Previously processed live |
| 317 // ranges would have avoided that register due to it being | 405 // ranges would have avoided that register due to it being |
| 318 // precolored. Future processed live ranges won't evict that | 406 // pre-colored. Future processed live ranges won't evict that |
| 319 // register because the live range has infinite weight. | 407 // register because the live range has infinite weight. |
| 320 if (Cur->hasReg()) { | 408 if (Cur->hasReg()) { |
| 321 int32_t RegNum = Cur->getRegNum(); | 409 int32_t RegNum = Cur->getRegNum(); |
| 322 // RegNumTmp should have already been set above. | 410 // RegNumTmp should have already been set above. |
| 323 assert(Cur->getRegNumTmp() == RegNum); | 411 assert(Cur->getRegNumTmp() == RegNum); |
| 324 if (Verbose) { | 412 if (Verbose) { |
| 325 Ostream &Str = Ctx->getStrDump(); | 413 Ostream &Str = Ctx->getStrDump(); |
| 326 Str << "Precoloring "; | 414 Str << "Precoloring "; |
| 327 dumpLiveRange(Cur, Func); | 415 dumpLiveRange(Cur, Func); |
| 328 Str << "\n"; | 416 Str << "\n"; |
| (...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 494 overlapsDefs(Func, Cur, Item)) { | 582 overlapsDefs(Func, Cur, Item)) { |
| 495 AllowOverlap = false; | 583 AllowOverlap = false; |
| 496 dumpDisableOverlap(Func, Item, "Active"); | 584 dumpDisableOverlap(Func, Item, "Active"); |
| 497 } | 585 } |
| 498 } | 586 } |
| 499 } | 587 } |
| 500 | 588 |
| 501 llvm::SmallVector<RegWeight, REGS_SIZE> Weights(RegMask.size()); | 589 llvm::SmallVector<RegWeight, REGS_SIZE> Weights(RegMask.size()); |
| 502 | 590 |
| 503 // Remove registers from the Free[] list where an Unhandled | 591 // Remove registers from the Free[] list where an Unhandled |
| 504 // precolored range overlaps with the current range, and set those | 592 // pre-colored range overlaps with the current range, and set those |
| 505 // registers to infinite weight so that they aren't candidates for | 593 // registers to infinite weight so that they aren't candidates for |
| 506 // eviction. Cur->rangeEndsBefore(Item) is an early exit check | 594 // eviction. Cur->rangeEndsBefore(Item) is an early exit check |
| 507 // that turns a guaranteed O(N^2) algorithm into expected linear | 595 // that turns a guaranteed O(N^2) algorithm into expected linear |
| 508 // complexity. | 596 // complexity. |
| 509 llvm::SmallBitVector PrecoloredUnhandledMask(RegMask.size()); | 597 llvm::SmallBitVector PrecoloredUnhandledMask(RegMask.size()); |
| 510 // Note: PrecoloredUnhandledMask is only used for dumping. | 598 // Note: PrecoloredUnhandledMask is only used for dumping. |
| 511 for (Variable *Item : reverse_range(UnhandledPrecolored)) { | 599 for (Variable *Item : reverse_range(UnhandledPrecolored)) { |
| 512 assert(Item->hasReg()); | 600 assert(Item->hasReg()); |
| 513 if (Cur->rangeEndsBefore(Item)) | 601 if (Cur->rangeEndsBefore(Item)) |
| 514 break; | 602 break; |
| 515 if (Item->rangeOverlaps(Cur)) { | 603 if (Item->rangeOverlaps(Cur)) { |
| 516 int32_t ItemReg = Item->getRegNum(); // Note: not getRegNumTmp() | 604 int32_t ItemReg = Item->getRegNum(); // Note: not getRegNumTmp() |
| 517 Weights[ItemReg].setWeight(RegWeight::Inf); | 605 Weights[ItemReg].setWeight(RegWeight::Inf); |
| 518 Free[ItemReg] = false; | 606 Free[ItemReg] = false; |
| 519 PrecoloredUnhandledMask[ItemReg] = true; | 607 PrecoloredUnhandledMask[ItemReg] = true; |
| 520 // Disable AllowOverlap if the preferred register is one of | 608 // Disable AllowOverlap if the preferred register is one of |
| 521 // these precolored unhandled overlapping ranges. | 609 // these pre-colored unhandled overlapping ranges. |
| 522 if (AllowOverlap && ItemReg == PreferReg) { | 610 if (AllowOverlap && ItemReg == PreferReg) { |
| 523 AllowOverlap = false; | 611 AllowOverlap = false; |
| 524 dumpDisableOverlap(Func, Item, "PrecoloredUnhandled"); | 612 dumpDisableOverlap(Func, Item, "PrecoloredUnhandled"); |
| 525 } | 613 } |
| 526 } | 614 } |
| 527 } | 615 } |
| 528 | 616 |
| 529 // Remove scratch registers from the Free[] list, and mark their | 617 // Remove scratch registers from the Free[] list, and mark their |
| 530 // Weights[] as infinite, if KillsRange overlaps Cur's live range. | 618 // Weights[] as infinite, if KillsRange overlaps Cur's live range. |
| 531 const bool UseTrimmed = true; | 619 constexpr bool UseTrimmed = true; |
| 532 if (Cur->getLiveRange().overlaps(KillsRange, UseTrimmed)) { | 620 if (Cur->getLiveRange().overlaps(KillsRange, UseTrimmed)) { |
| 533 Free.reset(KillsMask); | 621 Free.reset(KillsMask); |
| 534 for (int i = KillsMask.find_first(); i != -1; | 622 for (int i = KillsMask.find_first(); i != -1; |
| 535 i = KillsMask.find_next(i)) { | 623 i = KillsMask.find_next(i)) { |
| 536 Weights[i].setWeight(RegWeight::Inf); | 624 Weights[i].setWeight(RegWeight::Inf); |
| 537 if (PreferReg == i) | 625 if (PreferReg == i) |
| 538 AllowOverlap = false; | 626 AllowOverlap = false; |
| 539 } | 627 } |
| 540 } | 628 } |
| 541 | 629 |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 608 if (RegMask[i] && Weights[i] < Weights[MinWeightIndex]) | 696 if (RegMask[i] && Weights[i] < Weights[MinWeightIndex]) |
| 609 MinWeightIndex = i; | 697 MinWeightIndex = i; |
| 610 } | 698 } |
| 611 | 699 |
| 612 if (Cur->getLiveRange().getWeight() <= Weights[MinWeightIndex]) { | 700 if (Cur->getLiveRange().getWeight() <= Weights[MinWeightIndex]) { |
| 613 // Cur doesn't have priority over any other live ranges, so | 701 // Cur doesn't have priority over any other live ranges, so |
| 614 // don't allocate any register to it, and move it to the | 702 // don't allocate any register to it, and move it to the |
| 615 // Handled state. | 703 // Handled state. |
| 616 Handled.push_back(Cur); | 704 Handled.push_back(Cur); |
| 617 if (Cur->getLiveRange().getWeight().isInf()) { | 705 if (Cur->getLiveRange().getWeight().isInf()) { |
| 618 Func->setError("Unable to find a physical register for an " | 706 if (Kind == RAK_Phi) |
| 619 "infinite-weight live range"); | 707 addSpillFill(Cur, RegMask); |
| 708 else |
| 709 Func->setError("Unable to find a physical register for an " |
| 710 "infinite-weight live range"); |
| 620 } | 711 } |
| 621 } else { | 712 } else { |
| 622 // Evict all live ranges in Active that register number | 713 // Evict all live ranges in Active that register number |
| 623 // MinWeightIndex is assigned to. | 714 // MinWeightIndex is assigned to. |
| 624 for (SizeT I = Active.size(); I > 0; --I) { | 715 for (SizeT I = Active.size(); I > 0; --I) { |
| 625 const SizeT Index = I - 1; | 716 const SizeT Index = I - 1; |
| 626 Variable *Item = Active[Index]; | 717 Variable *Item = Active[Index]; |
| 627 if (Item->getRegNumTmp() == MinWeightIndex) { | 718 if (Item->getRegNumTmp() == MinWeightIndex) { |
| 628 if (Verbose) { | 719 if (Verbose) { |
| 629 Ostream &Str = Ctx->getStrDump(); | 720 Ostream &Str = Ctx->getStrDump(); |
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 760 Str << "\n"; | 851 Str << "\n"; |
| 761 } | 852 } |
| 762 Str << "++++++ Inactive:\n"; | 853 Str << "++++++ Inactive:\n"; |
| 763 for (const Variable *Item : Inactive) { | 854 for (const Variable *Item : Inactive) { |
| 764 dumpLiveRange(Item, Func); | 855 dumpLiveRange(Item, Func); |
| 765 Str << "\n"; | 856 Str << "\n"; |
| 766 } | 857 } |
| 767 } | 858 } |
| 768 | 859 |
| 769 } // end of namespace Ice | 860 } // end of namespace Ice |
| OLD | NEW |