24 #ifndef LLVM_SUPPORT_GENERICDOMTREE_H 25 #define LLVM_SUPPORT_GENERICDOMTREE_H 40 #include <type_traits> 46 template <
typename NodeT,
bool IsPostDom>
47 class DominatorTreeBase;
49 namespace DomTreeBuilder {
50 template <
typename DomTreeT>
65 std::vector<DomTreeNodeBase *> Children;
66 mutable unsigned DFSNumIn = ~0;
67 mutable unsigned DFSNumOut = ~0;
71 : TheBB(BB), IDom(iDom), Level(IDom ? IDom->Level + 1 : 0) {}
73 using iterator =
typename std::vector<DomTreeNodeBase *>::iterator;
75 typename std::vector<DomTreeNodeBase *>::const_iterator;
86 const std::vector<DomTreeNodeBase *> &
getChildren()
const {
return Children; }
89 std::unique_ptr<DomTreeNodeBase>
C) {
90 Children.push_back(C.get());
102 if (Level != Other->Level)
return true;
106 const NodeT *Nd =
I->getBlock();
112 if (OtherChildren.
count(N) == 0)
119 assert(IDom &&
"No immediate dominator?");
120 if (IDom == NewIDom)
return;
122 auto I =
find(IDom->Children,
this);
123 assert(
I != IDom->Children.end() &&
124 "Not in immediate dominator children set!");
126 IDom->Children.erase(
I);
130 IDom->Children.push_back(
this);
145 return this->DFSNumIn >= other->DFSNumIn &&
146 this->DFSNumOut <= other->DFSNumOut;
151 if (Level == IDom->Level + 1)
return;
155 while (!WorkStack.
empty()) {
157 Current->Level = Current->IDom->Level + 1;
161 if (
C->Level !=
C->IDom->Level + 1) WorkStack.
push_back(
C);
167 template <
class NodeT>
168 raw_ostream &operator<<(raw_ostream &O, const DomTreeNodeBase<NodeT> *Node) {
169 if (Node->getBlock())
170 Node->getBlock()->printAsOperand(
O,
false);
172 O <<
" <<exit node>>";
174 O <<
" {" << Node->getDFSNumIn() <<
"," << Node->getDFSNumOut() <<
"} [" 175 << Node->getLevel() <<
"]\n";
180 template <
class NodeT>
183 O.
indent(2 * Lev) <<
"[" << Lev <<
"] " <<
N;
187 PrintDomTree<NodeT>(*
I, O, Lev + 1);
190 namespace DomTreeBuilder {
192 template <
typename DomTreeT>
195 template <
typename DomTreeT>
199 template <
typename DomTreeT>
203 template <
typename DomTreeT>
207 template <
typename DomTreeT>
211 template <
typename DomTreeT>
212 bool Verify(
const DomTreeT &DT,
typename DomTreeT::VerificationLevel VL);
219 template <
typename NodeT,
bool IsPostDom>
223 "Currently DominatorTreeBase supports only pointer nodes");
227 static_assert(std::is_pointer<ParentPtr>::value,
228 "Currently NodeT's parent must be a pointer type");
229 using ParentType =
typename std::remove_pointer<ParentPtr>::type;
230 static constexpr
bool IsPostDominator = IsPostDom;
249 mutable bool DFSInfoValid =
false;
250 mutable unsigned int SlowQueries = 0;
258 : Roots(
std::move(
Arg.Roots)),
259 DomTreeNodes(
std::move(
Arg.DomTreeNodes)),
260 RootNode(
Arg.RootNode),
262 DFSInfoValid(
Arg.DFSInfoValid),
263 SlowQueries(
Arg.SlowQueries) {
268 Roots = std::move(RHS.Roots);
269 DomTreeNodes = std::move(RHS.DomTreeNodes);
270 RootNode = RHS.RootNode;
272 DFSInfoValid = RHS.DFSInfoValid;
273 SlowQueries = RHS.SlowQueries;
294 if (Parent != Other.
Parent)
return true;
303 if (DomTreeNodes.size() != OtherDomTreeNodes.size())
308 typename DomTreeNodeMapType::const_iterator OI =
309 OtherDomTreeNodes.find(BB);
310 if (OI == OtherDomTreeNodes.end())
330 auto I = DomTreeNodes.find(BB);
331 if (
I != DomTreeNodes.end())
332 return I->second.get();
360 while (!WL.
empty()) {
376 return dominates(A, B);
379 bool properlyDominates(
const NodeT *
A,
const NodeT *
B)
const;
384 assert(!this->isPostDominator() &&
385 "This is not implemented for post dominators");
386 return isReachableFromEntry(getNode(const_cast<NodeT *>(A)));
401 if (!isReachableFromEntry(B))
405 if (!isReachableFromEntry(A))
410 if (A->
getIDom() ==
B)
return false;
417 #ifdef EXPENSIVE_CHECKS 419 (dominatedBySlowTreeWalk(A, B) == B->DominatedBy(A))) &&
420 "Tree walk disagrees with dfs numbers!");
424 return B->DominatedBy(A);
429 if (SlowQueries > 32) {
431 return B->DominatedBy(A);
434 return dominatedBySlowTreeWalk(A, B);
437 bool dominates(
const NodeT *A,
const NodeT *B)
const;
440 assert(this->Roots.
size() == 1 &&
"Should always have entry node!");
441 return this->Roots[0];
447 assert(A && B &&
"Pointers are not valid");
448 assert(A->getParent() == B->getParent() &&
449 "Two blocks are not in same function");
453 if (!isPostDominator()) {
454 NodeT &Entry = A->getParent()->front();
455 if (A == &Entry || B == &Entry)
462 if (!NodeA || !NodeB)
return nullptr;
466 while (NodeA && NodeA != NodeB) {
472 return NodeA ? NodeA->
getBlock() :
nullptr;
476 const NodeT *B)
const {
479 return findNearestCommonDominator(const_cast<NodeT *>(A),
480 const_cast<NodeT *>(B));
484 return isPostDominator() && !A->
getBlock();
537 assert(From->getParent() == Parent);
538 assert(To->getParent() == Parent);
555 assert(From->getParent() == Parent);
556 assert(To->getParent() == Parent);
570 assert(getNode(BB) ==
nullptr &&
"Block already in dominator tree!");
572 assert(IDomNode &&
"Not immediate dominator specified for block!");
573 DFSInfoValid =
false;
574 return (DomTreeNodes[BB] = IDomNode->
addChild(
584 assert(getNode(BB) ==
nullptr &&
"Block already in dominator tree!");
585 assert(!this->isPostDominator() &&
586 "Cannot change root of post-dominator tree");
587 DFSInfoValid =
false;
589 llvm::make_unique<DomTreeNodeBase<NodeT>>(BB,
nullptr)).get();
594 NodeT *OldRoot = Roots.
front();
595 auto &OldNode = DomTreeNodes[OldRoot];
596 OldNode = NewNode->
addChild(std::move(DomTreeNodes[OldRoot]));
597 OldNode->IDom = NewNode;
598 OldNode->UpdateLevel();
601 return RootNode = NewNode;
609 assert(N && NewIDom &&
"Cannot change null node pointers!");
610 DFSInfoValid =
false;
615 changeImmediateDominator(getNode(BB), getNode(NewBB));
623 assert(Node &&
"Removing node that isn't in dominator tree.");
626 DFSInfoValid =
false;
631 const auto I =
find(IDom->Children, Node);
632 assert(
I != IDom->Children.end() &&
633 "Not in immediate dominator children set!");
635 IDom->Children.erase(
I);
638 DomTreeNodes.erase(BB);
640 if (!IsPostDom)
return;
644 if (RIt != Roots.
end()) {
654 Split<Inverse<NodeT *>>(NewBB);
656 Split<NodeT *>(NewBB);
662 O <<
"=============================--------------------------------\n";
664 O <<
"Inorder PostDominator Tree: ";
666 O <<
"Inorder Dominator Tree: ";
668 O <<
"DFSNumbers invalid: " << SlowQueries <<
" slow queries.";
672 if (getRootNode()) PrintDomTree<NodeT>(getRootNode(),
O, 1);
673 if (IsPostDominator) {
675 for (
const NodePtr Block : Roots) {
676 Block->printAsOperand(O,
false);
697 assert((!Parent || ThisRoot) &&
"Empty constructed DomTree");
706 ThisRoot->DFSNumIn = DFSNum++;
708 while (!WorkStack.
empty()) {
710 const auto ChildIt = WorkStack.
back().second;
714 if (ChildIt == Node->
end()) {
715 Node->DFSNumOut = DFSNum++;
720 ++WorkStack.
back().second;
723 Child->DFSNumIn = DFSNum++;
764 DomTreeNodes.clear();
768 DFSInfoValid =
false;
777 using NodeRef =
typename GraphT::NodeRef;
778 assert(std::distance(GraphT::child_begin(NewBB),
779 GraphT::child_end(NewBB)) == 1 &&
780 "NewBB should have a single successor!");
781 NodeRef NewBBSucc = *GraphT::child_begin(NewBB);
783 std::vector<NodeRef> PredBlocks;
785 PredBlocks.push_back(Pred);
787 assert(!PredBlocks.empty() &&
"No predblocks?");
789 bool NewBBDominatesNewBBSucc =
true;
791 if (Pred != NewBB && !dominates(NewBBSucc, Pred) &&
792 isReachableFromEntry(Pred)) {
793 NewBBDominatesNewBBSucc =
false;
800 NodeT *NewBBIDom =
nullptr;
802 for (i = 0; i < PredBlocks.size(); ++i)
803 if (isReachableFromEntry(PredBlocks[i])) {
804 NewBBIDom = PredBlocks[i];
811 if (!NewBBIDom)
return;
813 for (i = i + 1; i < PredBlocks.size(); ++i) {
814 if (isReachableFromEntry(PredBlocks[i]))
815 NewBBIDom = findNearestCommonDominator(NewBBIDom, PredBlocks[i]);
823 if (NewBBDominatesNewBBSucc) {
825 changeImmediateDominator(NewBBSuccNode, NewBBNode);
833 assert(isReachableFromEntry(B));
834 assert(isReachableFromEntry(A));
836 const unsigned ALevel = A->
getLevel();
852 DomTreeNodes.clear();
858 template <
typename T>
861 template <
typename T>
866 template <
typename NodeT,
bool IsPostDom>
868 const NodeT *
B)
const {
875 return dominates(getNode(const_cast<NodeT *>(A)),
876 getNode(const_cast<NodeT *>(B)));
878 template <
typename NodeT,
bool IsPostDom>
880 const NodeT *
A,
const NodeT *
B)
const {
887 return dominates(getNode(const_cast<NodeT *>(A)),
888 getNode(const_cast<NodeT *>(B)));
893 #endif // LLVM_SUPPORT_GENERICDOMTREE_H
typename std::vector< DomTreeNodeBase *>::const_iterator const_iterator
iterator_range< typename GraphTraits< GraphType >::ChildIteratorType > children(const typename GraphTraits< GraphType >::NodeRef &G)
void splitBlock(NodeT *NewBB)
splitBlock - BB is split and now it has one successor.
This class represents lattice values for constants.
void push_back(const T &Elt)
void recalculate(ParentType &Func)
recalculate - compute a dominator tree for the given function
DomTreeNodeBase(NodeT *BB, DomTreeNodeBase *iDom)
void recalculate(ParentType &Func, ArrayRef< UpdateType > Updates)
raw_ostream & indent(unsigned NumSpaces)
indent - Insert 'NumSpaces' spaces.
bool isReachableFromEntry(const NodeT *A) const
isReachableFromEntry - Return true if A is dominated by the entry block of the function containing it...
NodeT * findNearestCommonDominator(NodeT *A, NodeT *B) const
findNearestCommonDominator - Find nearest common dominator basic block for basic block A and B...
bool properlyDominates(const DomTreeNodeBase< NodeT > *A, const DomTreeNodeBase< NodeT > *B) const
properlyDominates - Returns true iff A dominates B and A != B.
block Block Frequency true
std::enable_if<!std::is_array< T >::value, std::unique_ptr< T > >::type make_unique(Args &&... args)
Constructs a new T() with the given args and returns a unique_ptr<T> which owns the object...
void eraseNode(NodeT *BB)
eraseNode - Removes a node from the dominator tree.
SmallVector< NodeT *, IsPostDom ? 4 :1 > Roots
void Split(typename GraphTraits< N >::NodeRef NewBB)
const NodeT * findNearestCommonDominator(const NodeT *A, const NodeT *B) const
bool isPostDominator() const
isPostDominator - Returns true if analysis based of postdoms
void InsertEdge(DomTreeT &DT, typename DomTreeT::NodePtr From, typename DomTreeT::NodePtr To)
bool verify(VerificationLevel VL=VerificationLevel::Full) const
verify - checks if the tree is correct.
DominatorTreeBase & operator=(DominatorTreeBase &&RHS)
void changeImmediateDominator(NodeT *BB, NodeT *NewBB)
void deleteEdge(NodeT *From, NodeT *To)
Inform the dominator tree about a CFG edge deletion and update the tree.
const SmallVectorImpl< NodeT * > & getRoots() const
getRoots - Return the root blocks of the current CFG.
decltype(std::declval< BasicBlock *>() ->getParent()) ParentPtr
bool compare(const DominatorTreeBase &Other) const
compare - Return false if the other dominator tree base matches this dominator tree base...
Fast - This calling convention attempts to make calls as fast as possible (e.g.
void PrintDomTree(const DomTreeNodeBase< NodeT > *N, raw_ostream &O, unsigned Lev)
const DomTreeNodeBase< NodeT > * getRootNode() const
Base class for the actual dominator tree node.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory)...
const std::vector< DomTreeNodeBase * > & getChildren() const
DomTreeNodeBase< NodeT > * setNewRoot(NodeT *BB)
Add a new node to the forward dominator tree and make it a new root.
void insertEdge(NodeT *From, NodeT *To)
Inform the dominator tree about a CFG edge insertion and update the tree.
Core dominator tree base class.
void applyUpdates(ArrayRef< UpdateType > Updates)
Inform the dominator tree about a sequence of CFG edge insertions and deletions and perform a batch u...
unsigned getDFSNumIn() const
getDFSNumIn/getDFSNumOut - These return the DFS visitation order for nodes in the dominator tree...
typename GraphType::UnknownGraphTypeError NodeRef
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
LLVM Basic Block Representation.
std::shared_ptr< Node > NodePtr
Short-hand for a Node pointer.
bool isReachableFromEntry(const DomTreeNodeBase< NodeT > *A) const
void getDescendants(NodeT *R, SmallVectorImpl< NodeT *> &Result) const
Get all nodes dominated by R, including R itself.
void changeImmediateDominator(DomTreeNodeBase< NodeT > *N, DomTreeNodeBase< NodeT > *NewIDom)
changeImmediateDominator - This method is used to update the dominator tree information when a node's...
DomTreeNodeBase * getIDom() const
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
LLVM_ATTRIBUTE_ALWAYS_INLINE iterator begin()
void DeleteEdge(DomTreeT &DT, typename DomTreeT::NodePtr From, typename DomTreeT::NodePtr To)
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
typename std::remove_pointer< ParentPtr >::type ParentType
unsigned getDFSNumOut() const
size_type count(ConstPtrType Ptr) const
count - Return 1 if the specified pointer is in the set, 0 otherwise.
DomTreeNodeBase< NodeT > * operator[](const NodeT *BB) const
See getNode.
DomTreeNodeBase< NodeT > * getRootNode()
getRootNode - This returns the entry node for the CFG of the function.
DomTreeNodeBase< NodeT > * getNode(const NodeT *BB) const
getNode - return the (Post)DominatorTree node for the specified basic block.
auto find(R &&Range, const T &Val) -> decltype(adl_begin(Range))
Provide wrappers to std::find which take ranges instead of having to pass begin/end explicitly...
void print(raw_ostream &O) const
print - Convert to human readable form
const_iterator begin() const
void CalculateWithUpdates(DomTreeT &DT, ArrayRef< typename DomTreeT::UpdateType > Updates)
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements...
BlockVerifier::State From
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small...
size_t getNumChildren() const
LLVM_NODISCARD T pop_back_val()
DomTreeNodeBase< NodeT > * RootNode
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
bool Verify(const DomTreeT &DT, typename DomTreeT::VerificationLevel VL)
PostDominatorTree Class - Concrete subclass of DominatorTree that is used to compute the post-dominat...
void append(in_iter in_start, in_iter in_end)
Add the specified range to the end of the SmallVector.
std::unique_ptr< DomTreeNodeBase > addChild(std::unique_ptr< DomTreeNodeBase > C)
bool dominates(const DomTreeNodeBase< NodeT > *A, const DomTreeNodeBase< NodeT > *B) const
dominates - Returns true iff A dominates B.
amdgpu Simplify well known AMD library false Value Value * Arg
void Calculate(DomTreeT &DT)
LLVM_ATTRIBUTE_ALWAYS_INLINE iterator end()
bool compare(const DomTreeNodeBase *Other) const
LLVM_NODISCARD bool empty() const
DomTreeNodeMapType DomTreeNodes
DomTreeNodeBase< NodeT > * addNewBlock(NodeT *BB, NodeT *DomBB)
Add a new node to the dominator tree information.
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
void ApplyUpdates(DomTreeT &DT, ArrayRef< typename DomTreeT::UpdateType > Updates)
DominatorTreeBase(DominatorTreeBase &&Arg)
bool isVirtualRoot(const DomTreeNodeBase< NodeT > *A) const
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
void updateDFSNumbers() const
updateDFSNumbers - Assign In and Out numbers to the nodes while walking dominator tree in dfs order...
typename std::vector< DomTreeNodeBase *>::iterator iterator
static const Function * getParent(const Value *V)
This class implements an extremely fast bulk output stream that can only output to a stream...
unsigned getLevel() const
const_iterator end() const
void setIDom(DomTreeNodeBase *NewIDom)