aboutsummaryrefslogtreecommitdiffstats
path: root/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/CodeGen/SelectionDAG/DAGCombiner.cpp')
-rw-r--r--lib/CodeGen/SelectionDAG/DAGCombiner.cpp50
1 files changed, 35 insertions, 15 deletions
diff --git a/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index d5d3f7a61a9f..432c86dd6f1e 100644
--- a/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -1118,22 +1118,30 @@ SDValue DAGCombiner::PromoteIntBinOp(SDValue Op) {
SDValue RV =
DAG.getNode(ISD::TRUNCATE, DL, VT, DAG.getNode(Opc, DL, PVT, NN0, NN1));
- // New replace instances of N0 and N1
- if (Replace0 && N0 && N0.getOpcode() != ISD::DELETED_NODE && NN0 &&
- NN0.getOpcode() != ISD::DELETED_NODE) {
+ // We are always replacing N0/N1's use in N and only need
+ // additional replacements if there are additional uses.
+ Replace0 &= !N0->hasOneUse();
+ Replace1 &= (N0 != N1) && !N1->hasOneUse();
+
+ // Combine Op here so it is presreved past replacements.
+ CombineTo(Op.getNode(), RV);
+
+ // If operands have a use ordering, make sur we deal with
+ // predecessor first.
+ if (Replace0 && Replace1 && N0.getNode()->isPredecessorOf(N1.getNode())) {
+ std::swap(N0, N1);
+ std::swap(NN0, NN1);
+ }
+
+ if (Replace0) {
AddToWorklist(NN0.getNode());
ReplaceLoadWithPromotedLoad(N0.getNode(), NN0.getNode());
}
-
- if (Replace1 && N1 && N1.getOpcode() != ISD::DELETED_NODE && NN1 &&
- NN1.getOpcode() != ISD::DELETED_NODE) {
+ if (Replace1) {
AddToWorklist(NN1.getNode());
ReplaceLoadWithPromotedLoad(N1.getNode(), NN1.getNode());
}
-
- // Deal with Op being deleted.
- if (Op && Op.getOpcode() != ISD::DELETED_NODE)
- return RV;
+ return Op;
}
return SDValue();
}
@@ -12599,25 +12607,37 @@ void DAGCombiner::getStoreMergeCandidates(
}
}
-// We need to check that merging these stores does not cause a loop
-// in the DAG. Any store candidate may depend on another candidate
+// We need to check that merging these stores does not cause a loop in
+// the DAG. Any store candidate may depend on another candidate
// indirectly through its operand (we already consider dependencies
// through the chain). Check in parallel by searching up from
// non-chain operands of candidates.
+
bool DAGCombiner::checkMergeStoreCandidatesForDependencies(
SmallVectorImpl<MemOpLink> &StoreNodes, unsigned NumStores) {
+
+ // FIXME: We should be able to truncate a full search of
+ // predecessors by doing a BFS and keeping tabs the originating
+ // stores from which worklist nodes come from in a similar way to
+ // TokenFactor simplfication.
+
SmallPtrSet<const SDNode *, 16> Visited;
SmallVector<const SDNode *, 8> Worklist;
- // search ops of store candidates
+ unsigned int Max = 8192;
+ // Search Ops of store candidates.
for (unsigned i = 0; i < NumStores; ++i) {
SDNode *n = StoreNodes[i].MemNode;
// Potential loops may happen only through non-chain operands
for (unsigned j = 1; j < n->getNumOperands(); ++j)
Worklist.push_back(n->getOperand(j).getNode());
}
- // search through DAG. We can stop early if we find a storenode
+ // Search through DAG. We can stop early if we find a store node.
for (unsigned i = 0; i < NumStores; ++i) {
- if (SDNode::hasPredecessorHelper(StoreNodes[i].MemNode, Visited, Worklist))
+ if (SDNode::hasPredecessorHelper(StoreNodes[i].MemNode, Visited, Worklist,
+ Max))
+ return false;
+ // Check if we ended early, failing conservatively if so.
+ if (Visited.size() >= Max)
return false;
}
return true;