| 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 condition, but it would be nice to | 
|  | 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. | 
|  | 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 | 
|---|