24#ifndef LLVM_SUPPORT_GENERICDOMTREE_H
25#define LLVM_SUPPORT_GENERICDOMTREE_H
46template <
typename NodeT,
bool IsPostDom>
52template <
typename DomTreeT>
70 mutable unsigned DFSNumIn = ~0;
71 mutable unsigned DFSNumOut = ~0;
75 : TheBB(BB), IDom(iDom), Level(IDom ? IDom->Level + 1 : 0) {}
88 return Other.Node == Node;
118 assert(!
C->Sibling &&
"cannot add child that already has siblings");
119 assert(!*AppendPtr &&
"sibling of last child must be nullptr");
121 AppendPtr = &
C->Sibling;
128 assert(*It !=
nullptr &&
"Not in immediate dominator children list!");
129 It = &(*It)->Sibling;
131 assert(!*AppendPtr &&
"sibling of last child must be nullptr");
132 assert(
C->Sibling || AppendPtr == &
C->Sibling);
135 C->Sibling =
nullptr;
140 bool isLeaf()
const {
return FirstChild ==
nullptr; }
143 if (Level !=
Other->Level)
return true;
147 const NodeT *Nd =
I->getBlock();
153 const NodeT *
N =
I->getBlock();
154 if (OtherChildren.
count(
N) == 0)
158 return OwnCount != OtherChildren.
size();
162 assert(IDom &&
"No immediate dominator?");
163 if (IDom == NewIDom)
return;
164 IDom->removeChild(
this);
183 return this->DFSNumIn >= other->DFSNumIn &&
184 this->DFSNumOut <= other->DFSNumOut;
189 if (Level == IDom->Level + 1)
return;
193 while (!WorkStack.empty()) {
195 Current->Level = Current->IDom->Level + 1;
199 if (
C->Level !=
C->IDom->Level + 1) WorkStack.push_back(
C);
205template <
class NodeT>
207 if (
Node->getBlock())
210 O <<
" <<exit node>>";
212 O <<
" {" <<
Node->getDFSNumIn() <<
"," <<
Node->getDFSNumOut() <<
"} ["
213 <<
Node->getLevel() <<
"]\n";
218template <
class NodeT>
221 O.indent(2 * Lev) <<
"[" << Lev <<
"] " <<
N;
222 for (
const auto &
I : *
N)
226namespace DomTreeBuilder {
228template <
typename DomTreeT>
231template <
typename DomTreeT>
235template <
typename DomTreeT>
236void InsertEdge(DomTreeT &DT,
typename DomTreeT::NodePtr From,
237 typename DomTreeT::NodePtr To);
239template <
typename DomTreeT>
240void DeleteEdge(DomTreeT &DT,
typename DomTreeT::NodePtr From,
241 typename DomTreeT::NodePtr To);
243template <
typename DomTreeT>
245 GraphDiff<
typename DomTreeT::NodePtr,
246 DomTreeT::IsPostDominator> &PreViewCFG,
247 GraphDiff<
typename DomTreeT::NodePtr,
248 DomTreeT::IsPostDominator> *PostViewCFG);
250template <
typename DomTreeT>
251bool Verify(
const DomTreeT &DT,
typename DomTreeT::VerificationLevel VL);
259 using ParentPtr =
decltype(std::declval<NodePtr>()->getParent());
260 static_assert(std::is_pointer_v<ParentPtr>,
261 "Currently NodeT's parent must be a pointer type");
272template <
typename NodeT,
bool IsPostDom>
275 static_assert(std::is_pointer_v<typename GraphTraits<NodeT *>::NodeRef>,
276 "Currently DominatorTreeBase supports only pointer nodes");
281 static_assert(std::is_pointer_v<ParentPtr>,
282 "Currently NodeT's parent must be a pointer type");
301 std::conditional_t<!GraphHasNodeNumbers<NodeT *>,
366 if (!std::is_permutation(
Roots.begin(),
Roots.end(),
Other.Roots.begin()))
380 size_t NumOtherNodes = 0;
381 for (
const auto &OtherNode :
Other.DomTreeNodes)
384 return NumNodes != NumOtherNodes;
395 std::optional<unsigned> getNodeIndex(
const NodeT *BB)
const {
398 GraphTraits<ParentPtr>::getNumberEpoch(
Parent) &&
399 "dominator tree used with outdated block numbers");
400 if constexpr (IsPostDom) {
404 assert(BB &&
"dominator tree block must be non-null");
405 return GraphTraits<const NodeT *>::getNumber(BB) + 1;
413 unsigned getNodeIndexForInsert(
const NodeT *BB) {
416 unsigned Idx = *getNodeIndex(BB);
418 unsigned Max = GraphTraits<ParentPtr>::getMaxNumber(
Parent);
439 "cannot get DomTreeNode of block with different parent");
440 if (
auto Idx = getNodeIndex(BB); Idx && *Idx <
DomTreeNodes.size())
469 while (!WL.
empty()) {
471 Result.push_back(
N->getBlock());
494 "This is not implemented for post dominators");
517 if (
B->getIDom() ==
A)
return true;
519 if (
A->getIDom() ==
B)
return false;
522 if (
A->getLevel() >=
B->getLevel())
return false;
526#ifdef EXPENSIVE_CHECKS
528 (dominatedBySlowTreeWalk(
A,
B) ==
B->DominatedBy(
A))) &&
529 "Tree walk disagrees with dfs numbers!");
533 return B->DominatedBy(
A);
540 return B->DominatedBy(
A);
543 return dominatedBySlowTreeWalk(
A,
B);
549 assert(this->Roots.
size() == 1 &&
"Should always have entry node!");
550 return this->Roots[0];
556 assert(
A &&
B &&
"Pointers are not valid");
558 "Two blocks are not in same function");
565 if (
A == &Entry ||
B == &Entry)
571 assert(NodeA &&
"A must be in the tree");
572 assert(NodeB &&
"B must be in the tree");
576 while (NodeA != NodeB) {
586 const NodeT *
B)
const {
590 const_cast<NodeT *
>(
B));
597 template <
typename IteratorTy>
601 NodeT *NCD = *Nodes.
begin();
661 if (Updates.
empty()) {
724 assert(
getNode(BB) ==
nullptr &&
"Block already in dominator tree!");
726 assert(IDomNode &&
"Not immediate dominator specified for block!");
737 assert(
getNode(BB) ==
nullptr &&
"Block already in dominator tree!");
739 "Cannot change root of post-dominator tree");
740 DFSInfoValid =
false;
746 NodeT *OldRoot =
Roots.front();
749 OldNode->IDom = NewNode;
750 OldNode->UpdateLevel();
761 assert(
N && NewIDom &&
"Cannot change null node pointers!");
774 std::optional<unsigned> IdxOpt = getNodeIndex(BB);
776 "Removing node that isn't in dominator tree.");
778 assert(
Node->isLeaf() &&
"Node is not a leaf node.");
790 if (!IsPostDom)
return;
794 if (RIt !=
Roots.end()) {
812 O <<
"=============================--------------------------------\n";
814 O <<
"Inorder PostDominator Tree: ";
816 O <<
"Inorder Dominator Tree: ";
818 O <<
"DFSNumbers invalid: " <<
SlowQueries <<
" slow queries.";
825 Block->printAsOperand(O,
false);
845 assert((!
Parent || ThisRoot) &&
"Empty constructed DomTree");
854 ThisRoot->DFSNumIn = DFSNum++;
856 while (!WorkStack.
empty()) {
858 const auto ChildIt = WorkStack.
back().second;
862 if (ChildIt ==
Node->end()) {
863 Node->DFSNumOut = DFSNum;
868 ++WorkStack.
back().second;
871 Child->DFSNumIn = DFSNum++;
880 void updateBlockNumberEpoch() {
890 updateBlockNumberEpoch();
896 updateBlockNumberEpoch();
901 template <
typename T = NodeT>
903 updateBlockNumberEpoch();
907 NewVector.
resize(MaxNumber + 1);
911 unsigned Idx = *getNodeIndex(
Node->getBlock());
913 if (Idx >= NewVector.
size())
914 NewVector.
resize(Idx + 1);
915 NewVector[Idx] = std::move(
Node);
955 static_assert(std::is_trivially_destructible_v<DomTreeNodeBase<NodeT>>);
957 unsigned NodeIdx = getNodeIndexForInsert(BB);
969 using NodeRef =
typename GraphT::NodeRef;
971 "NewBB should have a single successor!");
972 NodeRef NewBBSucc = *GraphT::child_begin(NewBB);
978 bool NewBBDominatesNewBBSucc =
true;
980 if (Pred != NewBB && !
dominates(NewBBSucc, Pred) &&
982 NewBBDominatesNewBBSucc =
false;
989 NodeT *NewBBIDom =
nullptr;
991 for (i = 0; i < PredBlocks.
size(); ++i)
993 NewBBIDom = PredBlocks[i];
1000 if (!NewBBIDom)
return;
1002 for (i = i + 1; i < PredBlocks.
size(); ++i) {
1012 if (NewBBDominatesNewBBSucc) {
1025 const unsigned ALevel =
A->getLevel();
1030 while ((IDom =
B->getIDom()) !=
nullptr && IDom->
getLevel() >= ALevel)
1037template <
typename T>
1040template <
typename T>
1045template <
typename NodeT,
bool IsPostDom>
1047 const NodeT *
B)
const {
1053template <
typename NodeT,
bool IsPostDom>
1055 const NodeT *
A,
const NodeT *
B)
const {
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static msgpack::DocNode getNode(msgpack::DocNode DN, msgpack::Type Type, MCValue Val)
Unify divergent function exit nodes
This file defines the BumpPtrAllocator interface.
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
This file defines the DenseMap class.
This file defines the little GraphTraits<X> template class that should be specialized by classes that...
ppc ctr loops PowerPC CTR Loops Verify
static bool dominates(InstrPosIndexes &PosIndexes, const MachineInstr &A, const MachineInstr &B)
This file defines the SmallPtrSet class.
This file defines the SmallVector class.
void printAsOperand(OutputBuffer &OB, Prec P=Prec::Default, bool StrictlyWorse=false) const
Represent a constant reference to an array (0 or more elements consecutively in memory),...
bool empty() const
Check if the array is empty.
Allocate memory in an ever growing pool, as if by bump-pointer.
const_iterator & operator++()
bool operator==(const const_iterator &Other) const
DomTreeNodeBase * operator*() const
const_iterator operator++(int)
const_iterator(DomTreeNodeBase *Node=nullptr)
Base class for the actual dominator tree node.
iterator_range< iterator > children()
DomTreeNodeBase(const DomTreeNodeBase &)=delete
void setIDom(DomTreeNodeBase *NewIDom)
void removeChild(DomTreeNodeBase *C)
DomTreeNodeBase * getIDom() const
unsigned getDFSNumIn() const
getDFSNumIn/getDFSNumOut - These return the DFS visitation order for nodes in the dominator tree.
DomTreeNodeBase & operator=(const DomTreeNodeBase &)=delete
DomTreeNodeBase(NodeT *BB, DomTreeNodeBase *iDom)
bool compare(const DomTreeNodeBase *Other) const
friend class PostDominatorTree
unsigned getLevel() const
iterator_range< const_iterator > children() const
unsigned getDFSNumOut() const
void addChild(DomTreeNodeBase *C)
Core dominator tree base class.
DominatorTreeBase(DominatorTreeBase &&Arg)=default
DomTreeNodeTraits< BlockT > NodeTrait
bool isReachableFromEntry(const DomTreeNodeBase< NodeT > *A) const
void print(raw_ostream &O) const
print - Convert to human readable form
typename NodeTrait::NodeType NodeType
DomTreeNodeBase< NodeT > * operator[](const NodeT *BB) const
See getNode.
typename SmallVectorImpl< BlockT * >::iterator root_iterator
DomTreeNodeBase< NodeT > * getRootNode()
getRootNode - This returns the entry node for the CFG of the function.
bool verify(VerificationLevel VL=VerificationLevel::Full) const
verify - checks if the tree is correct.
void changeImmediateDominator(NodeT *BB, NodeT *NewBB)
NodeT * findNearestCommonDominator(NodeT *A, NodeT *B) const
Find nearest common dominator basic block for basic block A and B.
DominatorTreeBase()=default
void Split(typename GraphTraits< N >::NodeRef NewBB)
iterator_range< root_iterator > roots()
void changeImmediateDominator(DomTreeNodeBase< NodeT > *N, DomTreeNodeBase< NodeT > *NewIDom)
changeImmediateDominator - This method is used to update the dominator tree information when a node's...
std::remove_pointer_t< ParentPtr > ParentType
NodeT * findNearestCommonDominator(iterator_range< IteratorTy > Nodes) const
BumpPtrAllocatorImpl< MallocAllocator, SlabSize, SlabSize, 2 > NodeAllocator
bool isPostDominator() const
isPostDominator - Returns true if analysis based of postdoms
bool dominates(const NodeT *A, const NodeT *B) const
const NodeT * findNearestCommonDominator(const NodeT *A, const NodeT *B) const
void getDescendants(NodeT *R, SmallVectorImpl< NodeT * > &Result) const
Get all nodes dominated by R, including R itself.
DomTreeNodeBase< NodeT > * addNewBlock(NodeT *BB, NodeT *DomBB)
Add a new node to the dominator tree information.
DomTreeNodeBase< NodeT > * createNode(NodeT *BB, DomTreeNodeBase< NodeT > *IDom=nullptr)
void applyUpdates(ArrayRef< UpdateType > Updates)
Inform the dominator tree about a sequence of CFG edge insertions and deletions and perform a batch u...
static constexpr size_t SlabSize
void insertEdge(NodeT *From, NodeT *To)
Inform the dominator tree about a CFG edge insertion and update the tree.
std::enable_if_t< GraphHasNodeNumbers< T * >, void > updateBlockNumbers()
Update dominator tree after renumbering blocks.
bool dominates(const DomTreeNodeBase< NodeT > *A, const DomTreeNodeBase< NodeT > *B) const
dominates - Returns true iff A dominates B.
iterator_range< const_root_iterator > roots() const
const_root_iterator root_end() const
void splitBlock(NodeT *NewBB)
splitBlock - BB is split and now it has one successor.
static constexpr UpdateKind Delete
void recalculate(ParentType &Func, ArrayRef< UpdateType > Updates)
void updateDFSNumbers() const
updateDFSNumbers - Assign In and Out numbers to the nodes while walking dominator tree in dfs order.
typename SmallVectorImpl< BlockT * >::const_iterator const_root_iterator
bool compare(const DominatorTreeBase &Other) const
compare - Return false if the other dominator tree base matches this dominator tree base.
DominatorTreeBase & operator=(DominatorTreeBase &&RHS)=default
DomTreeNodeBase< NodeT > * setNewRoot(NodeT *BB)
Add a new node to the forward dominator tree and make it a new root.
SmallVector< DomTreeNodeBase< BlockT > * > DomTreeNodeStorageTy
root_iterator root_begin()
DominatorTreeBase(const DominatorTreeBase &)=delete
static constexpr UpdateKind Insert
const_root_iterator root_begin() const
void recalculate(ParentType &Func)
recalculate - compute a dominator tree for the given function
SmallVector< BlockT *, IsPostDom ? 4 :1 > Roots
void eraseNode(NodeT *BB)
eraseNode - Removes a node from the dominator tree.
void deleteEdge(NodeT *From, NodeT *To)
Inform the dominator tree about a CFG edge deletion and update the tree.
const DomTreeNodeBase< NodeT > * getRootNode() const
std::conditional_t<!GraphHasNodeNumbers< BlockT * >, DenseMap< const BlockT *, unsigned >, std::tuple<> > NodeNumberMap
DomTreeNodeBase< BlockT > * RootNode
typename NodeTrait::NodePtr NodePtr
bool isReachableFromEntry(const NodeT *A) const
isReachableFromEntry - Return true if A is dominated by the entry block of the function containing it...
cfg::Update< NodePtr > UpdateType
cfg::UpdateKind UpdateKind
void applyUpdates(ArrayRef< UpdateType > Updates, ArrayRef< UpdateType > PostViewUpdates)
unsigned BlockNumberEpoch
DomTreeNodeStorageTy DomTreeNodes
DomTreeNodeBase< NodeT > * getNode(const NodeT *BB) const
getNode - return the (Post)DominatorTree node for the specified basic block.
bool properlyDominates(const NodeT *A, const NodeT *B) const
bool properlyDominates(const DomTreeNodeBase< NodeT > *A, const DomTreeNodeBase< NodeT > *B) const
properlyDominates - Returns true iff A dominates B and A != B.
bool isVirtualRoot(const DomTreeNodeBase< NodeT > *A) const
typename NodeTrait::ParentPtr ParentPtr
DominatorTreeBase & operator=(const DominatorTreeBase &)=delete
friend class LoopInfoBase
static constexpr bool IsPostDominator
This class builds and contains all of the top-level loop structures in the specified function.
size_type count(ConstPtrType Ptr) const
count - Return 1 if the specified pointer is in the set, 0 otherwise.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
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...
typename SuperClass::const_iterator const_iterator
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
typename SuperClass::iterator iterator
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
CRTP base class which implements the entire standard iterator facade in terms of a minimal subset of ...
A range adaptor for a pair of iterators.
This class implements an extremely fast bulk output stream that can only output to a stream.
@ C
The default llvm calling convention, compatible with C.
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)
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.
auto find(R &&Range, const T &Val)
Provide wrappers to std::find which take ranges instead of having to pass begin/end explicitly.
void PrintDomTree(const DomTreeNodeBase< NodeT > *N, raw_ostream &O, unsigned Lev)
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
constexpr bool GraphHasNodeNumbers
Indicate whether a GraphTraits<NodeT>::getNumber() is supported.
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
DominatorTreeBase< T, true > PostDomTreeBase
DominatorTreeBase< T, false > DomTreeBase
bool hasSingleElement(ContainerTy &&C)
Returns true if the given container only contains a single element.
iterator_range< filter_iterator< detail::IterOfRange< RangeT >, PredicateT > > make_filter_range(RangeT &&Range, PredicateT Pred)
Convenience function that takes a range of elements and a predicate, and return a new filter_iterator...
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
iterator_range< typename GraphTraits< Inverse< GraphType > >::ChildIteratorType > inverse_children(const typename GraphTraits< GraphType >::NodeRef &G)
raw_ostream & operator<<(raw_ostream &OS, const APFixedPoint &FX)
ArrayRef(const T &OneElt) -> ArrayRef< T >
iterator_range< typename GraphTraits< GraphType >::ChildIteratorType > children(const typename GraphTraits< GraphType >::NodeRef &G)
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Default DomTreeNode traits for NodeT.
static NodeT * getEntryNode(ParentPtr Parent)
std::remove_pointer_t< ParentPtr > ParentType
static ParentPtr getParent(NodePtr BB)
decltype(std::declval< NodePtr >() ->getParent()) ParentPtr
typename GraphType::UnknownGraphTypeError NodeRef