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

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: Remove manual specification of prefer/overlap. 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
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

Powered by Google App Engine
This is Rietveld 408576698