| 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 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 51 const InstDefList &Defs = VMetadata->getDefinitions(Var); | 51 const InstDefList &Defs = VMetadata->getDefinitions(Var); |
| 52 for (size_t i = 0; i < Defs.size(); ++i) { | 52 for (size_t i = 0; i < Defs.size(); ++i) { |
| 53 if (i > 0) | 53 if (i > 0) |
| 54 Str << ","; | 54 Str << ","; |
| 55 Str << Defs[i]->getNumber(); | 55 Str << Defs[i]->getNumber(); |
| 56 } | 56 } |
| 57 Str << "\n"; | 57 Str << "\n"; |
| 58 } | 58 } |
| 59 } | 59 } |
| 60 | 60 |
| 61 bool compareRanges(const LiveRangeWrapper &L, const LiveRangeWrapper &R) { |
| 62 InstNumberT Lstart = L.Var->getLiveRange().getStart(); |
| 63 InstNumberT Rstart = R.Var->getLiveRange().getStart(); |
| 64 if (Lstart == Rstart) |
| 65 return L.Var->getIndex() < R.Var->getIndex(); |
| 66 return Lstart < Rstart; |
| 67 } |
| 68 |
| 61 } // end of anonymous namespace | 69 } // end of anonymous namespace |
| 62 | 70 |
| 63 // Implements the linear-scan algorithm. Based on "Linear Scan | 71 // Implements the linear-scan algorithm. Based on "Linear Scan |
| 64 // Register Allocation in the Context of SSA Form and Register | 72 // Register Allocation in the Context of SSA Form and Register |
| 65 // Constraints" by Hanspeter Mössenböck and Michael Pfeiffer, | 73 // Constraints" by Hanspeter Mössenböck and Michael Pfeiffer, |
| 66 // ftp://ftp.ssw.uni-linz.ac.at/pub/Papers/Moe02.PDF . This | 74 // ftp://ftp.ssw.uni-linz.ac.at/pub/Papers/Moe02.PDF . This |
| 67 // implementation is modified to take affinity into account and allow | 75 // implementation is modified to take affinity into account and allow |
| 68 // two interfering variables to share the same register in certain | 76 // two interfering variables to share the same register in certain |
| 69 // cases. | 77 // cases. |
| 70 // | 78 // |
| 71 // Requires running Cfg::liveness(Liveness_Intervals) in | 79 // Requires running Cfg::liveness(Liveness_Intervals) in |
| 72 // preparation. Results are assigned to Variable::RegNum for each | 80 // preparation. Results are assigned to Variable::RegNum for each |
| 73 // Variable. | 81 // Variable. |
| 74 void LinearScan::scan(const llvm::SmallBitVector &RegMaskFull) { | 82 void LinearScan::scan(const llvm::SmallBitVector &RegMaskFull) { |
| 75 TimerMarker T(TimerStack::TT_linearScan, Func); | 83 TimerMarker T(TimerStack::TT_linearScan, Func); |
| 76 assert(RegMaskFull.any()); // Sanity check | 84 assert(RegMaskFull.any()); // Sanity check |
| 77 Unhandled.clear(); | 85 Unhandled.clear(); |
| 78 UnhandledPrecolored.clear(); | 86 UnhandledPrecolored.clear(); |
| 79 Handled.clear(); | 87 Handled.clear(); |
| 80 Inactive.clear(); | 88 Inactive.clear(); |
| 81 Active.clear(); | 89 Active.clear(); |
| 82 Ostream &Str = Func->getContext()->getStrDump(); | 90 Ostream &Str = Func->getContext()->getStrDump(); |
| 83 bool Verbose = Func->getContext()->isVerbose(IceV_LinearScan); | 91 bool Verbose = Func->getContext()->isVerbose(IceV_LinearScan); |
| 84 Func->resetCurrentNode(); | 92 Func->resetCurrentNode(); |
| 85 VariablesMetadata *VMetadata = Func->getVMetadata(); | 93 VariablesMetadata *VMetadata = Func->getVMetadata(); |
| 86 | 94 |
| 87 // Gather the live ranges of all variables and add them to the | 95 // Gather the live ranges of all variables and add them to the |
| 88 // Unhandled set. TODO: Unhandled is a set<> which is based on a | 96 // Unhandled set. |
| 89 // balanced binary tree, so inserting live ranges for N variables is | |
| 90 // O(N log N) complexity. N may be proportional to the number of | |
| 91 // instructions, thanks to temporary generation during lowering. As | |
| 92 // a result, it may be useful to design a better data structure for | |
| 93 // storing Func->getVariables(). | |
| 94 const VarList &Vars = Func->getVariables(); | 97 const VarList &Vars = Func->getVariables(); |
| 95 { | 98 { |
| 96 TimerMarker T(TimerStack::TT_initUnhandled, Func); | 99 TimerMarker T(TimerStack::TT_initUnhandled, Func); |
| 100 Unhandled.reserve(Vars.size()); |
| 97 for (Variable *Var : Vars) { | 101 for (Variable *Var : Vars) { |
| 98 // Explicitly don't consider zero-weight variables, which are | 102 // Explicitly don't consider zero-weight variables, which are |
| 99 // meant to be spill slots. | 103 // meant to be spill slots. |
| 100 if (Var->getWeight() == RegWeight::Zero) | 104 if (Var->getWeight() == RegWeight::Zero) |
| 101 continue; | 105 continue; |
| 102 // Don't bother if the variable has a null live range, which means | 106 // Don't bother if the variable has a null live range, which means |
| 103 // it was never referenced. | 107 // it was never referenced. |
| 104 if (Var->getLiveRange().isEmpty()) | 108 if (Var->getLiveRange().isEmpty()) |
| 105 continue; | 109 continue; |
| 106 Var->untrimLiveRange(); | 110 Var->untrimLiveRange(); |
| 107 LiveRangeWrapper R(Var); | 111 LiveRangeWrapper R(Var); |
| 108 Unhandled.insert(R); | 112 Unhandled.push_back(R); |
| 109 if (Var->hasReg()) { | 113 if (Var->hasReg()) { |
| 110 Var->setRegNumTmp(Var->getRegNum()); | 114 Var->setRegNumTmp(Var->getRegNum()); |
| 111 Var->setLiveRangeInfiniteWeight(); | 115 Var->setLiveRangeInfiniteWeight(); |
| 112 UnhandledPrecolored.insert(R); | 116 UnhandledPrecolored.push_back(R); |
| 113 } | 117 } |
| 114 } | 118 } |
| 119 // Do a reverse sort so that erasing elements (from the end) is fast. |
| 120 std::sort(Unhandled.rbegin(), Unhandled.rend(), compareRanges); |
| 121 std::sort(UnhandledPrecolored.rbegin(), UnhandledPrecolored.rend(), |
| 122 compareRanges); |
| 115 } | 123 } |
| 116 | 124 |
| 117 // RegUses[I] is the number of live ranges (variables) that register | 125 // RegUses[I] is the number of live ranges (variables) that register |
| 118 // I is currently assigned to. It can be greater than 1 as a result | 126 // I is currently assigned to. It can be greater than 1 as a result |
| 119 // of AllowOverlap inference below. | 127 // of AllowOverlap inference below. |
| 120 std::vector<int> RegUses(RegMaskFull.size()); | 128 std::vector<int> RegUses(RegMaskFull.size()); |
| 121 // Unhandled is already set to all ranges in increasing order of | 129 // Unhandled is already set to all ranges in increasing order of |
| 122 // start points. | 130 // start points. |
| 123 assert(Active.empty()); | 131 assert(Active.empty()); |
| 124 assert(Inactive.empty()); | 132 assert(Inactive.empty()); |
| 125 assert(Handled.empty()); | 133 assert(Handled.empty()); |
| 126 UnorderedRanges::iterator Next; | 134 UnorderedRanges::iterator Next; |
| 127 | 135 |
| 128 while (!Unhandled.empty()) { | 136 while (!Unhandled.empty()) { |
| 129 LiveRangeWrapper Cur = *Unhandled.begin(); | 137 LiveRangeWrapper Cur = Unhandled.back(); |
| 130 Unhandled.erase(Unhandled.begin()); | 138 Unhandled.pop_back(); |
| 131 if (Verbose) { | 139 if (Verbose) { |
| 132 Str << "\nConsidering "; | 140 Str << "\nConsidering "; |
| 133 Cur.dump(Func); | 141 Cur.dump(Func); |
| 134 Str << "\n"; | 142 Str << "\n"; |
| 135 } | 143 } |
| 136 const llvm::SmallBitVector RegMask = | 144 const llvm::SmallBitVector RegMask = |
| 137 RegMaskFull & | 145 RegMaskFull & |
| 138 Func->getTarget()->getRegisterSetForType(Cur.Var->getType()); | 146 Func->getTarget()->getRegisterSetForType(Cur.Var->getType()); |
| 139 | 147 |
| 140 // Check for precolored ranges. If Cur is precolored, it | 148 // Check for precolored ranges. If Cur is precolored, it |
| 141 // definitely gets that register. Previously processed live | 149 // definitely gets that register. Previously processed live |
| 142 // ranges would have avoided that register due to it being | 150 // ranges would have avoided that register due to it being |
| 143 // precolored. Future processed live ranges won't evict that | 151 // precolored. Future processed live ranges won't evict that |
| 144 // register because the live range has infinite weight. | 152 // register because the live range has infinite weight. |
| 145 if (Cur.Var->hasReg()) { | 153 if (Cur.Var->hasReg()) { |
| 146 int32_t RegNum = Cur.Var->getRegNum(); | 154 int32_t RegNum = Cur.Var->getRegNum(); |
| 147 // RegNumTmp should have already been set above. | 155 // RegNumTmp should have already been set above. |
| 148 assert(Cur.Var->getRegNumTmp() == RegNum); | 156 assert(Cur.Var->getRegNumTmp() == RegNum); |
| 149 if (Verbose) { | 157 if (Verbose) { |
| 150 Str << "Precoloring "; | 158 Str << "Precoloring "; |
| 151 Cur.dump(Func); | 159 Cur.dump(Func); |
| 152 Str << "\n"; | 160 Str << "\n"; |
| 153 } | 161 } |
| 154 Active.push_back(Cur); | 162 Active.push_back(Cur); |
| 155 assert(RegUses[RegNum] >= 0); | 163 assert(RegUses[RegNum] >= 0); |
| 156 ++RegUses[RegNum]; | 164 ++RegUses[RegNum]; |
| 157 assert(!UnhandledPrecolored.empty()); | 165 assert(!UnhandledPrecolored.empty()); |
| 158 assert(UnhandledPrecolored.begin()->Var == Cur.Var); | 166 assert(UnhandledPrecolored.back().Var == Cur.Var); |
| 159 UnhandledPrecolored.erase(UnhandledPrecolored.begin()); | 167 UnhandledPrecolored.pop_back(); |
| 160 continue; | 168 continue; |
| 161 } | 169 } |
| 162 | 170 |
| 163 // Check for active ranges that have expired or become inactive. | 171 // Check for active ranges that have expired or become inactive. |
| 164 for (auto I = Active.begin(), E = Active.end(); I != E; I = Next) { | 172 for (auto I = Active.begin(), E = Active.end(); I != E; I = Next) { |
| 165 Next = I; | 173 Next = I; |
| 166 ++Next; | 174 ++Next; |
| 167 LiveRangeWrapper Item = *I; | 175 LiveRangeWrapper Item = *I; |
| 168 Item.Var->trimLiveRange(Cur.range().getStart()); | 176 Item.Var->trimLiveRange(Cur.range().getStart()); |
| 169 bool Moved = false; | 177 bool Moved = false; |
| 170 if (Item.endsBefore(Cur)) { | 178 if (Item.endsBefore(Cur)) { |
| 171 // Move Item from Active to Handled list. | 179 // Move Item from Active to Handled list. |
| 172 if (Verbose) { | 180 if (Verbose) { |
| 173 Str << "Expiring "; | 181 Str << "Expiring "; |
| 174 Item.dump(Func); | 182 Item.dump(Func); |
| 175 Str << "\n"; | 183 Str << "\n"; |
| 176 } | 184 } |
| 177 Active.erase(I); | 185 Handled.splice(Handled.end(), Active, I); |
| 178 Handled.push_back(Item); | |
| 179 Moved = true; | 186 Moved = true; |
| 180 } else if (!Item.overlapsStart(Cur)) { | 187 } else if (!Item.overlapsStart(Cur)) { |
| 181 // Move Item from Active to Inactive list. | 188 // Move Item from Active to Inactive list. |
| 182 if (Verbose) { | 189 if (Verbose) { |
| 183 Str << "Inactivating "; | 190 Str << "Inactivating "; |
| 184 Item.dump(Func); | 191 Item.dump(Func); |
| 185 Str << "\n"; | 192 Str << "\n"; |
| 186 } | 193 } |
| 187 Active.erase(I); | 194 Inactive.splice(Inactive.end(), Active, I); |
| 188 Inactive.push_back(Item); | |
| 189 Moved = true; | 195 Moved = true; |
| 190 } | 196 } |
| 191 if (Moved) { | 197 if (Moved) { |
| 192 // Decrement Item from RegUses[]. | 198 // Decrement Item from RegUses[]. |
| 193 assert(Item.Var->hasRegTmp()); | 199 assert(Item.Var->hasRegTmp()); |
| 194 int32_t RegNum = Item.Var->getRegNumTmp(); | 200 int32_t RegNum = Item.Var->getRegNumTmp(); |
| 195 --RegUses[RegNum]; | 201 --RegUses[RegNum]; |
| 196 assert(RegUses[RegNum] >= 0); | 202 assert(RegUses[RegNum] >= 0); |
| 197 } | 203 } |
| 198 } | 204 } |
| (...skipping 13 matching lines...) Expand all Loading... |
| 212 // beginning of the function. | 218 // beginning of the function. |
| 213 if (!Item.range().isNonpoints()) | 219 if (!Item.range().isNonpoints()) |
| 214 continue; | 220 continue; |
| 215 if (Item.endsBefore(Cur)) { | 221 if (Item.endsBefore(Cur)) { |
| 216 // Move Item from Inactive to Handled list. | 222 // Move Item from Inactive to Handled list. |
| 217 if (Verbose) { | 223 if (Verbose) { |
| 218 Str << "Expiring "; | 224 Str << "Expiring "; |
| 219 Item.dump(Func); | 225 Item.dump(Func); |
| 220 Str << "\n"; | 226 Str << "\n"; |
| 221 } | 227 } |
| 222 Inactive.erase(I); | 228 Handled.splice(Handled.end(), Inactive, I); |
| 223 Handled.push_back(Item); | |
| 224 } else if (Item.overlapsStart(Cur)) { | 229 } else if (Item.overlapsStart(Cur)) { |
| 225 // Move Item from Inactive to Active list. | 230 // Move Item from Inactive to Active list. |
| 226 if (Verbose) { | 231 if (Verbose) { |
| 227 Str << "Reactivating "; | 232 Str << "Reactivating "; |
| 228 Item.dump(Func); | 233 Item.dump(Func); |
| 229 Str << "\n"; | 234 Str << "\n"; |
| 230 } | 235 } |
| 231 Inactive.erase(I); | 236 Active.splice(Active.end(), Inactive, I); |
| 232 Active.push_back(Item); | |
| 233 // Increment Item in RegUses[]. | 237 // Increment Item in RegUses[]. |
| 234 assert(Item.Var->hasRegTmp()); | 238 assert(Item.Var->hasRegTmp()); |
| 235 int32_t RegNum = Item.Var->getRegNumTmp(); | 239 int32_t RegNum = Item.Var->getRegNumTmp(); |
| 236 assert(RegUses[RegNum] >= 0); | 240 assert(RegUses[RegNum] >= 0); |
| 237 ++RegUses[RegNum]; | 241 ++RegUses[RegNum]; |
| 238 } | 242 } |
| 239 } | 243 } |
| 240 | 244 |
| 241 // Calculate available registers into Free[]. | 245 // Calculate available registers into Free[]. |
| 242 llvm::SmallBitVector Free = RegMask; | 246 llvm::SmallBitVector Free = RegMask; |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 332 std::vector<RegWeight> Weights(RegMask.size()); | 336 std::vector<RegWeight> Weights(RegMask.size()); |
| 333 | 337 |
| 334 // Remove registers from the Free[] list where an Unhandled | 338 // Remove registers from the Free[] list where an Unhandled |
| 335 // precolored range overlaps with the current range, and set those | 339 // precolored range overlaps with the current range, and set those |
| 336 // registers to infinite weight so that they aren't candidates for | 340 // registers to infinite weight so that they aren't candidates for |
| 337 // eviction. Cur.endsBefore(Item) is an early exit check that | 341 // eviction. Cur.endsBefore(Item) is an early exit check that |
| 338 // turns a guaranteed O(N^2) algorithm into expected linear | 342 // turns a guaranteed O(N^2) algorithm into expected linear |
| 339 // complexity. | 343 // complexity. |
| 340 llvm::SmallBitVector PrecoloredUnhandledMask(RegMask.size()); | 344 llvm::SmallBitVector PrecoloredUnhandledMask(RegMask.size()); |
| 341 // Note: PrecoloredUnhandledMask is only used for dumping. | 345 // Note: PrecoloredUnhandledMask is only used for dumping. |
| 342 for (const LiveRangeWrapper &Item : UnhandledPrecolored) { | 346 for (auto I = UnhandledPrecolored.rbegin(), E = UnhandledPrecolored.rend(); |
| 347 I != E; ++I) { |
| 348 LiveRangeWrapper &Item = *I; |
| 343 assert(Item.Var->hasReg()); | 349 assert(Item.Var->hasReg()); |
| 344 if (Cur.endsBefore(Item)) | 350 if (Cur.endsBefore(Item)) |
| 345 break; | 351 break; |
| 346 if (Item.overlaps(Cur)) { | 352 if (Item.overlaps(Cur)) { |
| 347 int32_t ItemReg = Item.Var->getRegNum(); // Note: not getRegNumTmp() | 353 int32_t ItemReg = Item.Var->getRegNum(); // Note: not getRegNumTmp() |
| 348 Weights[ItemReg].setWeight(RegWeight::Inf); | 354 Weights[ItemReg].setWeight(RegWeight::Inf); |
| 349 Free[ItemReg] = false; | 355 Free[ItemReg] = false; |
| 350 PrecoloredUnhandledMask[ItemReg] = true; | 356 PrecoloredUnhandledMask[ItemReg] = true; |
| 351 // Disable AllowOverlap if the preferred register is one of | 357 // Disable AllowOverlap if the preferred register is one of |
| 352 // these precolored unhandled overlapping ranges. | 358 // these precolored unhandled overlapping ranges. |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 442 LiveRangeWrapper Item = *I; | 448 LiveRangeWrapper Item = *I; |
| 443 if (Item.Var->getRegNumTmp() == MinWeightIndex) { | 449 if (Item.Var->getRegNumTmp() == MinWeightIndex) { |
| 444 if (Verbose) { | 450 if (Verbose) { |
| 445 Str << "Evicting "; | 451 Str << "Evicting "; |
| 446 Item.dump(Func); | 452 Item.dump(Func); |
| 447 Str << "\n"; | 453 Str << "\n"; |
| 448 } | 454 } |
| 449 --RegUses[MinWeightIndex]; | 455 --RegUses[MinWeightIndex]; |
| 450 assert(RegUses[MinWeightIndex] >= 0); | 456 assert(RegUses[MinWeightIndex] >= 0); |
| 451 Item.Var->setRegNumTmp(Variable::NoRegister); | 457 Item.Var->setRegNumTmp(Variable::NoRegister); |
| 452 Active.erase(I); | 458 Handled.splice(Handled.end(), Active, I); |
| 453 Handled.push_back(Item); | |
| 454 } | 459 } |
| 455 } | 460 } |
| 456 // Do the same for Inactive. | 461 // Do the same for Inactive. |
| 457 for (auto I = Inactive.begin(), E = Inactive.end(); I != E; I = Next) { | 462 for (auto I = Inactive.begin(), E = Inactive.end(); I != E; I = Next) { |
| 458 Next = I; | 463 Next = I; |
| 459 ++Next; | 464 ++Next; |
| 460 LiveRangeWrapper Item = *I; | 465 LiveRangeWrapper Item = *I; |
| 461 // Note: The Item.overlaps(Cur) clause is not part of the | 466 // Note: The Item.overlaps(Cur) clause is not part of the |
| 462 // description of AssignMemLoc() in the original paper. But | 467 // description of AssignMemLoc() in the original paper. But |
| 463 // there doesn't seem to be any need to evict an inactive | 468 // there doesn't seem to be any need to evict an inactive |
| 464 // live range that doesn't overlap with the live range | 469 // live range that doesn't overlap with the live range |
| 465 // currently being considered. It's especially bad if we | 470 // currently being considered. It's especially bad if we |
| 466 // would end up evicting an infinite-weight but | 471 // would end up evicting an infinite-weight but |
| 467 // currently-inactive live range. The most common situation | 472 // currently-inactive live range. The most common situation |
| 468 // for this would be a scratch register kill set for call | 473 // for this would be a scratch register kill set for call |
| 469 // instructions. | 474 // instructions. |
| 470 if (Item.Var->getRegNumTmp() == MinWeightIndex && | 475 if (Item.Var->getRegNumTmp() == MinWeightIndex && |
| 471 Item.overlaps(Cur)) { | 476 Item.overlaps(Cur)) { |
| 472 if (Verbose) { | 477 if (Verbose) { |
| 473 Str << "Evicting "; | 478 Str << "Evicting "; |
| 474 Item.dump(Func); | 479 Item.dump(Func); |
| 475 Str << "\n"; | 480 Str << "\n"; |
| 476 } | 481 } |
| 477 Item.Var->setRegNumTmp(Variable::NoRegister); | 482 Item.Var->setRegNumTmp(Variable::NoRegister); |
| 478 Inactive.erase(I); | 483 Handled.splice(Handled.end(), Inactive, I); |
| 479 Handled.push_back(Item); | |
| 480 } | 484 } |
| 481 } | 485 } |
| 482 // Assign the register to Cur. | 486 // Assign the register to Cur. |
| 483 Cur.Var->setRegNumTmp(MinWeightIndex); | 487 Cur.Var->setRegNumTmp(MinWeightIndex); |
| 484 assert(RegUses[MinWeightIndex] >= 0); | 488 assert(RegUses[MinWeightIndex] >= 0); |
| 485 ++RegUses[MinWeightIndex]; | 489 ++RegUses[MinWeightIndex]; |
| 486 Active.push_back(Cur); | 490 Active.push_back(Cur); |
| 487 if (Verbose) { | 491 if (Verbose) { |
| 488 Str << "Allocating "; | 492 Str << "Allocating "; |
| 489 Cur.dump(Func); | 493 Cur.dump(Func); |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 550 if (!Func->getContext()->isVerbose(IceV_LinearScan)) | 554 if (!Func->getContext()->isVerbose(IceV_LinearScan)) |
| 551 return; | 555 return; |
| 552 Func->resetCurrentNode(); | 556 Func->resetCurrentNode(); |
| 553 Str << "**** Current regalloc state:\n"; | 557 Str << "**** Current regalloc state:\n"; |
| 554 Str << "++++++ Handled:\n"; | 558 Str << "++++++ Handled:\n"; |
| 555 for (const LiveRangeWrapper &Item : Handled) { | 559 for (const LiveRangeWrapper &Item : Handled) { |
| 556 Item.dump(Func); | 560 Item.dump(Func); |
| 557 Str << "\n"; | 561 Str << "\n"; |
| 558 } | 562 } |
| 559 Str << "++++++ Unhandled:\n"; | 563 Str << "++++++ Unhandled:\n"; |
| 560 for (const LiveRangeWrapper &Item : Unhandled) { | 564 for (auto I = Unhandled.rbegin(), E = Unhandled.rend(); I != E; ++I) { |
| 561 Item.dump(Func); | 565 I->dump(Func); |
| 562 Str << "\n"; | 566 Str << "\n"; |
| 563 } | 567 } |
| 564 Str << "++++++ Active:\n"; | 568 Str << "++++++ Active:\n"; |
| 565 for (const LiveRangeWrapper &Item : Active) { | 569 for (const LiveRangeWrapper &Item : Active) { |
| 566 Item.dump(Func); | 570 Item.dump(Func); |
| 567 Str << "\n"; | 571 Str << "\n"; |
| 568 } | 572 } |
| 569 Str << "++++++ Inactive:\n"; | 573 Str << "++++++ Inactive:\n"; |
| 570 for (const LiveRangeWrapper &Item : Inactive) { | 574 for (const LiveRangeWrapper &Item : Inactive) { |
| 571 Item.dump(Func); | 575 Item.dump(Func); |
| 572 Str << "\n"; | 576 Str << "\n"; |
| 573 } | 577 } |
| 574 } | 578 } |
| 575 | 579 |
| 576 } // end of namespace Ice | 580 } // end of namespace Ice |
| OLD | NEW |