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

Evan Cheng evan.cheng at apple.com
Sat Oct 14 01:33:40 PDT 2006



Changes in directory llvm/lib/Target/X86:

X86ISelDAGToDAG.cpp updated: 1.118 -> 1.119
---
Log message:

Corrected load folding check. We need to start from the root of the sub-dag
being matched and ensure there isn't a non-direct path to the load (i.e. a
path that goes out of the sub-dag.)


---
Diffs of the changes:  (+65 -52)

 X86ISelDAGToDAG.cpp |  117 ++++++++++++++++++++++++++++------------------------
 1 files changed, 65 insertions(+), 52 deletions(-)


Index: llvm/lib/Target/X86/X86ISelDAGToDAG.cpp
diff -u llvm/lib/Target/X86/X86ISelDAGToDAG.cpp:1.118 llvm/lib/Target/X86/X86ISelDAGToDAG.cpp:1.119
--- llvm/lib/Target/X86/X86ISelDAGToDAG.cpp:1.118	Fri Oct 13 16:14:26 2006
+++ llvm/lib/Target/X86/X86ISelDAGToDAG.cpp	Sat Oct 14 03:33:25 2006
@@ -134,7 +134,7 @@
 
     virtual void EmitFunctionEntryCode(Function &Fn, MachineFunction &MF);
 
-    virtual bool CanBeFoldedBy(SDNode *N, SDNode *U);
+    virtual bool CanBeFoldedBy(SDNode *N, SDNode *U, SDNode *Root);
 
 // Include the pieces autogenerated from the target description.
 #include "X86GenDAGISel.inc"
@@ -227,52 +227,54 @@
   return NULL;
 }
 
-static void findNonImmUse(SDNode* Use, SDNode* Def, SDNode *Ignore, bool &found,
+static void findNonImmUse(SDNode *Use, SDNode* Def, SDNode *ImmedUse,
+                          SDNode *Root, SDNode *Skip, bool &found,
                           std::set<SDNode *> &Visited) {
   if (found ||
       Use->getNodeId() > Def->getNodeId() ||
       !Visited.insert(Use).second)
     return;
 
-  for (unsigned i = 0, e = Use->getNumOperands(); i != e; ++i) {
+  for (unsigned i = 0, e = Use->getNumOperands(); !found && i != e; ++i) {
     SDNode *N = Use->getOperand(i).Val;
-    if (N == Ignore)
+    if (N == Skip)
       continue;
-    if (N != Def) {
-      findNonImmUse(N, Def, Ignore, found, Visited);
-    } else {
+    if (N == Def) {
+      if (Use == ImmedUse)
+        continue; // Immediate use is ok.
+      if (Use == Root) {
+        assert(Use->getOpcode() == ISD::STORE ||
+               Use->getOpcode() == X86ISD::CMP);
+        continue;
+      }
       found = true;
       break;
     }
+    findNonImmUse(N, Def, ImmedUse, Root, Skip, found, Visited);
   }
 }
 
-static inline bool isNonImmUse(SDNode* Use, SDNode* Def, SDNode *Ignore=NULL) {
+/// isNonImmUse - Start searching from Root up the DAG to check is Def can
+/// be reached. Return true if that's the case. However, ignore direct uses
+/// by ImmedUse (which would be U in the example illustrated in
+/// CanBeFoldedBy) and by Root (which can happen in the store case).
+/// FIXME: to be really generic, we should allow direct use by any node
+/// that is being folded. But realisticly since we only fold loads which
+/// have one non-chain use, we only need to watch out for load/op/store
+/// and load/op/cmp case where the root (store / cmp) may reach the load via
+/// its chain operand.
+static inline bool isNonImmUse(SDNode *Root, SDNode *Def, SDNode *ImmedUse,
+                               SDNode *Skip = NULL) {
   std::set<SDNode *> Visited;
   bool found = false;
-  for (unsigned i = 0, e = Use->getNumOperands(); i != e; ++i) {
-    SDNode *N = Use->getOperand(i).Val;
-    if (N != Def && N != Ignore) {
-      findNonImmUse(N, Def, Ignore, found, Visited);
-      if (found) break;
-    }
-  }
-
-  if (!found && Ignore) {
-    // We must be checking for reachability between Def and a flag use. Go down
-    // recursively if Use also produces a flag.
-    MVT::ValueType VT = Use->getValueType(Use->getNumValues()-1);
-    if (VT == MVT::Flag && !Use->use_empty()) {
-      SDNode *FU = findFlagUse(Use);
-      if (FU)
-        return !isNonImmUse(FU, Def, Use);
-    }
-  }
+  findNonImmUse(Root, Def, ImmedUse, Root, Skip, found, Visited);
   return found;
 }
 
 
-bool X86DAGToDAGISel::CanBeFoldedBy(SDNode *N, SDNode *U) {
+bool X86DAGToDAGISel::CanBeFoldedBy(SDNode *N, SDNode *U, SDNode *Root) {
+  if (FastISel) return false;
+
   // 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 folded into into U, then X is both a predecessor and
@@ -285,32 +287,43 @@
   //      /        [X]
   //      |         ^
   //     [U]--------|
-  if (!FastISel && !isNonImmUse(U, N)) {
-    // If U produces a flag, then it gets (even more) interesting. Since it
-    // would have been "glued" together with its flag use, we need to check if
-    // it might reach N:
-    //
-    //      [ N ]
-    //        ^ ^
-    //        | |
-    //       [U] \--
-    //        ^   [TF]
-    //        |    |
-    //         \  /
-    //          [FU]
-    //
-    // If FU (flag use) indirectly reach N (the load), and U fold N (call it
-    // NU), then TF is a predecessor of FU and a successor of NU. But since
-    // NU and FU are flagged together, this effectively creates a cycle.
-    MVT::ValueType VT = U->getValueType(U->getNumValues()-1);
-    if (VT == MVT::Flag && !U->use_empty()) {
-      SDNode *FU = findFlagUse(U);
-      if (FU)
-        return !isNonImmUse(FU, N, U);
+
+  if (isNonImmUse(Root, N, U))
+    return false;
+
+  // If U produces a flag, then it gets (even more) interesting. Since it
+  // would have been "glued" together with its flag use, we need to check if
+  // it might reach N:
+  //
+  //       [ N ]
+  //        ^ ^
+  //        | |
+  //       [U] \--
+  //        ^   [TF]
+  //        |    ^
+  //        |    |
+  //         \  /
+  //          [FU]
+  //
+  // If FU (flag use) indirectly reach N (the load), and U fold N (call it
+  // NU), then TF is a predecessor of FU and a successor of NU. But since
+  // NU and FU are flagged together, this effectively creates a cycle.
+  bool HasFlagUse = false;
+  MVT::ValueType VT = Root->getValueType(Root->getNumValues()-1);
+  while ((VT == MVT::Flag && !Root->use_empty())) {
+    SDNode *FU = findFlagUse(Root);
+    if (FU == NULL)
+      break;
+    else {
+      Root = FU;
+      HasFlagUse = true;
     }
-    return true;
+    VT = Root->getValueType(Root->getNumValues()-1);
   }
-  return false;
+
+  if (HasFlagUse)
+    return !isNonImmUse(Root, N, Root, U);
+  return true;
 }
 
 /// MoveBelowTokenFactor - Replace TokenFactor operand with load's chain operand
@@ -909,7 +922,7 @@
                                   SDOperand &Index, SDOperand &Disp) {
   if (ISD::isNON_EXTLoad(N.Val) &&
       N.hasOneUse() &&
-      CanBeFoldedBy(N.Val, P.Val))
+      CanBeFoldedBy(N.Val, P.Val, P.Val))
     return SelectAddr(N.getOperand(1), Base, Scale, Index, Disp);
   return false;
 }






More information about the llvm-commits mailing list