mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-02-14 17:34:41 +00:00
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:
parent
39dfb0ff84
commit
944520f38c
@ -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.
|
||||
///
|
||||
|
@ -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 &&
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user