37#ifndef LLVM_SUPPORT_GENERICDOMTREECONSTRUCTION_H
38#define LLVM_SUPPORT_GENERICDOMTREECONSTRUCTION_H
49#define DEBUG_TYPE "dom-tree-builder"
52namespace DomTreeBuilder {
55 using NodePtr =
typename DomTreeT::NodePtr;
56 using NodeT =
typename DomTreeT::NodeType;
58 using RootsT =
decltype(DomTreeT::Roots);
59 static constexpr bool IsPostDom = DomTreeT::IsPostDominator;
86 using UpdateT =
typename DomTreeT::UpdateType;
107 unsigned MaxNodeNumber =
120 template <
bool Inversed>
131 using DirectedNodeT =
132 std::conditional_t<Inversed, Inverse<NodePtr>,
NodePtr>;
155 BP.
N->printAsOperand(O,
false);
173 template <
bool IsReverse = false,
typename DescendCondition>
175 unsigned AttachToNum,
181 while (!WorkList.
empty()) {
189 BBInfo.Parent = ParentNum;
190 unsigned Num = LastNum++;
191 BBInfo.Semi = BBInfo.Label = Num;
192 BBInfo.DFSNumPlus1 = Num + 1;
201 if (Condition(BB, Succ))
207 if (SuccOrder && Successors.size() > 1)
210 return SuccOrder->find(A)->second < SuccOrder->find(B)->second;
213 for (
const NodePtr Succ : Successors) {
214 if (!Condition(BB, Succ))
238 unsigned eval(
unsigned V,
unsigned LastLinked,
242 if (VInfo->
Parent < LastLinked)
248 Stack.push_back(VInfo);
249 VInfo = NumToInfo[VInfo->
Parent];
250 }
while (VInfo->
Parent >= LastLinked);
255 unsigned PLabel = PInfo->
Label;
257 VInfo = Stack.pop_back_val();
259 unsigned VLabel = VInfo->
Label;
261 VInfo->
Label = PLabel;
265 }
while (!Stack.empty());
271 const unsigned NextDFSNum(
NumToNode.size());
277 for (
unsigned i = 0; i < NextDFSNum; ++i) {
279 VInfo.IDom = VInfo.Parent;
280 NumToInfo[i] = &VInfo;
285 for (
unsigned i = NextDFSNum; --i;) {
286 auto &WInfo = *NumToInfo[i];
289 WInfo.Semi = WInfo.Parent;
290 for (
unsigned RCIdx = WInfo.ReverseChildrenStart; RCIdx != 0;) {
292 RCIdx = Entry.second;
293 unsigned SemiU =
eval(Entry.first, i + 1, EvalStack, NumToInfo);
294 if (SemiU < WInfo.Semi)
298 WInfo.Label = WInfo.Semi;
304 for (
unsigned i = 1; i < NextDFSNum; ++i) {
305 auto &WInfo = *NumToInfo[i];
306 unsigned WIDom = WInfo.IDom;
307 while (WIDom > WInfo.Semi)
308 WIDom = NumToInfo[WIDom]->IDom;
323 BBInfo.Semi = BBInfo.Label = 0;
324 BBInfo.DFSNumPlus1 = 1;
333 assert(
N &&
"N must be a valid node");
338 assert(DT.Parent &&
"Parent not set");
346 assert(DT.Parent &&
"Parent pointer is not set");
390 bool HasNonTrivialRoots =
false;
393 if (
Total + 1 != Num) {
394 HasNonTrivialRoots =
true;
401 std::optional<NodeOrderMap> SuccOrder;
402 auto InitSuccOrderOnce = [&]() {
407 SuccOrder->try_emplace(Succ, 0);
410 unsigned NodeNum = 0;
411 for (
const auto Node :
nodes(DT.Parent)) {
413 auto Order = SuccOrder->find(
Node);
414 if (Order != SuccOrder->end()) {
415 assert(Order->second == 0);
416 Order->second = NodeNum;
448 const unsigned NewNum =
452 <<
"(non-trivial root): "
454 Roots.push_back(FurthestAway);
455 LLVM_DEBUG(
dbgs() <<
"\t\t\tPrev DFSNum: " << Num <<
", new DFSNum: "
456 << NewNum <<
"\n\t\t\tRemoving DFS info\n");
457 for (
unsigned i = NewNum; i-- > Num;) {
464 const unsigned PrevNum = Num;
467 for (
unsigned i = PrevNum; i < Num; ++i)
479 assert((
Total + 1 == Num) &&
"Everything should have been visited");
482 if (HasNonTrivialRoots)
508 for (
unsigned i = 0; i < Roots.size(); ++i) {
509 auto &Root = Roots[i];
514 <<
" remains a root\n");
519 for (
unsigned x = 1; x < Num; ++x) {
540 template <
typename DescendCondition>
543 assert(DT.Roots.size() == 1 &&
"Dominators should have a singe root");
544 runDFS(DT.Roots[0], 0, DC, 0);
550 for (
const NodePtr Root : DT.Roots)
551 Num =
runDFS(Root, Num, DC, 0);
555 auto *Parent = DT.Parent;
579 dbgs() <<
"DomTree recalculated, skipping future batch updates\n");
582 if (DT.Roots.empty())
590 DT.RootNode = DT.createNode(Root);
596 for (
unsigned Num = 1,
E =
NumToNode.size(); Num !=
E; ++Num) {
598 assert(!DT.getNode(W) &&
"node was already attached");
603 DT.createNode(W, IDomNode);
608 DT.getNode(
NumToNode[0])->setIDom(AttachTo);
609 for (
unsigned Num = 1,
E =
NumToNode.size(); Num !=
E; ++Num) {
612 DT.getNode(
N)->setIDom(IDomNode);
620 return LHS->getLevel() <
RHS->getLevel();
626 std::priority_queue<TreeNodePtr, SmallVector<TreeNodePtr, 8>, Compare>
630#if LLVM_ENABLE_ABI_BREAKING_CHECKS
638 "From has to be a valid CFG node or a virtual root");
639 assert(To &&
"Cannot be a nullptr");
651 FromTN = DT.createNode(From, VirtualRoot);
652 DT.Roots.push_back(From);
655 DT.DFSInfoValid =
false;
672 if (!DT.isVirtualRoot(To->
getIDom()))
679 <<
" is no longer a root\n\t\tRebuilding the tree!!!\n");
687 if (
A.size() !=
B.size())
691 if (Set.count(
N) == 0)
704 return HasForwardSuccessors(N, BUI);
717 <<
"The entire tree needs to be rebuilt\n");
738 assert(NCDBlock || DT.isPostDominator());
743 const unsigned NCDLevel = NCD->
getLevel();
761 II.Visited.insert(To);
763 while (!
II.Bucket.empty()) {
766 II.Affected.push_back(TN);
768 const unsigned CurrentLevel = TN->
getLevel();
770 <<
"as affected, CurrentLevel " << CurrentLevel
787 "Unreachable successor found at reachable insertion");
788 const unsigned SuccLevel = SuccTN->
getLevel();
791 <<
", level = " << SuccLevel <<
"\n");
800 if (SuccLevel <= NCDLevel + 1 || !
II.Visited.insert(SuccTN).second)
803 if (SuccLevel > CurrentLevel) {
808 UnaffectedOnCurrentLevel.
push_back(SuccTN);
809#if LLVM_ENABLE_ABI_BREAKING_CHECKS
810 II.VisitedUnaffected.push_back(SuccTN);
816 <<
" to a Bucket\n");
817 II.Bucket.push(SuccTN);
821 if (UnaffectedOnCurrentLevel.
empty())
843#if LLVM_ENABLE_ABI_BREAKING_CHECKS && !defined(NDEBUG)
846 "TN should have been updated by an affected ancestor");
870 for (
const auto &Edge : DiscoveredEdgesToReachable) {
883 &DiscoveredConnectingEdges) {
884 assert(!DT.getNode(Root) &&
"Root must not be reachable");
887 auto UnreachableDescender = [&DT, &DiscoveredConnectingEdges](
NodePtr From,
893 DiscoveredConnectingEdges.push_back({From, ToTN});
898 SNCA.
runDFS(Root, 0, UnreachableDescender, 0);
900 DT.createNode(SNCA.
NumToNode[0], Incoming);
908 assert(From && To &&
"Cannot disconnect nullptrs");
912#if LLVM_ENABLE_ABI_BREAKING_CHECKS
916 auto IsSuccessor = [BUI](
const NodePtr SuccCandidate,
const NodePtr Of) {
921 assert(!IsSuccessor(To, From) &&
"Deleted edge still exists in the CFG!");
933 <<
") already unreachable -- there is no edge to delete\n");
937 const NodePtr NCDBlock = DT.findNearestCommonDominator(From, To);
942 DT.DFSInfoValid =
false;
972 assert(ToIDom || DT.isPostDominator());
978 if (!PrevIDomSubTree) {
985 const unsigned Level = ToIDomTN->
getLevel();
987 return DT.getNode(To)->getLevel() > Level;
994 SNCA.
runDFS(ToIDom, 0, DescendBelow, 0);
1009 if (!DT.getNode(Pred))
1012 const NodePtr Support = DT.findNearestCommonDominator(TNB, Pred);
1014 if (Support != TNB) {
1016 <<
" is reachable from support "
1038 LLVM_DEBUG(
dbgs() <<
"\tDeletion made a region reverse-unreachable\n");
1041 DT.Roots.push_back(ToTN->
getBlock());
1047 const unsigned Level = ToTN->
getLevel();
1051 auto DescendAndCollect = [Level, &AffectedQueue, &DT](
NodePtr,
NodePtr To) {
1063 unsigned LastDFSNum =
1070 for (
const NodePtr N : AffectedQueue) {
1074 assert(NCDBlock || DT.isPostDominator());
1094 for (
unsigned i = LastDFSNum; i-- > 0;) {
1102 if (MinNode == ToTN)
1105 LLVM_DEBUG(
dbgs() <<
"DeleteUnreachable: running DFS with MinNode = "
1107 const unsigned MinLevel = MinNode->
getLevel();
1116 return ToTN->
getLevel() > MinLevel;
1117 DT.createNode(To, DT.getNode(R));
1139 if (NumUpdates == 0)
1144 if (NumUpdates == 1) {
1147 if (Update.getKind() == UpdateKind::Insert)
1148 InsertEdge(DT,
nullptr, Update.getFrom(), Update.getTo());
1150 DeleteEdge(DT,
nullptr, Update.getFrom(), Update.getTo());
1153 if (Update.getKind() == UpdateKind::Insert)
1154 InsertEdge(DT, &BUI, Update.getFrom(), Update.getTo());
1156 DeleteEdge(DT, &BUI, Update.getFrom(), Update.getTo());
1170 if (DT.DomTreeNodes.size() <= 100) {
1173 }
else if (BUI.
NumLegalized > DT.DomTreeNodes.size() / 40)
1194 if (CurrentUpdate.getKind() == UpdateKind::Insert)
1195 InsertEdge(DT, &BUI, CurrentUpdate.getFrom(), CurrentUpdate.getTo());
1197 DeleteEdge(DT, &BUI, CurrentUpdate.getFrom(), CurrentUpdate.getTo());
1210 if (!DT.Parent && !DT.Roots.empty()) {
1211 errs() <<
"Tree has no parent but has roots!\n";
1217 if (DT.Roots.empty()) {
1218 errs() <<
"Tree doesn't have a root!\n";
1224 errs() <<
"Tree's root is not its parent's entry node!\n";
1232 errs() <<
"Tree has different roots than freshly computed ones!\n";
1233 errs() <<
"\tPDT roots: ";
1236 errs() <<
"\n\tComputed roots: ";
1237 for (
const NodePtr N : ComputedRoots)
1253 for (
auto *TN : DT.DomTreeNodes) {
1259 if (DT.isVirtualRoot(TN))
1264 <<
" not found by DFS walk!\n";
1272 if (
N && !DT.getNode(
N)) {
1274 <<
" not found in the DomTree!\n";
1288 for (
auto *TN : DT.DomTreeNodes) {
1296 if (!IDom && TN->
getLevel() != 0) {
1298 <<
" has a nonzero level " << TN->
getLevel() <<
"!\n";
1306 << TN->
getLevel() <<
" while its IDom "
1322 if (!DT.DFSInfoValid || !DT.Parent)
1328 auto PrintNodeAndDFSNums = [](
const TreeNodePtr TN) {
1336 errs() <<
"DFSIn number for the tree root is not:\n\t";
1337 PrintNodeAndDFSNums(Root);
1345 for (
auto *
Node : DT.DomTreeNodes) {
1350 if (
Node->isLeaf()) {
1351 if (
Node->getDFSNumIn() + 1 !=
Node->getDFSNumOut()) {
1352 errs() <<
"Tree leaf should have DFSOut = DFSIn + 1:\n\t";
1353 PrintNodeAndDFSNums(
Node);
1369 auto PrintChildrenError =
1374 errs() <<
"Incorrect DFS numbers for:\n\tParent ";
1375 PrintNodeAndDFSNums(
Node);
1377 errs() <<
"\n\tChild ";
1378 PrintNodeAndDFSNums(FirstCh);
1381 errs() <<
"\n\tSecond child ";
1382 PrintNodeAndDFSNums(SecondCh);
1385 errs() <<
"\nAll children: ";
1387 PrintNodeAndDFSNums(Ch);
1395 if (Children.front()->getDFSNumIn() !=
Node->getDFSNumIn() + 1) {
1396 PrintChildrenError(Children.front(),
nullptr);
1400 if (Children.back()->getDFSNumOut() !=
Node->getDFSNumOut()) {
1401 PrintChildrenError(Children.back(),
nullptr);
1405 for (
size_t i = 0, e = Children.size() - 1; i != e; ++i) {
1406 if (Children[i]->getDFSNumOut() != Children[i + 1]->getDFSNumIn()) {
1407 PrintChildrenError(Children[i], Children[i + 1]);
1460 for (
auto *TN : DT.DomTreeNodes) {
1471 return From != BB && To != BB;
1478 <<
" is removed!\n";
1495 for (
auto *TN : DT.DomTreeNodes) {
1506 return From != BBN && To != BBN;
1516 <<
" is removed!\n";
1537 FreshTree.recalculate(*DT.Parent);
1538 const bool Different = DT.compare(FreshTree);
1541 errs() << (DT.isPostDominator() ?
"Post" :
"")
1542 <<
"DominatorTree is different than a freshly computed one!\n"
1545 errs() <<
"\n\tFreshly computed tree:\n";
1546 FreshTree.print(
errs());
1558template <
typename DomTreeT>
1569template <
class DomTreeT>
1571 typename DomTreeT::NodePtr To) {
1572 if (DT.isPostDominator())
1577template <
class DomTreeT>
1579 typename DomTreeT::NodePtr To) {
1580 if (DT.isPostDominator())
1585template <
class DomTreeT>
1588 DomTreeT::IsPostDominator> &PreViewCFG,
1590 DomTreeT::IsPostDominator> *PostViewCFG) {
1594template <
class DomTreeT>
1595bool Verify(
const DomTreeT &DT,
typename DomTreeT::VerificationLevel VL) {
1609 if (VL == DomTreeT::VerificationLevel::Basic ||
1610 VL == DomTreeT::VerificationLevel::Full)
1613 if (VL == DomTreeT::VerificationLevel::Full)
1625template <
typename NodeT,
bool IsPostDom>
1633template <
typename NodeT,
bool IsPostDom>
1636 if (Updates.
empty()) {
1653template <
typename NodeT,
bool IsPostDom>
1662template <
typename NodeT,
bool IsPostDom>
1671template <
typename NodeT,
bool IsPostDom>
1674 updateBlockNumberEpoch();
1678template <
typename NodeT,
bool IsPostDom>
1682 updateBlockNumberEpoch();
1686template <
typename NodeT,
bool IsPostDom>
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
Unify divergent function exit nodes
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
This file defines the DenseSet and SmallDenseSet classes.
This file builds on the ADT/GraphTraits.h file to build generic depth first graph iterator.
This file defines a set of templates that efficiently compute a dominator tree over a generic graph.
Loop::LoopBounds::Direction Direction
uint64_t IntrinsicInst * II
ppc ctr loops PowerPC CTR Loops Verify
This file defines the SmallPtrSet class.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
bool empty() const
Check if the array is empty.
Base class for the actual dominator tree node.
iterator_range< iterator > children()
void setIDom(DomTreeNodeBase *NewIDom)
DomTreeNodeBase * getIDom() const
unsigned getDFSNumIn() const
getDFSNumIn/getDFSNumOut - These return the DFS visitation order for nodes in the dominator tree.
unsigned getLevel() const
unsigned getDFSNumOut() const
bool verify(VerificationLevel VL=VerificationLevel::Full) const
verify - checks if the tree is correct.
std::remove_pointer_t< ParentPtr > ParentType
void applyUpdates(ArrayRef< UpdateType > Updates)
Inform the dominator tree about a sequence of CFG edge insertions and deletions and perform a batch u...
void insertEdge(NodeT *From, NodeT *To)
Inform the dominator tree about a CFG edge insertion and update the tree.
void recalculate(ParentType &Func)
recalculate - compute a dominator tree for the given function
void deleteEdge(NodeT *From, NodeT *To)
Inform the dominator tree about a CFG edge deletion and update the tree.
cfg::Update< NodePtr > popUpdateForIncrementalUpdates()
unsigned getNumLegalizedUpdates() const
Implements a dense probed hash-table based set with some number of buckets stored inline.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void resize_for_overwrite(size_type N)
Like resize, but T is POD, the new values won't be initialized.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
This class implements an extremely fast bulk output stream that can only output to a stream.
bool Verify(const DomTreeT &DT, typename DomTreeT::VerificationLevel VL)
void CalculateWithUpdates(DomTreeT &DT, ArrayRef< typename DomTreeT::UpdateType > Updates)
void DeleteEdge(DomTreeT &DT, typename DomTreeT::NodePtr From, typename DomTreeT::NodePtr To)
void Calculate(DomTreeT &DT)
void ApplyUpdates(DomTreeT &DT, GraphDiff< typename DomTreeT::NodePtr, DomTreeT::IsPostDominator > &PreViewCFG, GraphDiff< typename DomTreeT::NodePtr, DomTreeT::IsPostDominator > *PostViewCFG)
void InsertEdge(DomTreeT &DT, typename DomTreeT::NodePtr From, typename DomTreeT::NodePtr To)
auto reverse_if(Range &&R)
This is an optimization pass for GlobalISel generic memory operations.
constexpr from_range_t from_range
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
void sort(IteratorTy Start, IteratorTy End)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
bool none_of(R &&Range, UnaryPredicate P)
Provide wrappers to std::none_of which take ranges instead of having to pass begin/end explicitly.
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
iterator_range< typename GraphTraits< GraphType >::ChildIteratorType > children(const typename GraphTraits< GraphType >::NodeRef &G)
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
BatchUpdateInfo(GraphDiffT &PreViewCFG, GraphDiffT *PostViewCFG=nullptr)
const size_t NumLegalized
friend raw_ostream & operator<<(raw_ostream &O, const BlockNamePrinter &BP)
BlockNamePrinter(NodePtr Block)
BlockNamePrinter(TreeNodePtr TN)
unsigned ReverseChildrenStart
bool operator()(TreeNodePtr LHS, TreeNodePtr RHS) const
std::priority_queue< TreeNodePtr, SmallVector< TreeNodePtr, 8 >, Compare > Bucket
SmallVector< TreeNodePtr, 8 > Affected
SmallDenseSet< TreeNodePtr, 8 > Visited
SmallVector< InfoRec, 32 > NodeInfos
static void UpdateInsertion(DomTreeT &DT, const BatchUpdatePtr BUI, const TreeNodePtr NCD, InsertionInfo &II)
static void DeleteEdge(DomTreeT &DT, const BatchUpdatePtr BUI, const NodePtr From, const NodePtr To)
InfoRec & getNodeInfo(NodePtr BB)
void doFullDFSWalk(const DomTreeT &DT, DescendCondition DC)
DenseMap< NodePtr, unsigned > NodeOrderMap
void attachNewSubtree(DomTreeT &DT)
static RootsT FindRoots(const DomTreeT &DT, BatchUpdatePtr BUI)
static SmallVector< NodePtr, 8 > getChildren(NodePtr N, BatchUpdatePtr BUI)
static void ComputeUnreachableDominators(DomTreeT &DT, const BatchUpdatePtr BUI, const NodePtr Root, const TreeNodePtr Incoming, SmallVectorImpl< std::pair< NodePtr, TreeNodePtr > > &DiscoveredConnectingEdges)
BatchUpdateInfo * BatchUpdatePtr
static bool VerifyLevels(const DomTreeT &DT)
decltype(DomTreeT::Roots) RootsT
bool verifyReachability(const DomTreeT &DT)
unsigned eval(unsigned V, unsigned LastLinked, SmallVectorImpl< InfoRec * > &Stack, ArrayRef< InfoRec * > NumToInfo)
static bool IsSameAsFreshTree(const DomTreeT &DT)
GraphDiff< NodePtr, IsPostDom > GraphDiffT
static constexpr bool IsPostDom
typename DomTreeT::NodePtr NodePtr
static void ApplyUpdates(DomTreeT &DT, GraphDiffT &PreViewCFG, GraphDiffT *PostViewCFG)
typename DomTreeT::UpdateKind UpdateKind
static bool UpdateRootsBeforeInsertion(DomTreeT &DT, const BatchUpdatePtr BUI, const TreeNodePtr From, const TreeNodePtr To)
bool verifySiblingProperty(const DomTreeT &DT)
typename DomTreeT::NodeType NodeT
void reattachExistingSubtree(DomTreeT &DT, const TreeNodePtr AttachTo)
static NodePtr GetEntryNode(const DomTreeT &DT)
static bool AlwaysDescend(NodePtr, NodePtr)
static void UpdateRootsAfterUpdate(DomTreeT &DT, const BatchUpdatePtr BUI)
unsigned runDFS(NodePtr V, unsigned LastNum, DescendCondition Condition, unsigned AttachToNum, const NodeOrderMap *SuccOrder=nullptr)
static void DeleteReachable(DomTreeT &DT, const BatchUpdatePtr BUI, const TreeNodePtr FromTN, const TreeNodePtr ToTN)
static void RemoveRedundantRoots(const DomTreeT &DT, BatchUpdatePtr BUI, RootsT &Roots)
static bool HasProperSupport(DomTreeT &DT, const BatchUpdatePtr BUI, const TreeNodePtr TN)
static bool isPermutation(const SmallVectorImpl< NodePtr > &A, const SmallVectorImpl< NodePtr > &B)
static constexpr unsigned Unvisited
static void CalculateFromScratch(DomTreeT &DT, BatchUpdatePtr BUI)
typename DomTreeT::UpdateType UpdateT
static void InsertReachable(DomTreeT &DT, const BatchUpdatePtr BUI, const TreeNodePtr From, const TreeNodePtr To)
static bool HasForwardSuccessors(const NodePtr N, BatchUpdatePtr BUI)
SemiNCAInfo(const DomTreeT &DT, BatchUpdatePtr BUI)
static void InsertUnreachable(DomTreeT &DT, const BatchUpdatePtr BUI, const TreeNodePtr From, const NodePtr To)
static void ApplyNextUpdate(DomTreeT &DT, BatchUpdateInfo &BUI)
DomTreeNodeBase< NodeT > * TreeNodePtr
static bool VerifyDFSNumbers(const DomTreeT &DT)
static void DeleteUnreachable(DomTreeT &DT, const BatchUpdatePtr BUI, const TreeNodePtr ToTN)
static auto getChildren(NodePtr N)
static void InsertEdge(DomTreeT &DT, const BatchUpdatePtr BUI, const NodePtr From, const NodePtr To)
SmallVector< NodePtr, 32 > NumToNode
BatchUpdateInfo * BatchUpdates
SmallVector< std::pair< unsigned, unsigned >, 32 > ReverseChildren
Reverse children of nodes; pairs of (DFSNum (predecessor), next-or-zero); forms a linked list in this...
bool verifyParentProperty(const DomTreeT &DT)
bool verifyRoots(const DomTreeT &DT)
static ParentPtr getParent(NodePtr BB)