OSDN Git Service

Subzero: Slight improvement to phi lowering.
authorJim Stichnoth <stichnot@chromium.org>
Wed, 5 Aug 2015 23:21:42 +0000 (16:21 -0700)
committerJim Stichnoth <stichnot@chromium.org>
Wed, 5 Aug 2015 23:21:42 +0000 (16:21 -0700)
When doing post phi lowering register allocation, the original code limited register allocation to pre-colored or infinite-weight variables with a non-empty live range within the new edge-split nodes.  This limitation ends up missing some opportunities.  Specifically, when a temporary is introduced to break a dependency cycle, e.g.:
  // a = phi(b)
  // b = phi(a)
  t = a
  a = b
  b = t
then t was always stack-allocated, even if a physical register was available.

In the new design, the RangeMask bitvector specifies which variables should have their live ranges tracked and computed.  For normal liveness analysis, all variables are tracked.  For post phi lowering liveness analysis, all variables created from phi lowering, plus all pre-colored variables, plus all infinite-weight variables, are tracked.

The result is slightly better code quality, and sometimes the frame size is 1 or 2 words smaller.

The hope was to narrow the 10% translation-time degradation in pnacl-llc.pexe compared to the old, hackish way of phi lowering, but that goal still proves to be elusive.

BUG= none
R=jvoung@chromium.org

Review URL: https://codereview.chromium.org/1271923002.

src/IceCfg.cpp
src/IceCfgNode.cpp
src/IceInst.cpp
src/IceLiveness.cpp
src/IceLiveness.h
src/IceRegAlloc.cpp

index 847563c..58d7957 100644 (file)
@@ -273,9 +273,6 @@ void Cfg::advancedPhiLowering() {
       InstNumberT FirstInstNum = getNextInstNumber();
       (*I)->renumberInstructions();
       InstNumberT LastInstNum = getNextInstNumber() - 1;
-      // TODO(stichnot): May be able to speed up liveness and live range
-      // calculation by having it consider only pre-colored or infinite-weight
-      // variables.  Could also simplify LinearScan::initForInfOnly() that way.
       (*I)->liveness(getLiveness());
       (*I)->livenessAddIntervals(getLiveness(), FirstInstNum, LastInstNum);
     }
index f319041..44e9d3e 100644 (file)
@@ -580,6 +580,8 @@ bool CfgNode::liveness(Liveness *Liveness) {
     Live |= Liveness->getLiveIn(Succ);
     // Mark corresponding argument of phis in successor as live.
     for (Inst &I : Succ->Phis) {
+      if (I.isDeleted())
+        continue;
       auto Phi = llvm::dyn_cast<InstPhi>(&I);
       Phi->livenessPhiOperand(Live, this, Liveness);
     }
@@ -698,6 +700,9 @@ void CfgNode::livenessAddIntervals(Liveness *Liveness, InstNumberT FirstInstNum,
     InstNumberT LE = i == i2 ? IEB->second : LastInstNum + 1;
 
     Variable *Var = Liveness->getVariable(i, this);
+    // TODO(stichnot): Push getIgnoreLiveness() into the initialization of
+    // Liveness::RangeMask so that LiveBegin and LiveEnd never even reference
+    // such variables.
     if (!Var->getIgnoreLiveness()) {
       if (LB > LE) {
         Var->addLiveRange(FirstInstNum, LE, 1);
@@ -720,7 +725,8 @@ void CfgNode::livenessAddIntervals(Liveness *Liveness, InstNumberT FirstInstNum,
   for (int i = LiveInAndOut.find_first(); i != -1;
        i = LiveInAndOut.find_next(i)) {
     Variable *Var = Liveness->getVariable(i, this);
-    Var->addLiveRange(FirstInstNum, LastInstNum + 1, 1);
+    if (Liveness->getRangeMask(Var->getIndex()))
+      Var->addLiveRange(FirstInstNum, LastInstNum + 1, 1);
   }
 }
 
index 900b408..4b89eb7 100644 (file)
@@ -183,7 +183,7 @@ bool Inst::liveness(InstNumberT InstNumber, LivenessBV &Live,
     if (Live[VarNum]) {
       if (!isDestNonKillable()) {
         Live[VarNum] = false;
-        if (LiveBegin) {
+        if (LiveBegin && Liveness->getRangeMask(Dest->getIndex())) {
           LiveBegin->push_back(std::make_pair(VarNum, InstNumber));
         }
       }
@@ -223,7 +223,7 @@ bool Inst::liveness(InstNumberT InstNumber, LivenessBV &Live,
           // when LiveEnd[VarNum]==0 (sentinel value).  Note that it's
           // OK to set LiveBegin multiple times because of the
           // backwards traversal.
-          if (LiveEnd) {
+          if (LiveEnd && Liveness->getRangeMask(Var->getIndex())) {
             // Ideally, we would verify that VarNum wasn't already
             // added in this block, but this can't be done very
             // efficiently with LiveEnd as a vector.  Instead,
index da9b23d..a1de893 100644 (file)
@@ -100,6 +100,17 @@ void Liveness::initInternal(NodeList::const_iterator FirstNode,
     // LiveBegin and LiveEnd are reinitialized before each pass over
     // the block.
   }
+
+  // Initialize the bitmask of which variables to track.
+  RangeMask.resize(NumVars);
+  RangeMask.set(0, NumVars);
+  if (!IsFullInit) {
+    // Reset initial variables that are not pre-colored or infinite-weight.
+    for (auto I = Func->getVariables().begin(); I != FirstVar; ++I) {
+      Variable *Var = *I;
+      RangeMask[Var->getIndex()] = (Var->hasReg() || Var->getWeight().isInf());
+    }
+  }
 }
 
 void Liveness::init() {
index da2c52e..895138d 100644 (file)
@@ -96,6 +96,7 @@ public:
     resize(Index);
     return &Nodes[Index].LiveEnd;
   }
+  bool getRangeMask(SizeT Index) const { return RangeMask[Index]; }
 
 private:
   void initInternal(NodeList::const_iterator FirstNode,
@@ -116,6 +117,9 @@ private:
   /// LiveToVarMap is analogous to LivenessNode::LiveToVarMap, but for
   /// non-local variables.
   std::vector<Variable *> LiveToVarMap;
+  /// RangeMask[Variable::Number] indicates whether we want to track that
+  /// Variable's live range.
+  llvm::BitVector RangeMask;
 };
 
 } // end of namespace Ice
index fad3d01..c651ae2 100644 (file)
@@ -107,10 +107,6 @@ void LinearScan::initForGlobal() {
     // it was never referenced.
     if (Var->getLiveRange().isEmpty())
       continue;
-    // Post phi lowering register allocation is only concerned with variables
-    // that are infinite-weight or pre-colored.
-    if (Kind == RAK_Phi && !Var->getWeight().isInf() && !Var->hasReg())
-      continue;
     Var->untrimLiveRange();
     Unhandled.push_back(Var);
     if (Var->hasReg()) {