24#ifndef LLVM_SUPPORT_GENERICDOMTREE_H
25#define LLVM_SUPPORT_GENERICDOMTREE_H
45template <
typename NodeT,
bool IsPostDom>
46class DominatorTreeBase;
48namespace DomTreeBuilder {
49template <
typename DomTreeT>
65 mutable unsigned DFSNumIn = ~0;
66 mutable unsigned DFSNumOut = ~0;
70 : TheBB(BB), IDom(iDom), Level(IDom ? IDom->Level + 1 : 0) {}
95 bool isLeaf()
const {
return Children.empty(); }
104 if (Level !=
Other->Level)
return true;
108 const NodeT *Nd =
I->getBlock();
113 const NodeT *
N =
I->getBlock();
114 if (OtherChildren.
count(
N) == 0)
121 assert(IDom &&
"No immediate dominator?");
122 if (IDom == NewIDom)
return;
124 auto I =
find(IDom->Children,
this);
125 assert(
I != IDom->Children.end() &&
126 "Not in immediate dominator children set!");
128 IDom->Children.erase(
I);
132 IDom->Children.push_back(
this);
147 return this->DFSNumIn >= other->DFSNumIn &&
148 this->DFSNumOut <= other->DFSNumOut;
153 if (Level == IDom->Level + 1)
return;
155 SmallVector<DomTreeNodeBase *, 64> WorkStack = {
this};
157 while (!WorkStack.empty()) {
159 Current->Level = Current->IDom->Level + 1;
161 for (DomTreeNodeBase *
C : *Current) {
163 if (
C->Level !=
C->IDom->Level + 1) WorkStack.push_back(
C);
169template <
class NodeT>
171 if (
Node->getBlock())
174 O <<
" <<exit node>>";
176 O <<
" {" <<
Node->getDFSNumIn() <<
"," <<
Node->getDFSNumOut() <<
"} ["
177 <<
Node->getLevel() <<
"]\n";
182template <
class NodeT>
185 O.indent(2 * Lev) <<
"[" << Lev <<
"] " <<
N;
186 for (
const auto &
I : *
N)
187 PrintDomTree<NodeT>(
I, O, Lev + 1);
190namespace DomTreeBuilder {
192template <
typename DomTreeT>
195template <
typename DomTreeT>
197 ArrayRef<typename DomTreeT::UpdateType> Updates);
199template <
typename DomTreeT>
201 typename DomTreeT::NodePtr To);
203template <
typename DomTreeT>
205 typename DomTreeT::NodePtr To);
207template <
typename DomTreeT>
209 GraphDiff<
typename DomTreeT::NodePtr,
210 DomTreeT::IsPostDominator> &PreViewCFG,
211 GraphDiff<
typename DomTreeT::NodePtr,
212 DomTreeT::IsPostDominator> *PostViewCFG);
214template <
typename DomTreeT>
215bool Verify(
const DomTreeT &DT,
typename DomTreeT::VerificationLevel VL);
223 using ParentPtr =
decltype(std::declval<NodePtr>()->getParent());
224 static_assert(std::is_pointer_v<ParentPtr>,
225 "Currently NodeT's parent must be a pointer type");
236template <
typename NodeT,
bool IsPostDom>
239 static_assert(std::is_pointer_v<typename GraphTraits<NodeT *>::NodeRef>,
240 "Currently DominatorTreeBase supports only pointer nodes");
245 static_assert(std::is_pointer_v<ParentPtr>,
246 "Currently NodeT's parent must be a pointer type");
266 std::conditional_t<!GraphHasNodeNumbers<NodeT *>,
353 size_t NumOtherNodes = 0;
354 for (
const auto &OtherNode :
Other.DomTreeNodes)
357 return NumNodes != NumOtherNodes;
361 std::optional<unsigned> getNodeIndex(
const NodeT *BB)
const {
362 if constexpr (GraphHasNodeNumbers<NodeT *>) {
366 "dominator tree used with outdated block numbers");
375 unsigned getNodeIndexForInsert(
const NodeT *BB) {
376 if constexpr (GraphHasNodeNumbers<NodeT *>) {
378 unsigned Idx = *getNodeIndex(BB);
380 unsigned Max = GraphTraits<ParentPtr>::getMaxNumber(
Parent);
401 "cannot get DomTreeNode of block with different parent");
431 while (!WL.
empty()) {
433 Result.push_back(
N->getBlock());
456 "This is not implemented for post dominators");
479 if (
B->getIDom() ==
A)
return true;
481 if (
A->getIDom() ==
B)
return false;
484 if (
A->getLevel() >=
B->getLevel())
return false;
488#ifdef EXPENSIVE_CHECKS
490 (dominatedBySlowTreeWalk(
A,
B) ==
B->DominatedBy(
A))) &&
491 "Tree walk disagrees with dfs numbers!");
495 return B->DominatedBy(
A);
502 return B->DominatedBy(
A);
505 return dominatedBySlowTreeWalk(
A,
B);
511 assert(this->Roots.
size() == 1 &&
"Should always have entry node!");
512 return this->Roots[0];
518 assert(
A &&
B &&
"Pointers are not valid");
520 "Two blocks are not in same function");
527 if (
A == &Entry ||
B == &Entry)
533 assert(NodeA &&
"A must be in the tree");
534 assert(NodeB &&
"B must be in the tree");
538 while (NodeA != NodeB) {
548 const NodeT *
B)
const {
552 const_cast<NodeT *
>(
B));
607 if (Updates.
empty()) {
670 assert(
getNode(BB) ==
nullptr &&
"Block already in dominator tree!");
672 assert(IDomNode &&
"Not immediate dominator specified for block!");
683 assert(
getNode(BB) ==
nullptr &&
"Block already in dominator tree!");
685 "Cannot change root of post-dominator tree");
686 DFSInfoValid =
false;
695 OldNode->IDom = NewNode;
696 OldNode->UpdateLevel();
707 assert(
N && NewIDom &&
"Cannot change null node pointers!");
720 std::optional<unsigned> IdxOpt = getNodeIndex(BB);
722 "Removing node that isn't in dominator tree.");
724 assert(
Node->isLeaf() &&
"Node is not a leaf node.");
731 const auto I =
find(IDom->Children,
Node);
732 assert(
I != IDom->Children.end() &&
733 "Not in immediate dominator children set!");
736 IDom->Children.pop_back();
740 if constexpr (!GraphHasNodeNumbers<NodeT *>)
743 if (!IsPostDom)
return;
757 Split<Inverse<NodeT *>>(NewBB);
759 Split<NodeT *>(NewBB);
765 O <<
"=============================--------------------------------\n";
767 O <<
"Inorder PostDominator Tree: ";
769 O <<
"Inorder Dominator Tree: ";
771 O <<
"DFSNumbers invalid: " <<
SlowQueries <<
" slow queries.";
778 Block->printAsOperand(O,
false);
798 assert((!
Parent || ThisRoot) &&
"Empty constructed DomTree");
807 ThisRoot->DFSNumIn = DFSNum++;
809 while (!WorkStack.
empty()) {
811 const auto ChildIt = WorkStack.
back().second;
815 if (ChildIt ==
Node->end()) {
816 Node->DFSNumOut = DFSNum++;
821 ++WorkStack.
back().second;
824 Child->DFSNumIn = DFSNum++;
833 void updateBlockNumberEpoch() {
835 if constexpr (GraphHasNodeNumbers<NodeT *>)
843 updateBlockNumberEpoch();
849 updateBlockNumberEpoch();
854 template <
typename T = NodeT>
856 updateBlockNumberEpoch();
860 NewVector.
resize(MaxNumber + 1);
864 unsigned Idx = *getNodeIndex(
Node->getBlock());
868 NewVector[
Idx] = std::move(
Node);
893 if constexpr (!GraphHasNodeNumbers<NodeT *>)
907 auto Node = std::make_unique<DomTreeNodeBase<NodeT>>(BB, IDom);
909 unsigned NodeIdx = getNodeIndexForInsert(BB);
921 using NodeRef =
typename GraphT::NodeRef;
923 "NewBB should have a single successor!");
924 NodeRef NewBBSucc = *GraphT::child_begin(NewBB);
930 bool NewBBDominatesNewBBSucc =
true;
931 for (
auto *Pred : inverse_children<N>(NewBBSucc)) {
932 if (Pred != NewBB && !
dominates(NewBBSucc, Pred) &&
934 NewBBDominatesNewBBSucc =
false;
941 NodeT *NewBBIDom =
nullptr;
943 for (i = 0; i < PredBlocks.
size(); ++i)
945 NewBBIDom = PredBlocks[i];
952 if (!NewBBIDom)
return;
954 for (i = i + 1; i < PredBlocks.
size(); ++i) {
964 if (NewBBDominatesNewBBSucc) {
977 const unsigned ALevel =
A->getLevel();
982 while ((IDom =
B->getIDom()) !=
nullptr && IDom->
getLevel() >= ALevel)
994 if constexpr (!GraphHasNodeNumbers<NodeT *>)
1001template <
typename T>
1004template <
typename T>
1009template <
typename NodeT,
bool IsPostDom>
1011 const NodeT *
B)
const {
1021template <
typename NodeT,
bool IsPostDom>
1023 const NodeT *
A,
const NodeT *
B)
const {
static msgpack::DocNode getNode(msgpack::DocNode DN, msgpack::Type Type, MCValue Val)
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 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
const MachineOperand & RHS
static bool dominates(InstrPosIndexes &PosIndexes, const MachineInstr &A, const MachineInstr &B)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
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.
Base class for the actual dominator tree node.
iterator_range< iterator > children()
const_iterator end() const
DomTreeNodeBase *& back()
void setIDom(DomTreeNodeBase *NewIDom)
typename SmallVector< DomTreeNodeBase *, 4 >::iterator iterator
DomTreeNodeBase *const & back() const
DomTreeNodeBase * getIDom() const
unsigned getDFSNumIn() const
getDFSNumIn/getDFSNumOut - These return the DFS visitation order for nodes in the dominator tree.
size_t getNumChildren() const
DomTreeNodeBase(NodeT *BB, DomTreeNodeBase *iDom)
bool compare(const DomTreeNodeBase *Other) const
unsigned getLevel() const
iterator_range< const_iterator > children() const
unsigned getDFSNumOut() const
typename SmallVector< DomTreeNodeBase *, 4 >::const_iterator const_iterator
const_iterator begin() const
void addChild(DomTreeNodeBase *C)
Core dominator tree base class.
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< NodeT * >::iterator root_iterator
Iteration over roots.
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
DominatorTreeBase(DominatorTreeBase &&Arg)
bool isPostDominator() const
isPostDominator - Returns true if analysis based of postdoms
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...
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.
DominatorTreeBase & operator=(DominatorTreeBase &&RHS)
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< NodeT * >::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.
DomTreeNodeBase< NodeT > * setNewRoot(NodeT *BB)
Add a new node to the forward dominator tree and make it a new root.
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< NodeT *, 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< NodeT * >, DenseMap< const NodeT *, unsigned >, std::tuple<> > NodeNumberMap
DomTreeNodeBase< NodeT > * 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...
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
PostDominatorTree Class - Concrete subclass of DominatorTree that is used to compute the post-dominat...
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.
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 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.
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
bool hasSingleElement(ContainerTy &&C)
Returns true if the given container only contains a single element.
raw_ostream & operator<<(raw_ostream &OS, const APFixedPoint &FX)
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
Implement std::hash so that hash_code can be used in STL containers.
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