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. TODO: Unhandled is a set<> which is based on a |
jvoung (off chromium)
2014/10/13 21:41:50
Could remove comment about Unhandled being a set<>
Jim Stichnoth
2014/10/13 23:40:31
Removed the TODO altogether, as I think this is no
| |
89 // balanced binary tree, so inserting live ranges for N variables is | 97 // 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 | 98 // O(N log N) complexity. N may be proportional to the number of |
91 // instructions, thanks to temporary generation during lowering. As | 99 // instructions, thanks to temporary generation during lowering. As |
92 // a result, it may be useful to design a better data structure for | 100 // a result, it may be useful to design a better data structure for |
93 // storing Func->getVariables(). | 101 // storing Func->getVariables(). |
94 const VarList &Vars = Func->getVariables(); | 102 const VarList &Vars = Func->getVariables(); |
95 { | 103 { |
96 TimerMarker T(TimerStack::TT_initUnhandled, Func); | 104 TimerMarker T(TimerStack::TT_initUnhandled, Func); |
105 Unhandled.reserve(Vars.size()); | |
97 for (Variable *Var : Vars) { | 106 for (Variable *Var : Vars) { |
98 // Explicitly don't consider zero-weight variables, which are | 107 // Explicitly don't consider zero-weight variables, which are |
99 // meant to be spill slots. | 108 // meant to be spill slots. |
100 if (Var->getWeight() == RegWeight::Zero) | 109 if (Var->getWeight() == RegWeight::Zero) |
101 continue; | 110 continue; |
102 // Don't bother if the variable has a null live range, which means | 111 // Don't bother if the variable has a null live range, which means |
103 // it was never referenced. | 112 // it was never referenced. |
104 if (Var->getLiveRange().isEmpty()) | 113 if (Var->getLiveRange().isEmpty()) |
105 continue; | 114 continue; |
106 Var->untrimLiveRange(); | 115 Var->untrimLiveRange(); |
107 LiveRangeWrapper R(Var); | 116 LiveRangeWrapper R(Var); |
108 Unhandled.insert(R); | 117 Unhandled.push_back(R); |
109 if (Var->hasReg()) { | 118 if (Var->hasReg()) { |
110 Var->setRegNumTmp(Var->getRegNum()); | 119 Var->setRegNumTmp(Var->getRegNum()); |
111 Var->setLiveRangeInfiniteWeight(); | 120 Var->setLiveRangeInfiniteWeight(); |
112 UnhandledPrecolored.insert(R); | 121 UnhandledPrecolored.push_back(R); |
113 } | 122 } |
114 } | 123 } |
124 // Do a reverse sort so that erasing elements (from the end) is | |
jvoung (off chromium)
2014/10/13 21:41:50
Can the comment fit on one line?
Jim Stichnoth
2014/10/13 23:40:31
Done. (overriding emacs's default preferences :)
| |
125 // fast. | |
126 std::sort(Unhandled.rbegin(), Unhandled.rend(), compareRanges); | |
127 std::sort(UnhandledPrecolored.rbegin(), UnhandledPrecolored.rend(), | |
128 compareRanges); | |
115 } | 129 } |
116 | 130 |
117 // RegUses[I] is the number of live ranges (variables) that register | 131 // 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 | 132 // I is currently assigned to. It can be greater than 1 as a result |
119 // of AllowOverlap inference below. | 133 // of AllowOverlap inference below. |
120 std::vector<int> RegUses(RegMaskFull.size()); | 134 std::vector<int> RegUses(RegMaskFull.size()); |
121 // Unhandled is already set to all ranges in increasing order of | 135 // Unhandled is already set to all ranges in increasing order of |
122 // start points. | 136 // start points. |
123 assert(Active.empty()); | 137 assert(Active.empty()); |
124 assert(Inactive.empty()); | 138 assert(Inactive.empty()); |
125 assert(Handled.empty()); | 139 assert(Handled.empty()); |
126 UnorderedRanges::iterator Next; | 140 UnorderedRanges::iterator Next; |
127 | 141 |
128 while (!Unhandled.empty()) { | 142 while (!Unhandled.empty()) { |
129 LiveRangeWrapper Cur = *Unhandled.begin(); | 143 LiveRangeWrapper Cur = Unhandled.back(); |
130 Unhandled.erase(Unhandled.begin()); | 144 Unhandled.pop_back(); |
131 if (Verbose) { | 145 if (Verbose) { |
132 Str << "\nConsidering "; | 146 Str << "\nConsidering "; |
133 Cur.dump(Func); | 147 Cur.dump(Func); |
134 Str << "\n"; | 148 Str << "\n"; |
135 } | 149 } |
136 const llvm::SmallBitVector RegMask = | 150 const llvm::SmallBitVector RegMask = |
137 RegMaskFull & | 151 RegMaskFull & |
138 Func->getTarget()->getRegisterSetForType(Cur.Var->getType()); | 152 Func->getTarget()->getRegisterSetForType(Cur.Var->getType()); |
139 | 153 |
140 // Check for precolored ranges. If Cur is precolored, it | 154 // Check for precolored ranges. If Cur is precolored, it |
141 // definitely gets that register. Previously processed live | 155 // definitely gets that register. Previously processed live |
142 // ranges would have avoided that register due to it being | 156 // ranges would have avoided that register due to it being |
143 // precolored. Future processed live ranges won't evict that | 157 // precolored. Future processed live ranges won't evict that |
144 // register because the live range has infinite weight. | 158 // register because the live range has infinite weight. |
145 if (Cur.Var->hasReg()) { | 159 if (Cur.Var->hasReg()) { |
146 int32_t RegNum = Cur.Var->getRegNum(); | 160 int32_t RegNum = Cur.Var->getRegNum(); |
147 // RegNumTmp should have already been set above. | 161 // RegNumTmp should have already been set above. |
148 assert(Cur.Var->getRegNumTmp() == RegNum); | 162 assert(Cur.Var->getRegNumTmp() == RegNum); |
149 if (Verbose) { | 163 if (Verbose) { |
150 Str << "Precoloring "; | 164 Str << "Precoloring "; |
151 Cur.dump(Func); | 165 Cur.dump(Func); |
152 Str << "\n"; | 166 Str << "\n"; |
153 } | 167 } |
154 Active.push_back(Cur); | 168 Active.push_back(Cur); |
155 assert(RegUses[RegNum] >= 0); | 169 assert(RegUses[RegNum] >= 0); |
156 ++RegUses[RegNum]; | 170 ++RegUses[RegNum]; |
157 assert(!UnhandledPrecolored.empty()); | 171 assert(!UnhandledPrecolored.empty()); |
158 assert(UnhandledPrecolored.begin()->Var == Cur.Var); | 172 assert(UnhandledPrecolored.back().Var == Cur.Var); |
159 UnhandledPrecolored.erase(UnhandledPrecolored.begin()); | 173 UnhandledPrecolored.pop_back(); |
160 continue; | 174 continue; |
161 } | 175 } |
162 | 176 |
163 // Check for active ranges that have expired or become inactive. | 177 // Check for active ranges that have expired or become inactive. |
164 for (auto I = Active.begin(), E = Active.end(); I != E; I = Next) { | 178 for (auto I = Active.begin(), E = Active.end(); I != E; I = Next) { |
165 Next = I; | 179 Next = I; |
166 ++Next; | 180 ++Next; |
167 LiveRangeWrapper Item = *I; | 181 LiveRangeWrapper Item = *I; |
168 Item.Var->trimLiveRange(Cur.range().getStart()); | 182 Item.Var->trimLiveRange(Cur.range().getStart()); |
169 bool Moved = false; | 183 bool Moved = false; |
170 if (Item.endsBefore(Cur)) { | 184 if (Item.endsBefore(Cur)) { |
171 // Move Item from Active to Handled list. | 185 // Move Item from Active to Handled list. |
172 if (Verbose) { | 186 if (Verbose) { |
173 Str << "Expiring "; | 187 Str << "Expiring "; |
174 Item.dump(Func); | 188 Item.dump(Func); |
175 Str << "\n"; | 189 Str << "\n"; |
176 } | 190 } |
177 Active.erase(I); | 191 Handled.splice(Handled.end(), Active, I); |
178 Handled.push_back(Item); | |
179 Moved = true; | 192 Moved = true; |
180 } else if (!Item.overlapsStart(Cur)) { | 193 } else if (!Item.overlapsStart(Cur)) { |
181 // Move Item from Active to Inactive list. | 194 // Move Item from Active to Inactive list. |
182 if (Verbose) { | 195 if (Verbose) { |
183 Str << "Inactivating "; | 196 Str << "Inactivating "; |
184 Item.dump(Func); | 197 Item.dump(Func); |
185 Str << "\n"; | 198 Str << "\n"; |
186 } | 199 } |
187 Active.erase(I); | 200 Inactive.splice(Inactive.end(), Active, I); |
188 Inactive.push_back(Item); | |
189 Moved = true; | 201 Moved = true; |
190 } | 202 } |
191 if (Moved) { | 203 if (Moved) { |
192 // Decrement Item from RegUses[]. | 204 // Decrement Item from RegUses[]. |
193 assert(Item.Var->hasRegTmp()); | 205 assert(Item.Var->hasRegTmp()); |
194 int32_t RegNum = Item.Var->getRegNumTmp(); | 206 int32_t RegNum = Item.Var->getRegNumTmp(); |
195 --RegUses[RegNum]; | 207 --RegUses[RegNum]; |
196 assert(RegUses[RegNum] >= 0); | 208 assert(RegUses[RegNum] >= 0); |
197 } | 209 } |
198 } | 210 } |
(...skipping 13 matching lines...) Expand all Loading... | |
212 // beginning of the function. | 224 // beginning of the function. |
213 if (!Item.range().isNonpoints()) | 225 if (!Item.range().isNonpoints()) |
214 continue; | 226 continue; |
215 if (Item.endsBefore(Cur)) { | 227 if (Item.endsBefore(Cur)) { |
216 // Move Item from Inactive to Handled list. | 228 // Move Item from Inactive to Handled list. |
217 if (Verbose) { | 229 if (Verbose) { |
218 Str << "Expiring "; | 230 Str << "Expiring "; |
219 Item.dump(Func); | 231 Item.dump(Func); |
220 Str << "\n"; | 232 Str << "\n"; |
221 } | 233 } |
222 Inactive.erase(I); | 234 Handled.splice(Handled.end(), Inactive, I); |
223 Handled.push_back(Item); | |
224 } else if (Item.overlapsStart(Cur)) { | 235 } else if (Item.overlapsStart(Cur)) { |
225 // Move Item from Inactive to Active list. | 236 // Move Item from Inactive to Active list. |
226 if (Verbose) { | 237 if (Verbose) { |
227 Str << "Reactivating "; | 238 Str << "Reactivating "; |
228 Item.dump(Func); | 239 Item.dump(Func); |
229 Str << "\n"; | 240 Str << "\n"; |
230 } | 241 } |
231 Inactive.erase(I); | 242 Active.splice(Active.end(), Inactive, I); |
232 Active.push_back(Item); | |
233 // Increment Item in RegUses[]. | 243 // Increment Item in RegUses[]. |
234 assert(Item.Var->hasRegTmp()); | 244 assert(Item.Var->hasRegTmp()); |
235 int32_t RegNum = Item.Var->getRegNumTmp(); | 245 int32_t RegNum = Item.Var->getRegNumTmp(); |
236 assert(RegUses[RegNum] >= 0); | 246 assert(RegUses[RegNum] >= 0); |
237 ++RegUses[RegNum]; | 247 ++RegUses[RegNum]; |
238 } | 248 } |
239 } | 249 } |
240 | 250 |
241 // Calculate available registers into Free[]. | 251 // Calculate available registers into Free[]. |
242 llvm::SmallBitVector Free = RegMask; | 252 llvm::SmallBitVector Free = RegMask; |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
332 std::vector<RegWeight> Weights(RegMask.size()); | 342 std::vector<RegWeight> Weights(RegMask.size()); |
333 | 343 |
334 // Remove registers from the Free[] list where an Unhandled | 344 // Remove registers from the Free[] list where an Unhandled |
335 // precolored range overlaps with the current range, and set those | 345 // precolored range overlaps with the current range, and set those |
336 // registers to infinite weight so that they aren't candidates for | 346 // registers to infinite weight so that they aren't candidates for |
337 // eviction. Cur.endsBefore(Item) is an early exit check that | 347 // eviction. Cur.endsBefore(Item) is an early exit check that |
338 // turns a guaranteed O(N^2) algorithm into expected linear | 348 // turns a guaranteed O(N^2) algorithm into expected linear |
339 // complexity. | 349 // complexity. |
340 llvm::SmallBitVector PrecoloredUnhandledMask(RegMask.size()); | 350 llvm::SmallBitVector PrecoloredUnhandledMask(RegMask.size()); |
341 // Note: PrecoloredUnhandledMask is only used for dumping. | 351 // Note: PrecoloredUnhandledMask is only used for dumping. |
342 for (const LiveRangeWrapper &Item : UnhandledPrecolored) { | 352 for (auto I = UnhandledPrecolored.rbegin(), E = UnhandledPrecolored.rend(); |
353 I != E; ++I) { | |
354 LiveRangeWrapper &Item = *I; | |
343 assert(Item.Var->hasReg()); | 355 assert(Item.Var->hasReg()); |
344 if (Cur.endsBefore(Item)) | 356 if (Cur.endsBefore(Item)) |
345 break; | 357 break; |
346 if (Item.overlaps(Cur)) { | 358 if (Item.overlaps(Cur)) { |
347 int32_t ItemReg = Item.Var->getRegNum(); // Note: not getRegNumTmp() | 359 int32_t ItemReg = Item.Var->getRegNum(); // Note: not getRegNumTmp() |
348 Weights[ItemReg].setWeight(RegWeight::Inf); | 360 Weights[ItemReg].setWeight(RegWeight::Inf); |
349 Free[ItemReg] = false; | 361 Free[ItemReg] = false; |
350 PrecoloredUnhandledMask[ItemReg] = true; | 362 PrecoloredUnhandledMask[ItemReg] = true; |
351 // Disable AllowOverlap if the preferred register is one of | 363 // Disable AllowOverlap if the preferred register is one of |
352 // these precolored unhandled overlapping ranges. | 364 // these precolored unhandled overlapping ranges. |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
442 LiveRangeWrapper Item = *I; | 454 LiveRangeWrapper Item = *I; |
443 if (Item.Var->getRegNumTmp() == MinWeightIndex) { | 455 if (Item.Var->getRegNumTmp() == MinWeightIndex) { |
444 if (Verbose) { | 456 if (Verbose) { |
445 Str << "Evicting "; | 457 Str << "Evicting "; |
446 Item.dump(Func); | 458 Item.dump(Func); |
447 Str << "\n"; | 459 Str << "\n"; |
448 } | 460 } |
449 --RegUses[MinWeightIndex]; | 461 --RegUses[MinWeightIndex]; |
450 assert(RegUses[MinWeightIndex] >= 0); | 462 assert(RegUses[MinWeightIndex] >= 0); |
451 Item.Var->setRegNumTmp(Variable::NoRegister); | 463 Item.Var->setRegNumTmp(Variable::NoRegister); |
452 Active.erase(I); | 464 Handled.splice(Handled.end(), Active, I); |
453 Handled.push_back(Item); | |
454 } | 465 } |
455 } | 466 } |
456 // Do the same for Inactive. | 467 // Do the same for Inactive. |
457 for (auto I = Inactive.begin(), E = Inactive.end(); I != E; I = Next) { | 468 for (auto I = Inactive.begin(), E = Inactive.end(); I != E; I = Next) { |
458 Next = I; | 469 Next = I; |
459 ++Next; | 470 ++Next; |
460 LiveRangeWrapper Item = *I; | 471 LiveRangeWrapper Item = *I; |
461 // Note: The Item.overlaps(Cur) clause is not part of the | 472 // Note: The Item.overlaps(Cur) clause is not part of the |
462 // description of AssignMemLoc() in the original paper. But | 473 // description of AssignMemLoc() in the original paper. But |
463 // there doesn't seem to be any need to evict an inactive | 474 // there doesn't seem to be any need to evict an inactive |
464 // live range that doesn't overlap with the live range | 475 // live range that doesn't overlap with the live range |
465 // currently being considered. It's especially bad if we | 476 // currently being considered. It's especially bad if we |
466 // would end up evicting an infinite-weight but | 477 // would end up evicting an infinite-weight but |
467 // currently-inactive live range. The most common situation | 478 // currently-inactive live range. The most common situation |
468 // for this would be a scratch register kill set for call | 479 // for this would be a scratch register kill set for call |
469 // instructions. | 480 // instructions. |
470 if (Item.Var->getRegNumTmp() == MinWeightIndex && | 481 if (Item.Var->getRegNumTmp() == MinWeightIndex && |
471 Item.overlaps(Cur)) { | 482 Item.overlaps(Cur)) { |
472 if (Verbose) { | 483 if (Verbose) { |
473 Str << "Evicting "; | 484 Str << "Evicting "; |
474 Item.dump(Func); | 485 Item.dump(Func); |
475 Str << "\n"; | 486 Str << "\n"; |
476 } | 487 } |
477 Item.Var->setRegNumTmp(Variable::NoRegister); | 488 Item.Var->setRegNumTmp(Variable::NoRegister); |
478 Inactive.erase(I); | 489 Handled.splice(Handled.end(), Inactive, I); |
479 Handled.push_back(Item); | |
480 } | 490 } |
481 } | 491 } |
482 // Assign the register to Cur. | 492 // Assign the register to Cur. |
483 Cur.Var->setRegNumTmp(MinWeightIndex); | 493 Cur.Var->setRegNumTmp(MinWeightIndex); |
484 assert(RegUses[MinWeightIndex] >= 0); | 494 assert(RegUses[MinWeightIndex] >= 0); |
485 ++RegUses[MinWeightIndex]; | 495 ++RegUses[MinWeightIndex]; |
486 Active.push_back(Cur); | 496 Active.push_back(Cur); |
487 if (Verbose) { | 497 if (Verbose) { |
488 Str << "Allocating "; | 498 Str << "Allocating "; |
489 Cur.dump(Func); | 499 Cur.dump(Func); |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
550 if (!Func->getContext()->isVerbose(IceV_LinearScan)) | 560 if (!Func->getContext()->isVerbose(IceV_LinearScan)) |
551 return; | 561 return; |
552 Func->resetCurrentNode(); | 562 Func->resetCurrentNode(); |
553 Str << "**** Current regalloc state:\n"; | 563 Str << "**** Current regalloc state:\n"; |
554 Str << "++++++ Handled:\n"; | 564 Str << "++++++ Handled:\n"; |
555 for (const LiveRangeWrapper &Item : Handled) { | 565 for (const LiveRangeWrapper &Item : Handled) { |
556 Item.dump(Func); | 566 Item.dump(Func); |
557 Str << "\n"; | 567 Str << "\n"; |
558 } | 568 } |
559 Str << "++++++ Unhandled:\n"; | 569 Str << "++++++ Unhandled:\n"; |
560 for (const LiveRangeWrapper &Item : Unhandled) { | 570 for (const LiveRangeWrapper &Item : Unhandled) { |
jvoung (off chromium)
2014/10/13 21:41:50
Maybe iterate over Unhandled in reverse to preserv
| |
561 Item.dump(Func); | 571 Item.dump(Func); |
562 Str << "\n"; | 572 Str << "\n"; |
563 } | 573 } |
564 Str << "++++++ Active:\n"; | 574 Str << "++++++ Active:\n"; |
565 for (const LiveRangeWrapper &Item : Active) { | 575 for (const LiveRangeWrapper &Item : Active) { |
566 Item.dump(Func); | 576 Item.dump(Func); |
567 Str << "\n"; | 577 Str << "\n"; |
568 } | 578 } |
569 Str << "++++++ Inactive:\n"; | 579 Str << "++++++ Inactive:\n"; |
570 for (const LiveRangeWrapper &Item : Inactive) { | 580 for (const LiveRangeWrapper &Item : Inactive) { |
571 Item.dump(Func); | 581 Item.dump(Func); |
572 Str << "\n"; | 582 Str << "\n"; |
573 } | 583 } |
574 } | 584 } |
575 | 585 |
576 } // end of namespace Ice | 586 } // end of namespace Ice |
OLD | NEW |