File indexing completed on 2026-05-10 08:44:31
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024 #ifndef LLVM_SUPPORT_GENERICDOMTREE_H
0025 #define LLVM_SUPPORT_GENERICDOMTREE_H
0026
0027 #include "llvm/ADT/DenseMap.h"
0028 #include "llvm/ADT/GraphTraits.h"
0029 #include "llvm/ADT/STLExtras.h"
0030 #include "llvm/ADT/SmallPtrSet.h"
0031 #include "llvm/ADT/SmallVector.h"
0032 #include "llvm/Support/CFGDiff.h"
0033 #include "llvm/Support/CFGUpdate.h"
0034 #include "llvm/Support/raw_ostream.h"
0035 #include <algorithm>
0036 #include <cassert>
0037 #include <cstddef>
0038 #include <iterator>
0039 #include <memory>
0040 #include <type_traits>
0041 #include <utility>
0042
0043 namespace llvm {
0044
0045 template <typename NodeT, bool IsPostDom>
0046 class DominatorTreeBase;
0047
0048 namespace DomTreeBuilder {
0049 template <typename DomTreeT>
0050 struct SemiNCAInfo;
0051 }
0052
0053
0054 template <class NodeT> class DomTreeNodeBase {
0055 friend class PostDominatorTree;
0056 friend class DominatorTreeBase<NodeT, false>;
0057 friend class DominatorTreeBase<NodeT, true>;
0058 friend struct DomTreeBuilder::SemiNCAInfo<DominatorTreeBase<NodeT, false>>;
0059 friend struct DomTreeBuilder::SemiNCAInfo<DominatorTreeBase<NodeT, true>>;
0060
0061 NodeT *TheBB;
0062 DomTreeNodeBase *IDom;
0063 unsigned Level;
0064 SmallVector<DomTreeNodeBase *, 4> Children;
0065 mutable unsigned DFSNumIn = ~0;
0066 mutable unsigned DFSNumOut = ~0;
0067
0068 public:
0069 DomTreeNodeBase(NodeT *BB, DomTreeNodeBase *iDom)
0070 : TheBB(BB), IDom(iDom), Level(IDom ? IDom->Level + 1 : 0) {}
0071
0072 using iterator = typename SmallVector<DomTreeNodeBase *, 4>::iterator;
0073 using const_iterator =
0074 typename SmallVector<DomTreeNodeBase *, 4>::const_iterator;
0075
0076 iterator begin() { return Children.begin(); }
0077 iterator end() { return Children.end(); }
0078 const_iterator begin() const { return Children.begin(); }
0079 const_iterator end() const { return Children.end(); }
0080
0081 DomTreeNodeBase *const &back() const { return Children.back(); }
0082 DomTreeNodeBase *&back() { return Children.back(); }
0083
0084 iterator_range<iterator> children() { return make_range(begin(), end()); }
0085 iterator_range<const_iterator> children() const {
0086 return make_range(begin(), end());
0087 }
0088
0089 NodeT *getBlock() const { return TheBB; }
0090 DomTreeNodeBase *getIDom() const { return IDom; }
0091 unsigned getLevel() const { return Level; }
0092
0093 void addChild(DomTreeNodeBase *C) { Children.push_back(C); }
0094
0095 bool isLeaf() const { return Children.empty(); }
0096 size_t getNumChildren() const { return Children.size(); }
0097
0098 void clearAllChildren() { Children.clear(); }
0099
0100 bool compare(const DomTreeNodeBase *Other) const {
0101 if (getNumChildren() != Other->getNumChildren())
0102 return true;
0103
0104 if (Level != Other->Level) return true;
0105
0106 SmallPtrSet<const NodeT *, 4> OtherChildren;
0107 for (const DomTreeNodeBase *I : *Other) {
0108 const NodeT *Nd = I->getBlock();
0109 OtherChildren.insert(Nd);
0110 }
0111
0112 for (const DomTreeNodeBase *I : *this) {
0113 const NodeT *N = I->getBlock();
0114 if (OtherChildren.count(N) == 0)
0115 return true;
0116 }
0117 return false;
0118 }
0119
0120 void setIDom(DomTreeNodeBase *NewIDom) {
0121 assert(IDom && "No immediate dominator?");
0122 if (IDom == NewIDom) return;
0123
0124 auto I = find(IDom->Children, this);
0125 assert(I != IDom->Children.end() &&
0126 "Not in immediate dominator children set!");
0127
0128 IDom->Children.erase(I);
0129
0130
0131 IDom = NewIDom;
0132 IDom->Children.push_back(this);
0133
0134 UpdateLevel();
0135 }
0136
0137
0138
0139
0140 unsigned getDFSNumIn() const { return DFSNumIn; }
0141 unsigned getDFSNumOut() const { return DFSNumOut; }
0142
0143 private:
0144
0145
0146 bool DominatedBy(const DomTreeNodeBase *other) const {
0147 return this->DFSNumIn >= other->DFSNumIn &&
0148 this->DFSNumOut <= other->DFSNumOut;
0149 }
0150
0151 void UpdateLevel() {
0152 assert(IDom);
0153 if (Level == IDom->Level + 1) return;
0154
0155 SmallVector<DomTreeNodeBase *, 64> WorkStack = {this};
0156
0157 while (!WorkStack.empty()) {
0158 DomTreeNodeBase *Current = WorkStack.pop_back_val();
0159 Current->Level = Current->IDom->Level + 1;
0160
0161 for (DomTreeNodeBase *C : *Current) {
0162 assert(C->IDom);
0163 if (C->Level != C->IDom->Level + 1) WorkStack.push_back(C);
0164 }
0165 }
0166 }
0167 };
0168
0169 template <class NodeT>
0170 raw_ostream &operator<<(raw_ostream &O, const DomTreeNodeBase<NodeT> *Node) {
0171 if (Node->getBlock())
0172 Node->getBlock()->printAsOperand(O, false);
0173 else
0174 O << " <<exit node>>";
0175
0176 O << " {" << Node->getDFSNumIn() << "," << Node->getDFSNumOut() << "} ["
0177 << Node->getLevel() << "]\n";
0178
0179 return O;
0180 }
0181
0182 template <class NodeT>
0183 void PrintDomTree(const DomTreeNodeBase<NodeT> *N, raw_ostream &O,
0184 unsigned Lev) {
0185 O.indent(2 * Lev) << "[" << Lev << "] " << N;
0186 for (const auto &I : *N)
0187 PrintDomTree<NodeT>(I, O, Lev + 1);
0188 }
0189
0190 namespace DomTreeBuilder {
0191
0192 template <typename DomTreeT>
0193 void Calculate(DomTreeT &DT);
0194
0195 template <typename DomTreeT>
0196 void CalculateWithUpdates(DomTreeT &DT,
0197 ArrayRef<typename DomTreeT::UpdateType> Updates);
0198
0199 template <typename DomTreeT>
0200 void InsertEdge(DomTreeT &DT, typename DomTreeT::NodePtr From,
0201 typename DomTreeT::NodePtr To);
0202
0203 template <typename DomTreeT>
0204 void DeleteEdge(DomTreeT &DT, typename DomTreeT::NodePtr From,
0205 typename DomTreeT::NodePtr To);
0206
0207 template <typename DomTreeT>
0208 void ApplyUpdates(DomTreeT &DT,
0209 GraphDiff<typename DomTreeT::NodePtr,
0210 DomTreeT::IsPostDominator> &PreViewCFG,
0211 GraphDiff<typename DomTreeT::NodePtr,
0212 DomTreeT::IsPostDominator> *PostViewCFG);
0213
0214 template <typename DomTreeT>
0215 bool Verify(const DomTreeT &DT, typename DomTreeT::VerificationLevel VL);
0216 }
0217
0218
0219
0220 template <typename NodeT> struct DomTreeNodeTraits {
0221 using NodeType = NodeT;
0222 using NodePtr = NodeT *;
0223 using ParentPtr = decltype(std::declval<NodePtr>()->getParent());
0224 static_assert(std::is_pointer_v<ParentPtr>,
0225 "Currently NodeT's parent must be a pointer type");
0226 using ParentType = std::remove_pointer_t<ParentPtr>;
0227
0228 static NodeT *getEntryNode(ParentPtr Parent) { return &Parent->front(); }
0229 static ParentPtr getParent(NodePtr BB) { return BB->getParent(); }
0230 };
0231
0232
0233
0234
0235
0236 template <typename NodeT, bool IsPostDom>
0237 class DominatorTreeBase {
0238 public:
0239 static_assert(std::is_pointer_v<typename GraphTraits<NodeT *>::NodeRef>,
0240 "Currently DominatorTreeBase supports only pointer nodes");
0241 using NodeTrait = DomTreeNodeTraits<NodeT>;
0242 using NodeType = typename NodeTrait::NodeType;
0243 using NodePtr = typename NodeTrait::NodePtr;
0244 using ParentPtr = typename NodeTrait::ParentPtr;
0245 static_assert(std::is_pointer_v<ParentPtr>,
0246 "Currently NodeT's parent must be a pointer type");
0247 using ParentType = std::remove_pointer_t<ParentPtr>;
0248 static constexpr bool IsPostDominator = IsPostDom;
0249
0250 using UpdateType = cfg::Update<NodePtr>;
0251 using UpdateKind = cfg::UpdateKind;
0252 static constexpr UpdateKind Insert = UpdateKind::Insert;
0253 static constexpr UpdateKind Delete = UpdateKind::Delete;
0254
0255 enum class VerificationLevel { Fast, Basic, Full };
0256
0257 protected:
0258
0259 SmallVector<NodeT *, IsPostDom ? 4 : 1> Roots;
0260
0261 using DomTreeNodeStorageTy =
0262 SmallVector<std::unique_ptr<DomTreeNodeBase<NodeT>>>;
0263 DomTreeNodeStorageTy DomTreeNodes;
0264
0265
0266 std::conditional_t<!GraphHasNodeNumbers<NodeT *>,
0267 DenseMap<const NodeT *, unsigned>, std::tuple<>>
0268 NodeNumberMap;
0269 DomTreeNodeBase<NodeT> *RootNode = nullptr;
0270 ParentPtr Parent = nullptr;
0271
0272 mutable bool DFSInfoValid = false;
0273 mutable unsigned int SlowQueries = 0;
0274 unsigned BlockNumberEpoch = 0;
0275
0276 friend struct DomTreeBuilder::SemiNCAInfo<DominatorTreeBase>;
0277
0278 public:
0279 DominatorTreeBase() = default;
0280
0281 DominatorTreeBase(DominatorTreeBase &&Arg)
0282 : Roots(std::move(Arg.Roots)), DomTreeNodes(std::move(Arg.DomTreeNodes)),
0283 NodeNumberMap(std::move(Arg.NodeNumberMap)), RootNode(Arg.RootNode),
0284 Parent(Arg.Parent), DFSInfoValid(Arg.DFSInfoValid),
0285 SlowQueries(Arg.SlowQueries), BlockNumberEpoch(Arg.BlockNumberEpoch) {
0286 Arg.wipe();
0287 }
0288
0289 DominatorTreeBase &operator=(DominatorTreeBase &&RHS) {
0290 if (this == &RHS)
0291 return *this;
0292 Roots = std::move(RHS.Roots);
0293 DomTreeNodes = std::move(RHS.DomTreeNodes);
0294 NodeNumberMap = std::move(RHS.NodeNumberMap);
0295 RootNode = RHS.RootNode;
0296 Parent = RHS.Parent;
0297 DFSInfoValid = RHS.DFSInfoValid;
0298 SlowQueries = RHS.SlowQueries;
0299 BlockNumberEpoch = RHS.BlockNumberEpoch;
0300 RHS.wipe();
0301 return *this;
0302 }
0303
0304 DominatorTreeBase(const DominatorTreeBase &) = delete;
0305 DominatorTreeBase &operator=(const DominatorTreeBase &) = delete;
0306
0307
0308
0309
0310
0311
0312 using root_iterator = typename SmallVectorImpl<NodeT *>::iterator;
0313 using const_root_iterator = typename SmallVectorImpl<NodeT *>::const_iterator;
0314
0315 root_iterator root_begin() { return Roots.begin(); }
0316 const_root_iterator root_begin() const { return Roots.begin(); }
0317 root_iterator root_end() { return Roots.end(); }
0318 const_root_iterator root_end() const { return Roots.end(); }
0319
0320 size_t root_size() const { return Roots.size(); }
0321
0322 iterator_range<root_iterator> roots() {
0323 return make_range(root_begin(), root_end());
0324 }
0325 iterator_range<const_root_iterator> roots() const {
0326 return make_range(root_begin(), root_end());
0327 }
0328
0329
0330
0331 bool isPostDominator() const { return IsPostDominator; }
0332
0333
0334
0335 bool compare(const DominatorTreeBase &Other) const {
0336 if (Parent != Other.Parent) return true;
0337
0338 if (Roots.size() != Other.Roots.size())
0339 return true;
0340
0341 if (!std::is_permutation(Roots.begin(), Roots.end(), Other.Roots.begin()))
0342 return true;
0343
0344 size_t NumNodes = 0;
0345
0346 for (const auto &Node : DomTreeNodes) {
0347 if (!Node)
0348 continue;
0349 if (Node->compare(Other.getNode(Node->getBlock())))
0350 return true;
0351 NumNodes++;
0352 }
0353
0354
0355 size_t NumOtherNodes = 0;
0356 for (const auto &OtherNode : Other.DomTreeNodes)
0357 if (OtherNode)
0358 NumOtherNodes++;
0359 return NumNodes != NumOtherNodes;
0360 }
0361
0362 private:
0363 std::optional<unsigned> getNodeIndex(const NodeT *BB) const {
0364 if constexpr (GraphHasNodeNumbers<NodeT *>) {
0365
0366 assert(BlockNumberEpoch ==
0367 GraphTraits<ParentPtr>::getNumberEpoch(Parent) &&
0368 "dominator tree used with outdated block numbers");
0369 return BB ? GraphTraits<const NodeT *>::getNumber(BB) + 1 : 0;
0370 } else {
0371 if (auto It = NodeNumberMap.find(BB); It != NodeNumberMap.end())
0372 return It->second;
0373 return std::nullopt;
0374 }
0375 }
0376
0377 unsigned getNodeIndexForInsert(const NodeT *BB) {
0378 if constexpr (GraphHasNodeNumbers<NodeT *>) {
0379
0380 unsigned Idx = *getNodeIndex(BB);
0381 if (Idx >= DomTreeNodes.size()) {
0382 unsigned Max = GraphTraits<ParentPtr>::getMaxNumber(Parent);
0383 DomTreeNodes.resize(Max > Idx + 1 ? Max : Idx + 1);
0384 }
0385 return Idx;
0386 } else {
0387
0388 unsigned Idx =
0389 NodeNumberMap.try_emplace(BB, DomTreeNodes.size()).first->second;
0390 if (Idx >= DomTreeNodes.size())
0391 DomTreeNodes.resize(Idx + 1);
0392 return Idx;
0393 }
0394 }
0395
0396 public:
0397
0398
0399
0400
0401 DomTreeNodeBase<NodeT> *getNode(const NodeT *BB) const {
0402 assert((!BB || Parent == NodeTrait::getParent(const_cast<NodeT *>(BB))) &&
0403 "cannot get DomTreeNode of block with different parent");
0404 if (auto Idx = getNodeIndex(BB); Idx && *Idx < DomTreeNodes.size())
0405 return DomTreeNodes[*Idx].get();
0406 return nullptr;
0407 }
0408
0409
0410 DomTreeNodeBase<NodeT> *operator[](const NodeT *BB) const {
0411 return getNode(BB);
0412 }
0413
0414
0415
0416
0417
0418
0419
0420
0421 DomTreeNodeBase<NodeT> *getRootNode() { return RootNode; }
0422 const DomTreeNodeBase<NodeT> *getRootNode() const { return RootNode; }
0423
0424
0425 void getDescendants(NodeT *R, SmallVectorImpl<NodeT *> &Result) const {
0426 Result.clear();
0427 const DomTreeNodeBase<NodeT> *RN = getNode(R);
0428 if (!RN)
0429 return;
0430 SmallVector<const DomTreeNodeBase<NodeT> *, 8> WL;
0431 WL.push_back(RN);
0432
0433 while (!WL.empty()) {
0434 const DomTreeNodeBase<NodeT> *N = WL.pop_back_val();
0435 Result.push_back(N->getBlock());
0436 WL.append(N->begin(), N->end());
0437 }
0438 }
0439
0440
0441
0442
0443 bool properlyDominates(const DomTreeNodeBase<NodeT> *A,
0444 const DomTreeNodeBase<NodeT> *B) const {
0445 if (!A || !B)
0446 return false;
0447 if (A == B)
0448 return false;
0449 return dominates(A, B);
0450 }
0451
0452 bool properlyDominates(const NodeT *A, const NodeT *B) const;
0453
0454
0455
0456 bool isReachableFromEntry(const NodeT *A) const {
0457 assert(!this->isPostDominator() &&
0458 "This is not implemented for post dominators");
0459 return isReachableFromEntry(getNode(A));
0460 }
0461
0462 bool isReachableFromEntry(const DomTreeNodeBase<NodeT> *A) const { return A; }
0463
0464
0465
0466
0467 bool dominates(const DomTreeNodeBase<NodeT> *A,
0468 const DomTreeNodeBase<NodeT> *B) const {
0469
0470 if (B == A)
0471 return true;
0472
0473
0474 if (!isReachableFromEntry(B))
0475 return true;
0476
0477
0478 if (!isReachableFromEntry(A))
0479 return false;
0480
0481 if (B->getIDom() == A) return true;
0482
0483 if (A->getIDom() == B) return false;
0484
0485
0486 if (A->getLevel() >= B->getLevel()) return false;
0487
0488
0489
0490 #ifdef EXPENSIVE_CHECKS
0491 assert((!DFSInfoValid ||
0492 (dominatedBySlowTreeWalk(A, B) == B->DominatedBy(A))) &&
0493 "Tree walk disagrees with dfs numbers!");
0494 #endif
0495
0496 if (DFSInfoValid)
0497 return B->DominatedBy(A);
0498
0499
0500
0501 SlowQueries++;
0502 if (SlowQueries > 32) {
0503 updateDFSNumbers();
0504 return B->DominatedBy(A);
0505 }
0506
0507 return dominatedBySlowTreeWalk(A, B);
0508 }
0509
0510 bool dominates(const NodeT *A, const NodeT *B) const;
0511
0512 NodeT *getRoot() const {
0513 assert(this->Roots.size() == 1 && "Should always have entry node!");
0514 return this->Roots[0];
0515 }
0516
0517
0518
0519 NodeT *findNearestCommonDominator(NodeT *A, NodeT *B) const {
0520 assert(A && B && "Pointers are not valid");
0521 assert(NodeTrait::getParent(A) == NodeTrait::getParent(B) &&
0522 "Two blocks are not in same function");
0523
0524
0525
0526 if (!isPostDominator()) {
0527 NodeT &Entry =
0528 *DomTreeNodeTraits<NodeT>::getEntryNode(NodeTrait::getParent(A));
0529 if (A == &Entry || B == &Entry)
0530 return &Entry;
0531 }
0532
0533 DomTreeNodeBase<NodeT> *NodeA = getNode(A);
0534 DomTreeNodeBase<NodeT> *NodeB = getNode(B);
0535 assert(NodeA && "A must be in the tree");
0536 assert(NodeB && "B must be in the tree");
0537
0538
0539
0540 while (NodeA != NodeB) {
0541 if (NodeA->getLevel() < NodeB->getLevel()) std::swap(NodeA, NodeB);
0542
0543 NodeA = NodeA->IDom;
0544 }
0545
0546 return NodeA->getBlock();
0547 }
0548
0549 const NodeT *findNearestCommonDominator(const NodeT *A,
0550 const NodeT *B) const {
0551
0552
0553 return findNearestCommonDominator(const_cast<NodeT *>(A),
0554 const_cast<NodeT *>(B));
0555 }
0556
0557 bool isVirtualRoot(const DomTreeNodeBase<NodeT> *A) const {
0558 return isPostDominator() && !A->getBlock();
0559 }
0560
0561 template <typename IteratorTy>
0562 NodeT *findNearestCommonDominator(iterator_range<IteratorTy> Nodes) const {
0563 assert(!Nodes.empty() && "Nodes list is empty!");
0564
0565 NodeT *NCD = *Nodes.begin();
0566 for (NodeT *Node : llvm::drop_begin(Nodes)) {
0567 NCD = findNearestCommonDominator(NCD, Node);
0568
0569
0570 if (isVirtualRoot(getNode(NCD)))
0571 return nullptr;
0572 }
0573
0574 return NCD;
0575 }
0576
0577
0578
0579
0580
0581
0582
0583
0584
0585
0586
0587
0588
0589
0590
0591
0592
0593
0594
0595
0596
0597
0598
0599
0600
0601
0602
0603
0604
0605
0606
0607
0608
0609
0610
0611
0612 void applyUpdates(ArrayRef<UpdateType> Updates) {
0613 GraphDiff<NodePtr, IsPostDominator> PreViewCFG(
0614 Updates, true);
0615 DomTreeBuilder::ApplyUpdates(*this, PreViewCFG, nullptr);
0616 }
0617
0618
0619
0620
0621
0622
0623 void applyUpdates(ArrayRef<UpdateType> Updates,
0624 ArrayRef<UpdateType> PostViewUpdates) {
0625 if (Updates.empty()) {
0626 GraphDiff<NodePtr, IsPostDom> PostViewCFG(PostViewUpdates);
0627 DomTreeBuilder::ApplyUpdates(*this, PostViewCFG, &PostViewCFG);
0628 } else {
0629
0630
0631
0632
0633
0634 SmallVector<UpdateType> AllUpdates(Updates);
0635 append_range(AllUpdates, PostViewUpdates);
0636 GraphDiff<NodePtr, IsPostDom> PreViewCFG(AllUpdates,
0637 true);
0638 GraphDiff<NodePtr, IsPostDom> PostViewCFG(PostViewUpdates);
0639 DomTreeBuilder::ApplyUpdates(*this, PreViewCFG, &PostViewCFG);
0640 }
0641 }
0642
0643
0644
0645
0646
0647
0648
0649
0650
0651
0652 void insertEdge(NodeT *From, NodeT *To) {
0653 assert(From);
0654 assert(To);
0655 assert(NodeTrait::getParent(From) == Parent);
0656 assert(NodeTrait::getParent(To) == Parent);
0657 DomTreeBuilder::InsertEdge(*this, From, To);
0658 }
0659
0660
0661
0662
0663
0664
0665
0666
0667
0668
0669
0670 void deleteEdge(NodeT *From, NodeT *To) {
0671 assert(From);
0672 assert(To);
0673 assert(NodeTrait::getParent(From) == Parent);
0674 assert(NodeTrait::getParent(To) == Parent);
0675 DomTreeBuilder::DeleteEdge(*this, From, To);
0676 }
0677
0678
0679
0680
0681
0682
0683
0684
0685
0686
0687 DomTreeNodeBase<NodeT> *addNewBlock(NodeT *BB, NodeT *DomBB) {
0688 assert(getNode(BB) == nullptr && "Block already in dominator tree!");
0689 DomTreeNodeBase<NodeT> *IDomNode = getNode(DomBB);
0690 assert(IDomNode && "Not immediate dominator specified for block!");
0691 DFSInfoValid = false;
0692 return createNode(BB, IDomNode);
0693 }
0694
0695
0696
0697
0698
0699
0700 DomTreeNodeBase<NodeT> *setNewRoot(NodeT *BB) {
0701 assert(getNode(BB) == nullptr && "Block already in dominator tree!");
0702 assert(!this->isPostDominator() &&
0703 "Cannot change root of post-dominator tree");
0704 DFSInfoValid = false;
0705 DomTreeNodeBase<NodeT> *NewNode = createNode(BB);
0706 if (Roots.empty()) {
0707 addRoot(BB);
0708 } else {
0709 assert(Roots.size() == 1);
0710 NodeT *OldRoot = Roots.front();
0711 DomTreeNodeBase<NodeT> *OldNode = getNode(OldRoot);
0712 NewNode->addChild(OldNode);
0713 OldNode->IDom = NewNode;
0714 OldNode->UpdateLevel();
0715 Roots[0] = BB;
0716 }
0717 return RootNode = NewNode;
0718 }
0719
0720
0721
0722
0723 void changeImmediateDominator(DomTreeNodeBase<NodeT> *N,
0724 DomTreeNodeBase<NodeT> *NewIDom) {
0725 assert(N && NewIDom && "Cannot change null node pointers!");
0726 DFSInfoValid = false;
0727 N->setIDom(NewIDom);
0728 }
0729
0730 void changeImmediateDominator(NodeT *BB, NodeT *NewBB) {
0731 changeImmediateDominator(getNode(BB), getNode(NewBB));
0732 }
0733
0734
0735
0736
0737 void eraseNode(NodeT *BB) {
0738 std::optional<unsigned> IdxOpt = getNodeIndex(BB);
0739 assert(IdxOpt && DomTreeNodes[*IdxOpt] &&
0740 "Removing node that isn't in dominator tree.");
0741 DomTreeNodeBase<NodeT> *Node = DomTreeNodes[*IdxOpt].get();
0742 assert(Node->isLeaf() && "Node is not a leaf node.");
0743
0744 DFSInfoValid = false;
0745
0746
0747 DomTreeNodeBase<NodeT> *IDom = Node->getIDom();
0748 if (IDom) {
0749 const auto I = find(IDom->Children, Node);
0750 assert(I != IDom->Children.end() &&
0751 "Not in immediate dominator children set!");
0752
0753 std::swap(*I, IDom->Children.back());
0754 IDom->Children.pop_back();
0755 }
0756
0757 DomTreeNodes[*IdxOpt] = nullptr;
0758 if constexpr (!GraphHasNodeNumbers<NodeT *>)
0759 NodeNumberMap.erase(BB);
0760
0761 if (!IsPostDom) return;
0762
0763
0764 auto RIt = llvm::find(Roots, BB);
0765 if (RIt != Roots.end()) {
0766 std::swap(*RIt, Roots.back());
0767 Roots.pop_back();
0768 }
0769 }
0770
0771
0772
0773 void splitBlock(NodeT *NewBB) {
0774 if (IsPostDominator)
0775 Split<Inverse<NodeT *>>(NewBB);
0776 else
0777 Split<NodeT *>(NewBB);
0778 }
0779
0780
0781
0782 void print(raw_ostream &O) const {
0783 O << "=============================--------------------------------\n";
0784 if (IsPostDominator)
0785 O << "Inorder PostDominator Tree: ";
0786 else
0787 O << "Inorder Dominator Tree: ";
0788 if (!DFSInfoValid)
0789 O << "DFSNumbers invalid: " << SlowQueries << " slow queries.";
0790 O << "\n";
0791
0792
0793 if (getRootNode()) PrintDomTree<NodeT>(getRootNode(), O, 1);
0794 O << "Roots: ";
0795 for (const NodePtr Block : Roots) {
0796 Block->printAsOperand(O, false);
0797 O << " ";
0798 }
0799 O << "\n";
0800 }
0801
0802 public:
0803
0804
0805 void updateDFSNumbers() const {
0806 if (DFSInfoValid) {
0807 SlowQueries = 0;
0808 return;
0809 }
0810
0811 SmallVector<std::pair<const DomTreeNodeBase<NodeT> *,
0812 typename DomTreeNodeBase<NodeT>::const_iterator>,
0813 32> WorkStack;
0814
0815 const DomTreeNodeBase<NodeT> *ThisRoot = getRootNode();
0816 assert((!Parent || ThisRoot) && "Empty constructed DomTree");
0817 if (!ThisRoot)
0818 return;
0819
0820
0821
0822 WorkStack.push_back({ThisRoot, ThisRoot->begin()});
0823
0824 unsigned DFSNum = 0;
0825 ThisRoot->DFSNumIn = DFSNum++;
0826
0827 while (!WorkStack.empty()) {
0828 const DomTreeNodeBase<NodeT> *Node = WorkStack.back().first;
0829 const auto ChildIt = WorkStack.back().second;
0830
0831
0832
0833 if (ChildIt == Node->end()) {
0834 Node->DFSNumOut = DFSNum++;
0835 WorkStack.pop_back();
0836 } else {
0837
0838 const DomTreeNodeBase<NodeT> *Child = *ChildIt;
0839 ++WorkStack.back().second;
0840
0841 WorkStack.push_back({Child, Child->begin()});
0842 Child->DFSNumIn = DFSNum++;
0843 }
0844 }
0845
0846 SlowQueries = 0;
0847 DFSInfoValid = true;
0848 }
0849
0850 private:
0851 void updateBlockNumberEpoch() {
0852
0853 if constexpr (GraphHasNodeNumbers<NodeT *>)
0854 BlockNumberEpoch = GraphTraits<ParentPtr>::getNumberEpoch(Parent);
0855 }
0856
0857 public:
0858
0859 void recalculate(ParentType &Func) {
0860 Parent = &Func;
0861 updateBlockNumberEpoch();
0862 DomTreeBuilder::Calculate(*this);
0863 }
0864
0865 void recalculate(ParentType &Func, ArrayRef<UpdateType> Updates) {
0866 Parent = &Func;
0867 updateBlockNumberEpoch();
0868 DomTreeBuilder::CalculateWithUpdates(*this, Updates);
0869 }
0870
0871
0872 template <typename T = NodeT>
0873 std::enable_if_t<GraphHasNodeNumbers<T *>, void> updateBlockNumbers() {
0874 updateBlockNumberEpoch();
0875
0876 unsigned MaxNumber = GraphTraits<ParentPtr>::getMaxNumber(Parent);
0877 DomTreeNodeStorageTy NewVector;
0878 NewVector.resize(MaxNumber + 1);
0879 for (auto &Node : DomTreeNodes) {
0880 if (!Node)
0881 continue;
0882 unsigned Idx = *getNodeIndex(Node->getBlock());
0883
0884 if (Idx >= NewVector.size())
0885 NewVector.resize(Idx + 1);
0886 NewVector[Idx] = std::move(Node);
0887 }
0888 DomTreeNodes = std::move(NewVector);
0889 }
0890
0891
0892
0893
0894
0895
0896
0897
0898
0899
0900
0901
0902
0903
0904
0905 bool verify(VerificationLevel VL = VerificationLevel::Full) const {
0906 return DomTreeBuilder::Verify(*this, VL);
0907 }
0908
0909 void reset() {
0910 DomTreeNodes.clear();
0911 if constexpr (!GraphHasNodeNumbers<NodeT *>)
0912 NodeNumberMap.clear();
0913 Roots.clear();
0914 RootNode = nullptr;
0915 Parent = nullptr;
0916 DFSInfoValid = false;
0917 SlowQueries = 0;
0918 }
0919
0920 protected:
0921 void addRoot(NodeT *BB) { this->Roots.push_back(BB); }
0922
0923 DomTreeNodeBase<NodeT> *createNode(NodeT *BB,
0924 DomTreeNodeBase<NodeT> *IDom = nullptr) {
0925 auto Node = std::make_unique<DomTreeNodeBase<NodeT>>(BB, IDom);
0926 auto *NodePtr = Node.get();
0927 unsigned NodeIdx = getNodeIndexForInsert(BB);
0928 DomTreeNodes[NodeIdx] = std::move(Node);
0929 if (IDom)
0930 IDom->addChild(NodePtr);
0931 return NodePtr;
0932 }
0933
0934
0935
0936 template <class N>
0937 void Split(typename GraphTraits<N>::NodeRef NewBB) {
0938 using GraphT = GraphTraits<N>;
0939 using NodeRef = typename GraphT::NodeRef;
0940 assert(llvm::hasSingleElement(children<N>(NewBB)) &&
0941 "NewBB should have a single successor!");
0942 NodeRef NewBBSucc = *GraphT::child_begin(NewBB);
0943
0944 SmallVector<NodeRef, 4> PredBlocks(inverse_children<N>(NewBB));
0945
0946 assert(!PredBlocks.empty() && "No predblocks?");
0947
0948 bool NewBBDominatesNewBBSucc = true;
0949 for (auto *Pred : inverse_children<N>(NewBBSucc)) {
0950 if (Pred != NewBB && !dominates(NewBBSucc, Pred) &&
0951 isReachableFromEntry(Pred)) {
0952 NewBBDominatesNewBBSucc = false;
0953 break;
0954 }
0955 }
0956
0957
0958
0959 NodeT *NewBBIDom = nullptr;
0960 unsigned i = 0;
0961 for (i = 0; i < PredBlocks.size(); ++i)
0962 if (isReachableFromEntry(PredBlocks[i])) {
0963 NewBBIDom = PredBlocks[i];
0964 break;
0965 }
0966
0967
0968
0969
0970 if (!NewBBIDom) return;
0971
0972 for (i = i + 1; i < PredBlocks.size(); ++i) {
0973 if (isReachableFromEntry(PredBlocks[i]))
0974 NewBBIDom = findNearestCommonDominator(NewBBIDom, PredBlocks[i]);
0975 }
0976
0977
0978 DomTreeNodeBase<NodeT> *NewBBNode = addNewBlock(NewBB, NewBBIDom);
0979
0980
0981
0982 if (NewBBDominatesNewBBSucc) {
0983 DomTreeNodeBase<NodeT> *NewBBSuccNode = getNode(NewBBSucc);
0984 changeImmediateDominator(NewBBSuccNode, NewBBNode);
0985 }
0986 }
0987
0988 private:
0989 bool dominatedBySlowTreeWalk(const DomTreeNodeBase<NodeT> *A,
0990 const DomTreeNodeBase<NodeT> *B) const {
0991 assert(A != B);
0992 assert(isReachableFromEntry(B));
0993 assert(isReachableFromEntry(A));
0994
0995 const unsigned ALevel = A->getLevel();
0996 const DomTreeNodeBase<NodeT> *IDom;
0997
0998
0999
1000 while ((IDom = B->getIDom()) != nullptr && IDom->getLevel() >= ALevel)
1001 B = IDom;
1002
1003 return B == A;
1004 }
1005
1006
1007
1008
1009
1010 void wipe() {
1011 DomTreeNodes.clear();
1012 if constexpr (!GraphHasNodeNumbers<NodeT *>)
1013 NodeNumberMap.clear();
1014 RootNode = nullptr;
1015 Parent = nullptr;
1016 }
1017 };
1018
1019 template <typename T>
1020 using DomTreeBase = DominatorTreeBase<T, false>;
1021
1022 template <typename T>
1023 using PostDomTreeBase = DominatorTreeBase<T, true>;
1024
1025
1026
1027 template <typename NodeT, bool IsPostDom>
1028 bool DominatorTreeBase<NodeT, IsPostDom>::dominates(const NodeT *A,
1029 const NodeT *B) const {
1030 if (A == B)
1031 return true;
1032
1033 return dominates(getNode(A), getNode(B));
1034 }
1035 template <typename NodeT, bool IsPostDom>
1036 bool DominatorTreeBase<NodeT, IsPostDom>::properlyDominates(
1037 const NodeT *A, const NodeT *B) const {
1038 if (A == B)
1039 return false;
1040
1041 return dominates(getNode(A), getNode(B));
1042 }
1043
1044 }
1045
1046 #endif