24#ifndef LLVM_SUPPORT_GENERICDOMTREE_H
25#define LLVM_SUPPORT_GENERICDOMTREE_H
46template <
typename NodeT,
bool IsPostDom>
50template <
typename DomTreeT>
68 mutable unsigned DFSNumIn = ~0;
69 mutable unsigned DFSNumOut = ~0;
73 : TheBB(BB), IDom(iDom), Level(IDom ? IDom->Level + 1 : 0) {}
86 return Other.Node == Node;
116 assert(!
C->Sibling &&
"cannot add child that already has siblings");
117 assert(!*AppendPtr &&
"sibling of last child must be nullptr");
119 AppendPtr = &
C->Sibling;
126 assert(*It !=
nullptr &&
"Not in immediate dominator children list!");
127 It = &(*It)->Sibling;
129 assert(!*AppendPtr &&
"sibling of last child must be nullptr");
130 assert(
C->Sibling || AppendPtr == &
C->Sibling);
133 C->Sibling =
nullptr;
138 bool isLeaf()
const {
return FirstChild ==
nullptr; }
141 if (Level !=
Other->Level)
return true;
145 const NodeT *Nd =
I->getBlock();
151 const NodeT *
N =
I->getBlock();
152 if (OtherChildren.
count(
N) == 0)
156 return OwnCount != OtherChildren.
size();
160 assert(IDom &&
"No immediate dominator?");
161 if (IDom == NewIDom)
return;
162 IDom->removeChild(
this);
181 return this->DFSNumIn >= other->DFSNumIn &&
182 this->DFSNumOut <= other->DFSNumOut;
187 if (Level == IDom->Level + 1)
return;
191 while (!WorkStack.empty()) {
193 Current->Level = Current->IDom->Level + 1;
197 if (
C->Level !=
C->IDom->Level + 1) WorkStack.push_back(
C);
203template <
class NodeT>
205 if (
Node->getBlock())
208 O <<
" <<exit node>>";
210 O <<
" {" <<
Node->getDFSNumIn() <<
"," <<
Node->getDFSNumOut() <<
"} ["
211 <<
Node->getLevel() <<
"]\n";
216template <
class NodeT>
219 O.indent(2 * Lev) <<
"[" << Lev <<
"] " <<
N;
220 for (
const auto &
I : *
N)
224namespace DomTreeBuilder {
226template <
typename DomTreeT>
229template <
typename DomTreeT>
233template <
typename DomTreeT>
234void InsertEdge(DomTreeT &DT,
typename DomTreeT::NodePtr From,
235 typename DomTreeT::NodePtr To);
237template <
typename DomTreeT>
238void DeleteEdge(DomTreeT &DT,
typename DomTreeT::NodePtr From,
239 typename DomTreeT::NodePtr To);
241template <
typename DomTreeT>
243 GraphDiff<
typename DomTreeT::NodePtr,
244 DomTreeT::IsPostDominator> &PreViewCFG,
245 GraphDiff<
typename DomTreeT::NodePtr,
246 DomTreeT::IsPostDominator> *PostViewCFG);
248template <
typename DomTreeT>
249bool Verify(
const DomTreeT &DT,
typename DomTreeT::VerificationLevel VL);
257 using ParentPtr =
decltype(std::declval<NodePtr>()->getParent());
258 static_assert(std::is_pointer_v<ParentPtr>,
259 "Currently NodeT's parent must be a pointer type");
270template <
typename NodeT,
bool IsPostDom>
273 static_assert(std::is_pointer_v<typename GraphTraits<NodeT *>::NodeRef>,
274 "Currently DominatorTreeBase supports only pointer nodes");
279 static_assert(std::is_pointer_v<ParentPtr>,
280 "Currently NodeT's parent must be a pointer type");
299 std::conditional_t<!GraphHasNodeNumbers<NodeT *>,
363 if (!std::is_permutation(
Roots.begin(),
Roots.end(),
Other.Roots.begin()))
377 size_t NumOtherNodes = 0;
378 for (
const auto &OtherNode :
Other.DomTreeNodes)
381 return NumNodes != NumOtherNodes;
385 std::optional<unsigned> getNodeIndex(
const NodeT *BB)
const {
389 "dominator tree used with outdated block numbers");
390 if constexpr (IsPostDom) {
394 assert(BB &&
"dominator tree block must be non-null");
395 return GraphTraits<const NodeT *>::getNumber(BB) + 1;
403 unsigned getNodeIndexForInsert(
const NodeT *BB) {
406 unsigned Idx = *getNodeIndex(BB);
408 unsigned Max = GraphTraits<ParentPtr>::getMaxNumber(
Parent);
429 "cannot get DomTreeNode of block with different parent");
430 if (
auto Idx = getNodeIndex(BB); Idx && *Idx <
DomTreeNodes.size())
459 while (!WL.
empty()) {
461 Result.push_back(
N->getBlock());
484 "This is not implemented for post dominators");
507 if (
B->getIDom() ==
A)
return true;
509 if (
A->getIDom() ==
B)
return false;
512 if (
A->getLevel() >=
B->getLevel())
return false;
516#ifdef EXPENSIVE_CHECKS
518 (dominatedBySlowTreeWalk(
A,
B) ==
B->DominatedBy(
A))) &&
519 "Tree walk disagrees with dfs numbers!");
523 return B->DominatedBy(
A);
530 return B->DominatedBy(
A);
533 return dominatedBySlowTreeWalk(
A,
B);
539 assert(this->Roots.
size() == 1 &&
"Should always have entry node!");
540 return this->Roots[0];
546 assert(
A &&
B &&
"Pointers are not valid");
548 "Two blocks are not in same function");
555 if (
A == &Entry ||
B == &Entry)
561 assert(NodeA &&
"A must be in the tree");
562 assert(NodeB &&
"B must be in the tree");
566 while (NodeA != NodeB) {
576 const NodeT *
B)
const {
580 const_cast<NodeT *
>(
B));
587 template <
typename IteratorTy>
591 NodeT *NCD = *Nodes.
begin();
651 if (Updates.
empty()) {
714 assert(
getNode(BB) ==
nullptr &&
"Block already in dominator tree!");
716 assert(IDomNode &&
"Not immediate dominator specified for block!");
727 assert(
getNode(BB) ==
nullptr &&
"Block already in dominator tree!");
729 "Cannot change root of post-dominator tree");
730 DFSInfoValid =
false;
736 NodeT *OldRoot =
Roots.front();
739 OldNode->IDom = NewNode;
740 OldNode->UpdateLevel();
751 assert(
N && NewIDom &&
"Cannot change null node pointers!");
764 std::optional<unsigned> IdxOpt = getNodeIndex(BB);
766 "Removing node that isn't in dominator tree.");
768 assert(
Node->isLeaf() &&
"Node is not a leaf node.");
780 if (!IsPostDom)
return;
784 if (RIt !=
Roots.end()) {
802 O <<
"=============================--------------------------------\n";
804 O <<
"Inorder PostDominator Tree: ";
806 O <<
"Inorder Dominator Tree: ";
808 O <<
"DFSNumbers invalid: " <<
SlowQueries <<
" slow queries.";
815 Block->printAsOperand(O,
false);
835 assert((!
Parent || ThisRoot) &&
"Empty constructed DomTree");
844 ThisRoot->DFSNumIn = DFSNum++;
846 while (!WorkStack.
empty()) {
848 const auto ChildIt = WorkStack.
back().second;
852 if (ChildIt ==
Node->end()) {
853 Node->DFSNumOut = DFSNum++;
858 ++WorkStack.
back().second;
861 Child->DFSNumIn = DFSNum++;
870 void updateBlockNumberEpoch() {
880 updateBlockNumberEpoch();
886 updateBlockNumberEpoch();
891 template <
typename T = NodeT>
893 updateBlockNumberEpoch();
897 NewVector.
resize(MaxNumber + 1);
901 unsigned Idx = *getNodeIndex(
Node->getBlock());
903 if (Idx >= NewVector.
size())
904 NewVector.
resize(Idx + 1);
905 NewVector[Idx] = std::move(
Node);
945 static_assert(std::is_trivially_destructible_v<DomTreeNodeBase<NodeT>>);
947 unsigned NodeIdx = getNodeIndexForInsert(BB);
959 using NodeRef =
typename GraphT::NodeRef;
961 "NewBB should have a single successor!");
962 NodeRef NewBBSucc = *GraphT::child_begin(NewBB);
968 bool NewBBDominatesNewBBSucc =
true;
970 if (Pred != NewBB && !
dominates(NewBBSucc, Pred) &&
972 NewBBDominatesNewBBSucc =
false;
979 NodeT *NewBBIDom =
nullptr;
981 for (i = 0; i < PredBlocks.
size(); ++i)
983 NewBBIDom = PredBlocks[i];
990 if (!NewBBIDom)
return;
992 for (i = i + 1; i < PredBlocks.
size(); ++i) {
1002 if (NewBBDominatesNewBBSucc) {
1015 const unsigned ALevel =
A->getLevel();
1020 while ((IDom =
B->getIDom()) !=
nullptr && IDom->
getLevel() >= ALevel)
1027template <
typename T>
1030template <
typename T>
1035template <
typename NodeT,
bool IsPostDom>
1037 const NodeT *
B)
const {
1043template <
typename NodeT,
bool IsPostDom>
1045 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)
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
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
bool empty() const
empty - 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
static constexpr bool IsPostDominator
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.
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