| 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 246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 257 // two interfering variables to share the same register in certain | 257 // two interfering variables to share the same register in certain |
| 258 // cases. | 258 // cases. |
| 259 // | 259 // |
| 260 // Requires running Cfg::liveness(Liveness_Intervals) in | 260 // Requires running Cfg::liveness(Liveness_Intervals) in |
| 261 // preparation. Results are assigned to Variable::RegNum for each | 261 // preparation. Results are assigned to Variable::RegNum for each |
| 262 // Variable. | 262 // Variable. |
| 263 void LinearScan::scan(const llvm::SmallBitVector &RegMaskFull, | 263 void LinearScan::scan(const llvm::SmallBitVector &RegMaskFull, |
| 264 bool Randomized) { | 264 bool Randomized) { |
| 265 TimerMarker T(TimerStack::TT_linearScan, Func); | 265 TimerMarker T(TimerStack::TT_linearScan, Func); |
| 266 assert(RegMaskFull.any()); // Sanity check | 266 assert(RegMaskFull.any()); // Sanity check |
| 267 Ostream &Str = Func->getContext()->getStrDump(); | 267 GlobalContext *Ctx = Func->getContext(); |
| 268 const bool Verbose = | 268 const bool Verbose = |
| 269 ALLOW_DUMP && Func->getContext()->isVerbose(IceV_LinearScan); | 269 ALLOW_DUMP && Ctx->isVerbose(IceV_LinearScan); |
| 270 if (Verbose) |
| 271 Ctx->lockStr(); |
| 270 Func->resetCurrentNode(); | 272 Func->resetCurrentNode(); |
| 271 VariablesMetadata *VMetadata = Func->getVMetadata(); | 273 VariablesMetadata *VMetadata = Func->getVMetadata(); |
| 272 const size_t NumRegisters = RegMaskFull.size(); | 274 const size_t NumRegisters = RegMaskFull.size(); |
| 273 llvm::SmallBitVector PreDefinedRegisters(NumRegisters); | 275 llvm::SmallBitVector PreDefinedRegisters(NumRegisters); |
| 274 if (Randomized) { | 276 if (Randomized) { |
| 275 for (Variable *Var : UnhandledPrecolored) { | 277 for (Variable *Var : UnhandledPrecolored) { |
| 276 PreDefinedRegisters[Var->getRegNum()] = true; | 278 PreDefinedRegisters[Var->getRegNum()] = true; |
| 277 } | 279 } |
| 278 } | 280 } |
| 279 | 281 |
| (...skipping 13 matching lines...) Expand all Loading... |
| 293 const TargetLowering::RegSetMask RegsInclude = | 295 const TargetLowering::RegSetMask RegsInclude = |
| 294 TargetLowering::RegSet_CallerSave; | 296 TargetLowering::RegSet_CallerSave; |
| 295 const TargetLowering::RegSetMask RegsExclude = TargetLowering::RegSet_None; | 297 const TargetLowering::RegSetMask RegsExclude = TargetLowering::RegSet_None; |
| 296 const llvm::SmallBitVector KillsMask = | 298 const llvm::SmallBitVector KillsMask = |
| 297 Func->getTarget()->getRegisterSet(RegsInclude, RegsExclude); | 299 Func->getTarget()->getRegisterSet(RegsInclude, RegsExclude); |
| 298 | 300 |
| 299 while (!Unhandled.empty()) { | 301 while (!Unhandled.empty()) { |
| 300 Variable *Cur = Unhandled.back(); | 302 Variable *Cur = Unhandled.back(); |
| 301 Unhandled.pop_back(); | 303 Unhandled.pop_back(); |
| 302 if (Verbose) { | 304 if (Verbose) { |
| 305 Ostream &Str = Ctx->getStrDump(); |
| 303 Str << "\nConsidering "; | 306 Str << "\nConsidering "; |
| 304 dumpLiveRange(Cur, Func); | 307 dumpLiveRange(Cur, Func); |
| 305 Str << "\n"; | 308 Str << "\n"; |
| 306 } | 309 } |
| 307 const llvm::SmallBitVector RegMask = | 310 const llvm::SmallBitVector RegMask = |
| 308 RegMaskFull & Func->getTarget()->getRegisterSetForType(Cur->getType()); | 311 RegMaskFull & Func->getTarget()->getRegisterSetForType(Cur->getType()); |
| 309 KillsRange.trim(Cur->getLiveRange().getStart()); | 312 KillsRange.trim(Cur->getLiveRange().getStart()); |
| 310 | 313 |
| 311 // Check for precolored ranges. If Cur is precolored, it | 314 // Check for precolored ranges. If Cur is precolored, it |
| 312 // definitely gets that register. Previously processed live | 315 // definitely gets that register. Previously processed live |
| 313 // ranges would have avoided that register due to it being | 316 // ranges would have avoided that register due to it being |
| 314 // precolored. Future processed live ranges won't evict that | 317 // precolored. Future processed live ranges won't evict that |
| 315 // register because the live range has infinite weight. | 318 // register because the live range has infinite weight. |
| 316 if (Cur->hasReg()) { | 319 if (Cur->hasReg()) { |
| 317 int32_t RegNum = Cur->getRegNum(); | 320 int32_t RegNum = Cur->getRegNum(); |
| 318 // RegNumTmp should have already been set above. | 321 // RegNumTmp should have already been set above. |
| 319 assert(Cur->getRegNumTmp() == RegNum); | 322 assert(Cur->getRegNumTmp() == RegNum); |
| 320 if (Verbose) { | 323 if (Verbose) { |
| 324 Ostream &Str = Ctx->getStrDump(); |
| 321 Str << "Precoloring "; | 325 Str << "Precoloring "; |
| 322 dumpLiveRange(Cur, Func); | 326 dumpLiveRange(Cur, Func); |
| 323 Str << "\n"; | 327 Str << "\n"; |
| 324 } | 328 } |
| 325 Active.push_back(Cur); | 329 Active.push_back(Cur); |
| 326 assert(RegUses[RegNum] >= 0); | 330 assert(RegUses[RegNum] >= 0); |
| 327 ++RegUses[RegNum]; | 331 ++RegUses[RegNum]; |
| 328 assert(!UnhandledPrecolored.empty()); | 332 assert(!UnhandledPrecolored.empty()); |
| 329 assert(UnhandledPrecolored.back() == Cur); | 333 assert(UnhandledPrecolored.back() == Cur); |
| 330 UnhandledPrecolored.pop_back(); | 334 UnhandledPrecolored.pop_back(); |
| 331 continue; | 335 continue; |
| 332 } | 336 } |
| 333 | 337 |
| 334 // Check for active ranges that have expired or become inactive. | 338 // Check for active ranges that have expired or become inactive. |
| 335 for (SizeT I = Active.size(); I > 0; --I) { | 339 for (SizeT I = Active.size(); I > 0; --I) { |
| 336 const SizeT Index = I - 1; | 340 const SizeT Index = I - 1; |
| 337 Variable *Item = Active[Index]; | 341 Variable *Item = Active[Index]; |
| 338 Item->trimLiveRange(Cur->getLiveRange().getStart()); | 342 Item->trimLiveRange(Cur->getLiveRange().getStart()); |
| 339 bool Moved = false; | 343 bool Moved = false; |
| 340 if (Item->rangeEndsBefore(Cur)) { | 344 if (Item->rangeEndsBefore(Cur)) { |
| 341 // Move Item from Active to Handled list. | 345 // Move Item from Active to Handled list. |
| 342 if (Verbose) { | 346 if (Verbose) { |
| 347 Ostream &Str = Ctx->getStrDump(); |
| 343 Str << "Expiring "; | 348 Str << "Expiring "; |
| 344 dumpLiveRange(Item, Func); | 349 dumpLiveRange(Item, Func); |
| 345 Str << "\n"; | 350 Str << "\n"; |
| 346 } | 351 } |
| 347 moveItem(Active, Index, Handled); | 352 moveItem(Active, Index, Handled); |
| 348 Moved = true; | 353 Moved = true; |
| 349 } else if (!Item->rangeOverlapsStart(Cur)) { | 354 } else if (!Item->rangeOverlapsStart(Cur)) { |
| 350 // Move Item from Active to Inactive list. | 355 // Move Item from Active to Inactive list. |
| 351 if (Verbose) { | 356 if (Verbose) { |
| 357 Ostream &Str = Ctx->getStrDump(); |
| 352 Str << "Inactivating "; | 358 Str << "Inactivating "; |
| 353 dumpLiveRange(Item, Func); | 359 dumpLiveRange(Item, Func); |
| 354 Str << "\n"; | 360 Str << "\n"; |
| 355 } | 361 } |
| 356 moveItem(Active, Index, Inactive); | 362 moveItem(Active, Index, Inactive); |
| 357 Moved = true; | 363 Moved = true; |
| 358 } | 364 } |
| 359 if (Moved) { | 365 if (Moved) { |
| 360 // Decrement Item from RegUses[]. | 366 // Decrement Item from RegUses[]. |
| 361 assert(Item->hasRegTmp()); | 367 assert(Item->hasRegTmp()); |
| 362 int32_t RegNum = Item->getRegNumTmp(); | 368 int32_t RegNum = Item->getRegNumTmp(); |
| 363 --RegUses[RegNum]; | 369 --RegUses[RegNum]; |
| 364 assert(RegUses[RegNum] >= 0); | 370 assert(RegUses[RegNum] >= 0); |
| 365 } | 371 } |
| 366 } | 372 } |
| 367 | 373 |
| 368 // Check for inactive ranges that have expired or reactivated. | 374 // Check for inactive ranges that have expired or reactivated. |
| 369 for (SizeT I = Inactive.size(); I > 0; --I) { | 375 for (SizeT I = Inactive.size(); I > 0; --I) { |
| 370 const SizeT Index = I - 1; | 376 const SizeT Index = I - 1; |
| 371 Variable *Item = Inactive[Index]; | 377 Variable *Item = Inactive[Index]; |
| 372 Item->trimLiveRange(Cur->getLiveRange().getStart()); | 378 Item->trimLiveRange(Cur->getLiveRange().getStart()); |
| 373 if (Item->rangeEndsBefore(Cur)) { | 379 if (Item->rangeEndsBefore(Cur)) { |
| 374 // Move Item from Inactive to Handled list. | 380 // Move Item from Inactive to Handled list. |
| 375 if (Verbose) { | 381 if (Verbose) { |
| 382 Ostream &Str = Ctx->getStrDump(); |
| 376 Str << "Expiring "; | 383 Str << "Expiring "; |
| 377 dumpLiveRange(Item, Func); | 384 dumpLiveRange(Item, Func); |
| 378 Str << "\n"; | 385 Str << "\n"; |
| 379 } | 386 } |
| 380 moveItem(Inactive, Index, Handled); | 387 moveItem(Inactive, Index, Handled); |
| 381 } else if (Item->rangeOverlapsStart(Cur)) { | 388 } else if (Item->rangeOverlapsStart(Cur)) { |
| 382 // Move Item from Inactive to Active list. | 389 // Move Item from Inactive to Active list. |
| 383 if (Verbose) { | 390 if (Verbose) { |
| 391 Ostream &Str = Ctx->getStrDump(); |
| 384 Str << "Reactivating "; | 392 Str << "Reactivating "; |
| 385 dumpLiveRange(Item, Func); | 393 dumpLiveRange(Item, Func); |
| 386 Str << "\n"; | 394 Str << "\n"; |
| 387 } | 395 } |
| 388 moveItem(Inactive, Index, Active); | 396 moveItem(Inactive, Index, Active); |
| 389 // Increment Item in RegUses[]. | 397 // Increment Item in RegUses[]. |
| 390 assert(Item->hasRegTmp()); | 398 assert(Item->hasRegTmp()); |
| 391 int32_t RegNum = Item->getRegNumTmp(); | 399 int32_t RegNum = Item->getRegNumTmp(); |
| 392 assert(RegUses[RegNum] >= 0); | 400 assert(RegUses[RegNum] >= 0); |
| 393 ++RegUses[RegNum]; | 401 ++RegUses[RegNum]; |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 439 IsSingleDef && IsAssign && !overlapsDefs(Func, Cur, SrcVar); | 447 IsSingleDef && IsAssign && !overlapsDefs(Func, Cur, SrcVar); |
| 440 } | 448 } |
| 441 if (AllowOverlap || Free[SrcReg]) { | 449 if (AllowOverlap || Free[SrcReg]) { |
| 442 Prefer = SrcVar; | 450 Prefer = SrcVar; |
| 443 PreferReg = SrcReg; | 451 PreferReg = SrcReg; |
| 444 } | 452 } |
| 445 } | 453 } |
| 446 } | 454 } |
| 447 } | 455 } |
| 448 if (Verbose && Prefer) { | 456 if (Verbose && Prefer) { |
| 457 Ostream &Str = Ctx->getStrDump(); |
| 449 Str << "Initial Prefer="; | 458 Str << "Initial Prefer="; |
| 450 Prefer->dump(Func); | 459 Prefer->dump(Func); |
| 451 Str << " R=" << PreferReg << " LIVE=" << Prefer->getLiveRange() | 460 Str << " R=" << PreferReg << " LIVE=" << Prefer->getLiveRange() |
| 452 << " Overlap=" << AllowOverlap << "\n"; | 461 << " Overlap=" << AllowOverlap << "\n"; |
| 453 } | 462 } |
| 454 } | 463 } |
| 455 } | 464 } |
| 456 | 465 |
| 457 // Remove registers from the Free[] list where an Inactive range | 466 // Remove registers from the Free[] list where an Inactive range |
| 458 // overlaps with the current range. | 467 // overlaps with the current range. |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 524 for (int i = KillsMask.find_first(); i != -1; | 533 for (int i = KillsMask.find_first(); i != -1; |
| 525 i = KillsMask.find_next(i)) { | 534 i = KillsMask.find_next(i)) { |
| 526 Weights[i].setWeight(RegWeight::Inf); | 535 Weights[i].setWeight(RegWeight::Inf); |
| 527 if (PreferReg == i) | 536 if (PreferReg == i) |
| 528 AllowOverlap = false; | 537 AllowOverlap = false; |
| 529 } | 538 } |
| 530 } | 539 } |
| 531 | 540 |
| 532 // Print info about physical register availability. | 541 // Print info about physical register availability. |
| 533 if (Verbose) { | 542 if (Verbose) { |
| 543 Ostream &Str = Ctx->getStrDump(); |
| 534 for (SizeT i = 0; i < RegMask.size(); ++i) { | 544 for (SizeT i = 0; i < RegMask.size(); ++i) { |
| 535 if (RegMask[i]) { | 545 if (RegMask[i]) { |
| 536 Str << Func->getTarget()->getRegName(i, IceType_i32) | 546 Str << Func->getTarget()->getRegName(i, IceType_i32) |
| 537 << "(U=" << RegUses[i] << ",F=" << Free[i] | 547 << "(U=" << RegUses[i] << ",F=" << Free[i] |
| 538 << ",P=" << PrecoloredUnhandledMask[i] << ") "; | 548 << ",P=" << PrecoloredUnhandledMask[i] << ") "; |
| 539 } | 549 } |
| 540 } | 550 } |
| 541 Str << "\n"; | 551 Str << "\n"; |
| 542 } | 552 } |
| 543 | 553 |
| 544 if (Prefer && (AllowOverlap || Free[PreferReg])) { | 554 if (Prefer && (AllowOverlap || Free[PreferReg])) { |
| 545 // First choice: a preferred register that is either free or is | 555 // First choice: a preferred register that is either free or is |
| 546 // allowed to overlap with its linked variable. | 556 // allowed to overlap with its linked variable. |
| 547 Cur->setRegNumTmp(PreferReg); | 557 Cur->setRegNumTmp(PreferReg); |
| 548 if (Verbose) { | 558 if (Verbose) { |
| 559 Ostream &Str = Ctx->getStrDump(); |
| 549 Str << "Preferring "; | 560 Str << "Preferring "; |
| 550 dumpLiveRange(Cur, Func); | 561 dumpLiveRange(Cur, Func); |
| 551 Str << "\n"; | 562 Str << "\n"; |
| 552 } | 563 } |
| 553 assert(RegUses[PreferReg] >= 0); | 564 assert(RegUses[PreferReg] >= 0); |
| 554 ++RegUses[PreferReg]; | 565 ++RegUses[PreferReg]; |
| 555 Active.push_back(Cur); | 566 Active.push_back(Cur); |
| 556 } else if (Free.any()) { | 567 } else if (Free.any()) { |
| 557 // Second choice: any free register. TODO: After explicit | 568 // Second choice: any free register. TODO: After explicit |
| 558 // affinity is considered, is there a strategy better than just | 569 // affinity is considered, is there a strategy better than just |
| 559 // picking the lowest-numbered available register? | 570 // picking the lowest-numbered available register? |
| 560 int32_t RegNum = Free.find_first(); | 571 int32_t RegNum = Free.find_first(); |
| 561 Cur->setRegNumTmp(RegNum); | 572 Cur->setRegNumTmp(RegNum); |
| 562 if (Verbose) { | 573 if (Verbose) { |
| 574 Ostream &Str = Ctx->getStrDump(); |
| 563 Str << "Allocating "; | 575 Str << "Allocating "; |
| 564 dumpLiveRange(Cur, Func); | 576 dumpLiveRange(Cur, Func); |
| 565 Str << "\n"; | 577 Str << "\n"; |
| 566 } | 578 } |
| 567 assert(RegUses[RegNum] >= 0); | 579 assert(RegUses[RegNum] >= 0); |
| 568 ++RegUses[RegNum]; | 580 ++RegUses[RegNum]; |
| 569 Active.push_back(Cur); | 581 Active.push_back(Cur); |
| 570 } else { | 582 } else { |
| 571 // Fallback: there are no free registers, so we look for the | 583 // Fallback: there are no free registers, so we look for the |
| 572 // lowest-weight register and see if Cur has higher weight. | 584 // lowest-weight register and see if Cur has higher weight. |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 606 "infinite-weight live range"); | 618 "infinite-weight live range"); |
| 607 } | 619 } |
| 608 } else { | 620 } else { |
| 609 // Evict all live ranges in Active that register number | 621 // Evict all live ranges in Active that register number |
| 610 // MinWeightIndex is assigned to. | 622 // MinWeightIndex is assigned to. |
| 611 for (SizeT I = Active.size(); I > 0; --I) { | 623 for (SizeT I = Active.size(); I > 0; --I) { |
| 612 const SizeT Index = I - 1; | 624 const SizeT Index = I - 1; |
| 613 Variable *Item = Active[Index]; | 625 Variable *Item = Active[Index]; |
| 614 if (Item->getRegNumTmp() == MinWeightIndex) { | 626 if (Item->getRegNumTmp() == MinWeightIndex) { |
| 615 if (Verbose) { | 627 if (Verbose) { |
| 628 Ostream &Str = Ctx->getStrDump(); |
| 616 Str << "Evicting "; | 629 Str << "Evicting "; |
| 617 dumpLiveRange(Item, Func); | 630 dumpLiveRange(Item, Func); |
| 618 Str << "\n"; | 631 Str << "\n"; |
| 619 } | 632 } |
| 620 --RegUses[MinWeightIndex]; | 633 --RegUses[MinWeightIndex]; |
| 621 assert(RegUses[MinWeightIndex] >= 0); | 634 assert(RegUses[MinWeightIndex] >= 0); |
| 622 Item->setRegNumTmp(Variable::NoRegister); | 635 Item->setRegNumTmp(Variable::NoRegister); |
| 623 moveItem(Active, Index, Handled); | 636 moveItem(Active, Index, Handled); |
| 624 } | 637 } |
| 625 } | 638 } |
| 626 // Do the same for Inactive. | 639 // Do the same for Inactive. |
| 627 for (SizeT I = Inactive.size(); I > 0; --I) { | 640 for (SizeT I = Inactive.size(); I > 0; --I) { |
| 628 const SizeT Index = I - 1; | 641 const SizeT Index = I - 1; |
| 629 Variable *Item = Inactive[Index]; | 642 Variable *Item = Inactive[Index]; |
| 630 // Note: The Item->rangeOverlaps(Cur) clause is not part of the | 643 // Note: The Item->rangeOverlaps(Cur) clause is not part of the |
| 631 // description of AssignMemLoc() in the original paper. But | 644 // description of AssignMemLoc() in the original paper. But |
| 632 // there doesn't seem to be any need to evict an inactive | 645 // there doesn't seem to be any need to evict an inactive |
| 633 // live range that doesn't overlap with the live range | 646 // live range that doesn't overlap with the live range |
| 634 // currently being considered. It's especially bad if we | 647 // currently being considered. It's especially bad if we |
| 635 // would end up evicting an infinite-weight but | 648 // would end up evicting an infinite-weight but |
| 636 // currently-inactive live range. The most common situation | 649 // currently-inactive live range. The most common situation |
| 637 // for this would be a scratch register kill set for call | 650 // for this would be a scratch register kill set for call |
| 638 // instructions. | 651 // instructions. |
| 639 if (Item->getRegNumTmp() == MinWeightIndex && | 652 if (Item->getRegNumTmp() == MinWeightIndex && |
| 640 Item->rangeOverlaps(Cur)) { | 653 Item->rangeOverlaps(Cur)) { |
| 641 if (Verbose) { | 654 if (Verbose) { |
| 655 Ostream &Str = Ctx->getStrDump(); |
| 642 Str << "Evicting "; | 656 Str << "Evicting "; |
| 643 dumpLiveRange(Item, Func); | 657 dumpLiveRange(Item, Func); |
| 644 Str << "\n"; | 658 Str << "\n"; |
| 645 } | 659 } |
| 646 Item->setRegNumTmp(Variable::NoRegister); | 660 Item->setRegNumTmp(Variable::NoRegister); |
| 647 moveItem(Inactive, Index, Handled); | 661 moveItem(Inactive, Index, Handled); |
| 648 } | 662 } |
| 649 } | 663 } |
| 650 // Assign the register to Cur. | 664 // Assign the register to Cur. |
| 651 Cur->setRegNumTmp(MinWeightIndex); | 665 Cur->setRegNumTmp(MinWeightIndex); |
| 652 assert(RegUses[MinWeightIndex] >= 0); | 666 assert(RegUses[MinWeightIndex] >= 0); |
| 653 ++RegUses[MinWeightIndex]; | 667 ++RegUses[MinWeightIndex]; |
| 654 Active.push_back(Cur); | 668 Active.push_back(Cur); |
| 655 if (Verbose) { | 669 if (Verbose) { |
| 670 Ostream &Str = Ctx->getStrDump(); |
| 656 Str << "Allocating "; | 671 Str << "Allocating "; |
| 657 dumpLiveRange(Cur, Func); | 672 dumpLiveRange(Cur, Func); |
| 658 Str << "\n"; | 673 Str << "\n"; |
| 659 } | 674 } |
| 660 } | 675 } |
| 661 } | 676 } |
| 662 dump(Func); | 677 dump(Func); |
| 663 } | 678 } |
| 664 // Move anything Active or Inactive to Handled for easier handling. | 679 // Move anything Active or Inactive to Handled for easier handling. |
| 665 for (Variable *I : Active) | 680 for (Variable *I : Active) |
| (...skipping 13 matching lines...) Expand all Loading... |
| 679 // Finish up by assigning RegNumTmp->RegNum (or a random permutation | 694 // Finish up by assigning RegNumTmp->RegNum (or a random permutation |
| 680 // thereof) for each Variable. | 695 // thereof) for each Variable. |
| 681 for (Variable *Item : Handled) { | 696 for (Variable *Item : Handled) { |
| 682 int32_t RegNum = Item->getRegNumTmp(); | 697 int32_t RegNum = Item->getRegNumTmp(); |
| 683 int32_t AssignedRegNum = RegNum; | 698 int32_t AssignedRegNum = RegNum; |
| 684 | 699 |
| 685 if (Randomized && Item->hasRegTmp() && !Item->hasReg()) { | 700 if (Randomized && Item->hasRegTmp() && !Item->hasReg()) { |
| 686 AssignedRegNum = Permutation[RegNum]; | 701 AssignedRegNum = Permutation[RegNum]; |
| 687 } | 702 } |
| 688 if (Verbose) { | 703 if (Verbose) { |
| 704 Ostream &Str = Ctx->getStrDump(); |
| 689 if (!Item->hasRegTmp()) { | 705 if (!Item->hasRegTmp()) { |
| 690 Str << "Not assigning "; | 706 Str << "Not assigning "; |
| 691 Item->dump(Func); | 707 Item->dump(Func); |
| 692 Str << "\n"; | 708 Str << "\n"; |
| 693 } else { | 709 } else { |
| 694 Str << (AssignedRegNum == Item->getRegNum() ? "Reassigning " | 710 Str << (AssignedRegNum == Item->getRegNum() ? "Reassigning " |
| 695 : "Assigning ") | 711 : "Assigning ") |
| 696 << Func->getTarget()->getRegName(AssignedRegNum, IceType_i32) | 712 << Func->getTarget()->getRegName(AssignedRegNum, IceType_i32) |
| 697 << "(r" << AssignedRegNum << ") to "; | 713 << "(r" << AssignedRegNum << ") to "; |
| 698 Item->dump(Func); | 714 Item->dump(Func); |
| 699 Str << "\n"; | 715 Str << "\n"; |
| 700 } | 716 } |
| 701 } | 717 } |
| 702 Item->setRegNum(AssignedRegNum); | 718 Item->setRegNum(AssignedRegNum); |
| 703 } | 719 } |
| 704 | 720 |
| 705 // TODO: Consider running register allocation one more time, with | 721 // TODO: Consider running register allocation one more time, with |
| 706 // infinite registers, for two reasons. First, evicted live ranges | 722 // infinite registers, for two reasons. First, evicted live ranges |
| 707 // get a second chance for a register. Second, it allows coalescing | 723 // get a second chance for a register. Second, it allows coalescing |
| 708 // of stack slots. If there is no time budget for the second | 724 // of stack slots. If there is no time budget for the second |
| 709 // register allocation run, each unallocated variable just gets its | 725 // register allocation run, each unallocated variable just gets its |
| 710 // own slot. | 726 // own slot. |
| 711 // | 727 // |
| 712 // Another idea for coalescing stack slots is to initialize the | 728 // Another idea for coalescing stack slots is to initialize the |
| 713 // Unhandled list with just the unallocated variables, saving time | 729 // Unhandled list with just the unallocated variables, saving time |
| 714 // but not offering second-chance opportunities. | 730 // but not offering second-chance opportunities. |
| 731 |
| 732 if (Verbose) |
| 733 Ctx->unlockStr(); |
| 715 } | 734 } |
| 716 | 735 |
| 717 // ======================== Dump routines ======================== // | 736 // ======================== Dump routines ======================== // |
| 718 | 737 |
| 719 void LinearScan::dump(Cfg *Func) const { | 738 void LinearScan::dump(Cfg *Func) const { |
| 720 if (!ALLOW_DUMP) | 739 if (!ALLOW_DUMP) |
| 721 return; | 740 return; |
| 722 Ostream &Str = Func->getContext()->getStrDump(); | |
| 723 if (!Func->getContext()->isVerbose(IceV_LinearScan)) | 741 if (!Func->getContext()->isVerbose(IceV_LinearScan)) |
| 724 return; | 742 return; |
| 743 Ostream &Str = Func->getContext()->getStrDump(); |
| 725 Func->resetCurrentNode(); | 744 Func->resetCurrentNode(); |
| 726 Str << "**** Current regalloc state:\n"; | 745 Str << "**** Current regalloc state:\n"; |
| 727 Str << "++++++ Handled:\n"; | 746 Str << "++++++ Handled:\n"; |
| 728 for (const Variable *Item : Handled) { | 747 for (const Variable *Item : Handled) { |
| 729 dumpLiveRange(Item, Func); | 748 dumpLiveRange(Item, Func); |
| 730 Str << "\n"; | 749 Str << "\n"; |
| 731 } | 750 } |
| 732 Str << "++++++ Unhandled:\n"; | 751 Str << "++++++ Unhandled:\n"; |
| 733 for (const Variable *Item : reverse_range(Unhandled)) { | 752 for (const Variable *Item : reverse_range(Unhandled)) { |
| 734 dumpLiveRange(Item, Func); | 753 dumpLiveRange(Item, Func); |
| 735 Str << "\n"; | 754 Str << "\n"; |
| 736 } | 755 } |
| 737 Str << "++++++ Active:\n"; | 756 Str << "++++++ Active:\n"; |
| 738 for (const Variable *Item : Active) { | 757 for (const Variable *Item : Active) { |
| 739 dumpLiveRange(Item, Func); | 758 dumpLiveRange(Item, Func); |
| 740 Str << "\n"; | 759 Str << "\n"; |
| 741 } | 760 } |
| 742 Str << "++++++ Inactive:\n"; | 761 Str << "++++++ Inactive:\n"; |
| 743 for (const Variable *Item : Inactive) { | 762 for (const Variable *Item : Inactive) { |
| 744 dumpLiveRange(Item, Func); | 763 dumpLiveRange(Item, Func); |
| 745 Str << "\n"; | 764 Str << "\n"; |
| 746 } | 765 } |
| 747 } | 766 } |
| 748 | 767 |
| 749 } // end of namespace Ice | 768 } // end of namespace Ice |
| OLD | NEW |