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

Evan Cheng evan.cheng at apple.com
Mon Oct 9 18:47:10 PDT 2006



Changes in directory llvm/lib/Target/X86:

X86ISelDAGToDAG.cpp updated: 1.112 -> 1.113
---
Log message:

More isel time load folding checking for nodes that produce flag values.
See comment in CanBeFoldedBy() for detailed explanation.


---
Diffs of the changes:  (+57 -6)

 X86ISelDAGToDAG.cpp |   63 +++++++++++++++++++++++++++++++++++++++++++++++-----
 1 files changed, 57 insertions(+), 6 deletions(-)


Index: llvm/lib/Target/X86/X86ISelDAGToDAG.cpp
diff -u llvm/lib/Target/X86/X86ISelDAGToDAG.cpp:1.112 llvm/lib/Target/X86/X86ISelDAGToDAG.cpp:1.113
--- llvm/lib/Target/X86/X86ISelDAGToDAG.cpp:1.112	Mon Oct  9 15:57:25 2006
+++ llvm/lib/Target/X86/X86ISelDAGToDAG.cpp	Mon Oct  9 20:46:56 2006
@@ -213,7 +213,20 @@
   };
 }
 
-static void findNonImmUse(SDNode* Use, SDNode* Def, bool &found,
+static SDNode *findFlagUse(SDNode *N) {
+  unsigned FlagResNo = N->getNumValues()-1;
+  for (SDNode::use_iterator I = N->use_begin(), E = N->use_end(); I != E; ++I) {
+    SDNode *User = *I;
+    for (unsigned i = 0, e = User->getNumOperands(); i != e; ++i) {
+      SDOperand Op = User->getOperand(i);
+      if (Op.ResNo == FlagResNo)
+        return User;
+    }
+  }
+  return NULL;
+}
+
+static void findNonImmUse(SDNode* Use, SDNode* Def, SDNode *Ignore, bool &found,
                           std::set<SDNode *> &Visited) {
   if (found ||
       Use->getNodeId() > Def->getNodeId() ||
@@ -222,8 +235,10 @@
 
   for (unsigned i = 0, e = Use->getNumOperands(); i != e; ++i) {
     SDNode *N = Use->getOperand(i).Val;
+    if (N == Ignore)
+      continue;
     if (N != Def) {
-      findNonImmUse(N, Def, found, Visited);
+      findNonImmUse(N, Def, Ignore, found, Visited);
     } else {
       found = true;
       break;
@@ -231,16 +246,27 @@
   }
 }
 
-static inline bool isNonImmUse(SDNode* Use, SDNode* Def) {
+static inline bool isNonImmUse(SDNode* Use, SDNode* Def, SDNode *Ignore=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) {
-      findNonImmUse(N, Def, found, Visited);
+    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);
+    }
+  }
   return found;
 }
 
@@ -258,7 +284,32 @@
   //      /        [X]
   //      |         ^
   //     [U]--------|
-  return !FastISel && !isNonImmUse(U, N);
+  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);
+    }
+    return true;
+  }
+  return false;
 }
 
 /// MoveBelowTokenFactor - Replace TokenFactor operand with load's chain operand






More information about the llvm-commits mailing list