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
This commit is contained in:
Lang Hames 2011-07-07 04:31:51 +00:00
parent 39dfb0ff84
commit 944520f38c
3 changed files with 58 additions and 19 deletions

View File

@ -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 isPredecessorOf(SDNode *N) const;
/// 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.
/// 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.
///

View File

@ -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 &&

View File

@ -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);
/// 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);
}
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;
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;
}