Skip to content

Commit 11fd14c

Browse files
committed
[DAG] Prune cycle check in store merge.
As part of merging stores we check that fusing the nodes does not cause a cycle due to one candidate store being indirectly dependent on another store (this may happen via chained memory copies). This is done by searching if a store is a predecessor to another store's value. Prune the search at the candidate search's root node which is a predecessor to all candidate stores. This reduces the size of the subgraph searched in large basic blocks. Reviewers: jyknight Subscribers: llvm-commits, hiraditya Differential Revision: https://reviews.llvm.org/D46955 llvm-svn: 332490
1 parent d9d86cb commit 11fd14c

File tree

1 file changed

+54
-18
lines changed

1 file changed

+54
-18
lines changed

llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp

Lines changed: 54 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -540,15 +540,20 @@ namespace {
540540

541541
/// This is a helper function for MergeConsecutiveStores. Stores
542542
/// that potentially may be merged with St are placed in
543-
/// StoreNodes.
543+
/// StoreNodes. RootNode is a chain predecessor to all store
544+
/// candidates.
544545
void getStoreMergeCandidates(StoreSDNode *St,
545-
SmallVectorImpl<MemOpLink> &StoreNodes);
546+
SmallVectorImpl<MemOpLink> &StoreNodes,
547+
SDNode *&Root);
546548

547549
/// Helper function for MergeConsecutiveStores. Checks if
548550
/// candidate stores have indirect dependency through their
549-
/// operands. \return True if safe to merge.
551+
/// operands. RootNode is the predecessor to all stores calculated
552+
/// by getStoreMergeCandidates and is used to prune the dependency check.
553+
/// \return True if safe to merge.
550554
bool checkMergeStoreCandidatesForDependencies(
551-
SmallVectorImpl<MemOpLink> &StoreNodes, unsigned NumStores);
555+
SmallVectorImpl<MemOpLink> &StoreNodes, unsigned NumStores,
556+
SDNode *RootNode);
552557

553558
/// Merge consecutive store operations into a wide store.
554559
/// This optimization uses wide integers or vectors when possible.
@@ -13229,7 +13234,8 @@ bool DAGCombiner::MergeStoresOfConstantsOrVecElts(
1322913234
}
1323013235

1323113236
void DAGCombiner::getStoreMergeCandidates(
13232-
StoreSDNode *St, SmallVectorImpl<MemOpLink> &StoreNodes) {
13237+
StoreSDNode *St, SmallVectorImpl<MemOpLink> &StoreNodes,
13238+
SDNode *&RootNode) {
1323313239
// This holds the base pointer, index, and the offset in bytes from the base
1323413240
// pointer.
1323513241
BaseIndexOffset BasePtr = BaseIndexOffset::match(St, DAG);
@@ -13328,7 +13334,7 @@ void DAGCombiner::getStoreMergeCandidates(
1332813334
// FIXME: We should be able to climb and
1332913335
// descend TokenFactors to find candidates as well.
1333013336

13331-
SDNode *RootNode = (St->getChain()).getNode();
13337+
RootNode = St->getChain().getNode();
1333213338

1333313339
if (LoadSDNode *Ldn = dyn_cast<LoadSDNode>(RootNode)) {
1333413340
RootNode = Ldn->getChain().getNode();
@@ -13359,21 +13365,48 @@ void DAGCombiner::getStoreMergeCandidates(
1335913365
// through the chain). Check in parallel by searching up from
1336013366
// non-chain operands of candidates.
1336113367
bool DAGCombiner::checkMergeStoreCandidatesForDependencies(
13362-
SmallVectorImpl<MemOpLink> &StoreNodes, unsigned NumStores) {
13368+
SmallVectorImpl<MemOpLink> &StoreNodes, unsigned NumStores,
13369+
SDNode *RootNode) {
1336313370
// FIXME: We should be able to truncate a full search of
1336413371
// predecessors by doing a BFS and keeping tabs the originating
1336513372
// stores from which worklist nodes come from in a similar way to
1336613373
// TokenFactor simplfication.
1336713374

13368-
SmallPtrSet<const SDNode *, 16> Visited;
13375+
SmallPtrSet<const SDNode *, 32> Visited;
1336913376
SmallVector<const SDNode *, 8> Worklist;
13370-
unsigned int Max = 1024;
13377+
13378+
// RootNode is a predecessor to all candidates so we need not search
13379+
// past it. Add RootNode (peeking through TokenFactors). Do not count
13380+
// these towards size check.
13381+
13382+
Worklist.push_back(RootNode);
13383+
while (!Worklist.empty()) {
13384+
auto N = Worklist.pop_back_val();
13385+
if (N->getOpcode() == ISD::TokenFactor) {
13386+
for (SDValue Op : N->ops())
13387+
Worklist.push_back(Op.getNode());
13388+
}
13389+
Visited.insert(N);
13390+
}
13391+
13392+
// Don't count pruning nodes towards max.
13393+
unsigned int Max = 1024 + Visited.size();
1337113394
// Search Ops of store candidates.
1337213395
for (unsigned i = 0; i < NumStores; ++i) {
13373-
SDNode *n = StoreNodes[i].MemNode;
13374-
// Potential loops may happen only through non-chain operands
13375-
for (unsigned j = 1; j < n->getNumOperands(); ++j)
13376-
Worklist.push_back(n->getOperand(j).getNode());
13396+
SDNode *N = StoreNodes[i].MemNode;
13397+
// Of the 4 Store Operands:
13398+
// * Chain (Op 0) -> We have already considered these
13399+
// in candidate selection and can be
13400+
// safely ignored
13401+
// * Value (Op 1) -> Cycles may happen (e.g. through load chains)
13402+
// * Address (Op 2) -> Merged addresses may only vary by a fixed constant
13403+
// and so no cycles are possible.
13404+
// * (Op 3) -> appears to always be undef. Cannot be source of cycle.
13405+
//
13406+
// Thus we need only check predecessors of the value operands.
13407+
auto *Op = N->getOperand(1).getNode();
13408+
if (Visited.insert(Op).second)
13409+
Worklist.push_back(Op);
1337713410
}
1337813411
// Search through DAG. We can stop early if we find a store node.
1337913412
for (unsigned i = 0; i < NumStores; ++i)
@@ -13417,8 +13450,9 @@ bool DAGCombiner::MergeConsecutiveStores(StoreSDNode *St) {
1341713450
return false;
1341813451

1341913452
SmallVector<MemOpLink, 8> StoreNodes;
13453+
SDNode *RootNode;
1342013454
// Find potential store merge candidates by searching through chain sub-DAG
13421-
getStoreMergeCandidates(St, StoreNodes);
13455+
getStoreMergeCandidates(St, StoreNodes, RootNode);
1342213456

1342313457
// Check if there is anything to merge.
1342413458
if (StoreNodes.size() < 2)
@@ -13569,7 +13603,8 @@ bool DAGCombiner::MergeConsecutiveStores(StoreSDNode *St) {
1356913603
}
1357013604

1357113605
// Check that we can merge these candidates without causing a cycle.
13572-
if (!checkMergeStoreCandidatesForDependencies(StoreNodes, NumElem)) {
13606+
if (!checkMergeStoreCandidatesForDependencies(StoreNodes, NumElem,
13607+
RootNode)) {
1357313608
StoreNodes.erase(StoreNodes.begin(), StoreNodes.begin() + NumElem);
1357413609
continue;
1357513610
}
@@ -13633,8 +13668,8 @@ bool DAGCombiner::MergeConsecutiveStores(StoreSDNode *St) {
1363313668
}
1363413669

1363513670
// Check that we can merge these candidates without causing a cycle.
13636-
if (!checkMergeStoreCandidatesForDependencies(StoreNodes,
13637-
NumStoresToMerge)) {
13671+
if (!checkMergeStoreCandidatesForDependencies(
13672+
StoreNodes, NumStoresToMerge, RootNode)) {
1363813673
StoreNodes.erase(StoreNodes.begin(),
1363913674
StoreNodes.begin() + NumStoresToMerge);
1364013675
continue;
@@ -13810,7 +13845,8 @@ bool DAGCombiner::MergeConsecutiveStores(StoreSDNode *St) {
1381013845
}
1381113846

1381213847
// Check that we can merge these candidates without causing a cycle.
13813-
if (!checkMergeStoreCandidatesForDependencies(StoreNodes, NumElem)) {
13848+
if (!checkMergeStoreCandidatesForDependencies(StoreNodes, NumElem,
13849+
RootNode)) {
1381413850
StoreNodes.erase(StoreNodes.begin(), StoreNodes.begin() + NumElem);
1381513851
continue;
1381613852
}

0 commit comments

Comments
 (0)