[llvm-commits] [llvm] r42625 - in /llvm/trunk: include/llvm/CodeGen/ScheduleDAG.h lib/CodeGen/SelectionDAG/ScheduleDAG.cpp lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp

Evan Cheng evan.cheng at apple.com
Thu Oct 4 18:39:18 PDT 2007


Author: evancheng
Date: Thu Oct  4 20:39:18 2007
New Revision: 42625

URL: http://llvm.org/viewvc/llvm-project?rev=42625&view=rev
Log:
If a node that defines a physical register that is expensive to copy. The
scheduler will try a number of tricks in order to avoid generating the
copies. This may not be possible in case the node produces a chain value
that prevent movement. Try unfolding the load from the node before to allow
it to be moved / cloned.

Modified:
    llvm/trunk/include/llvm/CodeGen/ScheduleDAG.h
    llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAG.cpp
    llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp

Modified: llvm/trunk/include/llvm/CodeGen/ScheduleDAG.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/ScheduleDAG.h?rev=42625&r1=42624&r2=42625&view=diff

==============================================================================
--- llvm/trunk/include/llvm/CodeGen/ScheduleDAG.h (original)
+++ llvm/trunk/include/llvm/CodeGen/ScheduleDAG.h Thu Oct  4 20:39:18 2007
@@ -115,7 +115,7 @@
     short NumSuccsLeft;                 // # of succs not scheduled.
     bool isTwoAddress     : 1;          // Is a two-address instruction.
     bool isCommutable     : 1;          // Is a commutable instruction.
-    bool hasPhysRegDefs  : 1;           // Has physreg defs that are being used.
+    bool hasPhysRegDefs   : 1;          // Has physreg defs that are being used.
     bool isPending        : 1;          // True once pending.
     bool isAvailable      : 1;          // True once available.
     bool isScheduled      : 1;          // True once scheduled.
@@ -297,6 +297,10 @@
     /// together nodes with a single SUnit.
     void BuildSchedUnits();
 
+    /// ComputeLatency - Compute node latency.
+    ///
+    void ComputeLatency(SUnit *SU);
+
     /// CalculateDepths, CalculateHeights - Calculate node depth / height.
     ///
     void CalculateDepths();

Modified: llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAG.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAG.cpp?rev=42625&r1=42624&r2=42625&view=diff

==============================================================================
--- llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAG.cpp (original)
+++ llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAG.cpp Thu Oct  4 20:39:18 2007
@@ -68,6 +68,7 @@
   return SU;
 }
 
+
 /// BuildSchedUnits - Build SUnits from the selection dag that we are input.
 /// This SUnit graph is similar to the SelectionDAG, but represents flagged
 /// together nodes with a single SUnit.
@@ -77,8 +78,6 @@
   // invalidated.
   SUnits.reserve(std::distance(DAG.allnodes_begin(), DAG.allnodes_end()));
   
-  const InstrItineraryData &InstrItins = TM.getInstrItineraryData();
-  
   for (SelectionDAG::allnodes_iterator NI = DAG.allnodes_begin(),
        E = DAG.allnodes_end(); NI != E; ++NI) {
     if (isPassiveNode(NI))  // Leaf node, e.g. a TargetImmediate.
@@ -131,32 +130,8 @@
     // Update the SUnit
     NodeSUnit->Node = N;
     SUnitMap[N].push_back(NodeSUnit);
-    
-    // Compute the latency for the node.  We use the sum of the latencies for
-    // all nodes flagged together into this SUnit.
-    if (InstrItins.isEmpty()) {
-      // No latency information.
-      NodeSUnit->Latency = 1;
-    } else {
-      NodeSUnit->Latency = 0;
-      if (N->isTargetOpcode()) {
-        unsigned SchedClass = TII->getSchedClass(N->getTargetOpcode());
-        InstrStage *S = InstrItins.begin(SchedClass);
-        InstrStage *E = InstrItins.end(SchedClass);
-        for (; S != E; ++S)
-          NodeSUnit->Latency += S->Cycles;
-      }
-      for (unsigned i = 0, e = NodeSUnit->FlaggedNodes.size(); i != e; ++i) {
-        SDNode *FNode = NodeSUnit->FlaggedNodes[i];
-        if (FNode->isTargetOpcode()) {
-          unsigned SchedClass = TII->getSchedClass(FNode->getTargetOpcode());
-          InstrStage *S = InstrItins.begin(SchedClass);
-          InstrStage *E = InstrItins.end(SchedClass);
-          for (; S != E; ++S)
-            NodeSUnit->Latency += S->Cycles;
-        }
-      }
-    }
+
+    ComputeLatency(NodeSUnit);
   }
   
   // Pass 2: add the preds, succs, etc.
@@ -214,6 +189,36 @@
   return;
 }
 
+void ScheduleDAG::ComputeLatency(SUnit *SU) {
+  const InstrItineraryData &InstrItins = TM.getInstrItineraryData();
+  
+  // Compute the latency for the node.  We use the sum of the latencies for
+  // all nodes flagged together into this SUnit.
+  if (InstrItins.isEmpty()) {
+    // No latency information.
+    SU->Latency = 1;
+  } else {
+    SU->Latency = 0;
+    if (SU->Node->isTargetOpcode()) {
+      unsigned SchedClass = TII->getSchedClass(SU->Node->getTargetOpcode());
+      InstrStage *S = InstrItins.begin(SchedClass);
+      InstrStage *E = InstrItins.end(SchedClass);
+      for (; S != E; ++S)
+        SU->Latency += S->Cycles;
+    }
+    for (unsigned i = 0, e = SU->FlaggedNodes.size(); i != e; ++i) {
+      SDNode *FNode = SU->FlaggedNodes[i];
+      if (FNode->isTargetOpcode()) {
+        unsigned SchedClass = TII->getSchedClass(FNode->getTargetOpcode());
+        InstrStage *S = InstrItins.begin(SchedClass);
+        InstrStage *E = InstrItins.end(SchedClass);
+        for (; S != E; ++S)
+          SU->Latency += S->Cycles;
+      }
+    }
+  }
+}
+
 void ScheduleDAG::CalculateDepths() {
   std::vector<std::pair<SUnit*, unsigned> > WorkList;
   for (unsigned i = 0, e = SUnits.size(); i != e; ++i)

Modified: llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp?rev=42625&r1=42624&r2=42625&view=diff

==============================================================================
--- llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp (original)
+++ llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp Thu Oct  4 20:39:18 2007
@@ -34,6 +34,7 @@
 using namespace llvm;
 
 STATISTIC(NumBacktracks, "Number of times scheduler backtraced");
+STATISTIC(NumUnfolds,    "Number of nodes unfolded");
 STATISTIC(NumDups,       "Number of duplicated nodes");
 STATISTIC(NumCCCopies,   "Number of cross class copies");
 
@@ -385,32 +386,145 @@
   ++NumBacktracks;
 }
 
-/// isSafeToCopy - True if the SUnit for the given SDNode can safely cloned,
-/// i.e. the node does not produce a flag, it does not read a flag and it does
-/// not have an incoming chain.
-static bool isSafeToCopy(SDNode *N) {
+/// CopyAndMoveSuccessors - Clone the specified node and move its scheduled
+/// successors to the newly created node.
+SUnit *ScheduleDAGRRList::CopyAndMoveSuccessors(SUnit *SU) {
+  if (SU->FlaggedNodes.size())
+    return NULL;
+
+  SDNode *N = SU->Node;
   if (!N)
-    return true;
+    return NULL;
 
+  SUnit *NewSU;
   for (unsigned i = 0, e = N->getNumValues(); i != e; ++i)
     if (N->getValueType(i) == MVT::Flag)
-      return false;
+      return NULL;
+  bool TryUnfold = false;
   for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) {
     const SDOperand &Op = N->getOperand(i);
     MVT::ValueType VT = Op.Val->getValueType(Op.ResNo);
-    if (VT == MVT::Other || VT == MVT::Flag)
-      return false;
-  }
+    if (VT == MVT::Flag)
+      return NULL;
+    else if (VT == MVT::Other)
+      TryUnfold = true;
+  }
+
+  if (TryUnfold) {
+    SmallVector<SDNode*, 4> NewNodes;
+    if (!MRI->unfoldMemoryOperand(DAG, N, NewNodes))
+      return NULL;
+
+    DOUT << "Unfolding SU # " << SU->NodeNum << "\n";
+    assert(NewNodes.size() == 2 && "Expected a load folding node!");
+
+    N = NewNodes[1];
+    SDNode *LoadNode = NewNodes[0];
+    std::vector<SDNode*> Deleted;
+    unsigned NumVals = N->getNumValues();
+    unsigned OldNumVals = SU->Node->getNumValues();
+    for (unsigned i = 0; i != NumVals; ++i)
+      DAG.ReplaceAllUsesOfValueWith(SDOperand(SU->Node, i),
+                                    SDOperand(N, i), Deleted);
+    DAG.ReplaceAllUsesOfValueWith(SDOperand(SU->Node, OldNumVals-1),
+                                  SDOperand(LoadNode, 1), Deleted);
+
+    SUnit *LoadSU = NewSUnit(LoadNode);
+    SUnit *NewSU = NewSUnit(N);
+    SUnitMap[LoadNode].push_back(LoadSU);
+    SUnitMap[N].push_back(NewSU);
+    const TargetInstrDescriptor *TID = &TII->get(LoadNode->getTargetOpcode());
+    for (unsigned i = 0; i != TID->numOperands; ++i) {
+      if (TID->getOperandConstraint(i, TOI::TIED_TO) != -1) {
+        LoadSU->isTwoAddress = true;
+        break;
+      }
+    }
+    if (TID->Flags & M_COMMUTABLE)
+      LoadSU->isCommutable = true;
 
-  return true;
-}
+    TID = &TII->get(N->getTargetOpcode());
+    for (unsigned i = 0; i != TID->numOperands; ++i) {
+      if (TID->getOperandConstraint(i, TOI::TIED_TO) != -1) {
+        NewSU->isTwoAddress = true;
+        break;
+      }
+    }
+    if (TID->Flags & M_COMMUTABLE)
+      NewSU->isCommutable = true;
 
-/// CopyAndMoveSuccessors - Clone the specified node and move its scheduled
-/// successors to the newly created node.
-SUnit *ScheduleDAGRRList::CopyAndMoveSuccessors(SUnit *SU) {
-  DOUT << "Duplicating SU # " << SU->NodeNum << "\n";
+    // FIXME: Calculate height / depth and propagate the changes?
+    LoadSU->Depth = NewSU->Depth = SU->Depth;
+    LoadSU->Height = NewSU->Height = SU->Height;
+    ComputeLatency(LoadSU);
+    ComputeLatency(NewSU);
+
+    SUnit *ChainPred = NULL;
+    SmallVector<SDep, 4> ChainSuccs;
+    SmallVector<SDep, 4> LoadPreds;
+    SmallVector<SDep, 4> NodePreds;
+    SmallVector<SDep, 4> NodeSuccs;
+    for (SUnit::pred_iterator I = SU->Preds.begin(), E = SU->Preds.end();
+         I != E; ++I) {
+      if (I->isCtrl)
+        ChainPred = I->Dep;
+      else if (I->Dep->Node && I->Dep->Node->isOperand(LoadNode))
+        LoadPreds.push_back(SDep(I->Dep, I->Reg, I->Cost, false, false));
+      else
+        NodePreds.push_back(SDep(I->Dep, I->Reg, I->Cost, false, false));
+    }
+    for (SUnit::succ_iterator I = SU->Succs.begin(), E = SU->Succs.end();
+         I != E; ++I) {
+      if (I->isCtrl)
+        ChainSuccs.push_back(SDep(I->Dep, I->Reg, I->Cost,
+                                  I->isCtrl, I->isSpecial));
+      else
+        NodeSuccs.push_back(SDep(I->Dep, I->Reg, I->Cost,
+                                 I->isCtrl, I->isSpecial));
+    }
 
-  SUnit *NewSU = Clone(SU);
+    SU->removePred(ChainPred, true, false);
+    LoadSU->addPred(ChainPred, true, false);
+    for (unsigned i = 0, e = LoadPreds.size(); i != e; ++i) {
+      SDep *Pred = &LoadPreds[i];
+      SU->removePred(Pred->Dep, Pred->isCtrl, Pred->isSpecial);
+      LoadSU->addPred(Pred->Dep, Pred->isCtrl, Pred->isSpecial,
+                      Pred->Reg, Pred->Cost);
+    }
+    for (unsigned i = 0, e = NodePreds.size(); i != e; ++i) {
+      SDep *Pred = &NodePreds[i];
+      SU->removePred(Pred->Dep, Pred->isCtrl, Pred->isSpecial);
+      NewSU->addPred(Pred->Dep, Pred->isCtrl, Pred->isSpecial,
+                     Pred->Reg, Pred->Cost);
+    }
+    for (unsigned i = 0, e = NodeSuccs.size(); i != e; ++i) {
+      SDep *Succ = &NodeSuccs[i];
+      Succ->Dep->removePred(SU, Succ->isCtrl, Succ->isSpecial);
+      Succ->Dep->addPred(NewSU, Succ->isCtrl, Succ->isSpecial,
+                         Succ->Reg, Succ->Cost);
+    }
+    for (unsigned i = 0, e = ChainSuccs.size(); i != e; ++i) {
+      SDep *Succ = &ChainSuccs[i];
+      Succ->Dep->removePred(SU, Succ->isCtrl, Succ->isSpecial);
+      Succ->Dep->addPred(LoadSU, Succ->isCtrl, Succ->isSpecial,
+                         Succ->Reg, Succ->Cost);
+    } 
+    NewSU->addPred(LoadSU, false, false);
+
+    AvailableQueue->addNode(LoadSU);
+    AvailableQueue->addNode(NewSU);
+
+    ++NumUnfolds;
+
+    if (NewSU->NumSuccsLeft == 0) {
+      NewSU->isAvailable = true;
+      return NewSU;
+    } else
+      SU = NewSU;
+  }
+
+  DOUT << "Duplicating SU # " << SU->NodeNum << "\n";
+  NewSU = Clone(SU);
 
   // New SUnit has the exact same predecessors.
   for (SUnit::pred_iterator I = SU->Preds.begin(), E = SU->Preds.end();
@@ -452,6 +566,7 @@
                                               const TargetRegisterClass *DestRC,
                                               const TargetRegisterClass *SrcRC,
                                                SmallVector<SUnit*, 2> &Copies) {
+  abort();
   SUnit *CopyFromSU = NewSUnit(NULL);
   CopyFromSU->CopySrcRC = SrcRC;
   CopyFromSU->CopyDstRC = DestRC;
@@ -640,10 +755,8 @@
         assert(LRegs.size() == 1 && "Can't handle this yet!");
         unsigned Reg = LRegs[0];
         SUnit *LRDef = LiveRegDefs[Reg];
-        SUnit *NewDef;
-        if (isSafeToCopy(LRDef->Node))
-          NewDef = CopyAndMoveSuccessors(LRDef);
-        else {
+        SUnit *NewDef = CopyAndMoveSuccessors(LRDef);
+        if (!NewDef) {
           // Issue expensive cross register class copies.
           MVT::ValueType VT = getPhysicalRegisterVT(LRDef->Node, Reg, TII);
           const TargetRegisterClass *RC =





More information about the llvm-commits mailing list