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 const InstDefList &Defs = Func->getVMetadata()->getDefinitions(Var); |
| 30 for (size_t i = 0; i < Defs.size(); ++i) { |
| 31 if (Item.range().overlaps(Defs[i]->getNumber())) |
| 32 return true; |
| 33 } |
| 34 return false; |
| 35 } |
| 36 |
| 37 void dumpDisableOverlap(const Cfg *Func, const Variable *Var, |
| 38 const char *Reason) { |
| 39 if (Func->getContext()->isVerbose(IceV_LinearScan)) { |
| 40 Ostream &Str = Func->getContext()->getStrDump(); |
| 41 Str << "Disabling Overlap due to " << Reason << " " << *Var |
| 42 << " LIVE=" << Var->getLiveRange() << " Defs="; |
| 43 const InstDefList &Defs = Func->getVMetadata()->getDefinitions(Var); |
| 44 for (size_t i = 0; i < Defs.size(); ++i) { |
| 45 if (i > 0) |
| 46 Str << ","; |
| 47 Str << Defs[i]->getNumber(); |
| 48 } |
| 49 Str << "\n"; |
| 50 } |
| 51 } |
| 52 |
| 53 } // end of anonymous namespace |
| 54 |
24 // Implements the linear-scan algorithm. Based on "Linear Scan | 55 // Implements the linear-scan algorithm. Based on "Linear Scan |
25 // Register Allocation in the Context of SSA Form and Register | 56 // Register Allocation in the Context of SSA Form and Register |
26 // Constraints" by Hanspeter Mössenböck and Michael Pfeiffer, | 57 // Constraints" by Hanspeter Mössenböck and Michael Pfeiffer, |
27 // ftp://ftp.ssw.uni-linz.ac.at/pub/Papers/Moe02.PDF . This | 58 // ftp://ftp.ssw.uni-linz.ac.at/pub/Papers/Moe02.PDF . This |
28 // implementation is modified to take affinity into account and allow | 59 // implementation is modified to take affinity into account and allow |
29 // two interfering variables to share the same register in certain | 60 // two interfering variables to share the same register in certain |
30 // cases. | 61 // cases. |
31 // | 62 // |
32 // Requires running Cfg::liveness(Liveness_Intervals) in | 63 // Requires running Cfg::liveness(Liveness_Intervals) in |
33 // preparation. Results are assigned to Variable::RegNum for each | 64 // preparation. Results are assigned to Variable::RegNum for each |
34 // Variable. | 65 // Variable. |
35 void LinearScan::scan(const llvm::SmallBitVector &RegMaskFull) { | 66 void LinearScan::scan(const llvm::SmallBitVector &RegMaskFull) { |
36 assert(RegMaskFull.any()); // Sanity check | 67 assert(RegMaskFull.any()); // Sanity check |
37 Unhandled.clear(); | 68 Unhandled.clear(); |
38 Handled.clear(); | 69 Handled.clear(); |
39 Inactive.clear(); | 70 Inactive.clear(); |
40 Active.clear(); | 71 Active.clear(); |
41 Ostream &Str = Func->getContext()->getStrDump(); | 72 Ostream &Str = Func->getContext()->getStrDump(); |
42 Func->resetCurrentNode(); | 73 Func->resetCurrentNode(); |
| 74 VariablesMetadata *VMetadata = Func->getVMetadata(); |
43 | 75 |
44 // Gather the live ranges of all variables and add them to the | 76 // 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 | 77 // Unhandled set. TODO: Unhandled is a set<> which is based on a |
46 // balanced binary tree, so inserting live ranges for N variables is | 78 // 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 | 79 // O(N log N) complexity. N may be proportional to the number of |
48 // instructions, thanks to temporary generation during lowering. As | 80 // instructions, thanks to temporary generation during lowering. As |
49 // a result, it may be useful to design a better data structure for | 81 // a result, it may be useful to design a better data structure for |
50 // storing Func->getVariables(). | 82 // storing Func->getVariables(). |
51 const VarList &Vars = Func->getVariables(); | 83 const VarList &Vars = Func->getVariables(); |
52 for (VarList::const_iterator I = Vars.begin(), E = Vars.end(); I != E; ++I) { | 84 for (VarList::const_iterator I = Vars.begin(), E = Vars.end(); I != E; ++I) { |
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
178 } | 210 } |
179 } | 211 } |
180 | 212 |
181 // Calculate available registers into Free[]. | 213 // Calculate available registers into Free[]. |
182 llvm::SmallBitVector Free = RegMask; | 214 llvm::SmallBitVector Free = RegMask; |
183 for (SizeT i = 0; i < RegMask.size(); ++i) { | 215 for (SizeT i = 0; i < RegMask.size(); ++i) { |
184 if (RegUses[i] > 0) | 216 if (RegUses[i] > 0) |
185 Free[i] = false; | 217 Free[i] = false; |
186 } | 218 } |
187 | 219 |
| 220 // Infer register preference and allowable overlap. Only form a |
| 221 // preference when the current Variable has an unambiguous "first" |
| 222 // definition. The preference is some source Variable of the |
| 223 // defining instruction that either is assigned a register that is |
| 224 // currently free, or that is assigned a register that is not free |
| 225 // but overlap is allowed. Overlap is allowed when the Variable |
| 226 // under consideration is single-definition, and its definition is |
| 227 // a simple assignment - i.e., the register gets copied/aliased |
| 228 // but is never modified. Furthermore, overlap is only allowed |
| 229 // when preferred Variable definition instructions do not appear |
| 230 // within the current Variable's live range. |
| 231 Variable *Prefer = NULL; |
| 232 int32_t PreferReg = Variable::NoRegister; |
| 233 bool AllowOverlap = false; |
| 234 if (const Inst *DefInst = VMetadata->getFirstDefinition(Cur.Var)) { |
| 235 assert(DefInst->getDest() == Cur.Var); |
| 236 bool IsAssign = DefInst->isSimpleAssign(); |
| 237 bool IsSingleDef = !VMetadata->isMultiDef(Cur.Var); |
| 238 for (SizeT i = 0; i < DefInst->getSrcSize(); ++i) { |
| 239 // TODO(stichnot): Iterate through the actual Variables of the |
| 240 // instruction, not just the source operands. This could |
| 241 // capture Load instructions, including address mode |
| 242 // optimization, for Prefer (but not for AllowOverlap). |
| 243 if (Variable *SrcVar = llvm::dyn_cast<Variable>(DefInst->getSrc(i))) { |
| 244 int32_t SrcReg = SrcVar->getRegNumTmp(); |
| 245 // Only consider source variables that have (so far) been |
| 246 // assigned a register. That register must be one in the |
| 247 // RegMask set, e.g. don't try to prefer the stack pointer |
| 248 // as a result of the stacksave intrinsic. |
| 249 if (SrcVar->hasRegTmp() && RegMask[SrcReg]) { |
| 250 if (!Free[SrcReg]) { |
| 251 // Don't bother trying to enable AllowOverlap if the |
| 252 // register is already free. |
| 253 AllowOverlap = |
| 254 IsSingleDef && IsAssign && !overlapsDefs(Func, Cur, SrcVar); |
| 255 } |
| 256 if (AllowOverlap || Free[SrcReg]) { |
| 257 Prefer = SrcVar; |
| 258 PreferReg = SrcReg; |
| 259 } |
| 260 } |
| 261 } |
| 262 } |
| 263 } |
| 264 if (Func->getContext()->isVerbose(IceV_LinearScan)) { |
| 265 if (Prefer) { |
| 266 Str << "Initial Prefer=" << *Prefer << " R=" << PreferReg |
| 267 << " LIVE=" << Prefer->getLiveRange() << " Overlap=" << AllowOverlap |
| 268 << "\n"; |
| 269 } |
| 270 } |
| 271 |
188 // Remove registers from the Free[] list where an Inactive range | 272 // Remove registers from the Free[] list where an Inactive range |
189 // overlaps with the current range. | 273 // overlaps with the current range. |
190 for (UnorderedRanges::const_iterator I = Inactive.begin(), | 274 for (UnorderedRanges::const_iterator I = Inactive.begin(), |
191 E = Inactive.end(); | 275 E = Inactive.end(); |
192 I != E; ++I) { | 276 I != E; ++I) { |
193 LiveRangeWrapper Item = *I; | 277 LiveRangeWrapper Item = *I; |
194 if (Item.overlaps(Cur)) { | 278 if (Item.overlaps(Cur)) { |
195 int32_t RegNum = Item.Var->getRegNumTmp(); | 279 int32_t RegNum = Item.Var->getRegNumTmp(); |
196 // Don't assert(Free[RegNum]) because in theory (though | 280 // Don't assert(Free[RegNum]) because in theory (though |
197 // probably never in practice) there could be two inactive | 281 // probably never in practice) there could be two inactive |
198 // variables that were allowed marked with | 282 // variables that were allowed marked with |
199 // AllowRegisterOverlap. | 283 // AllowRegisterOverlap. |
200 Free[RegNum] = false; | 284 Free[RegNum] = false; |
| 285 // Disable AllowOverlap if an Inactive variable, which is not |
| 286 // Prefer, shares Prefer's register, and has a definition |
| 287 // within Cur's live range. |
| 288 if (AllowOverlap && Item.Var != Prefer && RegNum == PreferReg && |
| 289 overlapsDefs(Func, Cur, Item.Var)) { |
| 290 AllowOverlap = false; |
| 291 dumpDisableOverlap(Func, Item.Var, "Inactive"); |
| 292 } |
201 } | 293 } |
202 } | 294 } |
203 | 295 |
| 296 // Disable AllowOverlap if an Active variable, which is not |
| 297 // Prefer, shares Prefer's register, and has a definition within |
| 298 // Cur's live range. |
| 299 for (UnorderedRanges::iterator I = Active.begin(), E = Active.end(); |
| 300 AllowOverlap && I != E; ++I) { |
| 301 LiveRangeWrapper Item = *I; |
| 302 int32_t RegNum = Item.Var->getRegNumTmp(); |
| 303 if (Item.Var != Prefer && RegNum == PreferReg && |
| 304 overlapsDefs(Func, Cur, Item.Var)) { |
| 305 AllowOverlap = false; |
| 306 dumpDisableOverlap(Func, Item.Var, "Active"); |
| 307 } |
| 308 } |
| 309 |
204 // Remove registers from the Free[] list where an Unhandled range | 310 // Remove registers from the Free[] list where an Unhandled range |
205 // overlaps with the current range and is precolored. | 311 // overlaps with the current range and is precolored. |
206 // Cur.endsBefore(*I) is an early exit check that turns a | 312 // Cur.endsBefore(*I) is an early exit check that turns a |
207 // guaranteed O(N^2) algorithm into expected linear complexity. | 313 // guaranteed O(N^2) algorithm into expected linear complexity. |
208 llvm::SmallBitVector PrecoloredUnhandled(RegMask.size()); | 314 llvm::SmallBitVector PrecoloredUnhandled(RegMask.size()); |
| 315 // Note: PrecoloredUnhandled is only used for dumping. |
209 for (OrderedRanges::const_iterator I = Unhandled.begin(), | 316 for (OrderedRanges::const_iterator I = Unhandled.begin(), |
210 E = Unhandled.end(); | 317 E = Unhandled.end(); |
211 I != E && !Cur.endsBefore(*I); ++I) { | 318 I != E && !Cur.endsBefore(*I); ++I) { |
212 LiveRangeWrapper Item = *I; | 319 LiveRangeWrapper Item = *I; |
213 if (Item.Var->hasReg() && Item.overlaps(Cur)) { | 320 if (Item.Var->hasReg() && Item.overlaps(Cur)) { |
214 Free[Item.Var->getRegNum()] = false; // Note: getRegNum not getRegNumTmp | 321 int32_t ItemReg = Item.Var->getRegNum(); // Note: not getRegNumTmp() |
215 PrecoloredUnhandled[Item.Var->getRegNum()] = true; | 322 Free[ItemReg] = false; |
| 323 PrecoloredUnhandled[ItemReg] = true; |
| 324 // Disable AllowOverlap if the preferred register is one of |
| 325 // these precolored unhandled overlapping ranges. |
| 326 if (AllowOverlap && ItemReg == PreferReg) { |
| 327 AllowOverlap = false; |
| 328 dumpDisableOverlap(Func, Item.Var, "PrecoloredUnhandled"); |
| 329 } |
216 } | 330 } |
217 } | 331 } |
218 | 332 |
219 // Print info about physical register availability. | 333 // Print info about physical register availability. |
220 if (Func->getContext()->isVerbose(IceV_LinearScan)) { | 334 if (Func->getContext()->isVerbose(IceV_LinearScan)) { |
221 for (SizeT i = 0; i < RegMask.size(); ++i) { | 335 for (SizeT i = 0; i < RegMask.size(); ++i) { |
222 if (RegMask[i]) { | 336 if (RegMask[i]) { |
223 Str << Func->getTarget()->getRegName(i, IceType_i32) | 337 Str << Func->getTarget()->getRegName(i, IceType_i32) |
224 << "(U=" << RegUses[i] << ",F=" << Free[i] | 338 << "(U=" << RegUses[i] << ",F=" << Free[i] |
225 << ",P=" << PrecoloredUnhandled[i] << ") "; | 339 << ",P=" << PrecoloredUnhandled[i] << ") "; |
226 } | 340 } |
227 } | 341 } |
228 Str << "\n"; | 342 Str << "\n"; |
229 } | 343 } |
230 | 344 |
231 Variable *Prefer = Cur.Var->getPreferredRegister(); | 345 if (Prefer && (AllowOverlap || Free[PreferReg])) { |
232 int32_t PreferReg = Prefer && Prefer->hasRegTmp() ? Prefer->getRegNumTmp() | |
233 : Variable::NoRegister; | |
234 bool AllowedToOverlap = Cur.Var->getRegisterOverlap() && | |
235 PreferReg != Variable::NoRegister && | |
236 RegMask[PreferReg] && | |
237 !PrecoloredUnhandled[PreferReg]; | |
238 if (PreferReg != Variable::NoRegister && | |
239 (AllowedToOverlap || Free[PreferReg])) { | |
240 // First choice: a preferred register that is either free or is | 346 // First choice: a preferred register that is either free or is |
241 // allowed to overlap with its linked variable. | 347 // allowed to overlap with its linked variable. |
242 Cur.Var->setRegNumTmp(PreferReg); | 348 Cur.Var->setRegNumTmp(PreferReg); |
243 if (Func->getContext()->isVerbose(IceV_LinearScan)) { | 349 if (Func->getContext()->isVerbose(IceV_LinearScan)) { |
244 Str << "Preferring "; | 350 Str << "Preferring "; |
245 Cur.dump(Func); | 351 Cur.dump(Func); |
246 Str << "\n"; | 352 Str << "\n"; |
247 } | 353 } |
248 assert(RegUses[PreferReg] >= 0); | 354 assert(RegUses[PreferReg] >= 0); |
249 ++RegUses[PreferReg]; | 355 ++RegUses[PreferReg]; |
(...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
469 } | 575 } |
470 Str << "++++++ Inactive:\n"; | 576 Str << "++++++ Inactive:\n"; |
471 for (UnorderedRanges::const_iterator I = Inactive.begin(), E = Inactive.end(); | 577 for (UnorderedRanges::const_iterator I = Inactive.begin(), E = Inactive.end(); |
472 I != E; ++I) { | 578 I != E; ++I) { |
473 I->dump(Func); | 579 I->dump(Func); |
474 Str << "\n"; | 580 Str << "\n"; |
475 } | 581 } |
476 } | 582 } |
477 | 583 |
478 } // end of namespace Ice | 584 } // end of namespace Ice |
OLD | NEW |