[llvm-commits] CVS: llvm/lib/CodeGen/SelectionDAG/ScheduleDAGList.cpp

Evan Cheng evan.cheng at apple.com
Tue May 9 00:13:47 PDT 2006



Changes in directory llvm/lib/CodeGen/SelectionDAG:

ScheduleDAGList.cpp updated: 1.55 -> 1.56
---
Log message:

Add pseudo dependency to force a def&use operand to be scheduled last (unless
the distance between the def and another use is much longer). This is under
option control for now "-sched-lower-defnuse".


---
Diffs of the changes:  (+108 -17)

 ScheduleDAGList.cpp |  125 ++++++++++++++++++++++++++++++++++++++++++++--------
 1 files changed, 108 insertions(+), 17 deletions(-)


Index: llvm/lib/CodeGen/SelectionDAG/ScheduleDAGList.cpp
diff -u llvm/lib/CodeGen/SelectionDAG/ScheduleDAGList.cpp:1.55 llvm/lib/CodeGen/SelectionDAG/ScheduleDAGList.cpp:1.56
--- llvm/lib/CodeGen/SelectionDAG/ScheduleDAGList.cpp:1.55	Thu May  4 20:47:05 2006
+++ llvm/lib/CodeGen/SelectionDAG/ScheduleDAGList.cpp	Tue May  9 02:13:34 2006
@@ -35,8 +35,8 @@
 using namespace llvm;
 
 namespace {
-  cl::opt<bool>
-  SchedVertically("sched-vertically", cl::Hidden);
+  cl::opt<bool> SchedVertically("sched-vertically", cl::Hidden);
+  cl::opt<bool> SchedLowerDefNUse("sched-lower-defnuse", cl::Hidden);
 }
 
 namespace {
@@ -198,6 +198,8 @@
   /// of scheduled nodes which are not themselves scheduled.
   std::map<const TargetRegisterClass*, std::set<SUnit*> > OpenNodes;
 
+  /// RegPressureLimits - Keep track of upper limit of register pressure for
+  /// each register class that allows the scheduler to go into vertical mode.
   std::map<const TargetRegisterClass*, unsigned> RegPressureLimits;
 
 public:
@@ -418,7 +420,7 @@
   
   // Build scheduling units.
   BuildSchedUnits();
-  
+
   AvailableQueue->initNodes(SUnits);
   
   // Execute the actual scheduling loop Top-Down or Bottom-Up as appropriate.
@@ -917,6 +919,9 @@
     
     void initNodes(const std::vector<SUnit> &sunits) {
       SUnits = &sunits;
+      // Add pseudo dependency edges for two-address nodes.
+      if (SchedLowerDefNUse)
+        AddPseudoTwoAddrDeps();
       // Calculate node priorities.
       CalculatePriorities();
     }
@@ -968,6 +973,7 @@
     }
 
   private:
+    void AddPseudoTwoAddrDeps();
     void CalculatePriorities();
     int CalcNodePriority(const SUnit *SU);
   };
@@ -993,18 +999,20 @@
   if (RIsFloater)
     RBonus += 2;
 
-  // Special tie breaker: if two nodes share a operand, the one that use it
-  // as a def&use operand is preferred.
-  if (LIsTarget && RIsTarget) {
-    if (left->isTwoAddress && !right->isTwoAddress) {
-      SDNode *DUNode = left->Node->getOperand(0).Val;
-      if (DUNode->isOperand(right->Node))
-        LBonus += 2;
-    }
-    if (!left->isTwoAddress && right->isTwoAddress) {
-      SDNode *DUNode = right->Node->getOperand(0).Val;
-      if (DUNode->isOperand(left->Node))
-        RBonus += 2;
+  if (!SchedLowerDefNUse) {
+    // Special tie breaker: if two nodes share a operand, the one that use it
+    // as a def&use operand is preferred.
+    if (LIsTarget && RIsTarget) {
+      if (left->isTwoAddress && !right->isTwoAddress) {
+        SDNode *DUNode = left->Node->getOperand(0).Val;
+        if (DUNode->isOperand(right->Node))
+          LBonus += 2;
+      }
+      if (!left->isTwoAddress && right->isTwoAddress) {
+        SDNode *DUNode = right->Node->getOperand(0).Val;
+        if (DUNode->isOperand(left->Node))
+          RBonus += 2;
+      }
     }
   }
 
@@ -1019,6 +1027,88 @@
   return false;
 }
 
+static inline bool isCopyFromLiveIn(const SUnit *SU) {
+  SDNode *N = SU->Node;
+  return N->getOpcode() == ISD::CopyFromReg &&
+    N->getOperand(N->getNumOperands()-1).getValueType() != MVT::Flag;
+}
+
+// FIXME: This is probably too slow!
+static void isReachable(SUnit *SU, SUnit *TargetSU,
+                        std::set<SUnit *> &Visited, bool &Reached) {
+  if (Reached) return;
+  if (SU == TargetSU) {
+    Reached = true;
+    return;
+  }
+  if (!Visited.insert(SU).second) return;
+
+  for (std::set<std::pair<SUnit*, bool> >::iterator I = SU->Preds.begin(),
+         E = SU->Preds.end(); I != E; ++I)
+    isReachable(I->first, TargetSU, Visited, Reached);
+}
+
+static bool isReachable(SUnit *SU, SUnit *TargetSU) {
+  std::set<SUnit *> Visited;
+  bool Reached = false;
+  isReachable(SU, TargetSU, Visited, Reached);
+  return Reached;
+}
+
+static SUnit *getDefUsePredecessor(SUnit *SU) {
+  SDNode *DU = SU->Node->getOperand(0).Val;
+  for (std::set<std::pair<SUnit*, bool> >::iterator
+         I = SU->Preds.begin(), E = SU->Preds.end(); I != E; ++I) {
+    if (I->second) continue;  // ignore chain preds
+    SUnit *PredSU = I->first;
+    if (PredSU->Node == DU)
+      return PredSU;
+  }
+
+  // Must be flagged.
+  return NULL;
+}
+
+static bool canClobber(SUnit *SU, SUnit *Op) {
+  if (SU->isTwoAddress)
+    return Op == getDefUsePredecessor(SU);
+  return false;
+}
+
+/// AddPseudoTwoAddrDeps - If two nodes share an operand and one of them uses
+/// it as a def&use operand. Add a pseudo control edge from it to the other
+/// node (if it won't create a cycle) so the two-address one will be scheduled
+/// first (lower in the schedule).
+void RegReductionPriorityQueue::AddPseudoTwoAddrDeps() {
+  for (unsigned i = 0, e = SUnits->size(); i != e; ++i) {
+    SUnit *SU = (SUnit *)&((*SUnits)[i]);
+    SDNode *Node = SU->Node;
+    if (!Node->isTargetOpcode())
+      continue;
+
+    if (SU->isTwoAddress) {
+      unsigned Depth = SU->Node->getNodeDepth();
+      SUnit *DUSU = getDefUsePredecessor(SU);
+      if (!DUSU) continue;
+
+      for (std::set<std::pair<SUnit*, bool> >::iterator I = DUSU->Succs.begin(),
+             E = DUSU->Succs.end(); I != E; ++I) {
+        SUnit *SuccSU = I->first;
+        if (SuccSU != SU && !canClobber(SuccSU, DUSU)) {
+          if (SuccSU->Node->getNodeDepth() <= Depth+2 &&
+              !isReachable(SuccSU, SU)) {
+            DEBUG(std::cerr << "Adding an edge from SU # " << SU->NodeNum
+                  << " to SU #" << SuccSU->NodeNum << "\n");
+            if (SU->Preds.insert(std::make_pair(SuccSU, true)).second)
+              SU->NumChainPredsLeft++;
+            if (SuccSU->Succs.insert(std::make_pair(SU, true)).second)
+              SuccSU->NumChainSuccsLeft++;
+          }
+        }
+      }
+    }
+  }
+}
 
 /// CalcNodePriority - Priority is the Sethi Ullman number. 
 /// Smaller number is the higher priority.
@@ -1036,7 +1126,8 @@
     // Give it a small SethiUllman number so it will be scheduled right before its
     // predecessors that it doesn't lengthen their live ranges.
     SethiUllmanNumber = INT_MIN + 10;
-  else if (SU->NumPredsLeft == 0 && Opc != ISD::CopyFromReg)
+  else if (SU->NumPredsLeft == 0 &&
+           (Opc != ISD::CopyFromReg || isCopyFromLiveIn(SU)))
     SethiUllmanNumber = 1;
   else {
     int Extra = 0;
@@ -1143,7 +1234,7 @@
       Queue.pop();
       return V;
     }
-        
+
     /// RemoveFromPriorityQueue - This is a really inefficient way to remove a
     /// node from a priority queue.  We should roll our own heap to make this
     /// better or something.






More information about the llvm-commits mailing list