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);
599 for (
unsigned Num = 1; Num !=
E; ++Num) {
601 assert(!DT.getNode(W) &&
"node was already attached");
604 for (
unsigned Num =
E; --Num;) {
611 DT.getNode(
NumToNode[0])->setIDom(AttachTo);
612 for (
unsigned Num = 1,
E =
NumToNode.size(); Num !=
E; ++Num) {
615 DT.getNode(
N)->setIDom(IDomNode);
623 return LHS->getLevel() <
RHS->getLevel();
629 std::priority_queue<TreeNodePtr, SmallVector<TreeNodePtr, 8>, Compare>
633#if LLVM_ENABLE_ABI_BREAKING_CHECKS
641 "From has to be a valid CFG node or a virtual root");
642 assert(To &&
"Cannot be a nullptr");
643 LLVM_DEBUG(
dbgs() <<
"Inserting edge " << BlockNamePrinter(From) <<
" -> "
644 << BlockNamePrinter(To) <<
"\n");
654 FromTN = DT.createNode(From, VirtualRoot);
655 DT.Roots.push_back(From);
658 DT.DFSInfoValid =
false;
675 if (!DT.isVirtualRoot(To->
getIDom()))
682 <<
" is no longer a root\n\t\tRebuilding the tree!!!\n");
690 if (
A.size() !=
B.size())
694 if (Set.count(
N) == 0)
707 return HasForwardSuccessors(N, BUI);
720 <<
"The entire tree needs to be rebuilt\n");
741 assert(NCDBlock || DT.isPostDominator());
746 const unsigned NCDLevel = NCD->
getLevel();
764 II.Visited.insert(To);
766 while (!
II.Bucket.empty()) {
769 II.Affected.push_back(TN);
771 const unsigned CurrentLevel = TN->
getLevel();
773 <<
"as affected, CurrentLevel " << CurrentLevel
790 "Unreachable successor found at reachable insertion");
791 const unsigned SuccLevel = SuccTN->
getLevel();
794 <<
", level = " << SuccLevel <<
"\n");
803 if (SuccLevel <= NCDLevel + 1 || !
II.Visited.insert(SuccTN).second)
806 if (SuccLevel > CurrentLevel) {
810 << BlockNamePrinter(Succ) <<
"\n");
811 UnaffectedOnCurrentLevel.
push_back(SuccTN);
812#if LLVM_ENABLE_ABI_BREAKING_CHECKS
813 II.VisitedUnaffected.push_back(SuccTN);
819 <<
" to a Bucket\n");
820 II.Bucket.push(SuccTN);
824 if (UnaffectedOnCurrentLevel.
empty())
842 <<
") = " << BlockNamePrinter(NCD) <<
"\n");
846#if LLVM_ENABLE_ABI_BREAKING_CHECKS && !defined(NDEBUG)
848 assert(TN->getLevel() == TN->getIDom()->getLevel() + 1 &&
849 "TN should have been updated by an affected ancestor");
873 for (
const auto &Edge : DiscoveredEdgesToReachable) {
886 &DiscoveredConnectingEdges) {
887 assert(!DT.getNode(Root) &&
"Root must not be reachable");
890 auto UnreachableDescender = [&DT, &DiscoveredConnectingEdges](
NodePtr From,
896 DiscoveredConnectingEdges.push_back({From, ToTN});
901 SNCA.
runDFS(Root, 0, UnreachableDescender, 0);
903 DT.createNode(SNCA.
NumToNode[0], Incoming);
911 assert(From && To &&
"Cannot disconnect nullptrs");
915#if LLVM_ENABLE_ABI_BREAKING_CHECKS
919 auto IsSuccessor = [BUI](
const NodePtr SuccCandidate,
const NodePtr Of) {
924 assert(!IsSuccessor(To, From) &&
"Deleted edge still exists in the CFG!");
936 <<
") already unreachable -- there is no edge to delete\n");
940 const NodePtr NCDBlock = DT.findNearestCommonDominator(From, To);
945 DT.DFSInfoValid =
false;
975 assert(ToIDom || DT.isPostDominator());
981 if (!PrevIDomSubTree) {
988 const unsigned Level = ToIDomTN->
getLevel();
990 return DT.getNode(To)->getLevel() > Level;
997 SNCA.
runDFS(ToIDom, 0, DescendBelow, 0);
1012 if (!DT.getNode(Pred))
1015 const NodePtr Support = DT.findNearestCommonDominator(TNB, Pred);
1017 if (Support != TNB) {
1019 <<
" is reachable from support "
1041 LLVM_DEBUG(
dbgs() <<
"\tDeletion made a region reverse-unreachable\n");
1044 DT.Roots.push_back(ToTN->
getBlock());
1050 const unsigned Level = ToTN->
getLevel();
1054 auto DescendAndCollect = [Level, &AffectedQueue, &DT](
NodePtr,
NodePtr To) {
1066 unsigned LastDFSNum =
1073 for (
const NodePtr N : AffectedQueue) {
1077 assert(NCDBlock || DT.isPostDominator());
1097 for (
unsigned i = LastDFSNum; i-- > 0;) {
1105 if (MinNode == ToTN)
1108 LLVM_DEBUG(
dbgs() <<
"DeleteUnreachable: running DFS with MinNode = "
1110 const unsigned MinLevel = MinNode->
getLevel();
1119 return ToTN->
getLevel() > MinLevel;
1120 DT.createNode(To, DT.getNode(R));
1142 if (NumUpdates == 0)
1147 if (NumUpdates == 1) {
1150 if (Update.getKind() == UpdateKind::Insert)
1151 InsertEdge(DT,
nullptr, Update.getFrom(), Update.getTo());
1153 DeleteEdge(DT,
nullptr, Update.getFrom(), Update.getTo());
1156 if (Update.getKind() == UpdateKind::Insert)
1157 InsertEdge(DT, &BUI, Update.getFrom(), Update.getTo());
1159 DeleteEdge(DT, &BUI, Update.getFrom(), Update.getTo());
1173 if (DT.DomTreeNodes.size() <= 100) {
1176 }
else if (BUI.
NumLegalized > DT.DomTreeNodes.size() / 40)
1197 if (CurrentUpdate.getKind() == UpdateKind::Insert)
1198 InsertEdge(DT, &BUI, CurrentUpdate.getFrom(), CurrentUpdate.getTo());
1200 DeleteEdge(DT, &BUI, CurrentUpdate.getFrom(), CurrentUpdate.getTo());
1213 if (!DT.Parent && !DT.Roots.empty()) {
1214 errs() <<
"Tree has no parent but has roots!\n";
1220 if (DT.Roots.empty()) {
1221 errs() <<
"Tree doesn't have a root!\n";
1227 errs() <<
"Tree's root is not its parent's entry node!\n";
1235 errs() <<
"Tree has different roots than freshly computed ones!\n";
1236 errs() <<
"\tPDT roots: ";
1239 errs() <<
"\n\tComputed roots: ";
1240 for (
const NodePtr N : ComputedRoots)
1256 for (
auto *TN : DT.DomTreeNodes) {
1259 const NodePtr BB = TN->getBlock();
1262 if (DT.isVirtualRoot(TN))
1267 <<
" not found by DFS walk!\n";
1275 if (
N && !DT.getNode(
N)) {
1277 <<
" not found in the DomTree!\n";
1291 for (
auto *TN : DT.DomTreeNodes) {
1294 const NodePtr BB = TN->getBlock();
1299 if (!IDom && TN->
getLevel() != 0) {
1301 <<
" has a nonzero level " << TN->getLevel() <<
"!\n";
1309 << TN->getLevel() <<
" while its IDom "
1325 if (!DT.DFSInfoValid || !DT.Parent)
1331 auto PrintNodeAndDFSNums = [](
const TreeNodePtr TN) {
1333 << TN->getDFSNumOut() <<
'}';
1339 errs() <<
"DFSIn number for the tree root is not:\n\t";
1340 PrintNodeAndDFSNums(Root);
1348 for (
auto *
Node : DT.DomTreeNodes) {
1353 if (
Node->isLeaf()) {
1354 if (
Node->getDFSNumIn() + 1 !=
Node->getDFSNumOut()) {
1355 errs() <<
"Tree leaf should have DFSOut = DFSIn + 1:\n\t";
1356 PrintNodeAndDFSNums(
Node);
1372 auto PrintChildrenError =
1377 errs() <<
"Incorrect DFS numbers for:\n\tParent ";
1378 PrintNodeAndDFSNums(
Node);
1380 errs() <<
"\n\tChild ";
1381 PrintNodeAndDFSNums(FirstCh);
1384 errs() <<
"\n\tSecond child ";
1385 PrintNodeAndDFSNums(SecondCh);
1388 errs() <<
"\nAll children: ";
1390 PrintNodeAndDFSNums(Ch);
1398 if (Children.front()->getDFSNumIn() !=
Node->getDFSNumIn() + 1) {
1399 PrintChildrenError(Children.front(),
nullptr);
1403 if (Children.back()->getDFSNumOut() !=
Node->getDFSNumOut()) {
1404 PrintChildrenError(Children.back(),
nullptr);
1408 for (
size_t i = 0, e = Children.size() - 1; i != e; ++i) {
1409 if (Children[i]->getDFSNumOut() != Children[i + 1]->getDFSNumIn()) {
1410 PrintChildrenError(Children[i], Children[i + 1]);
1463 for (
auto *TN : DT.DomTreeNodes) {
1466 const NodePtr BB = TN->getBlock();
1467 if (!BB || TN->isLeaf())
1474 return From != BB && To != BB;
1481 <<
" is removed!\n";
1498 for (
auto *TN : DT.DomTreeNodes) {
1501 const NodePtr BB = TN->getBlock();
1502 if (!BB || TN->isLeaf())
1509 return From != BBN && To != BBN;
1519 <<
" is removed!\n";
1540 FreshTree.recalculate(*DT.Parent);
1541 const bool Different = DT.compare(FreshTree);
1544 errs() << (DT.isPostDominator() ?
"Post" :
"")
1545 <<
"DominatorTree is different than a freshly computed one!\n"
1548 errs() <<
"\n\tFreshly computed tree:\n";
1549 FreshTree.print(
errs());
1561template <
typename DomTreeT>
1572template <
class DomTreeT>
1574 typename DomTreeT::NodePtr To) {
1575 if (DT.isPostDominator())
1580template <
class DomTreeT>
1582 typename DomTreeT::NodePtr To) {
1583 if (DT.isPostDominator())
1588template <
class DomTreeT>
1591 DomTreeT::IsPostDominator> &PreViewCFG,
1593 DomTreeT::IsPostDominator> *PostViewCFG) {
1597template <
class DomTreeT>
1598bool Verify(
const DomTreeT &DT,
typename DomTreeT::VerificationLevel VL) {
1612 if (VL == DomTreeT::VerificationLevel::Basic ||
1613 VL == DomTreeT::VerificationLevel::Full)
1616 if (VL == DomTreeT::VerificationLevel::Full)
1628template <
typename NodeT,
bool IsPostDom>
1636template <
typename NodeT,
bool IsPostDom>
1639 if (Updates.
empty()) {
1656template <
typename NodeT,
bool IsPostDom>
1665template <
typename NodeT,
bool IsPostDom>
1674template <
typename NodeT,
bool IsPostDom>
1677 updateBlockNumberEpoch();
1681template <
typename NodeT,
bool IsPostDom>
1685 updateBlockNumberEpoch();
1689template <
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.
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
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.
typename NodeTrait::NodePtr NodePtr
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)