37#ifndef LLVM_SUPPORT_GENERICDOMTREECONSTRUCTION_H
38#define LLVM_SUPPORT_GENERICDOMTREECONSTRUCTION_H
49#define DEBUG_TYPE "dom-tree-builder"
52namespace DomTreeBuilder {
54template <
typename DomTreeT>
56 using NodePtr =
typename DomTreeT::NodePtr;
57 using NodeT =
typename DomTreeT::NodeType;
59 using RootsT =
decltype(DomTreeT::Roots);
60 static constexpr bool IsPostDom = DomTreeT::IsPostDominator;
82 using UpdateT =
typename DomTreeT::UpdateType;
111 template <
bool Inversed>
114 return BUI->
PreViewCFG.template getChildren<Inversed>(
N);
115 return getChildren<Inversed>(
N);
118 template <
bool Inversed>
120 using DirectedNodeT =
121 std::conditional_t<Inversed, Inverse<NodePtr>,
NodePtr>;
122 auto R = children<DirectedNodeT>(
N);
131 if constexpr (GraphHasNodeNumbers<NodePtr>) {
136 Max =
GraphTraits<
decltype(BB->getParent())>::getMaxNumber(
156 assert(IDom || DT.getNode(
nullptr));
161 return DT.createNode(BB, IDomNode);
176 BP.
N->printAsOperand(O,
false);
194 template <
bool IsReverse = false,
typename DescendCondition>
196 unsigned AttachToNum,
202 while (!WorkList.
empty()) {
205 BBInfo.ReverseChildren.push_back(ParentNum);
208 if (BBInfo.DFSNum != 0)
continue;
209 BBInfo.Parent = ParentNum;
210 BBInfo.DFSNum = BBInfo.Semi = BBInfo.Label = ++LastNum;
214 auto Successors = getChildren<Direction>(BB,
BatchUpdates);
215 if (SuccOrder && Successors.size() > 1)
218 return SuccOrder->find(A)->second < SuccOrder->find(B)->second;
221 for (
const NodePtr Succ : Successors) {
222 if (!Condition(BB, Succ))
continue;
244 unsigned eval(
unsigned V,
unsigned LastLinked,
248 if (VInfo->
Parent < LastLinked)
254 Stack.push_back(VInfo);
255 VInfo = NumToInfo[VInfo->
Parent];
256 }
while (VInfo->
Parent >= LastLinked);
263 VInfo = Stack.pop_back_val();
266 if (PLabelInfo->
Semi < VLabelInfo->
Semi)
269 PLabelInfo = VLabelInfo;
271 }
while (!Stack.empty());
281 for (
unsigned i = 1; i < NextDFSNum; ++i) {
290 for (
unsigned i = NextDFSNum - 1; i >= 2; --i) {
291 auto &WInfo = *NumToInfo[i];
294 WInfo.Semi = WInfo.Parent;
295 for (
unsigned N : WInfo.ReverseChildren) {
296 unsigned SemiU = NumToInfo[
eval(
N, i + 1, EvalStack, NumToInfo)]->Semi;
297 if (SemiU < WInfo.Semi) WInfo.Semi = SemiU;
305 for (
unsigned i = 2; i < NextDFSNum; ++i) {
306 auto &WInfo = *NumToInfo[i];
308 const unsigned SDomNum = NumToInfo[WInfo.Semi]->DFSNum;
309 NodePtr WIDomCandidate = WInfo.IDom;
311 auto &WIDomCandidateInfo =
getNodeInfo(WIDomCandidate);
312 if (WIDomCandidateInfo.DFSNum <= SDomNum)
314 WIDomCandidate = WIDomCandidateInfo.IDom;
317 WInfo.IDom = WIDomCandidate;
331 BBInfo.DFSNum = BBInfo.Semi = BBInfo.Label = 1;
340 assert(
N &&
"N must be a valid node");
341 return !getChildren<false>(
N, BUI).empty();
345 assert(DT.Parent &&
"Parent not set");
353 assert(DT.Parent &&
"Parent pointer is not set");
397 bool HasNonTrivialRoots =
false;
400 if (
Total + 1 != Num) {
401 HasNonTrivialRoots =
true;
408 std::optional<NodeOrderMap> SuccOrder;
409 auto InitSuccOrderOnce = [&]() {
414 SuccOrder->try_emplace(Succ, 0);
417 unsigned NodeNum = 0;
418 for (
const auto Node :
nodes(DT.Parent)) {
420 auto Order = SuccOrder->find(
Node);
421 if (Order != SuccOrder->end()) {
422 assert(Order->second == 0);
423 Order->second = NodeNum;
455 const unsigned NewNum =
459 <<
"(non-trivial root): "
461 Roots.push_back(FurthestAway);
462 LLVM_DEBUG(
dbgs() <<
"\t\t\tPrev DFSNum: " << Num <<
", new DFSNum: "
463 << NewNum <<
"\n\t\t\tRemoving DFS info\n");
464 for (
unsigned i = NewNum; i > Num; --i) {
471 const unsigned PrevNum = Num;
474 for (
unsigned i = PrevNum + 1; i <= Num; ++i)
486 assert((
Total + 1 == Num) &&
"Everything should have been visited");
515 for (
unsigned i = 0; i < Roots.size(); ++i) {
516 auto &Root = Roots[i];
520 <<
" remains a root\n");
526 for (
unsigned x = 2; x <= Num; ++x) {
547 template <
typename DescendCondition>
550 assert(DT.Roots.size() == 1 &&
"Dominators should have a singe root");
551 runDFS(DT.Roots[0], 0, DC, 0);
557 for (
const NodePtr Root : DT.Roots) Num =
runDFS(Root, Num, DC, 1);
561 auto *Parent = DT.Parent;
585 dbgs() <<
"DomTree recalculated, skipping future batch updates\n");
588 if (DT.Roots.empty())
return;
595 DT.RootNode = DT.createNode(Root);
614 DT.createNode(W, IDomNode);
632 return LHS->getLevel() <
RHS->getLevel();
638 std::priority_queue<TreeNodePtr, SmallVector<TreeNodePtr, 8>,
643#if LLVM_ENABLE_ABI_BREAKING_CHECKS
651 "From has to be a valid CFG node or a virtual root");
652 assert(To &&
"Cannot be a nullptr");
663 FromTN = DT.createNode(
From, VirtualRoot);
664 DT.Roots.push_back(
From);
667 DT.DFSInfoValid =
false;
684 if (!DT.isVirtualRoot(To->
getIDom()))
return false;
690 <<
" is no longer a root\n\t\tRebuilding the tree!!!\n");
698 if (
A.size() !=
B.size())
702 if (Set.count(
N) == 0)
715 return HasForwardSuccessors(N, BUI);
728 <<
"The entire tree needs to be rebuilt\n");
746 ? DT.findNearestCommonDominator(
From->getBlock(), To->
getBlock())
748 assert(NCDBlock || DT.isPostDominator());
753 const unsigned NCDLevel = NCD->
getLevel();
771 II.Visited.insert(To);
773 while (!
II.Bucket.empty()) {
776 II.Affected.push_back(TN);
778 const unsigned CurrentLevel = TN->
getLevel();
780 "as affected, CurrentLevel " << CurrentLevel <<
"\n");
793 for (
const NodePtr Succ : getChildren<IsPostDom>(TN->
getBlock(), BUI)) {
796 "Unreachable successor found at reachable insertion");
797 const unsigned SuccLevel = SuccTN->
getLevel();
800 <<
", level = " << SuccLevel <<
"\n");
809 if (SuccLevel <= NCDLevel + 1 || !
II.Visited.insert(SuccTN).second)
812 if (SuccLevel > CurrentLevel) {
817 UnaffectedOnCurrentLevel.
push_back(SuccTN);
818#if LLVM_ENABLE_ABI_BREAKING_CHECKS
819 II.VisitedUnaffected.push_back(SuccTN);
825 <<
" to a Bucket\n");
826 II.Bucket.push(SuccTN);
830 if (UnaffectedOnCurrentLevel.
empty())
852#if LLVM_ENABLE_ABI_BREAKING_CHECKS && !defined(NDEBUG)
855 "TN should have been updated by an affected ancestor");
878 for (
const auto &Edge : DiscoveredEdgesToReachable) {
891 &DiscoveredConnectingEdges) {
892 assert(!DT.getNode(Root) &&
"Root must not be reachable");
895 auto UnreachableDescender = [&DT, &DiscoveredConnectingEdges](
NodePtr From,
898 if (!ToTN)
return true;
900 DiscoveredConnectingEdges.push_back({
From, ToTN});
905 SNCA.
runDFS(Root, 0, UnreachableDescender, 0);
914 assert(
From && To &&
"Cannot disconnect nullptrs");
918#if LLVM_ENABLE_ABI_BREAKING_CHECKS
922 auto IsSuccessor = [BUI](
const NodePtr SuccCandidate,
const NodePtr Of) {
923 auto Successors = getChildren<IsPostDom>(Of, BUI);
927 assert(!IsSuccessor(To,
From) &&
"Deleted edge still exists in the CFG!");
938 <<
") already unreachable -- there is no edge to delete\n");
942 const NodePtr NCDBlock = DT.findNearestCommonDominator(
From, To);
947 DT.DFSInfoValid =
false;
976 assert(ToIDom || DT.isPostDominator());
982 if (!PrevIDomSubTree) {
989 const unsigned Level = ToIDomTN->
getLevel();
991 return DT.getNode(To)->getLevel() > Level;
998 SNCA.
runDFS(ToIDom, 0, DescendBelow, 0);
1011 for (
const NodePtr Pred : getChildren<!IsPostDom>(TNB, BUI)) {
1013 if (!DT.getNode(Pred))
continue;
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) {
1057 if (TN->
getLevel() > Level)
return true;
1065 unsigned LastDFSNum =
1072 for (
const NodePtr N : AffectedQueue) {
1076 assert(NCDBlock || DT.isPostDominator());
1095 for (
unsigned i = LastDFSNum; i > 0; --i) {
1103 if (MinNode == ToTN)
return;
1105 LLVM_DEBUG(
dbgs() <<
"DeleteUnreachable: running DFS with MinNode = "
1107 const unsigned MinLevel = MinNode->
getLevel();
1115 return ToTN && ToTN->
getLevel() > MinLevel;
1136 if (NumUpdates == 0)
1141 if (NumUpdates == 1) {
1144 if (Update.getKind() == UpdateKind::Insert)
1145 InsertEdge(DT,
nullptr, Update.getFrom(), Update.getTo());
1147 DeleteEdge(DT,
nullptr, Update.getFrom(), Update.getTo());
1150 if (Update.getKind() == UpdateKind::Insert)
1151 InsertEdge(DT, &BUI, Update.getFrom(), Update.getTo());
1153 DeleteEdge(DT, &BUI, Update.getFrom(), Update.getTo());
1167 if (DT.DomTreeNodes.size() <= 100) {
1170 }
else if (BUI.
NumLegalized > DT.DomTreeNodes.size() / 40)
1191 if (CurrentUpdate.getKind() == UpdateKind::Insert)
1192 InsertEdge(DT, &BUI, CurrentUpdate.getFrom(), CurrentUpdate.getTo());
1194 DeleteEdge(DT, &BUI, CurrentUpdate.getFrom(), CurrentUpdate.getTo());
1207 if (!DT.Parent && !DT.Roots.empty()) {
1208 errs() <<
"Tree has no parent but has roots!\n";
1214 if (DT.Roots.empty()) {
1215 errs() <<
"Tree doesn't have a root!\n";
1221 errs() <<
"Tree's root is not its parent's entry node!\n";
1229 errs() <<
"Tree has different roots than freshly computed ones!\n";
1230 errs() <<
"\tPDT roots: ";
1232 errs() <<
"\n\tComputed roots: ";
1233 for (
const NodePtr N : ComputedRoots)
1249 for (
auto &NodeToTN : DT.DomTreeNodes) {
1256 if (DT.isVirtualRoot(TN))
continue;
1260 <<
" not found by DFS walk!\n";
1268 if (
N && !DT.getNode(
N)) {
1270 <<
" not found in the DomTree!\n";
1284 for (
auto &NodeToTN : DT.DomTreeNodes) {
1292 if (!IDom && TN->
getLevel() != 0) {
1294 <<
" has a nonzero level " << TN->
getLevel() <<
"!\n";
1302 << TN->
getLevel() <<
" while its IDom "
1318 if (!DT.DFSInfoValid || !DT.Parent)
1324 auto PrintNodeAndDFSNums = [](
const TreeNodePtr TN) {
1326 << TN->getDFSNumOut() <<
'}';
1332 errs() <<
"DFSIn number for the tree root is not:\n\t";
1333 PrintNodeAndDFSNums(Root);
1341 for (
const auto &NodeToTN : DT.DomTreeNodes) {
1347 if (
Node->isLeaf()) {
1348 if (
Node->getDFSNumIn() + 1 !=
Node->getDFSNumOut()) {
1349 errs() <<
"Tree leaf should have DFSOut = DFSIn + 1:\n\t";
1350 PrintNodeAndDFSNums(
Node);
1366 auto PrintChildrenError = [
Node, &Children, PrintNodeAndDFSNums](
1370 errs() <<
"Incorrect DFS numbers for:\n\tParent ";
1371 PrintNodeAndDFSNums(
Node);
1373 errs() <<
"\n\tChild ";
1374 PrintNodeAndDFSNums(FirstCh);
1377 errs() <<
"\n\tSecond child ";
1378 PrintNodeAndDFSNums(SecondCh);
1381 errs() <<
"\nAll children: ";
1383 PrintNodeAndDFSNums(Ch);
1391 if (Children.front()->getDFSNumIn() !=
Node->getDFSNumIn() + 1) {
1392 PrintChildrenError(Children.front(),
nullptr);
1396 if (Children.back()->getDFSNumOut() + 1 !=
Node->getDFSNumOut()) {
1397 PrintChildrenError(Children.back(),
nullptr);
1401 for (
size_t i = 0, e = Children.size() - 1; i != e; ++i) {
1402 if (Children[i]->getDFSNumOut() + 1 != Children[i + 1]->getDFSNumIn()) {
1403 PrintChildrenError(Children[i], Children[i + 1]);
1456 for (
auto &NodeToTN : DT.DomTreeNodes) {
1468 return From != BB && To != BB;
1475 <<
" is removed!\n";
1492 for (
auto &NodeToTN : DT.DomTreeNodes) {
1504 return From != BBN && To != BBN;
1508 if (S ==
N)
continue;
1513 <<
" is removed!\n";
1534 FreshTree.recalculate(*DT.Parent);
1535 const bool Different = DT.compare(FreshTree);
1538 errs() << (DT.isPostDominator() ?
"Post" :
"")
1539 <<
"DominatorTree is different than a freshly computed one!\n"
1542 errs() <<
"\n\tFreshly computed tree:\n";
1543 FreshTree.print(
errs());
1551template <
class DomTreeT>
1556template <
typename DomTreeT>
1567template <
class DomTreeT>
1569 typename DomTreeT::NodePtr To) {
1574template <
class DomTreeT>
1576 typename DomTreeT::NodePtr To) {
1581template <
class DomTreeT>
1584 DomTreeT::IsPostDominator> &PreViewCFG,
1586 DomTreeT::IsPostDominator> *PostViewCFG) {
1590template <
class DomTreeT>
1591bool Verify(
const DomTreeT &DT,
typename DomTreeT::VerificationLevel VL) {
1605 if (VL == DomTreeT::VerificationLevel::Basic ||
1606 VL == DomTreeT::VerificationLevel::Full)
1609 if (VL == DomTreeT::VerificationLevel::Full)
Unify divergent function exit nodes
BlockVerifier::State From
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
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
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file defines the SmallPtrSet class.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
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
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 reserve(size_type N)
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.
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)
This is an optimization pass for GlobalISel generic memory operations.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
void erase(Container &C, ValueType V)
Wrapper function to remove a value from a container:
void sort(IteratorTy Start, IteratorTy End)
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.
raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
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)
SmallVector< unsigned, 4 > ReverseChildren
bool operator()(TreeNodePtr LHS, TreeNodePtr RHS) const
std::priority_queue< TreeNodePtr, SmallVector< TreeNodePtr, 8 >, Compare > Bucket
SmallVector< TreeNodePtr, 8 > Affected
SmallDenseSet< TreeNodePtr, 8 > Visited
SemiNCAInfo(BatchUpdatePtr BUI)
static SmallVector< NodePtr, 8 > getChildren(NodePtr N)
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)
NodePtr getIDom(NodePtr BB)
InfoRec & getNodeInfo(NodePtr BB)
void doFullDFSWalk(const DomTreeT &DT, DescendCondition DC)
DenseMap< NodePtr, unsigned > NodeOrderMap
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)
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)
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)
SmallVector< NodePtr, 64 > NumToNode
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 void CalculateFromScratch(DomTreeT &DT, BatchUpdatePtr BUI)
TreeNodePtr getNodeForBlock(NodePtr BB, DomTreeT &DT)
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)
static void InsertUnreachable(DomTreeT &DT, const BatchUpdatePtr BUI, const TreeNodePtr From, const NodePtr To)
static void ApplyNextUpdate(DomTreeT &DT, BatchUpdateInfo &BUI)
static bool VerifyDFSNumbers(const DomTreeT &DT)
static void DeleteUnreachable(DomTreeT &DT, const BatchUpdatePtr BUI, const TreeNodePtr ToTN)
void attachNewSubtree(DomTreeT &DT, const TreeNodePtr AttachTo)
static void InsertEdge(DomTreeT &DT, const BatchUpdatePtr BUI, const NodePtr From, const NodePtr To)
BatchUpdateInfo * BatchUpdates
bool verifyParentProperty(const DomTreeT &DT)
bool verifyRoots(const DomTreeT &DT)
std::conditional_t< GraphHasNodeNumbers< NodePtr >, SmallVector< InfoRec, 64 >, DenseMap< NodePtr, InfoRec > > NodeInfos
Incoming for lane maks phi as machine instruction, incoming register Reg and incoming block Block are...