[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