summaryrefslogtreecommitdiffstats
path: root/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
diff options
context:
space:
mode:
authorTim Shen <timshen91@gmail.com>2016-01-31 03:59:34 +0000
committerTim Shen <timshen91@gmail.com>2016-01-31 03:59:34 +0000
commit3b428cb76472b0c4706e9075f5977233a79a3786 (patch)
tree89b46aa7a102b175021a2c7bc272b18d0fb5d47a /llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
parent429093a9a42ed6bb209a2b3f68db4a1aadadf2b8 (diff)
downloadbcm5719-llvm-3b428cb76472b0c4706e9075f5977233a79a3786.tar.gz
bcm5719-llvm-3b428cb76472b0c4706e9075f5977233a79a3786.zip
[SelectionDAG] Eliminate exponential behavior in WalkChainUsers
llvm-svn: 259315
Diffstat (limited to 'llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp')
-rw-r--r--llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp25
1 files changed, 20 insertions, 5 deletions
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
index 952018e4e2f..859d45c732b 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
@@ -2108,8 +2108,9 @@ enum ChainResult {
/// already selected nodes "below" us.
static ChainResult
WalkChainUsers(const SDNode *ChainedNode,
- SmallVectorImpl<SDNode*> &ChainedNodesInPattern,
- SmallVectorImpl<SDNode*> &InteriorChainedNodes) {
+ SmallVectorImpl<SDNode *> &ChainedNodesInPattern,
+ DenseMap<const SDNode *, ChainResult> &TokenFactorResult,
+ SmallVectorImpl<SDNode *> &InteriorChainedNodes) {
ChainResult Result = CR_Simple;
for (SDNode::use_iterator UI = ChainedNode->use_begin(),
@@ -2190,7 +2191,15 @@ WalkChainUsers(const SDNode *ChainedNode,
// as a new TokenFactor.
//
// To distinguish these two cases, do a recursive walk down the uses.
- switch (WalkChainUsers(User, ChainedNodesInPattern, InteriorChainedNodes)) {
+ auto MemoizeResult = TokenFactorResult.find(User);
+ bool Visited = MemoizeResult != TokenFactorResult.end();
+ // Recursively walk chain users only if the result is not memoized.
+ if (!Visited) {
+ auto Res = WalkChainUsers(User, ChainedNodesInPattern, TokenFactorResult,
+ InteriorChainedNodes);
+ MemoizeResult = TokenFactorResult.insert(std::make_pair(User, Res)).first;
+ }
+ switch (MemoizeResult->second) {
case CR_Simple:
// If the uses of the TokenFactor are just already-selected nodes, ignore
// it, it is "below" our pattern.
@@ -2210,8 +2219,10 @@ WalkChainUsers(const SDNode *ChainedNode,
// ultimate chain result of the generated code. We will also add its chain
// inputs as inputs to the ultimate TokenFactor we create.
Result = CR_LeadsToInteriorNode;
- ChainedNodesInPattern.push_back(User);
- InteriorChainedNodes.push_back(User);
+ if (!Visited) {
+ ChainedNodesInPattern.push_back(User);
+ InteriorChainedNodes.push_back(User);
+ }
continue;
}
@@ -2227,12 +2238,16 @@ WalkChainUsers(const SDNode *ChainedNode,
static SDValue
HandleMergeInputChains(SmallVectorImpl<SDNode*> &ChainNodesMatched,
SelectionDAG *CurDAG) {
+ // Used for memoization. Without it WalkChainUsers could take exponential
+ // time to run.
+ DenseMap<const SDNode *, ChainResult> TokenFactorResult;
// Walk all of the chained nodes we've matched, recursively scanning down the
// users of the chain result. This adds any TokenFactor nodes that are caught
// in between chained nodes to the chained and interior nodes list.
SmallVector<SDNode*, 3> InteriorChainedNodes;
for (unsigned i = 0, e = ChainNodesMatched.size(); i != e; ++i) {
if (WalkChainUsers(ChainNodesMatched[i], ChainNodesMatched,
+ TokenFactorResult,
InteriorChainedNodes) == CR_InducesCycle)
return SDValue(); // Would induce a cycle.
}
OpenPOWER on IntegriCloud