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...) 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...) 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...) 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 |