Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(17)

Unified Diff: src/IceRegAlloc.cpp

Issue 597003004: Subzero: Automatically infer regalloc preferences and overlap. (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: Code review changes Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/IceOperand.cpp ('k') | src/IceTargetLoweringX8632.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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);
« no previous file with comments | « src/IceOperand.cpp ('k') | src/IceTargetLoweringX8632.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698