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 |
11 // linear-scan register allocation after liveness analysis has been | 11 // linear-scan register allocation after liveness analysis has been |
12 // performed. | 12 // performed. |
13 // | 13 // |
14 //===----------------------------------------------------------------------===// | 14 //===----------------------------------------------------------------------===// |
15 | 15 |
16 #include "IceCfg.h" | 16 #include "IceCfg.h" |
17 #include "IceInst.h" | 17 #include "IceInst.h" |
18 #include "IceOperand.h" | 18 #include "IceOperand.h" |
19 #include "IceRegAlloc.h" | 19 #include "IceRegAlloc.h" |
20 #include "IceTargetLowering.h" | 20 #include "IceTargetLowering.h" |
21 | 21 |
22 namespace Ice { | 22 namespace Ice { |
23 | 23 |
24 namespace { | |
25 | |
26 // Returns true if Var has any definitions within Item's live range. | |
27 bool overlapsDefs(const Cfg *Func, const LiveRangeWrapper &Item, | |
28 const Variable *Var) { | |
29 VariablesMetadata *VMetadata = Func->getVMetadata(); | |
30 const InstDefList &Defs = VMetadata->getDefinitions(Var); | |
31 for (size_t i = 0; i < Defs.size(); ++i) { | |
32 if (Item.range().overlaps(Defs[i]->getNumber())) | |
33 return true; | |
34 } | |
35 return false; | |
36 } | |
37 | |
38 } // end of anonymous namespace | |
39 | |
24 // Implements the linear-scan algorithm. Based on "Linear Scan | 40 // Implements the linear-scan algorithm. Based on "Linear Scan |
25 // Register Allocation in the Context of SSA Form and Register | 41 // Register Allocation in the Context of SSA Form and Register |
26 // Constraints" by Hanspeter Mössenböck and Michael Pfeiffer, | 42 // Constraints" by Hanspeter Mössenböck and Michael Pfeiffer, |
27 // ftp://ftp.ssw.uni-linz.ac.at/pub/Papers/Moe02.PDF . This | 43 // ftp://ftp.ssw.uni-linz.ac.at/pub/Papers/Moe02.PDF . This |
28 // implementation is modified to take affinity into account and allow | 44 // implementation is modified to take affinity into account and allow |
29 // two interfering variables to share the same register in certain | 45 // two interfering variables to share the same register in certain |
30 // cases. | 46 // cases. |
31 // | 47 // |
32 // Requires running Cfg::liveness(Liveness_Intervals) in | 48 // Requires running Cfg::liveness(Liveness_Intervals) in |
33 // preparation. Results are assigned to Variable::RegNum for each | 49 // preparation. Results are assigned to Variable::RegNum for each |
34 // Variable. | 50 // Variable. |
35 void LinearScan::scan(const llvm::SmallBitVector &RegMaskFull) { | 51 void LinearScan::scan(const llvm::SmallBitVector &RegMaskFull) { |
36 assert(RegMaskFull.any()); // Sanity check | 52 assert(RegMaskFull.any()); // Sanity check |
37 Unhandled.clear(); | 53 Unhandled.clear(); |
38 Handled.clear(); | 54 Handled.clear(); |
39 Inactive.clear(); | 55 Inactive.clear(); |
40 Active.clear(); | 56 Active.clear(); |
41 Ostream &Str = Func->getContext()->getStrDump(); | 57 Ostream &Str = Func->getContext()->getStrDump(); |
42 Func->resetCurrentNode(); | 58 Func->resetCurrentNode(); |
59 VariablesMetadata *VMetadata = Func->getVMetadata(); | |
43 | 60 |
44 // Gather the live ranges of all variables and add them to the | 61 // Gather the live ranges of all variables and add them to the |
45 // Unhandled set. TODO: Unhandled is a set<> which is based on a | 62 // Unhandled set. TODO: Unhandled is a set<> which is based on a |
46 // balanced binary tree, so inserting live ranges for N variables is | 63 // balanced binary tree, so inserting live ranges for N variables is |
47 // O(N log N) complexity. N may be proportional to the number of | 64 // O(N log N) complexity. N may be proportional to the number of |
48 // instructions, thanks to temporary generation during lowering. As | 65 // instructions, thanks to temporary generation during lowering. As |
49 // a result, it may be useful to design a better data structure for | 66 // a result, it may be useful to design a better data structure for |
50 // storing Func->getVariables(). | 67 // storing Func->getVariables(). |
51 const VarList &Vars = Func->getVariables(); | 68 const VarList &Vars = Func->getVariables(); |
52 for (VarList::const_iterator I = Vars.begin(), E = Vars.end(); I != E; ++I) { | 69 for (VarList::const_iterator I = Vars.begin(), E = Vars.end(); I != E; ++I) { |
(...skipping 125 matching lines...) Loading... | |
178 } | 195 } |
179 } | 196 } |
180 | 197 |
181 // Calculate available registers into Free[]. | 198 // Calculate available registers into Free[]. |
182 llvm::SmallBitVector Free = RegMask; | 199 llvm::SmallBitVector Free = RegMask; |
183 for (SizeT i = 0; i < RegMask.size(); ++i) { | 200 for (SizeT i = 0; i < RegMask.size(); ++i) { |
184 if (RegUses[i] > 0) | 201 if (RegUses[i] > 0) |
185 Free[i] = false; | 202 Free[i] = false; |
186 } | 203 } |
187 | 204 |
205 // Infer register preference and allowable overlap. Only form a | |
206 // preference when the current Variable has an unambiguous "first" | |
207 // definition. The preference is some source Variable of the | |
208 // defining instruction that either is assigned a register that is | |
209 // currently free, or that is assigned a register that is not free | |
210 // but overlap is allowed. Overlap is allowed when the Variable | |
211 // under consideration is single-definition, and its definition is | |
212 // a simple assignment - i.e., the register gets copied/aliased | |
213 // but is never modified. Furthermore, overlap is only allowed | |
214 // when preferred Variable definition instructions do not appear | |
215 // within the current Variable's live range. | |
216 Variable *Prefer = NULL; | |
217 bool AllowedToOverlap = false; | |
218 if (const Inst *DefInst = VMetadata->getSingleDefinition(Cur.Var)) { | |
jvoung (off chromium)
2014/09/25 16:42:11
Was this meant to be getFirstDefinition() (based o
Jim Stichnoth
2014/09/25 18:13:55
Yeah, fixed.
| |
219 assert(DefInst->getDest() == Cur.Var); | |
220 bool IsAssign = DefInst->isSimpleAssign(); | |
221 bool IsSingleDef = !VMetadata->isMultiDef(Cur.Var); | |
222 for (SizeT i = 0; i < DefInst->getSrcSize(); ++i) { | |
223 if (Variable *SrcVar = llvm::dyn_cast<Variable>(DefInst->getSrc(i))) { | |
224 // The NoConflictingDefs condition is supposed to accurately | |
225 // represent this requirement: "overlap is only allowed when | |
226 // preferred Variable definition instructions do not appear | |
227 // within the current Variable's live range." | |
228 bool NoConflictingDefs = !overlapsDefs(Func, Cur, SrcVar); | |
229 int32_t SrcReg = SrcVar->getRegNumTmp(); | |
230 if (SrcReg != Variable::NoRegister && RegMask[SrcReg]) { | |
jvoung (off chromium)
2014/09/25 16:42:11
Would it be better to check SrcReg != Variable::No
Jim Stichnoth
2014/09/25 18:13:55
Yes. That should be fixed in the latest patchset.
| |
231 AllowedToOverlap = IsSingleDef && NoConflictingDefs && IsAssign; | |
232 if (AllowedToOverlap || Free[SrcReg]) | |
jvoung (off chromium)
2014/09/25 16:42:11
Similar, would it be cheaper to check for Free[Src
Jim Stichnoth
2014/09/25 18:13:55
Hmm, I think you're right. The logs do show a lot
| |
233 Prefer = SrcVar; | |
234 } | |
235 } | |
236 } | |
237 } | |
238 if (Func->getContext()->isVerbose(IceV_LinearScan)) { | |
239 if (Prefer) { | |
240 Str << "Initial Prefer=" << *Prefer << " R=" << Prefer->getRegNumTmp() | |
241 << " LIVE=" << Prefer->getLiveRange() | |
242 << " Overlap=" << AllowedToOverlap << "\n"; | |
243 } | |
244 } | |
245 | |
188 // Remove registers from the Free[] list where an Inactive range | 246 // Remove registers from the Free[] list where an Inactive range |
189 // overlaps with the current range. | 247 // overlaps with the current range. |
190 for (UnorderedRanges::const_iterator I = Inactive.begin(), | 248 for (UnorderedRanges::const_iterator I = Inactive.begin(), |
191 E = Inactive.end(); | 249 E = Inactive.end(); |
192 I != E; ++I) { | 250 I != E; ++I) { |
193 LiveRangeWrapper Item = *I; | 251 LiveRangeWrapper Item = *I; |
194 if (Item.overlaps(Cur)) { | 252 if (Item.overlaps(Cur)) { |
195 int32_t RegNum = Item.Var->getRegNumTmp(); | 253 int32_t RegNum = Item.Var->getRegNumTmp(); |
196 // Don't assert(Free[RegNum]) because in theory (though | 254 // Don't assert(Free[RegNum]) because in theory (though |
197 // probably never in practice) there could be two inactive | 255 // probably never in practice) there could be two inactive |
198 // variables that were allowed marked with | 256 // variables that were allowed marked with |
199 // AllowRegisterOverlap. | 257 // AllowRegisterOverlap. |
200 Free[RegNum] = false; | 258 Free[RegNum] = false; |
259 // If there is a variable on the inactive list, which is not | |
260 // Prefer, and overlaps with Cur, and shares Prefer's | |
261 // register, then disallow overlap. | |
262 if (AllowedToOverlap && Item.Var != Prefer && | |
263 RegNum == Prefer->getRegNumTmp() && Item.overlaps(Cur)) { | |
264 AllowedToOverlap = false; | |
265 if (Func->getContext()->isVerbose(IceV_LinearScan)) { | |
266 Str << "Disabling Overlap due to Inactive " << *Item.Var | |
267 << " LIVE=" << Item.Var->getLiveRange() << "\n"; | |
268 } | |
269 } | |
201 } | 270 } |
202 } | 271 } |
203 | 272 |
273 // Disable AllowOverlap if the preferred register is already used | |
274 // in an Active range (which by definition overlaps) that is not | |
275 // Prefer. TODO(stichnot): Actually only disable AllowOverlap if | |
276 // an Active variable with the preferred register has a definition | |
277 // within the current variable's live range. | |
278 | |
279 // If there is a variable on the active list, which is not Prefer, | |
280 // and shares Prefer's register, and has a definition within Cur's | |
281 // live range, then disallow overlap. | |
282 for (UnorderedRanges::iterator I = Active.begin(), E = Active.end(); | |
283 AllowedToOverlap && I != E; ++I) { | |
284 LiveRangeWrapper Item = *I; | |
285 int32_t RegNum = Item.Var->getRegNumTmp(); | |
286 if (Item.Var != Prefer && RegNum == Prefer->getRegNumTmp() && | |
287 overlapsDefs(Func, Cur, Item.Var)) { | |
288 AllowedToOverlap = false; | |
289 if (Func->getContext()->isVerbose(IceV_LinearScan)) { | |
290 Str << "Disabling Overlap due to Active " << *Item.Var | |
291 << " LIVE=" << Item.Var->getLiveRange() << "\n"; | |
292 } | |
293 } | |
294 } | |
295 | |
204 // Remove registers from the Free[] list where an Unhandled range | 296 // Remove registers from the Free[] list where an Unhandled range |
205 // overlaps with the current range and is precolored. | 297 // overlaps with the current range and is precolored. |
206 // Cur.endsBefore(*I) is an early exit check that turns a | 298 // Cur.endsBefore(*I) is an early exit check that turns a |
207 // guaranteed O(N^2) algorithm into expected linear complexity. | 299 // guaranteed O(N^2) algorithm into expected linear complexity. |
208 llvm::SmallBitVector PrecoloredUnhandled(RegMask.size()); | 300 llvm::SmallBitVector PrecoloredUnhandled(RegMask.size()); |
209 for (OrderedRanges::const_iterator I = Unhandled.begin(), | 301 for (OrderedRanges::const_iterator I = Unhandled.begin(), |
210 E = Unhandled.end(); | 302 E = Unhandled.end(); |
211 I != E && !Cur.endsBefore(*I); ++I) { | 303 I != E && !Cur.endsBefore(*I); ++I) { |
212 LiveRangeWrapper Item = *I; | 304 LiveRangeWrapper Item = *I; |
213 if (Item.Var->hasReg() && Item.overlaps(Cur)) { | 305 if (Item.Var->hasReg() && Item.overlaps(Cur)) { |
214 Free[Item.Var->getRegNum()] = false; // Note: getRegNum not getRegNumTmp | 306 Free[Item.Var->getRegNum()] = false; // Note: getRegNum not getRegNumTmp |
215 PrecoloredUnhandled[Item.Var->getRegNum()] = true; | 307 PrecoloredUnhandled[Item.Var->getRegNum()] = true; |
308 // Disallow overlap if the preferred register is one of these | |
309 // precolored unhandled overlapping ranges. | |
310 if (AllowedToOverlap && Prefer && | |
jvoung (off chromium)
2014/09/25 16:42:11
nit: I think technically, the "&& Prefer" check is
Jim Stichnoth
2014/09/25 18:13:54
Done. I think I originally had that just to be ab
| |
311 Item.Var->getRegNum() == Prefer->getRegNumTmp() && | |
312 Cur.overlaps(Item)) { | |
313 AllowedToOverlap = false; | |
314 if (Func->getContext()->isVerbose(IceV_LinearScan)) { | |
315 Str << "Disabling Overlap due to UnhandledPrecolored " << *Item.Var | |
316 << " LIVE=" << Item.Var->getLiveRange() << "\n"; | |
317 } | |
318 } | |
216 } | 319 } |
217 } | 320 } |
218 | 321 |
219 // Print info about physical register availability. | 322 // Print info about physical register availability. |
220 if (Func->getContext()->isVerbose(IceV_LinearScan)) { | 323 if (Func->getContext()->isVerbose(IceV_LinearScan)) { |
221 for (SizeT i = 0; i < RegMask.size(); ++i) { | 324 for (SizeT i = 0; i < RegMask.size(); ++i) { |
222 if (RegMask[i]) { | 325 if (RegMask[i]) { |
223 Str << Func->getTarget()->getRegName(i, IceType_i32) | 326 Str << Func->getTarget()->getRegName(i, IceType_i32) |
224 << "(U=" << RegUses[i] << ",F=" << Free[i] | 327 << "(U=" << RegUses[i] << ",F=" << Free[i] |
225 << ",P=" << PrecoloredUnhandled[i] << ") "; | 328 << ",P=" << PrecoloredUnhandled[i] << ") "; |
226 } | 329 } |
227 } | 330 } |
228 Str << "\n"; | 331 Str << "\n"; |
229 } | 332 } |
230 | 333 |
231 Variable *Prefer = Cur.Var->getPreferredRegister(); | 334 int32_t PreferReg = Variable::NoRegister; |
232 int32_t PreferReg = Prefer && Prefer->hasRegTmp() ? Prefer->getRegNumTmp() | 335 if (Prefer && Prefer->hasRegTmp()) |
233 : Variable::NoRegister; | 336 PreferReg = Prefer->getRegNumTmp(); |
234 bool AllowedToOverlap = Cur.Var->getRegisterOverlap() && | |
235 PreferReg != Variable::NoRegister && | |
236 RegMask[PreferReg] && | |
237 !PrecoloredUnhandled[PreferReg]; | |
jvoung (off chromium)
2014/09/25 16:42:11
It now seems like PrecoloredUnhandled is no longer
Jim Stichnoth
2014/09/25 18:13:54
True. It's worth keeping for the diagnostics, so
| |
238 if (PreferReg != Variable::NoRegister && | 337 if (PreferReg != Variable::NoRegister && |
239 (AllowedToOverlap || Free[PreferReg])) { | 338 (AllowedToOverlap || Free[PreferReg])) { |
240 // First choice: a preferred register that is either free or is | 339 // First choice: a preferred register that is either free or is |
241 // allowed to overlap with its linked variable. | 340 // allowed to overlap with its linked variable. |
242 Cur.Var->setRegNumTmp(PreferReg); | 341 Cur.Var->setRegNumTmp(PreferReg); |
243 if (Func->getContext()->isVerbose(IceV_LinearScan)) { | 342 if (Func->getContext()->isVerbose(IceV_LinearScan)) { |
244 Str << "Preferring "; | 343 Str << "Preferring "; |
245 Cur.dump(Func); | 344 Cur.dump(Func); |
246 Str << "\n"; | 345 Str << "\n"; |
247 } | 346 } |
(...skipping 221 matching lines...) Loading... | |
469 } | 568 } |
470 Str << "++++++ Inactive:\n"; | 569 Str << "++++++ Inactive:\n"; |
471 for (UnorderedRanges::const_iterator I = Inactive.begin(), E = Inactive.end(); | 570 for (UnorderedRanges::const_iterator I = Inactive.begin(), E = Inactive.end(); |
472 I != E; ++I) { | 571 I != E; ++I) { |
473 I->dump(Func); | 572 I->dump(Func); |
474 Str << "\n"; | 573 Str << "\n"; |
475 } | 574 } |
476 } | 575 } |
477 | 576 |
478 } // end of namespace Ice | 577 } // end of namespace Ice |
OLD | NEW |