| Index: src/IceRegAlloc.cpp
|
| diff --git a/src/IceRegAlloc.cpp b/src/IceRegAlloc.cpp
|
| index f79e8dcc7be4565327188990f51cd72a1a22f09a..36ada129b3d6611fedc44e55ad01ee1cb54e16ca 100644
|
| --- a/src/IceRegAlloc.cpp
|
| +++ b/src/IceRegAlloc.cpp
|
| @@ -21,6 +21,37 @@
|
|
|
| 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) {
|
| + const InstDefList &Defs = Func->getVMetadata()->getDefinitions(Var);
|
| + for (size_t i = 0; i < Defs.size(); ++i) {
|
| + if (Item.range().overlaps(Defs[i]->getNumber()))
|
| + return true;
|
| + }
|
| + return false;
|
| +}
|
| +
|
| +void dumpDisableOverlap(const Cfg *Func, const Variable *Var,
|
| + const char *Reason) {
|
| + if (Func->getContext()->isVerbose(IceV_LinearScan)) {
|
| + Ostream &Str = Func->getContext()->getStrDump();
|
| + Str << "Disabling Overlap due to " << Reason << " " << *Var
|
| + << " LIVE=" << Var->getLiveRange() << " Defs=";
|
| + const InstDefList &Defs = Func->getVMetadata()->getDefinitions(Var);
|
| + for (size_t i = 0; i < Defs.size(); ++i) {
|
| + if (i > 0)
|
| + Str << ",";
|
| + Str << Defs[i]->getNumber();
|
| + }
|
| + Str << "\n";
|
| + }
|
| +}
|
| +
|
| +} // 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 +71,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 +217,58 @@ 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;
|
| + int32_t PreferReg = Variable::NoRegister;
|
| + bool AllowOverlap = false;
|
| + if (const Inst *DefInst = VMetadata->getFirstDefinition(Cur.Var)) {
|
| + assert(DefInst->getDest() == Cur.Var);
|
| + bool IsAssign = DefInst->isSimpleAssign();
|
| + bool IsSingleDef = !VMetadata->isMultiDef(Cur.Var);
|
| + for (SizeT i = 0; i < DefInst->getSrcSize(); ++i) {
|
| + // TODO(stichnot): Iterate through the actual Variables of the
|
| + // instruction, not just the source operands. This could
|
| + // capture Load instructions, including address mode
|
| + // optimization, for Prefer (but not for AllowOverlap).
|
| + if (Variable *SrcVar = llvm::dyn_cast<Variable>(DefInst->getSrc(i))) {
|
| + int32_t SrcReg = SrcVar->getRegNumTmp();
|
| + // Only consider source variables that have (so far) been
|
| + // assigned a register. That register must be one in the
|
| + // RegMask set, e.g. don't try to prefer the stack pointer
|
| + // as a result of the stacksave intrinsic.
|
| + if (SrcVar->hasRegTmp() && RegMask[SrcReg]) {
|
| + if (!Free[SrcReg]) {
|
| + // Don't bother trying to enable AllowOverlap if the
|
| + // register is already free.
|
| + AllowOverlap =
|
| + IsSingleDef && IsAssign && !overlapsDefs(Func, Cur, SrcVar);
|
| + }
|
| + if (AllowOverlap || Free[SrcReg]) {
|
| + Prefer = SrcVar;
|
| + PreferReg = SrcReg;
|
| + }
|
| + }
|
| + }
|
| + }
|
| + }
|
| + if (Func->getContext()->isVerbose(IceV_LinearScan)) {
|
| + if (Prefer) {
|
| + Str << "Initial Prefer=" << *Prefer << " R=" << PreferReg
|
| + << " LIVE=" << Prefer->getLiveRange() << " Overlap=" << AllowOverlap
|
| + << "\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 +282,28 @@ void LinearScan::scan(const llvm::SmallBitVector &RegMaskFull) {
|
| // variables that were allowed marked with
|
| // AllowRegisterOverlap.
|
| Free[RegNum] = false;
|
| + // Disable AllowOverlap if an Inactive variable, which is not
|
| + // Prefer, shares Prefer's register, and has a definition
|
| + // within Cur's live range.
|
| + if (AllowOverlap && Item.Var != Prefer && RegNum == PreferReg &&
|
| + overlapsDefs(Func, Cur, Item.Var)) {
|
| + AllowOverlap = false;
|
| + dumpDisableOverlap(Func, Item.Var, "Inactive");
|
| + }
|
| + }
|
| + }
|
| +
|
| + // Disable AllowOverlap if an Active variable, which is not
|
| + // Prefer, shares Prefer's register, and has a definition within
|
| + // Cur's live range.
|
| + for (UnorderedRanges::iterator I = Active.begin(), E = Active.end();
|
| + AllowOverlap && I != E; ++I) {
|
| + LiveRangeWrapper Item = *I;
|
| + int32_t RegNum = Item.Var->getRegNumTmp();
|
| + if (Item.Var != Prefer && RegNum == PreferReg &&
|
| + overlapsDefs(Func, Cur, Item.Var)) {
|
| + AllowOverlap = false;
|
| + dumpDisableOverlap(Func, Item.Var, "Active");
|
| }
|
| }
|
|
|
| @@ -206,13 +312,21 @@ void LinearScan::scan(const llvm::SmallBitVector &RegMaskFull) {
|
| // Cur.endsBefore(*I) is an early exit check that turns a
|
| // guaranteed O(N^2) algorithm into expected linear complexity.
|
| llvm::SmallBitVector PrecoloredUnhandled(RegMask.size());
|
| + // Note: PrecoloredUnhandled is only used for dumping.
|
| for (OrderedRanges::const_iterator I = Unhandled.begin(),
|
| E = Unhandled.end();
|
| I != E && !Cur.endsBefore(*I); ++I) {
|
| LiveRangeWrapper Item = *I;
|
| if (Item.Var->hasReg() && Item.overlaps(Cur)) {
|
| - Free[Item.Var->getRegNum()] = false; // Note: getRegNum not getRegNumTmp
|
| - PrecoloredUnhandled[Item.Var->getRegNum()] = true;
|
| + int32_t ItemReg = Item.Var->getRegNum(); // Note: not getRegNumTmp()
|
| + Free[ItemReg] = false;
|
| + PrecoloredUnhandled[ItemReg] = true;
|
| + // Disable AllowOverlap if the preferred register is one of
|
| + // these precolored unhandled overlapping ranges.
|
| + if (AllowOverlap && ItemReg == PreferReg) {
|
| + AllowOverlap = false;
|
| + dumpDisableOverlap(Func, Item.Var, "PrecoloredUnhandled");
|
| + }
|
| }
|
| }
|
|
|
| @@ -228,15 +342,7 @@ 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];
|
| - if (PreferReg != Variable::NoRegister &&
|
| - (AllowedToOverlap || Free[PreferReg])) {
|
| + if (Prefer && (AllowOverlap || Free[PreferReg])) {
|
| // First choice: a preferred register that is either free or is
|
| // allowed to overlap with its linked variable.
|
| Cur.Var->setRegNumTmp(PreferReg);
|
|
|