LLVM: include/llvm/Support/GenericDomTree.h Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24#ifndef LLVM_SUPPORT_GENERICDOMTREE_H
25#define LLVM_SUPPORT_GENERICDOMTREE_H
26
35#include
36#include
37#include
38#include
39#include
40#include <type_traits>
41#include
42
43namespace llvm {
44
45template <typename NodeT, bool IsPostDom>
46class DominatorTreeBase;
47
48namespace DomTreeBuilder {
49template
50struct SemiNCAInfo;
51}
52
53
60
61 NodeT *TheBB;
63 unsigned Level;
65 mutable unsigned DFSNumIn = ~0;
66 mutable unsigned DFSNumOut = ~0;
67
68 public:
70 : TheBB(BB), IDom(iDom), Level(IDom ? IDom->Level + 1 : 0) {}
71
75
80
83
87 }
88
89 NodeT *getBlock() const { return TheBB; }
91 unsigned getLevel() const { return Level; }
92
94
95 bool isLeaf() const { return Children.empty(); }
97
99
102 return true;
103
104 if (Level != Other->Level) return true;
105
108 const NodeT *Nd = I->getBlock();
109 OtherChildren.insert(Nd);
110 }
111
113 const NodeT *N = I->getBlock();
114 if (OtherChildren.count(N) == 0)
115 return true;
116 }
117 return false;
118 }
119
121 assert(IDom && "No immediate dominator?");
122 if (IDom == NewIDom) return;
123
124 auto I = find(IDom->Children, this);
125 assert(I != IDom->Children.end() &&
126 "Not in immediate dominator children set!");
127
128 IDom->Children.erase(I);
129
130
131 IDom = NewIDom;
132 IDom->Children.push_back(this);
133
134 UpdateLevel();
135 }
136
137
138
139
142
143private:
144
145
147 return this->DFSNumIn >= other->DFSNumIn &&
148 this->DFSNumOut <= other->DFSNumOut;
149 }
150
151 void UpdateLevel() {
153 if (Level == IDom->Level + 1) return;
154
155 SmallVector<DomTreeNodeBase *, 64> WorkStack = {this};
156
157 while (!WorkStack.empty()) {
159 Current->Level = Current->IDom->Level + 1;
160
161 for (DomTreeNodeBase *C : *Current) {
163 if (C->Level != C->IDom->Level + 1) WorkStack.push_back(C);
164 }
165 }
166 }
167};
168
169template
171 if (Node->getBlock())
173 else
174 O << " <>";
175
176 O << " {" << Node->getDFSNumIn() << "," << Node->getDFSNumOut() << "} ["
177 << Node->getLevel() << "]\n";
178
179 return O;
180}
181
182template
184 unsigned Lev) {
185 O.indent(2 * Lev) << "[" << Lev << "] " << N;
187 PrintDomTree(I, O, Lev + 1);
188}
189
190namespace DomTreeBuilder {
191
192template
194
195template
197 ArrayRef Updates);
198
199template
200void InsertEdge(DomTreeT &DT, typename DomTreeT::NodePtr From,
201 typename DomTreeT::NodePtr To);
202
203template
204void DeleteEdge(DomTreeT &DT, typename DomTreeT::NodePtr From,
205 typename DomTreeT::NodePtr To);
206
207template
209 GraphDiff<typename DomTreeT::NodePtr,
210 DomTreeT::IsPostDominator> &PreViewCFG,
211 GraphDiff<typename DomTreeT::NodePtr,
212 DomTreeT::IsPostDominator> *PostViewCFG);
213
214template
215bool Verify(const DomTreeT &DT, typename DomTreeT::VerificationLevel VL);
216}
217
218
219
223 using ParentPtr = decltype(std::declval()->getParent());
224 static_assert(std::is_pointer_v,
225 "Currently NodeT's parent must be a pointer type");
226 using ParentType = std::remove_pointer_t;
227
230};
231
232
233
234
235
236template <typename NodeT, bool IsPostDom>
238 public:
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,
246 "Currently NodeT's parent must be a pointer type");
247 using ParentType = std::remove_pointer_t;
249
254
256
257protected:
258
260
264
265
266 std::conditional_t<!GraphHasNodeNumbers<NodeT *>,
271
275
277
278 public:
280
286 Arg.wipe();
287 }
288
290 if (this == &RHS)
291 return *this;
292 Roots = std::move(RHS.Roots);
300 RHS.wipe();
301 return *this;
302 }
303
306
307
308
309
310
311
314
319
321
324 }
327 }
328
329
330
332
333
334
337
339 return true;
340
342 return true;
343
344 size_t NumNodes = 0;
345
348 continue;
349 if (Node->compare(Other.getNode(Node->getBlock())))
350 return true;
351 NumNodes++;
352 }
353
354
355 size_t NumOtherNodes = 0;
356 for (const auto &OtherNode : Other.DomTreeNodes)
357 if (OtherNode)
358 NumOtherNodes++;
359 return NumNodes != NumOtherNodes;
360 }
361
362private:
363 std::optional getNodeIndex(const NodeT *BB) const {
364 if constexpr (GraphHasNodeNumbers<NodeT *>) {
365
368 "dominator tree used with outdated block numbers");
370 } else {
372 return It->second;
373 return std::nullopt;
374 }
375 }
376
377 unsigned getNodeIndexForInsert(const NodeT *BB) {
378 if constexpr (GraphHasNodeNumbers<NodeT *>) {
379
380 unsigned Idx = *getNodeIndex(BB);
382 unsigned Max = GraphTraits::getMaxNumber(Parent);
384 }
385 return Idx;
386 } else {
387
388 unsigned Idx =
392 return Idx;
393 }
394 }
395
396public:
397
398
399
400
403 "cannot get DomTreeNode of block with different parent");
406 return nullptr;
407 }
408
409
412 }
413
414
415
416
417
418
419
420
423
424
426 Result.clear();
428 if (!RN)
429 return;
432
433 while (!WL.empty()) {
435 Result.push_back(N->getBlock());
436 WL.append(N->begin(), N->end());
437 }
438 }
439
440
441
442
445 if ( ||
)
446 return false;
448 return false;
450 }
451
453
454
455
458 "This is not implemented for post dominators");
460 }
461
463
464
465
466
469
471 return true;
472
473
475 return true;
476
477
479 return false;
480
481 if (B->getIDom() == A) return true;
482
483 if (A->getIDom() == B) return false;
484
485
486 if (A->getLevel() >= B->getLevel()) return false;
487
488
489
490#ifdef EXPENSIVE_CHECKS
492 (dominatedBySlowTreeWalk(A, B) == B->DominatedBy(A))) &&
493 "Tree walk disagrees with dfs numbers!");
494#endif
495
498
499
500
505 }
506
507 return dominatedBySlowTreeWalk(A, B);
508 }
509
510 bool dominates(const NodeT *A, const NodeT *B) const;
511
513 assert(this->Roots.size() == 1 && "Should always have entry node!");
514 return this->Roots[0];
515 }
516
517
518
520 assert(A && B && "Pointers are not valid");
522 "Two blocks are not in same function");
523
524
525
527 NodeT &Entry =
529 if (A == &Entry || B == &Entry)
530 return &Entry;
531 }
532
535 assert(NodeA && "A must be in the tree");
536 assert(NodeB && "B must be in the tree");
537
538
539
540 while (NodeA != NodeB) {
542
543 NodeA = NodeA->IDom;
544 }
545
547 }
548
550 const NodeT *B) const {
551
552
554 const_cast<NodeT *>(B));
555 }
556
559 }
560
561 template
563 assert(!Nodes.empty() && "Nodes list is empty!");
564
565 NodeT *NCD = *Nodes.begin();
568
569
571 return nullptr;
572 }
573
574 return NCD;
575 }
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
614 Updates, true);
616 }
617
618
619
620
621
622
625 if (Updates.empty()) {
628 } else {
629
630
631
632
633
637 true);
640 }
641 }
642
643
644
645
646
647
648
649
650
651
658 }
659
660
661
662
663
664
665
666
667
668
669
676 }
677
678
679
680
681
682
683
684
685
686
688 assert(getNode(BB) == nullptr && "Block already in dominator tree!");
690 assert(IDomNode && "Not immediate dominator specified for block!");
693 }
694
695
696
697
698
699
701 assert(getNode(BB) == nullptr && "Block already in dominator tree!");
703 "Cannot change root of post-dominator tree");
704 DFSInfoValid = false;
708 } else {
713 OldNode->IDom = NewNode;
714 OldNode->UpdateLevel();
716 }
718 }
719
720
721
722
725 assert(N && NewIDom && "Cannot change null node pointers!");
727 N->setIDom(NewIDom);
728 }
729
732 }
733
734
735
736
738 std::optional IdxOpt = getNodeIndex(BB);
740 "Removing node that isn't in dominator tree.");
742 assert(Node->isLeaf() && "Node is not a leaf node.");
743
745
746
748 if (IDom) {
749 const auto I = find(IDom->Children, Node);
750 assert(I != IDom->Children.end() &&
751 "Not in immediate dominator children set!");
752
753 std::swap(*I, IDom->Children.back());
754 IDom->Children.pop_back();
755 }
756
758 if constexpr (!GraphHasNodeNumbers<NodeT *>)
760
761 if (!IsPostDom) return;
762
763
768 }
769 }
770
771
772
775 Split<Inverse<NodeT *>>(NewBB);
776 else
777 Split<NodeT *>(NewBB);
778 }
779
780
781
783 O << "=============================--------------------------------\n";
785 O << "Inorder PostDominator Tree: ";
786 else
787 O << "Inorder Dominator Tree: ";
789 O << "DFSNumbers invalid: " << SlowQueries << " slow queries.";
790 O << "\n";
791
792
794 O << "Roots: ";
796 Block->printAsOperand(O, false);
797 O << " ";
798 }
799 O << "\n";
800 }
801
802public:
803
804
808 return;
809 }
810
813 32> WorkStack;
814
816 assert(( || ThisRoot) && "Empty constructed DomTree");
817 if (!ThisRoot)
818 return;
819
820
821
823
824 unsigned DFSNum = 0;
825 ThisRoot->DFSNumIn = DFSNum++;
826
827 while (!WorkStack.empty()) {
829 const auto ChildIt = WorkStack.back().second;
830
831
832
833 if (ChildIt == Node->end()) {
834 Node->DFSNumOut = DFSNum++;
836 } else {
837
839 ++WorkStack.back().second;
840
842 Child->DFSNumIn = DFSNum++;
843 }
844 }
845
848 }
849
850private:
851 void updateBlockNumberEpoch() {
852
853 if constexpr (GraphHasNodeNumbers<NodeT *>)
855 }
856
857public:
858
861 updateBlockNumberEpoch();
863 }
864
867 updateBlockNumberEpoch();
869 }
870
871
872 template
874 updateBlockNumberEpoch();
875
878 NewVector.resize(MaxNumber + 1);
881 continue;
882 unsigned Idx = *getNodeIndex(Node->getBlock());
883
884 if (Idx >= NewVector.size())
886 NewVector[Idx] = std::move(Node);
887 }
889 }
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
907 }
908
911 if constexpr (!GraphHasNodeNumbers<NodeT *>)
918 }
919
920protected:
922
925 auto Node = std::make_unique<DomTreeNodeBase>(BB, IDom);
927 unsigned NodeIdx = getNodeIndexForInsert(BB);
929 if (IDom)
932 }
933
934
935
936 template
939 using NodeRef = typename GraphT::NodeRef;
941 "NewBB should have a single successor!");
942 NodeRef NewBBSucc = *GraphT::child_begin(NewBB);
943
945
946 assert(!PredBlocks.empty() && "No predblocks?");
947
948 bool NewBBDominatesNewBBSucc = true;
949 for (auto *Pred : inverse_children(NewBBSucc)) {
950 if (Pred != NewBB && (NewBBSucc, Pred) &&
952 NewBBDominatesNewBBSucc = false;
953 break;
954 }
955 }
956
957
958
959 NodeT *NewBBIDom = nullptr;
960 unsigned i = 0;
961 for (i = 0; i < PredBlocks.size(); ++i)
963 NewBBIDom = PredBlocks[i];
964 break;
965 }
966
967
968
969
970 if (!NewBBIDom) return;
971
972 for (i = i + 1; i < PredBlocks.size(); ++i) {
975 }
976
977
979
980
981
982 if (NewBBDominatesNewBBSucc) {
985 }
986 }
987
988 private:
994
995 const unsigned ALevel = A->getLevel();
997
998
999
1000 while ((IDom = B->getIDom()) != nullptr && IDom->getLevel() >= ALevel)
1001 B = IDom;
1002
1004 }
1005
1006
1007
1008
1009
1010 void wipe() {
1012 if constexpr (!GraphHasNodeNumbers<NodeT *>)
1016 }
1017};
1018
1019template
1021
1022template
1024
1025
1026
1027template <typename NodeT, bool IsPostDom>
1029 const NodeT *B) const {
1031 return true;
1032
1034}
1035template <typename NodeT, bool IsPostDom>
1037 const NodeT *A, const NodeT *B) const {
1039 return false;
1040
1042}
1043
1044}
1045
1046#endif
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 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)
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)
NodeT * findNearestCommonDominator(iterator_range< IteratorTy > Nodes) const
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 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.
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