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