Chromium Code Reviews| 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 |