| 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 /// \file | 10 /// \file |
| (...skipping 259 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 270 } | 270 } |
| 271 // This isn't actually a fatal condition, but it would be nice to know if we | 271 // This isn't actually a fatal condition, but it would be nice to know if we |
| 272 // somehow pre-calculated Unhandled's size wrong. | 272 // somehow pre-calculated Unhandled's size wrong. |
| 273 assert(NumVars == 0); | 273 assert(NumVars == 0); |
| 274 | 274 |
| 275 // Don't build up the list of Kills because we know that no infinite-weight | 275 // Don't build up the list of Kills because we know that no infinite-weight |
| 276 // Variable has a live range spanning a call. | 276 // Variable has a live range spanning a call. |
| 277 Kills.clear(); | 277 Kills.clear(); |
| 278 } | 278 } |
| 279 | 279 |
| 280 void LinearScan::initForSecondChance() { |
| 281 TimerMarker T(TimerStack::TT_initUnhandled, Func); |
| 282 FindPreference = true; |
| 283 FindOverlap = true; |
| 284 const VarList &Vars = Func->getVariables(); |
| 285 Unhandled.reserve(Vars.size()); |
| 286 UnhandledPrecolored.reserve(Vars.size()); |
| 287 for (Variable *Var : Vars) { |
| 288 if (Var->hasReg()) { |
| 289 Var->untrimLiveRange(); |
| 290 Var->setRegNumTmp(Var->getRegNum()); |
| 291 Var->setMustHaveReg(); |
| 292 UnhandledPrecolored.push_back(Var); |
| 293 Unhandled.push_back(Var); |
| 294 } |
| 295 } |
| 296 for (Variable *Var : Evicted) { |
| 297 Var->untrimLiveRange(); |
| 298 Unhandled.push_back(Var); |
| 299 } |
| 300 } |
| 301 |
| 280 void LinearScan::init(RegAllocKind Kind) { | 302 void LinearScan::init(RegAllocKind Kind) { |
| 281 this->Kind = Kind; | 303 this->Kind = Kind; |
| 282 Unhandled.clear(); | 304 Unhandled.clear(); |
| 283 UnhandledPrecolored.clear(); | 305 UnhandledPrecolored.clear(); |
| 284 Handled.clear(); | 306 Handled.clear(); |
| 285 Inactive.clear(); | 307 Inactive.clear(); |
| 286 Active.clear(); | 308 Active.clear(); |
| 287 | 309 |
| 288 SizeT NumRegs = Target->getNumRegisters(); | 310 SizeT NumRegs = Target->getNumRegisters(); |
| 289 RegAliases.resize(NumRegs); | 311 RegAliases.resize(NumRegs); |
| 290 for (SizeT Reg = 0; Reg < NumRegs; ++Reg) { | 312 for (SizeT Reg = 0; Reg < NumRegs; ++Reg) { |
| 291 RegAliases[Reg] = &Target->getAliasesForRegister(Reg); | 313 RegAliases[Reg] = &Target->getAliasesForRegister(Reg); |
| 292 } | 314 } |
| 293 | 315 |
| 294 switch (Kind) { | 316 switch (Kind) { |
| 295 case RAK_Unknown: | 317 case RAK_Unknown: |
| 296 llvm::report_fatal_error("Invalid RAK_Unknown"); | 318 llvm::report_fatal_error("Invalid RAK_Unknown"); |
| 297 break; | 319 break; |
| 298 case RAK_Global: | 320 case RAK_Global: |
| 299 case RAK_Phi: | 321 case RAK_Phi: |
| 300 initForGlobal(); | 322 initForGlobal(); |
| 301 break; | 323 break; |
| 302 case RAK_InfOnly: | 324 case RAK_InfOnly: |
| 303 initForInfOnly(); | 325 initForInfOnly(); |
| 304 break; | 326 break; |
| 327 case RAK_SecondChance: |
| 328 initForSecondChance(); |
| 329 break; |
| 305 } | 330 } |
| 306 | 331 |
| 332 Evicted.clear(); |
| 333 |
| 307 auto CompareRanges = [](const Variable *L, const Variable *R) { | 334 auto CompareRanges = [](const Variable *L, const Variable *R) { |
| 308 InstNumberT Lstart = L->getLiveRange().getStart(); | 335 InstNumberT Lstart = L->getLiveRange().getStart(); |
| 309 InstNumberT Rstart = R->getLiveRange().getStart(); | 336 InstNumberT Rstart = R->getLiveRange().getStart(); |
| 310 if (Lstart == Rstart) | 337 if (Lstart == Rstart) |
| 311 return L->getIndex() < R->getIndex(); | 338 return L->getIndex() < R->getIndex(); |
| 312 return Lstart < Rstart; | 339 return Lstart < Rstart; |
| 313 }; | 340 }; |
| 314 // Do a reverse sort so that erasing elements (from the end) is fast. | 341 // Do a reverse sort so that erasing elements (from the end) is fast. |
| 315 std::sort(Unhandled.rbegin(), Unhandled.rend(), CompareRanges); | 342 std::sort(Unhandled.rbegin(), Unhandled.rend(), CompareRanges); |
| 316 std::sort(UnhandledPrecolored.rbegin(), UnhandledPrecolored.rend(), | 343 std::sort(UnhandledPrecolored.rbegin(), UnhandledPrecolored.rend(), |
| 317 CompareRanges); | 344 CompareRanges); |
| 318 | 345 |
| 319 Handled.reserve(Unhandled.size()); | 346 Handled.reserve(Unhandled.size()); |
| 320 Inactive.reserve(Unhandled.size()); | 347 Inactive.reserve(Unhandled.size()); |
| 321 Active.reserve(Unhandled.size()); | 348 Active.reserve(Unhandled.size()); |
| 349 Evicted.reserve(Unhandled.size()); |
| 322 } | 350 } |
| 323 | 351 |
| 324 // This is called when Cur must be allocated a register but no registers are | 352 // This is called when Cur must be allocated a register but no registers are |
| 325 // available across Cur's live range. To handle this, we find a register that | 353 // available across Cur's live range. To handle this, we find a register that |
| 326 // is not explicitly used during Cur's live range, spill that register to a | 354 // is not explicitly used during Cur's live range, spill that register to a |
| 327 // stack location right before Cur's live range begins, and fill (reload) the | 355 // stack location right before Cur's live range begins, and fill (reload) the |
| 328 // register from the stack location right after Cur's live range ends. | 356 // register from the stack location right after Cur's live range ends. |
| 329 void LinearScan::addSpillFill(IterationState &Iter) { | 357 void LinearScan::addSpillFill(IterationState &Iter) { |
| 330 // Identify the actual instructions that begin and end Iter.Cur's live range. | 358 // Identify the actual instructions that begin and end Iter.Cur's live range. |
| 331 // Iterate through Iter.Cur's node's instruction list until we find the actual | 359 // Iterate through Iter.Cur's node's instruction list until we find the actual |
| (...skipping 324 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 656 for (SizeT I = Active.size(); I > 0; --I) { | 684 for (SizeT I = Active.size(); I > 0; --I) { |
| 657 const SizeT Index = I - 1; | 685 const SizeT Index = I - 1; |
| 658 Variable *Item = Active[Index]; | 686 Variable *Item = Active[Index]; |
| 659 int32_t RegNum = Item->getRegNumTmp(); | 687 int32_t RegNum = Item->getRegNumTmp(); |
| 660 if (Aliases[RegNum]) { | 688 if (Aliases[RegNum]) { |
| 661 dumpLiveRangeTrace("Evicting A ", Item); | 689 dumpLiveRangeTrace("Evicting A ", Item); |
| 662 --RegUses[RegNum]; | 690 --RegUses[RegNum]; |
| 663 assert(RegUses[RegNum] >= 0); | 691 assert(RegUses[RegNum] >= 0); |
| 664 Item->setRegNumTmp(Variable::NoRegister); | 692 Item->setRegNumTmp(Variable::NoRegister); |
| 665 moveItem(Active, Index, Handled); | 693 moveItem(Active, Index, Handled); |
| 694 Evicted.push_back(Item); |
| 666 } | 695 } |
| 667 } | 696 } |
| 668 // Do the same for Inactive. | 697 // Do the same for Inactive. |
| 669 for (SizeT I = Inactive.size(); I > 0; --I) { | 698 for (SizeT I = Inactive.size(); I > 0; --I) { |
| 670 const SizeT Index = I - 1; | 699 const SizeT Index = I - 1; |
| 671 Variable *Item = Inactive[Index]; | 700 Variable *Item = Inactive[Index]; |
| 672 // Note: The Item->rangeOverlaps(Cur) clause is not part of the | 701 // Note: The Item->rangeOverlaps(Cur) clause is not part of the |
| 673 // description of AssignMemLoc() in the original paper. But there doesn't | 702 // description of AssignMemLoc() in the original paper. But there doesn't |
| 674 // seem to be any need to evict an inactive live range that doesn't | 703 // seem to be any need to evict an inactive live range that doesn't |
| 675 // overlap with the live range currently being considered. It's | 704 // overlap with the live range currently being considered. It's |
| 676 // especially bad if we would end up evicting an infinite-weight but | 705 // especially bad if we would end up evicting an infinite-weight but |
| 677 // currently-inactive live range. The most common situation for this | 706 // currently-inactive live range. The most common situation for this |
| 678 // would be a scratch register kill set for call instructions. | 707 // would be a scratch register kill set for call instructions. |
| 679 if (Aliases[Item->getRegNumTmp()] && Item->rangeOverlaps(Iter.Cur)) { | 708 if (Aliases[Item->getRegNumTmp()] && Item->rangeOverlaps(Iter.Cur)) { |
| 680 dumpLiveRangeTrace("Evicting I ", Item); | 709 dumpLiveRangeTrace("Evicting I ", Item); |
| 681 Item->setRegNumTmp(Variable::NoRegister); | 710 Item->setRegNumTmp(Variable::NoRegister); |
| 682 moveItem(Inactive, Index, Handled); | 711 moveItem(Inactive, Index, Handled); |
| 712 Evicted.push_back(Item); |
| 683 } | 713 } |
| 684 } | 714 } |
| 685 // Assign the register to Cur. | 715 // Assign the register to Cur. |
| 686 Iter.Cur->setRegNumTmp(MinWeightIndex); | 716 Iter.Cur->setRegNumTmp(MinWeightIndex); |
| 687 for (int32_t RegAlias = Aliases.find_first(); RegAlias >= 0; | 717 for (int32_t RegAlias = Aliases.find_first(); RegAlias >= 0; |
| 688 RegAlias = Aliases.find_next(RegAlias)) { | 718 RegAlias = Aliases.find_next(RegAlias)) { |
| 689 assert(RegUses[RegAlias] >= 0); | 719 assert(RegUses[RegAlias] >= 0); |
| 690 ++RegUses[RegAlias]; | 720 ++RegUses[RegAlias]; |
| 691 } | 721 } |
| 692 Active.push_back(Iter.Cur); | 722 Active.push_back(Iter.Cur); |
| (...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 940 Str << "\n"; | 970 Str << "\n"; |
| 941 } | 971 } |
| 942 Str << "++++++ Inactive:\n"; | 972 Str << "++++++ Inactive:\n"; |
| 943 for (const Variable *Item : Inactive) { | 973 for (const Variable *Item : Inactive) { |
| 944 dumpLiveRange(Item, Func); | 974 dumpLiveRange(Item, Func); |
| 945 Str << "\n"; | 975 Str << "\n"; |
| 946 } | 976 } |
| 947 } | 977 } |
| 948 | 978 |
| 949 } // end of namespace Ice | 979 } // end of namespace Ice |
| OLD | NEW |