[llvm-commits] CVS: llvm/lib/Target/X86/X86ISelDAGToDAG.cpp

Evan Cheng evan.cheng at apple.com
Thu Jul 27 09:44:50 PDT 2006



Changes in directory llvm/lib/Target/X86:

X86ISelDAGToDAG.cpp updated: 1.75 -> 1.76
---
Log message:

Use reachbility information to determine whether a node can be folded into another during isel.

---
Diffs of the changes:  (+118 -3)

 X86ISelDAGToDAG.cpp |  121 ++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 118 insertions(+), 3 deletions(-)


Index: llvm/lib/Target/X86/X86ISelDAGToDAG.cpp
diff -u llvm/lib/Target/X86/X86ISelDAGToDAG.cpp:1.75 llvm/lib/Target/X86/X86ISelDAGToDAG.cpp:1.76
--- llvm/lib/Target/X86/X86ISelDAGToDAG.cpp:1.75	Wed Jun 28 18:27:49 2006
+++ llvm/lib/Target/X86/X86ISelDAGToDAG.cpp	Thu Jul 27 11:44:36 2006
@@ -34,6 +34,7 @@
 #include "llvm/Support/Visibility.h"
 #include "llvm/ADT/Statistic.h"
 #include <iostream>
+#include <list>
 #include <set>
 using namespace llvm;
 
@@ -92,12 +93,13 @@
     const X86Subtarget *Subtarget;
 
     unsigned GlobalBaseReg;
+
   public:
     X86DAGToDAGISel(X86TargetMachine &TM)
       : SelectionDAGISel(X86Lowering),
-        X86Lowering(*TM.getTargetLowering()) {
-      Subtarget = &TM.getSubtarget<X86Subtarget>();
-    }
+        X86Lowering(*TM.getTargetLowering()),
+        Subtarget(&TM.getSubtarget<X86Subtarget>()),
+        DAGSize(0), ReachibilityMatrix(NULL) {}
 
     virtual bool runOnFunction(Function &Fn) {
       // Make sure we re-emit a set of the global base reg if necessary
@@ -115,10 +117,15 @@
 
     virtual void EmitFunctionEntryCode(Function &Fn, MachineFunction &MF);
 
+    virtual bool IsFoldableBy(SDNode *N, SDNode *U);
+
 // Include the pieces autogenerated from the target description.
 #include "X86GenDAGISel.inc"
 
   private:
+    void DetermineTopologicalOrdering();
+    void DeterminReachibility();
+
     void Select(SDOperand &Result, SDOperand N);
 
     bool MatchAddress(SDOperand N, X86ISelAddressMode &AM, bool isRoot = true);
@@ -173,12 +180,116 @@
     /// base register.  Return the virtual register that holds this value.
     SDOperand getGlobalBaseReg();
 
+    /// DAGSize - Number of nodes in the DAG.
+    ///
+    unsigned DAGSize;
+
+    /// TopOrder - Topological ordering of all nodes in the DAG.
+    ///
+    std::vector<SDNode*> TopOrder;
+
+    /// ReachibilityMatrix - A N x N matrix representing all pairs reachibility
+    /// information. One bit per potential edge.
+    unsigned char *ReachibilityMatrix;
+
+    inline void setReachable(SDNode *f, SDNode *t) {
+      unsigned Idx = f->getNodeId() * DAGSize + t->getNodeId();
+      ReachibilityMatrix[Idx / 8] |= 1 << (Idx % 8);
+    }
+
+    inline bool isReachable(SDNode *f, SDNode *t) {
+      unsigned Idx = f->getNodeId() * DAGSize + t->getNodeId();
+      return ReachibilityMatrix[Idx / 8] & (1 << (Idx % 8));
+    }
+
 #ifndef NDEBUG
     unsigned Indent;
 #endif
   };
 }
 
+bool X86DAGToDAGISel::IsFoldableBy(SDNode *N, SDNode *U) {
+  // If U use can somehow reach N through another path then U can't fold N or
+  // it will create a cycle. e.g. In the following diagram, U can reach N
+  // through X. If N is foled into into U, then X is both a predecessor and
+  // a successor of U.
+  //
+  //         [ N ]
+  //         ^  ^
+  //         |  |
+  //        /   \---
+  //      /        [X]
+  //      |         ^
+  //     [U]--------|
+  if (!ReachibilityMatrix)
+    DeterminReachibility();
+  assert(isReachable(U, N) && "Attempting to fold a non-operand node?");
+  for (SDNode::op_iterator I = U->op_begin(), E = U->op_end(); I != E; ++I) {
+    SDNode *P = I->Val;
+    if (P != N && isReachable(P, N))
+      return false;
+  }
+  return true;
+}
+
+/// DetermineTopologicalOrdering - Determine topological ordering of the nodes
+/// in the DAG.
+void X86DAGToDAGISel::DetermineTopologicalOrdering() {
+  DAGSize = CurDAG->AssignNodeIds();
+  TopOrder.reserve(DAGSize);
+
+  std::vector<unsigned> InDegree(DAGSize);
+  std::list<SDNode*> Sources;
+  for (SelectionDAG::allnodes_iterator I = CurDAG->allnodes_begin(),
+         E = CurDAG->allnodes_end(); I != E; ++I) {
+    SDNode *N = I;
+    unsigned Degree = N->use_size();
+    InDegree[N->getNodeId()] = Degree;
+    if (Degree == 0)
+      Sources.push_back(I);
+  }
+
+  unsigned Order = 0;
+  while (!Sources.empty()) {
+    SDNode *N = Sources.front();
+    Sources.pop_front();
+    TopOrder[Order] = N;
+    Order++;
+    for (SDNode::op_iterator I = N->op_begin(), E = N->op_end(); I != E; ++I) {
+      SDNode *P = I->Val;
+      int PId = P->getNodeId();
+      unsigned Degree = InDegree[PId] - 1;
+      if (Degree == 0)
+        Sources.push_back(P);
+      InDegree[PId] = Degree;
+    }
+  }
+}
+
+void X86DAGToDAGISel::DeterminReachibility() {
+  DetermineTopologicalOrdering();
+  ReachibilityMatrix = new unsigned char[DAGSize * DAGSize];
+  memset(ReachibilityMatrix, 0, DAGSize * DAGSize * sizeof(unsigned char));
+
+  for (unsigned i = 0; i < DAGSize; ++i) {
+    SDNode *N = TopOrder[i];
+    setReachable(N, N);
+    // If N is a leaf node, there is nothing more to do.
+    if (N->getNumOperands() == 0)
+      continue;
+
+    for (unsigned i2 = 0; ; ++i2) {
+      SDNode *M = TopOrder[i2];
+      if (isReachable(M, N)) {
+        // Update reachibility from M to N's operands.
+        for (SDNode::op_iterator I = N->op_begin(), E = N->op_end(); I != E;++I)
+          setReachable(M, I->Val);
+      }
+      if (M == N) break;
+    }
+  }
+}
+
 /// InstructionSelectBasicBlock - This callback is invoked by SelectionDAGISel
 /// when it has created a SelectionDAG for us to codegen.
 void X86DAGToDAGISel::InstructionSelectBasicBlock(SelectionDAG &DAG) {
@@ -195,6 +306,10 @@
 #ifndef NDEBUG
   DEBUG(std::cerr << "===== Instruction selection ends:\n");
 #endif
+  if (ReachibilityMatrix) {
+    delete[] ReachibilityMatrix;
+    ReachibilityMatrix = NULL;
+  }
   CodeGenMap.clear();
   HandleMap.clear();
   ReplaceMap.clear();






More information about the llvm-commits mailing list