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 |