Chromium Code Reviews| Index: src/IceRegAlloc.cpp |
| diff --git a/src/IceRegAlloc.cpp b/src/IceRegAlloc.cpp |
| index f79e8dcc7be4565327188990f51cd72a1a22f09a..bc1bf4f01436566a15b9a4923c8f2583f5283eea 100644 |
| --- a/src/IceRegAlloc.cpp |
| +++ b/src/IceRegAlloc.cpp |
| @@ -21,6 +21,22 @@ |
| namespace Ice { |
| +namespace { |
| + |
| +// Returns true if Var has any definitions within Item's live range. |
| +bool overlapsDefs(const Cfg *Func, const LiveRangeWrapper &Item, |
| + const Variable *Var) { |
| + VariablesMetadata *VMetadata = Func->getVMetadata(); |
| + const InstDefList &Defs = VMetadata->getDefinitions(Var); |
| + for (size_t i = 0; i < Defs.size(); ++i) { |
| + if (Item.range().overlaps(Defs[i]->getNumber())) |
| + return true; |
| + } |
| + return false; |
| +} |
| + |
| +} // end of anonymous namespace |
| + |
| // Implements the linear-scan algorithm. Based on "Linear Scan |
| // Register Allocation in the Context of SSA Form and Register |
| // Constraints" by Hanspeter Mössenböck and Michael Pfeiffer, |
| @@ -40,6 +56,7 @@ void LinearScan::scan(const llvm::SmallBitVector &RegMaskFull) { |
| Active.clear(); |
| Ostream &Str = Func->getContext()->getStrDump(); |
| Func->resetCurrentNode(); |
| + VariablesMetadata *VMetadata = Func->getVMetadata(); |
| // Gather the live ranges of all variables and add them to the |
| // Unhandled set. TODO: Unhandled is a set<> which is based on a |
| @@ -185,6 +202,47 @@ void LinearScan::scan(const llvm::SmallBitVector &RegMaskFull) { |
| Free[i] = false; |
| } |
| + // Infer register preference and allowable overlap. Only form a |
| + // preference when the current Variable has an unambiguous "first" |
| + // definition. The preference is some source Variable of the |
| + // defining instruction that either is assigned a register that is |
| + // currently free, or that is assigned a register that is not free |
| + // but overlap is allowed. Overlap is allowed when the Variable |
| + // under consideration is single-definition, and its definition is |
| + // a simple assignment - i.e., the register gets copied/aliased |
| + // but is never modified. Furthermore, overlap is only allowed |
| + // when preferred Variable definition instructions do not appear |
| + // within the current Variable's live range. |
| + Variable *Prefer = NULL; |
| + bool AllowedToOverlap = false; |
| + if (const Inst *DefInst = VMetadata->getSingleDefinition(Cur.Var)) { |
|
jvoung (off chromium)
2014/09/25 16:42:11
Was this meant to be getFirstDefinition() (based o
Jim Stichnoth
2014/09/25 18:13:55
Yeah, fixed.
|
| + assert(DefInst->getDest() == Cur.Var); |
| + bool IsAssign = DefInst->isSimpleAssign(); |
| + bool IsSingleDef = !VMetadata->isMultiDef(Cur.Var); |
| + for (SizeT i = 0; i < DefInst->getSrcSize(); ++i) { |
| + if (Variable *SrcVar = llvm::dyn_cast<Variable>(DefInst->getSrc(i))) { |
| + // The NoConflictingDefs condition is supposed to accurately |
| + // represent this requirement: "overlap is only allowed when |
| + // preferred Variable definition instructions do not appear |
| + // within the current Variable's live range." |
| + bool NoConflictingDefs = !overlapsDefs(Func, Cur, SrcVar); |
| + int32_t SrcReg = SrcVar->getRegNumTmp(); |
| + if (SrcReg != Variable::NoRegister && RegMask[SrcReg]) { |
|
jvoung (off chromium)
2014/09/25 16:42:11
Would it be better to check SrcReg != Variable::No
Jim Stichnoth
2014/09/25 18:13:55
Yes. That should be fixed in the latest patchset.
|
| + AllowedToOverlap = IsSingleDef && NoConflictingDefs && IsAssign; |
| + if (AllowedToOverlap || Free[SrcReg]) |
|
jvoung (off chromium)
2014/09/25 16:42:11
Similar, would it be cheaper to check for Free[Src
Jim Stichnoth
2014/09/25 18:13:55
Hmm, I think you're right. The logs do show a lot
|
| + Prefer = SrcVar; |
| + } |
| + } |
| + } |
| + } |
| + if (Func->getContext()->isVerbose(IceV_LinearScan)) { |
| + if (Prefer) { |
| + Str << "Initial Prefer=" << *Prefer << " R=" << Prefer->getRegNumTmp() |
| + << " LIVE=" << Prefer->getLiveRange() |
| + << " Overlap=" << AllowedToOverlap << "\n"; |
| + } |
| + } |
| + |
| // Remove registers from the Free[] list where an Inactive range |
| // overlaps with the current range. |
| for (UnorderedRanges::const_iterator I = Inactive.begin(), |
| @@ -198,6 +256,40 @@ void LinearScan::scan(const llvm::SmallBitVector &RegMaskFull) { |
| // variables that were allowed marked with |
| // AllowRegisterOverlap. |
| Free[RegNum] = false; |
| + // If there is a variable on the inactive list, which is not |
| + // Prefer, and overlaps with Cur, and shares Prefer's |
| + // register, then disallow overlap. |
| + if (AllowedToOverlap && Item.Var != Prefer && |
| + RegNum == Prefer->getRegNumTmp() && Item.overlaps(Cur)) { |
| + AllowedToOverlap = false; |
| + if (Func->getContext()->isVerbose(IceV_LinearScan)) { |
| + Str << "Disabling Overlap due to Inactive " << *Item.Var |
| + << " LIVE=" << Item.Var->getLiveRange() << "\n"; |
| + } |
| + } |
| + } |
| + } |
| + |
| + // Disable AllowOverlap if the preferred register is already used |
| + // in an Active range (which by definition overlaps) that is not |
| + // Prefer. TODO(stichnot): Actually only disable AllowOverlap if |
| + // an Active variable with the preferred register has a definition |
| + // within the current variable's live range. |
| + |
| + // If there is a variable on the active list, which is not Prefer, |
| + // and shares Prefer's register, and has a definition within Cur's |
| + // live range, then disallow overlap. |
| + for (UnorderedRanges::iterator I = Active.begin(), E = Active.end(); |
| + AllowedToOverlap && I != E; ++I) { |
| + LiveRangeWrapper Item = *I; |
| + int32_t RegNum = Item.Var->getRegNumTmp(); |
| + if (Item.Var != Prefer && RegNum == Prefer->getRegNumTmp() && |
| + overlapsDefs(Func, Cur, Item.Var)) { |
| + AllowedToOverlap = false; |
| + if (Func->getContext()->isVerbose(IceV_LinearScan)) { |
| + Str << "Disabling Overlap due to Active " << *Item.Var |
| + << " LIVE=" << Item.Var->getLiveRange() << "\n"; |
| + } |
| } |
| } |
| @@ -213,6 +305,17 @@ void LinearScan::scan(const llvm::SmallBitVector &RegMaskFull) { |
| if (Item.Var->hasReg() && Item.overlaps(Cur)) { |
| Free[Item.Var->getRegNum()] = false; // Note: getRegNum not getRegNumTmp |
| PrecoloredUnhandled[Item.Var->getRegNum()] = true; |
| + // Disallow overlap if the preferred register is one of these |
| + // precolored unhandled overlapping ranges. |
| + if (AllowedToOverlap && Prefer && |
|
jvoung (off chromium)
2014/09/25 16:42:11
nit: I think technically, the "&& Prefer" check is
Jim Stichnoth
2014/09/25 18:13:54
Done. I think I originally had that just to be ab
|
| + Item.Var->getRegNum() == Prefer->getRegNumTmp() && |
| + Cur.overlaps(Item)) { |
| + AllowedToOverlap = false; |
| + if (Func->getContext()->isVerbose(IceV_LinearScan)) { |
| + Str << "Disabling Overlap due to UnhandledPrecolored " << *Item.Var |
| + << " LIVE=" << Item.Var->getLiveRange() << "\n"; |
| + } |
| + } |
| } |
| } |
| @@ -228,13 +331,9 @@ void LinearScan::scan(const llvm::SmallBitVector &RegMaskFull) { |
| Str << "\n"; |
| } |
| - Variable *Prefer = Cur.Var->getPreferredRegister(); |
| - int32_t PreferReg = Prefer && Prefer->hasRegTmp() ? Prefer->getRegNumTmp() |
| - : Variable::NoRegister; |
| - bool AllowedToOverlap = Cur.Var->getRegisterOverlap() && |
| - PreferReg != Variable::NoRegister && |
| - RegMask[PreferReg] && |
| - !PrecoloredUnhandled[PreferReg]; |
|
jvoung (off chromium)
2014/09/25 16:42:11
It now seems like PrecoloredUnhandled is no longer
Jim Stichnoth
2014/09/25 18:13:54
True. It's worth keeping for the diagnostics, so
|
| + int32_t PreferReg = Variable::NoRegister; |
| + if (Prefer && Prefer->hasRegTmp()) |
| + PreferReg = Prefer->getRegNumTmp(); |
| if (PreferReg != Variable::NoRegister && |
| (AllowedToOverlap || Free[PreferReg])) { |
| // First choice: a preferred register that is either free or is |