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
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037 #ifndef LLVM_SUPPORT_GENERICDOMTREECONSTRUCTION_H
0038 #define LLVM_SUPPORT_GENERICDOMTREECONSTRUCTION_H
0039
0040 #include "llvm/ADT/ArrayRef.h"
0041 #include "llvm/ADT/DenseSet.h"
0042 #include "llvm/ADT/DepthFirstIterator.h"
0043 #include "llvm/ADT/SmallPtrSet.h"
0044 #include "llvm/Support/Debug.h"
0045 #include "llvm/Support/GenericDomTree.h"
0046 #include <optional>
0047 #include <queue>
0048
0049 #define DEBUG_TYPE "dom-tree-builder"
0050
0051 namespace llvm {
0052 namespace DomTreeBuilder {
0053
0054 template <typename DomTreeT>
0055 struct SemiNCAInfo {
0056 using NodePtr = typename DomTreeT::NodePtr;
0057 using NodeT = typename DomTreeT::NodeType;
0058 using TreeNodePtr = DomTreeNodeBase<NodeT> *;
0059 using RootsT = decltype(DomTreeT::Roots);
0060 static constexpr bool IsPostDom = DomTreeT::IsPostDominator;
0061 using GraphDiffT = GraphDiff<NodePtr, IsPostDom>;
0062
0063
0064 struct InfoRec {
0065 unsigned DFSNum = 0;
0066 unsigned Parent = 0;
0067 unsigned Semi = 0;
0068 unsigned Label = 0;
0069 NodePtr IDom = nullptr;
0070 SmallVector<unsigned, 4> ReverseChildren;
0071 };
0072
0073
0074
0075 SmallVector<NodePtr, 64> NumToNode = {nullptr};
0076
0077
0078 std::conditional_t<GraphHasNodeNumbers<NodePtr>, SmallVector<InfoRec, 64>,
0079 DenseMap<NodePtr, InfoRec>>
0080 NodeInfos;
0081
0082 using UpdateT = typename DomTreeT::UpdateType;
0083 using UpdateKind = typename DomTreeT::UpdateKind;
0084 struct BatchUpdateInfo {
0085
0086 BatchUpdateInfo(GraphDiffT &PreViewCFG, GraphDiffT *PostViewCFG = nullptr)
0087 : PreViewCFG(PreViewCFG), PostViewCFG(PostViewCFG),
0088 NumLegalized(PreViewCFG.getNumLegalizedUpdates()) {}
0089
0090
0091
0092 bool IsRecalculated = false;
0093 GraphDiffT &PreViewCFG;
0094 GraphDiffT *PostViewCFG;
0095 const size_t NumLegalized;
0096 };
0097
0098 BatchUpdateInfo *BatchUpdates;
0099 using BatchUpdatePtr = BatchUpdateInfo *;
0100
0101
0102 SemiNCAInfo(BatchUpdatePtr BUI) : BatchUpdates(BUI) {}
0103
0104 void clear() {
0105 NumToNode = {nullptr};
0106 NodeInfos.clear();
0107
0108
0109 }
0110
0111 template <bool Inversed>
0112 static SmallVector<NodePtr, 8> getChildren(NodePtr N, BatchUpdatePtr BUI) {
0113 if (BUI)
0114 return BUI->PreViewCFG.template getChildren<Inversed>(N);
0115 return getChildren<Inversed>(N);
0116 }
0117
0118 template <bool Inversed>
0119 static SmallVector<NodePtr, 8> getChildren(NodePtr N) {
0120 using DirectedNodeT =
0121 std::conditional_t<Inversed, Inverse<NodePtr>, NodePtr>;
0122 auto R = children<DirectedNodeT>(N);
0123 SmallVector<NodePtr, 8> Res(detail::reverse_if<!Inversed>(R));
0124
0125
0126 llvm::erase(Res, nullptr);
0127 return Res;
0128 }
0129
0130 InfoRec &getNodeInfo(NodePtr BB) {
0131 if constexpr (GraphHasNodeNumbers<NodePtr>) {
0132 unsigned Idx = BB ? GraphTraits<NodePtr>::getNumber(BB) + 1 : 0;
0133 if (Idx >= NodeInfos.size()) {
0134 unsigned Max = 0;
0135 if (BB)
0136 Max = GraphTraits<decltype(BB->getParent())>::getMaxNumber(
0137 BB->getParent());
0138
0139 NodeInfos.resize(Max ? Max + 1 : Idx + 1);
0140 }
0141 return NodeInfos[Idx];
0142 } else {
0143 return NodeInfos[BB];
0144 }
0145 }
0146
0147 NodePtr getIDom(NodePtr BB) { return getNodeInfo(BB).IDom; }
0148
0149 TreeNodePtr getNodeForBlock(NodePtr BB, DomTreeT &DT) {
0150 if (TreeNodePtr Node = DT.getNode(BB)) return Node;
0151
0152
0153
0154 NodePtr IDom = getIDom(BB);
0155
0156 assert(IDom || DT.getNode(nullptr));
0157 TreeNodePtr IDomNode = getNodeForBlock(IDom, DT);
0158
0159
0160
0161 return DT.createNode(BB, IDomNode);
0162 }
0163
0164 static bool AlwaysDescend(NodePtr, NodePtr) { return true; }
0165
0166 struct BlockNamePrinter {
0167 NodePtr N;
0168
0169 BlockNamePrinter(NodePtr Block) : N(Block) {}
0170 BlockNamePrinter(TreeNodePtr TN) : N(TN ? TN->getBlock() : nullptr) {}
0171
0172 friend raw_ostream &operator<<(raw_ostream &O, const BlockNamePrinter &BP) {
0173 if (!BP.N)
0174 O << "nullptr";
0175 else
0176 BP.N->printAsOperand(O, false);
0177
0178 return O;
0179 }
0180 };
0181
0182 using NodeOrderMap = DenseMap<NodePtr, unsigned>;
0183
0184
0185
0186
0187
0188
0189
0190
0191
0192
0193
0194 template <bool IsReverse = false, typename DescendCondition>
0195 unsigned runDFS(NodePtr V, unsigned LastNum, DescendCondition Condition,
0196 unsigned AttachToNum,
0197 const NodeOrderMap *SuccOrder = nullptr) {
0198 assert(V);
0199 SmallVector<std::pair<NodePtr, unsigned>, 64> WorkList = {{V, AttachToNum}};
0200 getNodeInfo(V).Parent = AttachToNum;
0201
0202 while (!WorkList.empty()) {
0203 const auto [BB, ParentNum] = WorkList.pop_back_val();
0204 auto &BBInfo = getNodeInfo(BB);
0205 BBInfo.ReverseChildren.push_back(ParentNum);
0206
0207
0208 if (BBInfo.DFSNum != 0) continue;
0209 BBInfo.Parent = ParentNum;
0210 BBInfo.DFSNum = BBInfo.Semi = BBInfo.Label = ++LastNum;
0211 NumToNode.push_back(BB);
0212
0213 constexpr bool Direction = IsReverse != IsPostDom;
0214 auto Successors = getChildren<Direction>(BB, BatchUpdates);
0215 if (SuccOrder && Successors.size() > 1)
0216 llvm::sort(
0217 Successors.begin(), Successors.end(), [=](NodePtr A, NodePtr B) {
0218 return SuccOrder->find(A)->second < SuccOrder->find(B)->second;
0219 });
0220
0221 for (const NodePtr Succ : Successors) {
0222 if (!Condition(BB, Succ)) continue;
0223
0224 WorkList.push_back({Succ, LastNum});
0225 }
0226 }
0227
0228 return LastNum;
0229 }
0230
0231
0232
0233
0234
0235
0236
0237
0238
0239
0240
0241
0242
0243
0244 unsigned eval(unsigned V, unsigned LastLinked,
0245 SmallVectorImpl<InfoRec *> &Stack,
0246 ArrayRef<InfoRec *> NumToInfo) {
0247 InfoRec *VInfo = NumToInfo[V];
0248 if (VInfo->Parent < LastLinked)
0249 return VInfo->Label;
0250
0251
0252 assert(Stack.empty());
0253 do {
0254 Stack.push_back(VInfo);
0255 VInfo = NumToInfo[VInfo->Parent];
0256 } while (VInfo->Parent >= LastLinked);
0257
0258
0259
0260 const InfoRec *PInfo = VInfo;
0261 const InfoRec *PLabelInfo = NumToInfo[PInfo->Label];
0262 do {
0263 VInfo = Stack.pop_back_val();
0264 VInfo->Parent = PInfo->Parent;
0265 const InfoRec *VLabelInfo = NumToInfo[VInfo->Label];
0266 if (PLabelInfo->Semi < VLabelInfo->Semi)
0267 VInfo->Label = PInfo->Label;
0268 else
0269 PLabelInfo = VLabelInfo;
0270 PInfo = VInfo;
0271 } while (!Stack.empty());
0272 return VInfo->Label;
0273 }
0274
0275
0276 void runSemiNCA() {
0277 const unsigned NextDFSNum(NumToNode.size());
0278 SmallVector<InfoRec *, 8> NumToInfo = {nullptr};
0279 NumToInfo.reserve(NextDFSNum);
0280
0281 for (unsigned i = 1; i < NextDFSNum; ++i) {
0282 const NodePtr V = NumToNode[i];
0283 auto &VInfo = getNodeInfo(V);
0284 VInfo.IDom = NumToNode[VInfo.Parent];
0285 NumToInfo.push_back(&VInfo);
0286 }
0287
0288
0289 SmallVector<InfoRec *, 32> EvalStack;
0290 for (unsigned i = NextDFSNum - 1; i >= 2; --i) {
0291 auto &WInfo = *NumToInfo[i];
0292
0293
0294 WInfo.Semi = WInfo.Parent;
0295 for (unsigned N : WInfo.ReverseChildren) {
0296 unsigned SemiU = NumToInfo[eval(N, i + 1, EvalStack, NumToInfo)]->Semi;
0297 if (SemiU < WInfo.Semi) WInfo.Semi = SemiU;
0298 }
0299 }
0300
0301
0302
0303
0304
0305 for (unsigned i = 2; i < NextDFSNum; ++i) {
0306 auto &WInfo = *NumToInfo[i];
0307 assert(WInfo.Semi != 0);
0308 const unsigned SDomNum = NumToInfo[WInfo.Semi]->DFSNum;
0309 NodePtr WIDomCandidate = WInfo.IDom;
0310 while (true) {
0311 auto &WIDomCandidateInfo = getNodeInfo(WIDomCandidate);
0312 if (WIDomCandidateInfo.DFSNum <= SDomNum)
0313 break;
0314 WIDomCandidate = WIDomCandidateInfo.IDom;
0315 }
0316
0317 WInfo.IDom = WIDomCandidate;
0318 }
0319 }
0320
0321
0322
0323
0324
0325
0326 void addVirtualRoot() {
0327 assert(IsPostDom && "Only postdominators have a virtual root");
0328 assert(NumToNode.size() == 1 && "SNCAInfo must be freshly constructed");
0329
0330 auto &BBInfo = getNodeInfo(nullptr);
0331 BBInfo.DFSNum = BBInfo.Semi = BBInfo.Label = 1;
0332
0333 NumToNode.push_back(nullptr);
0334 }
0335
0336
0337
0338
0339 static bool HasForwardSuccessors(const NodePtr N, BatchUpdatePtr BUI) {
0340 assert(N && "N must be a valid node");
0341 return !getChildren<false>(N, BUI).empty();
0342 }
0343
0344 static NodePtr GetEntryNode(const DomTreeT &DT) {
0345 assert(DT.Parent && "Parent not set");
0346 return GraphTraits<typename DomTreeT::ParentPtr>::getEntryNode(DT.Parent);
0347 }
0348
0349
0350
0351
0352 static RootsT FindRoots(const DomTreeT &DT, BatchUpdatePtr BUI) {
0353 assert(DT.Parent && "Parent pointer is not set");
0354 RootsT Roots;
0355
0356
0357 if (!IsPostDom) {
0358 Roots.push_back(GetEntryNode(DT));
0359 return Roots;
0360 }
0361
0362 SemiNCAInfo SNCA(BUI);
0363
0364
0365 SNCA.addVirtualRoot();
0366 unsigned Num = 1;
0367
0368 LLVM_DEBUG(dbgs() << "\t\tLooking for trivial roots\n");
0369
0370
0371
0372 unsigned Total = 0;
0373
0374
0375
0376
0377
0378 for (const NodePtr N : nodes(DT.Parent)) {
0379 ++Total;
0380
0381 if (!HasForwardSuccessors(N, BUI)) {
0382 Roots.push_back(N);
0383
0384 Num = SNCA.runDFS(N, Num, AlwaysDescend, 1);
0385 LLVM_DEBUG(dbgs() << "Found a new trivial root: " << BlockNamePrinter(N)
0386 << "\n");
0387 LLVM_DEBUG(dbgs() << "Last visited node: "
0388 << BlockNamePrinter(SNCA.NumToNode[Num]) << "\n");
0389 }
0390 }
0391
0392 LLVM_DEBUG(dbgs() << "\t\tLooking for non-trivial roots\n");
0393
0394
0395
0396
0397 bool HasNonTrivialRoots = false;
0398
0399
0400 if (Total + 1 != Num) {
0401 HasNonTrivialRoots = true;
0402
0403
0404
0405
0406
0407
0408 std::optional<NodeOrderMap> SuccOrder;
0409 auto InitSuccOrderOnce = [&]() {
0410 SuccOrder = NodeOrderMap();
0411 for (const auto Node : nodes(DT.Parent))
0412 if (SNCA.getNodeInfo(Node).DFSNum == 0)
0413 for (const auto Succ : getChildren<false>(Node, SNCA.BatchUpdates))
0414 SuccOrder->try_emplace(Succ, 0);
0415
0416
0417 unsigned NodeNum = 0;
0418 for (const auto Node : nodes(DT.Parent)) {
0419 ++NodeNum;
0420 auto Order = SuccOrder->find(Node);
0421 if (Order != SuccOrder->end()) {
0422 assert(Order->second == 0);
0423 Order->second = NodeNum;
0424 }
0425 }
0426 };
0427
0428
0429
0430
0431
0432
0433
0434
0435 for (const NodePtr I : nodes(DT.Parent)) {
0436 if (SNCA.getNodeInfo(I).DFSNum == 0) {
0437 LLVM_DEBUG(dbgs()
0438 << "\t\t\tVisiting node " << BlockNamePrinter(I) << "\n");
0439
0440
0441
0442
0443
0444
0445
0446
0447
0448
0449 LLVM_DEBUG(dbgs() << "\t\t\tRunning forward DFS\n");
0450
0451 if (!SuccOrder)
0452 InitSuccOrderOnce();
0453 assert(SuccOrder);
0454
0455 const unsigned NewNum =
0456 SNCA.runDFS<true>(I, Num, AlwaysDescend, Num, &*SuccOrder);
0457 const NodePtr FurthestAway = SNCA.NumToNode[NewNum];
0458 LLVM_DEBUG(dbgs() << "\t\t\tFound a new furthest away node "
0459 << "(non-trivial root): "
0460 << BlockNamePrinter(FurthestAway) << "\n");
0461 Roots.push_back(FurthestAway);
0462 LLVM_DEBUG(dbgs() << "\t\t\tPrev DFSNum: " << Num << ", new DFSNum: "
0463 << NewNum << "\n\t\t\tRemoving DFS info\n");
0464 for (unsigned i = NewNum; i > Num; --i) {
0465 const NodePtr N = SNCA.NumToNode[i];
0466 LLVM_DEBUG(dbgs() << "\t\t\t\tRemoving DFS info for "
0467 << BlockNamePrinter(N) << "\n");
0468 SNCA.getNodeInfo(N) = {};
0469 SNCA.NumToNode.pop_back();
0470 }
0471 const unsigned PrevNum = Num;
0472 LLVM_DEBUG(dbgs() << "\t\t\tRunning reverse DFS\n");
0473 Num = SNCA.runDFS(FurthestAway, Num, AlwaysDescend, 1);
0474 for (unsigned i = PrevNum + 1; i <= Num; ++i)
0475 LLVM_DEBUG(dbgs() << "\t\t\t\tfound node "
0476 << BlockNamePrinter(SNCA.NumToNode[i]) << "\n");
0477 }
0478 }
0479 }
0480
0481 LLVM_DEBUG(dbgs() << "Total: " << Total << ", Num: " << Num << "\n");
0482 LLVM_DEBUG(dbgs() << "Discovered CFG nodes:\n");
0483 LLVM_DEBUG(for (size_t i = 0; i <= Num; ++i) dbgs()
0484 << i << ": " << BlockNamePrinter(SNCA.NumToNode[i]) << "\n");
0485
0486 assert((Total + 1 == Num) && "Everything should have been visited");
0487
0488
0489 if (HasNonTrivialRoots) RemoveRedundantRoots(DT, BUI, Roots);
0490
0491 LLVM_DEBUG(dbgs() << "Found roots: ");
0492 LLVM_DEBUG(for (auto *Root
0493 : Roots) dbgs()
0494 << BlockNamePrinter(Root) << " ");
0495 LLVM_DEBUG(dbgs() << "\n");
0496
0497 return Roots;
0498 }
0499
0500
0501
0502
0503
0504
0505
0506
0507
0508 static void RemoveRedundantRoots(const DomTreeT &DT, BatchUpdatePtr BUI,
0509 RootsT &Roots) {
0510 assert(IsPostDom && "This function is for postdominators only");
0511 LLVM_DEBUG(dbgs() << "Removing redundant roots\n");
0512
0513 SemiNCAInfo SNCA(BUI);
0514
0515 for (unsigned i = 0; i < Roots.size(); ++i) {
0516 auto &Root = Roots[i];
0517
0518 if (!HasForwardSuccessors(Root, BUI)) continue;
0519 LLVM_DEBUG(dbgs() << "\tChecking if " << BlockNamePrinter(Root)
0520 << " remains a root\n");
0521 SNCA.clear();
0522
0523 const unsigned Num = SNCA.runDFS<true>(Root, 0, AlwaysDescend, 0);
0524
0525
0526 for (unsigned x = 2; x <= Num; ++x) {
0527 const NodePtr N = SNCA.NumToNode[x];
0528
0529
0530
0531 if (llvm::is_contained(Roots, N)) {
0532 LLVM_DEBUG(dbgs() << "\tForward DFS walk found another root "
0533 << BlockNamePrinter(N) << "\n\tRemoving root "
0534 << BlockNamePrinter(Root) << "\n");
0535 std::swap(Root, Roots.back());
0536 Roots.pop_back();
0537
0538
0539
0540 --i;
0541 break;
0542 }
0543 }
0544 }
0545 }
0546
0547 template <typename DescendCondition>
0548 void doFullDFSWalk(const DomTreeT &DT, DescendCondition DC) {
0549 if (!IsPostDom) {
0550 assert(DT.Roots.size() == 1 && "Dominators should have a singe root");
0551 runDFS(DT.Roots[0], 0, DC, 0);
0552 return;
0553 }
0554
0555 addVirtualRoot();
0556 unsigned Num = 1;
0557 for (const NodePtr Root : DT.Roots) Num = runDFS(Root, Num, DC, 1);
0558 }
0559
0560 static void CalculateFromScratch(DomTreeT &DT, BatchUpdatePtr BUI) {
0561 auto *Parent = DT.Parent;
0562 DT.reset();
0563 DT.Parent = Parent;
0564
0565
0566
0567 BatchUpdatePtr PostViewBUI = nullptr;
0568 if (BUI && BUI->PostViewCFG) {
0569 BUI->PreViewCFG = *BUI->PostViewCFG;
0570 PostViewBUI = BUI;
0571 }
0572
0573
0574 SemiNCAInfo SNCA(PostViewBUI);
0575
0576
0577
0578 DT.Roots = FindRoots(DT, PostViewBUI);
0579 SNCA.doFullDFSWalk(DT, AlwaysDescend);
0580
0581 SNCA.runSemiNCA();
0582 if (BUI) {
0583 BUI->IsRecalculated = true;
0584 LLVM_DEBUG(
0585 dbgs() << "DomTree recalculated, skipping future batch updates\n");
0586 }
0587
0588 if (DT.Roots.empty()) return;
0589
0590
0591
0592
0593 NodePtr Root = IsPostDom ? nullptr : DT.Roots[0];
0594
0595 DT.RootNode = DT.createNode(Root);
0596 SNCA.attachNewSubtree(DT, DT.RootNode);
0597 }
0598
0599 void attachNewSubtree(DomTreeT& DT, const TreeNodePtr AttachTo) {
0600
0601 getNodeInfo(NumToNode[1]).IDom = AttachTo->getBlock();
0602
0603 for (NodePtr W : llvm::drop_begin(NumToNode)) {
0604 if (DT.getNode(W))
0605 continue;
0606
0607 NodePtr ImmDom = getIDom(W);
0608
0609
0610 TreeNodePtr IDomNode = getNodeForBlock(ImmDom, DT);
0611
0612
0613
0614 DT.createNode(W, IDomNode);
0615 }
0616 }
0617
0618 void reattachExistingSubtree(DomTreeT &DT, const TreeNodePtr AttachTo) {
0619 getNodeInfo(NumToNode[1]).IDom = AttachTo->getBlock();
0620 for (const NodePtr N : llvm::drop_begin(NumToNode)) {
0621 const TreeNodePtr TN = DT.getNode(N);
0622 assert(TN);
0623 const TreeNodePtr NewIDom = DT.getNode(getNodeInfo(N).IDom);
0624 TN->setIDom(NewIDom);
0625 }
0626 }
0627
0628
0629 struct InsertionInfo {
0630 struct Compare {
0631 bool operator()(TreeNodePtr LHS, TreeNodePtr RHS) const {
0632 return LHS->getLevel() < RHS->getLevel();
0633 }
0634 };
0635
0636
0637
0638 std::priority_queue<TreeNodePtr, SmallVector<TreeNodePtr, 8>,
0639 Compare>
0640 Bucket;
0641 SmallDenseSet<TreeNodePtr, 8> Visited;
0642 SmallVector<TreeNodePtr, 8> Affected;
0643 #if LLVM_ENABLE_ABI_BREAKING_CHECKS
0644 SmallVector<TreeNodePtr, 8> VisitedUnaffected;
0645 #endif
0646 };
0647
0648 static void InsertEdge(DomTreeT &DT, const BatchUpdatePtr BUI,
0649 const NodePtr From, const NodePtr To) {
0650 assert((From || IsPostDom) &&
0651 "From has to be a valid CFG node or a virtual root");
0652 assert(To && "Cannot be a nullptr");
0653 LLVM_DEBUG(dbgs() << "Inserting edge " << BlockNamePrinter(From) << " -> "
0654 << BlockNamePrinter(To) << "\n");
0655 TreeNodePtr FromTN = DT.getNode(From);
0656
0657 if (!FromTN) {
0658
0659 if (!IsPostDom) return;
0660
0661
0662 TreeNodePtr VirtualRoot = DT.getNode(nullptr);
0663 FromTN = DT.createNode(From, VirtualRoot);
0664 DT.Roots.push_back(From);
0665 }
0666
0667 DT.DFSInfoValid = false;
0668
0669 const TreeNodePtr ToTN = DT.getNode(To);
0670 if (!ToTN)
0671 InsertUnreachable(DT, BUI, FromTN, To);
0672 else
0673 InsertReachable(DT, BUI, FromTN, ToTN);
0674 }
0675
0676
0677
0678 static bool UpdateRootsBeforeInsertion(DomTreeT &DT, const BatchUpdatePtr BUI,
0679 const TreeNodePtr From,
0680 const TreeNodePtr To) {
0681 assert(IsPostDom && "This function is only for postdominators");
0682
0683
0684 if (!DT.isVirtualRoot(To->getIDom())) return false;
0685
0686 if (!llvm::is_contained(DT.Roots, To->getBlock()))
0687 return false;
0688
0689 LLVM_DEBUG(dbgs() << "\t\tAfter the insertion, " << BlockNamePrinter(To)
0690 << " is no longer a root\n\t\tRebuilding the tree!!!\n");
0691
0692 CalculateFromScratch(DT, BUI);
0693 return true;
0694 }
0695
0696 static bool isPermutation(const SmallVectorImpl<NodePtr> &A,
0697 const SmallVectorImpl<NodePtr> &B) {
0698 if (A.size() != B.size())
0699 return false;
0700 SmallPtrSet<NodePtr, 4> Set(A.begin(), A.end());
0701 for (NodePtr N : B)
0702 if (Set.count(N) == 0)
0703 return false;
0704 return true;
0705 }
0706
0707
0708
0709
0710 static void UpdateRootsAfterUpdate(DomTreeT &DT, const BatchUpdatePtr BUI) {
0711 assert(IsPostDom && "This function is only for postdominators");
0712
0713
0714 if (llvm::none_of(DT.Roots, [BUI](const NodePtr N) {
0715 return HasForwardSuccessors(N, BUI);
0716 }))
0717 return;
0718
0719
0720 RootsT Roots = FindRoots(DT, BUI);
0721 if (!isPermutation(DT.Roots, Roots)) {
0722
0723
0724
0725
0726
0727 LLVM_DEBUG(dbgs() << "Roots are different in updated trees\n"
0728 << "The entire tree needs to be rebuilt\n");
0729
0730
0731 CalculateFromScratch(DT, BUI);
0732 }
0733 }
0734
0735
0736 static void InsertReachable(DomTreeT &DT, const BatchUpdatePtr BUI,
0737 const TreeNodePtr From, const TreeNodePtr To) {
0738 LLVM_DEBUG(dbgs() << "\tReachable " << BlockNamePrinter(From->getBlock())
0739 << " -> " << BlockNamePrinter(To->getBlock()) << "\n");
0740 if (IsPostDom && UpdateRootsBeforeInsertion(DT, BUI, From, To)) return;
0741
0742
0743
0744 const NodePtr NCDBlock =
0745 (From->getBlock() && To->getBlock())
0746 ? DT.findNearestCommonDominator(From->getBlock(), To->getBlock())
0747 : nullptr;
0748 assert(NCDBlock || DT.isPostDominator());
0749 const TreeNodePtr NCD = DT.getNode(NCDBlock);
0750 assert(NCD);
0751
0752 LLVM_DEBUG(dbgs() << "\t\tNCA == " << BlockNamePrinter(NCD) << "\n");
0753 const unsigned NCDLevel = NCD->getLevel();
0754
0755
0756
0757
0758
0759
0760
0761
0762
0763
0764
0765 if (NCDLevel + 1 >= To->getLevel())
0766 return;
0767
0768 InsertionInfo II;
0769 SmallVector<TreeNodePtr, 8> UnaffectedOnCurrentLevel;
0770 II.Bucket.push(To);
0771 II.Visited.insert(To);
0772
0773 while (!II.Bucket.empty()) {
0774 TreeNodePtr TN = II.Bucket.top();
0775 II.Bucket.pop();
0776 II.Affected.push_back(TN);
0777
0778 const unsigned CurrentLevel = TN->getLevel();
0779 LLVM_DEBUG(dbgs() << "Mark " << BlockNamePrinter(TN) <<
0780 "as affected, CurrentLevel " << CurrentLevel << "\n");
0781
0782 assert(TN->getBlock() && II.Visited.count(TN) && "Preconditions!");
0783
0784 while (true) {
0785
0786
0787
0788
0789
0790
0791
0792
0793 for (const NodePtr Succ : getChildren<IsPostDom>(TN->getBlock(), BUI)) {
0794 const TreeNodePtr SuccTN = DT.getNode(Succ);
0795 assert(SuccTN &&
0796 "Unreachable successor found at reachable insertion");
0797 const unsigned SuccLevel = SuccTN->getLevel();
0798
0799 LLVM_DEBUG(dbgs() << "\tSuccessor " << BlockNamePrinter(Succ)
0800 << ", level = " << SuccLevel << "\n");
0801
0802
0803
0804
0805
0806
0807
0808
0809 if (SuccLevel <= NCDLevel + 1 || !II.Visited.insert(SuccTN).second)
0810 continue;
0811
0812 if (SuccLevel > CurrentLevel) {
0813
0814
0815 LLVM_DEBUG(dbgs() << "\t\tMarking visited not affected "
0816 << BlockNamePrinter(Succ) << "\n");
0817 UnaffectedOnCurrentLevel.push_back(SuccTN);
0818 #if LLVM_ENABLE_ABI_BREAKING_CHECKS
0819 II.VisitedUnaffected.push_back(SuccTN);
0820 #endif
0821 } else {
0822
0823
0824 LLVM_DEBUG(dbgs() << "\t\tAdd " << BlockNamePrinter(Succ)
0825 << " to a Bucket\n");
0826 II.Bucket.push(SuccTN);
0827 }
0828 }
0829
0830 if (UnaffectedOnCurrentLevel.empty())
0831 break;
0832 TN = UnaffectedOnCurrentLevel.pop_back_val();
0833 LLVM_DEBUG(dbgs() << " Next: " << BlockNamePrinter(TN) << "\n");
0834 }
0835 }
0836
0837
0838 UpdateInsertion(DT, BUI, NCD, II);
0839 }
0840
0841
0842 static void UpdateInsertion(DomTreeT &DT, const BatchUpdatePtr BUI,
0843 const TreeNodePtr NCD, InsertionInfo &II) {
0844 LLVM_DEBUG(dbgs() << "Updating NCD = " << BlockNamePrinter(NCD) << "\n");
0845
0846 for (const TreeNodePtr TN : II.Affected) {
0847 LLVM_DEBUG(dbgs() << "\tIDom(" << BlockNamePrinter(TN)
0848 << ") = " << BlockNamePrinter(NCD) << "\n");
0849 TN->setIDom(NCD);
0850 }
0851
0852 #if LLVM_ENABLE_ABI_BREAKING_CHECKS && !defined(NDEBUG)
0853 for (const TreeNodePtr TN : II.VisitedUnaffected)
0854 assert(TN->getLevel() == TN->getIDom()->getLevel() + 1 &&
0855 "TN should have been updated by an affected ancestor");
0856 #endif
0857
0858 if (IsPostDom) UpdateRootsAfterUpdate(DT, BUI);
0859 }
0860
0861
0862 static void InsertUnreachable(DomTreeT &DT, const BatchUpdatePtr BUI,
0863 const TreeNodePtr From, const NodePtr To) {
0864 LLVM_DEBUG(dbgs() << "Inserting " << BlockNamePrinter(From)
0865 << " -> (unreachable) " << BlockNamePrinter(To) << "\n");
0866
0867
0868 SmallVector<std::pair<NodePtr, TreeNodePtr>, 8> DiscoveredEdgesToReachable;
0869
0870 ComputeUnreachableDominators(DT, BUI, To, From, DiscoveredEdgesToReachable);
0871
0872 LLVM_DEBUG(dbgs() << "Inserted " << BlockNamePrinter(From)
0873 << " -> (prev unreachable) " << BlockNamePrinter(To)
0874 << "\n");
0875
0876
0877
0878 for (const auto &Edge : DiscoveredEdgesToReachable) {
0879 LLVM_DEBUG(dbgs() << "\tInserting discovered connecting edge "
0880 << BlockNamePrinter(Edge.first) << " -> "
0881 << BlockNamePrinter(Edge.second) << "\n");
0882 InsertReachable(DT, BUI, DT.getNode(Edge.first), Edge.second);
0883 }
0884 }
0885
0886
0887 static void ComputeUnreachableDominators(
0888 DomTreeT &DT, const BatchUpdatePtr BUI, const NodePtr Root,
0889 const TreeNodePtr Incoming,
0890 SmallVectorImpl<std::pair<NodePtr, TreeNodePtr>>
0891 &DiscoveredConnectingEdges) {
0892 assert(!DT.getNode(Root) && "Root must not be reachable");
0893
0894
0895 auto UnreachableDescender = [&DT, &DiscoveredConnectingEdges](NodePtr From,
0896 NodePtr To) {
0897 const TreeNodePtr ToTN = DT.getNode(To);
0898 if (!ToTN) return true;
0899
0900 DiscoveredConnectingEdges.push_back({From, ToTN});
0901 return false;
0902 };
0903
0904 SemiNCAInfo SNCA(BUI);
0905 SNCA.runDFS(Root, 0, UnreachableDescender, 0);
0906 SNCA.runSemiNCA();
0907 SNCA.attachNewSubtree(DT, Incoming);
0908
0909 LLVM_DEBUG(dbgs() << "After adding unreachable nodes\n");
0910 }
0911
0912 static void DeleteEdge(DomTreeT &DT, const BatchUpdatePtr BUI,
0913 const NodePtr From, const NodePtr To) {
0914 assert(From && To && "Cannot disconnect nullptrs");
0915 LLVM_DEBUG(dbgs() << "Deleting edge " << BlockNamePrinter(From) << " -> "
0916 << BlockNamePrinter(To) << "\n");
0917
0918 #if LLVM_ENABLE_ABI_BREAKING_CHECKS
0919
0920
0921
0922 auto IsSuccessor = [BUI](const NodePtr SuccCandidate, const NodePtr Of) {
0923 auto Successors = getChildren<IsPostDom>(Of, BUI);
0924 return llvm::is_contained(Successors, SuccCandidate);
0925 };
0926 (void)IsSuccessor;
0927 assert(!IsSuccessor(To, From) && "Deleted edge still exists in the CFG!");
0928 #endif
0929
0930 const TreeNodePtr FromTN = DT.getNode(From);
0931
0932 if (!FromTN) return;
0933
0934 const TreeNodePtr ToTN = DT.getNode(To);
0935 if (!ToTN) {
0936 LLVM_DEBUG(
0937 dbgs() << "\tTo (" << BlockNamePrinter(To)
0938 << ") already unreachable -- there is no edge to delete\n");
0939 return;
0940 }
0941
0942 const NodePtr NCDBlock = DT.findNearestCommonDominator(From, To);
0943 const TreeNodePtr NCD = DT.getNode(NCDBlock);
0944
0945
0946 if (ToTN != NCD) {
0947 DT.DFSInfoValid = false;
0948
0949 const TreeNodePtr ToIDom = ToTN->getIDom();
0950 LLVM_DEBUG(dbgs() << "\tNCD " << BlockNamePrinter(NCD) << ", ToIDom "
0951 << BlockNamePrinter(ToIDom) << "\n");
0952
0953
0954
0955 if (FromTN != ToIDom || HasProperSupport(DT, BUI, ToTN))
0956 DeleteReachable(DT, BUI, FromTN, ToTN);
0957 else
0958 DeleteUnreachable(DT, BUI, ToTN);
0959 }
0960
0961 if (IsPostDom) UpdateRootsAfterUpdate(DT, BUI);
0962 }
0963
0964
0965 static void DeleteReachable(DomTreeT &DT, const BatchUpdatePtr BUI,
0966 const TreeNodePtr FromTN,
0967 const TreeNodePtr ToTN) {
0968 LLVM_DEBUG(dbgs() << "Deleting reachable " << BlockNamePrinter(FromTN)
0969 << " -> " << BlockNamePrinter(ToTN) << "\n");
0970 LLVM_DEBUG(dbgs() << "\tRebuilding subtree\n");
0971
0972
0973
0974 const NodePtr ToIDom =
0975 DT.findNearestCommonDominator(FromTN->getBlock(), ToTN->getBlock());
0976 assert(ToIDom || DT.isPostDominator());
0977 const TreeNodePtr ToIDomTN = DT.getNode(ToIDom);
0978 assert(ToIDomTN);
0979 const TreeNodePtr PrevIDomSubTree = ToIDomTN->getIDom();
0980
0981
0982 if (!PrevIDomSubTree) {
0983 LLVM_DEBUG(dbgs() << "The entire tree needs to be rebuilt\n");
0984 CalculateFromScratch(DT, BUI);
0985 return;
0986 }
0987
0988
0989 const unsigned Level = ToIDomTN->getLevel();
0990 auto DescendBelow = [Level, &DT](NodePtr, NodePtr To) {
0991 return DT.getNode(To)->getLevel() > Level;
0992 };
0993
0994 LLVM_DEBUG(dbgs() << "\tTop of subtree: " << BlockNamePrinter(ToIDomTN)
0995 << "\n");
0996
0997 SemiNCAInfo SNCA(BUI);
0998 SNCA.runDFS(ToIDom, 0, DescendBelow, 0);
0999 LLVM_DEBUG(dbgs() << "\tRunning Semi-NCA\n");
1000 SNCA.runSemiNCA();
1001 SNCA.reattachExistingSubtree(DT, PrevIDomSubTree);
1002 }
1003
1004
1005
1006 static bool HasProperSupport(DomTreeT &DT, const BatchUpdatePtr BUI,
1007 const TreeNodePtr TN) {
1008 LLVM_DEBUG(dbgs() << "IsReachableFromIDom " << BlockNamePrinter(TN)
1009 << "\n");
1010 auto TNB = TN->getBlock();
1011 for (const NodePtr Pred : getChildren<!IsPostDom>(TNB, BUI)) {
1012 LLVM_DEBUG(dbgs() << "\tPred " << BlockNamePrinter(Pred) << "\n");
1013 if (!DT.getNode(Pred)) continue;
1014
1015 const NodePtr Support = DT.findNearestCommonDominator(TNB, Pred);
1016 LLVM_DEBUG(dbgs() << "\tSupport " << BlockNamePrinter(Support) << "\n");
1017 if (Support != TNB) {
1018 LLVM_DEBUG(dbgs() << "\t" << BlockNamePrinter(TN)
1019 << " is reachable from support "
1020 << BlockNamePrinter(Support) << "\n");
1021 return true;
1022 }
1023 }
1024
1025 return false;
1026 }
1027
1028
1029
1030 static void DeleteUnreachable(DomTreeT &DT, const BatchUpdatePtr BUI,
1031 const TreeNodePtr ToTN) {
1032 LLVM_DEBUG(dbgs() << "Deleting unreachable subtree "
1033 << BlockNamePrinter(ToTN) << "\n");
1034 assert(ToTN);
1035 assert(ToTN->getBlock());
1036
1037 if (IsPostDom) {
1038
1039
1040
1041 LLVM_DEBUG(dbgs() << "\tDeletion made a region reverse-unreachable\n");
1042 LLVM_DEBUG(dbgs() << "\tAdding new root " << BlockNamePrinter(ToTN)
1043 << "\n");
1044 DT.Roots.push_back(ToTN->getBlock());
1045 InsertReachable(DT, BUI, DT.getNode(nullptr), ToTN);
1046 return;
1047 }
1048
1049 SmallVector<NodePtr, 16> AffectedQueue;
1050 const unsigned Level = ToTN->getLevel();
1051
1052
1053
1054 auto DescendAndCollect = [Level, &AffectedQueue, &DT](NodePtr, NodePtr To) {
1055 const TreeNodePtr TN = DT.getNode(To);
1056 assert(TN);
1057 if (TN->getLevel() > Level) return true;
1058 if (!llvm::is_contained(AffectedQueue, To))
1059 AffectedQueue.push_back(To);
1060
1061 return false;
1062 };
1063
1064 SemiNCAInfo SNCA(BUI);
1065 unsigned LastDFSNum =
1066 SNCA.runDFS(ToTN->getBlock(), 0, DescendAndCollect, 0);
1067
1068 TreeNodePtr MinNode = ToTN;
1069
1070
1071
1072 for (const NodePtr N : AffectedQueue) {
1073 const TreeNodePtr TN = DT.getNode(N);
1074 const NodePtr NCDBlock =
1075 DT.findNearestCommonDominator(TN->getBlock(), ToTN->getBlock());
1076 assert(NCDBlock || DT.isPostDominator());
1077 const TreeNodePtr NCD = DT.getNode(NCDBlock);
1078 assert(NCD);
1079
1080 LLVM_DEBUG(dbgs() << "Processing affected node " << BlockNamePrinter(TN)
1081 << " with NCD = " << BlockNamePrinter(NCD)
1082 << ", MinNode =" << BlockNamePrinter(MinNode) << "\n");
1083 if (NCD != TN && NCD->getLevel() < MinNode->getLevel()) MinNode = NCD;
1084 }
1085
1086
1087 if (!MinNode->getIDom()) {
1088 LLVM_DEBUG(dbgs() << "The entire tree needs to be rebuilt\n");
1089 CalculateFromScratch(DT, BUI);
1090 return;
1091 }
1092
1093
1094
1095 for (unsigned i = LastDFSNum; i > 0; --i) {
1096 const NodePtr N = SNCA.NumToNode[i];
1097 LLVM_DEBUG(dbgs() << "Erasing node " << BlockNamePrinter(DT.getNode(N))
1098 << "\n");
1099 DT.eraseNode(N);
1100 }
1101
1102
1103 if (MinNode == ToTN) return;
1104
1105 LLVM_DEBUG(dbgs() << "DeleteUnreachable: running DFS with MinNode = "
1106 << BlockNamePrinter(MinNode) << "\n");
1107 const unsigned MinLevel = MinNode->getLevel();
1108 const TreeNodePtr PrevIDom = MinNode->getIDom();
1109 assert(PrevIDom);
1110 SNCA.clear();
1111
1112
1113 auto DescendBelow = [MinLevel, &DT](NodePtr, NodePtr To) {
1114 const TreeNodePtr ToTN = DT.getNode(To);
1115 return ToTN && ToTN->getLevel() > MinLevel;
1116 };
1117 SNCA.runDFS(MinNode->getBlock(), 0, DescendBelow, 0);
1118
1119 LLVM_DEBUG(dbgs() << "Previous IDom(MinNode) = "
1120 << BlockNamePrinter(PrevIDom) << "\nRunning Semi-NCA\n");
1121
1122
1123 SNCA.runSemiNCA();
1124 SNCA.reattachExistingSubtree(DT, PrevIDom);
1125 }
1126
1127
1128
1129
1130
1131 static void ApplyUpdates(DomTreeT &DT, GraphDiffT &PreViewCFG,
1132 GraphDiffT *PostViewCFG) {
1133
1134
1135 const size_t NumUpdates = PreViewCFG.getNumLegalizedUpdates();
1136 if (NumUpdates == 0)
1137 return;
1138
1139
1140
1141 if (NumUpdates == 1) {
1142 UpdateT Update = PreViewCFG.popUpdateForIncrementalUpdates();
1143 if (!PostViewCFG) {
1144 if (Update.getKind() == UpdateKind::Insert)
1145 InsertEdge(DT, nullptr, Update.getFrom(), Update.getTo());
1146 else
1147 DeleteEdge(DT, nullptr, Update.getFrom(), Update.getTo());
1148 } else {
1149 BatchUpdateInfo BUI(*PostViewCFG, PostViewCFG);
1150 if (Update.getKind() == UpdateKind::Insert)
1151 InsertEdge(DT, &BUI, Update.getFrom(), Update.getTo());
1152 else
1153 DeleteEdge(DT, &BUI, Update.getFrom(), Update.getTo());
1154 }
1155 return;
1156 }
1157
1158 BatchUpdateInfo BUI(PreViewCFG, PostViewCFG);
1159
1160
1161
1162
1163
1164
1165
1166
1167 if (DT.DomTreeNodes.size() <= 100) {
1168 if (BUI.NumLegalized > DT.DomTreeNodes.size())
1169 CalculateFromScratch(DT, &BUI);
1170 } else if (BUI.NumLegalized > DT.DomTreeNodes.size() / 40)
1171 CalculateFromScratch(DT, &BUI);
1172
1173
1174
1175
1176 for (size_t i = 0; i < BUI.NumLegalized && !BUI.IsRecalculated; ++i)
1177 ApplyNextUpdate(DT, BUI);
1178 }
1179
1180 static void ApplyNextUpdate(DomTreeT &DT, BatchUpdateInfo &BUI) {
1181
1182 UpdateT CurrentUpdate = BUI.PreViewCFG.popUpdateForIncrementalUpdates();
1183 #if 0
1184
1185
1186
1187 LLVM_DEBUG(dbgs() << "Applying update: ");
1188 LLVM_DEBUG(CurrentUpdate.dump(); dbgs() << "\n");
1189 #endif
1190
1191 if (CurrentUpdate.getKind() == UpdateKind::Insert)
1192 InsertEdge(DT, &BUI, CurrentUpdate.getFrom(), CurrentUpdate.getTo());
1193 else
1194 DeleteEdge(DT, &BUI, CurrentUpdate.getFrom(), CurrentUpdate.getTo());
1195 }
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206 bool verifyRoots(const DomTreeT &DT) {
1207 if (!DT.Parent && !DT.Roots.empty()) {
1208 errs() << "Tree has no parent but has roots!\n";
1209 errs().flush();
1210 return false;
1211 }
1212
1213 if (!IsPostDom) {
1214 if (DT.Roots.empty()) {
1215 errs() << "Tree doesn't have a root!\n";
1216 errs().flush();
1217 return false;
1218 }
1219
1220 if (DT.getRoot() != GetEntryNode(DT)) {
1221 errs() << "Tree's root is not its parent's entry node!\n";
1222 errs().flush();
1223 return false;
1224 }
1225 }
1226
1227 RootsT ComputedRoots = FindRoots(DT, nullptr);
1228 if (!isPermutation(DT.Roots, ComputedRoots)) {
1229 errs() << "Tree has different roots than freshly computed ones!\n";
1230 errs() << "\tPDT roots: ";
1231 for (const NodePtr N : DT.Roots) errs() << BlockNamePrinter(N) << ", ";
1232 errs() << "\n\tComputed roots: ";
1233 for (const NodePtr N : ComputedRoots)
1234 errs() << BlockNamePrinter(N) << ", ";
1235 errs() << "\n";
1236 errs().flush();
1237 return false;
1238 }
1239
1240 return true;
1241 }
1242
1243
1244
1245 bool verifyReachability(const DomTreeT &DT) {
1246 clear();
1247 doFullDFSWalk(DT, AlwaysDescend);
1248
1249 for (auto &NodeToTN : DT.DomTreeNodes) {
1250 const TreeNodePtr TN = NodeToTN.get();
1251 if (!TN)
1252 continue;
1253 const NodePtr BB = TN->getBlock();
1254
1255
1256 if (DT.isVirtualRoot(TN)) continue;
1257
1258 if (getNodeInfo(BB).DFSNum == 0) {
1259 errs() << "DomTree node " << BlockNamePrinter(BB)
1260 << " not found by DFS walk!\n";
1261 errs().flush();
1262
1263 return false;
1264 }
1265 }
1266
1267 for (const NodePtr N : NumToNode) {
1268 if (N && !DT.getNode(N)) {
1269 errs() << "CFG node " << BlockNamePrinter(N)
1270 << " not found in the DomTree!\n";
1271 errs().flush();
1272
1273 return false;
1274 }
1275 }
1276
1277 return true;
1278 }
1279
1280
1281
1282
1283 static bool VerifyLevels(const DomTreeT &DT) {
1284 for (auto &NodeToTN : DT.DomTreeNodes) {
1285 const TreeNodePtr TN = NodeToTN.get();
1286 if (!TN)
1287 continue;
1288 const NodePtr BB = TN->getBlock();
1289 if (!BB) continue;
1290
1291 const TreeNodePtr IDom = TN->getIDom();
1292 if (!IDom && TN->getLevel() != 0) {
1293 errs() << "Node without an IDom " << BlockNamePrinter(BB)
1294 << " has a nonzero level " << TN->getLevel() << "!\n";
1295 errs().flush();
1296
1297 return false;
1298 }
1299
1300 if (IDom && TN->getLevel() != IDom->getLevel() + 1) {
1301 errs() << "Node " << BlockNamePrinter(BB) << " has level "
1302 << TN->getLevel() << " while its IDom "
1303 << BlockNamePrinter(IDom->getBlock()) << " has level "
1304 << IDom->getLevel() << "!\n";
1305 errs().flush();
1306
1307 return false;
1308 }
1309 }
1310
1311 return true;
1312 }
1313
1314
1315
1316
1317 static bool VerifyDFSNumbers(const DomTreeT &DT) {
1318 if (!DT.DFSInfoValid || !DT.Parent)
1319 return true;
1320
1321 const NodePtr RootBB = IsPostDom ? nullptr : *DT.root_begin();
1322 const TreeNodePtr Root = DT.getNode(RootBB);
1323
1324 auto PrintNodeAndDFSNums = [](const TreeNodePtr TN) {
1325 errs() << BlockNamePrinter(TN) << " {" << TN->getDFSNumIn() << ", "
1326 << TN->getDFSNumOut() << '}';
1327 };
1328
1329
1330
1331 if (Root->getDFSNumIn() != 0) {
1332 errs() << "DFSIn number for the tree root is not:\n\t";
1333 PrintNodeAndDFSNums(Root);
1334 errs() << '\n';
1335 errs().flush();
1336 return false;
1337 }
1338
1339
1340
1341 for (const auto &NodeToTN : DT.DomTreeNodes) {
1342 const TreeNodePtr Node = NodeToTN.get();
1343 if (!Node)
1344 continue;
1345
1346
1347 if (Node->isLeaf()) {
1348 if (Node->getDFSNumIn() + 1 != Node->getDFSNumOut()) {
1349 errs() << "Tree leaf should have DFSOut = DFSIn + 1:\n\t";
1350 PrintNodeAndDFSNums(Node);
1351 errs() << '\n';
1352 errs().flush();
1353 return false;
1354 }
1355
1356 continue;
1357 }
1358
1359
1360
1361 SmallVector<TreeNodePtr, 8> Children(Node->begin(), Node->end());
1362 llvm::sort(Children, [](const TreeNodePtr Ch1, const TreeNodePtr Ch2) {
1363 return Ch1->getDFSNumIn() < Ch2->getDFSNumIn();
1364 });
1365
1366 auto PrintChildrenError = [Node, &Children, PrintNodeAndDFSNums](
1367 const TreeNodePtr FirstCh, const TreeNodePtr SecondCh) {
1368 assert(FirstCh);
1369
1370 errs() << "Incorrect DFS numbers for:\n\tParent ";
1371 PrintNodeAndDFSNums(Node);
1372
1373 errs() << "\n\tChild ";
1374 PrintNodeAndDFSNums(FirstCh);
1375
1376 if (SecondCh) {
1377 errs() << "\n\tSecond child ";
1378 PrintNodeAndDFSNums(SecondCh);
1379 }
1380
1381 errs() << "\nAll children: ";
1382 for (const TreeNodePtr Ch : Children) {
1383 PrintNodeAndDFSNums(Ch);
1384 errs() << ", ";
1385 }
1386
1387 errs() << '\n';
1388 errs().flush();
1389 };
1390
1391 if (Children.front()->getDFSNumIn() != Node->getDFSNumIn() + 1) {
1392 PrintChildrenError(Children.front(), nullptr);
1393 return false;
1394 }
1395
1396 if (Children.back()->getDFSNumOut() + 1 != Node->getDFSNumOut()) {
1397 PrintChildrenError(Children.back(), nullptr);
1398 return false;
1399 }
1400
1401 for (size_t i = 0, e = Children.size() - 1; i != e; ++i) {
1402 if (Children[i]->getDFSNumOut() + 1 != Children[i + 1]->getDFSNumIn()) {
1403 PrintChildrenError(Children[i], Children[i + 1]);
1404 return false;
1405 }
1406 }
1407 }
1408
1409 return true;
1410 }
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455 bool verifyParentProperty(const DomTreeT &DT) {
1456 for (auto &NodeToTN : DT.DomTreeNodes) {
1457 const TreeNodePtr TN = NodeToTN.get();
1458 if (!TN)
1459 continue;
1460 const NodePtr BB = TN->getBlock();
1461 if (!BB || TN->isLeaf())
1462 continue;
1463
1464 LLVM_DEBUG(dbgs() << "Verifying parent property of node "
1465 << BlockNamePrinter(TN) << "\n");
1466 clear();
1467 doFullDFSWalk(DT, [BB](NodePtr From, NodePtr To) {
1468 return From != BB && To != BB;
1469 });
1470
1471 for (TreeNodePtr Child : TN->children())
1472 if (getNodeInfo(Child->getBlock()).DFSNum != 0) {
1473 errs() << "Child " << BlockNamePrinter(Child)
1474 << " reachable after its parent " << BlockNamePrinter(BB)
1475 << " is removed!\n";
1476 errs().flush();
1477
1478 return false;
1479 }
1480 }
1481
1482 return true;
1483 }
1484
1485
1486
1487
1488
1489
1490
1491 bool verifySiblingProperty(const DomTreeT &DT) {
1492 for (auto &NodeToTN : DT.DomTreeNodes) {
1493 const TreeNodePtr TN = NodeToTN.get();
1494 if (!TN)
1495 continue;
1496 const NodePtr BB = TN->getBlock();
1497 if (!BB || TN->isLeaf())
1498 continue;
1499
1500 for (const TreeNodePtr N : TN->children()) {
1501 clear();
1502 NodePtr BBN = N->getBlock();
1503 doFullDFSWalk(DT, [BBN](NodePtr From, NodePtr To) {
1504 return From != BBN && To != BBN;
1505 });
1506
1507 for (const TreeNodePtr S : TN->children()) {
1508 if (S == N) continue;
1509
1510 if (getNodeInfo(S->getBlock()).DFSNum == 0) {
1511 errs() << "Node " << BlockNamePrinter(S)
1512 << " not reachable when its sibling " << BlockNamePrinter(N)
1513 << " is removed!\n";
1514 errs().flush();
1515
1516 return false;
1517 }
1518 }
1519 }
1520 }
1521
1522 return true;
1523 }
1524
1525
1526
1527
1528
1529
1530
1531
1532 static bool IsSameAsFreshTree(const DomTreeT &DT) {
1533 DomTreeT FreshTree;
1534 FreshTree.recalculate(*DT.Parent);
1535 const bool Different = DT.compare(FreshTree);
1536
1537 if (Different) {
1538 errs() << (DT.isPostDominator() ? "Post" : "")
1539 << "DominatorTree is different than a freshly computed one!\n"
1540 << "\tCurrent:\n";
1541 DT.print(errs());
1542 errs() << "\n\tFreshly computed tree:\n";
1543 FreshTree.print(errs());
1544 errs().flush();
1545 }
1546
1547 return !Different;
1548 }
1549 };
1550
1551 template <class DomTreeT>
1552 void Calculate(DomTreeT &DT) {
1553 SemiNCAInfo<DomTreeT>::CalculateFromScratch(DT, nullptr);
1554 }
1555
1556 template <typename DomTreeT>
1557 void CalculateWithUpdates(DomTreeT &DT,
1558 ArrayRef<typename DomTreeT::UpdateType> Updates) {
1559
1560
1561 GraphDiff<typename DomTreeT::NodePtr, DomTreeT::IsPostDominator> PreViewCFG(
1562 Updates, true);
1563 typename SemiNCAInfo<DomTreeT>::BatchUpdateInfo BUI(PreViewCFG);
1564 SemiNCAInfo<DomTreeT>::CalculateFromScratch(DT, &BUI);
1565 }
1566
1567 template <class DomTreeT>
1568 void InsertEdge(DomTreeT &DT, typename DomTreeT::NodePtr From,
1569 typename DomTreeT::NodePtr To) {
1570 if (DT.isPostDominator()) std::swap(From, To);
1571 SemiNCAInfo<DomTreeT>::InsertEdge(DT, nullptr, From, To);
1572 }
1573
1574 template <class DomTreeT>
1575 void DeleteEdge(DomTreeT &DT, typename DomTreeT::NodePtr From,
1576 typename DomTreeT::NodePtr To) {
1577 if (DT.isPostDominator()) std::swap(From, To);
1578 SemiNCAInfo<DomTreeT>::DeleteEdge(DT, nullptr, From, To);
1579 }
1580
1581 template <class DomTreeT>
1582 void ApplyUpdates(DomTreeT &DT,
1583 GraphDiff<typename DomTreeT::NodePtr,
1584 DomTreeT::IsPostDominator> &PreViewCFG,
1585 GraphDiff<typename DomTreeT::NodePtr,
1586 DomTreeT::IsPostDominator> *PostViewCFG) {
1587 SemiNCAInfo<DomTreeT>::ApplyUpdates(DT, PreViewCFG, PostViewCFG);
1588 }
1589
1590 template <class DomTreeT>
1591 bool Verify(const DomTreeT &DT, typename DomTreeT::VerificationLevel VL) {
1592 SemiNCAInfo<DomTreeT> SNCA(nullptr);
1593
1594
1595
1596 if (!SNCA.IsSameAsFreshTree(DT))
1597 return false;
1598
1599
1600 if (!SNCA.verifyRoots(DT) || !SNCA.verifyReachability(DT) ||
1601 !SNCA.VerifyLevels(DT) || !SNCA.VerifyDFSNumbers(DT))
1602 return false;
1603
1604
1605 if (VL == DomTreeT::VerificationLevel::Basic ||
1606 VL == DomTreeT::VerificationLevel::Full)
1607 if (!SNCA.verifyParentProperty(DT))
1608 return false;
1609 if (VL == DomTreeT::VerificationLevel::Full)
1610 if (!SNCA.verifySiblingProperty(DT))
1611 return false;
1612
1613 return true;
1614 }
1615
1616 }
1617 }
1618
1619 #undef DEBUG_TYPE
1620
1621 #endif