Chromium Code Reviews| 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 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 66 const static size_t BufLen = 30; | 66 const static size_t BufLen = 30; |
| 67 char buf[BufLen]; | 67 char buf[BufLen]; |
| 68 snprintf(buf, BufLen, "%2d", Var->getRegNumTmp()); | 68 snprintf(buf, BufLen, "%2d", Var->getRegNumTmp()); |
| 69 Str << "R=" << buf << " V="; | 69 Str << "R=" << buf << " V="; |
| 70 Var->dump(Func); | 70 Var->dump(Func); |
| 71 Str << " Range=" << Var->getLiveRange(); | 71 Str << " Range=" << Var->getLiveRange(); |
| 72 } | 72 } |
| 73 | 73 |
| 74 } // end of anonymous namespace | 74 } // end of anonymous namespace |
| 75 | 75 |
| 76 void LinearScan::initForGlobalAlloc() { | 76 // Prepare for full register allocation of all variables. We depend |
| 77 // on liveness analysis to have calculated live ranges. | |
| 78 void LinearScan::initForGlobal() { | |
| 77 TimerMarker T(TimerStack::TT_initUnhandled, Func); | 79 TimerMarker T(TimerStack::TT_initUnhandled, Func); |
| 78 Unhandled.clear(); | 80 FindPreference = true; |
| 79 UnhandledPrecolored.clear(); | 81 FindOverlap = true; |
| 80 Handled.clear(); | 82 const VarList &Vars = Func->getVariables(); |
| 81 Inactive.clear(); | 83 Unhandled.reserve(Vars.size()); |
| 82 Active.clear(); | |
| 83 // Gather the live ranges of all variables and add them to the | 84 // Gather the live ranges of all variables and add them to the |
| 84 // Unhandled set. | 85 // Unhandled set. |
| 85 const VarList &Vars = Func->getVariables(); | |
| 86 Unhandled.reserve(Vars.size()); | |
| 87 for (Variable *Var : Vars) { | 86 for (Variable *Var : Vars) { |
| 88 // Explicitly don't consider zero-weight variables, which are | 87 // Explicitly don't consider zero-weight variables, which are |
| 89 // meant to be spill slots. | 88 // meant to be spill slots. |
| 90 if (Var->getWeight() == RegWeight::Zero) | 89 if (Var->getWeight() == RegWeight::Zero) |
| 91 continue; | 90 continue; |
| 92 // Don't bother if the variable has a null live range, which means | 91 // Don't bother if the variable has a null live range, which means |
| 93 // it was never referenced. | 92 // it was never referenced. |
| 94 if (Var->getLiveRange().isEmpty()) | 93 if (Var->getLiveRange().isEmpty()) |
| 95 continue; | 94 continue; |
| 96 Var->untrimLiveRange(); | 95 Var->untrimLiveRange(); |
| 97 Unhandled.push_back(Var); | 96 Unhandled.push_back(Var); |
| 98 if (Var->hasReg()) { | 97 if (Var->hasReg()) { |
| 99 Var->setRegNumTmp(Var->getRegNum()); | 98 Var->setRegNumTmp(Var->getRegNum()); |
| 100 Var->setLiveRangeInfiniteWeight(); | 99 Var->setLiveRangeInfiniteWeight(); |
| 101 UnhandledPrecolored.push_back(Var); | 100 UnhandledPrecolored.push_back(Var); |
| 102 } | 101 } |
| 103 } | 102 } |
| 103 | |
| 104 // Build the (ordered) list of FakeKill instruction numbers. | |
| 105 Kills.clear(); | |
| 106 for (CfgNode *Node : Func->getNodes()) { | |
| 107 for (auto I = Node->getInsts().begin(), E = Node->getInsts().end(); I != E; | |
| 108 ++I) { | |
| 109 if (auto Kill = llvm::dyn_cast<InstFakeKill>(I)) { | |
| 110 if (!Kill->isDeleted() && !Kill->getLinked()->isDeleted()) | |
| 111 Kills.push_back(I->getNumber()); | |
| 112 } | |
| 113 } | |
| 114 } | |
| 115 } | |
| 116 | |
| 117 // Prepare for very simple register allocation of only infinite-weight | |
| 118 // Variables while respecting pre-colored Variables. Some properties | |
| 119 // we take advantage of: | |
| 120 // | |
| 121 // * Live ranges of interest consist of a single segment. | |
| 122 // | |
| 123 // * Live ranges of interest never span a call instruction. | |
| 124 // | |
| 125 // * Phi instructions are not considered because either phis have | |
| 126 // already been lowered, or they don't contain any pre-colored or | |
| 127 // infinite-weight Variables. | |
| 128 // | |
| 129 // * We don't need to renumber instructions before computing live | |
| 130 // ranges because all the high-level ICE instructions are deleted | |
| 131 // prior to lowering, and the low-level instructions are added in | |
| 132 // monotonically increasing order. | |
| 133 // | |
| 134 // * There are no opportunities for register preference or allowing | |
| 135 // overlap. | |
| 136 // | |
| 137 // Some properties we aren't (yet) taking advantage of: | |
| 138 // | |
| 139 // * Because live ranges are a single segment, the Unhandled set will | |
| 140 // always be empty, and the live range trimming operation is | |
| 141 // unnecessary. | |
| 142 // | |
| 143 // * Calculating overlap of single-segment live ranges could be | |
| 144 // optimized a bit. | |
| 145 void LinearScan::initForInfOnly() { | |
| 146 TimerMarker T(TimerStack::TT_initUnhandled, Func); | |
| 147 FindPreference = false; | |
| 148 FindOverlap = false; | |
| 149 SizeT NumVars = 0; | |
| 150 const VarList &Vars = Func->getVariables(); | |
| 151 | |
| 152 // Iterate across all instructions and record the begin and end of | |
| 153 // the live range for each variable that is pre-colored or infinite | |
| 154 // weight. | |
| 155 std::vector<InstNumberT> LRBegin(Vars.size(), Inst::NumberSentinel); | |
| 156 std::vector<InstNumberT> LREnd(Vars.size(), Inst::NumberSentinel); | |
| 157 for (CfgNode *Node : Func->getNodes()) { | |
| 158 for (auto Inst = Node->getInsts().begin(), E = Node->getInsts().end(); | |
| 159 Inst != E; ++Inst) { | |
| 160 if (Inst->isDeleted()) | |
| 161 continue; | |
| 162 if (const Variable *Var = Inst->getDest()) { | |
| 163 if (Var->hasReg() || Var->getWeight() == RegWeight::Inf) { | |
| 164 if (LRBegin[Var->getIndex()] == Inst::NumberSentinel) { | |
| 165 LRBegin[Var->getIndex()] = Inst->getNumber(); | |
| 166 ++NumVars; | |
| 167 } | |
| 168 } | |
| 169 } | |
| 170 for (SizeT I = 0; I < Inst->getSrcSize(); ++I) { | |
| 171 Operand *Src = Inst->getSrc(I); | |
| 172 SizeT NumVars = Src->getNumVars(); | |
| 173 for (SizeT J = 0; J < NumVars; ++J) { | |
| 174 const Variable *Var = Src->getVar(J); | |
| 175 if (Var->hasReg() || Var->getWeight() == RegWeight::Inf) | |
| 176 LREnd[Var->getIndex()] = Inst->getNumber(); | |
| 177 } | |
| 178 } | |
| 179 } | |
| 180 } | |
| 181 | |
| 182 Unhandled.reserve(NumVars); | |
| 183 for (SizeT i = 0; i < Vars.size(); ++i) { | |
| 184 Variable *Var = Vars[i]; | |
| 185 if (LRBegin[i] != Inst::NumberSentinel) { | |
| 186 assert(LREnd[i] != Inst::NumberSentinel); | |
| 187 Unhandled.push_back(Var); | |
| 188 Var->resetLiveRange(); | |
| 189 const uint32_t WeightDelta = 1; | |
| 190 Var->addLiveRange(LRBegin[i], LREnd[i], WeightDelta); | |
| 191 Var->untrimLiveRange(); | |
| 192 if (Var->hasReg()) { | |
| 193 Var->setRegNumTmp(Var->getRegNum()); | |
| 194 Var->setLiveRangeInfiniteWeight(); | |
| 195 UnhandledPrecolored.push_back(Var); | |
| 196 } | |
| 197 --NumVars; | |
| 198 } | |
| 199 } | |
| 200 // This isn't actually a fatal considition, but it would be nice to | |
|
jvoung (off chromium)
2014/11/14 23:26:22
"considition -> condition"
Jim Stichnoth
2014/11/14 23:51:34
Done.
| |
| 201 // know if we somehow pre-calculated Unhandled's size wrong. | |
| 202 assert(NumVars == 0); | |
| 203 | |
| 204 // Don't build up the list of Kills because we know that no | |
| 205 // infinite-weight Variable has a live range spanning a call. | |
|
jvoung (off chromium)
2014/11/14 23:26:22
It might be nice to have a assert-level verifier p
Jim Stichnoth
2014/11/14 23:51:34
Agreed. Also to verify things like monotonically
| |
| 206 Kills.clear(); | |
| 207 } | |
| 208 | |
| 209 void LinearScan::init(RegAllocKind Kind) { | |
| 210 Unhandled.clear(); | |
| 211 UnhandledPrecolored.clear(); | |
| 212 Handled.clear(); | |
| 213 Inactive.clear(); | |
| 214 Active.clear(); | |
| 215 | |
| 216 switch (Kind) { | |
| 217 case RAK_Global: | |
| 218 initForGlobal(); | |
| 219 break; | |
| 220 case RAK_InfOnly: | |
| 221 initForInfOnly(); | |
| 222 break; | |
| 223 } | |
| 224 | |
| 104 struct CompareRanges { | 225 struct CompareRanges { |
| 105 bool operator()(const Variable *L, const Variable *R) { | 226 bool operator()(const Variable *L, const Variable *R) { |
| 106 InstNumberT Lstart = L->getLiveRange().getStart(); | 227 InstNumberT Lstart = L->getLiveRange().getStart(); |
| 107 InstNumberT Rstart = R->getLiveRange().getStart(); | 228 InstNumberT Rstart = R->getLiveRange().getStart(); |
| 108 if (Lstart == Rstart) | 229 if (Lstart == Rstart) |
| 109 return L->getIndex() < R->getIndex(); | 230 return L->getIndex() < R->getIndex(); |
| 110 return Lstart < Rstart; | 231 return Lstart < Rstart; |
| 111 } | 232 } |
| 112 }; | 233 }; |
| 113 // Do a reverse sort so that erasing elements (from the end) is fast. | 234 // Do a reverse sort so that erasing elements (from the end) is fast. |
| 114 std::sort(Unhandled.rbegin(), Unhandled.rend(), CompareRanges()); | 235 std::sort(Unhandled.rbegin(), Unhandled.rend(), CompareRanges()); |
| 115 std::sort(UnhandledPrecolored.rbegin(), UnhandledPrecolored.rend(), | 236 std::sort(UnhandledPrecolored.rbegin(), UnhandledPrecolored.rend(), |
| 116 CompareRanges()); | 237 CompareRanges()); |
| 117 | |
| 118 // Build the (ordered) list of FakeKill instruction numbers. | |
| 119 Kills.clear(); | |
| 120 for (CfgNode *Node : Func->getNodes()) { | |
| 121 for (auto I = Node->getInsts().begin(), E = Node->getInsts().end(); I != E; | |
| 122 ++I) { | |
| 123 if (I->isDeleted()) | |
| 124 continue; | |
| 125 if (auto Kill = llvm::dyn_cast<InstFakeKill>(I)) { | |
| 126 if (!Kill->getLinked()->isDeleted()) | |
| 127 Kills.push_back(I->getNumber()); | |
| 128 } | |
| 129 } | |
| 130 } | |
| 131 } | 238 } |
| 132 | 239 |
| 133 // Implements the linear-scan algorithm. Based on "Linear Scan | 240 // Implements the linear-scan algorithm. Based on "Linear Scan |
| 134 // Register Allocation in the Context of SSA Form and Register | 241 // Register Allocation in the Context of SSA Form and Register |
| 135 // Constraints" by Hanspeter Mössenböck and Michael Pfeiffer, | 242 // Constraints" by Hanspeter Mössenböck and Michael Pfeiffer, |
| 136 // ftp://ftp.ssw.uni-linz.ac.at/pub/Papers/Moe02.PDF . This | 243 // ftp://ftp.ssw.uni-linz.ac.at/pub/Papers/Moe02.PDF . This |
| 137 // implementation is modified to take affinity into account and allow | 244 // implementation is modified to take affinity into account and allow |
| 138 // two interfering variables to share the same register in certain | 245 // two interfering variables to share the same register in certain |
| 139 // cases. | 246 // cases. |
| 140 // | 247 // |
| (...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 285 // currently free, or that is assigned a register that is not free | 392 // currently free, or that is assigned a register that is not free |
| 286 // but overlap is allowed. Overlap is allowed when the Variable | 393 // but overlap is allowed. Overlap is allowed when the Variable |
| 287 // under consideration is single-definition, and its definition is | 394 // under consideration is single-definition, and its definition is |
| 288 // a simple assignment - i.e., the register gets copied/aliased | 395 // a simple assignment - i.e., the register gets copied/aliased |
| 289 // but is never modified. Furthermore, overlap is only allowed | 396 // but is never modified. Furthermore, overlap is only allowed |
| 290 // when preferred Variable definition instructions do not appear | 397 // when preferred Variable definition instructions do not appear |
| 291 // within the current Variable's live range. | 398 // within the current Variable's live range. |
| 292 Variable *Prefer = NULL; | 399 Variable *Prefer = NULL; |
| 293 int32_t PreferReg = Variable::NoRegister; | 400 int32_t PreferReg = Variable::NoRegister; |
| 294 bool AllowOverlap = false; | 401 bool AllowOverlap = false; |
| 295 if (const Inst *DefInst = VMetadata->getFirstDefinition(Cur)) { | 402 if (FindPreference) { |
| 296 assert(DefInst->getDest() == Cur); | 403 if (const Inst *DefInst = VMetadata->getFirstDefinition(Cur)) { |
| 297 bool IsAssign = DefInst->isSimpleAssign(); | 404 assert(DefInst->getDest() == Cur); |
| 298 bool IsSingleDef = !VMetadata->isMultiDef(Cur); | 405 bool IsAssign = DefInst->isSimpleAssign(); |
| 299 for (SizeT i = 0; i < DefInst->getSrcSize(); ++i) { | 406 bool IsSingleDef = !VMetadata->isMultiDef(Cur); |
| 300 // TODO(stichnot): Iterate through the actual Variables of the | 407 for (SizeT i = 0; i < DefInst->getSrcSize(); ++i) { |
| 301 // instruction, not just the source operands. This could | 408 // TODO(stichnot): Iterate through the actual Variables of the |
| 302 // capture Load instructions, including address mode | 409 // instruction, not just the source operands. This could |
| 303 // optimization, for Prefer (but not for AllowOverlap). | 410 // capture Load instructions, including address mode |
| 304 if (Variable *SrcVar = llvm::dyn_cast<Variable>(DefInst->getSrc(i))) { | 411 // optimization, for Prefer (but not for AllowOverlap). |
| 305 int32_t SrcReg = SrcVar->getRegNumTmp(); | 412 if (Variable *SrcVar = llvm::dyn_cast<Variable>(DefInst->getSrc(i))) { |
| 306 // Only consider source variables that have (so far) been | 413 int32_t SrcReg = SrcVar->getRegNumTmp(); |
| 307 // assigned a register. That register must be one in the | 414 // Only consider source variables that have (so far) been |
| 308 // RegMask set, e.g. don't try to prefer the stack pointer | 415 // assigned a register. That register must be one in the |
| 309 // as a result of the stacksave intrinsic. | 416 // RegMask set, e.g. don't try to prefer the stack pointer |
| 310 if (SrcVar->hasRegTmp() && RegMask[SrcReg]) { | 417 // as a result of the stacksave intrinsic. |
| 311 if (!Free[SrcReg]) { | 418 if (SrcVar->hasRegTmp() && RegMask[SrcReg]) { |
| 312 // Don't bother trying to enable AllowOverlap if the | 419 if (FindOverlap && !Free[SrcReg]) { |
| 313 // register is already free. | 420 // Don't bother trying to enable AllowOverlap if the |
| 314 AllowOverlap = | 421 // register is already free. |
| 315 IsSingleDef && IsAssign && !overlapsDefs(Func, Cur, SrcVar); | 422 AllowOverlap = |
| 316 } | 423 IsSingleDef && IsAssign && !overlapsDefs(Func, Cur, SrcVar); |
| 317 if (AllowOverlap || Free[SrcReg]) { | 424 } |
| 318 Prefer = SrcVar; | 425 if (AllowOverlap || Free[SrcReg]) { |
| 319 PreferReg = SrcReg; | 426 Prefer = SrcVar; |
| 427 PreferReg = SrcReg; | |
| 428 } | |
| 320 } | 429 } |
| 321 } | 430 } |
| 322 } | 431 } |
| 323 } | 432 if (Verbose && Prefer) { |
| 324 } | 433 Str << "Initial Prefer=" << *Prefer << " R=" << PreferReg |
| 325 if (Verbose) { | 434 << " LIVE=" << Prefer->getLiveRange() |
| 326 if (Prefer) { | 435 << " Overlap=" << AllowOverlap << "\n"; |
| 327 Str << "Initial Prefer=" << *Prefer << " R=" << PreferReg | 436 } |
| 328 << " LIVE=" << Prefer->getLiveRange() << " Overlap=" << AllowOverlap | |
| 329 << "\n"; | |
| 330 } | 437 } |
| 331 } | 438 } |
| 332 | 439 |
| 333 // Remove registers from the Free[] list where an Inactive range | 440 // Remove registers from the Free[] list where an Inactive range |
| 334 // overlaps with the current range. | 441 // overlaps with the current range. |
| 335 for (const Variable *Item : Inactive) { | 442 for (const Variable *Item : Inactive) { |
| 336 if (Item->rangeOverlaps(Cur)) { | 443 if (Item->rangeOverlaps(Cur)) { |
| 337 int32_t RegNum = Item->getRegNumTmp(); | 444 int32_t RegNum = Item->getRegNumTmp(); |
| 338 // Don't assert(Free[RegNum]) because in theory (though | 445 // Don't assert(Free[RegNum]) because in theory (though |
| 339 // probably never in practice) there could be two inactive | 446 // probably never in practice) there could be two inactive |
| 340 // variables that were marked with AllowOverlap. | 447 // variables that were marked with AllowOverlap. |
| 341 Free[RegNum] = false; | 448 Free[RegNum] = false; |
| 342 // Disable AllowOverlap if an Inactive variable, which is not | 449 // Disable AllowOverlap if an Inactive variable, which is not |
| 343 // Prefer, shares Prefer's register, and has a definition | 450 // Prefer, shares Prefer's register, and has a definition |
| 344 // within Cur's live range. | 451 // within Cur's live range. |
| 345 if (AllowOverlap && Item != Prefer && RegNum == PreferReg && | 452 if (AllowOverlap && Item != Prefer && RegNum == PreferReg && |
| 346 overlapsDefs(Func, Cur, Item)) { | 453 overlapsDefs(Func, Cur, Item)) { |
| 347 AllowOverlap = false; | 454 AllowOverlap = false; |
| 348 dumpDisableOverlap(Func, Item, "Inactive"); | 455 dumpDisableOverlap(Func, Item, "Inactive"); |
| 349 } | 456 } |
| 350 } | 457 } |
| 351 } | 458 } |
| 352 | 459 |
| 353 // Disable AllowOverlap if an Active variable, which is not | 460 // Disable AllowOverlap if an Active variable, which is not |
| 354 // Prefer, shares Prefer's register, and has a definition within | 461 // Prefer, shares Prefer's register, and has a definition within |
| 355 // Cur's live range. | 462 // Cur's live range. |
| 356 for (const Variable *Item : Active) { | 463 if (AllowOverlap) { |
| 357 int32_t RegNum = Item->getRegNumTmp(); | 464 for (const Variable *Item : Active) { |
| 358 if (Item != Prefer && RegNum == PreferReg && | 465 int32_t RegNum = Item->getRegNumTmp(); |
| 359 overlapsDefs(Func, Cur, Item)) { | 466 if (Item != Prefer && RegNum == PreferReg && |
| 360 AllowOverlap = false; | 467 overlapsDefs(Func, Cur, Item)) { |
| 361 dumpDisableOverlap(Func, Item, "Active"); | 468 AllowOverlap = false; |
| 469 dumpDisableOverlap(Func, Item, "Active"); | |
| 470 } | |
| 362 } | 471 } |
| 363 } | 472 } |
| 364 | 473 |
| 365 std::vector<RegWeight> Weights(RegMask.size()); | 474 std::vector<RegWeight> Weights(RegMask.size()); |
| 366 | 475 |
| 367 // Remove registers from the Free[] list where an Unhandled | 476 // Remove registers from the Free[] list where an Unhandled |
| 368 // precolored range overlaps with the current range, and set those | 477 // precolored range overlaps with the current range, and set those |
| 369 // registers to infinite weight so that they aren't candidates for | 478 // registers to infinite weight so that they aren't candidates for |
| 370 // eviction. Cur->rangeEndsBefore(Item) is an early exit check | 479 // eviction. Cur->rangeEndsBefore(Item) is an early exit check |
| 371 // that turns a guaranteed O(N^2) algorithm into expected linear | 480 // that turns a guaranteed O(N^2) algorithm into expected linear |
| (...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 603 Str << "\n"; | 712 Str << "\n"; |
| 604 } | 713 } |
| 605 Str << "++++++ Inactive:\n"; | 714 Str << "++++++ Inactive:\n"; |
| 606 for (const Variable *Item : Inactive) { | 715 for (const Variable *Item : Inactive) { |
| 607 dumpLiveRange(Item, Func); | 716 dumpLiveRange(Item, Func); |
| 608 Str << "\n"; | 717 Str << "\n"; |
| 609 } | 718 } |
| 610 } | 719 } |
| 611 | 720 |
| 612 } // end of namespace Ice | 721 } // end of namespace Ice |
| OLD | NEW |