Skip to content

Commit 1d2b6d9

Browse files
authored
[Support] Use block numbers for DomTree construction (#101706)
Similar to #101705, do the same optimization for dominator tree construction.
1 parent f949b03 commit 1d2b6d9

File tree

2 files changed

+48
-21
lines changed

2 files changed

+48
-21
lines changed

llvm/include/llvm/ADT/GraphTraits.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#ifndef LLVM_ADT_GRAPHTRAITS_H
2020
#define LLVM_ADT_GRAPHTRAITS_H
2121

22+
#include "llvm/ADT/STLExtras.h"
2223
#include "llvm/ADT/iterator_range.h"
2324

2425
namespace llvm {
@@ -94,6 +95,16 @@ struct GraphTraits {
9495
using NodeRef = typename GraphType::UnknownGraphTypeError;
9596
};
9697

98+
namespace detail {
99+
template <typename T>
100+
using has_number_t = decltype(GraphTraits<T>::getNumber(std::declval<T>()));
101+
} // namespace detail
102+
103+
/// Indicate whether a GraphTraits<NodeT>::getNumber() is supported.
104+
template <typename NodeT>
105+
constexpr bool GraphHasNodeNumbers =
106+
is_detected<detail::has_number_t, NodeT>::value;
107+
97108
// Inverse - This class is used as a little marker class to tell the graph
98109
// iterator to iterate over the graph in a graph defined "Inverse" ordering.
99110
// Not all graphs define an inverse ordering, and if they do, it depends on

llvm/include/llvm/Support/GenericDomTreeConstruction.h

Lines changed: 37 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,11 @@ struct SemiNCAInfo {
7373
// Number to node mapping is 1-based. Initialize the mapping to start with
7474
// a dummy element.
7575
SmallVector<NodePtr, 64> NumToNode = {nullptr};
76-
DenseMap<NodePtr, InfoRec> NodeToInfo;
76+
// If blocks have numbers (e.g., BasicBlock, MachineBasicBlock), store node
77+
// infos in a vector. Otherwise, store them in a map.
78+
std::conditional_t<GraphHasNodeNumbers<NodePtr>, SmallVector<InfoRec, 64>,
79+
DenseMap<NodePtr, InfoRec>>
80+
NodeInfos;
7781

7882
using UpdateT = typename DomTreeT::UpdateType;
7983
using UpdateKind = typename DomTreeT::UpdateKind;
@@ -99,7 +103,7 @@ struct SemiNCAInfo {
99103

100104
void clear() {
101105
NumToNode = {nullptr}; // Restore to initial state with a dummy start node.
102-
NodeToInfo.clear();
106+
NodeInfos.clear();
103107
// Don't reset the pointer to BatchUpdateInfo here -- if there's an update
104108
// in progress, we need this information to continue it.
105109
}
@@ -123,13 +127,25 @@ struct SemiNCAInfo {
123127
return Res;
124128
}
125129

126-
NodePtr getIDom(NodePtr BB) const {
127-
auto InfoIt = NodeToInfo.find(BB);
128-
if (InfoIt == NodeToInfo.end()) return nullptr;
129-
130-
return InfoIt->second.IDom;
130+
InfoRec &getNodeInfo(NodePtr BB) {
131+
if constexpr (GraphHasNodeNumbers<NodePtr>) {
132+
unsigned Idx = BB ? GraphTraits<NodePtr>::getNumber(BB) + 1 : 0;
133+
if (Idx >= NodeInfos.size()) {
134+
unsigned Max = 0;
135+
if (BB)
136+
Max = GraphTraits<decltype(BB->getParent())>::getMaxNumber(
137+
BB->getParent());
138+
// Max might be zero, graphs might not support getMaxNumber().
139+
NodeInfos.resize(Max ? Max + 1 : Idx + 1);
140+
}
141+
return NodeInfos[Idx];
142+
} else {
143+
return NodeInfos[BB];
144+
}
131145
}
132146

147+
NodePtr getIDom(NodePtr BB) { return getNodeInfo(BB).IDom; }
148+
133149
TreeNodePtr getNodeForBlock(NodePtr BB, DomTreeT &DT) {
134150
if (TreeNodePtr Node = DT.getNode(BB)) return Node;
135151

@@ -181,11 +197,11 @@ struct SemiNCAInfo {
181197
const NodeOrderMap *SuccOrder = nullptr) {
182198
assert(V);
183199
SmallVector<std::pair<NodePtr, unsigned>, 64> WorkList = {{V, AttachToNum}};
184-
NodeToInfo[V].Parent = AttachToNum;
200+
getNodeInfo(V).Parent = AttachToNum;
185201

186202
while (!WorkList.empty()) {
187203
const auto [BB, ParentNum] = WorkList.pop_back_val();
188-
auto &BBInfo = NodeToInfo[BB];
204+
auto &BBInfo = getNodeInfo(BB);
189205
BBInfo.ReverseChildren.push_back(ParentNum);
190206

191207
// Visited nodes always have positive DFS numbers.
@@ -264,7 +280,7 @@ struct SemiNCAInfo {
264280
// Initialize IDoms to spanning tree parents.
265281
for (unsigned i = 1; i < NextDFSNum; ++i) {
266282
const NodePtr V = NumToNode[i];
267-
auto &VInfo = NodeToInfo[V];
283+
auto &VInfo = getNodeInfo(V);
268284
VInfo.IDom = NumToNode[VInfo.Parent];
269285
NumToInfo.push_back(&VInfo);
270286
}
@@ -292,7 +308,7 @@ struct SemiNCAInfo {
292308
const unsigned SDomNum = NumToInfo[WInfo.Semi]->DFSNum;
293309
NodePtr WIDomCandidate = WInfo.IDom;
294310
while (true) {
295-
auto &WIDomCandidateInfo = NodeToInfo.find(WIDomCandidate)->second;
311+
auto &WIDomCandidateInfo = getNodeInfo(WIDomCandidate);
296312
if (WIDomCandidateInfo.DFSNum <= SDomNum)
297313
break;
298314
WIDomCandidate = WIDomCandidateInfo.IDom;
@@ -311,7 +327,7 @@ struct SemiNCAInfo {
311327
assert(IsPostDom && "Only postdominators have a virtual root");
312328
assert(NumToNode.size() == 1 && "SNCAInfo must be freshly constructed");
313329

314-
auto &BBInfo = NodeToInfo[nullptr];
330+
auto &BBInfo = getNodeInfo(nullptr);
315331
BBInfo.DFSNum = BBInfo.Semi = BBInfo.Label = 1;
316332

317333
NumToNode.push_back(nullptr); // NumToNode[1] = nullptr;
@@ -393,7 +409,7 @@ struct SemiNCAInfo {
393409
auto InitSuccOrderOnce = [&]() {
394410
SuccOrder = NodeOrderMap();
395411
for (const auto Node : nodes(DT.Parent))
396-
if (SNCA.NodeToInfo.count(Node) == 0)
412+
if (SNCA.getNodeInfo(Node).DFSNum == 0)
397413
for (const auto Succ : getChildren<false>(Node, SNCA.BatchUpdates))
398414
SuccOrder->try_emplace(Succ, 0);
399415

@@ -417,7 +433,7 @@ struct SemiNCAInfo {
417433
// unreachable node once, we may just visit it in two directions,
418434
// depending on how lucky we get.
419435
for (const NodePtr I : nodes(DT.Parent)) {
420-
if (SNCA.NodeToInfo.count(I) == 0) {
436+
if (SNCA.getNodeInfo(I).DFSNum == 0) {
421437
LLVM_DEBUG(dbgs()
422438
<< "\t\t\tVisiting node " << BlockNamePrinter(I) << "\n");
423439
// Find the furthest away we can get by following successors, then
@@ -449,7 +465,7 @@ struct SemiNCAInfo {
449465
const NodePtr N = SNCA.NumToNode[i];
450466
LLVM_DEBUG(dbgs() << "\t\t\t\tRemoving DFS info for "
451467
<< BlockNamePrinter(N) << "\n");
452-
SNCA.NodeToInfo.erase(N);
468+
SNCA.getNodeInfo(N) = {};
453469
SNCA.NumToNode.pop_back();
454470
}
455471
const unsigned PrevNum = Num;
@@ -582,7 +598,7 @@ struct SemiNCAInfo {
582598

583599
void attachNewSubtree(DomTreeT& DT, const TreeNodePtr AttachTo) {
584600
// Attach the first unreachable block to AttachTo.
585-
NodeToInfo[NumToNode[1]].IDom = AttachTo->getBlock();
601+
getNodeInfo(NumToNode[1]).IDom = AttachTo->getBlock();
586602
// Loop over all of the discovered blocks in the function...
587603
for (NodePtr W : llvm::drop_begin(NumToNode)) {
588604
if (DT.getNode(W))
@@ -600,11 +616,11 @@ struct SemiNCAInfo {
600616
}
601617

602618
void reattachExistingSubtree(DomTreeT &DT, const TreeNodePtr AttachTo) {
603-
NodeToInfo[NumToNode[1]].IDom = AttachTo->getBlock();
619+
getNodeInfo(NumToNode[1]).IDom = AttachTo->getBlock();
604620
for (const NodePtr N : llvm::drop_begin(NumToNode)) {
605621
const TreeNodePtr TN = DT.getNode(N);
606622
assert(TN);
607-
const TreeNodePtr NewIDom = DT.getNode(NodeToInfo[N].IDom);
623+
const TreeNodePtr NewIDom = DT.getNode(getNodeInfo(N).IDom);
608624
TN->setIDom(NewIDom);
609625
}
610626
}
@@ -1239,7 +1255,7 @@ struct SemiNCAInfo {
12391255
// Virtual root has a corresponding virtual CFG node.
12401256
if (DT.isVirtualRoot(TN)) continue;
12411257

1242-
if (NodeToInfo.count(BB) == 0) {
1258+
if (getNodeInfo(BB).DFSNum == 0) {
12431259
errs() << "DomTree node " << BlockNamePrinter(BB)
12441260
<< " not found by DFS walk!\n";
12451261
errs().flush();
@@ -1453,7 +1469,7 @@ struct SemiNCAInfo {
14531469
});
14541470

14551471
for (TreeNodePtr Child : TN->children())
1456-
if (NodeToInfo.count(Child->getBlock()) != 0) {
1472+
if (getNodeInfo(Child->getBlock()).DFSNum != 0) {
14571473
errs() << "Child " << BlockNamePrinter(Child)
14581474
<< " reachable after its parent " << BlockNamePrinter(BB)
14591475
<< " is removed!\n";
@@ -1491,7 +1507,7 @@ struct SemiNCAInfo {
14911507
for (const TreeNodePtr S : TN->children()) {
14921508
if (S == N) continue;
14931509

1494-
if (NodeToInfo.count(S->getBlock()) == 0) {
1510+
if (getNodeInfo(S->getBlock()).DFSNum == 0) {
14951511
errs() << "Node " << BlockNamePrinter(S)
14961512
<< " not reachable when its sibling " << BlockNamePrinter(N)
14971513
<< " is removed!\n";

0 commit comments

Comments
 (0)