aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLang Hames <lhames@gmail.com>2011-07-07 04:31:51 +0000
committerLang Hames <lhames@gmail.com>2011-07-07 04:31:51 +0000
commit944520f38c79f3cbf1abfca92a5414458d639029 (patch)
tree6ea77b702ac307624a90ab74881fdc240c7069d5
parent39dfb0ff848be6b380ca81ff95d4ca4e0ae09c76 (diff)
downloadexternal_llvm-944520f38c79f3cbf1abfca92a5414458d639029.zip
external_llvm-944520f38c79f3cbf1abfca92a5414458d639029.tar.gz
external_llvm-944520f38c79f3cbf1abfca92a5414458d639029.tar.bz2
Add functions 'hasPredecessor' and 'hasPredecessorHelper' to SDNode. The
hasPredecessorHelper function allows predecessors to be cached to speed up repeated invocations. This fixes PR10186. X.isPredecessorOf(Y) now just calls Y.hasPredecessor(X) Y.hasPredecessor(X) calls Y.hasPredecessorHelper(X, Visited, Worklist) with empty Visited and Worklist sets (i.e. no caching over invocations). Y.hasPredecessorHelper(X, Visited, Worklist) caches search state in Visited and Worklist to speed up repeated calls. The Visited set is searched for X before going to the worklist to further search the DAG if necessary. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134592 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/llvm/CodeGen/SelectionDAGNodes.h27
-rw-r--r--lib/CodeGen/SelectionDAG/DAGCombiner.cpp7
-rw-r--r--lib/CodeGen/SelectionDAG/SelectionDAG.cpp45
3 files changed, 59 insertions, 20 deletions
diff --git a/include/llvm/CodeGen/SelectionDAGNodes.h b/include/llvm/CodeGen/SelectionDAGNodes.h
index 9d265f1..a5c4201 100644
--- a/include/llvm/CodeGen/SelectionDAGNodes.h
+++ b/include/llvm/CodeGen/SelectionDAGNodes.h
@@ -23,6 +23,7 @@
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/GraphTraits.h"
#include "llvm/ADT/ilist_node.h"
+#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/CodeGen/ISDOpcodes.h"
@@ -496,11 +497,29 @@ public:
///
bool isOperandOf(SDNode *N) const;
- /// isPredecessorOf - Return true if this node is a predecessor of N. This
- /// node is either an operand of N or it can be reached by recursively
+ /// isPredecessorOf - Return true if this node is a predecessor of N.
+ /// NOTE: Implemented on top of hasPredecessor and every bit as
+ /// expensive. Use carefully.
+ bool isPredecessorOf(const SDNode *N) const { return N->hasPredecessor(this); }
+
+ /// hasPredecessor - Return true if N is a predecessor of this node.
+ /// N is either an operand of this node, or can be reached by recursively
+ /// traversing up the operands.
+ /// NOTE: This is an expensive method. Use it carefully.
+ bool hasPredecessor(const SDNode *N) const;
+
+ /// hasPredecesorHelper - Return true if N is a predecessor of this node.
+ /// N is either an operand of this node, or can be reached by recursively
/// traversing up the operands.
- /// NOTE: this is an expensive method. Use it carefully.
- bool isPredecessorOf(SDNode *N) const;
+ /// In this helper the Visited and worklist sets are held externally to
+ /// cache predecessors over multiple invocations. If you want to test for
+ /// multiple predecessors this method is preferable to multiple calls to
+ /// hasPredecessor. Be sure to clear Visited and Worklist if the DAG
+ /// changes.
+ /// NOTE: This is still very expensive. Use carefully.
+ bool hasPredecessorHelper(const SDNode *N,
+ SmallPtrSet<const SDNode *, 32> &Visited,
+ SmallVector<const SDNode *, 16> &Worklist) const;
/// getNumOperands - Return the number of values used by this operation.
///
diff --git a/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index 90e0cc7..79e7612 100644
--- a/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -5929,12 +5929,17 @@ bool DAGCombiner::CombineToPreIndexedLoadStore(SDNode *N) {
// Now check for #3 and #4.
bool RealUse = false;
+
+ // Caches for hasPredecessorHelper
+ SmallPtrSet<const SDNode *, 32> Visited;
+ SmallVector<const SDNode *, 16> Worklist;
+
for (SDNode::use_iterator I = Ptr.getNode()->use_begin(),
E = Ptr.getNode()->use_end(); I != E; ++I) {
SDNode *Use = *I;
if (Use == N)
continue;
- if (Use->isPredecessorOf(N))
+ if (N->hasPredecessorHelper(Use, Visited, Worklist))
return false;
if (!((Use->getOpcode() == ISD::LOAD &&
diff --git a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
index b6ebcd2..f5e4526 100644
--- a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
+++ b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
@@ -5691,24 +5691,39 @@ bool SDValue::reachesChainWithoutSideEffects(SDValue Dest,
return false;
}
-/// isPredecessorOf - Return true if this node is a predecessor of N. This node
-/// is either an operand of N or it can be reached by traversing up the operands.
-/// NOTE: this is an expensive method. Use it carefully.
-bool SDNode::isPredecessorOf(SDNode *N) const {
- SmallPtrSet<SDNode *, 32> Visited;
- SmallVector<SDNode *, 16> Worklist;
- Worklist.push_back(N);
-
- do {
- N = Worklist.pop_back_val();
- for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) {
- SDNode *Op = N->getOperand(i).getNode();
- if (Op == this)
- return true;
+/// hasPredecessor - Return true if N is a predecessor of this node.
+/// N is either an operand of this node, or can be reached by recursively
+/// traversing up the operands.
+/// NOTE: This is an expensive method. Use it carefully.
+bool SDNode::hasPredecessor(const SDNode *N) const {
+ SmallPtrSet<const SDNode *, 32> Visited;
+ SmallVector<const SDNode *, 16> Worklist;
+ return hasPredecessorHelper(N, Visited, Worklist);
+}
+
+bool SDNode::hasPredecessorHelper(const SDNode *N,
+ SmallPtrSet<const SDNode *, 32> &Visited,
+ SmallVector<const SDNode *, 16> &Worklist) const {
+ if (Visited.empty()) {
+ Worklist.push_back(this);
+ } else {
+ // Take a look in the visited set. If we've already encountered this node
+ // we needn't search further.
+ if (Visited.count(N))
+ return true;
+ }
+
+ // Haven't visited N yet. Continue the search.
+ while (!Worklist.empty()) {
+ const SDNode *M = Worklist.pop_back_val();
+ for (unsigned i = 0, e = M->getNumOperands(); i != e; ++i) {
+ SDNode *Op = M->getOperand(i).getNode();
if (Visited.insert(Op))
Worklist.push_back(Op);
+ if (Op == N)
+ return true;
}
- } while (!Worklist.empty());
+ }
return false;
}