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 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
78 } // end of anonymous namespace | 78 } // end of anonymous namespace |
79 | 79 |
80 // Prepare for full register allocation of all variables. We depend | 80 // Prepare for full register allocation of all variables. We depend |
81 // on liveness analysis to have calculated live ranges. | 81 // on liveness analysis to have calculated live ranges. |
82 void LinearScan::initForGlobal() { | 82 void LinearScan::initForGlobal() { |
83 TimerMarker T(TimerStack::TT_initUnhandled, Func); | 83 TimerMarker T(TimerStack::TT_initUnhandled, Func); |
84 FindPreference = true; | 84 FindPreference = true; |
85 FindOverlap = true; | 85 FindOverlap = true; |
86 const VarList &Vars = Func->getVariables(); | 86 const VarList &Vars = Func->getVariables(); |
87 Unhandled.reserve(Vars.size()); | 87 Unhandled.reserve(Vars.size()); |
88 UnhandledPrecolored.reserve(Vars.size()); | |
88 // Gather the live ranges of all variables and add them to the | 89 // Gather the live ranges of all variables and add them to the |
89 // Unhandled set. | 90 // Unhandled set. |
90 for (Variable *Var : Vars) { | 91 for (Variable *Var : Vars) { |
91 // Explicitly don't consider zero-weight variables, which are | 92 // Explicitly don't consider zero-weight variables, which are |
92 // meant to be spill slots. | 93 // meant to be spill slots. |
93 if (Var->getWeight() == RegWeight::Zero) | 94 if (Var->getWeight() == RegWeight::Zero) |
94 continue; | 95 continue; |
95 // Don't bother if the variable has a null live range, which means | 96 // Don't bother if the variable has a null live range, which means |
96 // it was never referenced. | 97 // it was never referenced. |
97 if (Var->getLiveRange().isEmpty()) | 98 if (Var->getLiveRange().isEmpty()) |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
177 for (SizeT J = 0; J < NumVars; ++J) { | 178 for (SizeT J = 0; J < NumVars; ++J) { |
178 const Variable *Var = Src->getVar(J); | 179 const Variable *Var = Src->getVar(J); |
179 if (Var->hasReg() || Var->getWeight() == RegWeight::Inf) | 180 if (Var->hasReg() || Var->getWeight() == RegWeight::Inf) |
180 LREnd[Var->getIndex()] = Inst->getNumber(); | 181 LREnd[Var->getIndex()] = Inst->getNumber(); |
181 } | 182 } |
182 } | 183 } |
183 } | 184 } |
184 } | 185 } |
185 | 186 |
186 Unhandled.reserve(NumVars); | 187 Unhandled.reserve(NumVars); |
188 UnhandledPrecolored.reserve(NumVars); | |
187 for (SizeT i = 0; i < Vars.size(); ++i) { | 189 for (SizeT i = 0; i < Vars.size(); ++i) { |
188 Variable *Var = Vars[i]; | 190 Variable *Var = Vars[i]; |
189 if (LRBegin[i] != Inst::NumberSentinel) { | 191 if (LRBegin[i] != Inst::NumberSentinel) { |
190 assert(LREnd[i] != Inst::NumberSentinel); | 192 assert(LREnd[i] != Inst::NumberSentinel); |
191 Unhandled.push_back(Var); | 193 Unhandled.push_back(Var); |
192 Var->resetLiveRange(); | 194 Var->resetLiveRange(); |
193 const uint32_t WeightDelta = 1; | 195 const uint32_t WeightDelta = 1; |
194 Var->addLiveRange(LRBegin[i], LREnd[i], WeightDelta); | 196 Var->addLiveRange(LRBegin[i], LREnd[i], WeightDelta); |
195 Var->untrimLiveRange(); | 197 Var->untrimLiveRange(); |
196 if (Var->hasReg()) { | 198 if (Var->hasReg()) { |
(...skipping 12 matching lines...) Expand all Loading... | |
209 // infinite-weight Variable has a live range spanning a call. | 211 // infinite-weight Variable has a live range spanning a call. |
210 Kills.clear(); | 212 Kills.clear(); |
211 } | 213 } |
212 | 214 |
213 void LinearScan::init(RegAllocKind Kind) { | 215 void LinearScan::init(RegAllocKind Kind) { |
214 Unhandled.clear(); | 216 Unhandled.clear(); |
215 UnhandledPrecolored.clear(); | 217 UnhandledPrecolored.clear(); |
216 Handled.clear(); | 218 Handled.clear(); |
217 Inactive.clear(); | 219 Inactive.clear(); |
218 Active.clear(); | 220 Active.clear(); |
221 Handled.reserve(Unhandled.size()); | |
222 Inactive.reserve(Unhandled.size()); | |
jvoung (off chromium)
2014/12/04 02:46:44
Should this be after initForGlobal/initForInfOnly?
Jim Stichnoth
2014/12/04 04:25:17
Done, thanks!
| |
223 Active.reserve(Unhandled.size()); | |
219 | 224 |
220 switch (Kind) { | 225 switch (Kind) { |
221 case RAK_Global: | 226 case RAK_Global: |
222 initForGlobal(); | 227 initForGlobal(); |
223 break; | 228 break; |
224 case RAK_InfOnly: | 229 case RAK_InfOnly: |
225 initForInfOnly(); | 230 initForInfOnly(); |
226 break; | 231 break; |
227 } | 232 } |
228 | 233 |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
269 | 274 |
270 // RegUses[I] is the number of live ranges (variables) that register | 275 // RegUses[I] is the number of live ranges (variables) that register |
271 // I is currently assigned to. It can be greater than 1 as a result | 276 // I is currently assigned to. It can be greater than 1 as a result |
272 // of AllowOverlap inference below. | 277 // of AllowOverlap inference below. |
273 std::vector<int> RegUses(RegMaskFull.size()); | 278 std::vector<int> RegUses(RegMaskFull.size()); |
274 // Unhandled is already set to all ranges in increasing order of | 279 // Unhandled is already set to all ranges in increasing order of |
275 // start points. | 280 // start points. |
276 assert(Active.empty()); | 281 assert(Active.empty()); |
277 assert(Inactive.empty()); | 282 assert(Inactive.empty()); |
278 assert(Handled.empty()); | 283 assert(Handled.empty()); |
279 UnorderedRanges::iterator Next; | |
280 const TargetLowering::RegSetMask RegsInclude = | 284 const TargetLowering::RegSetMask RegsInclude = |
281 TargetLowering::RegSet_CallerSave; | 285 TargetLowering::RegSet_CallerSave; |
282 const TargetLowering::RegSetMask RegsExclude = TargetLowering::RegSet_None; | 286 const TargetLowering::RegSetMask RegsExclude = TargetLowering::RegSet_None; |
283 const llvm::SmallBitVector KillsMask = | 287 const llvm::SmallBitVector KillsMask = |
284 Func->getTarget()->getRegisterSet(RegsInclude, RegsExclude); | 288 Func->getTarget()->getRegisterSet(RegsInclude, RegsExclude); |
285 | 289 |
286 while (!Unhandled.empty()) { | 290 while (!Unhandled.empty()) { |
287 Variable *Cur = Unhandled.back(); | 291 Variable *Cur = Unhandled.back(); |
288 Unhandled.pop_back(); | 292 Unhandled.pop_back(); |
289 if (Verbose) { | 293 if (Verbose) { |
(...skipping 22 matching lines...) Expand all Loading... | |
312 Active.push_back(Cur); | 316 Active.push_back(Cur); |
313 assert(RegUses[RegNum] >= 0); | 317 assert(RegUses[RegNum] >= 0); |
314 ++RegUses[RegNum]; | 318 ++RegUses[RegNum]; |
315 assert(!UnhandledPrecolored.empty()); | 319 assert(!UnhandledPrecolored.empty()); |
316 assert(UnhandledPrecolored.back() == Cur); | 320 assert(UnhandledPrecolored.back() == Cur); |
317 UnhandledPrecolored.pop_back(); | 321 UnhandledPrecolored.pop_back(); |
318 continue; | 322 continue; |
319 } | 323 } |
320 | 324 |
321 // Check for active ranges that have expired or become inactive. | 325 // Check for active ranges that have expired or become inactive. |
322 for (auto I = Active.begin(), E = Active.end(); I != E; I = Next) { | 326 for (SizeT I = Active.size(); I > 0; --I) { |
323 Next = I; | 327 Variable *Item = Active[I - 1]; |
jvoung (off chromium)
2014/12/04 02:46:44
Maybe initialize I to Active.size() - 1, and go up
Jim Stichnoth
2014/12/04 04:25:17
SizeT is unsigned (uint32_t), so I>=0 is always tr
| |
324 ++Next; | |
325 Variable *Item = *I; | |
326 Item->trimLiveRange(Cur->getLiveRange().getStart()); | 328 Item->trimLiveRange(Cur->getLiveRange().getStart()); |
327 bool Moved = false; | 329 bool Moved = false; |
328 if (Item->rangeEndsBefore(Cur)) { | 330 if (Item->rangeEndsBefore(Cur)) { |
329 // Move Item from Active to Handled list. | 331 // Move Item from Active to Handled list. |
330 if (Verbose) { | 332 if (Verbose) { |
331 Str << "Expiring "; | 333 Str << "Expiring "; |
332 dumpLiveRange(Item, Func); | 334 dumpLiveRange(Item, Func); |
333 Str << "\n"; | 335 Str << "\n"; |
334 } | 336 } |
335 Handled.splice(Handled.end(), Active, I); | 337 moveItem(Active, I - 1, Handled); |
336 Moved = true; | 338 Moved = true; |
337 } else if (!Item->rangeOverlapsStart(Cur)) { | 339 } else if (!Item->rangeOverlapsStart(Cur)) { |
338 // Move Item from Active to Inactive list. | 340 // Move Item from Active to Inactive list. |
339 if (Verbose) { | 341 if (Verbose) { |
340 Str << "Inactivating "; | 342 Str << "Inactivating "; |
341 dumpLiveRange(Item, Func); | 343 dumpLiveRange(Item, Func); |
342 Str << "\n"; | 344 Str << "\n"; |
343 } | 345 } |
344 Inactive.splice(Inactive.end(), Active, I); | 346 moveItem(Active, I - 1, Inactive); |
345 Moved = true; | 347 Moved = true; |
346 } | 348 } |
347 if (Moved) { | 349 if (Moved) { |
348 // Decrement Item from RegUses[]. | 350 // Decrement Item from RegUses[]. |
349 assert(Item->hasRegTmp()); | 351 assert(Item->hasRegTmp()); |
350 int32_t RegNum = Item->getRegNumTmp(); | 352 int32_t RegNum = Item->getRegNumTmp(); |
351 --RegUses[RegNum]; | 353 --RegUses[RegNum]; |
352 assert(RegUses[RegNum] >= 0); | 354 assert(RegUses[RegNum] >= 0); |
353 } | 355 } |
354 } | 356 } |
355 | 357 |
356 // Check for inactive ranges that have expired or reactivated. | 358 // Check for inactive ranges that have expired or reactivated. |
357 for (auto I = Inactive.begin(), E = Inactive.end(); I != E; I = Next) { | 359 for (SizeT I = Inactive.size(); I > 0; --I) { |
358 Next = I; | 360 Variable *Item = Inactive[I - 1]; |
359 ++Next; | |
360 Variable *Item = *I; | |
361 Item->trimLiveRange(Cur->getLiveRange().getStart()); | 361 Item->trimLiveRange(Cur->getLiveRange().getStart()); |
362 if (Item->rangeEndsBefore(Cur)) { | 362 if (Item->rangeEndsBefore(Cur)) { |
363 // Move Item from Inactive to Handled list. | 363 // Move Item from Inactive to Handled list. |
364 if (Verbose) { | 364 if (Verbose) { |
365 Str << "Expiring "; | 365 Str << "Expiring "; |
366 dumpLiveRange(Item, Func); | 366 dumpLiveRange(Item, Func); |
367 Str << "\n"; | 367 Str << "\n"; |
368 } | 368 } |
369 Handled.splice(Handled.end(), Inactive, I); | 369 moveItem(Inactive, I - 1, Handled); |
370 } else if (Item->rangeOverlapsStart(Cur)) { | 370 } else if (Item->rangeOverlapsStart(Cur)) { |
371 // Move Item from Inactive to Active list. | 371 // Move Item from Inactive to Active list. |
372 if (Verbose) { | 372 if (Verbose) { |
373 Str << "Reactivating "; | 373 Str << "Reactivating "; |
374 dumpLiveRange(Item, Func); | 374 dumpLiveRange(Item, Func); |
375 Str << "\n"; | 375 Str << "\n"; |
376 } | 376 } |
377 Active.splice(Active.end(), Inactive, I); | 377 moveItem(Inactive, I - 1, Active); |
378 // Increment Item in RegUses[]. | 378 // Increment Item in RegUses[]. |
379 assert(Item->hasRegTmp()); | 379 assert(Item->hasRegTmp()); |
380 int32_t RegNum = Item->getRegNumTmp(); | 380 int32_t RegNum = Item->getRegNumTmp(); |
381 assert(RegUses[RegNum] >= 0); | 381 assert(RegUses[RegNum] >= 0); |
382 ++RegUses[RegNum]; | 382 ++RegUses[RegNum]; |
383 } | 383 } |
384 } | 384 } |
385 | 385 |
386 // Calculate available registers into Free[]. | 386 // Calculate available registers into Free[]. |
387 llvm::SmallBitVector Free = RegMask; | 387 llvm::SmallBitVector Free = RegMask; |
(...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
591 // don't allocate any register to it, and move it to the | 591 // don't allocate any register to it, and move it to the |
592 // Handled state. | 592 // Handled state. |
593 Handled.push_back(Cur); | 593 Handled.push_back(Cur); |
594 if (Cur->getLiveRange().getWeight().isInf()) { | 594 if (Cur->getLiveRange().getWeight().isInf()) { |
595 Func->setError("Unable to find a physical register for an " | 595 Func->setError("Unable to find a physical register for an " |
596 "infinite-weight live range"); | 596 "infinite-weight live range"); |
597 } | 597 } |
598 } else { | 598 } else { |
599 // Evict all live ranges in Active that register number | 599 // Evict all live ranges in Active that register number |
600 // MinWeightIndex is assigned to. | 600 // MinWeightIndex is assigned to. |
601 for (auto I = Active.begin(), E = Active.end(); I != E; I = Next) { | 601 for (SizeT I = Active.size(); I > 0; --I) { |
602 Next = I; | 602 Variable *Item = Active[I - 1]; |
603 ++Next; | |
604 Variable *Item = *I; | |
605 if (Item->getRegNumTmp() == MinWeightIndex) { | 603 if (Item->getRegNumTmp() == MinWeightIndex) { |
606 if (Verbose) { | 604 if (Verbose) { |
607 Str << "Evicting "; | 605 Str << "Evicting "; |
608 dumpLiveRange(Item, Func); | 606 dumpLiveRange(Item, Func); |
609 Str << "\n"; | 607 Str << "\n"; |
610 } | 608 } |
611 --RegUses[MinWeightIndex]; | 609 --RegUses[MinWeightIndex]; |
612 assert(RegUses[MinWeightIndex] >= 0); | 610 assert(RegUses[MinWeightIndex] >= 0); |
613 Item->setRegNumTmp(Variable::NoRegister); | 611 Item->setRegNumTmp(Variable::NoRegister); |
614 Handled.splice(Handled.end(), Active, I); | 612 moveItem(Active, I - 1, Handled); |
615 } | 613 } |
616 } | 614 } |
617 // Do the same for Inactive. | 615 // Do the same for Inactive. |
618 for (auto I = Inactive.begin(), E = Inactive.end(); I != E; I = Next) { | 616 for (SizeT I = Inactive.size(); I > 0; --I) { |
619 Next = I; | 617 Variable *Item = Inactive[I - 1]; |
620 ++Next; | |
621 Variable *Item = *I; | |
622 // Note: The Item->rangeOverlaps(Cur) clause is not part of the | 618 // Note: The Item->rangeOverlaps(Cur) clause is not part of the |
623 // description of AssignMemLoc() in the original paper. But | 619 // description of AssignMemLoc() in the original paper. But |
624 // there doesn't seem to be any need to evict an inactive | 620 // there doesn't seem to be any need to evict an inactive |
625 // live range that doesn't overlap with the live range | 621 // live range that doesn't overlap with the live range |
626 // currently being considered. It's especially bad if we | 622 // currently being considered. It's especially bad if we |
627 // would end up evicting an infinite-weight but | 623 // would end up evicting an infinite-weight but |
628 // currently-inactive live range. The most common situation | 624 // currently-inactive live range. The most common situation |
629 // for this would be a scratch register kill set for call | 625 // for this would be a scratch register kill set for call |
630 // instructions. | 626 // instructions. |
631 if (Item->getRegNumTmp() == MinWeightIndex && | 627 if (Item->getRegNumTmp() == MinWeightIndex && |
632 Item->rangeOverlaps(Cur)) { | 628 Item->rangeOverlaps(Cur)) { |
633 if (Verbose) { | 629 if (Verbose) { |
634 Str << "Evicting "; | 630 Str << "Evicting "; |
635 dumpLiveRange(Item, Func); | 631 dumpLiveRange(Item, Func); |
636 Str << "\n"; | 632 Str << "\n"; |
637 } | 633 } |
638 Item->setRegNumTmp(Variable::NoRegister); | 634 Item->setRegNumTmp(Variable::NoRegister); |
639 Handled.splice(Handled.end(), Inactive, I); | 635 moveItem(Inactive, I - 1, Handled); |
640 } | 636 } |
641 } | 637 } |
642 // Assign the register to Cur. | 638 // Assign the register to Cur. |
643 Cur->setRegNumTmp(MinWeightIndex); | 639 Cur->setRegNumTmp(MinWeightIndex); |
644 assert(RegUses[MinWeightIndex] >= 0); | 640 assert(RegUses[MinWeightIndex] >= 0); |
645 ++RegUses[MinWeightIndex]; | 641 ++RegUses[MinWeightIndex]; |
646 Active.push_back(Cur); | 642 Active.push_back(Cur); |
647 if (Verbose) { | 643 if (Verbose) { |
648 Str << "Allocating "; | 644 Str << "Allocating "; |
649 dumpLiveRange(Cur, Func); | 645 dumpLiveRange(Cur, Func); |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
719 Str << "\n"; | 715 Str << "\n"; |
720 } | 716 } |
721 Str << "++++++ Inactive:\n"; | 717 Str << "++++++ Inactive:\n"; |
722 for (const Variable *Item : Inactive) { | 718 for (const Variable *Item : Inactive) { |
723 dumpLiveRange(Item, Func); | 719 dumpLiveRange(Item, Func); |
724 Str << "\n"; | 720 Str << "\n"; |
725 } | 721 } |
726 } | 722 } |
727 | 723 |
728 } // end of namespace Ice | 724 } // end of namespace Ice |
OLD | NEW |