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 475 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
486 void LinearScan::findRegisterPreference(IterationState &Iter) { | 486 void LinearScan::findRegisterPreference(IterationState &Iter) { |
487 Iter.Prefer = nullptr; | 487 Iter.Prefer = nullptr; |
488 Iter.PreferReg = Variable::NoRegister; | 488 Iter.PreferReg = Variable::NoRegister; |
489 Iter.AllowOverlap = false; | 489 Iter.AllowOverlap = false; |
490 | 490 |
491 if (FindPreference) { | 491 if (FindPreference) { |
492 VariablesMetadata *VMetadata = Func->getVMetadata(); | 492 VariablesMetadata *VMetadata = Func->getVMetadata(); |
493 if (const Inst *DefInst = | 493 if (const Inst *DefInst = |
494 VMetadata->getFirstDefinitionSingleBlock(Iter.Cur)) { | 494 VMetadata->getFirstDefinitionSingleBlock(Iter.Cur)) { |
495 assert(DefInst->getDest() == Iter.Cur); | 495 assert(DefInst->getDest() == Iter.Cur); |
496 bool IsAssign = DefInst->isSimpleAssign(); | 496 bool IsAssign = DefInst->isVarAssign(); |
497 bool IsSingleDef = !VMetadata->isMultiDef(Iter.Cur); | 497 bool IsSingleDef = !VMetadata->isMultiDef(Iter.Cur); |
498 for (SizeT i = 0; i < DefInst->getSrcSize(); ++i) { | 498 FOREACH_VAR_IN_INST(SrcVar, *DefInst) { |
499 // TODO(stichnot): Iterate through the actual Variables of the | 499 int32_t SrcReg = SrcVar->getRegNumTmp(); |
500 // instruction, not just the source operands. This could capture Load | 500 // Only consider source variables that have (so far) been assigned a |
501 // instructions, including address mode optimization, for Prefer (but | 501 // register. That register must be one in the RegMask set, e.g. don't |
502 // not for AllowOverlap). | 502 // try to prefer the stack pointer as a result of the stacksave |
503 if (Variable *SrcVar = llvm::dyn_cast<Variable>(DefInst->getSrc(i))) { | 503 // intrinsic. |
504 int32_t SrcReg = SrcVar->getRegNumTmp(); | 504 if (SrcVar->hasRegTmp() && (Iter.RegMask & *RegAliases[SrcReg]).any()) { |
John
2015/10/12 15:35:17
this is super hard to read!!!
const bool SrcVarRe
Jim Stichnoth
2015/10/12 17:27:31
Done. Note that I want to put the cheap hasRegTmp
John
2015/10/12 20:39:58
Then you can define a static method (in an unnamed
| |
505 // Only consider source variables that have (so far) been assigned a | 505 if (FindOverlap && !Iter.Free[SrcReg]) { |
506 // register. That register must be one in the RegMask set, e.g. don't | 506 // Don't bother trying to enable AllowOverlap if the register is |
507 // try to prefer the stack pointer as a result of the stacksave | 507 // already free. |
508 // intrinsic. | 508 Iter.AllowOverlap = IsSingleDef && IsAssign && |
509 if (SrcVar->hasRegTmp() && Iter.RegMask[SrcReg]) { | 509 !overlapsDefs(Func, Iter.Cur, SrcVar); |
510 if (FindOverlap && !Iter.Free[SrcReg]) { | 510 } |
511 // Don't bother trying to enable AllowOverlap if the register is | 511 if (Iter.AllowOverlap || Iter.Free[SrcReg]) { |
512 // already free. | 512 Iter.Prefer = SrcVar; |
513 Iter.AllowOverlap = IsSingleDef && IsAssign && | 513 Iter.PreferReg = SrcReg; |
514 !overlapsDefs(Func, Iter.Cur, SrcVar); | 514 // Stop looking for a preference after the first valid preference is |
515 } | 515 // found. One might think that we should look at all instruction |
516 if (Iter.AllowOverlap || Iter.Free[SrcReg]) { | 516 // variables to find the best <Prefer,AllowOverlap> combination, but |
517 Iter.Prefer = SrcVar; | 517 // note that AllowOverlap can only be true for a simple assignment |
518 Iter.PreferReg = SrcReg; | 518 // statement which can have only one source operand, so it's not |
519 } | 519 // possible for AllowOverlap to be true beyond the first source |
520 // operand. | |
521 break; | |
520 } | 522 } |
521 } | 523 } |
522 } | 524 } |
523 if (Verbose && Iter.Prefer) { | 525 if (Verbose && Iter.Prefer) { |
524 Ostream &Str = Ctx->getStrDump(); | 526 Ostream &Str = Ctx->getStrDump(); |
525 Str << "Initial Iter.Prefer="; | 527 Str << "Initial Iter.Prefer="; |
526 Iter.Prefer->dump(Func); | 528 Iter.Prefer->dump(Func); |
527 Str << " R=" << Iter.PreferReg | 529 Str << " R=" << Iter.PreferReg |
528 << " LIVE=" << Iter.Prefer->getLiveRange() | 530 << " LIVE=" << Iter.Prefer->getLiveRange() |
529 << " Overlap=" << Iter.AllowOverlap << "\n"; | 531 << " Overlap=" << Iter.AllowOverlap << "\n"; |
530 } | 532 } |
531 } | 533 } |
532 } | 534 } |
533 } | 535 } |
534 | 536 |
535 // Remove registers from the Free[] list where an Inactive range overlaps with | 537 // Remove registers from the Free[] list where an Inactive range overlaps with |
536 // the current range. | 538 // the current range. |
537 void LinearScan::filterFreeWithInactiveRanges(IterationState &Iter) { | 539 void LinearScan::filterFreeWithInactiveRanges(IterationState &Iter) { |
538 for (const Variable *Item : Inactive) { | 540 for (const Variable *Item : Inactive) { |
539 if (!Item->rangeOverlaps(Iter.Cur)) | 541 if (!Item->rangeOverlaps(Iter.Cur)) |
540 continue; | 542 continue; |
541 const llvm::SmallBitVector &Aliases = *RegAliases[Item->getRegNumTmp()]; | 543 const llvm::SmallBitVector &Aliases = *RegAliases[Item->getRegNumTmp()]; |
544 // TODO(stichnot): Do this with bitvector ops, not a loop, for efficiency. | |
John
2015/10/12 15:35:17
this is a simple TODOne:
for (int32_t RegAlias =
Jim Stichnoth
2015/10/12 17:27:31
What I mean is, I think it can be changed to somet
| |
542 for (int32_t RegAlias = Aliases.find_first(); RegAlias >= 0; | 545 for (int32_t RegAlias = Aliases.find_first(); RegAlias >= 0; |
543 RegAlias = Aliases.find_next(RegAlias)) { | 546 RegAlias = Aliases.find_next(RegAlias)) { |
544 // Don't assert(Free[RegNum]) because in theory (though probably never in | 547 // Don't assert(Free[RegNum]) because in theory (though probably never in |
545 // practice) there could be two inactive variables that were marked with | 548 // practice) there could be two inactive variables that were marked with |
546 // AllowOverlap. | 549 // AllowOverlap. |
547 Iter.Free[RegAlias] = false; | 550 Iter.Free[RegAlias] = false; |
548 // Disable AllowOverlap if an Inactive variable, which is not Prefer, | 551 // Disable AllowOverlap if an Inactive variable, which is not Prefer, |
549 // shares Prefer's register, and has a definition within Cur's live | 552 // shares Prefer's register, and has a definition within Cur's live |
550 // range. | 553 // range. |
551 if (Iter.AllowOverlap && Item != Iter.Prefer && | 554 if (Iter.AllowOverlap && Item != Iter.Prefer && |
(...skipping 293 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
845 } | 848 } |
846 | 849 |
847 findRegisterPreference(Iter); | 850 findRegisterPreference(Iter); |
848 filterFreeWithInactiveRanges(Iter); | 851 filterFreeWithInactiveRanges(Iter); |
849 | 852 |
850 // Disable AllowOverlap if an Active variable, which is not Prefer, shares | 853 // Disable AllowOverlap if an Active variable, which is not Prefer, shares |
851 // Prefer's register, and has a definition within Cur's live range. | 854 // Prefer's register, and has a definition within Cur's live range. |
852 if (Iter.AllowOverlap) { | 855 if (Iter.AllowOverlap) { |
853 for (const Variable *Item : Active) { | 856 for (const Variable *Item : Active) { |
854 int32_t RegNum = Item->getRegNumTmp(); | 857 int32_t RegNum = Item->getRegNumTmp(); |
858 // TODO(stichnot): Consider aliases of RegNum. This is probably a | |
859 // correctness issue. | |
John
2015/10/12 15:35:17
This is definitively a correctness issue... :(
Jim Stichnoth
2015/10/12 17:27:31
Yeah, I want to address it in the context of the x
| |
855 if (Item != Iter.Prefer && RegNum == Iter.PreferReg && | 860 if (Item != Iter.Prefer && RegNum == Iter.PreferReg && |
856 overlapsDefs(Func, Iter.Cur, Item)) { | 861 overlapsDefs(Func, Iter.Cur, Item)) { |
857 Iter.AllowOverlap = false; | 862 Iter.AllowOverlap = false; |
858 dumpDisableOverlap(Func, Item, "Active"); | 863 dumpDisableOverlap(Func, Item, "Active"); |
859 } | 864 } |
860 } | 865 } |
861 } | 866 } |
862 | 867 |
863 Iter.Weights.resize(Iter.RegMask.size()); | 868 Iter.Weights.resize(Iter.RegMask.size()); |
864 std::fill(Iter.Weights.begin(), Iter.Weights.end(), RegWeight()); | 869 std::fill(Iter.Weights.begin(), Iter.Weights.end(), RegWeight()); |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
970 Str << "\n"; | 975 Str << "\n"; |
971 } | 976 } |
972 Str << "++++++ Inactive:\n"; | 977 Str << "++++++ Inactive:\n"; |
973 for (const Variable *Item : Inactive) { | 978 for (const Variable *Item : Inactive) { |
974 dumpLiveRange(Item, Func); | 979 dumpLiveRange(Item, Func); |
975 Str << "\n"; | 980 Str << "\n"; |
976 } | 981 } |
977 } | 982 } |
978 | 983 |
979 } // end of namespace Ice | 984 } // end of namespace Ice |
OLD | NEW |