/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/include/llvm/Support/GenericDomTreeConstruction.h
Line | Count | Source (jump to first uncovered line) |
1 | | //===- GenericDomTreeConstruction.h - Dominator Calculation ------*- C++ -*-==// |
2 | | // |
3 | | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | | // See https://llvm.org/LICENSE.txt for license information. |
5 | | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | | // |
7 | | //===----------------------------------------------------------------------===// |
8 | | /// \file |
9 | | /// |
10 | | /// Generic dominator tree construction - This file provides routines to |
11 | | /// construct immediate dominator information for a flow-graph based on the |
12 | | /// Semi-NCA algorithm described in this dissertation: |
13 | | /// |
14 | | /// Linear-Time Algorithms for Dominators and Related Problems |
15 | | /// Loukas Georgiadis, Princeton University, November 2005, pp. 21-23: |
16 | | /// ftp://ftp.cs.princeton.edu/reports/2005/737.pdf |
17 | | /// |
18 | | /// Semi-NCA algorithm runs in O(n^2) worst-case time but usually slightly |
19 | | /// faster than Simple Lengauer-Tarjan in practice. |
20 | | /// |
21 | | /// O(n^2) worst cases happen when the computation of nearest common ancestors |
22 | | /// requires O(n) average time, which is very unlikely in real world. If this |
23 | | /// ever turns out to be an issue, consider implementing a hybrid algorithm. |
24 | | /// |
25 | | /// The file uses the Depth Based Search algorithm to perform incremental |
26 | | /// updates (insertion and deletions). The implemented algorithm is based on |
27 | | /// this publication: |
28 | | /// |
29 | | /// An Experimental Study of Dynamic Dominators |
30 | | /// Loukas Georgiadis, et al., April 12 2016, pp. 5-7, 9-10: |
31 | | /// https://arxiv.org/pdf/1604.02711.pdf |
32 | | /// |
33 | | //===----------------------------------------------------------------------===// |
34 | | |
35 | | #ifndef LLVM_SUPPORT_GENERICDOMTREECONSTRUCTION_H |
36 | | #define LLVM_SUPPORT_GENERICDOMTREECONSTRUCTION_H |
37 | | |
38 | | #include <queue> |
39 | | #include "llvm/ADT/ArrayRef.h" |
40 | | #include "llvm/ADT/DenseSet.h" |
41 | | #include "llvm/ADT/DepthFirstIterator.h" |
42 | | #include "llvm/ADT/PointerIntPair.h" |
43 | | #include "llvm/ADT/SmallPtrSet.h" |
44 | | #include "llvm/Support/Debug.h" |
45 | | #include "llvm/Support/GenericDomTree.h" |
46 | | |
47 | | #define DEBUG_TYPE "dom-tree-builder" |
48 | | |
49 | | namespace llvm { |
50 | | namespace DomTreeBuilder { |
51 | | |
52 | | template <typename DomTreeT> |
53 | | struct SemiNCAInfo { |
54 | | using NodePtr = typename DomTreeT::NodePtr; |
55 | | using NodeT = typename DomTreeT::NodeType; |
56 | | using TreeNodePtr = DomTreeNodeBase<NodeT> *; |
57 | | using RootsT = decltype(DomTreeT::Roots); |
58 | | static constexpr bool IsPostDom = DomTreeT::IsPostDominator; |
59 | | |
60 | | // Information record used by Semi-NCA during tree construction. |
61 | | struct InfoRec { |
62 | | unsigned DFSNum = 0; |
63 | | unsigned Parent = 0; |
64 | | unsigned Semi = 0; |
65 | | NodePtr Label = nullptr; |
66 | | NodePtr IDom = nullptr; |
67 | | SmallVector<NodePtr, 2> ReverseChildren; |
68 | | }; |
69 | | |
70 | | // Number to node mapping is 1-based. Initialize the mapping to start with |
71 | | // a dummy element. |
72 | | std::vector<NodePtr> NumToNode = {nullptr}; |
73 | | DenseMap<NodePtr, InfoRec> NodeToInfo; |
74 | | |
75 | | using UpdateT = typename DomTreeT::UpdateType; |
76 | | using UpdateKind = typename DomTreeT::UpdateKind; |
77 | | struct BatchUpdateInfo { |
78 | | SmallVector<UpdateT, 4> Updates; |
79 | | using NodePtrAndKind = PointerIntPair<NodePtr, 1, UpdateKind>; |
80 | | |
81 | | // In order to be able to walk a CFG that is out of sync with the CFG |
82 | | // DominatorTree last knew about, use the list of updates to reconstruct |
83 | | // previous CFG versions of the current CFG. For each node, we store a set |
84 | | // of its virtually added/deleted future successors and predecessors. |
85 | | // Note that these children are from the future relative to what the |
86 | | // DominatorTree knows about -- using them to gets us some snapshot of the |
87 | | // CFG from the past (relative to the state of the CFG). |
88 | | DenseMap<NodePtr, SmallVector<NodePtrAndKind, 4>> FutureSuccessors; |
89 | | DenseMap<NodePtr, SmallVector<NodePtrAndKind, 4>> FuturePredecessors; |
90 | | // Remembers if the whole tree was recalculated at some point during the |
91 | | // current batch update. |
92 | | bool IsRecalculated = false; |
93 | | }; |
94 | | |
95 | | BatchUpdateInfo *BatchUpdates; |
96 | | using BatchUpdatePtr = BatchUpdateInfo *; |
97 | | |
98 | | // If BUI is a nullptr, then there's no batch update in progress. |
99 | 18.0M | SemiNCAInfo(BatchUpdatePtr BUI) : BatchUpdates(BUI) {} llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> >::SemiNCAInfo(llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> >::BatchUpdateInfo*) Line | Count | Source | 99 | 2.61M | SemiNCAInfo(BatchUpdatePtr BUI) : BatchUpdates(BUI) {} |
llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> >::SemiNCAInfo(llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> >::BatchUpdateInfo*) Line | Count | Source | 99 | 3.01M | SemiNCAInfo(BatchUpdatePtr BUI) : BatchUpdates(BUI) {} |
llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, false> >::SemiNCAInfo(llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, false> >::BatchUpdateInfo*) Line | Count | Source | 99 | 11.2M | SemiNCAInfo(BatchUpdatePtr BUI) : BatchUpdates(BUI) {} |
llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, true> >::SemiNCAInfo(llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, true> >::BatchUpdateInfo*) Line | Count | Source | 99 | 1.21M | SemiNCAInfo(BatchUpdatePtr BUI) : BatchUpdates(BUI) {} |
llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::VPBlockBase, false> >::SemiNCAInfo(llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::VPBlockBase, false> >::BatchUpdateInfo*) Line | Count | Source | 99 | 28 | SemiNCAInfo(BatchUpdatePtr BUI) : BatchUpdates(BUI) {} |
llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<clang::CFGBlock, false> >::SemiNCAInfo(llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<clang::CFGBlock, false> >::BatchUpdateInfo*) Line | Count | Source | 99 | 8 | SemiNCAInfo(BatchUpdatePtr BUI) : BatchUpdates(BUI) {} |
llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<clang::CFGBlock, true> >::SemiNCAInfo(llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<clang::CFGBlock, true> >::BatchUpdateInfo*) Line | Count | Source | 99 | 214 | SemiNCAInfo(BatchUpdatePtr BUI) : BatchUpdates(BUI) {} |
|
100 | | |
101 | 34.7k | void clear() { |
102 | 34.7k | NumToNode = {nullptr}; // Restore to initial state with a dummy start node. |
103 | 34.7k | NodeToInfo.clear(); |
104 | 34.7k | // Don't reset the pointer to BatchUpdateInfo here -- if there's an update |
105 | 34.7k | // in progress, we need this information to continue it. |
106 | 34.7k | } Unexecuted instantiation: llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> >::clear() llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> >::clear() Line | Count | Source | 101 | 1.38k | void clear() { | 102 | 1.38k | NumToNode = {nullptr}; // Restore to initial state with a dummy start node. | 103 | 1.38k | NodeToInfo.clear(); | 104 | 1.38k | // Don't reset the pointer to BatchUpdateInfo here -- if there's an update | 105 | 1.38k | // in progress, we need this information to continue it. | 106 | 1.38k | } |
llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, true> >::clear() Line | Count | Source | 101 | 4.71k | void clear() { | 102 | 4.71k | NumToNode = {nullptr}; // Restore to initial state with a dummy start node. | 103 | 4.71k | NodeToInfo.clear(); | 104 | 4.71k | // Don't reset the pointer to BatchUpdateInfo here -- if there's an update | 105 | 4.71k | // in progress, we need this information to continue it. | 106 | 4.71k | } |
llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, false> >::clear() Line | Count | Source | 101 | 28.6k | void clear() { | 102 | 28.6k | NumToNode = {nullptr}; // Restore to initial state with a dummy start node. | 103 | 28.6k | NodeToInfo.clear(); | 104 | 28.6k | // Don't reset the pointer to BatchUpdateInfo here -- if there's an update | 105 | 28.6k | // in progress, we need this information to continue it. | 106 | 28.6k | } |
Unexecuted instantiation: llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::VPBlockBase, false> >::clear() Unexecuted instantiation: llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<clang::CFGBlock, true> >::clear() Unexecuted instantiation: llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<clang::CFGBlock, false> >::clear() |
107 | | |
108 | | template <bool Inverse> |
109 | | struct ChildrenGetter { |
110 | | using ResultTy = SmallVector<NodePtr, 8>; |
111 | | |
112 | 111M | static ResultTy Get(NodePtr N, std::integral_constant<bool, false>) { |
113 | 111M | auto RChildren = reverse(children<NodePtr>(N)); |
114 | 111M | return ResultTy(RChildren.begin(), RChildren.end()); |
115 | 111M | } llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> >::ChildrenGetter<false>::Get(llvm::MachineBasicBlock*, std::__1::integral_constant<bool, false>) Line | Count | Source | 112 | 12.0M | static ResultTy Get(NodePtr N, std::integral_constant<bool, false>) { | 113 | 12.0M | auto RChildren = reverse(children<NodePtr>(N)); | 114 | 12.0M | return ResultTy(RChildren.begin(), RChildren.end()); | 115 | 12.0M | } |
llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> >::ChildrenGetter<false>::Get(llvm::MachineBasicBlock*, std::__1::integral_constant<bool, false>) Line | Count | Source | 112 | 8.53M | static ResultTy Get(NodePtr N, std::integral_constant<bool, false>) { | 113 | 8.53M | auto RChildren = reverse(children<NodePtr>(N)); | 114 | 8.53M | return ResultTy(RChildren.begin(), RChildren.end()); | 115 | 8.53M | } |
llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, false> >::ChildrenGetter<false>::Get(llvm::BasicBlock*, std::__1::integral_constant<bool, false>) Line | Count | Source | 112 | 87.7M | static ResultTy Get(NodePtr N, std::integral_constant<bool, false>) { | 113 | 87.7M | auto RChildren = reverse(children<NodePtr>(N)); | 114 | 87.7M | return ResultTy(RChildren.begin(), RChildren.end()); | 115 | 87.7M | } |
llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, true> >::ChildrenGetter<false>::Get(llvm::BasicBlock*, std::__1::integral_constant<bool, false>) Line | Count | Source | 112 | 3.07M | static ResultTy Get(NodePtr N, std::integral_constant<bool, false>) { | 113 | 3.07M | auto RChildren = reverse(children<NodePtr>(N)); | 114 | 3.07M | return ResultTy(RChildren.begin(), RChildren.end()); | 115 | 3.07M | } |
llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::VPBlockBase, false> >::ChildrenGetter<false>::Get(llvm::VPBlockBase*, std::__1::integral_constant<bool, false>) Line | Count | Source | 112 | 135 | static ResultTy Get(NodePtr N, std::integral_constant<bool, false>) { | 113 | 135 | auto RChildren = reverse(children<NodePtr>(N)); | 114 | 135 | return ResultTy(RChildren.begin(), RChildren.end()); | 115 | 135 | } |
|
116 | | |
117 | 23.6M | static ResultTy Get(NodePtr N, std::integral_constant<bool, true>) { |
118 | 23.6M | auto IChildren = inverse_children<NodePtr>(N); |
119 | 23.6M | return ResultTy(IChildren.begin(), IChildren.end()); |
120 | 23.6M | } Unexecuted instantiation: llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> >::ChildrenGetter<true>::Get(llvm::MachineBasicBlock*, std::__1::integral_constant<bool, true>) llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> >::ChildrenGetter<true>::Get(llvm::MachineBasicBlock*, std::__1::integral_constant<bool, true>) Line | Count | Source | 117 | 17.0M | static ResultTy Get(NodePtr N, std::integral_constant<bool, true>) { | 118 | 17.0M | auto IChildren = inverse_children<NodePtr>(N); | 119 | 17.0M | return ResultTy(IChildren.begin(), IChildren.end()); | 120 | 17.0M | } |
llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, true> >::ChildrenGetter<true>::Get(llvm::BasicBlock*, std::__1::integral_constant<bool, true>) Line | Count | Source | 117 | 6.16M | static ResultTy Get(NodePtr N, std::integral_constant<bool, true>) { | 118 | 6.16M | auto IChildren = inverse_children<NodePtr>(N); | 119 | 6.16M | return ResultTy(IChildren.begin(), IChildren.end()); | 120 | 6.16M | } |
llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, false> >::ChildrenGetter<true>::Get(llvm::BasicBlock*, std::__1::integral_constant<bool, true>) Line | Count | Source | 117 | 414k | static ResultTy Get(NodePtr N, std::integral_constant<bool, true>) { | 118 | 414k | auto IChildren = inverse_children<NodePtr>(N); | 119 | 414k | return ResultTy(IChildren.begin(), IChildren.end()); | 120 | 414k | } |
Unexecuted instantiation: llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::VPBlockBase, false> >::ChildrenGetter<true>::Get(llvm::VPBlockBase*, std::__1::integral_constant<bool, true>) |
121 | | |
122 | | using Tag = std::integral_constant<bool, Inverse>; |
123 | | |
124 | | // The function below is the core part of the batch updater. It allows the |
125 | | // Depth Based Search algorithm to perform incremental updates in lockstep |
126 | | // with updates to the CFG. We emulated lockstep CFG updates by getting its |
127 | | // next snapshots by reverse-applying future updates. |
128 | 134M | static ResultTy Get(NodePtr N, BatchUpdatePtr BUI) { |
129 | 134M | ResultTy Res = Get(N, Tag()); |
130 | 134M | // If there's no batch update in progress, simply return node's children. |
131 | 134M | if (!BUI) return Res111M ; |
132 | 23.8M | |
133 | 23.8M | // CFG children are actually its *most current* children, and we have to |
134 | 23.8M | // reverse-apply the future updates to get the node's children at the |
135 | 23.8M | // point in time the update was performed. |
136 | 23.8M | auto &FutureChildren = (Inverse != IsPostDom) ? BUI->FuturePredecessors402k |
137 | 23.8M | : BUI->FutureSuccessors23.4M ; |
138 | 23.8M | auto FCIt = FutureChildren.find(N); |
139 | 23.8M | if (FCIt == FutureChildren.end()) return Res23.0M ; |
140 | 796k | |
141 | 1.09M | for (auto ChildAndKind : FCIt->second)796k { |
142 | 1.09M | const NodePtr Child = ChildAndKind.getPointer(); |
143 | 1.09M | const UpdateKind UK = ChildAndKind.getInt(); |
144 | 1.09M | |
145 | 1.09M | // Reverse-apply the future update. |
146 | 1.09M | if (UK == UpdateKind::Insert) { |
147 | 431k | // If there's an insertion in the future, it means that the edge must |
148 | 431k | // exist in the current CFG, but was not present in it before. |
149 | 431k | assert(llvm::find(Res, Child) != Res.end() |
150 | 431k | && "Expected child not found in the CFG"); |
151 | 431k | Res.erase(std::remove(Res.begin(), Res.end(), Child), Res.end()); |
152 | 431k | LLVM_DEBUG(dbgs() << "\tHiding edge " << BlockNamePrinter(N) << " -> " |
153 | 431k | << BlockNamePrinter(Child) << "\n"); |
154 | 659k | } else { |
155 | 659k | // If there's an deletion in the future, it means that the edge cannot |
156 | 659k | // exist in the current CFG, but existed in it before. |
157 | 659k | assert(llvm::find(Res, Child) == Res.end() && |
158 | 659k | "Unexpected child found in the CFG"); |
159 | 659k | LLVM_DEBUG(dbgs() << "\tShowing virtual edge " << BlockNamePrinter(N) |
160 | 659k | << " -> " << BlockNamePrinter(Child) << "\n"); |
161 | 659k | Res.push_back(Child); |
162 | 659k | } |
163 | 1.09M | } |
164 | 796k | |
165 | 796k | return Res; |
166 | 796k | } llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> >::ChildrenGetter<false>::Get(llvm::MachineBasicBlock*, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> >::BatchUpdateInfo*) Line | Count | Source | 128 | 12.0M | static ResultTy Get(NodePtr N, BatchUpdatePtr BUI) { | 129 | 12.0M | ResultTy Res = Get(N, Tag()); | 130 | 12.0M | // If there's no batch update in progress, simply return node's children. | 131 | 12.0M | if (!BUI) return Res12.0M ; | 132 | 3 | | 133 | 3 | // CFG children are actually its *most current* children, and we have to | 134 | 3 | // reverse-apply the future updates to get the node's children at the | 135 | 3 | // point in time the update was performed. | 136 | 3 | auto &FutureChildren = (Inverse != IsPostDom) ? BUI->FuturePredecessors0 | 137 | 3 | : BUI->FutureSuccessors; | 138 | 3 | auto FCIt = FutureChildren.find(N); | 139 | 3 | if (FCIt == FutureChildren.end()) return Res0 ; | 140 | 3 | | 141 | 3 | for (auto ChildAndKind : FCIt->second) { | 142 | 0 | const NodePtr Child = ChildAndKind.getPointer(); | 143 | 0 | const UpdateKind UK = ChildAndKind.getInt(); | 144 | 0 |
| 145 | 0 | // Reverse-apply the future update. | 146 | 0 | if (UK == UpdateKind::Insert) { | 147 | 0 | // If there's an insertion in the future, it means that the edge must | 148 | 0 | // exist in the current CFG, but was not present in it before. | 149 | 0 | assert(llvm::find(Res, Child) != Res.end() | 150 | 0 | && "Expected child not found in the CFG"); | 151 | 0 | Res.erase(std::remove(Res.begin(), Res.end(), Child), Res.end()); | 152 | 0 | LLVM_DEBUG(dbgs() << "\tHiding edge " << BlockNamePrinter(N) << " -> " | 153 | 0 | << BlockNamePrinter(Child) << "\n"); | 154 | 0 | } else { | 155 | 0 | // If there's an deletion in the future, it means that the edge cannot | 156 | 0 | // exist in the current CFG, but existed in it before. | 157 | 0 | assert(llvm::find(Res, Child) == Res.end() && | 158 | 0 | "Unexpected child found in the CFG"); | 159 | 0 | LLVM_DEBUG(dbgs() << "\tShowing virtual edge " << BlockNamePrinter(N) | 160 | 0 | << " -> " << BlockNamePrinter(Child) << "\n"); | 161 | 0 | Res.push_back(Child); | 162 | 0 | } | 163 | 0 | } | 164 | 3 | | 165 | 3 | return Res; | 166 | 3 | } |
Unexecuted instantiation: llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> >::ChildrenGetter<true>::Get(llvm::MachineBasicBlock*, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> >::BatchUpdateInfo*) llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> >::ChildrenGetter<false>::Get(llvm::MachineBasicBlock*, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> >::BatchUpdateInfo*) Line | Count | Source | 128 | 8.53M | static ResultTy Get(NodePtr N, BatchUpdatePtr BUI) { | 129 | 8.53M | ResultTy Res = Get(N, Tag()); | 130 | 8.53M | // If there's no batch update in progress, simply return node's children. | 131 | 8.53M | if (!BUI8.53M ) return Res; | 132 | 18.4E | | 133 | 18.4E | // CFG children are actually its *most current* children, and we have to | 134 | 18.4E | // reverse-apply the future updates to get the node's children at the | 135 | 18.4E | // point in time the update was performed. | 136 | 18.4E | auto &FutureChildren = (Inverse != IsPostDom) ? BUI->FuturePredecessors0 | 137 | 18.4E | : BUI->FutureSuccessors; | 138 | 18.4E | auto FCIt = FutureChildren.find(N); | 139 | 18.4E | if (FCIt == FutureChildren.end()) return Res0 ; | 140 | 18.4E | | 141 | 18.4E | for (auto ChildAndKind : FCIt->second) { | 142 | 0 | const NodePtr Child = ChildAndKind.getPointer(); | 143 | 0 | const UpdateKind UK = ChildAndKind.getInt(); | 144 | 0 |
| 145 | 0 | // Reverse-apply the future update. | 146 | 0 | if (UK == UpdateKind::Insert) { | 147 | 0 | // If there's an insertion in the future, it means that the edge must | 148 | 0 | // exist in the current CFG, but was not present in it before. | 149 | 0 | assert(llvm::find(Res, Child) != Res.end() | 150 | 0 | && "Expected child not found in the CFG"); | 151 | 0 | Res.erase(std::remove(Res.begin(), Res.end(), Child), Res.end()); | 152 | 0 | LLVM_DEBUG(dbgs() << "\tHiding edge " << BlockNamePrinter(N) << " -> " | 153 | 0 | << BlockNamePrinter(Child) << "\n"); | 154 | 0 | } else { | 155 | 0 | // If there's an deletion in the future, it means that the edge cannot | 156 | 0 | // exist in the current CFG, but existed in it before. | 157 | 0 | assert(llvm::find(Res, Child) == Res.end() && | 158 | 0 | "Unexpected child found in the CFG"); | 159 | 0 | LLVM_DEBUG(dbgs() << "\tShowing virtual edge " << BlockNamePrinter(N) | 160 | 0 | << " -> " << BlockNamePrinter(Child) << "\n"); | 161 | 0 | Res.push_back(Child); | 162 | 0 | } | 163 | 0 | } | 164 | 18.4E | | 165 | 18.4E | return Res; | 166 | 18.4E | } |
llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> >::ChildrenGetter<true>::Get(llvm::MachineBasicBlock*, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> >::BatchUpdateInfo*) Line | Count | Source | 128 | 17.0M | static ResultTy Get(NodePtr N, BatchUpdatePtr BUI) { | 129 | 17.0M | ResultTy Res = Get(N, Tag()); | 130 | 17.0M | // If there's no batch update in progress, simply return node's children. | 131 | 17.0M | if (!BUI) return Res17.0M ; | 132 | 8 | | 133 | 8 | // CFG children are actually its *most current* children, and we have to | 134 | 8 | // reverse-apply the future updates to get the node's children at the | 135 | 8 | // point in time the update was performed. | 136 | 8 | auto &FutureChildren = (Inverse != IsPostDom) ? BUI->FuturePredecessors0 | 137 | 8 | : BUI->FutureSuccessors; | 138 | 8 | auto FCIt = FutureChildren.find(N); | 139 | 8 | if (FCIt == FutureChildren.end()) return Res0 ; | 140 | 8 | | 141 | 8 | for (auto ChildAndKind : FCIt->second) { | 142 | 0 | const NodePtr Child = ChildAndKind.getPointer(); | 143 | 0 | const UpdateKind UK = ChildAndKind.getInt(); | 144 | 0 |
| 145 | 0 | // Reverse-apply the future update. | 146 | 0 | if (UK == UpdateKind::Insert) { | 147 | 0 | // If there's an insertion in the future, it means that the edge must | 148 | 0 | // exist in the current CFG, but was not present in it before. | 149 | 0 | assert(llvm::find(Res, Child) != Res.end() | 150 | 0 | && "Expected child not found in the CFG"); | 151 | 0 | Res.erase(std::remove(Res.begin(), Res.end(), Child), Res.end()); | 152 | 0 | LLVM_DEBUG(dbgs() << "\tHiding edge " << BlockNamePrinter(N) << " -> " | 153 | 0 | << BlockNamePrinter(Child) << "\n"); | 154 | 0 | } else { | 155 | 0 | // If there's an deletion in the future, it means that the edge cannot | 156 | 0 | // exist in the current CFG, but existed in it before. | 157 | 0 | assert(llvm::find(Res, Child) == Res.end() && | 158 | 0 | "Unexpected child found in the CFG"); | 159 | 0 | LLVM_DEBUG(dbgs() << "\tShowing virtual edge " << BlockNamePrinter(N) | 160 | 0 | << " -> " << BlockNamePrinter(Child) << "\n"); | 161 | 0 | Res.push_back(Child); | 162 | 0 | } | 163 | 0 | } | 164 | 8 | | 165 | 8 | return Res; | 166 | 8 | } |
llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, false> >::ChildrenGetter<false>::Get(llvm::BasicBlock*, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, false> >::BatchUpdateInfo*) Line | Count | Source | 128 | 87.7M | static ResultTy Get(NodePtr N, BatchUpdatePtr BUI) { | 129 | 87.7M | ResultTy Res = Get(N, Tag()); | 130 | 87.7M | // If there's no batch update in progress, simply return node's children. | 131 | 87.7M | if (!BUI) return Res64.2M ; | 132 | 23.4M | | 133 | 23.4M | // CFG children are actually its *most current* children, and we have to | 134 | 23.4M | // reverse-apply the future updates to get the node's children at the | 135 | 23.4M | // point in time the update was performed. | 136 | 23.4M | auto &FutureChildren = (Inverse != IsPostDom) ? BUI->FuturePredecessors0 | 137 | 23.4M | : BUI->FutureSuccessors; | 138 | 23.4M | auto FCIt = FutureChildren.find(N); | 139 | 23.4M | if (FCIt == FutureChildren.end()) return Res22.7M ; | 140 | 766k | | 141 | 1.04M | for (auto ChildAndKind : FCIt->second)766k { | 142 | 1.04M | const NodePtr Child = ChildAndKind.getPointer(); | 143 | 1.04M | const UpdateKind UK = ChildAndKind.getInt(); | 144 | 1.04M | | 145 | 1.04M | // Reverse-apply the future update. | 146 | 1.04M | if (UK == UpdateKind::Insert) { | 147 | 408k | // If there's an insertion in the future, it means that the edge must | 148 | 408k | // exist in the current CFG, but was not present in it before. | 149 | 408k | assert(llvm::find(Res, Child) != Res.end() | 150 | 408k | && "Expected child not found in the CFG"); | 151 | 408k | Res.erase(std::remove(Res.begin(), Res.end(), Child), Res.end()); | 152 | 408k | LLVM_DEBUG(dbgs() << "\tHiding edge " << BlockNamePrinter(N) << " -> " | 153 | 408k | << BlockNamePrinter(Child) << "\n"); | 154 | 640k | } else { | 155 | 640k | // If there's an deletion in the future, it means that the edge cannot | 156 | 640k | // exist in the current CFG, but existed in it before. | 157 | 640k | assert(llvm::find(Res, Child) == Res.end() && | 158 | 640k | "Unexpected child found in the CFG"); | 159 | 640k | LLVM_DEBUG(dbgs() << "\tShowing virtual edge " << BlockNamePrinter(N) | 160 | 640k | << " -> " << BlockNamePrinter(Child) << "\n"); | 161 | 640k | Res.push_back(Child); | 162 | 640k | } | 163 | 1.04M | } | 164 | 766k | | 165 | 766k | return Res; | 166 | 766k | } |
llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, true> >::ChildrenGetter<false>::Get(llvm::BasicBlock*, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, true> >::BatchUpdateInfo*) Line | Count | Source | 128 | 3.07M | static ResultTy Get(NodePtr N, BatchUpdatePtr BUI) { | 129 | 3.07M | ResultTy Res = Get(N, Tag()); | 130 | 3.07M | // If there's no batch update in progress, simply return node's children. | 131 | 3.07M | if (!BUI) return Res3.06M ; | 132 | 804 | | 133 | 804 | // CFG children are actually its *most current* children, and we have to | 134 | 804 | // reverse-apply the future updates to get the node's children at the | 135 | 804 | // point in time the update was performed. | 136 | 804 | auto &FutureChildren = (Inverse != IsPostDom) ? BUI->FuturePredecessors794 | 137 | 804 | : BUI->FutureSuccessors10 ; | 138 | 804 | auto FCIt = FutureChildren.find(N); | 139 | 804 | if (FCIt == FutureChildren.end()) return Res493 ; | 140 | 311 | | 141 | 441 | for (auto ChildAndKind : FCIt->second)311 { | 142 | 441 | const NodePtr Child = ChildAndKind.getPointer(); | 143 | 441 | const UpdateKind UK = ChildAndKind.getInt(); | 144 | 441 | | 145 | 441 | // Reverse-apply the future update. | 146 | 441 | if (UK == UpdateKind::Insert) { | 147 | 272 | // If there's an insertion in the future, it means that the edge must | 148 | 272 | // exist in the current CFG, but was not present in it before. | 149 | 272 | assert(llvm::find(Res, Child) != Res.end() | 150 | 272 | && "Expected child not found in the CFG"); | 151 | 272 | Res.erase(std::remove(Res.begin(), Res.end(), Child), Res.end()); | 152 | 272 | LLVM_DEBUG(dbgs() << "\tHiding edge " << BlockNamePrinter(N) << " -> " | 153 | 272 | << BlockNamePrinter(Child) << "\n"); | 154 | 272 | } else { | 155 | 169 | // If there's an deletion in the future, it means that the edge cannot | 156 | 169 | // exist in the current CFG, but existed in it before. | 157 | 169 | assert(llvm::find(Res, Child) == Res.end() && | 158 | 169 | "Unexpected child found in the CFG"); | 159 | 169 | LLVM_DEBUG(dbgs() << "\tShowing virtual edge " << BlockNamePrinter(N) | 160 | 169 | << " -> " << BlockNamePrinter(Child) << "\n"); | 161 | 169 | Res.push_back(Child); | 162 | 169 | } | 163 | 441 | } | 164 | 311 | | 165 | 311 | return Res; | 166 | 311 | } |
llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, true> >::ChildrenGetter<true>::Get(llvm::BasicBlock*, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, true> >::BatchUpdateInfo*) Line | Count | Source | 128 | 6.16M | static ResultTy Get(NodePtr N, BatchUpdatePtr BUI) { | 129 | 6.16M | ResultTy Res = Get(N, Tag()); | 130 | 6.16M | // If there's no batch update in progress, simply return node's children. | 131 | 6.16M | if (!BUI) return Res6.16M ; | 132 | 540 | | 133 | 540 | // CFG children are actually its *most current* children, and we have to | 134 | 540 | // reverse-apply the future updates to get the node's children at the | 135 | 540 | // point in time the update was performed. | 136 | 540 | auto &FutureChildren = (Inverse != IsPostDom) ? BUI->FuturePredecessors0 | 137 | 540 | : BUI->FutureSuccessors; | 138 | 540 | auto FCIt = FutureChildren.find(N); | 139 | 540 | if (FCIt == FutureChildren.end()) return Res392 ; | 140 | 148 | | 141 | 237 | for (auto ChildAndKind : FCIt->second)148 { | 142 | 237 | const NodePtr Child = ChildAndKind.getPointer(); | 143 | 237 | const UpdateKind UK = ChildAndKind.getInt(); | 144 | 237 | | 145 | 237 | // Reverse-apply the future update. | 146 | 237 | if (UK == UpdateKind::Insert) { | 147 | 127 | // If there's an insertion in the future, it means that the edge must | 148 | 127 | // exist in the current CFG, but was not present in it before. | 149 | 127 | assert(llvm::find(Res, Child) != Res.end() | 150 | 127 | && "Expected child not found in the CFG"); | 151 | 127 | Res.erase(std::remove(Res.begin(), Res.end(), Child), Res.end()); | 152 | 127 | LLVM_DEBUG(dbgs() << "\tHiding edge " << BlockNamePrinter(N) << " -> " | 153 | 127 | << BlockNamePrinter(Child) << "\n"); | 154 | 127 | } else { | 155 | 110 | // If there's an deletion in the future, it means that the edge cannot | 156 | 110 | // exist in the current CFG, but existed in it before. | 157 | 110 | assert(llvm::find(Res, Child) == Res.end() && | 158 | 110 | "Unexpected child found in the CFG"); | 159 | 110 | LLVM_DEBUG(dbgs() << "\tShowing virtual edge " << BlockNamePrinter(N) | 160 | 110 | << " -> " << BlockNamePrinter(Child) << "\n"); | 161 | 110 | Res.push_back(Child); | 162 | 110 | } | 163 | 237 | } | 164 | 148 | | 165 | 148 | return Res; | 166 | 148 | } |
llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, false> >::ChildrenGetter<true>::Get(llvm::BasicBlock*, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, false> >::BatchUpdateInfo*) Line | Count | Source | 128 | 414k | static ResultTy Get(NodePtr N, BatchUpdatePtr BUI) { | 129 | 414k | ResultTy Res = Get(N, Tag()); | 130 | 414k | // If there's no batch update in progress, simply return node's children. | 131 | 414k | if (!BUI) return Res12.2k ; | 132 | 402k | | 133 | 402k | // CFG children are actually its *most current* children, and we have to | 134 | 402k | // reverse-apply the future updates to get the node's children at the | 135 | 402k | // point in time the update was performed. | 136 | 402k | auto &FutureChildren = (Inverse != IsPostDom) ? BUI->FuturePredecessors | 137 | 402k | : BUI->FutureSuccessors0 ; | 138 | 402k | auto FCIt = FutureChildren.find(N); | 139 | 402k | if (FCIt == FutureChildren.end()) return Res372k ; | 140 | 29.1k | | 141 | 42.2k | for (auto ChildAndKind : FCIt->second)29.1k { | 142 | 42.2k | const NodePtr Child = ChildAndKind.getPointer(); | 143 | 42.2k | const UpdateKind UK = ChildAndKind.getInt(); | 144 | 42.2k | | 145 | 42.2k | // Reverse-apply the future update. | 146 | 42.2k | if (UK == UpdateKind::Insert) { | 147 | 23.2k | // If there's an insertion in the future, it means that the edge must | 148 | 23.2k | // exist in the current CFG, but was not present in it before. | 149 | 23.2k | assert(llvm::find(Res, Child) != Res.end() | 150 | 23.2k | && "Expected child not found in the CFG"); | 151 | 23.2k | Res.erase(std::remove(Res.begin(), Res.end(), Child), Res.end()); | 152 | 23.2k | LLVM_DEBUG(dbgs() << "\tHiding edge " << BlockNamePrinter(N) << " -> " | 153 | 23.2k | << BlockNamePrinter(Child) << "\n"); | 154 | 23.2k | } else { | 155 | 18.9k | // If there's an deletion in the future, it means that the edge cannot | 156 | 18.9k | // exist in the current CFG, but existed in it before. | 157 | 18.9k | assert(llvm::find(Res, Child) == Res.end() && | 158 | 18.9k | "Unexpected child found in the CFG"); | 159 | 18.9k | LLVM_DEBUG(dbgs() << "\tShowing virtual edge " << BlockNamePrinter(N) | 160 | 18.9k | << " -> " << BlockNamePrinter(Child) << "\n"); | 161 | 18.9k | Res.push_back(Child); | 162 | 18.9k | } | 163 | 42.2k | } | 164 | 29.1k | | 165 | 29.1k | return Res; | 166 | 29.1k | } |
llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::VPBlockBase, false> >::ChildrenGetter<false>::Get(llvm::VPBlockBase*, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::VPBlockBase, false> >::BatchUpdateInfo*) Line | Count | Source | 128 | 135 | static ResultTy Get(NodePtr N, BatchUpdatePtr BUI) { | 129 | 135 | ResultTy Res = Get(N, Tag()); | 130 | 135 | // If there's no batch update in progress, simply return node's children. | 131 | 135 | if (!BUI) return Res; | 132 | 0 | | 133 | 0 | // CFG children are actually its *most current* children, and we have to | 134 | 0 | // reverse-apply the future updates to get the node's children at the | 135 | 0 | // point in time the update was performed. | 136 | 0 | auto &FutureChildren = (Inverse != IsPostDom) ? BUI->FuturePredecessors | 137 | 0 | : BUI->FutureSuccessors; | 138 | 0 | auto FCIt = FutureChildren.find(N); | 139 | 0 | if (FCIt == FutureChildren.end()) return Res; | 140 | 0 | | 141 | 0 | for (auto ChildAndKind : FCIt->second) { | 142 | 0 | const NodePtr Child = ChildAndKind.getPointer(); | 143 | 0 | const UpdateKind UK = ChildAndKind.getInt(); | 144 | 0 |
| 145 | 0 | // Reverse-apply the future update. | 146 | 0 | if (UK == UpdateKind::Insert) { | 147 | 0 | // If there's an insertion in the future, it means that the edge must | 148 | 0 | // exist in the current CFG, but was not present in it before. | 149 | 0 | assert(llvm::find(Res, Child) != Res.end() | 150 | 0 | && "Expected child not found in the CFG"); | 151 | 0 | Res.erase(std::remove(Res.begin(), Res.end(), Child), Res.end()); | 152 | 0 | LLVM_DEBUG(dbgs() << "\tHiding edge " << BlockNamePrinter(N) << " -> " | 153 | 0 | << BlockNamePrinter(Child) << "\n"); | 154 | 0 | } else { | 155 | 0 | // If there's an deletion in the future, it means that the edge cannot | 156 | 0 | // exist in the current CFG, but existed in it before. | 157 | 0 | assert(llvm::find(Res, Child) == Res.end() && | 158 | 0 | "Unexpected child found in the CFG"); | 159 | 0 | LLVM_DEBUG(dbgs() << "\tShowing virtual edge " << BlockNamePrinter(N) | 160 | 0 | << " -> " << BlockNamePrinter(Child) << "\n"); | 161 | 0 | Res.push_back(Child); | 162 | 0 | } | 163 | 0 | } | 164 | 0 |
| 165 | 0 | return Res; | 166 | 0 | } |
Unexecuted instantiation: llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::VPBlockBase, false> >::ChildrenGetter<true>::Get(llvm::VPBlockBase*, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::VPBlockBase, false> >::BatchUpdateInfo*) llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<clang::CFGBlock, false> >::ChildrenGetter<false>::Get(clang::CFGBlock*, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<clang::CFGBlock, false> >::BatchUpdateInfo*) Line | Count | Source | 128 | 66 | static ResultTy Get(NodePtr N, BatchUpdatePtr BUI) { | 129 | 66 | ResultTy Res = Get(N, Tag()); | 130 | 66 | // If there's no batch update in progress, simply return node's children. | 131 | 66 | if (!BUI) return Res; | 132 | 0 | | 133 | 0 | // CFG children are actually its *most current* children, and we have to | 134 | 0 | // reverse-apply the future updates to get the node's children at the | 135 | 0 | // point in time the update was performed. | 136 | 0 | auto &FutureChildren = (Inverse != IsPostDom) ? BUI->FuturePredecessors | 137 | 0 | : BUI->FutureSuccessors; | 138 | 0 | auto FCIt = FutureChildren.find(N); | 139 | 0 | if (FCIt == FutureChildren.end()) return Res; | 140 | 0 | | 141 | 0 | for (auto ChildAndKind : FCIt->second) { | 142 | 0 | const NodePtr Child = ChildAndKind.getPointer(); | 143 | 0 | const UpdateKind UK = ChildAndKind.getInt(); | 144 | 0 |
| 145 | 0 | // Reverse-apply the future update. | 146 | 0 | if (UK == UpdateKind::Insert) { | 147 | 0 | // If there's an insertion in the future, it means that the edge must | 148 | 0 | // exist in the current CFG, but was not present in it before. | 149 | 0 | assert(llvm::find(Res, Child) != Res.end() | 150 | 0 | && "Expected child not found in the CFG"); | 151 | 0 | Res.erase(std::remove(Res.begin(), Res.end(), Child), Res.end()); | 152 | 0 | LLVM_DEBUG(dbgs() << "\tHiding edge " << BlockNamePrinter(N) << " -> " | 153 | 0 | << BlockNamePrinter(Child) << "\n"); | 154 | 0 | } else { | 155 | 0 | // If there's an deletion in the future, it means that the edge cannot | 156 | 0 | // exist in the current CFG, but existed in it before. | 157 | 0 | assert(llvm::find(Res, Child) == Res.end() && | 158 | 0 | "Unexpected child found in the CFG"); | 159 | 0 | LLVM_DEBUG(dbgs() << "\tShowing virtual edge " << BlockNamePrinter(N) | 160 | 0 | << " -> " << BlockNamePrinter(Child) << "\n"); | 161 | 0 | Res.push_back(Child); | 162 | 0 | } | 163 | 0 | } | 164 | 0 |
| 165 | 0 | return Res; | 166 | 0 | } |
llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<clang::CFGBlock, true> >::ChildrenGetter<false>::Get(clang::CFGBlock*, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<clang::CFGBlock, true> >::BatchUpdateInfo*) Line | Count | Source | 128 | 549 | static ResultTy Get(NodePtr N, BatchUpdatePtr BUI) { | 129 | 549 | ResultTy Res = Get(N, Tag()); | 130 | 549 | // If there's no batch update in progress, simply return node's children. | 131 | 549 | if (!BUI) return Res; | 132 | 0 | | 133 | 0 | // CFG children are actually its *most current* children, and we have to | 134 | 0 | // reverse-apply the future updates to get the node's children at the | 135 | 0 | // point in time the update was performed. | 136 | 0 | auto &FutureChildren = (Inverse != IsPostDom) ? BUI->FuturePredecessors | 137 | 0 | : BUI->FutureSuccessors; | 138 | 0 | auto FCIt = FutureChildren.find(N); | 139 | 0 | if (FCIt == FutureChildren.end()) return Res; | 140 | 0 | | 141 | 0 | for (auto ChildAndKind : FCIt->second) { | 142 | 0 | const NodePtr Child = ChildAndKind.getPointer(); | 143 | 0 | const UpdateKind UK = ChildAndKind.getInt(); | 144 | 0 |
| 145 | 0 | // Reverse-apply the future update. | 146 | 0 | if (UK == UpdateKind::Insert) { | 147 | 0 | // If there's an insertion in the future, it means that the edge must | 148 | 0 | // exist in the current CFG, but was not present in it before. | 149 | 0 | assert(llvm::find(Res, Child) != Res.end() | 150 | 0 | && "Expected child not found in the CFG"); | 151 | 0 | Res.erase(std::remove(Res.begin(), Res.end(), Child), Res.end()); | 152 | 0 | LLVM_DEBUG(dbgs() << "\tHiding edge " << BlockNamePrinter(N) << " -> " | 153 | 0 | << BlockNamePrinter(Child) << "\n"); | 154 | 0 | } else { | 155 | 0 | // If there's an deletion in the future, it means that the edge cannot | 156 | 0 | // exist in the current CFG, but existed in it before. | 157 | 0 | assert(llvm::find(Res, Child) == Res.end() && | 158 | 0 | "Unexpected child found in the CFG"); | 159 | 0 | LLVM_DEBUG(dbgs() << "\tShowing virtual edge " << BlockNamePrinter(N) | 160 | 0 | << " -> " << BlockNamePrinter(Child) << "\n"); | 161 | 0 | Res.push_back(Child); | 162 | 0 | } | 163 | 0 | } | 164 | 0 |
| 165 | 0 | return Res; | 166 | 0 | } |
llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<clang::CFGBlock, true> >::ChildrenGetter<true>::Get(clang::CFGBlock*, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<clang::CFGBlock, true> >::BatchUpdateInfo*) Line | Count | Source | 128 | 1.09k | static ResultTy Get(NodePtr N, BatchUpdatePtr BUI) { | 129 | 1.09k | ResultTy Res = Get(N, Tag()); | 130 | 1.09k | // If there's no batch update in progress, simply return node's children. | 131 | 1.09k | if (!BUI) return Res; | 132 | 0 | | 133 | 0 | // CFG children are actually its *most current* children, and we have to | 134 | 0 | // reverse-apply the future updates to get the node's children at the | 135 | 0 | // point in time the update was performed. | 136 | 0 | auto &FutureChildren = (Inverse != IsPostDom) ? BUI->FuturePredecessors | 137 | 0 | : BUI->FutureSuccessors; | 138 | 0 | auto FCIt = FutureChildren.find(N); | 139 | 0 | if (FCIt == FutureChildren.end()) return Res; | 140 | 0 | | 141 | 0 | for (auto ChildAndKind : FCIt->second) { | 142 | 0 | const NodePtr Child = ChildAndKind.getPointer(); | 143 | 0 | const UpdateKind UK = ChildAndKind.getInt(); | 144 | 0 |
| 145 | 0 | // Reverse-apply the future update. | 146 | 0 | if (UK == UpdateKind::Insert) { | 147 | 0 | // If there's an insertion in the future, it means that the edge must | 148 | 0 | // exist in the current CFG, but was not present in it before. | 149 | 0 | assert(llvm::find(Res, Child) != Res.end() | 150 | 0 | && "Expected child not found in the CFG"); | 151 | 0 | Res.erase(std::remove(Res.begin(), Res.end(), Child), Res.end()); | 152 | 0 | LLVM_DEBUG(dbgs() << "\tHiding edge " << BlockNamePrinter(N) << " -> " | 153 | 0 | << BlockNamePrinter(Child) << "\n"); | 154 | 0 | } else { | 155 | 0 | // If there's an deletion in the future, it means that the edge cannot | 156 | 0 | // exist in the current CFG, but existed in it before. | 157 | 0 | assert(llvm::find(Res, Child) == Res.end() && | 158 | 0 | "Unexpected child found in the CFG"); | 159 | 0 | LLVM_DEBUG(dbgs() << "\tShowing virtual edge " << BlockNamePrinter(N) | 160 | 0 | << " -> " << BlockNamePrinter(Child) << "\n"); | 161 | 0 | Res.push_back(Child); | 162 | 0 | } | 163 | 0 | } | 164 | 0 |
| 165 | 0 | return Res; | 166 | 0 | } |
Unexecuted instantiation: llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<clang::CFGBlock, false> >::ChildrenGetter<true>::Get(clang::CFGBlock*, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<clang::CFGBlock, false> >::BatchUpdateInfo*) |
167 | | }; |
168 | | |
169 | 74.8M | NodePtr getIDom(NodePtr BB) const { |
170 | 74.8M | auto InfoIt = NodeToInfo.find(BB); |
171 | 74.8M | if (InfoIt == NodeToInfo.end()) return nullptr0 ; |
172 | 74.8M | |
173 | 74.8M | return InfoIt->second.IDom; |
174 | 74.8M | } llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> >::getIDom(llvm::MachineBasicBlock*) const Line | Count | Source | 169 | 9.38M | NodePtr getIDom(NodePtr BB) const { | 170 | 9.38M | auto InfoIt = NodeToInfo.find(BB); | 171 | 9.38M | if (InfoIt == NodeToInfo.end()) return nullptr0 ; | 172 | 9.38M | | 173 | 9.38M | return InfoIt->second.IDom; | 174 | 9.38M | } |
llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> >::getIDom(llvm::MachineBasicBlock*) const Line | Count | Source | 169 | 8.52M | NodePtr getIDom(NodePtr BB) const { | 170 | 8.52M | auto InfoIt = NodeToInfo.find(BB); | 171 | 8.52M | if (InfoIt == NodeToInfo.end()) return nullptr0 ; | 172 | 8.52M | | 173 | 8.52M | return InfoIt->second.IDom; | 174 | 8.52M | } |
llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, false> >::getIDom(llvm::BasicBlock*) const Line | Count | Source | 169 | 53.8M | NodePtr getIDom(NodePtr BB) const { | 170 | 53.8M | auto InfoIt = NodeToInfo.find(BB); | 171 | 53.8M | if (InfoIt == NodeToInfo.end()) return nullptr0 ; | 172 | 53.8M | | 173 | 53.8M | return InfoIt->second.IDom; | 174 | 53.8M | } |
llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, true> >::getIDom(llvm::BasicBlock*) const Line | Count | Source | 169 | 3.06M | NodePtr getIDom(NodePtr BB) const { | 170 | 3.06M | auto InfoIt = NodeToInfo.find(BB); | 171 | 3.06M | if (InfoIt == NodeToInfo.end()) return nullptr0 ; | 172 | 3.06M | | 173 | 3.06M | return InfoIt->second.IDom; | 174 | 3.06M | } |
llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::VPBlockBase, false> >::getIDom(llvm::VPBlockBase*) const Line | Count | Source | 169 | 107 | NodePtr getIDom(NodePtr BB) const { | 170 | 107 | auto InfoIt = NodeToInfo.find(BB); | 171 | 107 | if (InfoIt == NodeToInfo.end()) return nullptr0 ; | 172 | 107 | | 173 | 107 | return InfoIt->second.IDom; | 174 | 107 | } |
llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<clang::CFGBlock, false> >::getIDom(clang::CFGBlock*) const Line | Count | Source | 169 | 58 | NodePtr getIDom(NodePtr BB) const { | 170 | 58 | auto InfoIt = NodeToInfo.find(BB); | 171 | 58 | if (InfoIt == NodeToInfo.end()) return nullptr0 ; | 172 | 58 | | 173 | 58 | return InfoIt->second.IDom; | 174 | 58 | } |
llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<clang::CFGBlock, true> >::getIDom(clang::CFGBlock*) const Line | Count | Source | 169 | 549 | NodePtr getIDom(NodePtr BB) const { | 170 | 549 | auto InfoIt = NodeToInfo.find(BB); | 171 | 549 | if (InfoIt == NodeToInfo.end()) return nullptr0 ; | 172 | 549 | | 173 | 549 | return InfoIt->second.IDom; | 174 | 549 | } |
|
175 | | |
176 | 74.8M | TreeNodePtr getNodeForBlock(NodePtr BB, DomTreeT &DT) { |
177 | 74.8M | if (TreeNodePtr Node = DT.getNode(BB)) return Node74.8M ; |
178 | 1 | |
179 | 1 | // Haven't calculated this node yet? Get or calculate the node for the |
180 | 1 | // immediate dominator. |
181 | 1 | NodePtr IDom = getIDom(BB); |
182 | 1 | |
183 | 1 | assert(IDom || DT.DomTreeNodes[nullptr]); |
184 | 1 | TreeNodePtr IDomNode = getNodeForBlock(IDom, DT); |
185 | 1 | |
186 | 1 | // Add a new tree node for this NodeT, and link it as a child of |
187 | 1 | // IDomNode |
188 | 1 | return (DT.DomTreeNodes[BB] = IDomNode->addChild( |
189 | 1 | llvm::make_unique<DomTreeNodeBase<NodeT>>(BB, IDomNode))) |
190 | 1 | .get(); |
191 | 1 | } llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> >::getNodeForBlock(llvm::MachineBasicBlock*, llvm::DominatorTreeBase<llvm::MachineBasicBlock, false>&) Line | Count | Source | 176 | 9.38M | TreeNodePtr getNodeForBlock(NodePtr BB, DomTreeT &DT) { | 177 | 9.38M | if (TreeNodePtr Node = DT.getNode(BB)) return Node; | 178 | 0 | | 179 | 0 | // Haven't calculated this node yet? Get or calculate the node for the | 180 | 0 | // immediate dominator. | 181 | 0 | NodePtr IDom = getIDom(BB); | 182 | 0 |
| 183 | 0 | assert(IDom || DT.DomTreeNodes[nullptr]); | 184 | 0 | TreeNodePtr IDomNode = getNodeForBlock(IDom, DT); | 185 | 0 |
| 186 | 0 | // Add a new tree node for this NodeT, and link it as a child of | 187 | 0 | // IDomNode | 188 | 0 | return (DT.DomTreeNodes[BB] = IDomNode->addChild( | 189 | 0 | llvm::make_unique<DomTreeNodeBase<NodeT>>(BB, IDomNode))) | 190 | 0 | .get(); | 191 | 0 | } |
llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> >::getNodeForBlock(llvm::MachineBasicBlock*, llvm::DominatorTreeBase<llvm::MachineBasicBlock, true>&) Line | Count | Source | 176 | 8.52M | TreeNodePtr getNodeForBlock(NodePtr BB, DomTreeT &DT) { | 177 | 8.52M | if (TreeNodePtr Node = DT.getNode(BB)) return Node8.52M ; | 178 | 6 | | 179 | 6 | // Haven't calculated this node yet? Get or calculate the node for the | 180 | 6 | // immediate dominator. | 181 | 6 | NodePtr IDom = getIDom(BB); | 182 | 6 | | 183 | 6 | assert(IDom || DT.DomTreeNodes[nullptr]); | 184 | 6 | TreeNodePtr IDomNode = getNodeForBlock(IDom, DT); | 185 | 6 | | 186 | 6 | // Add a new tree node for this NodeT, and link it as a child of | 187 | 6 | // IDomNode | 188 | 6 | return (DT.DomTreeNodes[BB] = IDomNode->addChild( | 189 | 6 | llvm::make_unique<DomTreeNodeBase<NodeT>>(BB, IDomNode))) | 190 | 6 | .get(); | 191 | 6 | } |
llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, false> >::getNodeForBlock(llvm::BasicBlock*, llvm::DominatorTreeBase<llvm::BasicBlock, false>&) Line | Count | Source | 176 | 53.8M | TreeNodePtr getNodeForBlock(NodePtr BB, DomTreeT &DT) { | 177 | 53.8M | if (TreeNodePtr Node = DT.getNode(BB)) return Node; | 178 | 0 | | 179 | 0 | // Haven't calculated this node yet? Get or calculate the node for the | 180 | 0 | // immediate dominator. | 181 | 0 | NodePtr IDom = getIDom(BB); | 182 | 0 |
| 183 | 0 | assert(IDom || DT.DomTreeNodes[nullptr]); | 184 | 0 | TreeNodePtr IDomNode = getNodeForBlock(IDom, DT); | 185 | 0 |
| 186 | 0 | // Add a new tree node for this NodeT, and link it as a child of | 187 | 0 | // IDomNode | 188 | 0 | return (DT.DomTreeNodes[BB] = IDomNode->addChild( | 189 | 0 | llvm::make_unique<DomTreeNodeBase<NodeT>>(BB, IDomNode))) | 190 | 0 | .get(); | 191 | 0 | } |
llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, true> >::getNodeForBlock(llvm::BasicBlock*, llvm::DominatorTreeBase<llvm::BasicBlock, true>&) Line | Count | Source | 176 | 3.06M | TreeNodePtr getNodeForBlock(NodePtr BB, DomTreeT &DT) { | 177 | 3.06M | if (TreeNodePtr Node3.06M = DT.getNode(BB)) return Node; | 178 | 18.4E | | 179 | 18.4E | // Haven't calculated this node yet? Get or calculate the node for the | 180 | 18.4E | // immediate dominator. | 181 | 18.4E | NodePtr IDom = getIDom(BB); | 182 | 18.4E | | 183 | 18.4E | assert(IDom || DT.DomTreeNodes[nullptr]); | 184 | 18.4E | TreeNodePtr IDomNode = getNodeForBlock(IDom, DT); | 185 | 18.4E | | 186 | 18.4E | // Add a new tree node for this NodeT, and link it as a child of | 187 | 18.4E | // IDomNode | 188 | 18.4E | return (DT.DomTreeNodes[BB] = IDomNode->addChild( | 189 | 18.4E | llvm::make_unique<DomTreeNodeBase<NodeT>>(BB, IDomNode))) | 190 | 18.4E | .get(); | 191 | 18.4E | } |
llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::VPBlockBase, false> >::getNodeForBlock(llvm::VPBlockBase*, llvm::DominatorTreeBase<llvm::VPBlockBase, false>&) Line | Count | Source | 176 | 107 | TreeNodePtr getNodeForBlock(NodePtr BB, DomTreeT &DT) { | 177 | 107 | if (TreeNodePtr Node = DT.getNode(BB)) return Node; | 178 | 0 | | 179 | 0 | // Haven't calculated this node yet? Get or calculate the node for the | 180 | 0 | // immediate dominator. | 181 | 0 | NodePtr IDom = getIDom(BB); | 182 | 0 |
| 183 | 0 | assert(IDom || DT.DomTreeNodes[nullptr]); | 184 | 0 | TreeNodePtr IDomNode = getNodeForBlock(IDom, DT); | 185 | 0 |
| 186 | 0 | // Add a new tree node for this NodeT, and link it as a child of | 187 | 0 | // IDomNode | 188 | 0 | return (DT.DomTreeNodes[BB] = IDomNode->addChild( | 189 | 0 | llvm::make_unique<DomTreeNodeBase<NodeT>>(BB, IDomNode))) | 190 | 0 | .get(); | 191 | 0 | } |
llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<clang::CFGBlock, false> >::getNodeForBlock(clang::CFGBlock*, llvm::DominatorTreeBase<clang::CFGBlock, false>&) Line | Count | Source | 176 | 58 | TreeNodePtr getNodeForBlock(NodePtr BB, DomTreeT &DT) { | 177 | 58 | if (TreeNodePtr Node = DT.getNode(BB)) return Node; | 178 | 0 | | 179 | 0 | // Haven't calculated this node yet? Get or calculate the node for the | 180 | 0 | // immediate dominator. | 181 | 0 | NodePtr IDom = getIDom(BB); | 182 | 0 |
| 183 | 0 | assert(IDom || DT.DomTreeNodes[nullptr]); | 184 | 0 | TreeNodePtr IDomNode = getNodeForBlock(IDom, DT); | 185 | 0 |
| 186 | 0 | // Add a new tree node for this NodeT, and link it as a child of | 187 | 0 | // IDomNode | 188 | 0 | return (DT.DomTreeNodes[BB] = IDomNode->addChild( | 189 | 0 | llvm::make_unique<DomTreeNodeBase<NodeT>>(BB, IDomNode))) | 190 | 0 | .get(); | 191 | 0 | } |
llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<clang::CFGBlock, true> >::getNodeForBlock(clang::CFGBlock*, llvm::DominatorTreeBase<clang::CFGBlock, true>&) Line | Count | Source | 176 | 549 | TreeNodePtr getNodeForBlock(NodePtr BB, DomTreeT &DT) { | 177 | 549 | if (TreeNodePtr Node = DT.getNode(BB)) return Node; | 178 | 0 | | 179 | 0 | // Haven't calculated this node yet? Get or calculate the node for the | 180 | 0 | // immediate dominator. | 181 | 0 | NodePtr IDom = getIDom(BB); | 182 | 0 |
| 183 | 0 | assert(IDom || DT.DomTreeNodes[nullptr]); | 184 | 0 | TreeNodePtr IDomNode = getNodeForBlock(IDom, DT); | 185 | 0 |
| 186 | 0 | // Add a new tree node for this NodeT, and link it as a child of | 187 | 0 | // IDomNode | 188 | 0 | return (DT.DomTreeNodes[BB] = IDomNode->addChild( | 189 | 0 | llvm::make_unique<DomTreeNodeBase<NodeT>>(BB, IDomNode))) | 190 | 0 | .get(); | 191 | 0 | } |
|
192 | | |
193 | 91.5M | static bool AlwaysDescend(NodePtr, NodePtr) { return true; } llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> >::AlwaysDescend(llvm::MachineBasicBlock*, llvm::MachineBasicBlock*) Line | Count | Source | 193 | 10.3M | static bool AlwaysDescend(NodePtr, NodePtr) { return true; } |
llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> >::AlwaysDescend(llvm::MachineBasicBlock*, llvm::MachineBasicBlock*) Line | Count | Source | 193 | 16.3M | static bool AlwaysDescend(NodePtr, NodePtr) { return true; } |
llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, false> >::AlwaysDescend(llvm::BasicBlock*, llvm::BasicBlock*) Line | Count | Source | 193 | 59.5M | static bool AlwaysDescend(NodePtr, NodePtr) { return true; } |
llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, true> >::AlwaysDescend(llvm::BasicBlock*, llvm::BasicBlock*) Line | Count | Source | 193 | 5.24M | static bool AlwaysDescend(NodePtr, NodePtr) { return true; } |
llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::VPBlockBase, false> >::AlwaysDescend(llvm::VPBlockBase*, llvm::VPBlockBase*) Line | Count | Source | 193 | 114 | static bool AlwaysDescend(NodePtr, NodePtr) { return true; } |
llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<clang::CFGBlock, false> >::AlwaysDescend(clang::CFGBlock*, clang::CFGBlock*) Line | Count | Source | 193 | 61 | static bool AlwaysDescend(NodePtr, NodePtr) { return true; } |
llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<clang::CFGBlock, true> >::AlwaysDescend(clang::CFGBlock*, clang::CFGBlock*) Line | Count | Source | 193 | 884 | static bool AlwaysDescend(NodePtr, NodePtr) { return true; } |
|
194 | | |
195 | | struct BlockNamePrinter { |
196 | | NodePtr N; |
197 | | |
198 | 0 | BlockNamePrinter(NodePtr Block) : N(Block) {} Unexecuted instantiation: llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> >::BlockNamePrinter::BlockNamePrinter(llvm::MachineBasicBlock*) Unexecuted instantiation: llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> >::BlockNamePrinter::BlockNamePrinter(llvm::MachineBasicBlock*) Unexecuted instantiation: llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, false> >::BlockNamePrinter::BlockNamePrinter(llvm::BasicBlock*) Unexecuted instantiation: llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, true> >::BlockNamePrinter::BlockNamePrinter(llvm::BasicBlock*) |
199 | 0 | BlockNamePrinter(TreeNodePtr TN) : N(TN ? TN->getBlock() : nullptr) {} Unexecuted instantiation: llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> >::BlockNamePrinter::BlockNamePrinter(llvm::DomTreeNodeBase<llvm::MachineBasicBlock>*) Unexecuted instantiation: llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> >::BlockNamePrinter::BlockNamePrinter(llvm::DomTreeNodeBase<llvm::MachineBasicBlock>*) Unexecuted instantiation: llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, false> >::BlockNamePrinter::BlockNamePrinter(llvm::DomTreeNodeBase<llvm::BasicBlock>*) Unexecuted instantiation: llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, true> >::BlockNamePrinter::BlockNamePrinter(llvm::DomTreeNodeBase<llvm::BasicBlock>*) |
200 | | |
201 | 0 | friend raw_ostream &operator<<(raw_ostream &O, const BlockNamePrinter &BP) { |
202 | 0 | if (!BP.N) |
203 | 0 | O << "nullptr"; |
204 | 0 | else |
205 | 0 | BP.N->printAsOperand(O, false); |
206 | 0 |
|
207 | 0 | return O; |
208 | 0 | } Unexecuted instantiation: llvm::DomTreeBuilder::operator<<(llvm::raw_ostream&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> >::BlockNamePrinter const&) Unexecuted instantiation: llvm::DomTreeBuilder::operator<<(llvm::raw_ostream&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> >::BlockNamePrinter const&) Unexecuted instantiation: llvm::DomTreeBuilder::operator<<(llvm::raw_ostream&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, false> >::BlockNamePrinter const&) Unexecuted instantiation: llvm::DomTreeBuilder::operator<<(llvm::raw_ostream&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, true> >::BlockNamePrinter const&) |
209 | | }; |
210 | | |
211 | | // Custom DFS implementation which can skip nodes based on a provided |
212 | | // predicate. It also collects ReverseChildren so that we don't have to spend |
213 | | // time getting predecessors in SemiNCA. |
214 | | // |
215 | | // If IsReverse is set to true, the DFS walk will be performed backwards |
216 | | // relative to IsPostDom -- using reverse edges for dominators and forward |
217 | | // edges for postdominators. |
218 | | template <bool IsReverse = false, typename DescendCondition> |
219 | | unsigned runDFS(NodePtr V, unsigned LastNum, DescendCondition Condition, |
220 | 19.0M | unsigned AttachToNum) { |
221 | 19.0M | assert(V); |
222 | 19.0M | SmallVector<NodePtr, 64> WorkList = {V}; |
223 | 19.0M | if (NodeToInfo.count(V) != 0) NodeToInfo[V].Parent = AttachToNum0 ; |
224 | 19.0M | |
225 | 143M | while (!WorkList.empty()) { |
226 | 124M | const NodePtr BB = WorkList.pop_back_val(); |
227 | 124M | auto &BBInfo = NodeToInfo[BB]; |
228 | 124M | |
229 | 124M | // Visited nodes always have positive DFS numbers. |
230 | 124M | if (BBInfo.DFSNum != 0) continue11.1M ; |
231 | 113M | BBInfo.DFSNum = BBInfo.Semi = ++LastNum; |
232 | 113M | BBInfo.Label = BB; |
233 | 113M | NumToNode.push_back(BB); |
234 | 113M | |
235 | 113M | constexpr bool Direction = IsReverse != IsPostDom; // XOR. |
236 | 113M | for (const NodePtr Succ : |
237 | 143M | ChildrenGetter<Direction>::Get(BB, BatchUpdates)) { |
238 | 143M | const auto SIT = NodeToInfo.find(Succ); |
239 | 143M | // Don't visit nodes more than once but remember to collect |
240 | 143M | // ReverseChildren. |
241 | 143M | if (SIT != NodeToInfo.end() && SIT->second.DFSNum != 048.4M ) { |
242 | 37.2M | if (Succ != BB) SIT->second.ReverseChildren.push_back(BB)32.6M ; |
243 | 37.2M | continue; |
244 | 37.2M | } |
245 | 106M | |
246 | 106M | if (!Condition(BB, Succ)) continue778k ; |
247 | 105M | |
248 | 105M | // It's fine to add Succ to the map, because we know that it will be |
249 | 105M | // visited later. |
250 | 105M | auto &SuccInfo = NodeToInfo[Succ]; |
251 | 105M | WorkList.push_back(Succ); |
252 | 105M | SuccInfo.Parent = LastNum; |
253 | 105M | SuccInfo.ReverseChildren.push_back(BB); |
254 | 105M | } |
255 | 113M | } |
256 | 19.0M | |
257 | 19.0M | return LastNum; |
258 | 19.0M | } unsigned int llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> >::runDFS<false, bool (*)(llvm::MachineBasicBlock*, llvm::MachineBasicBlock*)>(llvm::MachineBasicBlock*, unsigned int, bool (*)(llvm::MachineBasicBlock*, llvm::MachineBasicBlock*), unsigned int) Line | Count | Source | 220 | 2.61M | unsigned AttachToNum) { | 221 | 2.61M | assert(V); | 222 | 2.61M | SmallVector<NodePtr, 64> WorkList = {V}; | 223 | 2.61M | if (NodeToInfo.count(V) != 0) NodeToInfo[V].Parent = AttachToNum0 ; | 224 | 2.61M | | 225 | 15.6M | while (!WorkList.empty()) { | 226 | 13.0M | const NodePtr BB = WorkList.pop_back_val(); | 227 | 13.0M | auto &BBInfo = NodeToInfo[BB]; | 228 | 13.0M | | 229 | 13.0M | // Visited nodes always have positive DFS numbers. | 230 | 13.0M | if (BBInfo.DFSNum != 0) continue1.00M ; | 231 | 12.0M | BBInfo.DFSNum = BBInfo.Semi = ++LastNum; | 232 | 12.0M | BBInfo.Label = BB; | 233 | 12.0M | NumToNode.push_back(BB); | 234 | 12.0M | | 235 | 12.0M | constexpr bool Direction = IsReverse != IsPostDom; // XOR. | 236 | 12.0M | for (const NodePtr Succ : | 237 | 14.2M | ChildrenGetter<Direction>::Get(BB, BatchUpdates)) { | 238 | 14.2M | const auto SIT = NodeToInfo.find(Succ); | 239 | 14.2M | // Don't visit nodes more than once but remember to collect | 240 | 14.2M | // ReverseChildren. | 241 | 14.2M | if (SIT != NodeToInfo.end() && SIT->second.DFSNum != 04.88M ) { | 242 | 3.88M | if (Succ != BB) SIT->second.ReverseChildren.push_back(BB)3.38M ; | 243 | 3.88M | continue; | 244 | 3.88M | } | 245 | 10.3M | | 246 | 10.3M | if (!Condition(BB, Succ)) continue0 ; | 247 | 10.3M | | 248 | 10.3M | // It's fine to add Succ to the map, because we know that it will be | 249 | 10.3M | // visited later. | 250 | 10.3M | auto &SuccInfo = NodeToInfo[Succ]; | 251 | 10.3M | WorkList.push_back(Succ); | 252 | 10.3M | SuccInfo.Parent = LastNum; | 253 | 10.3M | SuccInfo.ReverseChildren.push_back(BB); | 254 | 10.3M | } | 255 | 12.0M | } | 256 | 2.61M | | 257 | 2.61M | return LastNum; | 258 | 2.61M | } |
Unexecuted instantiation: unsigned int llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> >::runDFS<true, bool (*)(llvm::MachineBasicBlock*, llvm::MachineBasicBlock*)>(llvm::MachineBasicBlock*, unsigned int, bool (*)(llvm::MachineBasicBlock*, llvm::MachineBasicBlock*), unsigned int) Unexecuted instantiation: unsigned int llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> >::runDFS<false, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> >::ComputeUnreachableDominators(llvm::DominatorTreeBase<llvm::MachineBasicBlock, false>&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> >::BatchUpdateInfo*, llvm::MachineBasicBlock*, llvm::DomTreeNodeBase<llvm::MachineBasicBlock>*, llvm::SmallVectorImpl<std::__1::pair<llvm::MachineBasicBlock*, llvm::DomTreeNodeBase<llvm::MachineBasicBlock>*> >&)::'lambda'(llvm::MachineBasicBlock*, llvm::MachineBasicBlock*)>(llvm::MachineBasicBlock*, unsigned int, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> >::ComputeUnreachableDominators(llvm::DominatorTreeBase<llvm::MachineBasicBlock, false>&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> >::BatchUpdateInfo*, llvm::MachineBasicBlock*, llvm::DomTreeNodeBase<llvm::MachineBasicBlock>*, llvm::SmallVectorImpl<std::__1::pair<llvm::MachineBasicBlock*, llvm::DomTreeNodeBase<llvm::MachineBasicBlock>*> >&)::'lambda'(llvm::MachineBasicBlock*, llvm::MachineBasicBlock*), unsigned int) Unexecuted instantiation: unsigned int llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> >::runDFS<false, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> >::DeleteReachable(llvm::DominatorTreeBase<llvm::MachineBasicBlock, false>&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> >::BatchUpdateInfo*, llvm::DomTreeNodeBase<llvm::MachineBasicBlock>*, llvm::DomTreeNodeBase<llvm::MachineBasicBlock>*)::'lambda'(llvm::MachineBasicBlock*, llvm::MachineBasicBlock*)>(llvm::MachineBasicBlock*, unsigned int, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> >::DeleteReachable(llvm::DominatorTreeBase<llvm::MachineBasicBlock, false>&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> >::BatchUpdateInfo*, llvm::DomTreeNodeBase<llvm::MachineBasicBlock>*, llvm::DomTreeNodeBase<llvm::MachineBasicBlock>*)::'lambda'(llvm::MachineBasicBlock*, llvm::MachineBasicBlock*), unsigned int) Unexecuted instantiation: unsigned int llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> >::runDFS<false, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> >::DeleteUnreachable(llvm::DominatorTreeBase<llvm::MachineBasicBlock, false>&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> >::BatchUpdateInfo*, llvm::DomTreeNodeBase<llvm::MachineBasicBlock>*)::'lambda'(llvm::MachineBasicBlock*, llvm::MachineBasicBlock*)>(llvm::MachineBasicBlock*, unsigned int, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> >::DeleteUnreachable(llvm::DominatorTreeBase<llvm::MachineBasicBlock, false>&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> >::BatchUpdateInfo*, llvm::DomTreeNodeBase<llvm::MachineBasicBlock>*)::'lambda'(llvm::MachineBasicBlock*, llvm::MachineBasicBlock*), unsigned int) Unexecuted instantiation: unsigned int llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> >::runDFS<false, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> >::DeleteUnreachable(llvm::DominatorTreeBase<llvm::MachineBasicBlock, false>&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> >::BatchUpdateInfo*, llvm::DomTreeNodeBase<llvm::MachineBasicBlock>*)::'lambda0'(llvm::MachineBasicBlock*, llvm::MachineBasicBlock*)>(llvm::MachineBasicBlock*, unsigned int, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> >::DeleteUnreachable(llvm::DominatorTreeBase<llvm::MachineBasicBlock, false>&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> >::BatchUpdateInfo*, llvm::DomTreeNodeBase<llvm::MachineBasicBlock>*)::'lambda0'(llvm::MachineBasicBlock*, llvm::MachineBasicBlock*), unsigned int) Unexecuted instantiation: unsigned int llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> >::runDFS<false, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> >::verifyParentProperty(llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> const&)::'lambda'(llvm::MachineBasicBlock*, llvm::MachineBasicBlock*)>(llvm::MachineBasicBlock*, unsigned int, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> >::verifyParentProperty(llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> const&)::'lambda'(llvm::MachineBasicBlock*, llvm::MachineBasicBlock*), unsigned int) Unexecuted instantiation: unsigned int llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> >::runDFS<false, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> >::verifySiblingProperty(llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> const&)::'lambda'(llvm::MachineBasicBlock*, llvm::MachineBasicBlock*)>(llvm::MachineBasicBlock*, unsigned int, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> >::verifySiblingProperty(llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> const&)::'lambda'(llvm::MachineBasicBlock*, llvm::MachineBasicBlock*), unsigned int) unsigned int llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> >::runDFS<false, bool (*)(llvm::MachineBasicBlock*, llvm::MachineBasicBlock*)>(llvm::MachineBasicBlock*, unsigned int, bool (*)(llvm::MachineBasicBlock*, llvm::MachineBasicBlock*), unsigned int) Line | Count | Source | 220 | 3.85M | unsigned AttachToNum) { | 221 | 3.85M | assert(V); | 222 | 3.85M | SmallVector<NodePtr, 64> WorkList = {V}; | 223 | 3.85M | if (NodeToInfo.count(V) != 0) NodeToInfo[V].Parent = AttachToNum0 ; | 224 | 3.85M | | 225 | 24.1M | while (!WorkList.empty()) { | 226 | 20.2M | const NodePtr BB = WorkList.pop_back_val(); | 227 | 20.2M | auto &BBInfo = NodeToInfo[BB]; | 228 | 20.2M | | 229 | 20.2M | // Visited nodes always have positive DFS numbers. | 230 | 20.2M | if (BBInfo.DFSNum != 0) continue3.19M ; | 231 | 17.0M | BBInfo.DFSNum = BBInfo.Semi = ++LastNum; | 232 | 17.0M | BBInfo.Label = BB; | 233 | 17.0M | NumToNode.push_back(BB); | 234 | 17.0M | | 235 | 17.0M | constexpr bool Direction = IsReverse != IsPostDom; // XOR. | 236 | 17.0M | for (const NodePtr Succ : | 237 | 21.2M | ChildrenGetter<Direction>::Get(BB, BatchUpdates)) { | 238 | 21.2M | const auto SIT = NodeToInfo.find(Succ); | 239 | 21.2M | // Don't visit nodes more than once but remember to collect | 240 | 21.2M | // ReverseChildren. | 241 | 21.2M | if (SIT != NodeToInfo.end() && SIT->second.DFSNum != 08.08M ) { | 242 | 4.88M | if (Succ != BB) SIT->second.ReverseChildren.push_back(BB)4.15M ; | 243 | 4.88M | continue; | 244 | 4.88M | } | 245 | 16.3M | | 246 | 16.3M | if (!Condition(BB, Succ)) continue0 ; | 247 | 16.3M | | 248 | 16.3M | // It's fine to add Succ to the map, because we know that it will be | 249 | 16.3M | // visited later. | 250 | 16.3M | auto &SuccInfo = NodeToInfo[Succ]; | 251 | 16.3M | WorkList.push_back(Succ); | 252 | 16.3M | SuccInfo.Parent = LastNum; | 253 | 16.3M | SuccInfo.ReverseChildren.push_back(BB); | 254 | 16.3M | } | 255 | 17.0M | } | 256 | 3.85M | | 257 | 3.85M | return LastNum; | 258 | 3.85M | } |
unsigned int llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> >::runDFS<true, bool (*)(llvm::MachineBasicBlock*, llvm::MachineBasicBlock*)>(llvm::MachineBasicBlock*, unsigned int, bool (*)(llvm::MachineBasicBlock*, llvm::MachineBasicBlock*), unsigned int) Line | Count | Source | 220 | 2.77k | unsigned AttachToNum) { | 221 | 2.77k | assert(V); | 222 | 2.77k | SmallVector<NodePtr, 64> WorkList = {V}; | 223 | 2.77k | if (NodeToInfo.count(V) != 0) NodeToInfo[V].Parent = AttachToNum0 ; | 224 | 2.77k | | 225 | 11.6k | while (!WorkList.empty()) { | 226 | 8.91k | const NodePtr BB = WorkList.pop_back_val(); | 227 | 8.91k | auto &BBInfo = NodeToInfo[BB]; | 228 | 8.91k | | 229 | 8.91k | // Visited nodes always have positive DFS numbers. | 230 | 8.91k | if (BBInfo.DFSNum != 0) continue1.50k ; | 231 | 7.41k | BBInfo.DFSNum = BBInfo.Semi = ++LastNum; | 232 | 7.41k | BBInfo.Label = BB; | 233 | 7.41k | NumToNode.push_back(BB); | 234 | 7.41k | | 235 | 7.41k | constexpr bool Direction = IsReverse != IsPostDom; // XOR. | 236 | 7.41k | for (const NodePtr Succ : | 237 | 12.2k | ChildrenGetter<Direction>::Get(BB, BatchUpdates)) { | 238 | 12.2k | const auto SIT = NodeToInfo.find(Succ); | 239 | 12.2k | // Don't visit nodes more than once but remember to collect | 240 | 12.2k | // ReverseChildren. | 241 | 12.2k | if (SIT != NodeToInfo.end() && SIT->second.DFSNum != 07.60k ) { | 242 | 6.10k | if (Succ != BB) SIT->second.ReverseChildren.push_back(BB)3.45k ; | 243 | 6.10k | continue; | 244 | 6.10k | } | 245 | 6.13k | | 246 | 6.13k | if (!Condition(BB, Succ)) continue0 ; | 247 | 6.13k | | 248 | 6.13k | // It's fine to add Succ to the map, because we know that it will be | 249 | 6.13k | // visited later. | 250 | 6.13k | auto &SuccInfo = NodeToInfo[Succ]; | 251 | 6.13k | WorkList.push_back(Succ); | 252 | 6.13k | SuccInfo.Parent = LastNum; | 253 | 6.13k | SuccInfo.ReverseChildren.push_back(BB); | 254 | 6.13k | } | 255 | 7.41k | } | 256 | 2.77k | | 257 | 2.77k | return LastNum; | 258 | 2.77k | } |
Unexecuted instantiation: unsigned int llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> >::runDFS<false, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> >::ComputeUnreachableDominators(llvm::DominatorTreeBase<llvm::MachineBasicBlock, true>&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> >::BatchUpdateInfo*, llvm::MachineBasicBlock*, llvm::DomTreeNodeBase<llvm::MachineBasicBlock>*, llvm::SmallVectorImpl<std::__1::pair<llvm::MachineBasicBlock*, llvm::DomTreeNodeBase<llvm::MachineBasicBlock>*> >&)::'lambda'(llvm::MachineBasicBlock*, llvm::MachineBasicBlock*)>(llvm::MachineBasicBlock*, unsigned int, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> >::ComputeUnreachableDominators(llvm::DominatorTreeBase<llvm::MachineBasicBlock, true>&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> >::BatchUpdateInfo*, llvm::MachineBasicBlock*, llvm::DomTreeNodeBase<llvm::MachineBasicBlock>*, llvm::SmallVectorImpl<std::__1::pair<llvm::MachineBasicBlock*, llvm::DomTreeNodeBase<llvm::MachineBasicBlock>*> >&)::'lambda'(llvm::MachineBasicBlock*, llvm::MachineBasicBlock*), unsigned int) Unexecuted instantiation: unsigned int llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> >::runDFS<false, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> >::DeleteReachable(llvm::DominatorTreeBase<llvm::MachineBasicBlock, true>&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> >::BatchUpdateInfo*, llvm::DomTreeNodeBase<llvm::MachineBasicBlock>*, llvm::DomTreeNodeBase<llvm::MachineBasicBlock>*)::'lambda'(llvm::MachineBasicBlock*, llvm::MachineBasicBlock*)>(llvm::MachineBasicBlock*, unsigned int, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> >::DeleteReachable(llvm::DominatorTreeBase<llvm::MachineBasicBlock, true>&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> >::BatchUpdateInfo*, llvm::DomTreeNodeBase<llvm::MachineBasicBlock>*, llvm::DomTreeNodeBase<llvm::MachineBasicBlock>*)::'lambda'(llvm::MachineBasicBlock*, llvm::MachineBasicBlock*), unsigned int) Unexecuted instantiation: unsigned int llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> >::runDFS<false, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> >::verifyParentProperty(llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> const&)::'lambda'(llvm::MachineBasicBlock*, llvm::MachineBasicBlock*)>(llvm::MachineBasicBlock*, unsigned int, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> >::verifyParentProperty(llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> const&)::'lambda'(llvm::MachineBasicBlock*, llvm::MachineBasicBlock*), unsigned int) Unexecuted instantiation: unsigned int llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> >::runDFS<false, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> >::verifySiblingProperty(llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> const&)::'lambda'(llvm::MachineBasicBlock*, llvm::MachineBasicBlock*)>(llvm::MachineBasicBlock*, unsigned int, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> >::verifySiblingProperty(llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> const&)::'lambda'(llvm::MachineBasicBlock*, llvm::MachineBasicBlock*), unsigned int) Unexecuted instantiation: unsigned int llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> >::runDFS<false, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> >::DeleteUnreachable(llvm::DominatorTreeBase<llvm::MachineBasicBlock, true>&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> >::BatchUpdateInfo*, llvm::DomTreeNodeBase<llvm::MachineBasicBlock>*)::'lambda'(llvm::MachineBasicBlock*, llvm::MachineBasicBlock*)>(llvm::MachineBasicBlock*, unsigned int, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> >::DeleteUnreachable(llvm::DominatorTreeBase<llvm::MachineBasicBlock, true>&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> >::BatchUpdateInfo*, llvm::DomTreeNodeBase<llvm::MachineBasicBlock>*)::'lambda'(llvm::MachineBasicBlock*, llvm::MachineBasicBlock*), unsigned int) Unexecuted instantiation: unsigned int llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> >::runDFS<false, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> >::DeleteUnreachable(llvm::DominatorTreeBase<llvm::MachineBasicBlock, true>&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> >::BatchUpdateInfo*, llvm::DomTreeNodeBase<llvm::MachineBasicBlock>*)::'lambda0'(llvm::MachineBasicBlock*, llvm::MachineBasicBlock*)>(llvm::MachineBasicBlock*, unsigned int, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> >::DeleteUnreachable(llvm::DominatorTreeBase<llvm::MachineBasicBlock, true>&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> >::BatchUpdateInfo*, llvm::DomTreeNodeBase<llvm::MachineBasicBlock>*)::'lambda0'(llvm::MachineBasicBlock*, llvm::MachineBasicBlock*), unsigned int) unsigned int llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, false> >::runDFS<false, bool (*)(llvm::BasicBlock*, llvm::BasicBlock*)>(llvm::BasicBlock*, unsigned int, bool (*)(llvm::BasicBlock*, llvm::BasicBlock*), unsigned int) Line | Count | Source | 220 | 10.3M | unsigned AttachToNum) { | 221 | 10.3M | assert(V); | 222 | 10.3M | SmallVector<NodePtr, 64> WorkList = {V}; | 223 | 10.3M | if (NodeToInfo.count(V) != 0) NodeToInfo[V].Parent = AttachToNum0 ; | 224 | 10.3M | | 225 | 80.2M | while (!WorkList.empty()) { | 226 | 69.8M | const NodePtr BB = WorkList.pop_back_val(); | 227 | 69.8M | auto &BBInfo = NodeToInfo[BB]; | 228 | 69.8M | | 229 | 69.8M | // Visited nodes always have positive DFS numbers. | 230 | 69.8M | if (BBInfo.DFSNum != 0) continue5.85M ; | 231 | 64.0M | BBInfo.DFSNum = BBInfo.Semi = ++LastNum; | 232 | 64.0M | BBInfo.Label = BB; | 233 | 64.0M | NumToNode.push_back(BB); | 234 | 64.0M | | 235 | 64.0M | constexpr bool Direction = IsReverse != IsPostDom; // XOR. | 236 | 64.0M | for (const NodePtr Succ : | 237 | 83.5M | ChildrenGetter<Direction>::Get(BB, BatchUpdates)) { | 238 | 83.5M | const auto SIT = NodeToInfo.find(Succ); | 239 | 83.5M | // Don't visit nodes more than once but remember to collect | 240 | 83.5M | // ReverseChildren. | 241 | 83.5M | if (SIT != NodeToInfo.end() && SIT->second.DFSNum != 029.9M ) { | 242 | 24.0M | if (Succ != BB) SIT->second.ReverseChildren.push_back(BB)21.2M ; | 243 | 24.0M | continue; | 244 | 24.0M | } | 245 | 59.5M | | 246 | 59.5M | if (!Condition(BB, Succ)) continue0 ; | 247 | 59.5M | | 248 | 59.5M | // It's fine to add Succ to the map, because we know that it will be | 249 | 59.5M | // visited later. | 250 | 59.5M | auto &SuccInfo = NodeToInfo[Succ]; | 251 | 59.5M | WorkList.push_back(Succ); | 252 | 59.5M | SuccInfo.Parent = LastNum; | 253 | 59.5M | SuccInfo.ReverseChildren.push_back(BB); | 254 | 59.5M | } | 255 | 64.0M | } | 256 | 10.3M | | 257 | 10.3M | return LastNum; | 258 | 10.3M | } |
unsigned int llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, true> >::runDFS<false, bool (*)(llvm::BasicBlock*, llvm::BasicBlock*)>(llvm::BasicBlock*, unsigned int, bool (*)(llvm::BasicBlock*, llvm::BasicBlock*), unsigned int) Line | Count | Source | 220 | 1.32M | unsigned AttachToNum) { | 221 | 1.32M | assert(V); | 222 | 1.32M | SmallVector<NodePtr, 64> WorkList = {V}; | 223 | 1.32M | if (NodeToInfo.count(V) != 0) NodeToInfo[V].Parent = AttachToNum0 ; | 224 | 1.32M | | 225 | 7.89M | while (!WorkList.empty()) { | 226 | 6.57M | const NodePtr BB = WorkList.pop_back_val(); | 227 | 6.57M | auto &BBInfo = NodeToInfo[BB]; | 228 | 6.57M | | 229 | 6.57M | // Visited nodes always have positive DFS numbers. | 230 | 6.57M | if (BBInfo.DFSNum != 0) continue440k ; | 231 | 6.13M | BBInfo.DFSNum = BBInfo.Semi = ++LastNum; | 232 | 6.13M | BBInfo.Label = BB; | 233 | 6.13M | NumToNode.push_back(BB); | 234 | 6.13M | | 235 | 6.13M | constexpr bool Direction = IsReverse != IsPostDom; // XOR. | 236 | 6.13M | for (const NodePtr Succ : | 237 | 7.56M | ChildrenGetter<Direction>::Get(BB, BatchUpdates)) { | 238 | 7.56M | const auto SIT = NodeToInfo.find(Succ); | 239 | 7.56M | // Don't visit nodes more than once but remember to collect | 240 | 7.56M | // ReverseChildren. | 241 | 7.56M | if (SIT != NodeToInfo.end() && SIT->second.DFSNum != 02.75M ) { | 242 | 2.31M | if (Succ != BB) SIT->second.ReverseChildren.push_back(BB)2.10M ; | 243 | 2.31M | continue; | 244 | 2.31M | } | 245 | 5.24M | | 246 | 5.24M | if (!Condition(BB, Succ)) continue0 ; | 247 | 5.24M | | 248 | 5.24M | // It's fine to add Succ to the map, because we know that it will be | 249 | 5.24M | // visited later. | 250 | 5.24M | auto &SuccInfo = NodeToInfo[Succ]; | 251 | 5.24M | WorkList.push_back(Succ); | 252 | 5.24M | SuccInfo.Parent = LastNum; | 253 | 5.24M | SuccInfo.ReverseChildren.push_back(BB); | 254 | 5.24M | } | 255 | 6.13M | } | 256 | 1.32M | | 257 | 1.32M | return LastNum; | 258 | 1.32M | } |
unsigned int llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, true> >::runDFS<true, bool (*)(llvm::BasicBlock*, llvm::BasicBlock*)>(llvm::BasicBlock*, unsigned int, bool (*)(llvm::BasicBlock*, llvm::BasicBlock*), unsigned int) Line | Count | Source | 220 | 1.21k | unsigned AttachToNum) { | 221 | 1.21k | assert(V); | 222 | 1.21k | SmallVector<NodePtr, 64> WorkList = {V}; | 223 | 1.21k | if (NodeToInfo.count(V) != 0) NodeToInfo[V].Parent = AttachToNum0 ; | 224 | 1.21k | | 225 | 4.15k | while (!WorkList.empty()) { | 226 | 2.94k | const NodePtr BB = WorkList.pop_back_val(); | 227 | 2.94k | auto &BBInfo = NodeToInfo[BB]; | 228 | 2.94k | | 229 | 2.94k | // Visited nodes always have positive DFS numbers. | 230 | 2.94k | if (BBInfo.DFSNum != 0) continue105 ; | 231 | 2.83k | BBInfo.DFSNum = BBInfo.Semi = ++LastNum; | 232 | 2.83k | BBInfo.Label = BB; | 233 | 2.83k | NumToNode.push_back(BB); | 234 | 2.83k | | 235 | 2.83k | constexpr bool Direction = IsReverse != IsPostDom; // XOR. | 236 | 2.83k | for (const NodePtr Succ : | 237 | 3.20k | ChildrenGetter<Direction>::Get(BB, BatchUpdates)) { | 238 | 3.20k | const auto SIT = NodeToInfo.find(Succ); | 239 | 3.20k | // Don't visit nodes more than once but remember to collect | 240 | 3.20k | // ReverseChildren. | 241 | 3.20k | if (SIT != NodeToInfo.end() && SIT->second.DFSNum != 01.58k ) { | 242 | 1.47k | if (Succ != BB) SIT->second.ReverseChildren.push_back(BB)814 ; | 243 | 1.47k | continue; | 244 | 1.47k | } | 245 | 1.72k | | 246 | 1.72k | if (!Condition(BB, Succ)) continue0 ; | 247 | 1.72k | | 248 | 1.72k | // It's fine to add Succ to the map, because we know that it will be | 249 | 1.72k | // visited later. | 250 | 1.72k | auto &SuccInfo = NodeToInfo[Succ]; | 251 | 1.72k | WorkList.push_back(Succ); | 252 | 1.72k | SuccInfo.Parent = LastNum; | 253 | 1.72k | SuccInfo.ReverseChildren.push_back(BB); | 254 | 1.72k | } | 255 | 2.83k | } | 256 | 1.21k | | 257 | 1.21k | return LastNum; | 258 | 1.21k | } |
unsigned int llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, false> >::runDFS<false, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, false> >::ComputeUnreachableDominators(llvm::DominatorTreeBase<llvm::BasicBlock, false>&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, false> >::BatchUpdateInfo*, llvm::BasicBlock*, llvm::DomTreeNodeBase<llvm::BasicBlock>*, llvm::SmallVectorImpl<std::__1::pair<llvm::BasicBlock*, llvm::DomTreeNodeBase<llvm::BasicBlock>*> >&)::'lambda'(llvm::BasicBlock*, llvm::BasicBlock*)>(llvm::BasicBlock*, unsigned int, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, false> >::ComputeUnreachableDominators(llvm::DominatorTreeBase<llvm::BasicBlock, false>&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, false> >::BatchUpdateInfo*, llvm::BasicBlock*, llvm::DomTreeNodeBase<llvm::BasicBlock>*, llvm::SmallVectorImpl<std::__1::pair<llvm::BasicBlock*, llvm::DomTreeNodeBase<llvm::BasicBlock>*> >&)::'lambda'(llvm::BasicBlock*, llvm::BasicBlock*), unsigned int) Line | Count | Source | 220 | 114k | unsigned AttachToNum) { | 221 | 114k | assert(V); | 222 | 114k | SmallVector<NodePtr, 64> WorkList = {V}; | 223 | 114k | if (NodeToInfo.count(V) != 0) NodeToInfo[V].Parent = AttachToNum0 ; | 224 | 114k | | 225 | 354k | while (!WorkList.empty()) { | 226 | 239k | const NodePtr BB = WorkList.pop_back_val(); | 227 | 239k | auto &BBInfo = NodeToInfo[BB]; | 228 | 239k | | 229 | 239k | // Visited nodes always have positive DFS numbers. | 230 | 239k | if (BBInfo.DFSNum != 0) continue11.5k ; | 231 | 228k | BBInfo.DFSNum = BBInfo.Semi = ++LastNum; | 232 | 228k | BBInfo.Label = BB; | 233 | 228k | NumToNode.push_back(BB); | 234 | 228k | | 235 | 228k | constexpr bool Direction = IsReverse != IsPostDom; // XOR. | 236 | 228k | for (const NodePtr Succ : | 237 | 228k | ChildrenGetter<Direction>::Get(BB, BatchUpdates)) { | 238 | 189k | const auto SIT = NodeToInfo.find(Succ); | 239 | 189k | // Don't visit nodes more than once but remember to collect | 240 | 189k | // ReverseChildren. | 241 | 189k | if (SIT != NodeToInfo.end() && SIT->second.DFSNum != 049.8k ) { | 242 | 38.2k | if (Succ != BB) SIT->second.ReverseChildren.push_back(BB)33.5k ; | 243 | 38.2k | continue; | 244 | 38.2k | } | 245 | 150k | | 246 | 150k | if (!Condition(BB, Succ)) continue25.4k ; | 247 | 125k | | 248 | 125k | // It's fine to add Succ to the map, because we know that it will be | 249 | 125k | // visited later. | 250 | 125k | auto &SuccInfo = NodeToInfo[Succ]; | 251 | 125k | WorkList.push_back(Succ); | 252 | 125k | SuccInfo.Parent = LastNum; | 253 | 125k | SuccInfo.ReverseChildren.push_back(BB); | 254 | 125k | } | 255 | 228k | } | 256 | 114k | | 257 | 114k | return LastNum; | 258 | 114k | } |
unsigned int llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, true> >::runDFS<false, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, true> >::ComputeUnreachableDominators(llvm::DominatorTreeBase<llvm::BasicBlock, true>&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, true> >::BatchUpdateInfo*, llvm::BasicBlock*, llvm::DomTreeNodeBase<llvm::BasicBlock>*, llvm::SmallVectorImpl<std::__1::pair<llvm::BasicBlock*, llvm::DomTreeNodeBase<llvm::BasicBlock>*> >&)::'lambda'(llvm::BasicBlock*, llvm::BasicBlock*)>(llvm::BasicBlock*, unsigned int, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, true> >::ComputeUnreachableDominators(llvm::DominatorTreeBase<llvm::BasicBlock, true>&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, true> >::BatchUpdateInfo*, llvm::BasicBlock*, llvm::DomTreeNodeBase<llvm::BasicBlock>*, llvm::SmallVectorImpl<std::__1::pair<llvm::BasicBlock*, llvm::DomTreeNodeBase<llvm::BasicBlock>*> >&)::'lambda'(llvm::BasicBlock*, llvm::BasicBlock*), unsigned int) Line | Count | Source | 220 | 3 | unsigned AttachToNum) { | 221 | 3 | assert(V); | 222 | 3 | SmallVector<NodePtr, 64> WorkList = {V}; | 223 | 3 | if (NodeToInfo.count(V) != 0) NodeToInfo[V].Parent = AttachToNum0 ; | 224 | 3 | | 225 | 6 | while (!WorkList.empty()) { | 226 | 3 | const NodePtr BB = WorkList.pop_back_val(); | 227 | 3 | auto &BBInfo = NodeToInfo[BB]; | 228 | 3 | | 229 | 3 | // Visited nodes always have positive DFS numbers. | 230 | 3 | if (BBInfo.DFSNum != 0) continue0 ; | 231 | 3 | BBInfo.DFSNum = BBInfo.Semi = ++LastNum; | 232 | 3 | BBInfo.Label = BB; | 233 | 3 | NumToNode.push_back(BB); | 234 | 3 | | 235 | 3 | constexpr bool Direction = IsReverse != IsPostDom; // XOR. | 236 | 3 | for (const NodePtr Succ : | 237 | 3 | ChildrenGetter<Direction>::Get(BB, BatchUpdates)) { | 238 | 0 | const auto SIT = NodeToInfo.find(Succ); | 239 | 0 | // Don't visit nodes more than once but remember to collect | 240 | 0 | // ReverseChildren. | 241 | 0 | if (SIT != NodeToInfo.end() && SIT->second.DFSNum != 0) { | 242 | 0 | if (Succ != BB) SIT->second.ReverseChildren.push_back(BB); | 243 | 0 | continue; | 244 | 0 | } | 245 | 0 |
| 246 | 0 | if (!Condition(BB, Succ)) continue; | 247 | 0 | | 248 | 0 | // It's fine to add Succ to the map, because we know that it will be | 249 | 0 | // visited later. | 250 | 0 | auto &SuccInfo = NodeToInfo[Succ]; | 251 | 0 | WorkList.push_back(Succ); | 252 | 0 | SuccInfo.Parent = LastNum; | 253 | 0 | SuccInfo.ReverseChildren.push_back(BB); | 254 | 0 | } | 255 | 3 | } | 256 | 3 | | 257 | 3 | return LastNum; | 258 | 3 | } |
unsigned int llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, false> >::runDFS<false, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, false> >::DeleteReachable(llvm::DominatorTreeBase<llvm::BasicBlock, false>&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, false> >::BatchUpdateInfo*, llvm::DomTreeNodeBase<llvm::BasicBlock>*, llvm::DomTreeNodeBase<llvm::BasicBlock>*)::'lambda'(llvm::BasicBlock*, llvm::BasicBlock*)>(llvm::BasicBlock*, unsigned int, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, false> >::DeleteReachable(llvm::DominatorTreeBase<llvm::BasicBlock, false>&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, false> >::BatchUpdateInfo*, llvm::DomTreeNodeBase<llvm::BasicBlock>*, llvm::DomTreeNodeBase<llvm::BasicBlock>*)::'lambda'(llvm::BasicBlock*, llvm::BasicBlock*), unsigned int) Line | Count | Source | 220 | 399k | unsigned AttachToNum) { | 221 | 399k | assert(V); | 222 | 399k | SmallVector<NodePtr, 64> WorkList = {V}; | 223 | 399k | if (NodeToInfo.count(V) != 0) NodeToInfo[V].Parent = AttachToNum0 ; | 224 | 399k | | 225 | 14.3M | while (!WorkList.empty()) { | 226 | 13.9M | const NodePtr BB = WorkList.pop_back_val(); | 227 | 13.9M | auto &BBInfo = NodeToInfo[BB]; | 228 | 13.9M | | 229 | 13.9M | // Visited nodes always have positive DFS numbers. | 230 | 13.9M | if (BBInfo.DFSNum != 0) continue651k ; | 231 | 13.2M | BBInfo.DFSNum = BBInfo.Semi = ++LastNum; | 232 | 13.2M | BBInfo.Label = BB; | 233 | 13.2M | NumToNode.push_back(BB); | 234 | 13.2M | | 235 | 13.2M | constexpr bool Direction = IsReverse != IsPostDom; // XOR. | 236 | 13.2M | for (const NodePtr Succ : | 237 | 16.1M | ChildrenGetter<Direction>::Get(BB, BatchUpdates)) { | 238 | 16.1M | const auto SIT = NodeToInfo.find(Succ); | 239 | 16.1M | // Don't visit nodes more than once but remember to collect | 240 | 16.1M | // ReverseChildren. | 241 | 16.1M | if (SIT != NodeToInfo.end() && SIT->second.DFSNum != 02.60M ) { | 242 | 1.95M | if (Succ != BB) SIT->second.ReverseChildren.push_back(BB)1.66M ; | 243 | 1.95M | continue; | 244 | 1.95M | } | 245 | 14.1M | | 246 | 14.1M | if (!Condition(BB, Succ)) continue660k ; | 247 | 13.5M | | 248 | 13.5M | // It's fine to add Succ to the map, because we know that it will be | 249 | 13.5M | // visited later. | 250 | 13.5M | auto &SuccInfo = NodeToInfo[Succ]; | 251 | 13.5M | WorkList.push_back(Succ); | 252 | 13.5M | SuccInfo.Parent = LastNum; | 253 | 13.5M | SuccInfo.ReverseChildren.push_back(BB); | 254 | 13.5M | } | 255 | 13.2M | } | 256 | 399k | | 257 | 399k | return LastNum; | 258 | 399k | } |
unsigned int llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, false> >::runDFS<false, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, false> >::DeleteUnreachable(llvm::DominatorTreeBase<llvm::BasicBlock, false>&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, false> >::BatchUpdateInfo*, llvm::DomTreeNodeBase<llvm::BasicBlock>*)::'lambda'(llvm::BasicBlock*, llvm::BasicBlock*)>(llvm::BasicBlock*, unsigned int, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, false> >::DeleteUnreachable(llvm::DominatorTreeBase<llvm::BasicBlock, false>&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, false> >::BatchUpdateInfo*, llvm::DomTreeNodeBase<llvm::BasicBlock>*)::'lambda'(llvm::BasicBlock*, llvm::BasicBlock*), unsigned int) Line | Count | Source | 220 | 303k | unsigned AttachToNum) { | 221 | 303k | assert(V); | 222 | 303k | SmallVector<NodePtr, 64> WorkList = {V}; | 223 | 303k | if (NodeToInfo.count(V) != 0) NodeToInfo[V].Parent = AttachToNum0 ; | 224 | 303k | | 225 | 737k | while (!WorkList.empty()) { | 226 | 433k | const NodePtr BB = WorkList.pop_back_val(); | 227 | 433k | auto &BBInfo = NodeToInfo[BB]; | 228 | 433k | | 229 | 433k | // Visited nodes always have positive DFS numbers. | 230 | 433k | if (BBInfo.DFSNum != 0) continue10.1k ; | 231 | 423k | BBInfo.DFSNum = BBInfo.Semi = ++LastNum; | 232 | 423k | BBInfo.Label = BB; | 233 | 423k | NumToNode.push_back(BB); | 234 | 423k | | 235 | 423k | constexpr bool Direction = IsReverse != IsPostDom; // XOR. | 236 | 423k | for (const NodePtr Succ : | 237 | 423k | ChildrenGetter<Direction>::Get(BB, BatchUpdates)) { | 238 | 225k | const auto SIT = NodeToInfo.find(Succ); | 239 | 225k | // Don't visit nodes more than once but remember to collect | 240 | 225k | // ReverseChildren. | 241 | 225k | if (SIT != NodeToInfo.end() && SIT->second.DFSNum != 060.7k ) { | 242 | 50.5k | if (Succ != BB) SIT->second.ReverseChildren.push_back(BB)32.7k ; | 243 | 50.5k | continue; | 244 | 50.5k | } | 245 | 174k | | 246 | 174k | if (!Condition(BB, Succ)) continue44.3k ; | 247 | 130k | | 248 | 130k | // It's fine to add Succ to the map, because we know that it will be | 249 | 130k | // visited later. | 250 | 130k | auto &SuccInfo = NodeToInfo[Succ]; | 251 | 130k | WorkList.push_back(Succ); | 252 | 130k | SuccInfo.Parent = LastNum; | 253 | 130k | SuccInfo.ReverseChildren.push_back(BB); | 254 | 130k | } | 255 | 423k | } | 256 | 303k | | 257 | 303k | return LastNum; | 258 | 303k | } |
unsigned int llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, false> >::runDFS<false, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, false> >::DeleteUnreachable(llvm::DominatorTreeBase<llvm::BasicBlock, false>&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, false> >::BatchUpdateInfo*, llvm::DomTreeNodeBase<llvm::BasicBlock>*)::'lambda0'(llvm::BasicBlock*, llvm::BasicBlock*)>(llvm::BasicBlock*, unsigned int, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, false> >::DeleteUnreachable(llvm::DominatorTreeBase<llvm::BasicBlock, false>&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, false> >::BatchUpdateInfo*, llvm::DomTreeNodeBase<llvm::BasicBlock>*)::'lambda0'(llvm::BasicBlock*, llvm::BasicBlock*), unsigned int) Line | Count | Source | 220 | 24.0k | unsigned AttachToNum) { | 221 | 24.0k | assert(V); | 222 | 24.0k | SmallVector<NodePtr, 64> WorkList = {V}; | 223 | 24.0k | if (NodeToInfo.count(V) != 0) NodeToInfo[V].Parent = AttachToNum0 ; | 224 | 24.0k | | 225 | 358k | while (!WorkList.empty()) { | 226 | 334k | const NodePtr BB = WorkList.pop_back_val(); | 227 | 334k | auto &BBInfo = NodeToInfo[BB]; | 228 | 334k | | 229 | 334k | // Visited nodes always have positive DFS numbers. | 230 | 334k | if (BBInfo.DFSNum != 0) continue17.9k ; | 231 | 316k | BBInfo.DFSNum = BBInfo.Semi = ++LastNum; | 232 | 316k | BBInfo.Label = BB; | 233 | 316k | NumToNode.push_back(BB); | 234 | 316k | | 235 | 316k | constexpr bool Direction = IsReverse != IsPostDom; // XOR. | 236 | 316k | for (const NodePtr Succ : | 237 | 439k | ChildrenGetter<Direction>::Get(BB, BatchUpdates)) { | 238 | 439k | const auto SIT = NodeToInfo.find(Succ); | 239 | 439k | // Don't visit nodes more than once but remember to collect | 240 | 439k | // ReverseChildren. | 241 | 439k | if (SIT != NodeToInfo.end() && SIT->second.DFSNum != 0107k ) { | 242 | 89.5k | if (Succ != BB) SIT->second.ReverseChildren.push_back(BB)75.9k ; | 243 | 89.5k | continue; | 244 | 89.5k | } | 245 | 349k | | 246 | 349k | if (!Condition(BB, Succ)) continue39.2k ; | 247 | 310k | | 248 | 310k | // It's fine to add Succ to the map, because we know that it will be | 249 | 310k | // visited later. | 250 | 310k | auto &SuccInfo = NodeToInfo[Succ]; | 251 | 310k | WorkList.push_back(Succ); | 252 | 310k | SuccInfo.Parent = LastNum; | 253 | 310k | SuccInfo.ReverseChildren.push_back(BB); | 254 | 310k | } | 255 | 316k | } | 256 | 24.0k | | 257 | 24.0k | return LastNum; | 258 | 24.0k | } |
unsigned int llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, true> >::runDFS<false, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, true> >::DeleteReachable(llvm::DominatorTreeBase<llvm::BasicBlock, true>&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, true> >::BatchUpdateInfo*, llvm::DomTreeNodeBase<llvm::BasicBlock>*, llvm::DomTreeNodeBase<llvm::BasicBlock>*)::'lambda'(llvm::BasicBlock*, llvm::BasicBlock*)>(llvm::BasicBlock*, unsigned int, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, true> >::DeleteReachable(llvm::DominatorTreeBase<llvm::BasicBlock, true>&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, true> >::BatchUpdateInfo*, llvm::DomTreeNodeBase<llvm::BasicBlock>*, llvm::DomTreeNodeBase<llvm::BasicBlock>*)::'lambda'(llvm::BasicBlock*, llvm::BasicBlock*), unsigned int) Line | Count | Source | 220 | 93 | unsigned AttachToNum) { | 221 | 93 | assert(V); | 222 | 93 | SmallVector<NodePtr, 64> WorkList = {V}; | 223 | 93 | if (NodeToInfo.count(V) != 0) NodeToInfo[V].Parent = AttachToNum0 ; | 224 | 93 | | 225 | 478 | while (!WorkList.empty()) { | 226 | 385 | const NodePtr BB = WorkList.pop_back_val(); | 227 | 385 | auto &BBInfo = NodeToInfo[BB]; | 228 | 385 | | 229 | 385 | // Visited nodes always have positive DFS numbers. | 230 | 385 | if (BBInfo.DFSNum != 0) continue13 ; | 231 | 372 | BBInfo.DFSNum = BBInfo.Semi = ++LastNum; | 232 | 372 | BBInfo.Label = BB; | 233 | 372 | NumToNode.push_back(BB); | 234 | 372 | | 235 | 372 | constexpr bool Direction = IsReverse != IsPostDom; // XOR. | 236 | 372 | for (const NodePtr Succ : | 237 | 392 | ChildrenGetter<Direction>::Get(BB, BatchUpdates)) { | 238 | 392 | const auto SIT = NodeToInfo.find(Succ); | 239 | 392 | // Don't visit nodes more than once but remember to collect | 240 | 392 | // ReverseChildren. | 241 | 392 | if (SIT != NodeToInfo.end() && SIT->second.DFSNum != 044 ) { | 242 | 31 | if (Succ != BB) SIT->second.ReverseChildren.push_back(BB)28 ; | 243 | 31 | continue; | 244 | 31 | } | 245 | 361 | | 246 | 361 | if (!Condition(BB, Succ)) continue69 ; | 247 | 292 | | 248 | 292 | // It's fine to add Succ to the map, because we know that it will be | 249 | 292 | // visited later. | 250 | 292 | auto &SuccInfo = NodeToInfo[Succ]; | 251 | 292 | WorkList.push_back(Succ); | 252 | 292 | SuccInfo.Parent = LastNum; | 253 | 292 | SuccInfo.ReverseChildren.push_back(BB); | 254 | 292 | } | 255 | 372 | } | 256 | 93 | | 257 | 93 | return LastNum; | 258 | 93 | } |
unsigned int llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, false> >::runDFS<false, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, false> >::verifyParentProperty(llvm::DominatorTreeBase<llvm::BasicBlock, false> const&)::'lambda'(llvm::BasicBlock*, llvm::BasicBlock*)>(llvm::BasicBlock*, unsigned int, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, false> >::verifyParentProperty(llvm::DominatorTreeBase<llvm::BasicBlock, false> const&)::'lambda'(llvm::BasicBlock*, llvm::BasicBlock*), unsigned int) Line | Count | Source | 220 | 1.73k | unsigned AttachToNum) { | 221 | 1.73k | assert(V); | 222 | 1.73k | SmallVector<NodePtr, 64> WorkList = {V}; | 223 | 1.73k | if (NodeToInfo.count(V) != 0) NodeToInfo[V].Parent = AttachToNum0 ; | 224 | 1.73k | | 225 | 9.69k | while (!WorkList.empty()) { | 226 | 7.95k | const NodePtr BB = WorkList.pop_back_val(); | 227 | 7.95k | auto &BBInfo = NodeToInfo[BB]; | 228 | 7.95k | | 229 | 7.95k | // Visited nodes always have positive DFS numbers. | 230 | 7.95k | if (BBInfo.DFSNum != 0) continue141 ; | 231 | 7.81k | BBInfo.DFSNum = BBInfo.Semi = ++LastNum; | 232 | 7.81k | BBInfo.Label = BB; | 233 | 7.81k | NumToNode.push_back(BB); | 234 | 7.81k | | 235 | 7.81k | constexpr bool Direction = IsReverse != IsPostDom; // XOR. | 236 | 7.81k | for (const NodePtr Succ : | 237 | 8.68k | ChildrenGetter<Direction>::Get(BB, BatchUpdates)) { | 238 | 8.68k | const auto SIT = NodeToInfo.find(Succ); | 239 | 8.68k | // Don't visit nodes more than once but remember to collect | 240 | 8.68k | // ReverseChildren. | 241 | 8.68k | if (SIT != NodeToInfo.end() && SIT->second.DFSNum != 0768 ) { | 242 | 627 | if (Succ != BB) SIT->second.ReverseChildren.push_back(BB)450 ; | 243 | 627 | continue; | 244 | 627 | } | 245 | 8.06k | | 246 | 8.06k | if (!Condition(BB, Succ)) continue1.84k ; | 247 | 6.21k | | 248 | 6.21k | // It's fine to add Succ to the map, because we know that it will be | 249 | 6.21k | // visited later. | 250 | 6.21k | auto &SuccInfo = NodeToInfo[Succ]; | 251 | 6.21k | WorkList.push_back(Succ); | 252 | 6.21k | SuccInfo.Parent = LastNum; | 253 | 6.21k | SuccInfo.ReverseChildren.push_back(BB); | 254 | 6.21k | } | 255 | 7.81k | } | 256 | 1.73k | | 257 | 1.73k | return LastNum; | 258 | 1.73k | } |
unsigned int llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, false> >::runDFS<false, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, false> >::verifySiblingProperty(llvm::DominatorTreeBase<llvm::BasicBlock, false> const&)::'lambda'(llvm::BasicBlock*, llvm::BasicBlock*)>(llvm::BasicBlock*, unsigned int, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, false> >::verifySiblingProperty(llvm::DominatorTreeBase<llvm::BasicBlock, false> const&)::'lambda'(llvm::BasicBlock*, llvm::BasicBlock*), unsigned int) Line | Count | Source | 220 | 2.46k | unsigned AttachToNum) { | 221 | 2.46k | assert(V); | 222 | 2.46k | SmallVector<NodePtr, 64> WorkList = {V}; | 223 | 2.46k | if (NodeToInfo.count(V) != 0) NodeToInfo[V].Parent = AttachToNum0 ; | 224 | 2.46k | | 225 | 19.2k | while (!WorkList.empty()) { | 226 | 16.7k | const NodePtr BB = WorkList.pop_back_val(); | 227 | 16.7k | auto &BBInfo = NodeToInfo[BB]; | 228 | 16.7k | | 229 | 16.7k | // Visited nodes always have positive DFS numbers. | 230 | 16.7k | if (BBInfo.DFSNum != 0) continue351 ; | 231 | 16.4k | BBInfo.DFSNum = BBInfo.Semi = ++LastNum; | 232 | 16.4k | BBInfo.Label = BB; | 233 | 16.4k | NumToNode.push_back(BB); | 234 | 16.4k | | 235 | 16.4k | constexpr bool Direction = IsReverse != IsPostDom; // XOR. | 236 | 16.4k | for (const NodePtr Succ : | 237 | 18.5k | ChildrenGetter<Direction>::Get(BB, BatchUpdates)) { | 238 | 18.5k | const auto SIT = NodeToInfo.find(Succ); | 239 | 18.5k | // Don't visit nodes more than once but remember to collect | 240 | 18.5k | // ReverseChildren. | 241 | 18.5k | if (SIT != NodeToInfo.end() && SIT->second.DFSNum != 01.88k ) { | 242 | 1.53k | if (Succ != BB) SIT->second.ReverseChildren.push_back(BB)1.28k ; | 243 | 1.53k | continue; | 244 | 1.53k | } | 245 | 17.0k | | 246 | 17.0k | if (!Condition(BB, Succ)) continue2.74k ; | 247 | 14.3k | | 248 | 14.3k | // It's fine to add Succ to the map, because we know that it will be | 249 | 14.3k | // visited later. | 250 | 14.3k | auto &SuccInfo = NodeToInfo[Succ]; | 251 | 14.3k | WorkList.push_back(Succ); | 252 | 14.3k | SuccInfo.Parent = LastNum; | 253 | 14.3k | SuccInfo.ReverseChildren.push_back(BB); | 254 | 14.3k | } | 255 | 16.4k | } | 256 | 2.46k | | 257 | 2.46k | return LastNum; | 258 | 2.46k | } |
unsigned int llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, true> >::runDFS<false, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, true> >::verifyParentProperty(llvm::DominatorTreeBase<llvm::BasicBlock, true> const&)::'lambda'(llvm::BasicBlock*, llvm::BasicBlock*)>(llvm::BasicBlock*, unsigned int, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, true> >::verifyParentProperty(llvm::DominatorTreeBase<llvm::BasicBlock, true> const&)::'lambda'(llvm::BasicBlock*, llvm::BasicBlock*), unsigned int) Line | Count | Source | 220 | 5.13k | unsigned AttachToNum) { | 221 | 5.13k | assert(V); | 222 | 5.13k | SmallVector<NodePtr, 64> WorkList = {V}; | 223 | 5.13k | if (NodeToInfo.count(V) != 0) NodeToInfo[V].Parent = AttachToNum0 ; | 224 | 5.13k | | 225 | 20.3k | while (!WorkList.empty()) { | 226 | 15.1k | const NodePtr BB = WorkList.pop_back_val(); | 227 | 15.1k | auto &BBInfo = NodeToInfo[BB]; | 228 | 15.1k | | 229 | 15.1k | // Visited nodes always have positive DFS numbers. | 230 | 15.1k | if (BBInfo.DFSNum != 0) continue435 ; | 231 | 14.7k | BBInfo.DFSNum = BBInfo.Semi = ++LastNum; | 232 | 14.7k | BBInfo.Label = BB; | 233 | 14.7k | NumToNode.push_back(BB); | 234 | 14.7k | | 235 | 14.7k | constexpr bool Direction = IsReverse != IsPostDom; // XOR. | 236 | 14.7k | for (const NodePtr Succ : | 237 | 15.3k | ChildrenGetter<Direction>::Get(BB, BatchUpdates)) { | 238 | 15.3k | const auto SIT = NodeToInfo.find(Succ); | 239 | 15.3k | // Don't visit nodes more than once but remember to collect | 240 | 15.3k | // ReverseChildren. | 241 | 15.3k | if (SIT != NodeToInfo.end() && SIT->second.DFSNum != 03.23k ) { | 242 | 2.80k | if (Succ != BB) SIT->second.ReverseChildren.push_back(BB)2.79k ; | 243 | 2.80k | continue; | 244 | 2.80k | } | 245 | 12.5k | | 246 | 12.5k | if (!Condition(BB, Succ)) continue2.49k ; | 247 | 10.0k | | 248 | 10.0k | // It's fine to add Succ to the map, because we know that it will be | 249 | 10.0k | // visited later. | 250 | 10.0k | auto &SuccInfo = NodeToInfo[Succ]; | 251 | 10.0k | WorkList.push_back(Succ); | 252 | 10.0k | SuccInfo.Parent = LastNum; | 253 | 10.0k | SuccInfo.ReverseChildren.push_back(BB); | 254 | 10.0k | } | 255 | 14.7k | } | 256 | 5.13k | | 257 | 5.13k | return LastNum; | 258 | 5.13k | } |
unsigned int llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, true> >::runDFS<false, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, true> >::verifySiblingProperty(llvm::DominatorTreeBase<llvm::BasicBlock, true> const&)::'lambda'(llvm::BasicBlock*, llvm::BasicBlock*)>(llvm::BasicBlock*, unsigned int, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, true> >::verifySiblingProperty(llvm::DominatorTreeBase<llvm::BasicBlock, true> const&)::'lambda'(llvm::BasicBlock*, llvm::BasicBlock*), unsigned int) Line | Count | Source | 220 | 6.04k | unsigned AttachToNum) { | 221 | 6.04k | assert(V); | 222 | 6.04k | SmallVector<NodePtr, 64> WorkList = {V}; | 223 | 6.04k | if (NodeToInfo.count(V) != 0) NodeToInfo[V].Parent = AttachToNum0 ; | 224 | 6.04k | | 225 | 26.7k | while (!WorkList.empty()) { | 226 | 20.7k | const NodePtr BB = WorkList.pop_back_val(); | 227 | 20.7k | auto &BBInfo = NodeToInfo[BB]; | 228 | 20.7k | | 229 | 20.7k | // Visited nodes always have positive DFS numbers. | 230 | 20.7k | if (BBInfo.DFSNum != 0) continue807 ; | 231 | 19.9k | BBInfo.DFSNum = BBInfo.Semi = ++LastNum; | 232 | 19.9k | BBInfo.Label = BB; | 233 | 19.9k | NumToNode.push_back(BB); | 234 | 19.9k | | 235 | 19.9k | constexpr bool Direction = IsReverse != IsPostDom; // XOR. | 236 | 19.9k | for (const NodePtr Succ : | 237 | 21.3k | ChildrenGetter<Direction>::Get(BB, BatchUpdates)) { | 238 | 21.3k | const auto SIT = NodeToInfo.find(Succ); | 239 | 21.3k | // Don't visit nodes more than once but remember to collect | 240 | 21.3k | // ReverseChildren. | 241 | 21.3k | if (SIT != NodeToInfo.end() && SIT->second.DFSNum != 05.14k ) { | 242 | 4.33k | if (Succ != BB) SIT->second.ReverseChildren.push_back(BB)4.32k ; | 243 | 4.33k | continue; | 244 | 4.33k | } | 245 | 17.0k | | 246 | 17.0k | if (!Condition(BB, Succ)) continue2.35k ; | 247 | 14.6k | | 248 | 14.6k | // It's fine to add Succ to the map, because we know that it will be | 249 | 14.6k | // visited later. | 250 | 14.6k | auto &SuccInfo = NodeToInfo[Succ]; | 251 | 14.6k | WorkList.push_back(Succ); | 252 | 14.6k | SuccInfo.Parent = LastNum; | 253 | 14.6k | SuccInfo.ReverseChildren.push_back(BB); | 254 | 14.6k | } | 255 | 19.9k | } | 256 | 6.04k | | 257 | 6.04k | return LastNum; | 258 | 6.04k | } |
Unexecuted instantiation: unsigned int llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, false> >::runDFS<true, bool (*)(llvm::BasicBlock*, llvm::BasicBlock*)>(llvm::BasicBlock*, unsigned int, bool (*)(llvm::BasicBlock*, llvm::BasicBlock*), unsigned int) Unexecuted instantiation: unsigned int llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, true> >::runDFS<false, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, true> >::DeleteUnreachable(llvm::DominatorTreeBase<llvm::BasicBlock, true>&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, true> >::BatchUpdateInfo*, llvm::DomTreeNodeBase<llvm::BasicBlock>*)::'lambda'(llvm::BasicBlock*, llvm::BasicBlock*)>(llvm::BasicBlock*, unsigned int, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, true> >::DeleteUnreachable(llvm::DominatorTreeBase<llvm::BasicBlock, true>&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, true> >::BatchUpdateInfo*, llvm::DomTreeNodeBase<llvm::BasicBlock>*)::'lambda'(llvm::BasicBlock*, llvm::BasicBlock*), unsigned int) Unexecuted instantiation: unsigned int llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, true> >::runDFS<false, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, true> >::DeleteUnreachable(llvm::DominatorTreeBase<llvm::BasicBlock, true>&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, true> >::BatchUpdateInfo*, llvm::DomTreeNodeBase<llvm::BasicBlock>*)::'lambda0'(llvm::BasicBlock*, llvm::BasicBlock*)>(llvm::BasicBlock*, unsigned int, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, true> >::DeleteUnreachable(llvm::DominatorTreeBase<llvm::BasicBlock, true>&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, true> >::BatchUpdateInfo*, llvm::DomTreeNodeBase<llvm::BasicBlock>*)::'lambda0'(llvm::BasicBlock*, llvm::BasicBlock*), unsigned int) unsigned int llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::VPBlockBase, false> >::runDFS<false, bool (*)(llvm::VPBlockBase*, llvm::VPBlockBase*)>(llvm::VPBlockBase*, unsigned int, bool (*)(llvm::VPBlockBase*, llvm::VPBlockBase*), unsigned int) Line | Count | Source | 220 | 28 | unsigned AttachToNum) { | 221 | 28 | assert(V); | 222 | 28 | SmallVector<NodePtr, 64> WorkList = {V}; | 223 | 28 | if (NodeToInfo.count(V) != 0) NodeToInfo[V].Parent = AttachToNum0 ; | 224 | 28 | | 225 | 170 | while (!WorkList.empty()) { | 226 | 142 | const NodePtr BB = WorkList.pop_back_val(); | 227 | 142 | auto &BBInfo = NodeToInfo[BB]; | 228 | 142 | | 229 | 142 | // Visited nodes always have positive DFS numbers. | 230 | 142 | if (BBInfo.DFSNum != 0) continue7 ; | 231 | 135 | BBInfo.DFSNum = BBInfo.Semi = ++LastNum; | 232 | 135 | BBInfo.Label = BB; | 233 | 135 | NumToNode.push_back(BB); | 234 | 135 | | 235 | 135 | constexpr bool Direction = IsReverse != IsPostDom; // XOR. | 236 | 135 | for (const NodePtr Succ : | 237 | 158 | ChildrenGetter<Direction>::Get(BB, BatchUpdates)) { | 238 | 158 | const auto SIT = NodeToInfo.find(Succ); | 239 | 158 | // Don't visit nodes more than once but remember to collect | 240 | 158 | // ReverseChildren. | 241 | 158 | if (SIT != NodeToInfo.end() && SIT->second.DFSNum != 051 ) { | 242 | 44 | if (Succ != BB) SIT->second.ReverseChildren.push_back(BB)25 ; | 243 | 44 | continue; | 244 | 44 | } | 245 | 114 | | 246 | 114 | if (!Condition(BB, Succ)) continue0 ; | 247 | 114 | | 248 | 114 | // It's fine to add Succ to the map, because we know that it will be | 249 | 114 | // visited later. | 250 | 114 | auto &SuccInfo = NodeToInfo[Succ]; | 251 | 114 | WorkList.push_back(Succ); | 252 | 114 | SuccInfo.Parent = LastNum; | 253 | 114 | SuccInfo.ReverseChildren.push_back(BB); | 254 | 114 | } | 255 | 135 | } | 256 | 28 | | 257 | 28 | return LastNum; | 258 | 28 | } |
Unexecuted instantiation: unsigned int llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::VPBlockBase, false> >::runDFS<true, bool (*)(llvm::VPBlockBase*, llvm::VPBlockBase*)>(llvm::VPBlockBase*, unsigned int, bool (*)(llvm::VPBlockBase*, llvm::VPBlockBase*), unsigned int) unsigned int llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<clang::CFGBlock, false> >::runDFS<false, bool (*)(clang::CFGBlock*, clang::CFGBlock*)>(clang::CFGBlock*, unsigned int, bool (*)(clang::CFGBlock*, clang::CFGBlock*), unsigned int) Line | Count | Source | 220 | 8 | unsigned AttachToNum) { | 221 | 8 | assert(V); | 222 | 8 | SmallVector<NodePtr, 64> WorkList = {V}; | 223 | 8 | if (NodeToInfo.count(V) != 0) NodeToInfo[V].Parent = AttachToNum0 ; | 224 | 8 | | 225 | 77 | while (!WorkList.empty()) { | 226 | 69 | const NodePtr BB = WorkList.pop_back_val(); | 227 | 69 | auto &BBInfo = NodeToInfo[BB]; | 228 | 69 | | 229 | 69 | // Visited nodes always have positive DFS numbers. | 230 | 69 | if (BBInfo.DFSNum != 0) continue3 ; | 231 | 66 | BBInfo.DFSNum = BBInfo.Semi = ++LastNum; | 232 | 66 | BBInfo.Label = BB; | 233 | 66 | NumToNode.push_back(BB); | 234 | 66 | | 235 | 66 | constexpr bool Direction = IsReverse != IsPostDom; // XOR. | 236 | 66 | for (const NodePtr Succ : | 237 | 74 | ChildrenGetter<Direction>::Get(BB, BatchUpdates)) { | 238 | 74 | const auto SIT = NodeToInfo.find(Succ); | 239 | 74 | // Don't visit nodes more than once but remember to collect | 240 | 74 | // ReverseChildren. | 241 | 74 | if (SIT != NodeToInfo.end() && SIT->second.DFSNum != 016 ) { | 242 | 13 | if (Succ != BB) SIT->second.ReverseChildren.push_back(BB); | 243 | 13 | continue; | 244 | 13 | } | 245 | 61 | | 246 | 61 | if (!Condition(BB, Succ)) continue0 ; | 247 | 61 | | 248 | 61 | // It's fine to add Succ to the map, because we know that it will be | 249 | 61 | // visited later. | 250 | 61 | auto &SuccInfo = NodeToInfo[Succ]; | 251 | 61 | WorkList.push_back(Succ); | 252 | 61 | SuccInfo.Parent = LastNum; | 253 | 61 | SuccInfo.ReverseChildren.push_back(BB); | 254 | 61 | } | 255 | 66 | } | 256 | 8 | | 257 | 8 | return LastNum; | 258 | 8 | } |
unsigned int llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<clang::CFGBlock, true> >::runDFS<false, bool (*)(clang::CFGBlock*, clang::CFGBlock*)>(clang::CFGBlock*, unsigned int, bool (*)(clang::CFGBlock*, clang::CFGBlock*), unsigned int) Line | Count | Source | 220 | 214 | unsigned AttachToNum) { | 221 | 214 | assert(V); | 222 | 214 | SmallVector<NodePtr, 64> WorkList = {V}; | 223 | 214 | if (NodeToInfo.count(V) != 0) NodeToInfo[V].Parent = AttachToNum0 ; | 224 | 214 | | 225 | 1.31k | while (!WorkList.empty()) { | 226 | 1.09k | const NodePtr BB = WorkList.pop_back_val(); | 227 | 1.09k | auto &BBInfo = NodeToInfo[BB]; | 228 | 1.09k | | 229 | 1.09k | // Visited nodes always have positive DFS numbers. | 230 | 1.09k | if (BBInfo.DFSNum != 0) continue0 ; | 231 | 1.09k | BBInfo.DFSNum = BBInfo.Semi = ++LastNum; | 232 | 1.09k | BBInfo.Label = BB; | 233 | 1.09k | NumToNode.push_back(BB); | 234 | 1.09k | | 235 | 1.09k | constexpr bool Direction = IsReverse != IsPostDom; // XOR. | 236 | 1.09k | for (const NodePtr Succ : | 237 | 1.17k | ChildrenGetter<Direction>::Get(BB, BatchUpdates)) { | 238 | 1.17k | const auto SIT = NodeToInfo.find(Succ); | 239 | 1.17k | // Don't visit nodes more than once but remember to collect | 240 | 1.17k | // ReverseChildren. | 241 | 1.17k | if (SIT != NodeToInfo.end() && SIT->second.DFSNum != 0294 ) { | 242 | 294 | if (Succ != BB) SIT->second.ReverseChildren.push_back(BB); | 243 | 294 | continue; | 244 | 294 | } | 245 | 884 | | 246 | 884 | if (!Condition(BB, Succ)) continue0 ; | 247 | 884 | | 248 | 884 | // It's fine to add Succ to the map, because we know that it will be | 249 | 884 | // visited later. | 250 | 884 | auto &SuccInfo = NodeToInfo[Succ]; | 251 | 884 | WorkList.push_back(Succ); | 252 | 884 | SuccInfo.Parent = LastNum; | 253 | 884 | SuccInfo.ReverseChildren.push_back(BB); | 254 | 884 | } | 255 | 1.09k | } | 256 | 214 | | 257 | 214 | return LastNum; | 258 | 214 | } |
Unexecuted instantiation: unsigned int llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<clang::CFGBlock, true> >::runDFS<true, bool (*)(clang::CFGBlock*, clang::CFGBlock*)>(clang::CFGBlock*, unsigned int, bool (*)(clang::CFGBlock*, clang::CFGBlock*), unsigned int) Unexecuted instantiation: unsigned int llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<clang::CFGBlock, false> >::runDFS<true, bool (*)(clang::CFGBlock*, clang::CFGBlock*)>(clang::CFGBlock*, unsigned int, bool (*)(clang::CFGBlock*, clang::CFGBlock*), unsigned int) |
259 | | |
260 | | // V is a predecessor of W. eval() returns V if V < W, otherwise the minimum |
261 | | // of sdom(U), where U > W and there is a virtual forest path from U to V. The |
262 | | // virtual forest consists of linked edges of processed vertices. |
263 | | // |
264 | | // We can follow Parent pointers (virtual forest edges) to determine the |
265 | | // ancestor U with minimum sdom(U). But it is slow and thus we employ the path |
266 | | // compression technique to speed up to O(m*log(n)). Theoretically the virtual |
267 | | // forest can be organized as balanced trees to achieve almost linear |
268 | | // O(m*alpha(m,n)) running time. But it requires two auxiliary arrays (Size |
269 | | // and Child) and is unlikely to be faster than the simple implementation. |
270 | | // |
271 | | // For each vertex V, its Label points to the vertex with the minimal sdom(U) |
272 | | // (Semi) in its path from V (included) to NodeToInfo[V].Parent (excluded). |
273 | | NodePtr eval(NodePtr V, unsigned LastLinked, |
274 | 124M | SmallVectorImpl<InfoRec *> &Stack) { |
275 | 124M | InfoRec *VInfo = &NodeToInfo[V]; |
276 | 124M | if (VInfo->Parent < LastLinked) |
277 | 106M | return VInfo->Label; |
278 | 17.3M | |
279 | 17.3M | // Store ancestors except the last (root of a virtual tree) into a stack. |
280 | 17.3M | assert(Stack.empty()); |
281 | 42.5M | do { |
282 | 42.5M | Stack.push_back(VInfo); |
283 | 42.5M | VInfo = &NodeToInfo[NumToNode[VInfo->Parent]]; |
284 | 42.5M | } while (VInfo->Parent >= LastLinked); |
285 | 17.3M | |
286 | 17.3M | // Path compression. Point each vertex's Parent to the root and update its |
287 | 17.3M | // Label if any of its ancestors (PInfo->Label) has a smaller Semi. |
288 | 17.3M | const InfoRec *PInfo = VInfo; |
289 | 17.3M | const InfoRec *PLabelInfo = &NodeToInfo[PInfo->Label]; |
290 | 42.5M | do { |
291 | 42.5M | VInfo = Stack.pop_back_val(); |
292 | 42.5M | VInfo->Parent = PInfo->Parent; |
293 | 42.5M | const InfoRec *VLabelInfo = &NodeToInfo[VInfo->Label]; |
294 | 42.5M | if (PLabelInfo->Semi < VLabelInfo->Semi) |
295 | 40.2M | VInfo->Label = PInfo->Label; |
296 | 2.34M | else |
297 | 2.34M | PLabelInfo = VLabelInfo; |
298 | 42.5M | PInfo = VInfo; |
299 | 42.5M | } while (!Stack.empty()); |
300 | 17.3M | return VInfo->Label; |
301 | 17.3M | } llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> >::eval(llvm::MachineBasicBlock*, unsigned int, llvm::SmallVectorImpl<llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> >::InfoRec*>&) Line | Count | Source | 274 | 13.7M | SmallVectorImpl<InfoRec *> &Stack) { | 275 | 13.7M | InfoRec *VInfo = &NodeToInfo[V]; | 276 | 13.7M | if (VInfo->Parent < LastLinked) | 277 | 11.7M | return VInfo->Label; | 278 | 2.01M | | 279 | 2.01M | // Store ancestors except the last (root of a virtual tree) into a stack. | 280 | 2.01M | assert(Stack.empty()); | 281 | 4.95M | do { | 282 | 4.95M | Stack.push_back(VInfo); | 283 | 4.95M | VInfo = &NodeToInfo[NumToNode[VInfo->Parent]]; | 284 | 4.95M | } while (VInfo->Parent >= LastLinked); | 285 | 2.01M | | 286 | 2.01M | // Path compression. Point each vertex's Parent to the root and update its | 287 | 2.01M | // Label if any of its ancestors (PInfo->Label) has a smaller Semi. | 288 | 2.01M | const InfoRec *PInfo = VInfo; | 289 | 2.01M | const InfoRec *PLabelInfo = &NodeToInfo[PInfo->Label]; | 290 | 4.95M | do { | 291 | 4.95M | VInfo = Stack.pop_back_val(); | 292 | 4.95M | VInfo->Parent = PInfo->Parent; | 293 | 4.95M | const InfoRec *VLabelInfo = &NodeToInfo[VInfo->Label]; | 294 | 4.95M | if (PLabelInfo->Semi < VLabelInfo->Semi) | 295 | 4.79M | VInfo->Label = PInfo->Label; | 296 | 157k | else | 297 | 157k | PLabelInfo = VLabelInfo; | 298 | 4.95M | PInfo = VInfo; | 299 | 4.95M | } while (!Stack.empty()); | 300 | 2.01M | return VInfo->Label; | 301 | 2.01M | } |
llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> >::eval(llvm::MachineBasicBlock*, unsigned int, llvm::SmallVectorImpl<llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> >::InfoRec*>&) Line | Count | Source | 274 | 10.2M | SmallVectorImpl<InfoRec *> &Stack) { | 275 | 10.2M | InfoRec *VInfo = &NodeToInfo[V]; | 276 | 10.2M | if (VInfo->Parent < LastLinked) | 277 | 9.33M | return VInfo->Label; | 278 | 940k | | 279 | 940k | // Store ancestors except the last (root of a virtual tree) into a stack. | 280 | 940k | assert(Stack.empty()); | 281 | 3.01M | do { | 282 | 3.01M | Stack.push_back(VInfo); | 283 | 3.01M | VInfo = &NodeToInfo[NumToNode[VInfo->Parent]]; | 284 | 3.01M | } while (VInfo->Parent >= LastLinked); | 285 | 940k | | 286 | 940k | // Path compression. Point each vertex's Parent to the root and update its | 287 | 940k | // Label if any of its ancestors (PInfo->Label) has a smaller Semi. | 288 | 940k | const InfoRec *PInfo = VInfo; | 289 | 940k | const InfoRec *PLabelInfo = &NodeToInfo[PInfo->Label]; | 290 | 3.01M | do { | 291 | 3.01M | VInfo = Stack.pop_back_val(); | 292 | 3.01M | VInfo->Parent = PInfo->Parent; | 293 | 3.01M | const InfoRec *VLabelInfo = &NodeToInfo[VInfo->Label]; | 294 | 3.01M | if (PLabelInfo->Semi < VLabelInfo->Semi) | 295 | 2.05M | VInfo->Label = PInfo->Label; | 296 | 966k | else | 297 | 966k | PLabelInfo = VLabelInfo; | 298 | 3.01M | PInfo = VInfo; | 299 | 3.01M | } while (!Stack.empty()); | 300 | 940k | return VInfo->Label; | 301 | 940k | } |
llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, false> >::eval(llvm::BasicBlock*, unsigned int, llvm::SmallVectorImpl<llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, false> >::InfoRec*>&) Line | Count | Source | 274 | 96.4M | SmallVectorImpl<InfoRec *> &Stack) { | 275 | 96.4M | InfoRec *VInfo = &NodeToInfo[V]; | 276 | 96.4M | if (VInfo->Parent < LastLinked) | 277 | 82.5M | return VInfo->Label; | 278 | 13.9M | | 279 | 13.9M | // Store ancestors except the last (root of a virtual tree) into a stack. | 280 | 13.9M | assert(Stack.empty()); | 281 | 33.4M | do { | 282 | 33.4M | Stack.push_back(VInfo); | 283 | 33.4M | VInfo = &NodeToInfo[NumToNode[VInfo->Parent]]; | 284 | 33.4M | } while (VInfo->Parent >= LastLinked); | 285 | 13.9M | | 286 | 13.9M | // Path compression. Point each vertex's Parent to the root and update its | 287 | 13.9M | // Label if any of its ancestors (PInfo->Label) has a smaller Semi. | 288 | 13.9M | const InfoRec *PInfo = VInfo; | 289 | 13.9M | const InfoRec *PLabelInfo = &NodeToInfo[PInfo->Label]; | 290 | 33.4M | do { | 291 | 33.4M | VInfo = Stack.pop_back_val(); | 292 | 33.4M | VInfo->Parent = PInfo->Parent; | 293 | 33.4M | const InfoRec *VLabelInfo = &NodeToInfo[VInfo->Label]; | 294 | 33.4M | if (PLabelInfo->Semi < VLabelInfo->Semi) | 295 | 32.6M | VInfo->Label = PInfo->Label; | 296 | 850k | else | 297 | 850k | PLabelInfo = VLabelInfo; | 298 | 33.4M | PInfo = VInfo; | 299 | 33.4M | } while (!Stack.empty()); | 300 | 13.9M | return VInfo->Label; | 301 | 13.9M | } |
llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, true> >::eval(llvm::BasicBlock*, unsigned int, llvm::SmallVectorImpl<llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, true> >::InfoRec*>&) Line | Count | Source | 274 | 3.67M | SmallVectorImpl<InfoRec *> &Stack) { | 275 | 3.67M | InfoRec *VInfo = &NodeToInfo[V]; | 276 | 3.67M | if (VInfo->Parent < LastLinked) | 277 | 3.17M | return VInfo->Label; | 278 | 493k | | 279 | 493k | // Store ancestors except the last (root of a virtual tree) into a stack. | 280 | 493k | assert(Stack.empty()); | 281 | 1.07M | do { | 282 | 1.07M | Stack.push_back(VInfo); | 283 | 1.07M | VInfo = &NodeToInfo[NumToNode[VInfo->Parent]]; | 284 | 1.07M | } while (VInfo->Parent >= LastLinked); | 285 | 493k | | 286 | 493k | // Path compression. Point each vertex's Parent to the root and update its | 287 | 493k | // Label if any of its ancestors (PInfo->Label) has a smaller Semi. | 288 | 493k | const InfoRec *PInfo = VInfo; | 289 | 493k | const InfoRec *PLabelInfo = &NodeToInfo[PInfo->Label]; | 290 | 1.07M | do { | 291 | 1.07M | VInfo = Stack.pop_back_val(); | 292 | 1.07M | VInfo->Parent = PInfo->Parent; | 293 | 1.07M | const InfoRec *VLabelInfo = &NodeToInfo[VInfo->Label]; | 294 | 1.07M | if (PLabelInfo->Semi < VLabelInfo->Semi) | 295 | 713k | VInfo->Label = PInfo->Label; | 296 | 366k | else | 297 | 366k | PLabelInfo = VLabelInfo; | 298 | 1.07M | PInfo = VInfo; | 299 | 1.07M | } while (!Stack.empty()); | 300 | 493k | return VInfo->Label; | 301 | 493k | } |
llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::VPBlockBase, false> >::eval(llvm::VPBlockBase*, unsigned int, llvm::SmallVectorImpl<llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::VPBlockBase, false> >::InfoRec*>&) Line | Count | Source | 274 | 139 | SmallVectorImpl<InfoRec *> &Stack) { | 275 | 139 | InfoRec *VInfo = &NodeToInfo[V]; | 276 | 139 | if (VInfo->Parent < LastLinked) | 277 | 121 | return VInfo->Label; | 278 | 18 | | 279 | 18 | // Store ancestors except the last (root of a virtual tree) into a stack. | 280 | 18 | assert(Stack.empty()); | 281 | 30 | do { | 282 | 30 | Stack.push_back(VInfo); | 283 | 30 | VInfo = &NodeToInfo[NumToNode[VInfo->Parent]]; | 284 | 30 | } while (VInfo->Parent >= LastLinked); | 285 | 18 | | 286 | 18 | // Path compression. Point each vertex's Parent to the root and update its | 287 | 18 | // Label if any of its ancestors (PInfo->Label) has a smaller Semi. | 288 | 18 | const InfoRec *PInfo = VInfo; | 289 | 18 | const InfoRec *PLabelInfo = &NodeToInfo[PInfo->Label]; | 290 | 30 | do { | 291 | 30 | VInfo = Stack.pop_back_val(); | 292 | 30 | VInfo->Parent = PInfo->Parent; | 293 | 30 | const InfoRec *VLabelInfo = &NodeToInfo[VInfo->Label]; | 294 | 30 | if (PLabelInfo->Semi < VLabelInfo->Semi) | 295 | 22 | VInfo->Label = PInfo->Label; | 296 | 8 | else | 297 | 8 | PLabelInfo = VLabelInfo; | 298 | 30 | PInfo = VInfo; | 299 | 30 | } while (!Stack.empty()); | 300 | 18 | return VInfo->Label; | 301 | 18 | } |
llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<clang::CFGBlock, false> >::eval(clang::CFGBlock*, unsigned int, llvm::SmallVectorImpl<llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<clang::CFGBlock, false> >::InfoRec*>&) Line | Count | Source | 274 | 74 | SmallVectorImpl<InfoRec *> &Stack) { | 275 | 74 | InfoRec *VInfo = &NodeToInfo[V]; | 276 | 74 | if (VInfo->Parent < LastLinked) | 277 | 67 | return VInfo->Label; | 278 | 7 | | 279 | 7 | // Store ancestors except the last (root of a virtual tree) into a stack. | 280 | 7 | assert(Stack.empty()); | 281 | 10 | do { | 282 | 10 | Stack.push_back(VInfo); | 283 | 10 | VInfo = &NodeToInfo[NumToNode[VInfo->Parent]]; | 284 | 10 | } while (VInfo->Parent >= LastLinked); | 285 | 7 | | 286 | 7 | // Path compression. Point each vertex's Parent to the root and update its | 287 | 7 | // Label if any of its ancestors (PInfo->Label) has a smaller Semi. | 288 | 7 | const InfoRec *PInfo = VInfo; | 289 | 7 | const InfoRec *PLabelInfo = &NodeToInfo[PInfo->Label]; | 290 | 10 | do { | 291 | 10 | VInfo = Stack.pop_back_val(); | 292 | 10 | VInfo->Parent = PInfo->Parent; | 293 | 10 | const InfoRec *VLabelInfo = &NodeToInfo[VInfo->Label]; | 294 | 10 | if (PLabelInfo->Semi < VLabelInfo->Semi) | 295 | 10 | VInfo->Label = PInfo->Label; | 296 | 0 | else | 297 | 0 | PLabelInfo = VLabelInfo; | 298 | 10 | PInfo = VInfo; | 299 | 10 | } while (!Stack.empty()); | 300 | 7 | return VInfo->Label; | 301 | 7 | } |
llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<clang::CFGBlock, true> >::eval(clang::CFGBlock*, unsigned int, llvm::SmallVectorImpl<llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<clang::CFGBlock, true> >::InfoRec*>&) Line | Count | Source | 274 | 589 | SmallVectorImpl<InfoRec *> &Stack) { | 275 | 589 | InfoRec *VInfo = &NodeToInfo[V]; | 276 | 589 | if (VInfo->Parent < LastLinked) | 277 | 570 | return VInfo->Label; | 278 | 19 | | 279 | 19 | // Store ancestors except the last (root of a virtual tree) into a stack. | 280 | 19 | assert(Stack.empty()); | 281 | 25 | do { | 282 | 25 | Stack.push_back(VInfo); | 283 | 25 | VInfo = &NodeToInfo[NumToNode[VInfo->Parent]]; | 284 | 25 | } while (VInfo->Parent >= LastLinked); | 285 | 19 | | 286 | 19 | // Path compression. Point each vertex's Parent to the root and update its | 287 | 19 | // Label if any of its ancestors (PInfo->Label) has a smaller Semi. | 288 | 19 | const InfoRec *PInfo = VInfo; | 289 | 19 | const InfoRec *PLabelInfo = &NodeToInfo[PInfo->Label]; | 290 | 25 | do { | 291 | 25 | VInfo = Stack.pop_back_val(); | 292 | 25 | VInfo->Parent = PInfo->Parent; | 293 | 25 | const InfoRec *VLabelInfo = &NodeToInfo[VInfo->Label]; | 294 | 25 | if (PLabelInfo->Semi < VLabelInfo->Semi) | 295 | 25 | VInfo->Label = PInfo->Label; | 296 | 0 | else | 297 | 0 | PLabelInfo = VLabelInfo; | 298 | 25 | PInfo = VInfo; | 299 | 25 | } while (!Stack.empty()); | 300 | 19 | return VInfo->Label; | 301 | 19 | } |
|
302 | | |
303 | | // This function requires DFS to be run before calling it. |
304 | 15.6M | void runSemiNCA(DomTreeT &DT, const unsigned MinLevel = 0) { |
305 | 15.6M | const unsigned NextDFSNum(NumToNode.size()); |
306 | 15.6M | // Initialize IDoms to spanning tree parents. |
307 | 119M | for (unsigned i = 1; i < NextDFSNum; ++i103M ) { |
308 | 103M | const NodePtr V = NumToNode[i]; |
309 | 103M | auto &VInfo = NodeToInfo[V]; |
310 | 103M | VInfo.IDom = NumToNode[VInfo.Parent]; |
311 | 103M | } |
312 | 15.6M | |
313 | 15.6M | // Step #1: Calculate the semidominators of all vertices. |
314 | 15.6M | SmallVector<InfoRec *, 32> EvalStack; |
315 | 103M | for (unsigned i = NextDFSNum - 1; i >= 2; --i87.9M ) { |
316 | 87.9M | NodePtr W = NumToNode[i]; |
317 | 87.9M | auto &WInfo = NodeToInfo[W]; |
318 | 87.9M | |
319 | 87.9M | // Initialize the semi dominator to point to the parent node. |
320 | 87.9M | WInfo.Semi = WInfo.Parent; |
321 | 124M | for (const auto &N : WInfo.ReverseChildren) { |
322 | 124M | if (NodeToInfo.count(N) == 0) // Skip unreachable predecessors. |
323 | 0 | continue; |
324 | 124M | |
325 | 124M | const TreeNodePtr TN = DT.getNode(N); |
326 | 124M | // Skip predecessors whose level is above the subtree we are processing. |
327 | 124M | if (TN && TN->getLevel() < MinLevel15.5M ) |
328 | 0 | continue; |
329 | 124M | |
330 | 124M | unsigned SemiU = NodeToInfo[eval(N, i + 1, EvalStack)].Semi; |
331 | 124M | if (SemiU < WInfo.Semi) WInfo.Semi = SemiU14.9M ; |
332 | 124M | } |
333 | 87.9M | } |
334 | 15.6M | |
335 | 15.6M | // Step #2: Explicitly define the immediate dominator of each vertex. |
336 | 15.6M | // IDom[i] = NCA(SDom[i], SpanningTreeParent(i)). |
337 | 15.6M | // Note that the parents were stored in IDoms and later got invalidated |
338 | 15.6M | // during path compression in Eval. |
339 | 103M | for (unsigned i = 2; i < NextDFSNum; ++i87.9M ) { |
340 | 87.9M | const NodePtr W = NumToNode[i]; |
341 | 87.9M | auto &WInfo = NodeToInfo[W]; |
342 | 87.9M | const unsigned SDomNum = NodeToInfo[NumToNode[WInfo.Semi]].DFSNum; |
343 | 87.9M | NodePtr WIDomCandidate = WInfo.IDom; |
344 | 114M | while (NodeToInfo[WIDomCandidate].DFSNum > SDomNum) |
345 | 26.3M | WIDomCandidate = NodeToInfo[WIDomCandidate].IDom; |
346 | 87.9M | |
347 | 87.9M | WInfo.IDom = WIDomCandidate; |
348 | 87.9M | } |
349 | 15.6M | } llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> >::runSemiNCA(llvm::DominatorTreeBase<llvm::MachineBasicBlock, false>&, unsigned int) Line | Count | Source | 304 | 2.61M | void runSemiNCA(DomTreeT &DT, const unsigned MinLevel = 0) { | 305 | 2.61M | const unsigned NextDFSNum(NumToNode.size()); | 306 | 2.61M | // Initialize IDoms to spanning tree parents. | 307 | 14.6M | for (unsigned i = 1; i < NextDFSNum; ++i12.0M ) { | 308 | 12.0M | const NodePtr V = NumToNode[i]; | 309 | 12.0M | auto &VInfo = NodeToInfo[V]; | 310 | 12.0M | VInfo.IDom = NumToNode[VInfo.Parent]; | 311 | 12.0M | } | 312 | 2.61M | | 313 | 2.61M | // Step #1: Calculate the semidominators of all vertices. | 314 | 2.61M | SmallVector<InfoRec *, 32> EvalStack; | 315 | 12.0M | for (unsigned i = NextDFSNum - 1; i >= 2; --i9.38M ) { | 316 | 9.38M | NodePtr W = NumToNode[i]; | 317 | 9.38M | auto &WInfo = NodeToInfo[W]; | 318 | 9.38M | | 319 | 9.38M | // Initialize the semi dominator to point to the parent node. | 320 | 9.38M | WInfo.Semi = WInfo.Parent; | 321 | 13.7M | for (const auto &N : WInfo.ReverseChildren) { | 322 | 13.7M | if (NodeToInfo.count(N) == 0) // Skip unreachable predecessors. | 323 | 0 | continue; | 324 | 13.7M | | 325 | 13.7M | const TreeNodePtr TN = DT.getNode(N); | 326 | 13.7M | // Skip predecessors whose level is above the subtree we are processing. | 327 | 13.7M | if (TN && TN->getLevel() < MinLevel0 ) | 328 | 0 | continue; | 329 | 13.7M | | 330 | 13.7M | unsigned SemiU = NodeToInfo[eval(N, i + 1, EvalStack)].Semi; | 331 | 13.7M | if (SemiU < WInfo.Semi) WInfo.Semi = SemiU1.60M ; | 332 | 13.7M | } | 333 | 9.38M | } | 334 | 2.61M | | 335 | 2.61M | // Step #2: Explicitly define the immediate dominator of each vertex. | 336 | 2.61M | // IDom[i] = NCA(SDom[i], SpanningTreeParent(i)). | 337 | 2.61M | // Note that the parents were stored in IDoms and later got invalidated | 338 | 2.61M | // during path compression in Eval. | 339 | 12.0M | for (unsigned i = 2; i < NextDFSNum; ++i9.38M ) { | 340 | 9.38M | const NodePtr W = NumToNode[i]; | 341 | 9.38M | auto &WInfo = NodeToInfo[W]; | 342 | 9.38M | const unsigned SDomNum = NodeToInfo[NumToNode[WInfo.Semi]].DFSNum; | 343 | 9.38M | NodePtr WIDomCandidate = WInfo.IDom; | 344 | 12.2M | while (NodeToInfo[WIDomCandidate].DFSNum > SDomNum) | 345 | 2.84M | WIDomCandidate = NodeToInfo[WIDomCandidate].IDom; | 346 | 9.38M | | 347 | 9.38M | WInfo.IDom = WIDomCandidate; | 348 | 9.38M | } | 349 | 2.61M | } |
llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> >::runSemiNCA(llvm::DominatorTreeBase<llvm::MachineBasicBlock, true>&, unsigned int) Line | Count | Source | 304 | 1.50M | void runSemiNCA(DomTreeT &DT, const unsigned MinLevel = 0) { | 305 | 1.50M | const unsigned NextDFSNum(NumToNode.size()); | 306 | 1.50M | // Initialize IDoms to spanning tree parents. | 307 | 11.5M | for (unsigned i = 1; i < NextDFSNum; ++i10.0M ) { | 308 | 10.0M | const NodePtr V = NumToNode[i]; | 309 | 10.0M | auto &VInfo = NodeToInfo[V]; | 310 | 10.0M | VInfo.IDom = NumToNode[VInfo.Parent]; | 311 | 10.0M | } | 312 | 1.50M | | 313 | 1.50M | // Step #1: Calculate the semidominators of all vertices. | 314 | 1.50M | SmallVector<InfoRec *, 32> EvalStack; | 315 | 10.0M | for (unsigned i = NextDFSNum - 1; i >= 2; --i8.52M ) { | 316 | 8.52M | NodePtr W = NumToNode[i]; | 317 | 8.52M | auto &WInfo = NodeToInfo[W]; | 318 | 8.52M | | 319 | 8.52M | // Initialize the semi dominator to point to the parent node. | 320 | 8.52M | WInfo.Semi = WInfo.Parent; | 321 | 10.2M | for (const auto &N : WInfo.ReverseChildren) { | 322 | 10.2M | if (NodeToInfo.count(N) == 0) // Skip unreachable predecessors. | 323 | 0 | continue; | 324 | 10.2M | | 325 | 10.2M | const TreeNodePtr TN = DT.getNode(N); | 326 | 10.2M | // Skip predecessors whose level is above the subtree we are processing. | 327 | 10.2M | if (TN && TN->getLevel() < MinLevel0 ) | 328 | 0 | continue; | 329 | 10.2M | | 330 | 10.2M | unsigned SemiU = NodeToInfo[eval(N, i + 1, EvalStack)].Semi; | 331 | 10.2M | if (SemiU < WInfo.Semi) WInfo.Semi = SemiU3.37M ; | 332 | 10.2M | } | 333 | 8.52M | } | 334 | 1.50M | | 335 | 1.50M | // Step #2: Explicitly define the immediate dominator of each vertex. | 336 | 1.50M | // IDom[i] = NCA(SDom[i], SpanningTreeParent(i)). | 337 | 1.50M | // Note that the parents were stored in IDoms and later got invalidated | 338 | 1.50M | // during path compression in Eval. | 339 | 10.0M | for (unsigned i = 2; i < NextDFSNum; ++i8.52M ) { | 340 | 8.52M | const NodePtr W = NumToNode[i]; | 341 | 8.52M | auto &WInfo = NodeToInfo[W]; | 342 | 8.52M | const unsigned SDomNum = NodeToInfo[NumToNode[WInfo.Semi]].DFSNum; | 343 | 8.52M | NodePtr WIDomCandidate = WInfo.IDom; | 344 | 13.2M | while (NodeToInfo[WIDomCandidate].DFSNum > SDomNum) | 345 | 4.70M | WIDomCandidate = NodeToInfo[WIDomCandidate].IDom; | 346 | 8.52M | | 347 | 8.52M | WInfo.IDom = WIDomCandidate; | 348 | 8.52M | } | 349 | 1.50M | } |
llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, false> >::runSemiNCA(llvm::DominatorTreeBase<llvm::BasicBlock, false>&, unsigned int) Line | Count | Source | 304 | 10.9M | void runSemiNCA(DomTreeT &DT, const unsigned MinLevel = 0) { | 305 | 10.9M | const unsigned NextDFSNum(NumToNode.size()); | 306 | 10.9M | // Initialize IDoms to spanning tree parents. | 307 | 88.7M | for (unsigned i = 1; i < NextDFSNum; ++i77.8M ) { | 308 | 77.8M | const NodePtr V = NumToNode[i]; | 309 | 77.8M | auto &VInfo = NodeToInfo[V]; | 310 | 77.8M | VInfo.IDom = NumToNode[VInfo.Parent]; | 311 | 77.8M | } | 312 | 10.9M | | 313 | 10.9M | // Step #1: Calculate the semidominators of all vertices. | 314 | 10.9M | SmallVector<InfoRec *, 32> EvalStack; | 315 | 77.8M | for (unsigned i = NextDFSNum - 1; i >= 2; --i66.9M ) { | 316 | 66.9M | NodePtr W = NumToNode[i]; | 317 | 66.9M | auto &WInfo = NodeToInfo[W]; | 318 | 66.9M | | 319 | 66.9M | // Initialize the semi dominator to point to the parent node. | 320 | 66.9M | WInfo.Semi = WInfo.Parent; | 321 | 96.4M | for (const auto &N : WInfo.ReverseChildren) { | 322 | 96.4M | if (NodeToInfo.count(N) == 0) // Skip unreachable predecessors. | 323 | 0 | continue; | 324 | 96.4M | | 325 | 96.4M | const TreeNodePtr TN = DT.getNode(N); | 326 | 96.4M | // Skip predecessors whose level is above the subtree we are processing. | 327 | 96.4M | if (TN && TN->getLevel() < MinLevel15.5M ) | 328 | 0 | continue; | 329 | 96.4M | | 330 | 96.4M | unsigned SemiU = NodeToInfo[eval(N, i + 1, EvalStack)].Semi; | 331 | 96.4M | if (SemiU < WInfo.Semi) WInfo.Semi = SemiU9.19M ; | 332 | 96.4M | } | 333 | 66.9M | } | 334 | 10.9M | | 335 | 10.9M | // Step #2: Explicitly define the immediate dominator of each vertex. | 336 | 10.9M | // IDom[i] = NCA(SDom[i], SpanningTreeParent(i)). | 337 | 10.9M | // Note that the parents were stored in IDoms and later got invalidated | 338 | 10.9M | // during path compression in Eval. | 339 | 77.8M | for (unsigned i = 2; i < NextDFSNum; ++i66.9M ) { | 340 | 66.9M | const NodePtr W = NumToNode[i]; | 341 | 66.9M | auto &WInfo = NodeToInfo[W]; | 342 | 66.9M | const unsigned SDomNum = NodeToInfo[NumToNode[WInfo.Semi]].DFSNum; | 343 | 66.9M | NodePtr WIDomCandidate = WInfo.IDom; | 344 | 84.7M | while (NodeToInfo[WIDomCandidate].DFSNum > SDomNum) | 345 | 17.8M | WIDomCandidate = NodeToInfo[WIDomCandidate].IDom; | 346 | 66.9M | | 347 | 66.9M | WInfo.IDom = WIDomCandidate; | 348 | 66.9M | } | 349 | 10.9M | } |
llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, true> >::runSemiNCA(llvm::DominatorTreeBase<llvm::BasicBlock, true>&, unsigned int) Line | Count | Source | 304 | 605k | void runSemiNCA(DomTreeT &DT, const unsigned MinLevel = 0) { | 305 | 605k | const unsigned NextDFSNum(NumToNode.size()); | 306 | 605k | // Initialize IDoms to spanning tree parents. | 307 | 4.27M | for (unsigned i = 1; i < NextDFSNum; ++i3.66M ) { | 308 | 3.66M | const NodePtr V = NumToNode[i]; | 309 | 3.66M | auto &VInfo = NodeToInfo[V]; | 310 | 3.66M | VInfo.IDom = NumToNode[VInfo.Parent]; | 311 | 3.66M | } | 312 | 605k | | 313 | 605k | // Step #1: Calculate the semidominators of all vertices. | 314 | 605k | SmallVector<InfoRec *, 32> EvalStack; | 315 | 3.66M | for (unsigned i = NextDFSNum - 1; i >= 2; --i3.06M ) { | 316 | 3.06M | NodePtr W = NumToNode[i]; | 317 | 3.06M | auto &WInfo = NodeToInfo[W]; | 318 | 3.06M | | 319 | 3.06M | // Initialize the semi dominator to point to the parent node. | 320 | 3.06M | WInfo.Semi = WInfo.Parent; | 321 | 3.67M | for (const auto &N : WInfo.ReverseChildren) { | 322 | 3.67M | if (NodeToInfo.count(N) == 0) // Skip unreachable predecessors. | 323 | 0 | continue; | 324 | 3.67M | | 325 | 3.67M | const TreeNodePtr TN = DT.getNode(N); | 326 | 3.67M | // Skip predecessors whose level is above the subtree we are processing. | 327 | 3.67M | if (TN && TN->getLevel() < MinLevel308 ) | 328 | 0 | continue; | 329 | 3.67M | | 330 | 3.67M | unsigned SemiU = NodeToInfo[eval(N, i + 1, EvalStack)].Semi; | 331 | 3.67M | if (SemiU < WInfo.Semi) WInfo.Semi = SemiU792k ; | 332 | 3.67M | } | 333 | 3.06M | } | 334 | 605k | | 335 | 605k | // Step #2: Explicitly define the immediate dominator of each vertex. | 336 | 605k | // IDom[i] = NCA(SDom[i], SpanningTreeParent(i)). | 337 | 605k | // Note that the parents were stored in IDoms and later got invalidated | 338 | 605k | // during path compression in Eval. | 339 | 3.66M | for (unsigned i = 2; i < NextDFSNum; ++i3.06M ) { | 340 | 3.06M | const NodePtr W = NumToNode[i]; | 341 | 3.06M | auto &WInfo = NodeToInfo[W]; | 342 | 3.06M | const unsigned SDomNum = NodeToInfo[NumToNode[WInfo.Semi]].DFSNum; | 343 | 3.06M | NodePtr WIDomCandidate = WInfo.IDom; | 344 | 4.05M | while (NodeToInfo[WIDomCandidate].DFSNum > SDomNum) | 345 | 992k | WIDomCandidate = NodeToInfo[WIDomCandidate].IDom; | 346 | 3.06M | | 347 | 3.06M | WInfo.IDom = WIDomCandidate; | 348 | 3.06M | } | 349 | 605k | } |
llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::VPBlockBase, false> >::runSemiNCA(llvm::DominatorTreeBase<llvm::VPBlockBase, false>&, unsigned int) Line | Count | Source | 304 | 28 | void runSemiNCA(DomTreeT &DT, const unsigned MinLevel = 0) { | 305 | 28 | const unsigned NextDFSNum(NumToNode.size()); | 306 | 28 | // Initialize IDoms to spanning tree parents. | 307 | 163 | for (unsigned i = 1; i < NextDFSNum; ++i135 ) { | 308 | 135 | const NodePtr V = NumToNode[i]; | 309 | 135 | auto &VInfo = NodeToInfo[V]; | 310 | 135 | VInfo.IDom = NumToNode[VInfo.Parent]; | 311 | 135 | } | 312 | 28 | | 313 | 28 | // Step #1: Calculate the semidominators of all vertices. | 314 | 28 | SmallVector<InfoRec *, 32> EvalStack; | 315 | 135 | for (unsigned i = NextDFSNum - 1; i >= 2; --i107 ) { | 316 | 107 | NodePtr W = NumToNode[i]; | 317 | 107 | auto &WInfo = NodeToInfo[W]; | 318 | 107 | | 319 | 107 | // Initialize the semi dominator to point to the parent node. | 320 | 107 | WInfo.Semi = WInfo.Parent; | 321 | 139 | for (const auto &N : WInfo.ReverseChildren) { | 322 | 139 | if (NodeToInfo.count(N) == 0) // Skip unreachable predecessors. | 323 | 0 | continue; | 324 | 139 | | 325 | 139 | const TreeNodePtr TN = DT.getNode(N); | 326 | 139 | // Skip predecessors whose level is above the subtree we are processing. | 327 | 139 | if (TN && TN->getLevel() < MinLevel0 ) | 328 | 0 | continue; | 329 | 139 | | 330 | 139 | unsigned SemiU = NodeToInfo[eval(N, i + 1, EvalStack)].Semi; | 331 | 139 | if (SemiU < WInfo.Semi) WInfo.Semi = SemiU10 ; | 332 | 139 | } | 333 | 107 | } | 334 | 28 | | 335 | 28 | // Step #2: Explicitly define the immediate dominator of each vertex. | 336 | 28 | // IDom[i] = NCA(SDom[i], SpanningTreeParent(i)). | 337 | 28 | // Note that the parents were stored in IDoms and later got invalidated | 338 | 28 | // during path compression in Eval. | 339 | 135 | for (unsigned i = 2; i < NextDFSNum; ++i107 ) { | 340 | 107 | const NodePtr W = NumToNode[i]; | 341 | 107 | auto &WInfo = NodeToInfo[W]; | 342 | 107 | const unsigned SDomNum = NodeToInfo[NumToNode[WInfo.Semi]].DFSNum; | 343 | 107 | NodePtr WIDomCandidate = WInfo.IDom; | 344 | 123 | while (NodeToInfo[WIDomCandidate].DFSNum > SDomNum) | 345 | 16 | WIDomCandidate = NodeToInfo[WIDomCandidate].IDom; | 346 | 107 | | 347 | 107 | WInfo.IDom = WIDomCandidate; | 348 | 107 | } | 349 | 28 | } |
llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<clang::CFGBlock, false> >::runSemiNCA(llvm::DominatorTreeBase<clang::CFGBlock, false>&, unsigned int) Line | Count | Source | 304 | 8 | void runSemiNCA(DomTreeT &DT, const unsigned MinLevel = 0) { | 305 | 8 | const unsigned NextDFSNum(NumToNode.size()); | 306 | 8 | // Initialize IDoms to spanning tree parents. | 307 | 74 | for (unsigned i = 1; i < NextDFSNum; ++i66 ) { | 308 | 66 | const NodePtr V = NumToNode[i]; | 309 | 66 | auto &VInfo = NodeToInfo[V]; | 310 | 66 | VInfo.IDom = NumToNode[VInfo.Parent]; | 311 | 66 | } | 312 | 8 | | 313 | 8 | // Step #1: Calculate the semidominators of all vertices. | 314 | 8 | SmallVector<InfoRec *, 32> EvalStack; | 315 | 66 | for (unsigned i = NextDFSNum - 1; i >= 2; --i58 ) { | 316 | 58 | NodePtr W = NumToNode[i]; | 317 | 58 | auto &WInfo = NodeToInfo[W]; | 318 | 58 | | 319 | 58 | // Initialize the semi dominator to point to the parent node. | 320 | 58 | WInfo.Semi = WInfo.Parent; | 321 | 74 | for (const auto &N : WInfo.ReverseChildren) { | 322 | 74 | if (NodeToInfo.count(N) == 0) // Skip unreachable predecessors. | 323 | 0 | continue; | 324 | 74 | | 325 | 74 | const TreeNodePtr TN = DT.getNode(N); | 326 | 74 | // Skip predecessors whose level is above the subtree we are processing. | 327 | 74 | if (TN && TN->getLevel() < MinLevel0 ) | 328 | 0 | continue; | 329 | 74 | | 330 | 74 | unsigned SemiU = NodeToInfo[eval(N, i + 1, EvalStack)].Semi; | 331 | 74 | if (SemiU < WInfo.Semi) WInfo.Semi = SemiU9 ; | 332 | 74 | } | 333 | 58 | } | 334 | 8 | | 335 | 8 | // Step #2: Explicitly define the immediate dominator of each vertex. | 336 | 8 | // IDom[i] = NCA(SDom[i], SpanningTreeParent(i)). | 337 | 8 | // Note that the parents were stored in IDoms and later got invalidated | 338 | 8 | // during path compression in Eval. | 339 | 66 | for (unsigned i = 2; i < NextDFSNum; ++i58 ) { | 340 | 58 | const NodePtr W = NumToNode[i]; | 341 | 58 | auto &WInfo = NodeToInfo[W]; | 342 | 58 | const unsigned SDomNum = NodeToInfo[NumToNode[WInfo.Semi]].DFSNum; | 343 | 58 | NodePtr WIDomCandidate = WInfo.IDom; | 344 | 70 | while (NodeToInfo[WIDomCandidate].DFSNum > SDomNum) | 345 | 12 | WIDomCandidate = NodeToInfo[WIDomCandidate].IDom; | 346 | 58 | | 347 | 58 | WInfo.IDom = WIDomCandidate; | 348 | 58 | } | 349 | 8 | } |
llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<clang::CFGBlock, true> >::runSemiNCA(llvm::DominatorTreeBase<clang::CFGBlock, true>&, unsigned int) Line | Count | Source | 304 | 107 | void runSemiNCA(DomTreeT &DT, const unsigned MinLevel = 0) { | 305 | 107 | const unsigned NextDFSNum(NumToNode.size()); | 306 | 107 | // Initialize IDoms to spanning tree parents. | 307 | 763 | for (unsigned i = 1; i < NextDFSNum; ++i656 ) { | 308 | 656 | const NodePtr V = NumToNode[i]; | 309 | 656 | auto &VInfo = NodeToInfo[V]; | 310 | 656 | VInfo.IDom = NumToNode[VInfo.Parent]; | 311 | 656 | } | 312 | 107 | | 313 | 107 | // Step #1: Calculate the semidominators of all vertices. | 314 | 107 | SmallVector<InfoRec *, 32> EvalStack; | 315 | 656 | for (unsigned i = NextDFSNum - 1; i >= 2; --i549 ) { | 316 | 549 | NodePtr W = NumToNode[i]; | 317 | 549 | auto &WInfo = NodeToInfo[W]; | 318 | 549 | | 319 | 549 | // Initialize the semi dominator to point to the parent node. | 320 | 549 | WInfo.Semi = WInfo.Parent; | 321 | 589 | for (const auto &N : WInfo.ReverseChildren) { | 322 | 589 | if (NodeToInfo.count(N) == 0) // Skip unreachable predecessors. | 323 | 0 | continue; | 324 | 589 | | 325 | 589 | const TreeNodePtr TN = DT.getNode(N); | 326 | 589 | // Skip predecessors whose level is above the subtree we are processing. | 327 | 589 | if (TN && TN->getLevel() < MinLevel0 ) | 328 | 0 | continue; | 329 | 589 | | 330 | 589 | unsigned SemiU = NodeToInfo[eval(N, i + 1, EvalStack)].Semi; | 331 | 589 | if (SemiU < WInfo.Semi) WInfo.Semi = SemiU16 ; | 332 | 589 | } | 333 | 549 | } | 334 | 107 | | 335 | 107 | // Step #2: Explicitly define the immediate dominator of each vertex. | 336 | 107 | // IDom[i] = NCA(SDom[i], SpanningTreeParent(i)). | 337 | 107 | // Note that the parents were stored in IDoms and later got invalidated | 338 | 107 | // during path compression in Eval. | 339 | 656 | for (unsigned i = 2; i < NextDFSNum; ++i549 ) { | 340 | 549 | const NodePtr W = NumToNode[i]; | 341 | 549 | auto &WInfo = NodeToInfo[W]; | 342 | 549 | const unsigned SDomNum = NodeToInfo[NumToNode[WInfo.Semi]].DFSNum; | 343 | 549 | NodePtr WIDomCandidate = WInfo.IDom; | 344 | 569 | while (NodeToInfo[WIDomCandidate].DFSNum > SDomNum) | 345 | 20 | WIDomCandidate = NodeToInfo[WIDomCandidate].IDom; | 346 | 549 | | 347 | 549 | WInfo.IDom = WIDomCandidate; | 348 | 549 | } | 349 | 107 | } |
|
350 | | |
351 | | // PostDominatorTree always has a virtual root that represents a virtual CFG |
352 | | // node that serves as a single exit from the function. All the other exits |
353 | | // (CFG nodes with terminators and nodes in infinite loops are logically |
354 | | // connected to this virtual CFG exit node). |
355 | | // This functions maps a nullptr CFG node to the virtual root tree node. |
356 | 4.22M | void addVirtualRoot() { |
357 | 4.22M | assert(IsPostDom && "Only postdominators have a virtual root"); |
358 | 4.22M | assert(NumToNode.size() == 1 && "SNCAInfo must be freshly constructed"); |
359 | 4.22M | |
360 | 4.22M | auto &BBInfo = NodeToInfo[nullptr]; |
361 | 4.22M | BBInfo.DFSNum = BBInfo.Semi = 1; |
362 | 4.22M | BBInfo.Label = nullptr; |
363 | 4.22M | |
364 | 4.22M | NumToNode.push_back(nullptr); // NumToNode[1] = nullptr; |
365 | 4.22M | } Unexecuted instantiation: llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> >::addVirtualRoot() llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> >::addVirtualRoot() Line | Count | Source | 356 | 3.01M | void addVirtualRoot() { | 357 | 3.01M | assert(IsPostDom && "Only postdominators have a virtual root"); | 358 | 3.01M | assert(NumToNode.size() == 1 && "SNCAInfo must be freshly constructed"); | 359 | 3.01M | | 360 | 3.01M | auto &BBInfo = NodeToInfo[nullptr]; | 361 | 3.01M | BBInfo.DFSNum = BBInfo.Semi = 1; | 362 | 3.01M | BBInfo.Label = nullptr; | 363 | 3.01M | | 364 | 3.01M | NumToNode.push_back(nullptr); // NumToNode[1] = nullptr; | 365 | 3.01M | } |
llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, true> >::addVirtualRoot() Line | Count | Source | 356 | 1.21M | void addVirtualRoot() { | 357 | 1.21M | assert(IsPostDom && "Only postdominators have a virtual root"); | 358 | 1.21M | assert(NumToNode.size() == 1 && "SNCAInfo must be freshly constructed"); | 359 | 1.21M | | 360 | 1.21M | auto &BBInfo = NodeToInfo[nullptr]; | 361 | 1.21M | BBInfo.DFSNum = BBInfo.Semi = 1; | 362 | 1.21M | BBInfo.Label = nullptr; | 363 | 1.21M | | 364 | 1.21M | NumToNode.push_back(nullptr); // NumToNode[1] = nullptr; | 365 | 1.21M | } |
Unexecuted instantiation: llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, false> >::addVirtualRoot() Unexecuted instantiation: llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::VPBlockBase, false> >::addVirtualRoot() llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<clang::CFGBlock, true> >::addVirtualRoot() Line | Count | Source | 356 | 214 | void addVirtualRoot() { | 357 | 214 | assert(IsPostDom && "Only postdominators have a virtual root"); | 358 | 214 | assert(NumToNode.size() == 1 && "SNCAInfo must be freshly constructed"); | 359 | 214 | | 360 | 214 | auto &BBInfo = NodeToInfo[nullptr]; | 361 | 214 | BBInfo.DFSNum = BBInfo.Semi = 1; | 362 | 214 | BBInfo.Label = nullptr; | 363 | 214 | | 364 | 214 | NumToNode.push_back(nullptr); // NumToNode[1] = nullptr; | 365 | 214 | } |
Unexecuted instantiation: llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<clang::CFGBlock, false> >::addVirtualRoot() |
366 | | |
367 | | // For postdominators, nodes with no forward successors are trivial roots that |
368 | | // are always selected as tree roots. Roots with forward successors correspond |
369 | | // to CFG nodes within infinite loops. |
370 | 11.5M | static bool HasForwardSuccessors(const NodePtr N, BatchUpdatePtr BUI) { |
371 | 11.5M | assert(N && "N must be a valid node"); |
372 | 11.5M | return !ChildrenGetter<false>::Get(N, BUI).empty(); |
373 | 11.5M | } Unexecuted instantiation: llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> >::HasForwardSuccessors(llvm::MachineBasicBlock*, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> >::BatchUpdateInfo*) llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> >::HasForwardSuccessors(llvm::MachineBasicBlock*, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> >::BatchUpdateInfo*) Line | Count | Source | 370 | 8.52M | static bool HasForwardSuccessors(const NodePtr N, BatchUpdatePtr BUI) { | 371 | 8.52M | assert(N && "N must be a valid node"); | 372 | 8.52M | return !ChildrenGetter<false>::Get(N, BUI).empty(); | 373 | 8.52M | } |
llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, true> >::HasForwardSuccessors(llvm::BasicBlock*, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, true> >::BatchUpdateInfo*) Line | Count | Source | 370 | 3.06M | static bool HasForwardSuccessors(const NodePtr N, BatchUpdatePtr BUI) { | 371 | 3.06M | assert(N && "N must be a valid node"); | 372 | 3.06M | return !ChildrenGetter<false>::Get(N, BUI).empty(); | 373 | 3.06M | } |
Unexecuted instantiation: llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, false> >::HasForwardSuccessors(llvm::BasicBlock*, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, false> >::BatchUpdateInfo*) Unexecuted instantiation: llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::VPBlockBase, false> >::HasForwardSuccessors(llvm::VPBlockBase*, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::VPBlockBase, false> >::BatchUpdateInfo*) llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<clang::CFGBlock, true> >::HasForwardSuccessors(clang::CFGBlock*, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<clang::CFGBlock, true> >::BatchUpdateInfo*) Line | Count | Source | 370 | 549 | static bool HasForwardSuccessors(const NodePtr N, BatchUpdatePtr BUI) { | 371 | 549 | assert(N && "N must be a valid node"); | 372 | 549 | return !ChildrenGetter<false>::Get(N, BUI).empty(); | 373 | 549 | } |
Unexecuted instantiation: llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<clang::CFGBlock, false> >::HasForwardSuccessors(clang::CFGBlock*, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<clang::CFGBlock, false> >::BatchUpdateInfo*) |
374 | | |
375 | 13.0M | static NodePtr GetEntryNode(const DomTreeT &DT) { |
376 | 13.0M | assert(DT.Parent && "Parent not set"); |
377 | 13.0M | return GraphTraits<typename DomTreeT::ParentPtr>::getEntryNode(DT.Parent); |
378 | 13.0M | } llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> >::GetEntryNode(llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> const&) Line | Count | Source | 375 | 2.61M | static NodePtr GetEntryNode(const DomTreeT &DT) { | 376 | 2.61M | assert(DT.Parent && "Parent not set"); | 377 | 2.61M | return GraphTraits<typename DomTreeT::ParentPtr>::getEntryNode(DT.Parent); | 378 | 2.61M | } |
Unexecuted instantiation: llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> >::GetEntryNode(llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> const&) llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, false> >::GetEntryNode(llvm::DominatorTreeBase<llvm::BasicBlock, false> const&) Line | Count | Source | 375 | 10.3M | static NodePtr GetEntryNode(const DomTreeT &DT) { | 376 | 10.3M | assert(DT.Parent && "Parent not set"); | 377 | 10.3M | return GraphTraits<typename DomTreeT::ParentPtr>::getEntryNode(DT.Parent); | 378 | 10.3M | } |
Unexecuted instantiation: llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, true> >::GetEntryNode(llvm::DominatorTreeBase<llvm::BasicBlock, true> const&) llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::VPBlockBase, false> >::GetEntryNode(llvm::DominatorTreeBase<llvm::VPBlockBase, false> const&) Line | Count | Source | 375 | 28 | static NodePtr GetEntryNode(const DomTreeT &DT) { | 376 | 28 | assert(DT.Parent && "Parent not set"); | 377 | 28 | return GraphTraits<typename DomTreeT::ParentPtr>::getEntryNode(DT.Parent); | 378 | 28 | } |
llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<clang::CFGBlock, false> >::GetEntryNode(llvm::DominatorTreeBase<clang::CFGBlock, false> const&) Line | Count | Source | 375 | 8 | static NodePtr GetEntryNode(const DomTreeT &DT) { | 376 | 8 | assert(DT.Parent && "Parent not set"); | 377 | 8 | return GraphTraits<typename DomTreeT::ParentPtr>::getEntryNode(DT.Parent); | 378 | 8 | } |
Unexecuted instantiation: llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<clang::CFGBlock, true> >::GetEntryNode(llvm::DominatorTreeBase<clang::CFGBlock, true> const&) |
379 | | |
380 | | // Finds all roots without relaying on the set of roots already stored in the |
381 | | // tree. |
382 | | // We define roots to be some non-redundant set of the CFG nodes |
383 | 15.1M | static RootsT FindRoots(const DomTreeT &DT, BatchUpdatePtr BUI) { |
384 | 15.1M | assert(DT.Parent && "Parent pointer is not set"); |
385 | 15.1M | RootsT Roots; |
386 | 15.1M | |
387 | 15.1M | // For dominators, function entry CFG node is always a tree root node. |
388 | 15.1M | if (!IsPostDom) { |
389 | 13.0M | Roots.push_back(GetEntryNode(DT)); |
390 | 13.0M | return Roots; |
391 | 13.0M | } |
392 | 2.11M | |
393 | 2.11M | SemiNCAInfo SNCA(BUI); |
394 | 2.11M | |
395 | 2.11M | // PostDominatorTree always has a virtual root. |
396 | 2.11M | SNCA.addVirtualRoot(); |
397 | 2.11M | unsigned Num = 1; |
398 | 2.11M | |
399 | 2.11M | LLVM_DEBUG(dbgs() << "\t\tLooking for trivial roots\n"); |
400 | 2.11M | |
401 | 2.11M | // Step #1: Find all the trivial roots that are going to will definitely |
402 | 2.11M | // remain tree roots. |
403 | 2.11M | unsigned Total = 0; |
404 | 2.11M | // It may happen that there are some new nodes in the CFG that are result of |
405 | 2.11M | // the ongoing batch update, but we cannot really pretend that they don't |
406 | 2.11M | // exist -- we won't see any outgoing or incoming edges to them, so it's |
407 | 2.11M | // fine to discover them here, as they would end up appearing in the CFG at |
408 | 2.11M | // some point anyway. |
409 | 11.5M | for (const NodePtr N : nodes(DT.Parent)) { |
410 | 11.5M | ++Total; |
411 | 11.5M | // If it has no *successors*, it is definitely a root. |
412 | 11.5M | if (!HasForwardSuccessors(N, BUI)) { |
413 | 2.59M | Roots.push_back(N); |
414 | 2.59M | // Run DFS not to walk this part of CFG later. |
415 | 2.59M | Num = SNCA.runDFS(N, Num, AlwaysDescend, 1); |
416 | 2.59M | LLVM_DEBUG(dbgs() << "Found a new trivial root: " << BlockNamePrinter(N) |
417 | 2.59M | << "\n"); |
418 | 2.59M | LLVM_DEBUG(dbgs() << "Last visited node: " |
419 | 2.59M | << BlockNamePrinter(SNCA.NumToNode[Num]) << "\n"); |
420 | 2.59M | } |
421 | 11.5M | } |
422 | 2.11M | |
423 | 2.11M | LLVM_DEBUG(dbgs() << "\t\tLooking for non-trivial roots\n"); |
424 | 2.11M | |
425 | 2.11M | // Step #2: Find all non-trivial root candidates. Those are CFG nodes that |
426 | 2.11M | // are reverse-unreachable were not visited by previous DFS walks (i.e. CFG |
427 | 2.11M | // nodes in infinite loops). |
428 | 2.11M | bool HasNonTrivialRoots = false; |
429 | 2.11M | // Accounting for the virtual exit, see if we had any reverse-unreachable |
430 | 2.11M | // nodes. |
431 | 2.11M | if (Total + 1 != Num) { |
432 | 1.80k | HasNonTrivialRoots = true; |
433 | 1.80k | // Make another DFS pass over all other nodes to find the |
434 | 1.80k | // reverse-unreachable blocks, and find the furthest paths we'll be able |
435 | 1.80k | // to make. |
436 | 1.80k | // Note that this looks N^2, but it's really 2N worst case, if every node |
437 | 1.80k | // is unreachable. This is because we are still going to only visit each |
438 | 1.80k | // unreachable node once, we may just visit it in two directions, |
439 | 1.80k | // depending on how lucky we get. |
440 | 1.80k | SmallPtrSet<NodePtr, 4> ConnectToExitBlock; |
441 | 18.2k | for (const NodePtr I : nodes(DT.Parent)) { |
442 | 18.2k | if (SNCA.NodeToInfo.count(I) == 0) { |
443 | 1.99k | LLVM_DEBUG(dbgs() |
444 | 1.99k | << "\t\t\tVisiting node " << BlockNamePrinter(I) << "\n"); |
445 | 1.99k | // Find the furthest away we can get by following successors, then |
446 | 1.99k | // follow them in reverse. This gives us some reasonable answer about |
447 | 1.99k | // the post-dom tree inside any infinite loop. In particular, it |
448 | 1.99k | // guarantees we get to the farthest away point along *some* |
449 | 1.99k | // path. This also matches the GCC's behavior. |
450 | 1.99k | // If we really wanted a totally complete picture of dominance inside |
451 | 1.99k | // this infinite loop, we could do it with SCC-like algorithms to find |
452 | 1.99k | // the lowest and highest points in the infinite loop. In theory, it |
453 | 1.99k | // would be nice to give the canonical backedge for the loop, but it's |
454 | 1.99k | // expensive and does not always lead to a minimal set of roots. |
455 | 1.99k | LLVM_DEBUG(dbgs() << "\t\t\tRunning forward DFS\n"); |
456 | 1.99k | |
457 | 1.99k | const unsigned NewNum = SNCA.runDFS<true>(I, Num, AlwaysDescend, Num); |
458 | 1.99k | const NodePtr FurthestAway = SNCA.NumToNode[NewNum]; |
459 | 1.99k | LLVM_DEBUG(dbgs() << "\t\t\tFound a new furthest away node " |
460 | 1.99k | << "(non-trivial root): " |
461 | 1.99k | << BlockNamePrinter(FurthestAway) << "\n"); |
462 | 1.99k | ConnectToExitBlock.insert(FurthestAway); |
463 | 1.99k | Roots.push_back(FurthestAway); |
464 | 1.99k | LLVM_DEBUG(dbgs() << "\t\t\tPrev DFSNum: " << Num << ", new DFSNum: " |
465 | 1.99k | << NewNum << "\n\t\t\tRemoving DFS info\n"); |
466 | 8.11k | for (unsigned i = NewNum; i > Num; --i6.12k ) { |
467 | 6.12k | const NodePtr N = SNCA.NumToNode[i]; |
468 | 6.12k | LLVM_DEBUG(dbgs() << "\t\t\t\tRemoving DFS info for " |
469 | 6.12k | << BlockNamePrinter(N) << "\n"); |
470 | 6.12k | SNCA.NodeToInfo.erase(N); |
471 | 6.12k | SNCA.NumToNode.pop_back(); |
472 | 6.12k | } |
473 | 1.99k | const unsigned PrevNum = Num; |
474 | 1.99k | LLVM_DEBUG(dbgs() << "\t\t\tRunning reverse DFS\n"); |
475 | 1.99k | Num = SNCA.runDFS(FurthestAway, Num, AlwaysDescend, 1); |
476 | 7.89k | for (unsigned i = PrevNum + 1; i <= Num; ++i5.90k ) |
477 | 1.99k | LLVM_DEBUG(dbgs() << "\t\t\t\tfound node " |
478 | 1.99k | << BlockNamePrinter(SNCA.NumToNode[i]) << "\n"); |
479 | 1.99k | } |
480 | 18.2k | } |
481 | 1.80k | } |
482 | 2.11M | |
483 | 2.11M | LLVM_DEBUG(dbgs() << "Total: " << Total << ", Num: " << Num << "\n"); |
484 | 2.11M | LLVM_DEBUG(dbgs() << "Discovered CFG nodes:\n"); |
485 | 2.11M | LLVM_DEBUG(for (size_t i = 0; i <= Num; ++i) dbgs() |
486 | 2.11M | << i << ": " << BlockNamePrinter(SNCA.NumToNode[i]) << "\n"); |
487 | 2.11M | |
488 | 2.11M | assert((Total + 1 == Num) && "Everything should have been visited"); |
489 | 2.11M | |
490 | 2.11M | // Step #3: If we found some non-trivial roots, make them non-redundant. |
491 | 2.11M | if (HasNonTrivialRoots) RemoveRedundantRoots(DT, BUI, Roots)1.80k ; |
492 | 2.11M | |
493 | 2.11M | LLVM_DEBUG(dbgs() << "Found roots: "); |
494 | 2.11M | LLVM_DEBUG(for (auto *Root |
495 | 2.11M | : Roots) dbgs() |
496 | 2.11M | << BlockNamePrinter(Root) << " "); |
497 | 2.11M | LLVM_DEBUG(dbgs() << "\n"); |
498 | 2.11M | |
499 | 2.11M | return Roots; |
500 | 2.11M | } llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> >::FindRoots(llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> const&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> >::BatchUpdateInfo*) Line | Count | Source | 383 | 2.61M | static RootsT FindRoots(const DomTreeT &DT, BatchUpdatePtr BUI) { | 384 | 2.61M | assert(DT.Parent && "Parent pointer is not set"); | 385 | 2.61M | RootsT Roots; | 386 | 2.61M | | 387 | 2.61M | // For dominators, function entry CFG node is always a tree root node. | 388 | 2.61M | if (!IsPostDom) { | 389 | 2.61M | Roots.push_back(GetEntryNode(DT)); | 390 | 2.61M | return Roots; | 391 | 2.61M | } | 392 | 0 | | 393 | 0 | SemiNCAInfo SNCA(BUI); | 394 | 0 |
| 395 | 0 | // PostDominatorTree always has a virtual root. | 396 | 0 | SNCA.addVirtualRoot(); | 397 | 0 | unsigned Num = 1; | 398 | 0 |
| 399 | 0 | LLVM_DEBUG(dbgs() << "\t\tLooking for trivial roots\n"); | 400 | 0 |
| 401 | 0 | // Step #1: Find all the trivial roots that are going to will definitely | 402 | 0 | // remain tree roots. | 403 | 0 | unsigned Total = 0; | 404 | 0 | // It may happen that there are some new nodes in the CFG that are result of | 405 | 0 | // the ongoing batch update, but we cannot really pretend that they don't | 406 | 0 | // exist -- we won't see any outgoing or incoming edges to them, so it's | 407 | 0 | // fine to discover them here, as they would end up appearing in the CFG at | 408 | 0 | // some point anyway. | 409 | 0 | for (const NodePtr N : nodes(DT.Parent)) { | 410 | 0 | ++Total; | 411 | 0 | // If it has no *successors*, it is definitely a root. | 412 | 0 | if (!HasForwardSuccessors(N, BUI)) { | 413 | 0 | Roots.push_back(N); | 414 | 0 | // Run DFS not to walk this part of CFG later. | 415 | 0 | Num = SNCA.runDFS(N, Num, AlwaysDescend, 1); | 416 | 0 | LLVM_DEBUG(dbgs() << "Found a new trivial root: " << BlockNamePrinter(N) | 417 | 0 | << "\n"); | 418 | 0 | LLVM_DEBUG(dbgs() << "Last visited node: " | 419 | 0 | << BlockNamePrinter(SNCA.NumToNode[Num]) << "\n"); | 420 | 0 | } | 421 | 0 | } | 422 | 0 |
| 423 | 0 | LLVM_DEBUG(dbgs() << "\t\tLooking for non-trivial roots\n"); | 424 | 0 |
| 425 | 0 | // Step #2: Find all non-trivial root candidates. Those are CFG nodes that | 426 | 0 | // are reverse-unreachable were not visited by previous DFS walks (i.e. CFG | 427 | 0 | // nodes in infinite loops). | 428 | 0 | bool HasNonTrivialRoots = false; | 429 | 0 | // Accounting for the virtual exit, see if we had any reverse-unreachable | 430 | 0 | // nodes. | 431 | 0 | if (Total + 1 != Num) { | 432 | 0 | HasNonTrivialRoots = true; | 433 | 0 | // Make another DFS pass over all other nodes to find the | 434 | 0 | // reverse-unreachable blocks, and find the furthest paths we'll be able | 435 | 0 | // to make. | 436 | 0 | // Note that this looks N^2, but it's really 2N worst case, if every node | 437 | 0 | // is unreachable. This is because we are still going to only visit each | 438 | 0 | // unreachable node once, we may just visit it in two directions, | 439 | 0 | // depending on how lucky we get. | 440 | 0 | SmallPtrSet<NodePtr, 4> ConnectToExitBlock; | 441 | 0 | for (const NodePtr I : nodes(DT.Parent)) { | 442 | 0 | if (SNCA.NodeToInfo.count(I) == 0) { | 443 | 0 | LLVM_DEBUG(dbgs() | 444 | 0 | << "\t\t\tVisiting node " << BlockNamePrinter(I) << "\n"); | 445 | 0 | // Find the furthest away we can get by following successors, then | 446 | 0 | // follow them in reverse. This gives us some reasonable answer about | 447 | 0 | // the post-dom tree inside any infinite loop. In particular, it | 448 | 0 | // guarantees we get to the farthest away point along *some* | 449 | 0 | // path. This also matches the GCC's behavior. | 450 | 0 | // If we really wanted a totally complete picture of dominance inside | 451 | 0 | // this infinite loop, we could do it with SCC-like algorithms to find | 452 | 0 | // the lowest and highest points in the infinite loop. In theory, it | 453 | 0 | // would be nice to give the canonical backedge for the loop, but it's | 454 | 0 | // expensive and does not always lead to a minimal set of roots. | 455 | 0 | LLVM_DEBUG(dbgs() << "\t\t\tRunning forward DFS\n"); | 456 | 0 |
| 457 | 0 | const unsigned NewNum = SNCA.runDFS<true>(I, Num, AlwaysDescend, Num); | 458 | 0 | const NodePtr FurthestAway = SNCA.NumToNode[NewNum]; | 459 | 0 | LLVM_DEBUG(dbgs() << "\t\t\tFound a new furthest away node " | 460 | 0 | << "(non-trivial root): " | 461 | 0 | << BlockNamePrinter(FurthestAway) << "\n"); | 462 | 0 | ConnectToExitBlock.insert(FurthestAway); | 463 | 0 | Roots.push_back(FurthestAway); | 464 | 0 | LLVM_DEBUG(dbgs() << "\t\t\tPrev DFSNum: " << Num << ", new DFSNum: " | 465 | 0 | << NewNum << "\n\t\t\tRemoving DFS info\n"); | 466 | 0 | for (unsigned i = NewNum; i > Num; --i) { | 467 | 0 | const NodePtr N = SNCA.NumToNode[i]; | 468 | 0 | LLVM_DEBUG(dbgs() << "\t\t\t\tRemoving DFS info for " | 469 | 0 | << BlockNamePrinter(N) << "\n"); | 470 | 0 | SNCA.NodeToInfo.erase(N); | 471 | 0 | SNCA.NumToNode.pop_back(); | 472 | 0 | } | 473 | 0 | const unsigned PrevNum = Num; | 474 | 0 | LLVM_DEBUG(dbgs() << "\t\t\tRunning reverse DFS\n"); | 475 | 0 | Num = SNCA.runDFS(FurthestAway, Num, AlwaysDescend, 1); | 476 | 0 | for (unsigned i = PrevNum + 1; i <= Num; ++i) | 477 | 0 | LLVM_DEBUG(dbgs() << "\t\t\t\tfound node " | 478 | 0 | << BlockNamePrinter(SNCA.NumToNode[i]) << "\n"); | 479 | 0 | } | 480 | 0 | } | 481 | 0 | } | 482 | 0 |
| 483 | 0 | LLVM_DEBUG(dbgs() << "Total: " << Total << ", Num: " << Num << "\n"); | 484 | 0 | LLVM_DEBUG(dbgs() << "Discovered CFG nodes:\n"); | 485 | 0 | LLVM_DEBUG(for (size_t i = 0; i <= Num; ++i) dbgs() | 486 | 0 | << i << ": " << BlockNamePrinter(SNCA.NumToNode[i]) << "\n"); | 487 | 0 |
| 488 | 0 | assert((Total + 1 == Num) && "Everything should have been visited"); | 489 | 0 |
| 490 | 0 | // Step #3: If we found some non-trivial roots, make them non-redundant. | 491 | 0 | if (HasNonTrivialRoots) RemoveRedundantRoots(DT, BUI, Roots); | 492 | 0 |
| 493 | 0 | LLVM_DEBUG(dbgs() << "Found roots: "); | 494 | 0 | LLVM_DEBUG(for (auto *Root | 495 | 0 | : Roots) dbgs() | 496 | 0 | << BlockNamePrinter(Root) << " "); | 497 | 0 | LLVM_DEBUG(dbgs() << "\n"); | 498 | 0 |
| 499 | 0 | return Roots; | 500 | 0 | } |
llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> >::FindRoots(llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> const&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> >::BatchUpdateInfo*) Line | Count | Source | 383 | 1.50M | static RootsT FindRoots(const DomTreeT &DT, BatchUpdatePtr BUI) { | 384 | 1.50M | assert(DT.Parent && "Parent pointer is not set"); | 385 | 1.50M | RootsT Roots; | 386 | 1.50M | | 387 | 1.50M | // For dominators, function entry CFG node is always a tree root node. | 388 | 1.50M | if (!IsPostDom) { | 389 | 0 | Roots.push_back(GetEntryNode(DT)); | 390 | 0 | return Roots; | 391 | 0 | } | 392 | 1.50M | | 393 | 1.50M | SemiNCAInfo SNCA(BUI); | 394 | 1.50M | | 395 | 1.50M | // PostDominatorTree always has a virtual root. | 396 | 1.50M | SNCA.addVirtualRoot(); | 397 | 1.50M | unsigned Num = 1; | 398 | 1.50M | | 399 | 1.50M | LLVM_DEBUG(dbgs() << "\t\tLooking for trivial roots\n"); | 400 | 1.50M | | 401 | 1.50M | // Step #1: Find all the trivial roots that are going to will definitely | 402 | 1.50M | // remain tree roots. | 403 | 1.50M | unsigned Total = 0; | 404 | 1.50M | // It may happen that there are some new nodes in the CFG that are result of | 405 | 1.50M | // the ongoing batch update, but we cannot really pretend that they don't | 406 | 1.50M | // exist -- we won't see any outgoing or incoming edges to them, so it's | 407 | 1.50M | // fine to discover them here, as they would end up appearing in the CFG at | 408 | 1.50M | // some point anyway. | 409 | 8.52M | for (const NodePtr N : nodes(DT.Parent)) { | 410 | 8.52M | ++Total; | 411 | 8.52M | // If it has no *successors*, it is definitely a root. | 412 | 8.52M | if (!HasForwardSuccessors(N, BUI)) { | 413 | 1.92M | Roots.push_back(N); | 414 | 1.92M | // Run DFS not to walk this part of CFG later. | 415 | 1.92M | Num = SNCA.runDFS(N, Num, AlwaysDescend, 1); | 416 | 1.92M | LLVM_DEBUG(dbgs() << "Found a new trivial root: " << BlockNamePrinter(N) | 417 | 1.92M | << "\n"); | 418 | 1.92M | LLVM_DEBUG(dbgs() << "Last visited node: " | 419 | 1.92M | << BlockNamePrinter(SNCA.NumToNode[Num]) << "\n"); | 420 | 1.92M | } | 421 | 8.52M | } | 422 | 1.50M | | 423 | 1.50M | LLVM_DEBUG(dbgs() << "\t\tLooking for non-trivial roots\n"); | 424 | 1.50M | | 425 | 1.50M | // Step #2: Find all non-trivial root candidates. Those are CFG nodes that | 426 | 1.50M | // are reverse-unreachable were not visited by previous DFS walks (i.e. CFG | 427 | 1.50M | // nodes in infinite loops). | 428 | 1.50M | bool HasNonTrivialRoots = false; | 429 | 1.50M | // Accounting for the virtual exit, see if we had any reverse-unreachable | 430 | 1.50M | // nodes. | 431 | 1.50M | if (Total + 1 != Num) { | 432 | 1.29k | HasNonTrivialRoots = true; | 433 | 1.29k | // Make another DFS pass over all other nodes to find the | 434 | 1.29k | // reverse-unreachable blocks, and find the furthest paths we'll be able | 435 | 1.29k | // to make. | 436 | 1.29k | // Note that this looks N^2, but it's really 2N worst case, if every node | 437 | 1.29k | // is unreachable. This is because we are still going to only visit each | 438 | 1.29k | // unreachable node once, we may just visit it in two directions, | 439 | 1.29k | // depending on how lucky we get. | 440 | 1.29k | SmallPtrSet<NodePtr, 4> ConnectToExitBlock; | 441 | 9.47k | for (const NodePtr I : nodes(DT.Parent)) { | 442 | 9.47k | if (SNCA.NodeToInfo.count(I) == 0) { | 443 | 1.38k | LLVM_DEBUG(dbgs() | 444 | 1.38k | << "\t\t\tVisiting node " << BlockNamePrinter(I) << "\n"); | 445 | 1.38k | // Find the furthest away we can get by following successors, then | 446 | 1.38k | // follow them in reverse. This gives us some reasonable answer about | 447 | 1.38k | // the post-dom tree inside any infinite loop. In particular, it | 448 | 1.38k | // guarantees we get to the farthest away point along *some* | 449 | 1.38k | // path. This also matches the GCC's behavior. | 450 | 1.38k | // If we really wanted a totally complete picture of dominance inside | 451 | 1.38k | // this infinite loop, we could do it with SCC-like algorithms to find | 452 | 1.38k | // the lowest and highest points in the infinite loop. In theory, it | 453 | 1.38k | // would be nice to give the canonical backedge for the loop, but it's | 454 | 1.38k | // expensive and does not always lead to a minimal set of roots. | 455 | 1.38k | LLVM_DEBUG(dbgs() << "\t\t\tRunning forward DFS\n"); | 456 | 1.38k | | 457 | 1.38k | const unsigned NewNum = SNCA.runDFS<true>(I, Num, AlwaysDescend, Num); | 458 | 1.38k | const NodePtr FurthestAway = SNCA.NumToNode[NewNum]; | 459 | 1.38k | LLVM_DEBUG(dbgs() << "\t\t\tFound a new furthest away node " | 460 | 1.38k | << "(non-trivial root): " | 461 | 1.38k | << BlockNamePrinter(FurthestAway) << "\n"); | 462 | 1.38k | ConnectToExitBlock.insert(FurthestAway); | 463 | 1.38k | Roots.push_back(FurthestAway); | 464 | 1.38k | LLVM_DEBUG(dbgs() << "\t\t\tPrev DFSNum: " << Num << ", new DFSNum: " | 465 | 1.38k | << NewNum << "\n\t\t\tRemoving DFS info\n"); | 466 | 5.85k | for (unsigned i = NewNum; i > Num; --i4.46k ) { | 467 | 4.46k | const NodePtr N = SNCA.NumToNode[i]; | 468 | 4.46k | LLVM_DEBUG(dbgs() << "\t\t\t\tRemoving DFS info for " | 469 | 4.46k | << BlockNamePrinter(N) << "\n"); | 470 | 4.46k | SNCA.NodeToInfo.erase(N); | 471 | 4.46k | SNCA.NumToNode.pop_back(); | 472 | 4.46k | } | 473 | 1.38k | const unsigned PrevNum = Num; | 474 | 1.38k | LLVM_DEBUG(dbgs() << "\t\t\tRunning reverse DFS\n"); | 475 | 1.38k | Num = SNCA.runDFS(FurthestAway, Num, AlwaysDescend, 1); | 476 | 5.69k | for (unsigned i = PrevNum + 1; i <= Num; ++i4.30k ) | 477 | 1.38k | LLVM_DEBUG(dbgs() << "\t\t\t\tfound node " | 478 | 1.38k | << BlockNamePrinter(SNCA.NumToNode[i]) << "\n"); | 479 | 1.38k | } | 480 | 9.47k | } | 481 | 1.29k | } | 482 | 1.50M | | 483 | 1.50M | LLVM_DEBUG(dbgs() << "Total: " << Total << ", Num: " << Num << "\n"); | 484 | 1.50M | LLVM_DEBUG(dbgs() << "Discovered CFG nodes:\n"); | 485 | 1.50M | LLVM_DEBUG(for (size_t i = 0; i <= Num; ++i) dbgs() | 486 | 1.50M | << i << ": " << BlockNamePrinter(SNCA.NumToNode[i]) << "\n"); | 487 | 1.50M | | 488 | 1.50M | assert((Total + 1 == Num) && "Everything should have been visited"); | 489 | 1.50M | | 490 | 1.50M | // Step #3: If we found some non-trivial roots, make them non-redundant. | 491 | 1.50M | if (HasNonTrivialRoots) RemoveRedundantRoots(DT, BUI, Roots)1.29k ; | 492 | 1.50M | | 493 | 1.50M | LLVM_DEBUG(dbgs() << "Found roots: "); | 494 | 1.50M | LLVM_DEBUG(for (auto *Root | 495 | 1.50M | : Roots) dbgs() | 496 | 1.50M | << BlockNamePrinter(Root) << " "); | 497 | 1.50M | LLVM_DEBUG(dbgs() << "\n"); | 498 | 1.50M | | 499 | 1.50M | return Roots; | 500 | 1.50M | } |
llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, false> >::FindRoots(llvm::DominatorTreeBase<llvm::BasicBlock, false> const&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, false> >::BatchUpdateInfo*) Line | Count | Source | 383 | 10.3M | static RootsT FindRoots(const DomTreeT &DT, BatchUpdatePtr BUI) { | 384 | 10.3M | assert(DT.Parent && "Parent pointer is not set"); | 385 | 10.3M | RootsT Roots; | 386 | 10.3M | | 387 | 10.3M | // For dominators, function entry CFG node is always a tree root node. | 388 | 10.3M | if (!IsPostDom) { | 389 | 10.3M | Roots.push_back(GetEntryNode(DT)); | 390 | 10.3M | return Roots; | 391 | 10.3M | } | 392 | 0 | | 393 | 0 | SemiNCAInfo SNCA(BUI); | 394 | 0 |
| 395 | 0 | // PostDominatorTree always has a virtual root. | 396 | 0 | SNCA.addVirtualRoot(); | 397 | 0 | unsigned Num = 1; | 398 | 0 |
| 399 | 0 | LLVM_DEBUG(dbgs() << "\t\tLooking for trivial roots\n"); | 400 | 0 |
| 401 | 0 | // Step #1: Find all the trivial roots that are going to will definitely | 402 | 0 | // remain tree roots. | 403 | 0 | unsigned Total = 0; | 404 | 0 | // It may happen that there are some new nodes in the CFG that are result of | 405 | 0 | // the ongoing batch update, but we cannot really pretend that they don't | 406 | 0 | // exist -- we won't see any outgoing or incoming edges to them, so it's | 407 | 0 | // fine to discover them here, as they would end up appearing in the CFG at | 408 | 0 | // some point anyway. | 409 | 0 | for (const NodePtr N : nodes(DT.Parent)) { | 410 | 0 | ++Total; | 411 | 0 | // If it has no *successors*, it is definitely a root. | 412 | 0 | if (!HasForwardSuccessors(N, BUI)) { | 413 | 0 | Roots.push_back(N); | 414 | 0 | // Run DFS not to walk this part of CFG later. | 415 | 0 | Num = SNCA.runDFS(N, Num, AlwaysDescend, 1); | 416 | 0 | LLVM_DEBUG(dbgs() << "Found a new trivial root: " << BlockNamePrinter(N) | 417 | 0 | << "\n"); | 418 | 0 | LLVM_DEBUG(dbgs() << "Last visited node: " | 419 | 0 | << BlockNamePrinter(SNCA.NumToNode[Num]) << "\n"); | 420 | 0 | } | 421 | 0 | } | 422 | 0 |
| 423 | 0 | LLVM_DEBUG(dbgs() << "\t\tLooking for non-trivial roots\n"); | 424 | 0 |
| 425 | 0 | // Step #2: Find all non-trivial root candidates. Those are CFG nodes that | 426 | 0 | // are reverse-unreachable were not visited by previous DFS walks (i.e. CFG | 427 | 0 | // nodes in infinite loops). | 428 | 0 | bool HasNonTrivialRoots = false; | 429 | 0 | // Accounting for the virtual exit, see if we had any reverse-unreachable | 430 | 0 | // nodes. | 431 | 0 | if (Total + 1 != Num) { | 432 | 0 | HasNonTrivialRoots = true; | 433 | 0 | // Make another DFS pass over all other nodes to find the | 434 | 0 | // reverse-unreachable blocks, and find the furthest paths we'll be able | 435 | 0 | // to make. | 436 | 0 | // Note that this looks N^2, but it's really 2N worst case, if every node | 437 | 0 | // is unreachable. This is because we are still going to only visit each | 438 | 0 | // unreachable node once, we may just visit it in two directions, | 439 | 0 | // depending on how lucky we get. | 440 | 0 | SmallPtrSet<NodePtr, 4> ConnectToExitBlock; | 441 | 0 | for (const NodePtr I : nodes(DT.Parent)) { | 442 | 0 | if (SNCA.NodeToInfo.count(I) == 0) { | 443 | 0 | LLVM_DEBUG(dbgs() | 444 | 0 | << "\t\t\tVisiting node " << BlockNamePrinter(I) << "\n"); | 445 | 0 | // Find the furthest away we can get by following successors, then | 446 | 0 | // follow them in reverse. This gives us some reasonable answer about | 447 | 0 | // the post-dom tree inside any infinite loop. In particular, it | 448 | 0 | // guarantees we get to the farthest away point along *some* | 449 | 0 | // path. This also matches the GCC's behavior. | 450 | 0 | // If we really wanted a totally complete picture of dominance inside | 451 | 0 | // this infinite loop, we could do it with SCC-like algorithms to find | 452 | 0 | // the lowest and highest points in the infinite loop. In theory, it | 453 | 0 | // would be nice to give the canonical backedge for the loop, but it's | 454 | 0 | // expensive and does not always lead to a minimal set of roots. | 455 | 0 | LLVM_DEBUG(dbgs() << "\t\t\tRunning forward DFS\n"); | 456 | 0 |
| 457 | 0 | const unsigned NewNum = SNCA.runDFS<true>(I, Num, AlwaysDescend, Num); | 458 | 0 | const NodePtr FurthestAway = SNCA.NumToNode[NewNum]; | 459 | 0 | LLVM_DEBUG(dbgs() << "\t\t\tFound a new furthest away node " | 460 | 0 | << "(non-trivial root): " | 461 | 0 | << BlockNamePrinter(FurthestAway) << "\n"); | 462 | 0 | ConnectToExitBlock.insert(FurthestAway); | 463 | 0 | Roots.push_back(FurthestAway); | 464 | 0 | LLVM_DEBUG(dbgs() << "\t\t\tPrev DFSNum: " << Num << ", new DFSNum: " | 465 | 0 | << NewNum << "\n\t\t\tRemoving DFS info\n"); | 466 | 0 | for (unsigned i = NewNum; i > Num; --i) { | 467 | 0 | const NodePtr N = SNCA.NumToNode[i]; | 468 | 0 | LLVM_DEBUG(dbgs() << "\t\t\t\tRemoving DFS info for " | 469 | 0 | << BlockNamePrinter(N) << "\n"); | 470 | 0 | SNCA.NodeToInfo.erase(N); | 471 | 0 | SNCA.NumToNode.pop_back(); | 472 | 0 | } | 473 | 0 | const unsigned PrevNum = Num; | 474 | 0 | LLVM_DEBUG(dbgs() << "\t\t\tRunning reverse DFS\n"); | 475 | 0 | Num = SNCA.runDFS(FurthestAway, Num, AlwaysDescend, 1); | 476 | 0 | for (unsigned i = PrevNum + 1; i <= Num; ++i) | 477 | 0 | LLVM_DEBUG(dbgs() << "\t\t\t\tfound node " | 478 | 0 | << BlockNamePrinter(SNCA.NumToNode[i]) << "\n"); | 479 | 0 | } | 480 | 0 | } | 481 | 0 | } | 482 | 0 |
| 483 | 0 | LLVM_DEBUG(dbgs() << "Total: " << Total << ", Num: " << Num << "\n"); | 484 | 0 | LLVM_DEBUG(dbgs() << "Discovered CFG nodes:\n"); | 485 | 0 | LLVM_DEBUG(for (size_t i = 0; i <= Num; ++i) dbgs() | 486 | 0 | << i << ": " << BlockNamePrinter(SNCA.NumToNode[i]) << "\n"); | 487 | 0 |
| 488 | 0 | assert((Total + 1 == Num) && "Everything should have been visited"); | 489 | 0 |
| 490 | 0 | // Step #3: If we found some non-trivial roots, make them non-redundant. | 491 | 0 | if (HasNonTrivialRoots) RemoveRedundantRoots(DT, BUI, Roots); | 492 | 0 |
| 493 | 0 | LLVM_DEBUG(dbgs() << "Found roots: "); | 494 | 0 | LLVM_DEBUG(for (auto *Root | 495 | 0 | : Roots) dbgs() | 496 | 0 | << BlockNamePrinter(Root) << " "); | 497 | 0 | LLVM_DEBUG(dbgs() << "\n"); | 498 | 0 |
| 499 | 0 | return Roots; | 500 | 0 | } |
llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, true> >::FindRoots(llvm::DominatorTreeBase<llvm::BasicBlock, true> const&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, true> >::BatchUpdateInfo*) Line | Count | Source | 383 | 605k | static RootsT FindRoots(const DomTreeT &DT, BatchUpdatePtr BUI) { | 384 | 605k | assert(DT.Parent && "Parent pointer is not set"); | 385 | 605k | RootsT Roots; | 386 | 605k | | 387 | 605k | // For dominators, function entry CFG node is always a tree root node. | 388 | 605k | if (!IsPostDom) { | 389 | 0 | Roots.push_back(GetEntryNode(DT)); | 390 | 0 | return Roots; | 391 | 0 | } | 392 | 605k | | 393 | 605k | SemiNCAInfo SNCA(BUI); | 394 | 605k | | 395 | 605k | // PostDominatorTree always has a virtual root. | 396 | 605k | SNCA.addVirtualRoot(); | 397 | 605k | unsigned Num = 1; | 398 | 605k | | 399 | 605k | LLVM_DEBUG(dbgs() << "\t\tLooking for trivial roots\n"); | 400 | 605k | | 401 | 605k | // Step #1: Find all the trivial roots that are going to will definitely | 402 | 605k | // remain tree roots. | 403 | 605k | unsigned Total = 0; | 404 | 605k | // It may happen that there are some new nodes in the CFG that are result of | 405 | 605k | // the ongoing batch update, but we cannot really pretend that they don't | 406 | 605k | // exist -- we won't see any outgoing or incoming edges to them, so it's | 407 | 605k | // fine to discover them here, as they would end up appearing in the CFG at | 408 | 605k | // some point anyway. | 409 | 3.06M | for (const NodePtr N : nodes(DT.Parent)) { | 410 | 3.06M | ++Total; | 411 | 3.06M | // If it has no *successors*, it is definitely a root. | 412 | 3.06M | if (!HasForwardSuccessors(N, BUI)) { | 413 | 663k | Roots.push_back(N); | 414 | 663k | // Run DFS not to walk this part of CFG later. | 415 | 663k | Num = SNCA.runDFS(N, Num, AlwaysDescend, 1); | 416 | 663k | LLVM_DEBUG(dbgs() << "Found a new trivial root: " << BlockNamePrinter(N) | 417 | 663k | << "\n"); | 418 | 663k | LLVM_DEBUG(dbgs() << "Last visited node: " | 419 | 663k | << BlockNamePrinter(SNCA.NumToNode[Num]) << "\n"); | 420 | 663k | } | 421 | 3.06M | } | 422 | 605k | | 423 | 605k | LLVM_DEBUG(dbgs() << "\t\tLooking for non-trivial roots\n"); | 424 | 605k | | 425 | 605k | // Step #2: Find all non-trivial root candidates. Those are CFG nodes that | 426 | 605k | // are reverse-unreachable were not visited by previous DFS walks (i.e. CFG | 427 | 605k | // nodes in infinite loops). | 428 | 605k | bool HasNonTrivialRoots = false; | 429 | 605k | // Accounting for the virtual exit, see if we had any reverse-unreachable | 430 | 605k | // nodes. | 431 | 605k | if (Total + 1 != Num) { | 432 | 509 | HasNonTrivialRoots = true; | 433 | 509 | // Make another DFS pass over all other nodes to find the | 434 | 509 | // reverse-unreachable blocks, and find the furthest paths we'll be able | 435 | 509 | // to make. | 436 | 509 | // Note that this looks N^2, but it's really 2N worst case, if every node | 437 | 509 | // is unreachable. This is because we are still going to only visit each | 438 | 509 | // unreachable node once, we may just visit it in two directions, | 439 | 509 | // depending on how lucky we get. | 440 | 509 | SmallPtrSet<NodePtr, 4> ConnectToExitBlock; | 441 | 8.76k | for (const NodePtr I : nodes(DT.Parent)) { | 442 | 8.76k | if (SNCA.NodeToInfo.count(I) == 0) { | 443 | 606 | LLVM_DEBUG(dbgs() | 444 | 606 | << "\t\t\tVisiting node " << BlockNamePrinter(I) << "\n"); | 445 | 606 | // Find the furthest away we can get by following successors, then | 446 | 606 | // follow them in reverse. This gives us some reasonable answer about | 447 | 606 | // the post-dom tree inside any infinite loop. In particular, it | 448 | 606 | // guarantees we get to the farthest away point along *some* | 449 | 606 | // path. This also matches the GCC's behavior. | 450 | 606 | // If we really wanted a totally complete picture of dominance inside | 451 | 606 | // this infinite loop, we could do it with SCC-like algorithms to find | 452 | 606 | // the lowest and highest points in the infinite loop. In theory, it | 453 | 606 | // would be nice to give the canonical backedge for the loop, but it's | 454 | 606 | // expensive and does not always lead to a minimal set of roots. | 455 | 606 | LLVM_DEBUG(dbgs() << "\t\t\tRunning forward DFS\n"); | 456 | 606 | | 457 | 606 | const unsigned NewNum = SNCA.runDFS<true>(I, Num, AlwaysDescend, Num); | 458 | 606 | const NodePtr FurthestAway = SNCA.NumToNode[NewNum]; | 459 | 606 | LLVM_DEBUG(dbgs() << "\t\t\tFound a new furthest away node " | 460 | 606 | << "(non-trivial root): " | 461 | 606 | << BlockNamePrinter(FurthestAway) << "\n"); | 462 | 606 | ConnectToExitBlock.insert(FurthestAway); | 463 | 606 | Roots.push_back(FurthestAway); | 464 | 606 | LLVM_DEBUG(dbgs() << "\t\t\tPrev DFSNum: " << Num << ", new DFSNum: " | 465 | 606 | << NewNum << "\n\t\t\tRemoving DFS info\n"); | 466 | 2.26k | for (unsigned i = NewNum; i > Num; --i1.65k ) { | 467 | 1.65k | const NodePtr N = SNCA.NumToNode[i]; | 468 | 1.65k | LLVM_DEBUG(dbgs() << "\t\t\t\tRemoving DFS info for " | 469 | 1.65k | << BlockNamePrinter(N) << "\n"); | 470 | 1.65k | SNCA.NodeToInfo.erase(N); | 471 | 1.65k | SNCA.NumToNode.pop_back(); | 472 | 1.65k | } | 473 | 606 | const unsigned PrevNum = Num; | 474 | 606 | LLVM_DEBUG(dbgs() << "\t\t\tRunning reverse DFS\n"); | 475 | 606 | Num = SNCA.runDFS(FurthestAway, Num, AlwaysDescend, 1); | 476 | 2.20k | for (unsigned i = PrevNum + 1; i <= Num; ++i1.59k ) | 477 | 606 | LLVM_DEBUG(dbgs() << "\t\t\t\tfound node " | 478 | 606 | << BlockNamePrinter(SNCA.NumToNode[i]) << "\n"); | 479 | 606 | } | 480 | 8.76k | } | 481 | 509 | } | 482 | 605k | | 483 | 605k | LLVM_DEBUG(dbgs() << "Total: " << Total << ", Num: " << Num << "\n"); | 484 | 605k | LLVM_DEBUG(dbgs() << "Discovered CFG nodes:\n"); | 485 | 605k | LLVM_DEBUG(for (size_t i = 0; i <= Num; ++i) dbgs() | 486 | 605k | << i << ": " << BlockNamePrinter(SNCA.NumToNode[i]) << "\n"); | 487 | 605k | | 488 | 605k | assert((Total + 1 == Num) && "Everything should have been visited"); | 489 | 605k | | 490 | 605k | // Step #3: If we found some non-trivial roots, make them non-redundant. | 491 | 605k | if (HasNonTrivialRoots) RemoveRedundantRoots(DT, BUI, Roots)509 ; | 492 | 605k | | 493 | 605k | LLVM_DEBUG(dbgs() << "Found roots: "); | 494 | 605k | LLVM_DEBUG(for (auto *Root | 495 | 605k | : Roots) dbgs() | 496 | 605k | << BlockNamePrinter(Root) << " "); | 497 | 605k | LLVM_DEBUG(dbgs() << "\n"); | 498 | 605k | | 499 | 605k | return Roots; | 500 | 605k | } |
llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::VPBlockBase, false> >::FindRoots(llvm::DominatorTreeBase<llvm::VPBlockBase, false> const&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::VPBlockBase, false> >::BatchUpdateInfo*) Line | Count | Source | 383 | 28 | static RootsT FindRoots(const DomTreeT &DT, BatchUpdatePtr BUI) { | 384 | 28 | assert(DT.Parent && "Parent pointer is not set"); | 385 | 28 | RootsT Roots; | 386 | 28 | | 387 | 28 | // For dominators, function entry CFG node is always a tree root node. | 388 | 28 | if (!IsPostDom) { | 389 | 28 | Roots.push_back(GetEntryNode(DT)); | 390 | 28 | return Roots; | 391 | 28 | } | 392 | 0 | | 393 | 0 | SemiNCAInfo SNCA(BUI); | 394 | 0 |
| 395 | 0 | // PostDominatorTree always has a virtual root. | 396 | 0 | SNCA.addVirtualRoot(); | 397 | 0 | unsigned Num = 1; | 398 | 0 |
| 399 | 0 | LLVM_DEBUG(dbgs() << "\t\tLooking for trivial roots\n"); | 400 | 0 |
| 401 | 0 | // Step #1: Find all the trivial roots that are going to will definitely | 402 | 0 | // remain tree roots. | 403 | 0 | unsigned Total = 0; | 404 | 0 | // It may happen that there are some new nodes in the CFG that are result of | 405 | 0 | // the ongoing batch update, but we cannot really pretend that they don't | 406 | 0 | // exist -- we won't see any outgoing or incoming edges to them, so it's | 407 | 0 | // fine to discover them here, as they would end up appearing in the CFG at | 408 | 0 | // some point anyway. | 409 | 0 | for (const NodePtr N : nodes(DT.Parent)) { | 410 | 0 | ++Total; | 411 | 0 | // If it has no *successors*, it is definitely a root. | 412 | 0 | if (!HasForwardSuccessors(N, BUI)) { | 413 | 0 | Roots.push_back(N); | 414 | 0 | // Run DFS not to walk this part of CFG later. | 415 | 0 | Num = SNCA.runDFS(N, Num, AlwaysDescend, 1); | 416 | 0 | LLVM_DEBUG(dbgs() << "Found a new trivial root: " << BlockNamePrinter(N) | 417 | 0 | << "\n"); | 418 | 0 | LLVM_DEBUG(dbgs() << "Last visited node: " | 419 | 0 | << BlockNamePrinter(SNCA.NumToNode[Num]) << "\n"); | 420 | 0 | } | 421 | 0 | } | 422 | 0 |
| 423 | 0 | LLVM_DEBUG(dbgs() << "\t\tLooking for non-trivial roots\n"); | 424 | 0 |
| 425 | 0 | // Step #2: Find all non-trivial root candidates. Those are CFG nodes that | 426 | 0 | // are reverse-unreachable were not visited by previous DFS walks (i.e. CFG | 427 | 0 | // nodes in infinite loops). | 428 | 0 | bool HasNonTrivialRoots = false; | 429 | 0 | // Accounting for the virtual exit, see if we had any reverse-unreachable | 430 | 0 | // nodes. | 431 | 0 | if (Total + 1 != Num) { | 432 | 0 | HasNonTrivialRoots = true; | 433 | 0 | // Make another DFS pass over all other nodes to find the | 434 | 0 | // reverse-unreachable blocks, and find the furthest paths we'll be able | 435 | 0 | // to make. | 436 | 0 | // Note that this looks N^2, but it's really 2N worst case, if every node | 437 | 0 | // is unreachable. This is because we are still going to only visit each | 438 | 0 | // unreachable node once, we may just visit it in two directions, | 439 | 0 | // depending on how lucky we get. | 440 | 0 | SmallPtrSet<NodePtr, 4> ConnectToExitBlock; | 441 | 0 | for (const NodePtr I : nodes(DT.Parent)) { | 442 | 0 | if (SNCA.NodeToInfo.count(I) == 0) { | 443 | 0 | LLVM_DEBUG(dbgs() | 444 | 0 | << "\t\t\tVisiting node " << BlockNamePrinter(I) << "\n"); | 445 | 0 | // Find the furthest away we can get by following successors, then | 446 | 0 | // follow them in reverse. This gives us some reasonable answer about | 447 | 0 | // the post-dom tree inside any infinite loop. In particular, it | 448 | 0 | // guarantees we get to the farthest away point along *some* | 449 | 0 | // path. This also matches the GCC's behavior. | 450 | 0 | // If we really wanted a totally complete picture of dominance inside | 451 | 0 | // this infinite loop, we could do it with SCC-like algorithms to find | 452 | 0 | // the lowest and highest points in the infinite loop. In theory, it | 453 | 0 | // would be nice to give the canonical backedge for the loop, but it's | 454 | 0 | // expensive and does not always lead to a minimal set of roots. | 455 | 0 | LLVM_DEBUG(dbgs() << "\t\t\tRunning forward DFS\n"); | 456 | 0 |
| 457 | 0 | const unsigned NewNum = SNCA.runDFS<true>(I, Num, AlwaysDescend, Num); | 458 | 0 | const NodePtr FurthestAway = SNCA.NumToNode[NewNum]; | 459 | 0 | LLVM_DEBUG(dbgs() << "\t\t\tFound a new furthest away node " | 460 | 0 | << "(non-trivial root): " | 461 | 0 | << BlockNamePrinter(FurthestAway) << "\n"); | 462 | 0 | ConnectToExitBlock.insert(FurthestAway); | 463 | 0 | Roots.push_back(FurthestAway); | 464 | 0 | LLVM_DEBUG(dbgs() << "\t\t\tPrev DFSNum: " << Num << ", new DFSNum: " | 465 | 0 | << NewNum << "\n\t\t\tRemoving DFS info\n"); | 466 | 0 | for (unsigned i = NewNum; i > Num; --i) { | 467 | 0 | const NodePtr N = SNCA.NumToNode[i]; | 468 | 0 | LLVM_DEBUG(dbgs() << "\t\t\t\tRemoving DFS info for " | 469 | 0 | << BlockNamePrinter(N) << "\n"); | 470 | 0 | SNCA.NodeToInfo.erase(N); | 471 | 0 | SNCA.NumToNode.pop_back(); | 472 | 0 | } | 473 | 0 | const unsigned PrevNum = Num; | 474 | 0 | LLVM_DEBUG(dbgs() << "\t\t\tRunning reverse DFS\n"); | 475 | 0 | Num = SNCA.runDFS(FurthestAway, Num, AlwaysDescend, 1); | 476 | 0 | for (unsigned i = PrevNum + 1; i <= Num; ++i) | 477 | 0 | LLVM_DEBUG(dbgs() << "\t\t\t\tfound node " | 478 | 0 | << BlockNamePrinter(SNCA.NumToNode[i]) << "\n"); | 479 | 0 | } | 480 | 0 | } | 481 | 0 | } | 482 | 0 |
| 483 | 0 | LLVM_DEBUG(dbgs() << "Total: " << Total << ", Num: " << Num << "\n"); | 484 | 0 | LLVM_DEBUG(dbgs() << "Discovered CFG nodes:\n"); | 485 | 0 | LLVM_DEBUG(for (size_t i = 0; i <= Num; ++i) dbgs() | 486 | 0 | << i << ": " << BlockNamePrinter(SNCA.NumToNode[i]) << "\n"); | 487 | 0 |
| 488 | 0 | assert((Total + 1 == Num) && "Everything should have been visited"); | 489 | 0 |
| 490 | 0 | // Step #3: If we found some non-trivial roots, make them non-redundant. | 491 | 0 | if (HasNonTrivialRoots) RemoveRedundantRoots(DT, BUI, Roots); | 492 | 0 |
| 493 | 0 | LLVM_DEBUG(dbgs() << "Found roots: "); | 494 | 0 | LLVM_DEBUG(for (auto *Root | 495 | 0 | : Roots) dbgs() | 496 | 0 | << BlockNamePrinter(Root) << " "); | 497 | 0 | LLVM_DEBUG(dbgs() << "\n"); | 498 | 0 |
| 499 | 0 | return Roots; | 500 | 0 | } |
llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<clang::CFGBlock, false> >::FindRoots(llvm::DominatorTreeBase<clang::CFGBlock, false> const&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<clang::CFGBlock, false> >::BatchUpdateInfo*) Line | Count | Source | 383 | 8 | static RootsT FindRoots(const DomTreeT &DT, BatchUpdatePtr BUI) { | 384 | 8 | assert(DT.Parent && "Parent pointer is not set"); | 385 | 8 | RootsT Roots; | 386 | 8 | | 387 | 8 | // For dominators, function entry CFG node is always a tree root node. | 388 | 8 | if (!IsPostDom) { | 389 | 8 | Roots.push_back(GetEntryNode(DT)); | 390 | 8 | return Roots; | 391 | 8 | } | 392 | 0 | | 393 | 0 | SemiNCAInfo SNCA(BUI); | 394 | 0 |
| 395 | 0 | // PostDominatorTree always has a virtual root. | 396 | 0 | SNCA.addVirtualRoot(); | 397 | 0 | unsigned Num = 1; | 398 | 0 |
| 399 | 0 | LLVM_DEBUG(dbgs() << "\t\tLooking for trivial roots\n"); | 400 | 0 |
| 401 | 0 | // Step #1: Find all the trivial roots that are going to will definitely | 402 | 0 | // remain tree roots. | 403 | 0 | unsigned Total = 0; | 404 | 0 | // It may happen that there are some new nodes in the CFG that are result of | 405 | 0 | // the ongoing batch update, but we cannot really pretend that they don't | 406 | 0 | // exist -- we won't see any outgoing or incoming edges to them, so it's | 407 | 0 | // fine to discover them here, as they would end up appearing in the CFG at | 408 | 0 | // some point anyway. | 409 | 0 | for (const NodePtr N : nodes(DT.Parent)) { | 410 | 0 | ++Total; | 411 | 0 | // If it has no *successors*, it is definitely a root. | 412 | 0 | if (!HasForwardSuccessors(N, BUI)) { | 413 | 0 | Roots.push_back(N); | 414 | 0 | // Run DFS not to walk this part of CFG later. | 415 | 0 | Num = SNCA.runDFS(N, Num, AlwaysDescend, 1); | 416 | 0 | LLVM_DEBUG(dbgs() << "Found a new trivial root: " << BlockNamePrinter(N) | 417 | 0 | << "\n"); | 418 | 0 | LLVM_DEBUG(dbgs() << "Last visited node: " | 419 | 0 | << BlockNamePrinter(SNCA.NumToNode[Num]) << "\n"); | 420 | 0 | } | 421 | 0 | } | 422 | 0 |
| 423 | 0 | LLVM_DEBUG(dbgs() << "\t\tLooking for non-trivial roots\n"); | 424 | 0 |
| 425 | 0 | // Step #2: Find all non-trivial root candidates. Those are CFG nodes that | 426 | 0 | // are reverse-unreachable were not visited by previous DFS walks (i.e. CFG | 427 | 0 | // nodes in infinite loops). | 428 | 0 | bool HasNonTrivialRoots = false; | 429 | 0 | // Accounting for the virtual exit, see if we had any reverse-unreachable | 430 | 0 | // nodes. | 431 | 0 | if (Total + 1 != Num) { | 432 | 0 | HasNonTrivialRoots = true; | 433 | 0 | // Make another DFS pass over all other nodes to find the | 434 | 0 | // reverse-unreachable blocks, and find the furthest paths we'll be able | 435 | 0 | // to make. | 436 | 0 | // Note that this looks N^2, but it's really 2N worst case, if every node | 437 | 0 | // is unreachable. This is because we are still going to only visit each | 438 | 0 | // unreachable node once, we may just visit it in two directions, | 439 | 0 | // depending on how lucky we get. | 440 | 0 | SmallPtrSet<NodePtr, 4> ConnectToExitBlock; | 441 | 0 | for (const NodePtr I : nodes(DT.Parent)) { | 442 | 0 | if (SNCA.NodeToInfo.count(I) == 0) { | 443 | 0 | LLVM_DEBUG(dbgs() | 444 | 0 | << "\t\t\tVisiting node " << BlockNamePrinter(I) << "\n"); | 445 | 0 | // Find the furthest away we can get by following successors, then | 446 | 0 | // follow them in reverse. This gives us some reasonable answer about | 447 | 0 | // the post-dom tree inside any infinite loop. In particular, it | 448 | 0 | // guarantees we get to the farthest away point along *some* | 449 | 0 | // path. This also matches the GCC's behavior. | 450 | 0 | // If we really wanted a totally complete picture of dominance inside | 451 | 0 | // this infinite loop, we could do it with SCC-like algorithms to find | 452 | 0 | // the lowest and highest points in the infinite loop. In theory, it | 453 | 0 | // would be nice to give the canonical backedge for the loop, but it's | 454 | 0 | // expensive and does not always lead to a minimal set of roots. | 455 | 0 | LLVM_DEBUG(dbgs() << "\t\t\tRunning forward DFS\n"); | 456 | 0 |
| 457 | 0 | const unsigned NewNum = SNCA.runDFS<true>(I, Num, AlwaysDescend, Num); | 458 | 0 | const NodePtr FurthestAway = SNCA.NumToNode[NewNum]; | 459 | 0 | LLVM_DEBUG(dbgs() << "\t\t\tFound a new furthest away node " | 460 | 0 | << "(non-trivial root): " | 461 | 0 | << BlockNamePrinter(FurthestAway) << "\n"); | 462 | 0 | ConnectToExitBlock.insert(FurthestAway); | 463 | 0 | Roots.push_back(FurthestAway); | 464 | 0 | LLVM_DEBUG(dbgs() << "\t\t\tPrev DFSNum: " << Num << ", new DFSNum: " | 465 | 0 | << NewNum << "\n\t\t\tRemoving DFS info\n"); | 466 | 0 | for (unsigned i = NewNum; i > Num; --i) { | 467 | 0 | const NodePtr N = SNCA.NumToNode[i]; | 468 | 0 | LLVM_DEBUG(dbgs() << "\t\t\t\tRemoving DFS info for " | 469 | 0 | << BlockNamePrinter(N) << "\n"); | 470 | 0 | SNCA.NodeToInfo.erase(N); | 471 | 0 | SNCA.NumToNode.pop_back(); | 472 | 0 | } | 473 | 0 | const unsigned PrevNum = Num; | 474 | 0 | LLVM_DEBUG(dbgs() << "\t\t\tRunning reverse DFS\n"); | 475 | 0 | Num = SNCA.runDFS(FurthestAway, Num, AlwaysDescend, 1); | 476 | 0 | for (unsigned i = PrevNum + 1; i <= Num; ++i) | 477 | 0 | LLVM_DEBUG(dbgs() << "\t\t\t\tfound node " | 478 | 0 | << BlockNamePrinter(SNCA.NumToNode[i]) << "\n"); | 479 | 0 | } | 480 | 0 | } | 481 | 0 | } | 482 | 0 |
| 483 | 0 | LLVM_DEBUG(dbgs() << "Total: " << Total << ", Num: " << Num << "\n"); | 484 | 0 | LLVM_DEBUG(dbgs() << "Discovered CFG nodes:\n"); | 485 | 0 | LLVM_DEBUG(for (size_t i = 0; i <= Num; ++i) dbgs() | 486 | 0 | << i << ": " << BlockNamePrinter(SNCA.NumToNode[i]) << "\n"); | 487 | 0 |
| 488 | 0 | assert((Total + 1 == Num) && "Everything should have been visited"); | 489 | 0 |
| 490 | 0 | // Step #3: If we found some non-trivial roots, make them non-redundant. | 491 | 0 | if (HasNonTrivialRoots) RemoveRedundantRoots(DT, BUI, Roots); | 492 | 0 |
| 493 | 0 | LLVM_DEBUG(dbgs() << "Found roots: "); | 494 | 0 | LLVM_DEBUG(for (auto *Root | 495 | 0 | : Roots) dbgs() | 496 | 0 | << BlockNamePrinter(Root) << " "); | 497 | 0 | LLVM_DEBUG(dbgs() << "\n"); | 498 | 0 |
| 499 | 0 | return Roots; | 500 | 0 | } |
llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<clang::CFGBlock, true> >::FindRoots(llvm::DominatorTreeBase<clang::CFGBlock, true> const&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<clang::CFGBlock, true> >::BatchUpdateInfo*) Line | Count | Source | 383 | 107 | static RootsT FindRoots(const DomTreeT &DT, BatchUpdatePtr BUI) { | 384 | 107 | assert(DT.Parent && "Parent pointer is not set"); | 385 | 107 | RootsT Roots; | 386 | 107 | | 387 | 107 | // For dominators, function entry CFG node is always a tree root node. | 388 | 107 | if (!IsPostDom) { | 389 | 0 | Roots.push_back(GetEntryNode(DT)); | 390 | 0 | return Roots; | 391 | 0 | } | 392 | 107 | | 393 | 107 | SemiNCAInfo SNCA(BUI); | 394 | 107 | | 395 | 107 | // PostDominatorTree always has a virtual root. | 396 | 107 | SNCA.addVirtualRoot(); | 397 | 107 | unsigned Num = 1; | 398 | 107 | | 399 | 107 | LLVM_DEBUG(dbgs() << "\t\tLooking for trivial roots\n"); | 400 | 107 | | 401 | 107 | // Step #1: Find all the trivial roots that are going to will definitely | 402 | 107 | // remain tree roots. | 403 | 107 | unsigned Total = 0; | 404 | 107 | // It may happen that there are some new nodes in the CFG that are result of | 405 | 107 | // the ongoing batch update, but we cannot really pretend that they don't | 406 | 107 | // exist -- we won't see any outgoing or incoming edges to them, so it's | 407 | 107 | // fine to discover them here, as they would end up appearing in the CFG at | 408 | 107 | // some point anyway. | 409 | 549 | for (const NodePtr N : nodes(DT.Parent)) { | 410 | 549 | ++Total; | 411 | 549 | // If it has no *successors*, it is definitely a root. | 412 | 549 | if (!HasForwardSuccessors(N, BUI)) { | 413 | 107 | Roots.push_back(N); | 414 | 107 | // Run DFS not to walk this part of CFG later. | 415 | 107 | Num = SNCA.runDFS(N, Num, AlwaysDescend, 1); | 416 | 107 | LLVM_DEBUG(dbgs() << "Found a new trivial root: " << BlockNamePrinter(N) | 417 | 107 | << "\n"); | 418 | 107 | LLVM_DEBUG(dbgs() << "Last visited node: " | 419 | 107 | << BlockNamePrinter(SNCA.NumToNode[Num]) << "\n"); | 420 | 107 | } | 421 | 549 | } | 422 | 107 | | 423 | 107 | LLVM_DEBUG(dbgs() << "\t\tLooking for non-trivial roots\n"); | 424 | 107 | | 425 | 107 | // Step #2: Find all non-trivial root candidates. Those are CFG nodes that | 426 | 107 | // are reverse-unreachable were not visited by previous DFS walks (i.e. CFG | 427 | 107 | // nodes in infinite loops). | 428 | 107 | bool HasNonTrivialRoots = false; | 429 | 107 | // Accounting for the virtual exit, see if we had any reverse-unreachable | 430 | 107 | // nodes. | 431 | 107 | if (Total + 1 != Num) { | 432 | 0 | HasNonTrivialRoots = true; | 433 | 0 | // Make another DFS pass over all other nodes to find the | 434 | 0 | // reverse-unreachable blocks, and find the furthest paths we'll be able | 435 | 0 | // to make. | 436 | 0 | // Note that this looks N^2, but it's really 2N worst case, if every node | 437 | 0 | // is unreachable. This is because we are still going to only visit each | 438 | 0 | // unreachable node once, we may just visit it in two directions, | 439 | 0 | // depending on how lucky we get. | 440 | 0 | SmallPtrSet<NodePtr, 4> ConnectToExitBlock; | 441 | 0 | for (const NodePtr I : nodes(DT.Parent)) { | 442 | 0 | if (SNCA.NodeToInfo.count(I) == 0) { | 443 | 0 | LLVM_DEBUG(dbgs() | 444 | 0 | << "\t\t\tVisiting node " << BlockNamePrinter(I) << "\n"); | 445 | 0 | // Find the furthest away we can get by following successors, then | 446 | 0 | // follow them in reverse. This gives us some reasonable answer about | 447 | 0 | // the post-dom tree inside any infinite loop. In particular, it | 448 | 0 | // guarantees we get to the farthest away point along *some* | 449 | 0 | // path. This also matches the GCC's behavior. | 450 | 0 | // If we really wanted a totally complete picture of dominance inside | 451 | 0 | // this infinite loop, we could do it with SCC-like algorithms to find | 452 | 0 | // the lowest and highest points in the infinite loop. In theory, it | 453 | 0 | // would be nice to give the canonical backedge for the loop, but it's | 454 | 0 | // expensive and does not always lead to a minimal set of roots. | 455 | 0 | LLVM_DEBUG(dbgs() << "\t\t\tRunning forward DFS\n"); | 456 | 0 |
| 457 | 0 | const unsigned NewNum = SNCA.runDFS<true>(I, Num, AlwaysDescend, Num); | 458 | 0 | const NodePtr FurthestAway = SNCA.NumToNode[NewNum]; | 459 | 0 | LLVM_DEBUG(dbgs() << "\t\t\tFound a new furthest away node " | 460 | 0 | << "(non-trivial root): " | 461 | 0 | << BlockNamePrinter(FurthestAway) << "\n"); | 462 | 0 | ConnectToExitBlock.insert(FurthestAway); | 463 | 0 | Roots.push_back(FurthestAway); | 464 | 0 | LLVM_DEBUG(dbgs() << "\t\t\tPrev DFSNum: " << Num << ", new DFSNum: " | 465 | 0 | << NewNum << "\n\t\t\tRemoving DFS info\n"); | 466 | 0 | for (unsigned i = NewNum; i > Num; --i) { | 467 | 0 | const NodePtr N = SNCA.NumToNode[i]; | 468 | 0 | LLVM_DEBUG(dbgs() << "\t\t\t\tRemoving DFS info for " | 469 | 0 | << BlockNamePrinter(N) << "\n"); | 470 | 0 | SNCA.NodeToInfo.erase(N); | 471 | 0 | SNCA.NumToNode.pop_back(); | 472 | 0 | } | 473 | 0 | const unsigned PrevNum = Num; | 474 | 0 | LLVM_DEBUG(dbgs() << "\t\t\tRunning reverse DFS\n"); | 475 | 0 | Num = SNCA.runDFS(FurthestAway, Num, AlwaysDescend, 1); | 476 | 0 | for (unsigned i = PrevNum + 1; i <= Num; ++i) | 477 | 0 | LLVM_DEBUG(dbgs() << "\t\t\t\tfound node " | 478 | 0 | << BlockNamePrinter(SNCA.NumToNode[i]) << "\n"); | 479 | 0 | } | 480 | 0 | } | 481 | 0 | } | 482 | 107 | | 483 | 107 | LLVM_DEBUG(dbgs() << "Total: " << Total << ", Num: " << Num << "\n"); | 484 | 107 | LLVM_DEBUG(dbgs() << "Discovered CFG nodes:\n"); | 485 | 107 | LLVM_DEBUG(for (size_t i = 0; i <= Num; ++i) dbgs() | 486 | 107 | << i << ": " << BlockNamePrinter(SNCA.NumToNode[i]) << "\n"); | 487 | 107 | | 488 | 107 | assert((Total + 1 == Num) && "Everything should have been visited"); | 489 | 107 | | 490 | 107 | // Step #3: If we found some non-trivial roots, make them non-redundant. | 491 | 107 | if (HasNonTrivialRoots) RemoveRedundantRoots(DT, BUI, Roots)0 ; | 492 | 107 | | 493 | 107 | LLVM_DEBUG(dbgs() << "Found roots: "); | 494 | 107 | LLVM_DEBUG(for (auto *Root | 495 | 107 | : Roots) dbgs() | 496 | 107 | << BlockNamePrinter(Root) << " "); | 497 | 107 | LLVM_DEBUG(dbgs() << "\n"); | 498 | 107 | | 499 | 107 | return Roots; | 500 | 107 | } |
|
501 | | |
502 | | // This function only makes sense for postdominators. |
503 | | // We define roots to be some set of CFG nodes where (reverse) DFS walks have |
504 | | // to start in order to visit all the CFG nodes (including the |
505 | | // reverse-unreachable ones). |
506 | | // When the search for non-trivial roots is done it may happen that some of |
507 | | // the non-trivial roots are reverse-reachable from other non-trivial roots, |
508 | | // which makes them redundant. This function removes them from the set of |
509 | | // input roots. |
510 | | static void RemoveRedundantRoots(const DomTreeT &DT, BatchUpdatePtr BUI, |
511 | 1.80k | RootsT &Roots) { |
512 | 1.80k | assert(IsPostDom && "This function is for postdominators only"); |
513 | 1.80k | LLVM_DEBUG(dbgs() << "Removing redundant roots\n"); |
514 | 1.80k | |
515 | 1.80k | SemiNCAInfo SNCA(BUI); |
516 | 1.80k | |
517 | 5.08k | for (unsigned i = 0; i < Roots.size(); ++i3.28k ) { |
518 | 3.28k | auto &Root = Roots[i]; |
519 | 3.28k | // Trivial roots are always non-redundant. |
520 | 3.28k | if (!HasForwardSuccessors(Root, BUI)) continue1.29k ; |
521 | 1.99k | LLVM_DEBUG(dbgs() << "\tChecking if " << BlockNamePrinter(Root) |
522 | 1.99k | << " remains a root\n"); |
523 | 1.99k | SNCA.clear(); |
524 | 1.99k | // Do a forward walk looking for the other roots. |
525 | 1.99k | const unsigned Num = SNCA.runDFS<true>(Root, 0, AlwaysDescend, 0); |
526 | 1.99k | // Skip the start node and begin from the second one (note that DFS uses |
527 | 1.99k | // 1-based indexing). |
528 | 3.95k | for (unsigned x = 2; x <= Num; ++x1.96k ) { |
529 | 2.04k | const NodePtr N = SNCA.NumToNode[x]; |
530 | 2.04k | // If we wound another root in a (forward) DFS walk, remove the current |
531 | 2.04k | // root from the set of roots, as it is reverse-reachable from the other |
532 | 2.04k | // one. |
533 | 2.04k | if (llvm::find(Roots, N) != Roots.end()) { |
534 | 79 | LLVM_DEBUG(dbgs() << "\tForward DFS walk found another root " |
535 | 79 | << BlockNamePrinter(N) << "\n\tRemoving root " |
536 | 79 | << BlockNamePrinter(Root) << "\n"); |
537 | 79 | std::swap(Root, Roots.back()); |
538 | 79 | Roots.pop_back(); |
539 | 79 | |
540 | 79 | // Root at the back takes the current root's place. |
541 | 79 | // Start the next loop iteration with the same index. |
542 | 79 | --i; |
543 | 79 | break; |
544 | 79 | } |
545 | 2.04k | } |
546 | 1.99k | } |
547 | 1.80k | } Unexecuted instantiation: llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> >::RemoveRedundantRoots(llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> const&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> >::BatchUpdateInfo*, llvm::SmallVector<llvm::MachineBasicBlock*, 1u>&) llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> >::RemoveRedundantRoots(llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> const&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> >::BatchUpdateInfo*, llvm::SmallVector<llvm::MachineBasicBlock*, 4u>&) Line | Count | Source | 511 | 1.29k | RootsT &Roots) { | 512 | 1.29k | assert(IsPostDom && "This function is for postdominators only"); | 513 | 1.29k | LLVM_DEBUG(dbgs() << "Removing redundant roots\n"); | 514 | 1.29k | | 515 | 1.29k | SemiNCAInfo SNCA(BUI); | 516 | 1.29k | | 517 | 3.42k | for (unsigned i = 0; i < Roots.size(); ++i2.13k ) { | 518 | 2.13k | auto &Root = Roots[i]; | 519 | 2.13k | // Trivial roots are always non-redundant. | 520 | 2.13k | if (!HasForwardSuccessors(Root, BUI)) continue744 ; | 521 | 1.38k | LLVM_DEBUG(dbgs() << "\tChecking if " << BlockNamePrinter(Root) | 522 | 1.38k | << " remains a root\n"); | 523 | 1.38k | SNCA.clear(); | 524 | 1.38k | // Do a forward walk looking for the other roots. | 525 | 1.38k | const unsigned Num = SNCA.runDFS<true>(Root, 0, AlwaysDescend, 0); | 526 | 1.38k | // Skip the start node and begin from the second one (note that DFS uses | 527 | 1.38k | // 1-based indexing). | 528 | 2.85k | for (unsigned x = 2; x <= Num; ++x1.47k ) { | 529 | 1.51k | const NodePtr N = SNCA.NumToNode[x]; | 530 | 1.51k | // If we wound another root in a (forward) DFS walk, remove the current | 531 | 1.51k | // root from the set of roots, as it is reverse-reachable from the other | 532 | 1.51k | // one. | 533 | 1.51k | if (llvm::find(Roots, N) != Roots.end()) { | 534 | 39 | LLVM_DEBUG(dbgs() << "\tForward DFS walk found another root " | 535 | 39 | << BlockNamePrinter(N) << "\n\tRemoving root " | 536 | 39 | << BlockNamePrinter(Root) << "\n"); | 537 | 39 | std::swap(Root, Roots.back()); | 538 | 39 | Roots.pop_back(); | 539 | 39 | | 540 | 39 | // Root at the back takes the current root's place. | 541 | 39 | // Start the next loop iteration with the same index. | 542 | 39 | --i; | 543 | 39 | break; | 544 | 39 | } | 545 | 1.51k | } | 546 | 1.38k | } | 547 | 1.29k | } |
llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, true> >::RemoveRedundantRoots(llvm::DominatorTreeBase<llvm::BasicBlock, true> const&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, true> >::BatchUpdateInfo*, llvm::SmallVector<llvm::BasicBlock*, 4u>&) Line | Count | Source | 511 | 509 | RootsT &Roots) { | 512 | 509 | assert(IsPostDom && "This function is for postdominators only"); | 513 | 509 | LLVM_DEBUG(dbgs() << "Removing redundant roots\n"); | 514 | 509 | | 515 | 509 | SemiNCAInfo SNCA(BUI); | 516 | 509 | | 517 | 1.66k | for (unsigned i = 0; i < Roots.size(); ++i1.15k ) { | 518 | 1.15k | auto &Root = Roots[i]; | 519 | 1.15k | // Trivial roots are always non-redundant. | 520 | 1.15k | if (!HasForwardSuccessors(Root, BUI)) continue547 ; | 521 | 606 | LLVM_DEBUG(dbgs() << "\tChecking if " << BlockNamePrinter(Root) | 522 | 606 | << " remains a root\n"); | 523 | 606 | SNCA.clear(); | 524 | 606 | // Do a forward walk looking for the other roots. | 525 | 606 | const unsigned Num = SNCA.runDFS<true>(Root, 0, AlwaysDescend, 0); | 526 | 606 | // Skip the start node and begin from the second one (note that DFS uses | 527 | 606 | // 1-based indexing). | 528 | 1.10k | for (unsigned x = 2; x <= Num; ++x495 ) { | 529 | 535 | const NodePtr N = SNCA.NumToNode[x]; | 530 | 535 | // If we wound another root in a (forward) DFS walk, remove the current | 531 | 535 | // root from the set of roots, as it is reverse-reachable from the other | 532 | 535 | // one. | 533 | 535 | if (llvm::find(Roots, N) != Roots.end()) { | 534 | 40 | LLVM_DEBUG(dbgs() << "\tForward DFS walk found another root " | 535 | 40 | << BlockNamePrinter(N) << "\n\tRemoving root " | 536 | 40 | << BlockNamePrinter(Root) << "\n"); | 537 | 40 | std::swap(Root, Roots.back()); | 538 | 40 | Roots.pop_back(); | 539 | 40 | | 540 | 40 | // Root at the back takes the current root's place. | 541 | 40 | // Start the next loop iteration with the same index. | 542 | 40 | --i; | 543 | 40 | break; | 544 | 40 | } | 545 | 535 | } | 546 | 606 | } | 547 | 509 | } |
Unexecuted instantiation: llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, false> >::RemoveRedundantRoots(llvm::DominatorTreeBase<llvm::BasicBlock, false> const&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, false> >::BatchUpdateInfo*, llvm::SmallVector<llvm::BasicBlock*, 1u>&) Unexecuted instantiation: llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::VPBlockBase, false> >::RemoveRedundantRoots(llvm::DominatorTreeBase<llvm::VPBlockBase, false> const&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::VPBlockBase, false> >::BatchUpdateInfo*, llvm::SmallVector<llvm::VPBlockBase*, 1u>&) Unexecuted instantiation: llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<clang::CFGBlock, true> >::RemoveRedundantRoots(llvm::DominatorTreeBase<clang::CFGBlock, true> const&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<clang::CFGBlock, true> >::BatchUpdateInfo*, llvm::SmallVector<clang::CFGBlock*, 4u>&) Unexecuted instantiation: llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<clang::CFGBlock, false> >::RemoveRedundantRoots(llvm::DominatorTreeBase<clang::CFGBlock, false> const&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<clang::CFGBlock, false> >::BatchUpdateInfo*, llvm::SmallVector<clang::CFGBlock*, 1u>&) |
548 | | |
549 | | template <typename DescendCondition> |
550 | 15.1M | void doFullDFSWalk(const DomTreeT &DT, DescendCondition DC) { |
551 | 15.1M | if (!IsPostDom) { |
552 | 13.0M | assert(DT.Roots.size() == 1 && "Dominators should have a singe root"); |
553 | 13.0M | runDFS(DT.Roots[0], 0, DC, 0); |
554 | 13.0M | return; |
555 | 13.0M | } |
556 | 2.11M | |
557 | 2.11M | addVirtualRoot(); |
558 | 2.11M | unsigned Num = 1; |
559 | 2.60M | for (const NodePtr Root : DT.Roots) Num = runDFS(Root, Num, DC, 0); |
560 | 2.11M | } void llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> >::doFullDFSWalk<bool (*)(llvm::MachineBasicBlock*, llvm::MachineBasicBlock*)>(llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> const&, bool (*)(llvm::MachineBasicBlock*, llvm::MachineBasicBlock*)) Line | Count | Source | 550 | 2.61M | void doFullDFSWalk(const DomTreeT &DT, DescendCondition DC) { | 551 | 2.61M | if (!IsPostDom) { | 552 | 2.61M | assert(DT.Roots.size() == 1 && "Dominators should have a singe root"); | 553 | 2.61M | runDFS(DT.Roots[0], 0, DC, 0); | 554 | 2.61M | return; | 555 | 2.61M | } | 556 | 0 | | 557 | 0 | addVirtualRoot(); | 558 | 0 | unsigned Num = 1; | 559 | 0 | for (const NodePtr Root : DT.Roots) Num = runDFS(Root, Num, DC, 0); | 560 | 0 | } |
Unexecuted instantiation: void llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> >::doFullDFSWalk<llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> >::verifyParentProperty(llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> const&)::'lambda'(llvm::MachineBasicBlock*, llvm::MachineBasicBlock*)>(llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> const&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> >::verifyParentProperty(llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> const&)::'lambda'(llvm::MachineBasicBlock*, llvm::MachineBasicBlock*)) Unexecuted instantiation: void llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> >::doFullDFSWalk<llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> >::verifySiblingProperty(llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> const&)::'lambda'(llvm::MachineBasicBlock*, llvm::MachineBasicBlock*)>(llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> const&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> >::verifySiblingProperty(llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> const&)::'lambda'(llvm::MachineBasicBlock*, llvm::MachineBasicBlock*)) void llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> >::doFullDFSWalk<bool (*)(llvm::MachineBasicBlock*, llvm::MachineBasicBlock*)>(llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> const&, bool (*)(llvm::MachineBasicBlock*, llvm::MachineBasicBlock*)) Line | Count | Source | 550 | 1.50M | void doFullDFSWalk(const DomTreeT &DT, DescendCondition DC) { | 551 | 1.50M | if (!IsPostDom) { | 552 | 0 | assert(DT.Roots.size() == 1 && "Dominators should have a singe root"); | 553 | 0 | runDFS(DT.Roots[0], 0, DC, 0); | 554 | 0 | return; | 555 | 0 | } | 556 | 1.50M | | 557 | 1.50M | addVirtualRoot(); | 558 | 1.50M | unsigned Num = 1; | 559 | 1.92M | for (const NodePtr Root : DT.Roots) Num = runDFS(Root, Num, DC, 0); | 560 | 1.50M | } |
Unexecuted instantiation: void llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> >::doFullDFSWalk<llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> >::verifyParentProperty(llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> const&)::'lambda'(llvm::MachineBasicBlock*, llvm::MachineBasicBlock*)>(llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> const&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> >::verifyParentProperty(llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> const&)::'lambda'(llvm::MachineBasicBlock*, llvm::MachineBasicBlock*)) Unexecuted instantiation: void llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> >::doFullDFSWalk<llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> >::verifySiblingProperty(llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> const&)::'lambda'(llvm::MachineBasicBlock*, llvm::MachineBasicBlock*)>(llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> const&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> >::verifySiblingProperty(llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> const&)::'lambda'(llvm::MachineBasicBlock*, llvm::MachineBasicBlock*)) void llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, false> >::doFullDFSWalk<bool (*)(llvm::BasicBlock*, llvm::BasicBlock*)>(llvm::DominatorTreeBase<llvm::BasicBlock, false> const&, bool (*)(llvm::BasicBlock*, llvm::BasicBlock*)) Line | Count | Source | 550 | 10.3M | void doFullDFSWalk(const DomTreeT &DT, DescendCondition DC) { | 551 | 10.3M | if (!IsPostDom) { | 552 | 10.3M | assert(DT.Roots.size() == 1 && "Dominators should have a singe root"); | 553 | 10.3M | runDFS(DT.Roots[0], 0, DC, 0); | 554 | 10.3M | return; | 555 | 10.3M | } | 556 | 0 | | 557 | 0 | addVirtualRoot(); | 558 | 0 | unsigned Num = 1; | 559 | 0 | for (const NodePtr Root : DT.Roots) Num = runDFS(Root, Num, DC, 0); | 560 | 0 | } |
void llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, true> >::doFullDFSWalk<bool (*)(llvm::BasicBlock*, llvm::BasicBlock*)>(llvm::DominatorTreeBase<llvm::BasicBlock, true> const&, bool (*)(llvm::BasicBlock*, llvm::BasicBlock*)) Line | Count | Source | 550 | 605k | void doFullDFSWalk(const DomTreeT &DT, DescendCondition DC) { | 551 | 605k | if (!IsPostDom) { | 552 | 0 | assert(DT.Roots.size() == 1 && "Dominators should have a singe root"); | 553 | 0 | runDFS(DT.Roots[0], 0, DC, 0); | 554 | 0 | return; | 555 | 0 | } | 556 | 605k | | 557 | 605k | addVirtualRoot(); | 558 | 605k | unsigned Num = 1; | 559 | 663k | for (const NodePtr Root : DT.Roots) Num = runDFS(Root, Num, DC, 0); | 560 | 605k | } |
void llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, false> >::doFullDFSWalk<llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, false> >::verifyParentProperty(llvm::DominatorTreeBase<llvm::BasicBlock, false> const&)::'lambda'(llvm::BasicBlock*, llvm::BasicBlock*)>(llvm::DominatorTreeBase<llvm::BasicBlock, false> const&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, false> >::verifyParentProperty(llvm::DominatorTreeBase<llvm::BasicBlock, false> const&)::'lambda'(llvm::BasicBlock*, llvm::BasicBlock*)) Line | Count | Source | 550 | 1.73k | void doFullDFSWalk(const DomTreeT &DT, DescendCondition DC) { | 551 | 1.73k | if (!IsPostDom) { | 552 | 1.73k | assert(DT.Roots.size() == 1 && "Dominators should have a singe root"); | 553 | 1.73k | runDFS(DT.Roots[0], 0, DC, 0); | 554 | 1.73k | return; | 555 | 1.73k | } | 556 | 0 | | 557 | 0 | addVirtualRoot(); | 558 | 0 | unsigned Num = 1; | 559 | 0 | for (const NodePtr Root : DT.Roots) Num = runDFS(Root, Num, DC, 0); | 560 | 0 | } |
void llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, false> >::doFullDFSWalk<llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, false> >::verifySiblingProperty(llvm::DominatorTreeBase<llvm::BasicBlock, false> const&)::'lambda'(llvm::BasicBlock*, llvm::BasicBlock*)>(llvm::DominatorTreeBase<llvm::BasicBlock, false> const&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, false> >::verifySiblingProperty(llvm::DominatorTreeBase<llvm::BasicBlock, false> const&)::'lambda'(llvm::BasicBlock*, llvm::BasicBlock*)) Line | Count | Source | 550 | 2.46k | void doFullDFSWalk(const DomTreeT &DT, DescendCondition DC) { | 551 | 2.46k | if (!IsPostDom) { | 552 | 2.46k | assert(DT.Roots.size() == 1 && "Dominators should have a singe root"); | 553 | 2.46k | runDFS(DT.Roots[0], 0, DC, 0); | 554 | 2.46k | return; | 555 | 2.46k | } | 556 | 0 | | 557 | 0 | addVirtualRoot(); | 558 | 0 | unsigned Num = 1; | 559 | 0 | for (const NodePtr Root : DT.Roots) Num = runDFS(Root, Num, DC, 0); | 560 | 0 | } |
void llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, true> >::doFullDFSWalk<llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, true> >::verifyParentProperty(llvm::DominatorTreeBase<llvm::BasicBlock, true> const&)::'lambda'(llvm::BasicBlock*, llvm::BasicBlock*)>(llvm::DominatorTreeBase<llvm::BasicBlock, true> const&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, true> >::verifyParentProperty(llvm::DominatorTreeBase<llvm::BasicBlock, true> const&)::'lambda'(llvm::BasicBlock*, llvm::BasicBlock*)) Line | Count | Source | 550 | 1.70k | void doFullDFSWalk(const DomTreeT &DT, DescendCondition DC) { | 551 | 1.70k | if (!IsPostDom) { | 552 | 0 | assert(DT.Roots.size() == 1 && "Dominators should have a singe root"); | 553 | 0 | runDFS(DT.Roots[0], 0, DC, 0); | 554 | 0 | return; | 555 | 0 | } | 556 | 1.70k | | 557 | 1.70k | addVirtualRoot(); | 558 | 1.70k | unsigned Num = 1; | 559 | 5.13k | for (const NodePtr Root : DT.Roots) Num = runDFS(Root, Num, DC, 0); | 560 | 1.70k | } |
void llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, true> >::doFullDFSWalk<llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, true> >::verifySiblingProperty(llvm::DominatorTreeBase<llvm::BasicBlock, true> const&)::'lambda'(llvm::BasicBlock*, llvm::BasicBlock*)>(llvm::DominatorTreeBase<llvm::BasicBlock, true> const&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, true> >::verifySiblingProperty(llvm::DominatorTreeBase<llvm::BasicBlock, true> const&)::'lambda'(llvm::BasicBlock*, llvm::BasicBlock*)) Line | Count | Source | 550 | 2.05k | void doFullDFSWalk(const DomTreeT &DT, DescendCondition DC) { | 551 | 2.05k | if (!IsPostDom) { | 552 | 0 | assert(DT.Roots.size() == 1 && "Dominators should have a singe root"); | 553 | 0 | runDFS(DT.Roots[0], 0, DC, 0); | 554 | 0 | return; | 555 | 0 | } | 556 | 2.05k | | 557 | 2.05k | addVirtualRoot(); | 558 | 2.05k | unsigned Num = 1; | 559 | 6.04k | for (const NodePtr Root : DT.Roots) Num = runDFS(Root, Num, DC, 0); | 560 | 2.05k | } |
void llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::VPBlockBase, false> >::doFullDFSWalk<bool (*)(llvm::VPBlockBase*, llvm::VPBlockBase*)>(llvm::DominatorTreeBase<llvm::VPBlockBase, false> const&, bool (*)(llvm::VPBlockBase*, llvm::VPBlockBase*)) Line | Count | Source | 550 | 28 | void doFullDFSWalk(const DomTreeT &DT, DescendCondition DC) { | 551 | 28 | if (!IsPostDom) { | 552 | 28 | assert(DT.Roots.size() == 1 && "Dominators should have a singe root"); | 553 | 28 | runDFS(DT.Roots[0], 0, DC, 0); | 554 | 28 | return; | 555 | 28 | } | 556 | 0 | | 557 | 0 | addVirtualRoot(); | 558 | 0 | unsigned Num = 1; | 559 | 0 | for (const NodePtr Root : DT.Roots) Num = runDFS(Root, Num, DC, 0); | 560 | 0 | } |
void llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<clang::CFGBlock, false> >::doFullDFSWalk<bool (*)(clang::CFGBlock*, clang::CFGBlock*)>(llvm::DominatorTreeBase<clang::CFGBlock, false> const&, bool (*)(clang::CFGBlock*, clang::CFGBlock*)) Line | Count | Source | 550 | 8 | void doFullDFSWalk(const DomTreeT &DT, DescendCondition DC) { | 551 | 8 | if (!IsPostDom) { | 552 | 8 | assert(DT.Roots.size() == 1 && "Dominators should have a singe root"); | 553 | 8 | runDFS(DT.Roots[0], 0, DC, 0); | 554 | 8 | return; | 555 | 8 | } | 556 | 0 | | 557 | 0 | addVirtualRoot(); | 558 | 0 | unsigned Num = 1; | 559 | 0 | for (const NodePtr Root : DT.Roots) Num = runDFS(Root, Num, DC, 0); | 560 | 0 | } |
void llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<clang::CFGBlock, true> >::doFullDFSWalk<bool (*)(clang::CFGBlock*, clang::CFGBlock*)>(llvm::DominatorTreeBase<clang::CFGBlock, true> const&, bool (*)(clang::CFGBlock*, clang::CFGBlock*)) Line | Count | Source | 550 | 107 | void doFullDFSWalk(const DomTreeT &DT, DescendCondition DC) { | 551 | 107 | if (!IsPostDom) { | 552 | 0 | assert(DT.Roots.size() == 1 && "Dominators should have a singe root"); | 553 | 0 | runDFS(DT.Roots[0], 0, DC, 0); | 554 | 0 | return; | 555 | 0 | } | 556 | 107 | | 557 | 107 | addVirtualRoot(); | 558 | 107 | unsigned Num = 1; | 559 | 107 | for (const NodePtr Root : DT.Roots) Num = runDFS(Root, Num, DC, 0); | 560 | 107 | } |
|
561 | | |
562 | 15.1M | static void CalculateFromScratch(DomTreeT &DT, BatchUpdatePtr BUI) { |
563 | 15.1M | auto *Parent = DT.Parent; |
564 | 15.1M | DT.reset(); |
565 | 15.1M | DT.Parent = Parent; |
566 | 15.1M | SemiNCAInfo SNCA(nullptr); // Since we are rebuilding the whole tree, |
567 | 15.1M | // there's no point doing it incrementally. |
568 | 15.1M | |
569 | 15.1M | // Step #0: Number blocks in depth-first order and initialize variables used |
570 | 15.1M | // in later stages of the algorithm. |
571 | 15.1M | DT.Roots = FindRoots(DT, nullptr); |
572 | 15.1M | SNCA.doFullDFSWalk(DT, AlwaysDescend); |
573 | 15.1M | |
574 | 15.1M | SNCA.runSemiNCA(DT); |
575 | 15.1M | if (BUI) { |
576 | 165k | BUI->IsRecalculated = true; |
577 | 165k | LLVM_DEBUG( |
578 | 165k | dbgs() << "DomTree recalculated, skipping future batch updates\n"); |
579 | 165k | } |
580 | 15.1M | |
581 | 15.1M | if (DT.Roots.empty()) return0 ; |
582 | 15.1M | |
583 | 15.1M | // Add a node for the root. If the tree is a PostDominatorTree it will be |
584 | 15.1M | // the virtual exit (denoted by (BasicBlock *) nullptr) which postdominates |
585 | 15.1M | // all real exits (including multiple exit blocks, infinite loops). |
586 | 15.1M | NodePtr Root = IsPostDom ? nullptr2.11M : DT.Roots[0]13.0M ; |
587 | 15.1M | |
588 | 15.1M | DT.RootNode = (DT.DomTreeNodes[Root] = |
589 | 15.1M | llvm::make_unique<DomTreeNodeBase<NodeT>>(Root, nullptr)) |
590 | 15.1M | .get(); |
591 | 15.1M | SNCA.attachNewSubtree(DT, DT.RootNode); |
592 | 15.1M | } llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> >::CalculateFromScratch(llvm::DominatorTreeBase<llvm::MachineBasicBlock, false>&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> >::BatchUpdateInfo*) Line | Count | Source | 562 | 2.61M | static void CalculateFromScratch(DomTreeT &DT, BatchUpdatePtr BUI) { | 563 | 2.61M | auto *Parent = DT.Parent; | 564 | 2.61M | DT.reset(); | 565 | 2.61M | DT.Parent = Parent; | 566 | 2.61M | SemiNCAInfo SNCA(nullptr); // Since we are rebuilding the whole tree, | 567 | 2.61M | // there's no point doing it incrementally. | 568 | 2.61M | | 569 | 2.61M | // Step #0: Number blocks in depth-first order and initialize variables used | 570 | 2.61M | // in later stages of the algorithm. | 571 | 2.61M | DT.Roots = FindRoots(DT, nullptr); | 572 | 2.61M | SNCA.doFullDFSWalk(DT, AlwaysDescend); | 573 | 2.61M | | 574 | 2.61M | SNCA.runSemiNCA(DT); | 575 | 2.61M | if (BUI) { | 576 | 0 | BUI->IsRecalculated = true; | 577 | 0 | LLVM_DEBUG( | 578 | 0 | dbgs() << "DomTree recalculated, skipping future batch updates\n"); | 579 | 0 | } | 580 | 2.61M | | 581 | 2.61M | if (DT.Roots.empty()) return0 ; | 582 | 2.61M | | 583 | 2.61M | // Add a node for the root. If the tree is a PostDominatorTree it will be | 584 | 2.61M | // the virtual exit (denoted by (BasicBlock *) nullptr) which postdominates | 585 | 2.61M | // all real exits (including multiple exit blocks, infinite loops). | 586 | 2.61M | NodePtr Root = IsPostDom ? nullptr0 : DT.Roots[0]; | 587 | 2.61M | | 588 | 2.61M | DT.RootNode = (DT.DomTreeNodes[Root] = | 589 | 2.61M | llvm::make_unique<DomTreeNodeBase<NodeT>>(Root, nullptr)) | 590 | 2.61M | .get(); | 591 | 2.61M | SNCA.attachNewSubtree(DT, DT.RootNode); | 592 | 2.61M | } |
llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> >::CalculateFromScratch(llvm::DominatorTreeBase<llvm::MachineBasicBlock, true>&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> >::BatchUpdateInfo*) Line | Count | Source | 562 | 1.50M | static void CalculateFromScratch(DomTreeT &DT, BatchUpdatePtr BUI) { | 563 | 1.50M | auto *Parent = DT.Parent; | 564 | 1.50M | DT.reset(); | 565 | 1.50M | DT.Parent = Parent; | 566 | 1.50M | SemiNCAInfo SNCA(nullptr); // Since we are rebuilding the whole tree, | 567 | 1.50M | // there's no point doing it incrementally. | 568 | 1.50M | | 569 | 1.50M | // Step #0: Number blocks in depth-first order and initialize variables used | 570 | 1.50M | // in later stages of the algorithm. | 571 | 1.50M | DT.Roots = FindRoots(DT, nullptr); | 572 | 1.50M | SNCA.doFullDFSWalk(DT, AlwaysDescend); | 573 | 1.50M | | 574 | 1.50M | SNCA.runSemiNCA(DT); | 575 | 1.50M | if (BUI) { | 576 | 0 | BUI->IsRecalculated = true; | 577 | 0 | LLVM_DEBUG( | 578 | 0 | dbgs() << "DomTree recalculated, skipping future batch updates\n"); | 579 | 0 | } | 580 | 1.50M | | 581 | 1.50M | if (DT.Roots.empty()) return0 ; | 582 | 1.50M | | 583 | 1.50M | // Add a node for the root. If the tree is a PostDominatorTree it will be | 584 | 1.50M | // the virtual exit (denoted by (BasicBlock *) nullptr) which postdominates | 585 | 1.50M | // all real exits (including multiple exit blocks, infinite loops). | 586 | 18.4E | NodePtr Root = IsPostDom 1.50M ? nullptr1.50M : DT.Roots[0]; | 587 | 1.50M | | 588 | 1.50M | DT.RootNode = (DT.DomTreeNodes[Root] = | 589 | 1.50M | llvm::make_unique<DomTreeNodeBase<NodeT>>(Root, nullptr)) | 590 | 1.50M | .get(); | 591 | 1.50M | SNCA.attachNewSubtree(DT, DT.RootNode); | 592 | 1.50M | } |
llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, false> >::CalculateFromScratch(llvm::DominatorTreeBase<llvm::BasicBlock, false>&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, false> >::BatchUpdateInfo*) Line | Count | Source | 562 | 10.3M | static void CalculateFromScratch(DomTreeT &DT, BatchUpdatePtr BUI) { | 563 | 10.3M | auto *Parent = DT.Parent; | 564 | 10.3M | DT.reset(); | 565 | 10.3M | DT.Parent = Parent; | 566 | 10.3M | SemiNCAInfo SNCA(nullptr); // Since we are rebuilding the whole tree, | 567 | 10.3M | // there's no point doing it incrementally. | 568 | 10.3M | | 569 | 10.3M | // Step #0: Number blocks in depth-first order and initialize variables used | 570 | 10.3M | // in later stages of the algorithm. | 571 | 10.3M | DT.Roots = FindRoots(DT, nullptr); | 572 | 10.3M | SNCA.doFullDFSWalk(DT, AlwaysDescend); | 573 | 10.3M | | 574 | 10.3M | SNCA.runSemiNCA(DT); | 575 | 10.3M | if (BUI) { | 576 | 165k | BUI->IsRecalculated = true; | 577 | 165k | LLVM_DEBUG( | 578 | 165k | dbgs() << "DomTree recalculated, skipping future batch updates\n"); | 579 | 165k | } | 580 | 10.3M | | 581 | 10.3M | if (DT.Roots.empty()) return0 ; | 582 | 10.3M | | 583 | 10.3M | // Add a node for the root. If the tree is a PostDominatorTree it will be | 584 | 10.3M | // the virtual exit (denoted by (BasicBlock *) nullptr) which postdominates | 585 | 10.3M | // all real exits (including multiple exit blocks, infinite loops). | 586 | 10.3M | NodePtr Root = IsPostDom ? nullptr0 : DT.Roots[0]; | 587 | 10.3M | | 588 | 10.3M | DT.RootNode = (DT.DomTreeNodes[Root] = | 589 | 10.3M | llvm::make_unique<DomTreeNodeBase<NodeT>>(Root, nullptr)) | 590 | 10.3M | .get(); | 591 | 10.3M | SNCA.attachNewSubtree(DT, DT.RootNode); | 592 | 10.3M | } |
llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, true> >::CalculateFromScratch(llvm::DominatorTreeBase<llvm::BasicBlock, true>&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, true> >::BatchUpdateInfo*) Line | Count | Source | 562 | 605k | static void CalculateFromScratch(DomTreeT &DT, BatchUpdatePtr BUI) { | 563 | 605k | auto *Parent = DT.Parent; | 564 | 605k | DT.reset(); | 565 | 605k | DT.Parent = Parent; | 566 | 605k | SemiNCAInfo SNCA(nullptr); // Since we are rebuilding the whole tree, | 567 | 605k | // there's no point doing it incrementally. | 568 | 605k | | 569 | 605k | // Step #0: Number blocks in depth-first order and initialize variables used | 570 | 605k | // in later stages of the algorithm. | 571 | 605k | DT.Roots = FindRoots(DT, nullptr); | 572 | 605k | SNCA.doFullDFSWalk(DT, AlwaysDescend); | 573 | 605k | | 574 | 605k | SNCA.runSemiNCA(DT); | 575 | 605k | if (BUI) { | 576 | 56 | BUI->IsRecalculated = true; | 577 | 56 | LLVM_DEBUG( | 578 | 56 | dbgs() << "DomTree recalculated, skipping future batch updates\n"); | 579 | 56 | } | 580 | 605k | | 581 | 605k | if (DT.Roots.empty()) return0 ; | 582 | 605k | | 583 | 605k | // Add a node for the root. If the tree is a PostDominatorTree it will be | 584 | 605k | // the virtual exit (denoted by (BasicBlock *) nullptr) which postdominates | 585 | 605k | // all real exits (including multiple exit blocks, infinite loops). | 586 | 605k | NodePtr Root = IsPostDom ? nullptr605k : DT.Roots[0]3 ; | 587 | 605k | | 588 | 605k | DT.RootNode = (DT.DomTreeNodes[Root] = | 589 | 605k | llvm::make_unique<DomTreeNodeBase<NodeT>>(Root, nullptr)) | 590 | 605k | .get(); | 591 | 605k | SNCA.attachNewSubtree(DT, DT.RootNode); | 592 | 605k | } |
llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::VPBlockBase, false> >::CalculateFromScratch(llvm::DominatorTreeBase<llvm::VPBlockBase, false>&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::VPBlockBase, false> >::BatchUpdateInfo*) Line | Count | Source | 562 | 28 | static void CalculateFromScratch(DomTreeT &DT, BatchUpdatePtr BUI) { | 563 | 28 | auto *Parent = DT.Parent; | 564 | 28 | DT.reset(); | 565 | 28 | DT.Parent = Parent; | 566 | 28 | SemiNCAInfo SNCA(nullptr); // Since we are rebuilding the whole tree, | 567 | 28 | // there's no point doing it incrementally. | 568 | 28 | | 569 | 28 | // Step #0: Number blocks in depth-first order and initialize variables used | 570 | 28 | // in later stages of the algorithm. | 571 | 28 | DT.Roots = FindRoots(DT, nullptr); | 572 | 28 | SNCA.doFullDFSWalk(DT, AlwaysDescend); | 573 | 28 | | 574 | 28 | SNCA.runSemiNCA(DT); | 575 | 28 | if (BUI) { | 576 | 0 | BUI->IsRecalculated = true; | 577 | 0 | LLVM_DEBUG( | 578 | 0 | dbgs() << "DomTree recalculated, skipping future batch updates\n"); | 579 | 0 | } | 580 | 28 | | 581 | 28 | if (DT.Roots.empty()) return0 ; | 582 | 28 | | 583 | 28 | // Add a node for the root. If the tree is a PostDominatorTree it will be | 584 | 28 | // the virtual exit (denoted by (BasicBlock *) nullptr) which postdominates | 585 | 28 | // all real exits (including multiple exit blocks, infinite loops). | 586 | 28 | NodePtr Root = IsPostDom ? nullptr0 : DT.Roots[0]; | 587 | 28 | | 588 | 28 | DT.RootNode = (DT.DomTreeNodes[Root] = | 589 | 28 | llvm::make_unique<DomTreeNodeBase<NodeT>>(Root, nullptr)) | 590 | 28 | .get(); | 591 | 28 | SNCA.attachNewSubtree(DT, DT.RootNode); | 592 | 28 | } |
llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<clang::CFGBlock, false> >::CalculateFromScratch(llvm::DominatorTreeBase<clang::CFGBlock, false>&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<clang::CFGBlock, false> >::BatchUpdateInfo*) Line | Count | Source | 562 | 8 | static void CalculateFromScratch(DomTreeT &DT, BatchUpdatePtr BUI) { | 563 | 8 | auto *Parent = DT.Parent; | 564 | 8 | DT.reset(); | 565 | 8 | DT.Parent = Parent; | 566 | 8 | SemiNCAInfo SNCA(nullptr); // Since we are rebuilding the whole tree, | 567 | 8 | // there's no point doing it incrementally. | 568 | 8 | | 569 | 8 | // Step #0: Number blocks in depth-first order and initialize variables used | 570 | 8 | // in later stages of the algorithm. | 571 | 8 | DT.Roots = FindRoots(DT, nullptr); | 572 | 8 | SNCA.doFullDFSWalk(DT, AlwaysDescend); | 573 | 8 | | 574 | 8 | SNCA.runSemiNCA(DT); | 575 | 8 | if (BUI) { | 576 | 0 | BUI->IsRecalculated = true; | 577 | 0 | LLVM_DEBUG( | 578 | 0 | dbgs() << "DomTree recalculated, skipping future batch updates\n"); | 579 | 0 | } | 580 | 8 | | 581 | 8 | if (DT.Roots.empty()) return0 ; | 582 | 8 | | 583 | 8 | // Add a node for the root. If the tree is a PostDominatorTree it will be | 584 | 8 | // the virtual exit (denoted by (BasicBlock *) nullptr) which postdominates | 585 | 8 | // all real exits (including multiple exit blocks, infinite loops). | 586 | 8 | NodePtr Root = IsPostDom ? nullptr0 : DT.Roots[0]; | 587 | 8 | | 588 | 8 | DT.RootNode = (DT.DomTreeNodes[Root] = | 589 | 8 | llvm::make_unique<DomTreeNodeBase<NodeT>>(Root, nullptr)) | 590 | 8 | .get(); | 591 | 8 | SNCA.attachNewSubtree(DT, DT.RootNode); | 592 | 8 | } |
llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<clang::CFGBlock, true> >::CalculateFromScratch(llvm::DominatorTreeBase<clang::CFGBlock, true>&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<clang::CFGBlock, true> >::BatchUpdateInfo*) Line | Count | Source | 562 | 107 | static void CalculateFromScratch(DomTreeT &DT, BatchUpdatePtr BUI) { | 563 | 107 | auto *Parent = DT.Parent; | 564 | 107 | DT.reset(); | 565 | 107 | DT.Parent = Parent; | 566 | 107 | SemiNCAInfo SNCA(nullptr); // Since we are rebuilding the whole tree, | 567 | 107 | // there's no point doing it incrementally. | 568 | 107 | | 569 | 107 | // Step #0: Number blocks in depth-first order and initialize variables used | 570 | 107 | // in later stages of the algorithm. | 571 | 107 | DT.Roots = FindRoots(DT, nullptr); | 572 | 107 | SNCA.doFullDFSWalk(DT, AlwaysDescend); | 573 | 107 | | 574 | 107 | SNCA.runSemiNCA(DT); | 575 | 107 | if (BUI) { | 576 | 0 | BUI->IsRecalculated = true; | 577 | 0 | LLVM_DEBUG( | 578 | 0 | dbgs() << "DomTree recalculated, skipping future batch updates\n"); | 579 | 0 | } | 580 | 107 | | 581 | 107 | if (DT.Roots.empty()) return0 ; | 582 | 107 | | 583 | 107 | // Add a node for the root. If the tree is a PostDominatorTree it will be | 584 | 107 | // the virtual exit (denoted by (BasicBlock *) nullptr) which postdominates | 585 | 107 | // all real exits (including multiple exit blocks, infinite loops). | 586 | 107 | NodePtr Root = IsPostDom ? nullptr : DT.Roots[0]0 ; | 587 | 107 | | 588 | 107 | DT.RootNode = (DT.DomTreeNodes[Root] = | 589 | 107 | llvm::make_unique<DomTreeNodeBase<NodeT>>(Root, nullptr)) | 590 | 107 | .get(); | 591 | 107 | SNCA.attachNewSubtree(DT, DT.RootNode); | 592 | 107 | } |
|
593 | | |
594 | 15.2M | void attachNewSubtree(DomTreeT& DT, const TreeNodePtr AttachTo) { |
595 | 15.2M | // Attach the first unreachable block to AttachTo. |
596 | 15.2M | NodeToInfo[NumToNode[1]].IDom = AttachTo->getBlock(); |
597 | 15.2M | // Loop over all of the discovered blocks in the function... |
598 | 105M | for (size_t i = 1, e = NumToNode.size(); i != e; ++i89.9M ) { |
599 | 89.9M | NodePtr W = NumToNode[i]; |
600 | 89.9M | LLVM_DEBUG(dbgs() << "\tdiscovered a new reachable node " |
601 | 89.9M | << BlockNamePrinter(W) << "\n"); |
602 | 89.9M | |
603 | 89.9M | // Don't replace this with 'count', the insertion side effect is important |
604 | 89.9M | if (DT.DomTreeNodes[W]) continue15.1M ; // Haven't calculated this node yet? |
605 | 74.8M | |
606 | 74.8M | NodePtr ImmDom = getIDom(W); |
607 | 74.8M | |
608 | 74.8M | // Get or calculate the node for the immediate dominator. |
609 | 74.8M | TreeNodePtr IDomNode = getNodeForBlock(ImmDom, DT); |
610 | 74.8M | |
611 | 74.8M | // Add a new tree node for this BasicBlock, and link it as a child of |
612 | 74.8M | // IDomNode. |
613 | 74.8M | DT.DomTreeNodes[W] = IDomNode->addChild( |
614 | 74.8M | llvm::make_unique<DomTreeNodeBase<NodeT>>(W, IDomNode)); |
615 | 74.8M | } |
616 | 15.2M | } llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> >::attachNewSubtree(llvm::DominatorTreeBase<llvm::MachineBasicBlock, false>&, llvm::DomTreeNodeBase<llvm::MachineBasicBlock>*) Line | Count | Source | 594 | 2.61M | void attachNewSubtree(DomTreeT& DT, const TreeNodePtr AttachTo) { | 595 | 2.61M | // Attach the first unreachable block to AttachTo. | 596 | 2.61M | NodeToInfo[NumToNode[1]].IDom = AttachTo->getBlock(); | 597 | 2.61M | // Loop over all of the discovered blocks in the function... | 598 | 14.6M | for (size_t i = 1, e = NumToNode.size(); i != e; ++i12.0M ) { | 599 | 12.0M | NodePtr W = NumToNode[i]; | 600 | 12.0M | LLVM_DEBUG(dbgs() << "\tdiscovered a new reachable node " | 601 | 12.0M | << BlockNamePrinter(W) << "\n"); | 602 | 12.0M | | 603 | 12.0M | // Don't replace this with 'count', the insertion side effect is important | 604 | 12.0M | if (DT.DomTreeNodes[W]) continue2.61M ; // Haven't calculated this node yet? | 605 | 9.38M | | 606 | 9.38M | NodePtr ImmDom = getIDom(W); | 607 | 9.38M | | 608 | 9.38M | // Get or calculate the node for the immediate dominator. | 609 | 9.38M | TreeNodePtr IDomNode = getNodeForBlock(ImmDom, DT); | 610 | 9.38M | | 611 | 9.38M | // Add a new tree node for this BasicBlock, and link it as a child of | 612 | 9.38M | // IDomNode. | 613 | 9.38M | DT.DomTreeNodes[W] = IDomNode->addChild( | 614 | 9.38M | llvm::make_unique<DomTreeNodeBase<NodeT>>(W, IDomNode)); | 615 | 9.38M | } | 616 | 2.61M | } |
llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> >::attachNewSubtree(llvm::DominatorTreeBase<llvm::MachineBasicBlock, true>&, llvm::DomTreeNodeBase<llvm::MachineBasicBlock>*) Line | Count | Source | 594 | 1.50M | void attachNewSubtree(DomTreeT& DT, const TreeNodePtr AttachTo) { | 595 | 1.50M | // Attach the first unreachable block to AttachTo. | 596 | 1.50M | NodeToInfo[NumToNode[1]].IDom = AttachTo->getBlock(); | 597 | 1.50M | // Loop over all of the discovered blocks in the function... | 598 | 11.5M | for (size_t i = 1, e = NumToNode.size(); i != e; ++i10.0M ) { | 599 | 10.0M | NodePtr W = NumToNode[i]; | 600 | 10.0M | LLVM_DEBUG(dbgs() << "\tdiscovered a new reachable node " | 601 | 10.0M | << BlockNamePrinter(W) << "\n"); | 602 | 10.0M | | 603 | 10.0M | // Don't replace this with 'count', the insertion side effect is important | 604 | 10.0M | if (DT.DomTreeNodes[W]) continue1.50M ; // Haven't calculated this node yet? | 605 | 8.52M | | 606 | 8.52M | NodePtr ImmDom = getIDom(W); | 607 | 8.52M | | 608 | 8.52M | // Get or calculate the node for the immediate dominator. | 609 | 8.52M | TreeNodePtr IDomNode = getNodeForBlock(ImmDom, DT); | 610 | 8.52M | | 611 | 8.52M | // Add a new tree node for this BasicBlock, and link it as a child of | 612 | 8.52M | // IDomNode. | 613 | 8.52M | DT.DomTreeNodes[W] = IDomNode->addChild( | 614 | 8.52M | llvm::make_unique<DomTreeNodeBase<NodeT>>(W, IDomNode)); | 615 | 8.52M | } | 616 | 1.50M | } |
llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, false> >::attachNewSubtree(llvm::DominatorTreeBase<llvm::BasicBlock, false>&, llvm::DomTreeNodeBase<llvm::BasicBlock>*) Line | Count | Source | 594 | 10.5M | void attachNewSubtree(DomTreeT& DT, const TreeNodePtr AttachTo) { | 595 | 10.5M | // Attach the first unreachable block to AttachTo. | 596 | 10.5M | NodeToInfo[NumToNode[1]].IDom = AttachTo->getBlock(); | 597 | 10.5M | // Loop over all of the discovered blocks in the function... | 598 | 74.7M | for (size_t i = 1, e = NumToNode.size(); i != e; ++i64.2M ) { | 599 | 64.2M | NodePtr W = NumToNode[i]; | 600 | 64.2M | LLVM_DEBUG(dbgs() << "\tdiscovered a new reachable node " | 601 | 64.2M | << BlockNamePrinter(W) << "\n"); | 602 | 64.2M | | 603 | 64.2M | // Don't replace this with 'count', the insertion side effect is important | 604 | 64.2M | if (DT.DomTreeNodes[W]) continue10.3M ; // Haven't calculated this node yet? | 605 | 53.8M | | 606 | 53.8M | NodePtr ImmDom = getIDom(W); | 607 | 53.8M | | 608 | 53.8M | // Get or calculate the node for the immediate dominator. | 609 | 53.8M | TreeNodePtr IDomNode = getNodeForBlock(ImmDom, DT); | 610 | 53.8M | | 611 | 53.8M | // Add a new tree node for this BasicBlock, and link it as a child of | 612 | 53.8M | // IDomNode. | 613 | 53.8M | DT.DomTreeNodes[W] = IDomNode->addChild( | 614 | 53.8M | llvm::make_unique<DomTreeNodeBase<NodeT>>(W, IDomNode)); | 615 | 53.8M | } | 616 | 10.5M | } |
llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, true> >::attachNewSubtree(llvm::DominatorTreeBase<llvm::BasicBlock, true>&, llvm::DomTreeNodeBase<llvm::BasicBlock>*) Line | Count | Source | 594 | 605k | void attachNewSubtree(DomTreeT& DT, const TreeNodePtr AttachTo) { | 595 | 605k | // Attach the first unreachable block to AttachTo. | 596 | 605k | NodeToInfo[NumToNode[1]].IDom = AttachTo->getBlock(); | 597 | 605k | // Loop over all of the discovered blocks in the function... | 598 | 4.27M | for (size_t i = 1, e = NumToNode.size(); i != e; ++i3.66M ) { | 599 | 3.66M | NodePtr W = NumToNode[i]; | 600 | 3.66M | LLVM_DEBUG(dbgs() << "\tdiscovered a new reachable node " | 601 | 3.66M | << BlockNamePrinter(W) << "\n"); | 602 | 3.66M | | 603 | 3.66M | // Don't replace this with 'count', the insertion side effect is important | 604 | 3.66M | if (DT.DomTreeNodes[W]) continue605k ; // Haven't calculated this node yet? | 605 | 3.06M | | 606 | 3.06M | NodePtr ImmDom = getIDom(W); | 607 | 3.06M | | 608 | 3.06M | // Get or calculate the node for the immediate dominator. | 609 | 3.06M | TreeNodePtr IDomNode = getNodeForBlock(ImmDom, DT); | 610 | 3.06M | | 611 | 3.06M | // Add a new tree node for this BasicBlock, and link it as a child of | 612 | 3.06M | // IDomNode. | 613 | 3.06M | DT.DomTreeNodes[W] = IDomNode->addChild( | 614 | 3.06M | llvm::make_unique<DomTreeNodeBase<NodeT>>(W, IDomNode)); | 615 | 3.06M | } | 616 | 605k | } |
llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::VPBlockBase, false> >::attachNewSubtree(llvm::DominatorTreeBase<llvm::VPBlockBase, false>&, llvm::DomTreeNodeBase<llvm::VPBlockBase>*) Line | Count | Source | 594 | 28 | void attachNewSubtree(DomTreeT& DT, const TreeNodePtr AttachTo) { | 595 | 28 | // Attach the first unreachable block to AttachTo. | 596 | 28 | NodeToInfo[NumToNode[1]].IDom = AttachTo->getBlock(); | 597 | 28 | // Loop over all of the discovered blocks in the function... | 598 | 163 | for (size_t i = 1, e = NumToNode.size(); i != e; ++i135 ) { | 599 | 135 | NodePtr W = NumToNode[i]; | 600 | 135 | LLVM_DEBUG(dbgs() << "\tdiscovered a new reachable node " | 601 | 135 | << BlockNamePrinter(W) << "\n"); | 602 | 135 | | 603 | 135 | // Don't replace this with 'count', the insertion side effect is important | 604 | 135 | if (DT.DomTreeNodes[W]) continue28 ; // Haven't calculated this node yet? | 605 | 107 | | 606 | 107 | NodePtr ImmDom = getIDom(W); | 607 | 107 | | 608 | 107 | // Get or calculate the node for the immediate dominator. | 609 | 107 | TreeNodePtr IDomNode = getNodeForBlock(ImmDom, DT); | 610 | 107 | | 611 | 107 | // Add a new tree node for this BasicBlock, and link it as a child of | 612 | 107 | // IDomNode. | 613 | 107 | DT.DomTreeNodes[W] = IDomNode->addChild( | 614 | 107 | llvm::make_unique<DomTreeNodeBase<NodeT>>(W, IDomNode)); | 615 | 107 | } | 616 | 28 | } |
llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<clang::CFGBlock, false> >::attachNewSubtree(llvm::DominatorTreeBase<clang::CFGBlock, false>&, llvm::DomTreeNodeBase<clang::CFGBlock>*) Line | Count | Source | 594 | 8 | void attachNewSubtree(DomTreeT& DT, const TreeNodePtr AttachTo) { | 595 | 8 | // Attach the first unreachable block to AttachTo. | 596 | 8 | NodeToInfo[NumToNode[1]].IDom = AttachTo->getBlock(); | 597 | 8 | // Loop over all of the discovered blocks in the function... | 598 | 74 | for (size_t i = 1, e = NumToNode.size(); i != e; ++i66 ) { | 599 | 66 | NodePtr W = NumToNode[i]; | 600 | 66 | LLVM_DEBUG(dbgs() << "\tdiscovered a new reachable node " | 601 | 66 | << BlockNamePrinter(W) << "\n"); | 602 | 66 | | 603 | 66 | // Don't replace this with 'count', the insertion side effect is important | 604 | 66 | if (DT.DomTreeNodes[W]) continue8 ; // Haven't calculated this node yet? | 605 | 58 | | 606 | 58 | NodePtr ImmDom = getIDom(W); | 607 | 58 | | 608 | 58 | // Get or calculate the node for the immediate dominator. | 609 | 58 | TreeNodePtr IDomNode = getNodeForBlock(ImmDom, DT); | 610 | 58 | | 611 | 58 | // Add a new tree node for this BasicBlock, and link it as a child of | 612 | 58 | // IDomNode. | 613 | 58 | DT.DomTreeNodes[W] = IDomNode->addChild( | 614 | 58 | llvm::make_unique<DomTreeNodeBase<NodeT>>(W, IDomNode)); | 615 | 58 | } | 616 | 8 | } |
llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<clang::CFGBlock, true> >::attachNewSubtree(llvm::DominatorTreeBase<clang::CFGBlock, true>&, llvm::DomTreeNodeBase<clang::CFGBlock>*) Line | Count | Source | 594 | 107 | void attachNewSubtree(DomTreeT& DT, const TreeNodePtr AttachTo) { | 595 | 107 | // Attach the first unreachable block to AttachTo. | 596 | 107 | NodeToInfo[NumToNode[1]].IDom = AttachTo->getBlock(); | 597 | 107 | // Loop over all of the discovered blocks in the function... | 598 | 763 | for (size_t i = 1, e = NumToNode.size(); i != e; ++i656 ) { | 599 | 656 | NodePtr W = NumToNode[i]; | 600 | 656 | LLVM_DEBUG(dbgs() << "\tdiscovered a new reachable node " | 601 | 656 | << BlockNamePrinter(W) << "\n"); | 602 | 656 | | 603 | 656 | // Don't replace this with 'count', the insertion side effect is important | 604 | 656 | if (DT.DomTreeNodes[W]) continue107 ; // Haven't calculated this node yet? | 605 | 549 | | 606 | 549 | NodePtr ImmDom = getIDom(W); | 607 | 549 | | 608 | 549 | // Get or calculate the node for the immediate dominator. | 609 | 549 | TreeNodePtr IDomNode = getNodeForBlock(ImmDom, DT); | 610 | 549 | | 611 | 549 | // Add a new tree node for this BasicBlock, and link it as a child of | 612 | 549 | // IDomNode. | 613 | 549 | DT.DomTreeNodes[W] = IDomNode->addChild( | 614 | 549 | llvm::make_unique<DomTreeNodeBase<NodeT>>(W, IDomNode)); | 615 | 549 | } | 616 | 107 | } |
|
617 | | |
618 | 423k | void reattachExistingSubtree(DomTreeT &DT, const TreeNodePtr AttachTo) { |
619 | 423k | NodeToInfo[NumToNode[1]].IDom = AttachTo->getBlock(); |
620 | 14.0M | for (size_t i = 1, e = NumToNode.size(); i != e; ++i13.5M ) { |
621 | 13.5M | const NodePtr N = NumToNode[i]; |
622 | 13.5M | const TreeNodePtr TN = DT.getNode(N); |
623 | 13.5M | assert(TN); |
624 | 13.5M | const TreeNodePtr NewIDom = DT.getNode(NodeToInfo[N].IDom); |
625 | 13.5M | TN->setIDom(NewIDom); |
626 | 13.5M | } |
627 | 423k | } Unexecuted instantiation: llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> >::reattachExistingSubtree(llvm::DominatorTreeBase<llvm::MachineBasicBlock, false>&, llvm::DomTreeNodeBase<llvm::MachineBasicBlock>*) Unexecuted instantiation: llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> >::reattachExistingSubtree(llvm::DominatorTreeBase<llvm::MachineBasicBlock, true>&, llvm::DomTreeNodeBase<llvm::MachineBasicBlock>*) llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, false> >::reattachExistingSubtree(llvm::DominatorTreeBase<llvm::BasicBlock, false>&, llvm::DomTreeNodeBase<llvm::BasicBlock>*) Line | Count | Source | 618 | 423k | void reattachExistingSubtree(DomTreeT &DT, const TreeNodePtr AttachTo) { | 619 | 423k | NodeToInfo[NumToNode[1]].IDom = AttachTo->getBlock(); | 620 | 14.0M | for (size_t i = 1, e = NumToNode.size(); i != e; ++i13.5M ) { | 621 | 13.5M | const NodePtr N = NumToNode[i]; | 622 | 13.5M | const TreeNodePtr TN = DT.getNode(N); | 623 | 13.5M | assert(TN); | 624 | 13.5M | const TreeNodePtr NewIDom = DT.getNode(NodeToInfo[N].IDom); | 625 | 13.5M | TN->setIDom(NewIDom); | 626 | 13.5M | } | 627 | 423k | } |
llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, true> >::reattachExistingSubtree(llvm::DominatorTreeBase<llvm::BasicBlock, true>&, llvm::DomTreeNodeBase<llvm::BasicBlock>*) Line | Count | Source | 618 | 93 | void reattachExistingSubtree(DomTreeT &DT, const TreeNodePtr AttachTo) { | 619 | 93 | NodeToInfo[NumToNode[1]].IDom = AttachTo->getBlock(); | 620 | 465 | for (size_t i = 1, e = NumToNode.size(); i != e; ++i372 ) { | 621 | 372 | const NodePtr N = NumToNode[i]; | 622 | 372 | const TreeNodePtr TN = DT.getNode(N); | 623 | 372 | assert(TN); | 624 | 372 | const TreeNodePtr NewIDom = DT.getNode(NodeToInfo[N].IDom); | 625 | 372 | TN->setIDom(NewIDom); | 626 | 372 | } | 627 | 93 | } |
|
628 | | |
629 | | // Helper struct used during edge insertions. |
630 | | struct InsertionInfo { |
631 | | struct Compare { |
632 | 855 | bool operator()(TreeNodePtr LHS, TreeNodePtr RHS) const { |
633 | 855 | return LHS->getLevel() < RHS->getLevel(); |
634 | 855 | } Unexecuted instantiation: llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> >::InsertionInfo::Compare::operator()(llvm::DomTreeNodeBase<llvm::MachineBasicBlock>*, llvm::DomTreeNodeBase<llvm::MachineBasicBlock>*) const Unexecuted instantiation: llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> >::InsertionInfo::Compare::operator()(llvm::DomTreeNodeBase<llvm::MachineBasicBlock>*, llvm::DomTreeNodeBase<llvm::MachineBasicBlock>*) const llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, false> >::InsertionInfo::Compare::operator()(llvm::DomTreeNodeBase<llvm::BasicBlock>*, llvm::DomTreeNodeBase<llvm::BasicBlock>*) const Line | Count | Source | 632 | 854 | bool operator()(TreeNodePtr LHS, TreeNodePtr RHS) const { | 633 | 854 | return LHS->getLevel() < RHS->getLevel(); | 634 | 854 | } |
llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, true> >::InsertionInfo::Compare::operator()(llvm::DomTreeNodeBase<llvm::BasicBlock>*, llvm::DomTreeNodeBase<llvm::BasicBlock>*) const Line | Count | Source | 632 | 1 | bool operator()(TreeNodePtr LHS, TreeNodePtr RHS) const { | 633 | 1 | return LHS->getLevel() < RHS->getLevel(); | 634 | 1 | } |
|
635 | | }; |
636 | | |
637 | | // Bucket queue of tree nodes ordered by descending level. For simplicity, |
638 | | // we use a priority_queue here. |
639 | | std::priority_queue<TreeNodePtr, SmallVector<TreeNodePtr, 8>, |
640 | | Compare> |
641 | | Bucket; |
642 | | SmallDenseSet<TreeNodePtr, 8> Visited; |
643 | | SmallVector<TreeNodePtr, 8> Affected; |
644 | | #ifndef NDEBUG |
645 | | SmallVector<TreeNodePtr, 8> VisitedUnaffected; |
646 | | #endif |
647 | | }; |
648 | | |
649 | | static void InsertEdge(DomTreeT &DT, const BatchUpdatePtr BUI, |
650 | 619k | const NodePtr From, const NodePtr To) { |
651 | 619k | assert((From || IsPostDom) && |
652 | 619k | "From has to be a valid CFG node or a virtual root"); |
653 | 619k | assert(To && "Cannot be a nullptr"); |
654 | 619k | LLVM_DEBUG(dbgs() << "Inserting edge " << BlockNamePrinter(From) << " -> " |
655 | 619k | << BlockNamePrinter(To) << "\n"); |
656 | 619k | TreeNodePtr FromTN = DT.getNode(From); |
657 | 619k | |
658 | 619k | if (!FromTN) { |
659 | 11.3k | // Ignore edges from unreachable nodes for (forward) dominators. |
660 | 11.3k | if (!IsPostDom) return11.3k ; |
661 | 3 | |
662 | 3 | // The unreachable node becomes a new root -- a tree node for it. |
663 | 3 | TreeNodePtr VirtualRoot = DT.getNode(nullptr); |
664 | 3 | FromTN = |
665 | 3 | (DT.DomTreeNodes[From] = VirtualRoot->addChild( |
666 | 3 | llvm::make_unique<DomTreeNodeBase<NodeT>>(From, VirtualRoot))) |
667 | 3 | .get(); |
668 | 3 | DT.Roots.push_back(From); |
669 | 3 | } |
670 | 619k | |
671 | 619k | DT.DFSInfoValid = false; |
672 | 608k | |
673 | 608k | const TreeNodePtr ToTN = DT.getNode(To); |
674 | 608k | if (!ToTN) |
675 | 114k | InsertUnreachable(DT, BUI, FromTN, To); |
676 | 493k | else |
677 | 493k | InsertReachable(DT, BUI, FromTN, ToTN); |
678 | 608k | } Unexecuted instantiation: llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> >::InsertEdge(llvm::DominatorTreeBase<llvm::MachineBasicBlock, false>&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> >::BatchUpdateInfo*, llvm::MachineBasicBlock*, llvm::MachineBasicBlock*) Unexecuted instantiation: llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> >::InsertEdge(llvm::DominatorTreeBase<llvm::MachineBasicBlock, true>&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> >::BatchUpdateInfo*, llvm::MachineBasicBlock*, llvm::MachineBasicBlock*) llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, false> >::InsertEdge(llvm::DominatorTreeBase<llvm::BasicBlock, false>&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, false> >::BatchUpdateInfo*, llvm::BasicBlock*, llvm::BasicBlock*) Line | Count | Source | 650 | 619k | const NodePtr From, const NodePtr To) { | 651 | 619k | assert((From || IsPostDom) && | 652 | 619k | "From has to be a valid CFG node or a virtual root"); | 653 | 619k | assert(To && "Cannot be a nullptr"); | 654 | 619k | LLVM_DEBUG(dbgs() << "Inserting edge " << BlockNamePrinter(From) << " -> " | 655 | 619k | << BlockNamePrinter(To) << "\n"); | 656 | 619k | TreeNodePtr FromTN = DT.getNode(From); | 657 | 619k | | 658 | 619k | if (!FromTN) { | 659 | 11.3k | // Ignore edges from unreachable nodes for (forward) dominators. | 660 | 11.3k | if (!IsPostDom) return; | 661 | 0 | | 662 | 0 | // The unreachable node becomes a new root -- a tree node for it. | 663 | 0 | TreeNodePtr VirtualRoot = DT.getNode(nullptr); | 664 | 0 | FromTN = | 665 | 0 | (DT.DomTreeNodes[From] = VirtualRoot->addChild( | 666 | 0 | llvm::make_unique<DomTreeNodeBase<NodeT>>(From, VirtualRoot))) | 667 | 0 | .get(); | 668 | 0 | DT.Roots.push_back(From); | 669 | 0 | } | 670 | 619k | | 671 | 619k | DT.DFSInfoValid = false; | 672 | 608k | | 673 | 608k | const TreeNodePtr ToTN = DT.getNode(To); | 674 | 608k | if (!ToTN) | 675 | 114k | InsertUnreachable(DT, BUI, FromTN, To); | 676 | 493k | else | 677 | 493k | InsertReachable(DT, BUI, FromTN, ToTN); | 678 | 608k | } |
llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, true> >::InsertEdge(llvm::DominatorTreeBase<llvm::BasicBlock, true>&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, true> >::BatchUpdateInfo*, llvm::BasicBlock*, llvm::BasicBlock*) Line | Count | Source | 650 | 162 | const NodePtr From, const NodePtr To) { | 651 | 162 | assert((From || IsPostDom) && | 652 | 162 | "From has to be a valid CFG node or a virtual root"); | 653 | 162 | assert(To && "Cannot be a nullptr"); | 654 | 162 | LLVM_DEBUG(dbgs() << "Inserting edge " << BlockNamePrinter(From) << " -> " | 655 | 162 | << BlockNamePrinter(To) << "\n"); | 656 | 162 | TreeNodePtr FromTN = DT.getNode(From); | 657 | 162 | | 658 | 162 | if (!FromTN) { | 659 | 3 | // Ignore edges from unreachable nodes for (forward) dominators. | 660 | 3 | if (!IsPostDom) return0 ; | 661 | 3 | | 662 | 3 | // The unreachable node becomes a new root -- a tree node for it. | 663 | 3 | TreeNodePtr VirtualRoot = DT.getNode(nullptr); | 664 | 3 | FromTN = | 665 | 3 | (DT.DomTreeNodes[From] = VirtualRoot->addChild( | 666 | 3 | llvm::make_unique<DomTreeNodeBase<NodeT>>(From, VirtualRoot))) | 667 | 3 | .get(); | 668 | 3 | DT.Roots.push_back(From); | 669 | 3 | } | 670 | 162 | | 671 | 162 | DT.DFSInfoValid = false; | 672 | 162 | | 673 | 162 | const TreeNodePtr ToTN = DT.getNode(To); | 674 | 162 | if (!ToTN) | 675 | 3 | InsertUnreachable(DT, BUI, FromTN, To); | 676 | 159 | else | 677 | 159 | InsertReachable(DT, BUI, FromTN, ToTN); | 678 | 162 | } |
|
679 | | |
680 | | // Determines if some existing root becomes reverse-reachable after the |
681 | | // insertion. Rebuilds the whole tree if that situation happens. |
682 | | static bool UpdateRootsBeforeInsertion(DomTreeT &DT, const BatchUpdatePtr BUI, |
683 | | const TreeNodePtr From, |
684 | 230 | const TreeNodePtr To) { |
685 | 230 | assert(IsPostDom && "This function is only for postdominators"); |
686 | 230 | // Destination node is not attached to the virtual root, so it cannot be a |
687 | 230 | // root. |
688 | 230 | if (!DT.isVirtualRoot(To->getIDom())) return false130 ; |
689 | 100 | |
690 | 100 | auto RIt = llvm::find(DT.Roots, To->getBlock()); |
691 | 100 | if (RIt == DT.Roots.end()) |
692 | 15 | return false; // To is not a root, nothing to update. |
693 | 85 | |
694 | 85 | LLVM_DEBUG(dbgs() << "\t\tAfter the insertion, " << BlockNamePrinter(To) |
695 | 85 | << " is no longer a root\n\t\tRebuilding the tree!!!\n"); |
696 | 85 | |
697 | 85 | CalculateFromScratch(DT, BUI); |
698 | 85 | return true; |
699 | 85 | } Unexecuted instantiation: llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> >::UpdateRootsBeforeInsertion(llvm::DominatorTreeBase<llvm::MachineBasicBlock, false>&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> >::BatchUpdateInfo*, llvm::DomTreeNodeBase<llvm::MachineBasicBlock>*, llvm::DomTreeNodeBase<llvm::MachineBasicBlock>*) Unexecuted instantiation: llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> >::UpdateRootsBeforeInsertion(llvm::DominatorTreeBase<llvm::MachineBasicBlock, true>&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> >::BatchUpdateInfo*, llvm::DomTreeNodeBase<llvm::MachineBasicBlock>*, llvm::DomTreeNodeBase<llvm::MachineBasicBlock>*) llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, true> >::UpdateRootsBeforeInsertion(llvm::DominatorTreeBase<llvm::BasicBlock, true>&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, true> >::BatchUpdateInfo*, llvm::DomTreeNodeBase<llvm::BasicBlock>*, llvm::DomTreeNodeBase<llvm::BasicBlock>*) Line | Count | Source | 684 | 230 | const TreeNodePtr To) { | 685 | 230 | assert(IsPostDom && "This function is only for postdominators"); | 686 | 230 | // Destination node is not attached to the virtual root, so it cannot be a | 687 | 230 | // root. | 688 | 230 | if (!DT.isVirtualRoot(To->getIDom())) return false130 ; | 689 | 100 | | 690 | 100 | auto RIt = llvm::find(DT.Roots, To->getBlock()); | 691 | 100 | if (RIt == DT.Roots.end()) | 692 | 15 | return false; // To is not a root, nothing to update. | 693 | 85 | | 694 | 85 | LLVM_DEBUG(dbgs() << "\t\tAfter the insertion, " << BlockNamePrinter(To) | 695 | 85 | << " is no longer a root\n\t\tRebuilding the tree!!!\n"); | 696 | 85 | | 697 | 85 | CalculateFromScratch(DT, BUI); | 698 | 85 | return true; | 699 | 85 | } |
Unexecuted instantiation: llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, false> >::UpdateRootsBeforeInsertion(llvm::DominatorTreeBase<llvm::BasicBlock, false>&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, false> >::BatchUpdateInfo*, llvm::DomTreeNodeBase<llvm::BasicBlock>*, llvm::DomTreeNodeBase<llvm::BasicBlock>*) |
700 | | |
701 | | static bool isPermutation(const SmallVectorImpl<NodePtr> &A, |
702 | 782 | const SmallVectorImpl<NodePtr> &B) { |
703 | 782 | if (A.size() != B.size()) |
704 | 11 | return false; |
705 | 771 | SmallPtrSet<NodePtr, 4> Set(A.begin(), A.end()); |
706 | 771 | for (NodePtr N : B) |
707 | 1.50k | if (Set.count(N) == 0) |
708 | 26 | return false; |
709 | 771 | return true745 ; |
710 | 771 | } Unexecuted instantiation: llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> >::isPermutation(llvm::SmallVectorImpl<llvm::MachineBasicBlock*> const&, llvm::SmallVectorImpl<llvm::MachineBasicBlock*> const&) Unexecuted instantiation: llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> >::isPermutation(llvm::SmallVectorImpl<llvm::MachineBasicBlock*> const&, llvm::SmallVectorImpl<llvm::MachineBasicBlock*> const&) llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, true> >::isPermutation(llvm::SmallVectorImpl<llvm::BasicBlock*> const&, llvm::SmallVectorImpl<llvm::BasicBlock*> const&) Line | Count | Source | 702 | 415 | const SmallVectorImpl<NodePtr> &B) { | 703 | 415 | if (A.size() != B.size()) | 704 | 11 | return false; | 705 | 404 | SmallPtrSet<NodePtr, 4> Set(A.begin(), A.end()); | 706 | 404 | for (NodePtr N : B) | 707 | 1.13k | if (Set.count(N) == 0) | 708 | 26 | return false; | 709 | 404 | return true378 ; | 710 | 404 | } |
llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, false> >::isPermutation(llvm::SmallVectorImpl<llvm::BasicBlock*> const&, llvm::SmallVectorImpl<llvm::BasicBlock*> const&) Line | Count | Source | 702 | 367 | const SmallVectorImpl<NodePtr> &B) { | 703 | 367 | if (A.size() != B.size()) | 704 | 0 | return false; | 705 | 367 | SmallPtrSet<NodePtr, 4> Set(A.begin(), A.end()); | 706 | 367 | for (NodePtr N : B) | 707 | 367 | if (Set.count(N) == 0) | 708 | 0 | return false; | 709 | 367 | return true; | 710 | 367 | } |
|
711 | | |
712 | | // Updates the set of roots after insertion or deletion. This ensures that |
713 | | // roots are the same when after a series of updates and when the tree would |
714 | | // be built from scratch. |
715 | 330 | static void UpdateRootsAfterUpdate(DomTreeT &DT, const BatchUpdatePtr BUI) { |
716 | 330 | assert(IsPostDom && "This function is only for postdominators"); |
717 | 330 | |
718 | 330 | // The tree has only trivial roots -- nothing to update. |
719 | 763 | if (std::none_of(DT.Roots.begin(), DT.Roots.end(), [BUI](const NodePtr N) 330 { |
720 | 763 | return HasForwardSuccessors(N, BUI); |
721 | 763 | })) Unexecuted instantiation: llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> >::UpdateRootsAfterUpdate(llvm::DominatorTreeBase<llvm::MachineBasicBlock, true>&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> >::BatchUpdateInfo*)::'lambda'(llvm::MachineBasicBlock*)::operator()(llvm::MachineBasicBlock*) const llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, true> >::UpdateRootsAfterUpdate(llvm::DominatorTreeBase<llvm::BasicBlock, true>&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, true> >::BatchUpdateInfo*)::'lambda'(llvm::BasicBlock*)::operator()(llvm::BasicBlock*) const Line | Count | Source | 719 | 763 | if (std::none_of(DT.Roots.begin(), DT.Roots.end(), [BUI](const NodePtr N) { | 720 | 763 | return HasForwardSuccessors(N, BUI); | 721 | 763 | })) |
|
722 | 263 | return; |
723 | 67 | |
724 | 67 | // Recalculate the set of roots. |
725 | 67 | RootsT Roots = FindRoots(DT, BUI); |
726 | 67 | if (!isPermutation(DT.Roots, Roots)) { |
727 | 37 | // The roots chosen in the CFG have changed. This is because the |
728 | 37 | // incremental algorithm does not really know or use the set of roots and |
729 | 37 | // can make a different (implicit) decision about which node within an |
730 | 37 | // infinite loop becomes a root. |
731 | 37 | |
732 | 37 | LLVM_DEBUG(dbgs() << "Roots are different in updated trees\n" |
733 | 37 | << "The entire tree needs to be rebuilt\n"); |
734 | 37 | // It may be possible to update the tree without recalculating it, but |
735 | 37 | // we do not know yet how to do it, and it happens rarely in practise. |
736 | 37 | CalculateFromScratch(DT, BUI); |
737 | 37 | } |
738 | 67 | } Unexecuted instantiation: llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> >::UpdateRootsAfterUpdate(llvm::DominatorTreeBase<llvm::MachineBasicBlock, false>&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> >::BatchUpdateInfo*) Unexecuted instantiation: llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> >::UpdateRootsAfterUpdate(llvm::DominatorTreeBase<llvm::MachineBasicBlock, true>&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> >::BatchUpdateInfo*) llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, true> >::UpdateRootsAfterUpdate(llvm::DominatorTreeBase<llvm::BasicBlock, true>&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, true> >::BatchUpdateInfo*) Line | Count | Source | 715 | 330 | static void UpdateRootsAfterUpdate(DomTreeT &DT, const BatchUpdatePtr BUI) { | 716 | 330 | assert(IsPostDom && "This function is only for postdominators"); | 717 | 330 | | 718 | 330 | // The tree has only trivial roots -- nothing to update. | 719 | 330 | if (std::none_of(DT.Roots.begin(), DT.Roots.end(), [BUI](const NodePtr N) { | 720 | 330 | return HasForwardSuccessors(N, BUI); | 721 | 330 | })) | 722 | 263 | return; | 723 | 67 | | 724 | 67 | // Recalculate the set of roots. | 725 | 67 | RootsT Roots = FindRoots(DT, BUI); | 726 | 67 | if (!isPermutation(DT.Roots, Roots)) { | 727 | 37 | // The roots chosen in the CFG have changed. This is because the | 728 | 37 | // incremental algorithm does not really know or use the set of roots and | 729 | 37 | // can make a different (implicit) decision about which node within an | 730 | 37 | // infinite loop becomes a root. | 731 | 37 | | 732 | 37 | LLVM_DEBUG(dbgs() << "Roots are different in updated trees\n" | 733 | 37 | << "The entire tree needs to be rebuilt\n"); | 734 | 37 | // It may be possible to update the tree without recalculating it, but | 735 | 37 | // we do not know yet how to do it, and it happens rarely in practise. | 736 | 37 | CalculateFromScratch(DT, BUI); | 737 | 37 | } | 738 | 67 | } |
Unexecuted instantiation: llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, false> >::UpdateRootsAfterUpdate(llvm::DominatorTreeBase<llvm::BasicBlock, false>&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, false> >::BatchUpdateInfo*) |
739 | | |
740 | | // Handles insertion to a node already in the dominator tree. |
741 | | static void InsertReachable(DomTreeT &DT, const BatchUpdatePtr BUI, |
742 | 519k | const TreeNodePtr From, const TreeNodePtr To) { |
743 | 519k | LLVM_DEBUG(dbgs() << "\tReachable " << BlockNamePrinter(From->getBlock()) |
744 | 519k | << " -> " << BlockNamePrinter(To->getBlock()) << "\n"); |
745 | 519k | if (IsPostDom && UpdateRootsBeforeInsertion(DT, BUI, From, To)230 ) return85 ; |
746 | 519k | // DT.findNCD expects both pointers to be valid. When From is a virtual |
747 | 519k | // root, then its CFG block pointer is a nullptr, so we have to 'compute' |
748 | 519k | // the NCD manually. |
749 | 519k | const NodePtr NCDBlock = |
750 | 519k | (From->getBlock() && To->getBlock()519k ) |
751 | 519k | ? DT.findNearestCommonDominator(From->getBlock(), To->getBlock())519k |
752 | 519k | : nullptr71 ; |
753 | 519k | assert(NCDBlock || DT.isPostDominator()); |
754 | 519k | const TreeNodePtr NCD = DT.getNode(NCDBlock); |
755 | 519k | assert(NCD); |
756 | 519k | |
757 | 519k | LLVM_DEBUG(dbgs() << "\t\tNCA == " << BlockNamePrinter(NCD) << "\n"); |
758 | 519k | const unsigned NCDLevel = NCD->getLevel(); |
759 | 519k | |
760 | 519k | // Based on Lemma 2.5 from the second paper, after insertion of (From,To), v |
761 | 519k | // is affected iff depth(NCD)+1 < depth(v) && a path P from To to v exists |
762 | 519k | // where every w on P s.t. depth(v) <= depth(w) |
763 | 519k | // |
764 | 519k | // This reduces to a widest path problem (maximizing the depth of the |
765 | 519k | // minimum vertex in the path) which can be solved by a modified version of |
766 | 519k | // Dijkstra with a bucket queue (named depth-based search in the paper). |
767 | 519k | |
768 | 519k | // To is in the path, so depth(NCD)+1 < depth(v) <= depth(To). Nothing |
769 | 519k | // affected if this does not hold. |
770 | 519k | if (NCDLevel + 1 >= To->getLevel()) |
771 | 189k | return; |
772 | 329k | |
773 | 329k | InsertionInfo II; |
774 | 329k | SmallVector<TreeNodePtr, 8> UnaffectedOnCurrentLevel; |
775 | 329k | II.Bucket.push(To); |
776 | 329k | II.Visited.insert(To); |
777 | 329k | |
778 | 671k | while (!II.Bucket.empty()) { |
779 | 341k | TreeNodePtr TN = II.Bucket.top(); |
780 | 341k | II.Bucket.pop(); |
781 | 341k | II.Affected.push_back(TN); |
782 | 341k | |
783 | 341k | const unsigned CurrentLevel = TN->getLevel(); |
784 | 341k | LLVM_DEBUG(dbgs() << "Mark " << BlockNamePrinter(TN) << |
785 | 341k | "as affected, CurrentLevel " << CurrentLevel << "\n"); |
786 | 341k | |
787 | 341k | assert(TN->getBlock() && II.Visited.count(TN) && "Preconditions!"); |
788 | 341k | |
789 | 9.43M | while (true) { |
790 | 9.43M | // Unlike regular Dijkstra, we have an inner loop to expand more |
791 | 9.43M | // vertices. The first iteration is for the (affected) vertex popped |
792 | 9.43M | // from II.Bucket and the rest are for vertices in |
793 | 9.43M | // UnaffectedOnCurrentLevel, which may eventually expand to affected |
794 | 9.43M | // vertices. |
795 | 9.43M | // |
796 | 9.43M | // Invariant: there is an optimal path from `To` to TN with the minimum |
797 | 9.43M | // depth being CurrentLevel. |
798 | 9.43M | for (const NodePtr Succ : |
799 | 10.4M | ChildrenGetter<IsPostDom>::Get(TN->getBlock(), BUI)) { |
800 | 10.4M | const TreeNodePtr SuccTN = DT.getNode(Succ); |
801 | 10.4M | assert(SuccTN && |
802 | 10.4M | "Unreachable successor found at reachable insertion"); |
803 | 10.4M | const unsigned SuccLevel = SuccTN->getLevel(); |
804 | 10.4M | |
805 | 10.4M | LLVM_DEBUG(dbgs() << "\tSuccessor " << BlockNamePrinter(Succ) |
806 | 10.4M | << ", level = " << SuccLevel << "\n"); |
807 | 10.4M | |
808 | 10.4M | // There is an optimal path from `To` to Succ with the minimum depth |
809 | 10.4M | // being min(CurrentLevel, SuccLevel). |
810 | 10.4M | // |
811 | 10.4M | // If depth(NCD)+1 < depth(Succ) is not satisfied, Succ is unaffected |
812 | 10.4M | // and no affected vertex may be reached by a path passing through it. |
813 | 10.4M | // Stop here. Also, Succ may be visited by other predecessors but the |
814 | 10.4M | // first visit has the optimal path. Stop if Succ has been visited. |
815 | 10.4M | if (SuccLevel <= NCDLevel + 1 || !II.Visited.insert(SuccTN).second9.99M ) |
816 | 1.34M | continue; |
817 | 9.10M | |
818 | 9.10M | if (SuccLevel > CurrentLevel) { |
819 | 9.09M | // Succ is unaffected but it may (transitively) expand to affected |
820 | 9.09M | // vertices. Store it in UnaffectedOnCurrentLevel. |
821 | 9.09M | LLVM_DEBUG(dbgs() << "\t\tMarking visited not affected " |
822 | 9.09M | << BlockNamePrinter(Succ) << "\n"); |
823 | 9.09M | UnaffectedOnCurrentLevel.push_back(SuccTN); |
824 | | #ifndef NDEBUG |
825 | | II.VisitedUnaffected.push_back(SuccTN); |
826 | | #endif |
827 | 11.5k | } else { |
828 | 11.5k | // The condition is satisfied (Succ is affected). Add Succ to the |
829 | 11.5k | // bucket queue. |
830 | 11.5k | LLVM_DEBUG(dbgs() << "\t\tAdd " << BlockNamePrinter(Succ) |
831 | 11.5k | << " to a Bucket\n"); |
832 | 11.5k | II.Bucket.push(SuccTN); |
833 | 11.5k | } |
834 | 9.10M | } |
835 | 9.43M | |
836 | 9.43M | if (UnaffectedOnCurrentLevel.empty()) |
837 | 341k | break; |
838 | 9.09M | TN = UnaffectedOnCurrentLevel.pop_back_val(); |
839 | 9.09M | LLVM_DEBUG(dbgs() << " Next: " << BlockNamePrinter(TN) << "\n"); |
840 | 9.09M | } |
841 | 341k | } |
842 | 329k | |
843 | 329k | // Finish by updating immediate dominators and levels. |
844 | 329k | UpdateInsertion(DT, BUI, NCD, II); |
845 | 329k | } Unexecuted instantiation: llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> >::InsertReachable(llvm::DominatorTreeBase<llvm::MachineBasicBlock, false>&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> >::BatchUpdateInfo*, llvm::DomTreeNodeBase<llvm::MachineBasicBlock>*, llvm::DomTreeNodeBase<llvm::MachineBasicBlock>*) Unexecuted instantiation: llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> >::InsertReachable(llvm::DominatorTreeBase<llvm::MachineBasicBlock, true>&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> >::BatchUpdateInfo*, llvm::DomTreeNodeBase<llvm::MachineBasicBlock>*, llvm::DomTreeNodeBase<llvm::MachineBasicBlock>*) llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, false> >::InsertReachable(llvm::DominatorTreeBase<llvm::BasicBlock, false>&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, false> >::BatchUpdateInfo*, llvm::DomTreeNodeBase<llvm::BasicBlock>*, llvm::DomTreeNodeBase<llvm::BasicBlock>*) Line | Count | Source | 742 | 519k | const TreeNodePtr From, const TreeNodePtr To) { | 743 | 519k | LLVM_DEBUG(dbgs() << "\tReachable " << BlockNamePrinter(From->getBlock()) | 744 | 519k | << " -> " << BlockNamePrinter(To->getBlock()) << "\n"); | 745 | 519k | if (IsPostDom && UpdateRootsBeforeInsertion(DT, BUI, From, To)0 ) return0 ; | 746 | 519k | // DT.findNCD expects both pointers to be valid. When From is a virtual | 747 | 519k | // root, then its CFG block pointer is a nullptr, so we have to 'compute' | 748 | 519k | // the NCD manually. | 749 | 519k | const NodePtr NCDBlock = | 750 | 519k | (From->getBlock() && To->getBlock()) | 751 | 519k | ? DT.findNearestCommonDominator(From->getBlock(), To->getBlock()) | 752 | 519k | : nullptr0 ; | 753 | 519k | assert(NCDBlock || DT.isPostDominator()); | 754 | 519k | const TreeNodePtr NCD = DT.getNode(NCDBlock); | 755 | 519k | assert(NCD); | 756 | 519k | | 757 | 519k | LLVM_DEBUG(dbgs() << "\t\tNCA == " << BlockNamePrinter(NCD) << "\n"); | 758 | 519k | const unsigned NCDLevel = NCD->getLevel(); | 759 | 519k | | 760 | 519k | // Based on Lemma 2.5 from the second paper, after insertion of (From,To), v | 761 | 519k | // is affected iff depth(NCD)+1 < depth(v) && a path P from To to v exists | 762 | 519k | // where every w on P s.t. depth(v) <= depth(w) | 763 | 519k | // | 764 | 519k | // This reduces to a widest path problem (maximizing the depth of the | 765 | 519k | // minimum vertex in the path) which can be solved by a modified version of | 766 | 519k | // Dijkstra with a bucket queue (named depth-based search in the paper). | 767 | 519k | | 768 | 519k | // To is in the path, so depth(NCD)+1 < depth(v) <= depth(To). Nothing | 769 | 519k | // affected if this does not hold. | 770 | 519k | if (NCDLevel + 1 >= To->getLevel()) | 771 | 189k | return; | 772 | 329k | | 773 | 329k | InsertionInfo II; | 774 | 329k | SmallVector<TreeNodePtr, 8> UnaffectedOnCurrentLevel; | 775 | 329k | II.Bucket.push(To); | 776 | 329k | II.Visited.insert(To); | 777 | 329k | | 778 | 671k | while (!II.Bucket.empty()) { | 779 | 341k | TreeNodePtr TN = II.Bucket.top(); | 780 | 341k | II.Bucket.pop(); | 781 | 341k | II.Affected.push_back(TN); | 782 | 341k | | 783 | 341k | const unsigned CurrentLevel = TN->getLevel(); | 784 | 341k | LLVM_DEBUG(dbgs() << "Mark " << BlockNamePrinter(TN) << | 785 | 341k | "as affected, CurrentLevel " << CurrentLevel << "\n"); | 786 | 341k | | 787 | 341k | assert(TN->getBlock() && II.Visited.count(TN) && "Preconditions!"); | 788 | 341k | | 789 | 9.43M | while (true) { | 790 | 9.43M | // Unlike regular Dijkstra, we have an inner loop to expand more | 791 | 9.43M | // vertices. The first iteration is for the (affected) vertex popped | 792 | 9.43M | // from II.Bucket and the rest are for vertices in | 793 | 9.43M | // UnaffectedOnCurrentLevel, which may eventually expand to affected | 794 | 9.43M | // vertices. | 795 | 9.43M | // | 796 | 9.43M | // Invariant: there is an optimal path from `To` to TN with the minimum | 797 | 9.43M | // depth being CurrentLevel. | 798 | 9.43M | for (const NodePtr Succ : | 799 | 10.4M | ChildrenGetter<IsPostDom>::Get(TN->getBlock(), BUI)) { | 800 | 10.4M | const TreeNodePtr SuccTN = DT.getNode(Succ); | 801 | 10.4M | assert(SuccTN && | 802 | 10.4M | "Unreachable successor found at reachable insertion"); | 803 | 10.4M | const unsigned SuccLevel = SuccTN->getLevel(); | 804 | 10.4M | | 805 | 10.4M | LLVM_DEBUG(dbgs() << "\tSuccessor " << BlockNamePrinter(Succ) | 806 | 10.4M | << ", level = " << SuccLevel << "\n"); | 807 | 10.4M | | 808 | 10.4M | // There is an optimal path from `To` to Succ with the minimum depth | 809 | 10.4M | // being min(CurrentLevel, SuccLevel). | 810 | 10.4M | // | 811 | 10.4M | // If depth(NCD)+1 < depth(Succ) is not satisfied, Succ is unaffected | 812 | 10.4M | // and no affected vertex may be reached by a path passing through it. | 813 | 10.4M | // Stop here. Also, Succ may be visited by other predecessors but the | 814 | 10.4M | // first visit has the optimal path. Stop if Succ has been visited. | 815 | 10.4M | if (SuccLevel <= NCDLevel + 1 || !II.Visited.insert(SuccTN).second9.99M ) | 816 | 1.34M | continue; | 817 | 9.10M | | 818 | 9.10M | if (SuccLevel > CurrentLevel) { | 819 | 9.09M | // Succ is unaffected but it may (transitively) expand to affected | 820 | 9.09M | // vertices. Store it in UnaffectedOnCurrentLevel. | 821 | 9.09M | LLVM_DEBUG(dbgs() << "\t\tMarking visited not affected " | 822 | 9.09M | << BlockNamePrinter(Succ) << "\n"); | 823 | 9.09M | UnaffectedOnCurrentLevel.push_back(SuccTN); | 824 | | #ifndef NDEBUG | 825 | | II.VisitedUnaffected.push_back(SuccTN); | 826 | | #endif | 827 | 11.5k | } else { | 828 | 11.5k | // The condition is satisfied (Succ is affected). Add Succ to the | 829 | 11.5k | // bucket queue. | 830 | 11.5k | LLVM_DEBUG(dbgs() << "\t\tAdd " << BlockNamePrinter(Succ) | 831 | 11.5k | << " to a Bucket\n"); | 832 | 11.5k | II.Bucket.push(SuccTN); | 833 | 11.5k | } | 834 | 9.10M | } | 835 | 9.43M | | 836 | 9.43M | if (UnaffectedOnCurrentLevel.empty()) | 837 | 341k | break; | 838 | 9.09M | TN = UnaffectedOnCurrentLevel.pop_back_val(); | 839 | 9.09M | LLVM_DEBUG(dbgs() << " Next: " << BlockNamePrinter(TN) << "\n"); | 840 | 9.09M | } | 841 | 341k | } | 842 | 329k | | 843 | 329k | // Finish by updating immediate dominators and levels. | 844 | 329k | UpdateInsertion(DT, BUI, NCD, II); | 845 | 329k | } |
llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, true> >::InsertReachable(llvm::DominatorTreeBase<llvm::BasicBlock, true>&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, true> >::BatchUpdateInfo*, llvm::DomTreeNodeBase<llvm::BasicBlock>*, llvm::DomTreeNodeBase<llvm::BasicBlock>*) Line | Count | Source | 742 | 230 | const TreeNodePtr From, const TreeNodePtr To) { | 743 | 230 | LLVM_DEBUG(dbgs() << "\tReachable " << BlockNamePrinter(From->getBlock()) | 744 | 230 | << " -> " << BlockNamePrinter(To->getBlock()) << "\n"); | 745 | 230 | if (IsPostDom && UpdateRootsBeforeInsertion(DT, BUI, From, To)) return85 ; | 746 | 145 | // DT.findNCD expects both pointers to be valid. When From is a virtual | 747 | 145 | // root, then its CFG block pointer is a nullptr, so we have to 'compute' | 748 | 145 | // the NCD manually. | 749 | 145 | const NodePtr NCDBlock = | 750 | 145 | (From->getBlock() && To->getBlock()74 ) | 751 | 145 | ? DT.findNearestCommonDominator(From->getBlock(), To->getBlock())74 | 752 | 145 | : nullptr71 ; | 753 | 145 | assert(NCDBlock || DT.isPostDominator()); | 754 | 145 | const TreeNodePtr NCD = DT.getNode(NCDBlock); | 755 | 145 | assert(NCD); | 756 | 145 | | 757 | 145 | LLVM_DEBUG(dbgs() << "\t\tNCA == " << BlockNamePrinter(NCD) << "\n"); | 758 | 145 | const unsigned NCDLevel = NCD->getLevel(); | 759 | 145 | | 760 | 145 | // Based on Lemma 2.5 from the second paper, after insertion of (From,To), v | 761 | 145 | // is affected iff depth(NCD)+1 < depth(v) && a path P from To to v exists | 762 | 145 | // where every w on P s.t. depth(v) <= depth(w) | 763 | 145 | // | 764 | 145 | // This reduces to a widest path problem (maximizing the depth of the | 765 | 145 | // minimum vertex in the path) which can be solved by a modified version of | 766 | 145 | // Dijkstra with a bucket queue (named depth-based search in the paper). | 767 | 145 | | 768 | 145 | // To is in the path, so depth(NCD)+1 < depth(v) <= depth(To). Nothing | 769 | 145 | // affected if this does not hold. | 770 | 145 | if (NCDLevel + 1 >= To->getLevel()) | 771 | 38 | return; | 772 | 107 | | 773 | 107 | InsertionInfo II; | 774 | 107 | SmallVector<TreeNodePtr, 8> UnaffectedOnCurrentLevel; | 775 | 107 | II.Bucket.push(To); | 776 | 107 | II.Visited.insert(To); | 777 | 107 | | 778 | 228 | while (!II.Bucket.empty()) { | 779 | 121 | TreeNodePtr TN = II.Bucket.top(); | 780 | 121 | II.Bucket.pop(); | 781 | 121 | II.Affected.push_back(TN); | 782 | 121 | | 783 | 121 | const unsigned CurrentLevel = TN->getLevel(); | 784 | 121 | LLVM_DEBUG(dbgs() << "Mark " << BlockNamePrinter(TN) << | 785 | 121 | "as affected, CurrentLevel " << CurrentLevel << "\n"); | 786 | 121 | | 787 | 121 | assert(TN->getBlock() && II.Visited.count(TN) && "Preconditions!"); | 788 | 121 | | 789 | 263 | while (true) { | 790 | 263 | // Unlike regular Dijkstra, we have an inner loop to expand more | 791 | 263 | // vertices. The first iteration is for the (affected) vertex popped | 792 | 263 | // from II.Bucket and the rest are for vertices in | 793 | 263 | // UnaffectedOnCurrentLevel, which may eventually expand to affected | 794 | 263 | // vertices. | 795 | 263 | // | 796 | 263 | // Invariant: there is an optimal path from `To` to TN with the minimum | 797 | 263 | // depth being CurrentLevel. | 798 | 263 | for (const NodePtr Succ : | 799 | 263 | ChildrenGetter<IsPostDom>::Get(TN->getBlock(), BUI)) { | 800 | 227 | const TreeNodePtr SuccTN = DT.getNode(Succ); | 801 | 227 | assert(SuccTN && | 802 | 227 | "Unreachable successor found at reachable insertion"); | 803 | 227 | const unsigned SuccLevel = SuccTN->getLevel(); | 804 | 227 | | 805 | 227 | LLVM_DEBUG(dbgs() << "\tSuccessor " << BlockNamePrinter(Succ) | 806 | 227 | << ", level = " << SuccLevel << "\n"); | 807 | 227 | | 808 | 227 | // There is an optimal path from `To` to Succ with the minimum depth | 809 | 227 | // being min(CurrentLevel, SuccLevel). | 810 | 227 | // | 811 | 227 | // If depth(NCD)+1 < depth(Succ) is not satisfied, Succ is unaffected | 812 | 227 | // and no affected vertex may be reached by a path passing through it. | 813 | 227 | // Stop here. Also, Succ may be visited by other predecessors but the | 814 | 227 | // first visit has the optimal path. Stop if Succ has been visited. | 815 | 227 | if (SuccLevel <= NCDLevel + 1 || !II.Visited.insert(SuccTN).second184 ) | 816 | 71 | continue; | 817 | 156 | | 818 | 156 | if (SuccLevel > CurrentLevel) { | 819 | 142 | // Succ is unaffected but it may (transitively) expand to affected | 820 | 142 | // vertices. Store it in UnaffectedOnCurrentLevel. | 821 | 142 | LLVM_DEBUG(dbgs() << "\t\tMarking visited not affected " | 822 | 142 | << BlockNamePrinter(Succ) << "\n"); | 823 | 142 | UnaffectedOnCurrentLevel.push_back(SuccTN); | 824 | | #ifndef NDEBUG | 825 | | II.VisitedUnaffected.push_back(SuccTN); | 826 | | #endif | 827 | 14 | } else { | 828 | 14 | // The condition is satisfied (Succ is affected). Add Succ to the | 829 | 14 | // bucket queue. | 830 | 14 | LLVM_DEBUG(dbgs() << "\t\tAdd " << BlockNamePrinter(Succ) | 831 | 14 | << " to a Bucket\n"); | 832 | 14 | II.Bucket.push(SuccTN); | 833 | 14 | } | 834 | 156 | } | 835 | 263 | | 836 | 263 | if (UnaffectedOnCurrentLevel.empty()) | 837 | 121 | break; | 838 | 142 | TN = UnaffectedOnCurrentLevel.pop_back_val(); | 839 | 142 | LLVM_DEBUG(dbgs() << " Next: " << BlockNamePrinter(TN) << "\n"); | 840 | 142 | } | 841 | 121 | } | 842 | 107 | | 843 | 107 | // Finish by updating immediate dominators and levels. | 844 | 107 | UpdateInsertion(DT, BUI, NCD, II); | 845 | 107 | } |
|
846 | | |
847 | | // Updates immediate dominators and levels after insertion. |
848 | | static void UpdateInsertion(DomTreeT &DT, const BatchUpdatePtr BUI, |
849 | 329k | const TreeNodePtr NCD, InsertionInfo &II) { |
850 | 329k | LLVM_DEBUG(dbgs() << "Updating NCD = " << BlockNamePrinter(NCD) << "\n"); |
851 | 329k | |
852 | 341k | for (const TreeNodePtr TN : II.Affected) { |
853 | 341k | LLVM_DEBUG(dbgs() << "\tIDom(" << BlockNamePrinter(TN) |
854 | 341k | << ") = " << BlockNamePrinter(NCD) << "\n"); |
855 | 341k | TN->setIDom(NCD); |
856 | 341k | } |
857 | 329k | |
858 | | #ifndef NDEBUG |
859 | | for (const TreeNodePtr TN : II.VisitedUnaffected) |
860 | | assert(TN->getLevel() == TN->getIDom()->getLevel() + 1 && |
861 | | "TN should have been updated by an affected ancestor"); |
862 | | #endif |
863 | | |
864 | 329k | if (IsPostDom) UpdateRootsAfterUpdate(DT, BUI)107 ; |
865 | 329k | } Unexecuted instantiation: llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> >::UpdateInsertion(llvm::DominatorTreeBase<llvm::MachineBasicBlock, false>&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> >::BatchUpdateInfo*, llvm::DomTreeNodeBase<llvm::MachineBasicBlock>*, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> >::InsertionInfo&) Unexecuted instantiation: llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> >::UpdateInsertion(llvm::DominatorTreeBase<llvm::MachineBasicBlock, true>&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> >::BatchUpdateInfo*, llvm::DomTreeNodeBase<llvm::MachineBasicBlock>*, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> >::InsertionInfo&) llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, false> >::UpdateInsertion(llvm::DominatorTreeBase<llvm::BasicBlock, false>&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, false> >::BatchUpdateInfo*, llvm::DomTreeNodeBase<llvm::BasicBlock>*, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, false> >::InsertionInfo&) Line | Count | Source | 849 | 329k | const TreeNodePtr NCD, InsertionInfo &II) { | 850 | 329k | LLVM_DEBUG(dbgs() << "Updating NCD = " << BlockNamePrinter(NCD) << "\n"); | 851 | 329k | | 852 | 341k | for (const TreeNodePtr TN : II.Affected) { | 853 | 341k | LLVM_DEBUG(dbgs() << "\tIDom(" << BlockNamePrinter(TN) | 854 | 341k | << ") = " << BlockNamePrinter(NCD) << "\n"); | 855 | 341k | TN->setIDom(NCD); | 856 | 341k | } | 857 | 329k | | 858 | | #ifndef NDEBUG | 859 | | for (const TreeNodePtr TN : II.VisitedUnaffected) | 860 | | assert(TN->getLevel() == TN->getIDom()->getLevel() + 1 && | 861 | | "TN should have been updated by an affected ancestor"); | 862 | | #endif | 863 | | | 864 | 329k | if (IsPostDom) UpdateRootsAfterUpdate(DT, BUI)0 ; | 865 | 329k | } |
llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, true> >::UpdateInsertion(llvm::DominatorTreeBase<llvm::BasicBlock, true>&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, true> >::BatchUpdateInfo*, llvm::DomTreeNodeBase<llvm::BasicBlock>*, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, true> >::InsertionInfo&) Line | Count | Source | 849 | 107 | const TreeNodePtr NCD, InsertionInfo &II) { | 850 | 107 | LLVM_DEBUG(dbgs() << "Updating NCD = " << BlockNamePrinter(NCD) << "\n"); | 851 | 107 | | 852 | 121 | for (const TreeNodePtr TN : II.Affected) { | 853 | 121 | LLVM_DEBUG(dbgs() << "\tIDom(" << BlockNamePrinter(TN) | 854 | 121 | << ") = " << BlockNamePrinter(NCD) << "\n"); | 855 | 121 | TN->setIDom(NCD); | 856 | 121 | } | 857 | 107 | | 858 | | #ifndef NDEBUG | 859 | | for (const TreeNodePtr TN : II.VisitedUnaffected) | 860 | | assert(TN->getLevel() == TN->getIDom()->getLevel() + 1 && | 861 | | "TN should have been updated by an affected ancestor"); | 862 | | #endif | 863 | | | 864 | 107 | if (IsPostDom) UpdateRootsAfterUpdate(DT, BUI); | 865 | 107 | } |
|
866 | | |
867 | | // Handles insertion to previously unreachable nodes. |
868 | | static void InsertUnreachable(DomTreeT &DT, const BatchUpdatePtr BUI, |
869 | 114k | const TreeNodePtr From, const NodePtr To) { |
870 | 114k | LLVM_DEBUG(dbgs() << "Inserting " << BlockNamePrinter(From) |
871 | 114k | << " -> (unreachable) " << BlockNamePrinter(To) << "\n"); |
872 | 114k | |
873 | 114k | // Collect discovered edges to already reachable nodes. |
874 | 114k | SmallVector<std::pair<NodePtr, TreeNodePtr>, 8> DiscoveredEdgesToReachable; |
875 | 114k | // Discover and connect nodes that became reachable with the insertion. |
876 | 114k | ComputeUnreachableDominators(DT, BUI, To, From, DiscoveredEdgesToReachable); |
877 | 114k | |
878 | 114k | LLVM_DEBUG(dbgs() << "Inserted " << BlockNamePrinter(From) |
879 | 114k | << " -> (prev unreachable) " << BlockNamePrinter(To) |
880 | 114k | << "\n"); |
881 | 114k | |
882 | 114k | // Used the discovered edges and inset discovered connecting (incoming) |
883 | 114k | // edges. |
884 | 114k | for (const auto &Edge : DiscoveredEdgesToReachable) { |
885 | 25.4k | LLVM_DEBUG(dbgs() << "\tInserting discovered connecting edge " |
886 | 25.4k | << BlockNamePrinter(Edge.first) << " -> " |
887 | 25.4k | << BlockNamePrinter(Edge.second) << "\n"); |
888 | 25.4k | InsertReachable(DT, BUI, DT.getNode(Edge.first), Edge.second); |
889 | 25.4k | } |
890 | 114k | } Unexecuted instantiation: llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> >::InsertUnreachable(llvm::DominatorTreeBase<llvm::MachineBasicBlock, false>&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> >::BatchUpdateInfo*, llvm::DomTreeNodeBase<llvm::MachineBasicBlock>*, llvm::MachineBasicBlock*) Unexecuted instantiation: llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> >::InsertUnreachable(llvm::DominatorTreeBase<llvm::MachineBasicBlock, true>&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> >::BatchUpdateInfo*, llvm::DomTreeNodeBase<llvm::MachineBasicBlock>*, llvm::MachineBasicBlock*) llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, false> >::InsertUnreachable(llvm::DominatorTreeBase<llvm::BasicBlock, false>&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, false> >::BatchUpdateInfo*, llvm::DomTreeNodeBase<llvm::BasicBlock>*, llvm::BasicBlock*) Line | Count | Source | 869 | 114k | const TreeNodePtr From, const NodePtr To) { | 870 | 114k | LLVM_DEBUG(dbgs() << "Inserting " << BlockNamePrinter(From) | 871 | 114k | << " -> (unreachable) " << BlockNamePrinter(To) << "\n"); | 872 | 114k | | 873 | 114k | // Collect discovered edges to already reachable nodes. | 874 | 114k | SmallVector<std::pair<NodePtr, TreeNodePtr>, 8> DiscoveredEdgesToReachable; | 875 | 114k | // Discover and connect nodes that became reachable with the insertion. | 876 | 114k | ComputeUnreachableDominators(DT, BUI, To, From, DiscoveredEdgesToReachable); | 877 | 114k | | 878 | 114k | LLVM_DEBUG(dbgs() << "Inserted " << BlockNamePrinter(From) | 879 | 114k | << " -> (prev unreachable) " << BlockNamePrinter(To) | 880 | 114k | << "\n"); | 881 | 114k | | 882 | 114k | // Used the discovered edges and inset discovered connecting (incoming) | 883 | 114k | // edges. | 884 | 114k | for (const auto &Edge : DiscoveredEdgesToReachable) { | 885 | 25.4k | LLVM_DEBUG(dbgs() << "\tInserting discovered connecting edge " | 886 | 25.4k | << BlockNamePrinter(Edge.first) << " -> " | 887 | 25.4k | << BlockNamePrinter(Edge.second) << "\n"); | 888 | 25.4k | InsertReachable(DT, BUI, DT.getNode(Edge.first), Edge.second); | 889 | 25.4k | } | 890 | 114k | } |
llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, true> >::InsertUnreachable(llvm::DominatorTreeBase<llvm::BasicBlock, true>&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, true> >::BatchUpdateInfo*, llvm::DomTreeNodeBase<llvm::BasicBlock>*, llvm::BasicBlock*) Line | Count | Source | 869 | 3 | const TreeNodePtr From, const NodePtr To) { | 870 | 3 | LLVM_DEBUG(dbgs() << "Inserting " << BlockNamePrinter(From) | 871 | 3 | << " -> (unreachable) " << BlockNamePrinter(To) << "\n"); | 872 | 3 | | 873 | 3 | // Collect discovered edges to already reachable nodes. | 874 | 3 | SmallVector<std::pair<NodePtr, TreeNodePtr>, 8> DiscoveredEdgesToReachable; | 875 | 3 | // Discover and connect nodes that became reachable with the insertion. | 876 | 3 | ComputeUnreachableDominators(DT, BUI, To, From, DiscoveredEdgesToReachable); | 877 | 3 | | 878 | 3 | LLVM_DEBUG(dbgs() << "Inserted " << BlockNamePrinter(From) | 879 | 3 | << " -> (prev unreachable) " << BlockNamePrinter(To) | 880 | 3 | << "\n"); | 881 | 3 | | 882 | 3 | // Used the discovered edges and inset discovered connecting (incoming) | 883 | 3 | // edges. | 884 | 3 | for (const auto &Edge : DiscoveredEdgesToReachable) { | 885 | 0 | LLVM_DEBUG(dbgs() << "\tInserting discovered connecting edge " | 886 | 0 | << BlockNamePrinter(Edge.first) << " -> " | 887 | 0 | << BlockNamePrinter(Edge.second) << "\n"); | 888 | 0 | InsertReachable(DT, BUI, DT.getNode(Edge.first), Edge.second); | 889 | 0 | } | 890 | 3 | } |
|
891 | | |
892 | | // Connects nodes that become reachable with an insertion. |
893 | | static void ComputeUnreachableDominators( |
894 | | DomTreeT &DT, const BatchUpdatePtr BUI, const NodePtr Root, |
895 | | const TreeNodePtr Incoming, |
896 | | SmallVectorImpl<std::pair<NodePtr, TreeNodePtr>> |
897 | 114k | &DiscoveredConnectingEdges) { |
898 | 114k | assert(!DT.getNode(Root) && "Root must not be reachable"); |
899 | 114k | |
900 | 114k | // Visit only previously unreachable nodes. |
901 | 114k | auto UnreachableDescender = [&DT, &DiscoveredConnectingEdges](NodePtr From, |
902 | 150k | NodePtr To) { |
903 | 150k | const TreeNodePtr ToTN = DT.getNode(To); |
904 | 150k | if (!ToTN) return true125k ; |
905 | 25.4k | |
906 | 25.4k | DiscoveredConnectingEdges.push_back({From, ToTN}); |
907 | 25.4k | return false; |
908 | 25.4k | }; Unexecuted instantiation: llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> >::ComputeUnreachableDominators(llvm::DominatorTreeBase<llvm::MachineBasicBlock, false>&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> >::BatchUpdateInfo*, llvm::MachineBasicBlock*, llvm::DomTreeNodeBase<llvm::MachineBasicBlock>*, llvm::SmallVectorImpl<std::__1::pair<llvm::MachineBasicBlock*, llvm::DomTreeNodeBase<llvm::MachineBasicBlock>*> >&)::'lambda'(llvm::MachineBasicBlock*, llvm::MachineBasicBlock*)::operator()(llvm::MachineBasicBlock*, llvm::MachineBasicBlock*) const Unexecuted instantiation: llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> >::ComputeUnreachableDominators(llvm::DominatorTreeBase<llvm::MachineBasicBlock, true>&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> >::BatchUpdateInfo*, llvm::MachineBasicBlock*, llvm::DomTreeNodeBase<llvm::MachineBasicBlock>*, llvm::SmallVectorImpl<std::__1::pair<llvm::MachineBasicBlock*, llvm::DomTreeNodeBase<llvm::MachineBasicBlock>*> >&)::'lambda'(llvm::MachineBasicBlock*, llvm::MachineBasicBlock*)::operator()(llvm::MachineBasicBlock*, llvm::MachineBasicBlock*) const llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, false> >::ComputeUnreachableDominators(llvm::DominatorTreeBase<llvm::BasicBlock, false>&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, false> >::BatchUpdateInfo*, llvm::BasicBlock*, llvm::DomTreeNodeBase<llvm::BasicBlock>*, llvm::SmallVectorImpl<std::__1::pair<llvm::BasicBlock*, llvm::DomTreeNodeBase<llvm::BasicBlock>*> >&)::'lambda'(llvm::BasicBlock*, llvm::BasicBlock*)::operator()(llvm::BasicBlock*, llvm::BasicBlock*) const Line | Count | Source | 902 | 150k | NodePtr To) { | 903 | 150k | const TreeNodePtr ToTN = DT.getNode(To); | 904 | 150k | if (!ToTN) return true125k ; | 905 | 25.4k | | 906 | 25.4k | DiscoveredConnectingEdges.push_back({From, ToTN}); | 907 | 25.4k | return false; | 908 | 25.4k | }; |
Unexecuted instantiation: llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, true> >::ComputeUnreachableDominators(llvm::DominatorTreeBase<llvm::BasicBlock, true>&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, true> >::BatchUpdateInfo*, llvm::BasicBlock*, llvm::DomTreeNodeBase<llvm::BasicBlock>*, llvm::SmallVectorImpl<std::__1::pair<llvm::BasicBlock*, llvm::DomTreeNodeBase<llvm::BasicBlock>*> >&)::'lambda'(llvm::BasicBlock*, llvm::BasicBlock*)::operator()(llvm::BasicBlock*, llvm::BasicBlock*) const |
909 | 114k | |
910 | 114k | SemiNCAInfo SNCA(BUI); |
911 | 114k | SNCA.runDFS(Root, 0, UnreachableDescender, 0); |
912 | 114k | SNCA.runSemiNCA(DT); |
913 | 114k | SNCA.attachNewSubtree(DT, Incoming); |
914 | 114k | |
915 | 114k | LLVM_DEBUG(dbgs() << "After adding unreachable nodes\n"); |
916 | 114k | } Unexecuted instantiation: llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> >::ComputeUnreachableDominators(llvm::DominatorTreeBase<llvm::MachineBasicBlock, false>&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> >::BatchUpdateInfo*, llvm::MachineBasicBlock*, llvm::DomTreeNodeBase<llvm::MachineBasicBlock>*, llvm::SmallVectorImpl<std::__1::pair<llvm::MachineBasicBlock*, llvm::DomTreeNodeBase<llvm::MachineBasicBlock>*> >&) Unexecuted instantiation: llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> >::ComputeUnreachableDominators(llvm::DominatorTreeBase<llvm::MachineBasicBlock, true>&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> >::BatchUpdateInfo*, llvm::MachineBasicBlock*, llvm::DomTreeNodeBase<llvm::MachineBasicBlock>*, llvm::SmallVectorImpl<std::__1::pair<llvm::MachineBasicBlock*, llvm::DomTreeNodeBase<llvm::MachineBasicBlock>*> >&) llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, false> >::ComputeUnreachableDominators(llvm::DominatorTreeBase<llvm::BasicBlock, false>&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, false> >::BatchUpdateInfo*, llvm::BasicBlock*, llvm::DomTreeNodeBase<llvm::BasicBlock>*, llvm::SmallVectorImpl<std::__1::pair<llvm::BasicBlock*, llvm::DomTreeNodeBase<llvm::BasicBlock>*> >&) Line | Count | Source | 897 | 114k | &DiscoveredConnectingEdges) { | 898 | 114k | assert(!DT.getNode(Root) && "Root must not be reachable"); | 899 | 114k | | 900 | 114k | // Visit only previously unreachable nodes. | 901 | 114k | auto UnreachableDescender = [&DT, &DiscoveredConnectingEdges](NodePtr From, | 902 | 114k | NodePtr To) { | 903 | 114k | const TreeNodePtr ToTN = DT.getNode(To); | 904 | 114k | if (!ToTN) return true; | 905 | 114k | | 906 | 114k | DiscoveredConnectingEdges.push_back({From, ToTN}); | 907 | 114k | return false; | 908 | 114k | }; | 909 | 114k | | 910 | 114k | SemiNCAInfo SNCA(BUI); | 911 | 114k | SNCA.runDFS(Root, 0, UnreachableDescender, 0); | 912 | 114k | SNCA.runSemiNCA(DT); | 913 | 114k | SNCA.attachNewSubtree(DT, Incoming); | 914 | 114k | | 915 | 114k | LLVM_DEBUG(dbgs() << "After adding unreachable nodes\n"); | 916 | 114k | } |
llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, true> >::ComputeUnreachableDominators(llvm::DominatorTreeBase<llvm::BasicBlock, true>&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, true> >::BatchUpdateInfo*, llvm::BasicBlock*, llvm::DomTreeNodeBase<llvm::BasicBlock>*, llvm::SmallVectorImpl<std::__1::pair<llvm::BasicBlock*, llvm::DomTreeNodeBase<llvm::BasicBlock>*> >&) Line | Count | Source | 897 | 3 | &DiscoveredConnectingEdges) { | 898 | 3 | assert(!DT.getNode(Root) && "Root must not be reachable"); | 899 | 3 | | 900 | 3 | // Visit only previously unreachable nodes. | 901 | 3 | auto UnreachableDescender = [&DT, &DiscoveredConnectingEdges](NodePtr From, | 902 | 3 | NodePtr To) { | 903 | 3 | const TreeNodePtr ToTN = DT.getNode(To); | 904 | 3 | if (!ToTN) return true; | 905 | 3 | | 906 | 3 | DiscoveredConnectingEdges.push_back({From, ToTN}); | 907 | 3 | return false; | 908 | 3 | }; | 909 | 3 | | 910 | 3 | SemiNCAInfo SNCA(BUI); | 911 | 3 | SNCA.runDFS(Root, 0, UnreachableDescender, 0); | 912 | 3 | SNCA.runSemiNCA(DT); | 913 | 3 | SNCA.attachNewSubtree(DT, Incoming); | 914 | 3 | | 915 | 3 | LLVM_DEBUG(dbgs() << "After adding unreachable nodes\n"); | 916 | 3 | } |
|
917 | | |
918 | | static void DeleteEdge(DomTreeT &DT, const BatchUpdatePtr BUI, |
919 | 841k | const NodePtr From, const NodePtr To) { |
920 | 841k | assert(From && To && "Cannot disconnect nullptrs"); |
921 | 841k | LLVM_DEBUG(dbgs() << "Deleting edge " << BlockNamePrinter(From) << " -> " |
922 | 841k | << BlockNamePrinter(To) << "\n"); |
923 | 841k | |
924 | | #ifndef NDEBUG |
925 | | // Ensure that the edge was in fact deleted from the CFG before informing |
926 | | // the DomTree about it. |
927 | | // The check is O(N), so run it only in debug configuration. |
928 | | auto IsSuccessor = [BUI](const NodePtr SuccCandidate, const NodePtr Of) { |
929 | | auto Successors = ChildrenGetter<IsPostDom>::Get(Of, BUI); |
930 | | return llvm::find(Successors, SuccCandidate) != Successors.end(); |
931 | | }; |
932 | | (void)IsSuccessor; |
933 | | assert(!IsSuccessor(To, From) && "Deleted edge still exists in the CFG!"); |
934 | | #endif |
935 | | |
936 | 841k | const TreeNodePtr FromTN = DT.getNode(From); |
937 | 841k | // Deletion in an unreachable subtree -- nothing to do. |
938 | 841k | if (!FromTN) return8.22k ; |
939 | 833k | |
940 | 833k | const TreeNodePtr ToTN = DT.getNode(To); |
941 | 833k | if (!ToTN) { |
942 | 0 | LLVM_DEBUG( |
943 | 0 | dbgs() << "\tTo (" << BlockNamePrinter(To) |
944 | 0 | << ") already unreachable -- there is no edge to delete\n"); |
945 | 0 | return; |
946 | 0 | } |
947 | 833k | |
948 | 833k | const NodePtr NCDBlock = DT.findNearestCommonDominator(From, To); |
949 | 833k | const TreeNodePtr NCD = DT.getNode(NCDBlock); |
950 | 833k | |
951 | 833k | // If To dominates From -- nothing to do. |
952 | 833k | if (ToTN != NCD) { |
953 | 790k | DT.DFSInfoValid = false; |
954 | 790k | |
955 | 790k | const TreeNodePtr ToIDom = ToTN->getIDom(); |
956 | 790k | LLVM_DEBUG(dbgs() << "\tNCD " << BlockNamePrinter(NCD) << ", ToIDom " |
957 | 790k | << BlockNamePrinter(ToIDom) << "\n"); |
958 | 790k | |
959 | 790k | // To remains reachable after deletion. |
960 | 790k | // (Based on the caption under Figure 4. from the second paper.) |
961 | 790k | if (FromTN != ToIDom || HasProperSupport(DT, BUI, ToTN)414k ) |
962 | 487k | DeleteReachable(DT, BUI, FromTN, ToTN); |
963 | 303k | else |
964 | 303k | DeleteUnreachable(DT, BUI, ToTN); |
965 | 790k | } |
966 | 833k | |
967 | 833k | if (IsPostDom) UpdateRootsAfterUpdate(DT, BUI)223 ; |
968 | 833k | } Unexecuted instantiation: llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> >::DeleteEdge(llvm::DominatorTreeBase<llvm::MachineBasicBlock, false>&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> >::BatchUpdateInfo*, llvm::MachineBasicBlock*, llvm::MachineBasicBlock*) Unexecuted instantiation: llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> >::DeleteEdge(llvm::DominatorTreeBase<llvm::MachineBasicBlock, true>&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> >::BatchUpdateInfo*, llvm::MachineBasicBlock*, llvm::MachineBasicBlock*) llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, false> >::DeleteEdge(llvm::DominatorTreeBase<llvm::BasicBlock, false>&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, false> >::BatchUpdateInfo*, llvm::BasicBlock*, llvm::BasicBlock*) Line | Count | Source | 919 | 841k | const NodePtr From, const NodePtr To) { | 920 | 841k | assert(From && To && "Cannot disconnect nullptrs"); | 921 | 841k | LLVM_DEBUG(dbgs() << "Deleting edge " << BlockNamePrinter(From) << " -> " | 922 | 841k | << BlockNamePrinter(To) << "\n"); | 923 | 841k | | 924 | | #ifndef NDEBUG | 925 | | // Ensure that the edge was in fact deleted from the CFG before informing | 926 | | // the DomTree about it. | 927 | | // The check is O(N), so run it only in debug configuration. | 928 | | auto IsSuccessor = [BUI](const NodePtr SuccCandidate, const NodePtr Of) { | 929 | | auto Successors = ChildrenGetter<IsPostDom>::Get(Of, BUI); | 930 | | return llvm::find(Successors, SuccCandidate) != Successors.end(); | 931 | | }; | 932 | | (void)IsSuccessor; | 933 | | assert(!IsSuccessor(To, From) && "Deleted edge still exists in the CFG!"); | 934 | | #endif | 935 | | | 936 | 841k | const TreeNodePtr FromTN = DT.getNode(From); | 937 | 841k | // Deletion in an unreachable subtree -- nothing to do. | 938 | 841k | if (!FromTN) return8.22k ; | 939 | 832k | | 940 | 832k | const TreeNodePtr ToTN = DT.getNode(To); | 941 | 832k | if (!ToTN) { | 942 | 0 | LLVM_DEBUG( | 943 | 0 | dbgs() << "\tTo (" << BlockNamePrinter(To) | 944 | 0 | << ") already unreachable -- there is no edge to delete\n"); | 945 | 0 | return; | 946 | 0 | } | 947 | 832k | | 948 | 832k | const NodePtr NCDBlock = DT.findNearestCommonDominator(From, To); | 949 | 832k | const TreeNodePtr NCD = DT.getNode(NCDBlock); | 950 | 832k | | 951 | 832k | // If To dominates From -- nothing to do. | 952 | 832k | if (ToTN != NCD) { | 953 | 790k | DT.DFSInfoValid = false; | 954 | 790k | | 955 | 790k | const TreeNodePtr ToIDom = ToTN->getIDom(); | 956 | 790k | LLVM_DEBUG(dbgs() << "\tNCD " << BlockNamePrinter(NCD) << ", ToIDom " | 957 | 790k | << BlockNamePrinter(ToIDom) << "\n"); | 958 | 790k | | 959 | 790k | // To remains reachable after deletion. | 960 | 790k | // (Based on the caption under Figure 4. from the second paper.) | 961 | 790k | if (FromTN != ToIDom || HasProperSupport(DT, BUI, ToTN)414k ) | 962 | 487k | DeleteReachable(DT, BUI, FromTN, ToTN); | 963 | 303k | else | 964 | 303k | DeleteUnreachable(DT, BUI, ToTN); | 965 | 790k | } | 966 | 832k | | 967 | 832k | if (IsPostDom) UpdateRootsAfterUpdate(DT, BUI)0 ; | 968 | 832k | } |
llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, true> >::DeleteEdge(llvm::DominatorTreeBase<llvm::BasicBlock, true>&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, true> >::BatchUpdateInfo*, llvm::BasicBlock*, llvm::BasicBlock*) Line | Count | Source | 919 | 223 | const NodePtr From, const NodePtr To) { | 920 | 223 | assert(From && To && "Cannot disconnect nullptrs"); | 921 | 223 | LLVM_DEBUG(dbgs() << "Deleting edge " << BlockNamePrinter(From) << " -> " | 922 | 223 | << BlockNamePrinter(To) << "\n"); | 923 | 223 | | 924 | | #ifndef NDEBUG | 925 | | // Ensure that the edge was in fact deleted from the CFG before informing | 926 | | // the DomTree about it. | 927 | | // The check is O(N), so run it only in debug configuration. | 928 | | auto IsSuccessor = [BUI](const NodePtr SuccCandidate, const NodePtr Of) { | 929 | | auto Successors = ChildrenGetter<IsPostDom>::Get(Of, BUI); | 930 | | return llvm::find(Successors, SuccCandidate) != Successors.end(); | 931 | | }; | 932 | | (void)IsSuccessor; | 933 | | assert(!IsSuccessor(To, From) && "Deleted edge still exists in the CFG!"); | 934 | | #endif | 935 | | | 936 | 223 | const TreeNodePtr FromTN = DT.getNode(From); | 937 | 223 | // Deletion in an unreachable subtree -- nothing to do. | 938 | 223 | if (!FromTN) return0 ; | 939 | 223 | | 940 | 223 | const TreeNodePtr ToTN = DT.getNode(To); | 941 | 223 | if (!ToTN) { | 942 | 0 | LLVM_DEBUG( | 943 | 0 | dbgs() << "\tTo (" << BlockNamePrinter(To) | 944 | 0 | << ") already unreachable -- there is no edge to delete\n"); | 945 | 0 | return; | 946 | 0 | } | 947 | 223 | | 948 | 223 | const NodePtr NCDBlock = DT.findNearestCommonDominator(From, To); | 949 | 223 | const TreeNodePtr NCD = DT.getNode(NCDBlock); | 950 | 223 | | 951 | 223 | // If To dominates From -- nothing to do. | 952 | 223 | if (ToTN != NCD) { | 953 | 215 | DT.DFSInfoValid = false; | 954 | 215 | | 955 | 215 | const TreeNodePtr ToIDom = ToTN->getIDom(); | 956 | 215 | LLVM_DEBUG(dbgs() << "\tNCD " << BlockNamePrinter(NCD) << ", ToIDom " | 957 | 215 | << BlockNamePrinter(ToIDom) << "\n"); | 958 | 215 | | 959 | 215 | // To remains reachable after deletion. | 960 | 215 | // (Based on the caption under Figure 4. from the second paper.) | 961 | 215 | if (FromTN != ToIDom || HasProperSupport(DT, BUI, ToTN)74 ) | 962 | 144 | DeleteReachable(DT, BUI, FromTN, ToTN); | 963 | 71 | else | 964 | 71 | DeleteUnreachable(DT, BUI, ToTN); | 965 | 215 | } | 966 | 223 | | 967 | 223 | if (IsPostDom) UpdateRootsAfterUpdate(DT, BUI); | 968 | 223 | } |
|
969 | | |
970 | | // Handles deletions that leave destination nodes reachable. |
971 | | static void DeleteReachable(DomTreeT &DT, const BatchUpdatePtr BUI, |
972 | | const TreeNodePtr FromTN, |
973 | 487k | const TreeNodePtr ToTN) { |
974 | 487k | LLVM_DEBUG(dbgs() << "Deleting reachable " << BlockNamePrinter(FromTN) |
975 | 487k | << " -> " << BlockNamePrinter(ToTN) << "\n"); |
976 | 487k | LLVM_DEBUG(dbgs() << "\tRebuilding subtree\n"); |
977 | 487k | |
978 | 487k | // Find the top of the subtree that needs to be rebuilt. |
979 | 487k | // (Based on the lemma 2.6 from the second paper.) |
980 | 487k | const NodePtr ToIDom = |
981 | 487k | DT.findNearestCommonDominator(FromTN->getBlock(), ToTN->getBlock()); |
982 | 487k | assert(ToIDom || DT.isPostDominator()); |
983 | 487k | const TreeNodePtr ToIDomTN = DT.getNode(ToIDom); |
984 | 487k | assert(ToIDomTN); |
985 | 487k | const TreeNodePtr PrevIDomSubTree = ToIDomTN->getIDom(); |
986 | 487k | // Top of the subtree to rebuild is the root node. Rebuild the tree from |
987 | 487k | // scratch. |
988 | 487k | if (!PrevIDomSubTree) { |
989 | 87.7k | LLVM_DEBUG(dbgs() << "The entire tree needs to be rebuilt\n"); |
990 | 87.7k | CalculateFromScratch(DT, BUI); |
991 | 87.7k | return; |
992 | 87.7k | } |
993 | 399k | |
994 | 399k | // Only visit nodes in the subtree starting at To. |
995 | 399k | const unsigned Level = ToIDomTN->getLevel(); |
996 | 14.1M | auto DescendBelow = [Level, &DT](NodePtr, NodePtr To) { |
997 | 14.1M | return DT.getNode(To)->getLevel() > Level; |
998 | 14.1M | }; Unexecuted instantiation: llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> >::DeleteReachable(llvm::DominatorTreeBase<llvm::MachineBasicBlock, false>&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> >::BatchUpdateInfo*, llvm::DomTreeNodeBase<llvm::MachineBasicBlock>*, llvm::DomTreeNodeBase<llvm::MachineBasicBlock>*)::'lambda'(llvm::MachineBasicBlock*, llvm::MachineBasicBlock*)::operator()(llvm::MachineBasicBlock*, llvm::MachineBasicBlock*) const Unexecuted instantiation: llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> >::DeleteReachable(llvm::DominatorTreeBase<llvm::MachineBasicBlock, true>&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> >::BatchUpdateInfo*, llvm::DomTreeNodeBase<llvm::MachineBasicBlock>*, llvm::DomTreeNodeBase<llvm::MachineBasicBlock>*)::'lambda'(llvm::MachineBasicBlock*, llvm::MachineBasicBlock*)::operator()(llvm::MachineBasicBlock*, llvm::MachineBasicBlock*) const llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, false> >::DeleteReachable(llvm::DominatorTreeBase<llvm::BasicBlock, false>&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, false> >::BatchUpdateInfo*, llvm::DomTreeNodeBase<llvm::BasicBlock>*, llvm::DomTreeNodeBase<llvm::BasicBlock>*)::'lambda'(llvm::BasicBlock*, llvm::BasicBlock*)::operator()(llvm::BasicBlock*, llvm::BasicBlock*) const Line | Count | Source | 996 | 14.1M | auto DescendBelow = [Level, &DT](NodePtr, NodePtr To) { | 997 | 14.1M | return DT.getNode(To)->getLevel() > Level; | 998 | 14.1M | }; |
llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, true> >::DeleteReachable(llvm::DominatorTreeBase<llvm::BasicBlock, true>&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, true> >::BatchUpdateInfo*, llvm::DomTreeNodeBase<llvm::BasicBlock>*, llvm::DomTreeNodeBase<llvm::BasicBlock>*)::'lambda'(llvm::BasicBlock*, llvm::BasicBlock*)::operator()(llvm::BasicBlock*, llvm::BasicBlock*) const Line | Count | Source | 996 | 361 | auto DescendBelow = [Level, &DT](NodePtr, NodePtr To) { | 997 | 361 | return DT.getNode(To)->getLevel() > Level; | 998 | 361 | }; |
|
999 | 399k | |
1000 | 399k | LLVM_DEBUG(dbgs() << "\tTop of subtree: " << BlockNamePrinter(ToIDomTN) |
1001 | 399k | << "\n"); |
1002 | 399k | |
1003 | 399k | SemiNCAInfo SNCA(BUI); |
1004 | 399k | SNCA.runDFS(ToIDom, 0, DescendBelow, 0); |
1005 | 399k | LLVM_DEBUG(dbgs() << "\tRunning Semi-NCA\n"); |
1006 | 399k | SNCA.runSemiNCA(DT, Level); |
1007 | 399k | SNCA.reattachExistingSubtree(DT, PrevIDomSubTree); |
1008 | 399k | } Unexecuted instantiation: llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> >::DeleteReachable(llvm::DominatorTreeBase<llvm::MachineBasicBlock, false>&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> >::BatchUpdateInfo*, llvm::DomTreeNodeBase<llvm::MachineBasicBlock>*, llvm::DomTreeNodeBase<llvm::MachineBasicBlock>*) Unexecuted instantiation: llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> >::DeleteReachable(llvm::DominatorTreeBase<llvm::MachineBasicBlock, true>&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> >::BatchUpdateInfo*, llvm::DomTreeNodeBase<llvm::MachineBasicBlock>*, llvm::DomTreeNodeBase<llvm::MachineBasicBlock>*) llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, false> >::DeleteReachable(llvm::DominatorTreeBase<llvm::BasicBlock, false>&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, false> >::BatchUpdateInfo*, llvm::DomTreeNodeBase<llvm::BasicBlock>*, llvm::DomTreeNodeBase<llvm::BasicBlock>*) Line | Count | Source | 973 | 487k | const TreeNodePtr ToTN) { | 974 | 487k | LLVM_DEBUG(dbgs() << "Deleting reachable " << BlockNamePrinter(FromTN) | 975 | 487k | << " -> " << BlockNamePrinter(ToTN) << "\n"); | 976 | 487k | LLVM_DEBUG(dbgs() << "\tRebuilding subtree\n"); | 977 | 487k | | 978 | 487k | // Find the top of the subtree that needs to be rebuilt. | 979 | 487k | // (Based on the lemma 2.6 from the second paper.) | 980 | 487k | const NodePtr ToIDom = | 981 | 487k | DT.findNearestCommonDominator(FromTN->getBlock(), ToTN->getBlock()); | 982 | 487k | assert(ToIDom || DT.isPostDominator()); | 983 | 487k | const TreeNodePtr ToIDomTN = DT.getNode(ToIDom); | 984 | 487k | assert(ToIDomTN); | 985 | 487k | const TreeNodePtr PrevIDomSubTree = ToIDomTN->getIDom(); | 986 | 487k | // Top of the subtree to rebuild is the root node. Rebuild the tree from | 987 | 487k | // scratch. | 988 | 487k | if (!PrevIDomSubTree) { | 989 | 87.7k | LLVM_DEBUG(dbgs() << "The entire tree needs to be rebuilt\n"); | 990 | 87.7k | CalculateFromScratch(DT, BUI); | 991 | 87.7k | return; | 992 | 87.7k | } | 993 | 399k | | 994 | 399k | // Only visit nodes in the subtree starting at To. | 995 | 399k | const unsigned Level = ToIDomTN->getLevel(); | 996 | 399k | auto DescendBelow = [Level, &DT](NodePtr, NodePtr To) { | 997 | 399k | return DT.getNode(To)->getLevel() > Level; | 998 | 399k | }; | 999 | 399k | | 1000 | 399k | LLVM_DEBUG(dbgs() << "\tTop of subtree: " << BlockNamePrinter(ToIDomTN) | 1001 | 399k | << "\n"); | 1002 | 399k | | 1003 | 399k | SemiNCAInfo SNCA(BUI); | 1004 | 399k | SNCA.runDFS(ToIDom, 0, DescendBelow, 0); | 1005 | 399k | LLVM_DEBUG(dbgs() << "\tRunning Semi-NCA\n"); | 1006 | 399k | SNCA.runSemiNCA(DT, Level); | 1007 | 399k | SNCA.reattachExistingSubtree(DT, PrevIDomSubTree); | 1008 | 399k | } |
llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, true> >::DeleteReachable(llvm::DominatorTreeBase<llvm::BasicBlock, true>&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, true> >::BatchUpdateInfo*, llvm::DomTreeNodeBase<llvm::BasicBlock>*, llvm::DomTreeNodeBase<llvm::BasicBlock>*) Line | Count | Source | 973 | 144 | const TreeNodePtr ToTN) { | 974 | 144 | LLVM_DEBUG(dbgs() << "Deleting reachable " << BlockNamePrinter(FromTN) | 975 | 144 | << " -> " << BlockNamePrinter(ToTN) << "\n"); | 976 | 144 | LLVM_DEBUG(dbgs() << "\tRebuilding subtree\n"); | 977 | 144 | | 978 | 144 | // Find the top of the subtree that needs to be rebuilt. | 979 | 144 | // (Based on the lemma 2.6 from the second paper.) | 980 | 144 | const NodePtr ToIDom = | 981 | 144 | DT.findNearestCommonDominator(FromTN->getBlock(), ToTN->getBlock()); | 982 | 144 | assert(ToIDom || DT.isPostDominator()); | 983 | 144 | const TreeNodePtr ToIDomTN = DT.getNode(ToIDom); | 984 | 144 | assert(ToIDomTN); | 985 | 144 | const TreeNodePtr PrevIDomSubTree = ToIDomTN->getIDom(); | 986 | 144 | // Top of the subtree to rebuild is the root node. Rebuild the tree from | 987 | 144 | // scratch. | 988 | 144 | if (!PrevIDomSubTree) { | 989 | 51 | LLVM_DEBUG(dbgs() << "The entire tree needs to be rebuilt\n"); | 990 | 51 | CalculateFromScratch(DT, BUI); | 991 | 51 | return; | 992 | 51 | } | 993 | 93 | | 994 | 93 | // Only visit nodes in the subtree starting at To. | 995 | 93 | const unsigned Level = ToIDomTN->getLevel(); | 996 | 93 | auto DescendBelow = [Level, &DT](NodePtr, NodePtr To) { | 997 | 93 | return DT.getNode(To)->getLevel() > Level; | 998 | 93 | }; | 999 | 93 | | 1000 | 93 | LLVM_DEBUG(dbgs() << "\tTop of subtree: " << BlockNamePrinter(ToIDomTN) | 1001 | 93 | << "\n"); | 1002 | 93 | | 1003 | 93 | SemiNCAInfo SNCA(BUI); | 1004 | 93 | SNCA.runDFS(ToIDom, 0, DescendBelow, 0); | 1005 | 93 | LLVM_DEBUG(dbgs() << "\tRunning Semi-NCA\n"); | 1006 | 93 | SNCA.runSemiNCA(DT, Level); | 1007 | 93 | SNCA.reattachExistingSubtree(DT, PrevIDomSubTree); | 1008 | 93 | } |
|
1009 | | |
1010 | | // Checks if a node has proper support, as defined on the page 3 and later |
1011 | | // explained on the page 7 of the second paper. |
1012 | | static bool HasProperSupport(DomTreeT &DT, const BatchUpdatePtr BUI, |
1013 | 414k | const TreeNodePtr TN) { |
1014 | 414k | LLVM_DEBUG(dbgs() << "IsReachableFromIDom " << BlockNamePrinter(TN) |
1015 | 414k | << "\n"); |
1016 | 414k | for (const NodePtr Pred : |
1017 | 414k | ChildrenGetter<!IsPostDom>::Get(TN->getBlock(), BUI)) { |
1018 | 127k | LLVM_DEBUG(dbgs() << "\tPred " << BlockNamePrinter(Pred) << "\n"); |
1019 | 127k | if (!DT.getNode(Pred)) continue1.64k ; |
1020 | 125k | |
1021 | 125k | const NodePtr Support = |
1022 | 125k | DT.findNearestCommonDominator(TN->getBlock(), Pred); |
1023 | 125k | LLVM_DEBUG(dbgs() << "\tSupport " << BlockNamePrinter(Support) << "\n"); |
1024 | 125k | if (Support != TN->getBlock()) { |
1025 | 110k | LLVM_DEBUG(dbgs() << "\t" << BlockNamePrinter(TN) |
1026 | 110k | << " is reachable from support " |
1027 | 110k | << BlockNamePrinter(Support) << "\n"); |
1028 | 110k | return true; |
1029 | 110k | } |
1030 | 125k | } |
1031 | 414k | |
1032 | 414k | return false303k ; |
1033 | 414k | } Unexecuted instantiation: llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> >::HasProperSupport(llvm::DominatorTreeBase<llvm::MachineBasicBlock, false>&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> >::BatchUpdateInfo*, llvm::DomTreeNodeBase<llvm::MachineBasicBlock>*) Unexecuted instantiation: llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> >::HasProperSupport(llvm::DominatorTreeBase<llvm::MachineBasicBlock, true>&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> >::BatchUpdateInfo*, llvm::DomTreeNodeBase<llvm::MachineBasicBlock>*) llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, false> >::HasProperSupport(llvm::DominatorTreeBase<llvm::BasicBlock, false>&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, false> >::BatchUpdateInfo*, llvm::DomTreeNodeBase<llvm::BasicBlock>*) Line | Count | Source | 1013 | 414k | const TreeNodePtr TN) { | 1014 | 414k | LLVM_DEBUG(dbgs() << "IsReachableFromIDom " << BlockNamePrinter(TN) | 1015 | 414k | << "\n"); | 1016 | 414k | for (const NodePtr Pred : | 1017 | 414k | ChildrenGetter<!IsPostDom>::Get(TN->getBlock(), BUI)) { | 1018 | 127k | LLVM_DEBUG(dbgs() << "\tPred " << BlockNamePrinter(Pred) << "\n"); | 1019 | 127k | if (!DT.getNode(Pred)) continue1.64k ; | 1020 | 125k | | 1021 | 125k | const NodePtr Support = | 1022 | 125k | DT.findNearestCommonDominator(TN->getBlock(), Pred); | 1023 | 125k | LLVM_DEBUG(dbgs() << "\tSupport " << BlockNamePrinter(Support) << "\n"); | 1024 | 125k | if (Support != TN->getBlock()) { | 1025 | 110k | LLVM_DEBUG(dbgs() << "\t" << BlockNamePrinter(TN) | 1026 | 110k | << " is reachable from support " | 1027 | 110k | << BlockNamePrinter(Support) << "\n"); | 1028 | 110k | return true; | 1029 | 110k | } | 1030 | 125k | } | 1031 | 414k | | 1032 | 414k | return false303k ; | 1033 | 414k | } |
llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, true> >::HasProperSupport(llvm::DominatorTreeBase<llvm::BasicBlock, true>&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, true> >::BatchUpdateInfo*, llvm::DomTreeNodeBase<llvm::BasicBlock>*) Line | Count | Source | 1013 | 74 | const TreeNodePtr TN) { | 1014 | 74 | LLVM_DEBUG(dbgs() << "IsReachableFromIDom " << BlockNamePrinter(TN) | 1015 | 74 | << "\n"); | 1016 | 74 | for (const NodePtr Pred : | 1017 | 74 | ChildrenGetter<!IsPostDom>::Get(TN->getBlock(), BUI)) { | 1018 | 17 | LLVM_DEBUG(dbgs() << "\tPred " << BlockNamePrinter(Pred) << "\n"); | 1019 | 17 | if (!DT.getNode(Pred)) continue0 ; | 1020 | 17 | | 1021 | 17 | const NodePtr Support = | 1022 | 17 | DT.findNearestCommonDominator(TN->getBlock(), Pred); | 1023 | 17 | LLVM_DEBUG(dbgs() << "\tSupport " << BlockNamePrinter(Support) << "\n"); | 1024 | 17 | if (Support != TN->getBlock()) { | 1025 | 3 | LLVM_DEBUG(dbgs() << "\t" << BlockNamePrinter(TN) | 1026 | 3 | << " is reachable from support " | 1027 | 3 | << BlockNamePrinter(Support) << "\n"); | 1028 | 3 | return true; | 1029 | 3 | } | 1030 | 17 | } | 1031 | 74 | | 1032 | 74 | return false71 ; | 1033 | 74 | } |
|
1034 | | |
1035 | | // Handle deletions that make destination node unreachable. |
1036 | | // (Based on the lemma 2.7 from the second paper.) |
1037 | | static void DeleteUnreachable(DomTreeT &DT, const BatchUpdatePtr BUI, |
1038 | 303k | const TreeNodePtr ToTN) { |
1039 | 303k | LLVM_DEBUG(dbgs() << "Deleting unreachable subtree " |
1040 | 303k | << BlockNamePrinter(ToTN) << "\n"); |
1041 | 303k | assert(ToTN); |
1042 | 303k | assert(ToTN->getBlock()); |
1043 | 303k | |
1044 | 303k | if (IsPostDom) { |
1045 | 71 | // Deletion makes a region reverse-unreachable and creates a new root. |
1046 | 71 | // Simulate that by inserting an edge from the virtual root to ToTN and |
1047 | 71 | // adding it as a new root. |
1048 | 71 | LLVM_DEBUG(dbgs() << "\tDeletion made a region reverse-unreachable\n"); |
1049 | 71 | LLVM_DEBUG(dbgs() << "\tAdding new root " << BlockNamePrinter(ToTN) |
1050 | 71 | << "\n"); |
1051 | 71 | DT.Roots.push_back(ToTN->getBlock()); |
1052 | 71 | InsertReachable(DT, BUI, DT.getNode(nullptr), ToTN); |
1053 | 71 | return; |
1054 | 71 | } |
1055 | 303k | |
1056 | 303k | SmallVector<NodePtr, 16> AffectedQueue; |
1057 | 303k | const unsigned Level = ToTN->getLevel(); |
1058 | 303k | |
1059 | 303k | // Traverse destination node's descendants with greater level in the tree |
1060 | 303k | // and collect visited nodes. |
1061 | 303k | auto DescendAndCollect = [Level, &AffectedQueue, &DT](NodePtr, NodePtr To) { |
1062 | 174k | const TreeNodePtr TN = DT.getNode(To); |
1063 | 174k | assert(TN); |
1064 | 174k | if (TN->getLevel() > Level) return true130k ; |
1065 | 44.3k | if (llvm::find(AffectedQueue, To) == AffectedQueue.end()) |
1066 | 34.7k | AffectedQueue.push_back(To); |
1067 | 44.3k | |
1068 | 44.3k | return false; |
1069 | 44.3k | }; Unexecuted instantiation: llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> >::DeleteUnreachable(llvm::DominatorTreeBase<llvm::MachineBasicBlock, false>&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> >::BatchUpdateInfo*, llvm::DomTreeNodeBase<llvm::MachineBasicBlock>*)::'lambda'(llvm::MachineBasicBlock*, llvm::MachineBasicBlock*)::operator()(llvm::MachineBasicBlock*, llvm::MachineBasicBlock*) const llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, false> >::DeleteUnreachable(llvm::DominatorTreeBase<llvm::BasicBlock, false>&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, false> >::BatchUpdateInfo*, llvm::DomTreeNodeBase<llvm::BasicBlock>*)::'lambda'(llvm::BasicBlock*, llvm::BasicBlock*)::operator()(llvm::BasicBlock*, llvm::BasicBlock*) const Line | Count | Source | 1061 | 174k | auto DescendAndCollect = [Level, &AffectedQueue, &DT](NodePtr, NodePtr To) { | 1062 | 174k | const TreeNodePtr TN = DT.getNode(To); | 1063 | 174k | assert(TN); | 1064 | 174k | if (TN->getLevel() > Level) return true130k ; | 1065 | 44.3k | if (llvm::find(AffectedQueue, To) == AffectedQueue.end()) | 1066 | 34.7k | AffectedQueue.push_back(To); | 1067 | 44.3k | | 1068 | 44.3k | return false; | 1069 | 44.3k | }; |
|
1070 | 303k | |
1071 | 303k | SemiNCAInfo SNCA(BUI); |
1072 | 303k | unsigned LastDFSNum = |
1073 | 303k | SNCA.runDFS(ToTN->getBlock(), 0, DescendAndCollect, 0); |
1074 | 303k | |
1075 | 303k | TreeNodePtr MinNode = ToTN; |
1076 | 303k | |
1077 | 303k | // Identify the top of the subtree to rebuild by finding the NCD of all |
1078 | 303k | // the affected nodes. |
1079 | 303k | for (const NodePtr N : AffectedQueue) { |
1080 | 34.7k | const TreeNodePtr TN = DT.getNode(N); |
1081 | 34.7k | const NodePtr NCDBlock = |
1082 | 34.7k | DT.findNearestCommonDominator(TN->getBlock(), ToTN->getBlock()); |
1083 | 34.7k | assert(NCDBlock || DT.isPostDominator()); |
1084 | 34.7k | const TreeNodePtr NCD = DT.getNode(NCDBlock); |
1085 | 34.7k | assert(NCD); |
1086 | 34.7k | |
1087 | 34.7k | LLVM_DEBUG(dbgs() << "Processing affected node " << BlockNamePrinter(TN) |
1088 | 34.7k | << " with NCD = " << BlockNamePrinter(NCD) |
1089 | 34.7k | << ", MinNode =" << BlockNamePrinter(MinNode) << "\n"); |
1090 | 34.7k | if (NCD != TN && NCD->getLevel() < MinNode->getLevel()31.7k ) MinNode = NCD30.1k ; |
1091 | 34.7k | } |
1092 | 303k | |
1093 | 303k | // Root reached, rebuild the whole tree from scratch. |
1094 | 303k | if (!MinNode->getIDom()) { |
1095 | 5.51k | LLVM_DEBUG(dbgs() << "The entire tree needs to be rebuilt\n"); |
1096 | 5.51k | CalculateFromScratch(DT, BUI); |
1097 | 5.51k | return; |
1098 | 5.51k | } |
1099 | 298k | |
1100 | 298k | // Erase the unreachable subtree in reverse preorder to process all children |
1101 | 298k | // before deleting their parent. |
1102 | 672k | for (unsigned i = LastDFSNum; 298k i > 0; --i374k ) { |
1103 | 374k | const NodePtr N = SNCA.NumToNode[i]; |
1104 | 374k | const TreeNodePtr TN = DT.getNode(N); |
1105 | 374k | LLVM_DEBUG(dbgs() << "Erasing node " << BlockNamePrinter(TN) << "\n"); |
1106 | 374k | |
1107 | 374k | EraseNode(DT, TN); |
1108 | 374k | } |
1109 | 298k | |
1110 | 298k | // The affected subtree start at the To node -- there's no extra work to do. |
1111 | 298k | if (MinNode == ToTN) return274k ; |
1112 | 24.0k | |
1113 | 24.0k | LLVM_DEBUG(dbgs() << "DeleteUnreachable: running DFS with MinNode = " |
1114 | 24.0k | << BlockNamePrinter(MinNode) << "\n"); |
1115 | 24.0k | const unsigned MinLevel = MinNode->getLevel(); |
1116 | 24.0k | const TreeNodePtr PrevIDom = MinNode->getIDom(); |
1117 | 24.0k | assert(PrevIDom); |
1118 | 24.0k | SNCA.clear(); |
1119 | 24.0k | |
1120 | 24.0k | // Identify nodes that remain in the affected subtree. |
1121 | 349k | auto DescendBelow = [MinLevel, &DT](NodePtr, NodePtr To) { |
1122 | 349k | const TreeNodePtr ToTN = DT.getNode(To); |
1123 | 349k | return ToTN && ToTN->getLevel() > MinLevel; |
1124 | 349k | }; Unexecuted instantiation: llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> >::DeleteUnreachable(llvm::DominatorTreeBase<llvm::MachineBasicBlock, false>&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> >::BatchUpdateInfo*, llvm::DomTreeNodeBase<llvm::MachineBasicBlock>*)::'lambda0'(llvm::MachineBasicBlock*, llvm::MachineBasicBlock*)::operator()(llvm::MachineBasicBlock*, llvm::MachineBasicBlock*) const llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, false> >::DeleteUnreachable(llvm::DominatorTreeBase<llvm::BasicBlock, false>&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, false> >::BatchUpdateInfo*, llvm::DomTreeNodeBase<llvm::BasicBlock>*)::'lambda0'(llvm::BasicBlock*, llvm::BasicBlock*)::operator()(llvm::BasicBlock*, llvm::BasicBlock*) const Line | Count | Source | 1121 | 349k | auto DescendBelow = [MinLevel, &DT](NodePtr, NodePtr To) { | 1122 | 349k | const TreeNodePtr ToTN = DT.getNode(To); | 1123 | 349k | return ToTN && ToTN->getLevel() > MinLevel; | 1124 | 349k | }; |
|
1125 | 24.0k | SNCA.runDFS(MinNode->getBlock(), 0, DescendBelow, 0); |
1126 | 24.0k | |
1127 | 24.0k | LLVM_DEBUG(dbgs() << "Previous IDom(MinNode) = " |
1128 | 24.0k | << BlockNamePrinter(PrevIDom) << "\nRunning Semi-NCA\n"); |
1129 | 24.0k | |
1130 | 24.0k | // Rebuild the remaining part of affected subtree. |
1131 | 24.0k | SNCA.runSemiNCA(DT, MinLevel); |
1132 | 24.0k | SNCA.reattachExistingSubtree(DT, PrevIDom); |
1133 | 24.0k | } Unexecuted instantiation: llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> >::DeleteUnreachable(llvm::DominatorTreeBase<llvm::MachineBasicBlock, false>&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> >::BatchUpdateInfo*, llvm::DomTreeNodeBase<llvm::MachineBasicBlock>*) Unexecuted instantiation: llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> >::DeleteUnreachable(llvm::DominatorTreeBase<llvm::MachineBasicBlock, true>&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> >::BatchUpdateInfo*, llvm::DomTreeNodeBase<llvm::MachineBasicBlock>*) llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, false> >::DeleteUnreachable(llvm::DominatorTreeBase<llvm::BasicBlock, false>&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, false> >::BatchUpdateInfo*, llvm::DomTreeNodeBase<llvm::BasicBlock>*) Line | Count | Source | 1038 | 303k | const TreeNodePtr ToTN) { | 1039 | 303k | LLVM_DEBUG(dbgs() << "Deleting unreachable subtree " | 1040 | 303k | << BlockNamePrinter(ToTN) << "\n"); | 1041 | 303k | assert(ToTN); | 1042 | 303k | assert(ToTN->getBlock()); | 1043 | 303k | | 1044 | 303k | if (IsPostDom) { | 1045 | 0 | // Deletion makes a region reverse-unreachable and creates a new root. | 1046 | 0 | // Simulate that by inserting an edge from the virtual root to ToTN and | 1047 | 0 | // adding it as a new root. | 1048 | 0 | LLVM_DEBUG(dbgs() << "\tDeletion made a region reverse-unreachable\n"); | 1049 | 0 | LLVM_DEBUG(dbgs() << "\tAdding new root " << BlockNamePrinter(ToTN) | 1050 | 0 | << "\n"); | 1051 | 0 | DT.Roots.push_back(ToTN->getBlock()); | 1052 | 0 | InsertReachable(DT, BUI, DT.getNode(nullptr), ToTN); | 1053 | 0 | return; | 1054 | 0 | } | 1055 | 303k | | 1056 | 303k | SmallVector<NodePtr, 16> AffectedQueue; | 1057 | 303k | const unsigned Level = ToTN->getLevel(); | 1058 | 303k | | 1059 | 303k | // Traverse destination node's descendants with greater level in the tree | 1060 | 303k | // and collect visited nodes. | 1061 | 303k | auto DescendAndCollect = [Level, &AffectedQueue, &DT](NodePtr, NodePtr To) { | 1062 | 303k | const TreeNodePtr TN = DT.getNode(To); | 1063 | 303k | assert(TN); | 1064 | 303k | if (TN->getLevel() > Level) return true; | 1065 | 303k | if (llvm::find(AffectedQueue, To) == AffectedQueue.end()) | 1066 | 303k | AffectedQueue.push_back(To); | 1067 | 303k | | 1068 | 303k | return false; | 1069 | 303k | }; | 1070 | 303k | | 1071 | 303k | SemiNCAInfo SNCA(BUI); | 1072 | 303k | unsigned LastDFSNum = | 1073 | 303k | SNCA.runDFS(ToTN->getBlock(), 0, DescendAndCollect, 0); | 1074 | 303k | | 1075 | 303k | TreeNodePtr MinNode = ToTN; | 1076 | 303k | | 1077 | 303k | // Identify the top of the subtree to rebuild by finding the NCD of all | 1078 | 303k | // the affected nodes. | 1079 | 303k | for (const NodePtr N : AffectedQueue) { | 1080 | 34.7k | const TreeNodePtr TN = DT.getNode(N); | 1081 | 34.7k | const NodePtr NCDBlock = | 1082 | 34.7k | DT.findNearestCommonDominator(TN->getBlock(), ToTN->getBlock()); | 1083 | 34.7k | assert(NCDBlock || DT.isPostDominator()); | 1084 | 34.7k | const TreeNodePtr NCD = DT.getNode(NCDBlock); | 1085 | 34.7k | assert(NCD); | 1086 | 34.7k | | 1087 | 34.7k | LLVM_DEBUG(dbgs() << "Processing affected node " << BlockNamePrinter(TN) | 1088 | 34.7k | << " with NCD = " << BlockNamePrinter(NCD) | 1089 | 34.7k | << ", MinNode =" << BlockNamePrinter(MinNode) << "\n"); | 1090 | 34.7k | if (NCD != TN && NCD->getLevel() < MinNode->getLevel()31.7k ) MinNode = NCD30.1k ; | 1091 | 34.7k | } | 1092 | 303k | | 1093 | 303k | // Root reached, rebuild the whole tree from scratch. | 1094 | 303k | if (!MinNode->getIDom()) { | 1095 | 5.51k | LLVM_DEBUG(dbgs() << "The entire tree needs to be rebuilt\n"); | 1096 | 5.51k | CalculateFromScratch(DT, BUI); | 1097 | 5.51k | return; | 1098 | 5.51k | } | 1099 | 298k | | 1100 | 298k | // Erase the unreachable subtree in reverse preorder to process all children | 1101 | 298k | // before deleting their parent. | 1102 | 672k | for (unsigned i = LastDFSNum; 298k i > 0; --i374k ) { | 1103 | 374k | const NodePtr N = SNCA.NumToNode[i]; | 1104 | 374k | const TreeNodePtr TN = DT.getNode(N); | 1105 | 374k | LLVM_DEBUG(dbgs() << "Erasing node " << BlockNamePrinter(TN) << "\n"); | 1106 | 374k | | 1107 | 374k | EraseNode(DT, TN); | 1108 | 374k | } | 1109 | 298k | | 1110 | 298k | // The affected subtree start at the To node -- there's no extra work to do. | 1111 | 298k | if (MinNode == ToTN) return274k ; | 1112 | 24.0k | | 1113 | 24.0k | LLVM_DEBUG(dbgs() << "DeleteUnreachable: running DFS with MinNode = " | 1114 | 24.0k | << BlockNamePrinter(MinNode) << "\n"); | 1115 | 24.0k | const unsigned MinLevel = MinNode->getLevel(); | 1116 | 24.0k | const TreeNodePtr PrevIDom = MinNode->getIDom(); | 1117 | 24.0k | assert(PrevIDom); | 1118 | 24.0k | SNCA.clear(); | 1119 | 24.0k | | 1120 | 24.0k | // Identify nodes that remain in the affected subtree. | 1121 | 24.0k | auto DescendBelow = [MinLevel, &DT](NodePtr, NodePtr To) { | 1122 | 24.0k | const TreeNodePtr ToTN = DT.getNode(To); | 1123 | 24.0k | return ToTN && ToTN->getLevel() > MinLevel; | 1124 | 24.0k | }; | 1125 | 24.0k | SNCA.runDFS(MinNode->getBlock(), 0, DescendBelow, 0); | 1126 | 24.0k | | 1127 | 24.0k | LLVM_DEBUG(dbgs() << "Previous IDom(MinNode) = " | 1128 | 24.0k | << BlockNamePrinter(PrevIDom) << "\nRunning Semi-NCA\n"); | 1129 | 24.0k | | 1130 | 24.0k | // Rebuild the remaining part of affected subtree. | 1131 | 24.0k | SNCA.runSemiNCA(DT, MinLevel); | 1132 | 24.0k | SNCA.reattachExistingSubtree(DT, PrevIDom); | 1133 | 24.0k | } |
llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, true> >::DeleteUnreachable(llvm::DominatorTreeBase<llvm::BasicBlock, true>&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, true> >::BatchUpdateInfo*, llvm::DomTreeNodeBase<llvm::BasicBlock>*) Line | Count | Source | 1038 | 71 | const TreeNodePtr ToTN) { | 1039 | 71 | LLVM_DEBUG(dbgs() << "Deleting unreachable subtree " | 1040 | 71 | << BlockNamePrinter(ToTN) << "\n"); | 1041 | 71 | assert(ToTN); | 1042 | 71 | assert(ToTN->getBlock()); | 1043 | 71 | | 1044 | 71 | if (IsPostDom) { | 1045 | 71 | // Deletion makes a region reverse-unreachable and creates a new root. | 1046 | 71 | // Simulate that by inserting an edge from the virtual root to ToTN and | 1047 | 71 | // adding it as a new root. | 1048 | 71 | LLVM_DEBUG(dbgs() << "\tDeletion made a region reverse-unreachable\n"); | 1049 | 71 | LLVM_DEBUG(dbgs() << "\tAdding new root " << BlockNamePrinter(ToTN) | 1050 | 71 | << "\n"); | 1051 | 71 | DT.Roots.push_back(ToTN->getBlock()); | 1052 | 71 | InsertReachable(DT, BUI, DT.getNode(nullptr), ToTN); | 1053 | 71 | return; | 1054 | 71 | } | 1055 | 0 | | 1056 | 0 | SmallVector<NodePtr, 16> AffectedQueue; | 1057 | 0 | const unsigned Level = ToTN->getLevel(); | 1058 | 0 |
| 1059 | 0 | // Traverse destination node's descendants with greater level in the tree | 1060 | 0 | // and collect visited nodes. | 1061 | 0 | auto DescendAndCollect = [Level, &AffectedQueue, &DT](NodePtr, NodePtr To) { | 1062 | 0 | const TreeNodePtr TN = DT.getNode(To); | 1063 | 0 | assert(TN); | 1064 | 0 | if (TN->getLevel() > Level) return true; | 1065 | 0 | if (llvm::find(AffectedQueue, To) == AffectedQueue.end()) | 1066 | 0 | AffectedQueue.push_back(To); | 1067 | 0 |
| 1068 | 0 | return false; | 1069 | 0 | }; | 1070 | 0 |
| 1071 | 0 | SemiNCAInfo SNCA(BUI); | 1072 | 0 | unsigned LastDFSNum = | 1073 | 0 | SNCA.runDFS(ToTN->getBlock(), 0, DescendAndCollect, 0); | 1074 | 0 |
| 1075 | 0 | TreeNodePtr MinNode = ToTN; | 1076 | 0 |
| 1077 | 0 | // Identify the top of the subtree to rebuild by finding the NCD of all | 1078 | 0 | // the affected nodes. | 1079 | 0 | for (const NodePtr N : AffectedQueue) { | 1080 | 0 | const TreeNodePtr TN = DT.getNode(N); | 1081 | 0 | const NodePtr NCDBlock = | 1082 | 0 | DT.findNearestCommonDominator(TN->getBlock(), ToTN->getBlock()); | 1083 | 0 | assert(NCDBlock || DT.isPostDominator()); | 1084 | 0 | const TreeNodePtr NCD = DT.getNode(NCDBlock); | 1085 | 0 | assert(NCD); | 1086 | 0 |
| 1087 | 0 | LLVM_DEBUG(dbgs() << "Processing affected node " << BlockNamePrinter(TN) | 1088 | 0 | << " with NCD = " << BlockNamePrinter(NCD) | 1089 | 0 | << ", MinNode =" << BlockNamePrinter(MinNode) << "\n"); | 1090 | 0 | if (NCD != TN && NCD->getLevel() < MinNode->getLevel()) MinNode = NCD; | 1091 | 0 | } | 1092 | 0 |
| 1093 | 0 | // Root reached, rebuild the whole tree from scratch. | 1094 | 0 | if (!MinNode->getIDom()) { | 1095 | 0 | LLVM_DEBUG(dbgs() << "The entire tree needs to be rebuilt\n"); | 1096 | 0 | CalculateFromScratch(DT, BUI); | 1097 | 0 | return; | 1098 | 0 | } | 1099 | 0 |
| 1100 | 0 | // Erase the unreachable subtree in reverse preorder to process all children | 1101 | 0 | // before deleting their parent. | 1102 | 0 | for (unsigned i = LastDFSNum; i > 0; --i) { | 1103 | 0 | const NodePtr N = SNCA.NumToNode[i]; | 1104 | 0 | const TreeNodePtr TN = DT.getNode(N); | 1105 | 0 | LLVM_DEBUG(dbgs() << "Erasing node " << BlockNamePrinter(TN) << "\n"); | 1106 | 0 |
| 1107 | 0 | EraseNode(DT, TN); | 1108 | 0 | } | 1109 | 0 |
| 1110 | 0 | // The affected subtree start at the To node -- there's no extra work to do. | 1111 | 0 | if (MinNode == ToTN) return; | 1112 | 0 | | 1113 | 0 | LLVM_DEBUG(dbgs() << "DeleteUnreachable: running DFS with MinNode = " | 1114 | 0 | << BlockNamePrinter(MinNode) << "\n"); | 1115 | 0 | const unsigned MinLevel = MinNode->getLevel(); | 1116 | 0 | const TreeNodePtr PrevIDom = MinNode->getIDom(); | 1117 | 0 | assert(PrevIDom); | 1118 | 0 | SNCA.clear(); | 1119 | 0 |
| 1120 | 0 | // Identify nodes that remain in the affected subtree. | 1121 | 0 | auto DescendBelow = [MinLevel, &DT](NodePtr, NodePtr To) { | 1122 | 0 | const TreeNodePtr ToTN = DT.getNode(To); | 1123 | 0 | return ToTN && ToTN->getLevel() > MinLevel; | 1124 | 0 | }; | 1125 | 0 | SNCA.runDFS(MinNode->getBlock(), 0, DescendBelow, 0); | 1126 | 0 |
| 1127 | 0 | LLVM_DEBUG(dbgs() << "Previous IDom(MinNode) = " | 1128 | 0 | << BlockNamePrinter(PrevIDom) << "\nRunning Semi-NCA\n"); | 1129 | 0 |
| 1130 | 0 | // Rebuild the remaining part of affected subtree. | 1131 | 0 | SNCA.runSemiNCA(DT, MinLevel); | 1132 | 0 | SNCA.reattachExistingSubtree(DT, PrevIDom); | 1133 | 0 | } |
|
1134 | | |
1135 | | // Removes leaf tree nodes from the dominator tree. |
1136 | 374k | static void EraseNode(DomTreeT &DT, const TreeNodePtr TN) { |
1137 | 374k | assert(TN); |
1138 | 374k | assert(TN->getNumChildren() == 0 && "Not a tree leaf"); |
1139 | 374k | |
1140 | 374k | const TreeNodePtr IDom = TN->getIDom(); |
1141 | 374k | assert(IDom); |
1142 | 374k | |
1143 | 374k | auto ChIt = llvm::find(IDom->Children, TN); |
1144 | 374k | assert(ChIt != IDom->Children.end()); |
1145 | 374k | std::swap(*ChIt, IDom->Children.back()); |
1146 | 374k | IDom->Children.pop_back(); |
1147 | 374k | |
1148 | 374k | DT.DomTreeNodes.erase(TN->getBlock()); |
1149 | 374k | } Unexecuted instantiation: llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> >::EraseNode(llvm::DominatorTreeBase<llvm::MachineBasicBlock, false>&, llvm::DomTreeNodeBase<llvm::MachineBasicBlock>*) Unexecuted instantiation: llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> >::EraseNode(llvm::DominatorTreeBase<llvm::MachineBasicBlock, true>&, llvm::DomTreeNodeBase<llvm::MachineBasicBlock>*) llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, false> >::EraseNode(llvm::DominatorTreeBase<llvm::BasicBlock, false>&, llvm::DomTreeNodeBase<llvm::BasicBlock>*) Line | Count | Source | 1136 | 374k | static void EraseNode(DomTreeT &DT, const TreeNodePtr TN) { | 1137 | 374k | assert(TN); | 1138 | 374k | assert(TN->getNumChildren() == 0 && "Not a tree leaf"); | 1139 | 374k | | 1140 | 374k | const TreeNodePtr IDom = TN->getIDom(); | 1141 | 374k | assert(IDom); | 1142 | 374k | | 1143 | 374k | auto ChIt = llvm::find(IDom->Children, TN); | 1144 | 374k | assert(ChIt != IDom->Children.end()); | 1145 | 374k | std::swap(*ChIt, IDom->Children.back()); | 1146 | 374k | IDom->Children.pop_back(); | 1147 | 374k | | 1148 | 374k | DT.DomTreeNodes.erase(TN->getBlock()); | 1149 | 374k | } |
Unexecuted instantiation: llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, true> >::EraseNode(llvm::DominatorTreeBase<llvm::BasicBlock, true>&, llvm::DomTreeNodeBase<llvm::BasicBlock>*) |
1150 | | |
1151 | | //~~ |
1152 | | //===--------------------- DomTree Batch Updater --------------------------=== |
1153 | | //~~ |
1154 | | |
1155 | 521k | static void ApplyUpdates(DomTreeT &DT, ArrayRef<UpdateT> Updates) { |
1156 | 521k | const size_t NumUpdates = Updates.size(); |
1157 | 521k | if (NumUpdates == 0) |
1158 | 192 | return; |
1159 | 521k | |
1160 | 521k | // Take the fast path for a single update and avoid running the batch update |
1161 | 521k | // machinery. |
1162 | 521k | if (NumUpdates == 1) { |
1163 | 7.77k | const auto &Update = Updates.front(); |
1164 | 7.77k | if (Update.getKind() == UpdateKind::Insert) |
1165 | 4.19k | DT.insertEdge(Update.getFrom(), Update.getTo()); |
1166 | 3.58k | else |
1167 | 3.58k | DT.deleteEdge(Update.getFrom(), Update.getTo()); |
1168 | 7.77k | |
1169 | 7.77k | return; |
1170 | 7.77k | } |
1171 | 513k | |
1172 | 513k | BatchUpdateInfo BUI; |
1173 | 513k | LLVM_DEBUG(dbgs() << "Legalizing " << BUI.Updates.size() << " updates\n"); |
1174 | 513k | cfg::LegalizeUpdates<NodePtr>(Updates, BUI.Updates, IsPostDom); |
1175 | 513k | |
1176 | 513k | const size_t NumLegalized = BUI.Updates.size(); |
1177 | 513k | BUI.FutureSuccessors.reserve(NumLegalized); |
1178 | 513k | BUI.FuturePredecessors.reserve(NumLegalized); |
1179 | 513k | |
1180 | 513k | // Use the legalized future updates to initialize future successors and |
1181 | 513k | // predecessors. Note that these sets will only decrease size over time, as |
1182 | 513k | // the next CFG snapshots slowly approach the actual (current) CFG. |
1183 | 2.49M | for (UpdateT &U : BUI.Updates) { |
1184 | 2.49M | BUI.FutureSuccessors[U.getFrom()].push_back({U.getTo(), U.getKind()}); |
1185 | 2.49M | BUI.FuturePredecessors[U.getTo()].push_back({U.getFrom(), U.getKind()}); |
1186 | 2.49M | } |
1187 | 513k | |
1188 | | #if 0 |
1189 | | // FIXME: The LLVM_DEBUG macro only plays well with a modular |
1190 | | // build of LLVM when the header is marked as textual, but doing |
1191 | | // so causes redefinition errors. |
1192 | | LLVM_DEBUG(dbgs() << "About to apply " << NumLegalized << " updates\n"); |
1193 | | LLVM_DEBUG(if (NumLegalized < 32) for (const auto &U |
1194 | | : reverse(BUI.Updates)) { |
1195 | | dbgs() << "\t"; |
1196 | | U.dump(); |
1197 | | dbgs() << "\n"; |
1198 | | }); |
1199 | | LLVM_DEBUG(dbgs() << "\n"); |
1200 | | #endif |
1201 | | |
1202 | 513k | // Recalculate the DominatorTree when the number of updates |
1203 | 513k | // exceeds a threshold, which usually makes direct updating slower than |
1204 | 513k | // recalculation. We select this threshold proportional to the |
1205 | 513k | // size of the DominatorTree. The constant is selected |
1206 | 513k | // by choosing the one with an acceptable performance on some real-world |
1207 | 513k | // inputs. |
1208 | 513k | |
1209 | 513k | // Make unittests of the incremental algorithm work |
1210 | 513k | if (DT.DomTreeNodes.size() <= 100) { |
1211 | 339k | if (NumLegalized > DT.DomTreeNodes.size()) |
1212 | 5.25k | CalculateFromScratch(DT, &BUI); |
1213 | 339k | } else if (174k NumLegalized > DT.DomTreeNodes.size() / 40174k ) |
1214 | 69.9k | CalculateFromScratch(DT, &BUI); |
1215 | 513k | |
1216 | 513k | // If the DominatorTree was recalculated at some point, stop the batch |
1217 | 513k | // updates. Full recalculations ignore batch updates and look at the actual |
1218 | 513k | // CFG. |
1219 | 1.95M | for (size_t i = 0; i < NumLegalized && !BUI.IsRecalculated1.57M ; ++i1.44M ) |
1220 | 1.44M | ApplyNextUpdate(DT, BUI); |
1221 | 513k | } Unexecuted instantiation: llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> >::ApplyUpdates(llvm::DominatorTreeBase<llvm::MachineBasicBlock, false>&, llvm::ArrayRef<llvm::cfg::Update<llvm::MachineBasicBlock*> >) Unexecuted instantiation: llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> >::ApplyUpdates(llvm::DominatorTreeBase<llvm::MachineBasicBlock, true>&, llvm::ArrayRef<llvm::cfg::Update<llvm::MachineBasicBlock*> >) llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, false> >::ApplyUpdates(llvm::DominatorTreeBase<llvm::BasicBlock, false>&, llvm::ArrayRef<llvm::cfg::Update<llvm::BasicBlock*> >) Line | Count | Source | 1155 | 521k | static void ApplyUpdates(DomTreeT &DT, ArrayRef<UpdateT> Updates) { | 1156 | 521k | const size_t NumUpdates = Updates.size(); | 1157 | 521k | if (NumUpdates == 0) | 1158 | 15 | return; | 1159 | 521k | | 1160 | 521k | // Take the fast path for a single update and avoid running the batch update | 1161 | 521k | // machinery. | 1162 | 521k | if (NumUpdates == 1) { | 1163 | 7.67k | const auto &Update = Updates.front(); | 1164 | 7.67k | if (Update.getKind() == UpdateKind::Insert) | 1165 | 4.19k | DT.insertEdge(Update.getFrom(), Update.getTo()); | 1166 | 3.48k | else | 1167 | 3.48k | DT.deleteEdge(Update.getFrom(), Update.getTo()); | 1168 | 7.67k | | 1169 | 7.67k | return; | 1170 | 7.67k | } | 1171 | 513k | | 1172 | 513k | BatchUpdateInfo BUI; | 1173 | 513k | LLVM_DEBUG(dbgs() << "Legalizing " << BUI.Updates.size() << " updates\n"); | 1174 | 513k | cfg::LegalizeUpdates<NodePtr>(Updates, BUI.Updates, IsPostDom); | 1175 | 513k | | 1176 | 513k | const size_t NumLegalized = BUI.Updates.size(); | 1177 | 513k | BUI.FutureSuccessors.reserve(NumLegalized); | 1178 | 513k | BUI.FuturePredecessors.reserve(NumLegalized); | 1179 | 513k | | 1180 | 513k | // Use the legalized future updates to initialize future successors and | 1181 | 513k | // predecessors. Note that these sets will only decrease size over time, as | 1182 | 513k | // the next CFG snapshots slowly approach the actual (current) CFG. | 1183 | 2.49M | for (UpdateT &U : BUI.Updates) { | 1184 | 2.49M | BUI.FutureSuccessors[U.getFrom()].push_back({U.getTo(), U.getKind()}); | 1185 | 2.49M | BUI.FuturePredecessors[U.getTo()].push_back({U.getFrom(), U.getKind()}); | 1186 | 2.49M | } | 1187 | 513k | | 1188 | | #if 0 | 1189 | | // FIXME: The LLVM_DEBUG macro only plays well with a modular | 1190 | | // build of LLVM when the header is marked as textual, but doing | 1191 | | // so causes redefinition errors. | 1192 | | LLVM_DEBUG(dbgs() << "About to apply " << NumLegalized << " updates\n"); | 1193 | | LLVM_DEBUG(if (NumLegalized < 32) for (const auto &U | 1194 | | : reverse(BUI.Updates)) { | 1195 | | dbgs() << "\t"; | 1196 | | U.dump(); | 1197 | | dbgs() << "\n"; | 1198 | | }); | 1199 | | LLVM_DEBUG(dbgs() << "\n"); | 1200 | | #endif | 1201 | | | 1202 | 513k | // Recalculate the DominatorTree when the number of updates | 1203 | 513k | // exceeds a threshold, which usually makes direct updating slower than | 1204 | 513k | // recalculation. We select this threshold proportional to the | 1205 | 513k | // size of the DominatorTree. The constant is selected | 1206 | 513k | // by choosing the one with an acceptable performance on some real-world | 1207 | 513k | // inputs. | 1208 | 513k | | 1209 | 513k | // Make unittests of the incremental algorithm work | 1210 | 513k | if (DT.DomTreeNodes.size() <= 100) { | 1211 | 339k | if (NumLegalized > DT.DomTreeNodes.size()) | 1212 | 5.25k | CalculateFromScratch(DT, &BUI); | 1213 | 339k | } else if (174k NumLegalized > DT.DomTreeNodes.size() / 40174k ) | 1214 | 69.9k | CalculateFromScratch(DT, &BUI); | 1215 | 513k | | 1216 | 513k | // If the DominatorTree was recalculated at some point, stop the batch | 1217 | 513k | // updates. Full recalculations ignore batch updates and look at the actual | 1218 | 513k | // CFG. | 1219 | 1.95M | for (size_t i = 0; i < NumLegalized && !BUI.IsRecalculated1.57M ; ++i1.44M ) | 1220 | 1.44M | ApplyNextUpdate(DT, BUI); | 1221 | 513k | } |
llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, true> >::ApplyUpdates(llvm::DominatorTreeBase<llvm::BasicBlock, true>&, llvm::ArrayRef<llvm::cfg::Update<llvm::BasicBlock*> >) Line | Count | Source | 1155 | 326 | static void ApplyUpdates(DomTreeT &DT, ArrayRef<UpdateT> Updates) { | 1156 | 326 | const size_t NumUpdates = Updates.size(); | 1157 | 326 | if (NumUpdates == 0) | 1158 | 177 | return; | 1159 | 149 | | 1160 | 149 | // Take the fast path for a single update and avoid running the batch update | 1161 | 149 | // machinery. | 1162 | 149 | if (NumUpdates == 1) { | 1163 | 107 | const auto &Update = Updates.front(); | 1164 | 107 | if (Update.getKind() == UpdateKind::Insert) | 1165 | 2 | DT.insertEdge(Update.getFrom(), Update.getTo()); | 1166 | 105 | else | 1167 | 105 | DT.deleteEdge(Update.getFrom(), Update.getTo()); | 1168 | 107 | | 1169 | 107 | return; | 1170 | 107 | } | 1171 | 42 | | 1172 | 42 | BatchUpdateInfo BUI; | 1173 | 42 | LLVM_DEBUG(dbgs() << "Legalizing " << BUI.Updates.size() << " updates\n"); | 1174 | 42 | cfg::LegalizeUpdates<NodePtr>(Updates, BUI.Updates, IsPostDom); | 1175 | 42 | | 1176 | 42 | const size_t NumLegalized = BUI.Updates.size(); | 1177 | 42 | BUI.FutureSuccessors.reserve(NumLegalized); | 1178 | 42 | BUI.FuturePredecessors.reserve(NumLegalized); | 1179 | 42 | | 1180 | 42 | // Use the legalized future updates to initialize future successors and | 1181 | 42 | // predecessors. Note that these sets will only decrease size over time, as | 1182 | 42 | // the next CFG snapshots slowly approach the actual (current) CFG. | 1183 | 300 | for (UpdateT &U : BUI.Updates) { | 1184 | 300 | BUI.FutureSuccessors[U.getFrom()].push_back({U.getTo(), U.getKind()}); | 1185 | 300 | BUI.FuturePredecessors[U.getTo()].push_back({U.getFrom(), U.getKind()}); | 1186 | 300 | } | 1187 | 42 | | 1188 | | #if 0 | 1189 | | // FIXME: The LLVM_DEBUG macro only plays well with a modular | 1190 | | // build of LLVM when the header is marked as textual, but doing | 1191 | | // so causes redefinition errors. | 1192 | | LLVM_DEBUG(dbgs() << "About to apply " << NumLegalized << " updates\n"); | 1193 | | LLVM_DEBUG(if (NumLegalized < 32) for (const auto &U | 1194 | | : reverse(BUI.Updates)) { | 1195 | | dbgs() << "\t"; | 1196 | | U.dump(); | 1197 | | dbgs() << "\n"; | 1198 | | }); | 1199 | | LLVM_DEBUG(dbgs() << "\n"); | 1200 | | #endif | 1201 | | | 1202 | 42 | // Recalculate the DominatorTree when the number of updates | 1203 | 42 | // exceeds a threshold, which usually makes direct updating slower than | 1204 | 42 | // recalculation. We select this threshold proportional to the | 1205 | 42 | // size of the DominatorTree. The constant is selected | 1206 | 42 | // by choosing the one with an acceptable performance on some real-world | 1207 | 42 | // inputs. | 1208 | 42 | | 1209 | 42 | // Make unittests of the incremental algorithm work | 1210 | 42 | if (DT.DomTreeNodes.size() <= 100) { | 1211 | 42 | if (NumLegalized > DT.DomTreeNodes.size()) | 1212 | 1 | CalculateFromScratch(DT, &BUI); | 1213 | 42 | } else if (0 NumLegalized > DT.DomTreeNodes.size() / 400 ) | 1214 | 0 | CalculateFromScratch(DT, &BUI); | 1215 | 42 | | 1216 | 42 | // If the DominatorTree was recalculated at some point, stop the batch | 1217 | 42 | // updates. Full recalculations ignore batch updates and look at the actual | 1218 | 42 | // CFG. | 1219 | 103 | for (size_t i = 0; i < NumLegalized && !BUI.IsRecalculated94 ; ++i61 ) | 1220 | 61 | ApplyNextUpdate(DT, BUI); | 1221 | 42 | } |
|
1222 | | |
1223 | 1.44M | static void ApplyNextUpdate(DomTreeT &DT, BatchUpdateInfo &BUI) { |
1224 | 1.44M | assert(!BUI.Updates.empty() && "No updates to apply!"); |
1225 | 1.44M | UpdateT CurrentUpdate = BUI.Updates.pop_back_val(); |
1226 | | #if 0 |
1227 | | // FIXME: The LLVM_DEBUG macro only plays well with a modular |
1228 | | // build of LLVM when the header is marked as textual, but doing |
1229 | | // so causes redefinition errors. |
1230 | | LLVM_DEBUG(dbgs() << "Applying update: "); |
1231 | | LLVM_DEBUG(CurrentUpdate.dump(); dbgs() << "\n"); |
1232 | | #endif |
1233 | | |
1234 | 1.44M | // Move to the next snapshot of the CFG by removing the reverse-applied |
1235 | 1.44M | // current update. Since updates are performed in the same order they are |
1236 | 1.44M | // legalized it's sufficient to pop the last item here. |
1237 | 1.44M | auto &FS = BUI.FutureSuccessors[CurrentUpdate.getFrom()]; |
1238 | 1.44M | assert(FS.back().getPointer() == CurrentUpdate.getTo() && |
1239 | 1.44M | FS.back().getInt() == CurrentUpdate.getKind()); |
1240 | 1.44M | FS.pop_back(); |
1241 | 1.44M | if (FS.empty()) BUI.FutureSuccessors.erase(CurrentUpdate.getFrom())857k ; |
1242 | 1.44M | |
1243 | 1.44M | auto &FP = BUI.FuturePredecessors[CurrentUpdate.getTo()]; |
1244 | 1.44M | assert(FP.back().getPointer() == CurrentUpdate.getFrom() && |
1245 | 1.44M | FP.back().getInt() == CurrentUpdate.getKind()); |
1246 | 1.44M | FP.pop_back(); |
1247 | 1.44M | if (FP.empty()) BUI.FuturePredecessors.erase(CurrentUpdate.getTo())955k ; |
1248 | 1.44M | |
1249 | 1.44M | if (CurrentUpdate.getKind() == UpdateKind::Insert) |
1250 | 615k | InsertEdge(DT, &BUI, CurrentUpdate.getFrom(), CurrentUpdate.getTo()); |
1251 | 828k | else |
1252 | 828k | DeleteEdge(DT, &BUI, CurrentUpdate.getFrom(), CurrentUpdate.getTo()); |
1253 | 1.44M | } Unexecuted instantiation: llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> >::ApplyNextUpdate(llvm::DominatorTreeBase<llvm::MachineBasicBlock, false>&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> >::BatchUpdateInfo&) Unexecuted instantiation: llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> >::ApplyNextUpdate(llvm::DominatorTreeBase<llvm::MachineBasicBlock, true>&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> >::BatchUpdateInfo&) llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, false> >::ApplyNextUpdate(llvm::DominatorTreeBase<llvm::BasicBlock, false>&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, false> >::BatchUpdateInfo&) Line | Count | Source | 1223 | 1.44M | static void ApplyNextUpdate(DomTreeT &DT, BatchUpdateInfo &BUI) { | 1224 | 1.44M | assert(!BUI.Updates.empty() && "No updates to apply!"); | 1225 | 1.44M | UpdateT CurrentUpdate = BUI.Updates.pop_back_val(); | 1226 | | #if 0 | 1227 | | // FIXME: The LLVM_DEBUG macro only plays well with a modular | 1228 | | // build of LLVM when the header is marked as textual, but doing | 1229 | | // so causes redefinition errors. | 1230 | | LLVM_DEBUG(dbgs() << "Applying update: "); | 1231 | | LLVM_DEBUG(CurrentUpdate.dump(); dbgs() << "\n"); | 1232 | | #endif | 1233 | | | 1234 | 1.44M | // Move to the next snapshot of the CFG by removing the reverse-applied | 1235 | 1.44M | // current update. Since updates are performed in the same order they are | 1236 | 1.44M | // legalized it's sufficient to pop the last item here. | 1237 | 1.44M | auto &FS = BUI.FutureSuccessors[CurrentUpdate.getFrom()]; | 1238 | 1.44M | assert(FS.back().getPointer() == CurrentUpdate.getTo() && | 1239 | 1.44M | FS.back().getInt() == CurrentUpdate.getKind()); | 1240 | 1.44M | FS.pop_back(); | 1241 | 1.44M | if (FS.empty()) BUI.FutureSuccessors.erase(CurrentUpdate.getFrom())857k ; | 1242 | 1.44M | | 1243 | 1.44M | auto &FP = BUI.FuturePredecessors[CurrentUpdate.getTo()]; | 1244 | 1.44M | assert(FP.back().getPointer() == CurrentUpdate.getFrom() && | 1245 | 1.44M | FP.back().getInt() == CurrentUpdate.getKind()); | 1246 | 1.44M | FP.pop_back(); | 1247 | 1.44M | if (FP.empty()) BUI.FuturePredecessors.erase(CurrentUpdate.getTo())955k ; | 1248 | 1.44M | | 1249 | 1.44M | if (CurrentUpdate.getKind() == UpdateKind::Insert) | 1250 | 615k | InsertEdge(DT, &BUI, CurrentUpdate.getFrom(), CurrentUpdate.getTo()); | 1251 | 828k | else | 1252 | 828k | DeleteEdge(DT, &BUI, CurrentUpdate.getFrom(), CurrentUpdate.getTo()); | 1253 | 1.44M | } |
llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, true> >::ApplyNextUpdate(llvm::DominatorTreeBase<llvm::BasicBlock, true>&, llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, true> >::BatchUpdateInfo&) Line | Count | Source | 1223 | 61 | static void ApplyNextUpdate(DomTreeT &DT, BatchUpdateInfo &BUI) { | 1224 | 61 | assert(!BUI.Updates.empty() && "No updates to apply!"); | 1225 | 61 | UpdateT CurrentUpdate = BUI.Updates.pop_back_val(); | 1226 | | #if 0 | 1227 | | // FIXME: The LLVM_DEBUG macro only plays well with a modular | 1228 | | // build of LLVM when the header is marked as textual, but doing | 1229 | | // so causes redefinition errors. | 1230 | | LLVM_DEBUG(dbgs() << "Applying update: "); | 1231 | | LLVM_DEBUG(CurrentUpdate.dump(); dbgs() << "\n"); | 1232 | | #endif | 1233 | | | 1234 | 61 | // Move to the next snapshot of the CFG by removing the reverse-applied | 1235 | 61 | // current update. Since updates are performed in the same order they are | 1236 | 61 | // legalized it's sufficient to pop the last item here. | 1237 | 61 | auto &FS = BUI.FutureSuccessors[CurrentUpdate.getFrom()]; | 1238 | 61 | assert(FS.back().getPointer() == CurrentUpdate.getTo() && | 1239 | 61 | FS.back().getInt() == CurrentUpdate.getKind()); | 1240 | 61 | FS.pop_back(); | 1241 | 61 | if (FS.empty()) BUI.FutureSuccessors.erase(CurrentUpdate.getFrom())44 ; | 1242 | 61 | | 1243 | 61 | auto &FP = BUI.FuturePredecessors[CurrentUpdate.getTo()]; | 1244 | 61 | assert(FP.back().getPointer() == CurrentUpdate.getFrom() && | 1245 | 61 | FP.back().getInt() == CurrentUpdate.getKind()); | 1246 | 61 | FP.pop_back(); | 1247 | 61 | if (FP.empty()) BUI.FuturePredecessors.erase(CurrentUpdate.getTo())21 ; | 1248 | 61 | | 1249 | 61 | if (CurrentUpdate.getKind() == UpdateKind::Insert) | 1250 | 20 | InsertEdge(DT, &BUI, CurrentUpdate.getFrom(), CurrentUpdate.getTo()); | 1251 | 41 | else | 1252 | 41 | DeleteEdge(DT, &BUI, CurrentUpdate.getFrom(), CurrentUpdate.getTo()); | 1253 | 61 | } |
|
1254 | | |
1255 | | //~~ |
1256 | | //===--------------- DomTree correctness verification ---------------------=== |
1257 | | //~~ |
1258 | | |
1259 | | // Check if the tree has correct roots. A DominatorTree always has a single |
1260 | | // root which is the function's entry node. A PostDominatorTree can have |
1261 | | // multiple roots - one for each node with no successors and for infinite |
1262 | | // loops. |
1263 | | // Running time: O(N). |
1264 | 715 | bool verifyRoots(const DomTreeT &DT) { |
1265 | 715 | if (!DT.Parent && !DT.Roots.empty()0 ) { |
1266 | 0 | errs() << "Tree has no parent but has roots!\n"; |
1267 | 0 | errs().flush(); |
1268 | 0 | return false; |
1269 | 0 | } |
1270 | 715 | |
1271 | 715 | if (!IsPostDom) { |
1272 | 367 | if (DT.Roots.empty()) { |
1273 | 0 | errs() << "Tree doesn't have a root!\n"; |
1274 | 0 | errs().flush(); |
1275 | 0 | return false; |
1276 | 0 | } |
1277 | 367 | |
1278 | 367 | if (DT.getRoot() != GetEntryNode(DT)) { |
1279 | 0 | errs() << "Tree's root is not its parent's entry node!\n"; |
1280 | 0 | errs().flush(); |
1281 | 0 | return false; |
1282 | 0 | } |
1283 | 715 | } |
1284 | 715 | |
1285 | 715 | RootsT ComputedRoots = FindRoots(DT, nullptr); |
1286 | 715 | if (!isPermutation(DT.Roots, ComputedRoots)) { |
1287 | 0 | errs() << "Tree has different roots than freshly computed ones!\n"; |
1288 | 0 | errs() << "\tPDT roots: "; |
1289 | 0 | for (const NodePtr N : DT.Roots) errs() << BlockNamePrinter(N) << ", "; |
1290 | 0 | errs() << "\n\tComputed roots: "; |
1291 | 0 | for (const NodePtr N : ComputedRoots) |
1292 | 0 | errs() << BlockNamePrinter(N) << ", "; |
1293 | 0 | errs() << "\n"; |
1294 | 0 | errs().flush(); |
1295 | 0 | return false; |
1296 | 0 | } |
1297 | 715 | |
1298 | 715 | return true; |
1299 | 715 | } Unexecuted instantiation: llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> >::verifyRoots(llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> const&) Unexecuted instantiation: llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> >::verifyRoots(llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> const&) llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, false> >::verifyRoots(llvm::DominatorTreeBase<llvm::BasicBlock, false> const&) Line | Count | Source | 1264 | 367 | bool verifyRoots(const DomTreeT &DT) { | 1265 | 367 | if (!DT.Parent && !DT.Roots.empty()0 ) { | 1266 | 0 | errs() << "Tree has no parent but has roots!\n"; | 1267 | 0 | errs().flush(); | 1268 | 0 | return false; | 1269 | 0 | } | 1270 | 367 | | 1271 | 367 | if (!IsPostDom) { | 1272 | 367 | if (DT.Roots.empty()) { | 1273 | 0 | errs() << "Tree doesn't have a root!\n"; | 1274 | 0 | errs().flush(); | 1275 | 0 | return false; | 1276 | 0 | } | 1277 | 367 | | 1278 | 367 | if (DT.getRoot() != GetEntryNode(DT)) { | 1279 | 0 | errs() << "Tree's root is not its parent's entry node!\n"; | 1280 | 0 | errs().flush(); | 1281 | 0 | return false; | 1282 | 0 | } | 1283 | 367 | } | 1284 | 367 | | 1285 | 367 | RootsT ComputedRoots = FindRoots(DT, nullptr); | 1286 | 367 | if (!isPermutation(DT.Roots, ComputedRoots)) { | 1287 | 0 | errs() << "Tree has different roots than freshly computed ones!\n"; | 1288 | 0 | errs() << "\tPDT roots: "; | 1289 | 0 | for (const NodePtr N : DT.Roots) errs() << BlockNamePrinter(N) << ", "; | 1290 | 0 | errs() << "\n\tComputed roots: "; | 1291 | 0 | for (const NodePtr N : ComputedRoots) | 1292 | 0 | errs() << BlockNamePrinter(N) << ", "; | 1293 | 0 | errs() << "\n"; | 1294 | 0 | errs().flush(); | 1295 | 0 | return false; | 1296 | 0 | } | 1297 | 367 | | 1298 | 367 | return true; | 1299 | 367 | } |
llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, true> >::verifyRoots(llvm::DominatorTreeBase<llvm::BasicBlock, true> const&) Line | Count | Source | 1264 | 348 | bool verifyRoots(const DomTreeT &DT) { | 1265 | 348 | if (!DT.Parent && !DT.Roots.empty()0 ) { | 1266 | 0 | errs() << "Tree has no parent but has roots!\n"; | 1267 | 0 | errs().flush(); | 1268 | 0 | return false; | 1269 | 0 | } | 1270 | 348 | | 1271 | 348 | if (!IsPostDom) { | 1272 | 0 | if (DT.Roots.empty()) { | 1273 | 0 | errs() << "Tree doesn't have a root!\n"; | 1274 | 0 | errs().flush(); | 1275 | 0 | return false; | 1276 | 0 | } | 1277 | 0 | | 1278 | 0 | if (DT.getRoot() != GetEntryNode(DT)) { | 1279 | 0 | errs() << "Tree's root is not its parent's entry node!\n"; | 1280 | 0 | errs().flush(); | 1281 | 0 | return false; | 1282 | 0 | } | 1283 | 348 | } | 1284 | 348 | | 1285 | 348 | RootsT ComputedRoots = FindRoots(DT, nullptr); | 1286 | 348 | if (!isPermutation(DT.Roots, ComputedRoots)) { | 1287 | 0 | errs() << "Tree has different roots than freshly computed ones!\n"; | 1288 | 0 | errs() << "\tPDT roots: "; | 1289 | 0 | for (const NodePtr N : DT.Roots) errs() << BlockNamePrinter(N) << ", "; | 1290 | 0 | errs() << "\n\tComputed roots: "; | 1291 | 0 | for (const NodePtr N : ComputedRoots) | 1292 | 0 | errs() << BlockNamePrinter(N) << ", "; | 1293 | 0 | errs() << "\n"; | 1294 | 0 | errs().flush(); | 1295 | 0 | return false; | 1296 | 0 | } | 1297 | 348 | | 1298 | 348 | return true; | 1299 | 348 | } |
|
1300 | | |
1301 | | // Checks if the tree contains all reachable nodes in the input graph. |
1302 | | // Running time: O(N). |
1303 | 715 | bool verifyReachability(const DomTreeT &DT) { |
1304 | 715 | clear(); |
1305 | 715 | doFullDFSWalk(DT, AlwaysDescend); |
1306 | 715 | |
1307 | 6.68k | for (auto &NodeToTN : DT.DomTreeNodes) { |
1308 | 6.68k | const TreeNodePtr TN = NodeToTN.second.get(); |
1309 | 6.68k | const NodePtr BB = TN->getBlock(); |
1310 | 6.68k | |
1311 | 6.68k | // Virtual root has a corresponding virtual CFG node. |
1312 | 6.68k | if (DT.isVirtualRoot(TN)) continue348 ; |
1313 | 6.33k | |
1314 | 6.33k | if (NodeToInfo.count(BB) == 0) { |
1315 | 0 | errs() << "DomTree node " << BlockNamePrinter(BB) |
1316 | 0 | << " not found by DFS walk!\n"; |
1317 | 0 | errs().flush(); |
1318 | 0 |
|
1319 | 0 | return false; |
1320 | 0 | } |
1321 | 6.33k | } |
1322 | 715 | |
1323 | 7.39k | for (const NodePtr N : NumToNode)715 { |
1324 | 7.39k | if (N && !DT.getNode(N)6.33k ) { |
1325 | 0 | errs() << "CFG node " << BlockNamePrinter(N) |
1326 | 0 | << " not found in the DomTree!\n"; |
1327 | 0 | errs().flush(); |
1328 | 0 |
|
1329 | 0 | return false; |
1330 | 0 | } |
1331 | 7.39k | } |
1332 | 715 | |
1333 | 715 | return true; |
1334 | 715 | } Unexecuted instantiation: llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> >::verifyReachability(llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> const&) Unexecuted instantiation: llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> >::verifyReachability(llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> const&) llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, false> >::verifyReachability(llvm::DominatorTreeBase<llvm::BasicBlock, false> const&) Line | Count | Source | 1303 | 367 | bool verifyReachability(const DomTreeT &DT) { | 1304 | 367 | clear(); | 1305 | 367 | doFullDFSWalk(DT, AlwaysDescend); | 1306 | 367 | | 1307 | 2.83k | for (auto &NodeToTN : DT.DomTreeNodes) { | 1308 | 2.83k | const TreeNodePtr TN = NodeToTN.second.get(); | 1309 | 2.83k | const NodePtr BB = TN->getBlock(); | 1310 | 2.83k | | 1311 | 2.83k | // Virtual root has a corresponding virtual CFG node. | 1312 | 2.83k | if (DT.isVirtualRoot(TN)) continue0 ; | 1313 | 2.83k | | 1314 | 2.83k | if (NodeToInfo.count(BB) == 0) { | 1315 | 0 | errs() << "DomTree node " << BlockNamePrinter(BB) | 1316 | 0 | << " not found by DFS walk!\n"; | 1317 | 0 | errs().flush(); | 1318 | 0 |
| 1319 | 0 | return false; | 1320 | 0 | } | 1321 | 2.83k | } | 1322 | 367 | | 1323 | 3.20k | for (const NodePtr N : NumToNode)367 { | 1324 | 3.20k | if (N && !DT.getNode(N)2.83k ) { | 1325 | 0 | errs() << "CFG node " << BlockNamePrinter(N) | 1326 | 0 | << " not found in the DomTree!\n"; | 1327 | 0 | errs().flush(); | 1328 | 0 |
| 1329 | 0 | return false; | 1330 | 0 | } | 1331 | 3.20k | } | 1332 | 367 | | 1333 | 367 | return true; | 1334 | 367 | } |
llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, true> >::verifyReachability(llvm::DominatorTreeBase<llvm::BasicBlock, true> const&) Line | Count | Source | 1303 | 348 | bool verifyReachability(const DomTreeT &DT) { | 1304 | 348 | clear(); | 1305 | 348 | doFullDFSWalk(DT, AlwaysDescend); | 1306 | 348 | | 1307 | 3.85k | for (auto &NodeToTN : DT.DomTreeNodes) { | 1308 | 3.85k | const TreeNodePtr TN = NodeToTN.second.get(); | 1309 | 3.85k | const NodePtr BB = TN->getBlock(); | 1310 | 3.85k | | 1311 | 3.85k | // Virtual root has a corresponding virtual CFG node. | 1312 | 3.85k | if (DT.isVirtualRoot(TN)) continue348 ; | 1313 | 3.50k | | 1314 | 3.50k | if (NodeToInfo.count(BB) == 0) { | 1315 | 0 | errs() << "DomTree node " << BlockNamePrinter(BB) | 1316 | 0 | << " not found by DFS walk!\n"; | 1317 | 0 | errs().flush(); | 1318 | 0 |
| 1319 | 0 | return false; | 1320 | 0 | } | 1321 | 3.50k | } | 1322 | 348 | | 1323 | 4.19k | for (const NodePtr N : NumToNode)348 { | 1324 | 4.19k | if (N && !DT.getNode(N)3.50k ) { | 1325 | 0 | errs() << "CFG node " << BlockNamePrinter(N) | 1326 | 0 | << " not found in the DomTree!\n"; | 1327 | 0 | errs().flush(); | 1328 | 0 |
| 1329 | 0 | return false; | 1330 | 0 | } | 1331 | 4.19k | } | 1332 | 348 | | 1333 | 348 | return true; | 1334 | 348 | } |
|
1335 | | |
1336 | | // Check if for every parent with a level L in the tree all of its children |
1337 | | // have level L + 1. |
1338 | | // Running time: O(N). |
1339 | 715 | static bool VerifyLevels(const DomTreeT &DT) { |
1340 | 6.68k | for (auto &NodeToTN : DT.DomTreeNodes) { |
1341 | 6.68k | const TreeNodePtr TN = NodeToTN.second.get(); |
1342 | 6.68k | const NodePtr BB = TN->getBlock(); |
1343 | 6.68k | if (!BB) continue348 ; |
1344 | 6.33k | |
1345 | 6.33k | const TreeNodePtr IDom = TN->getIDom(); |
1346 | 6.33k | if (!IDom && TN->getLevel() != 0367 ) { |
1347 | 0 | errs() << "Node without an IDom " << BlockNamePrinter(BB) |
1348 | 0 | << " has a nonzero level " << TN->getLevel() << "!\n"; |
1349 | 0 | errs().flush(); |
1350 | 0 |
|
1351 | 0 | return false; |
1352 | 0 | } |
1353 | 6.33k | |
1354 | 6.33k | if (IDom && TN->getLevel() != IDom->getLevel() + 15.96k ) { |
1355 | 0 | errs() << "Node " << BlockNamePrinter(BB) << " has level " |
1356 | 0 | << TN->getLevel() << " while its IDom " |
1357 | 0 | << BlockNamePrinter(IDom->getBlock()) << " has level " |
1358 | 0 | << IDom->getLevel() << "!\n"; |
1359 | 0 | errs().flush(); |
1360 | 0 |
|
1361 | 0 | return false; |
1362 | 0 | } |
1363 | 6.33k | } |
1364 | 715 | |
1365 | 715 | return true; |
1366 | 715 | } Unexecuted instantiation: llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> >::VerifyLevels(llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> const&) Unexecuted instantiation: llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> >::VerifyLevels(llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> const&) llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, false> >::VerifyLevels(llvm::DominatorTreeBase<llvm::BasicBlock, false> const&) Line | Count | Source | 1339 | 367 | static bool VerifyLevels(const DomTreeT &DT) { | 1340 | 2.83k | for (auto &NodeToTN : DT.DomTreeNodes) { | 1341 | 2.83k | const TreeNodePtr TN = NodeToTN.second.get(); | 1342 | 2.83k | const NodePtr BB = TN->getBlock(); | 1343 | 2.83k | if (!BB) continue0 ; | 1344 | 2.83k | | 1345 | 2.83k | const TreeNodePtr IDom = TN->getIDom(); | 1346 | 2.83k | if (!IDom && TN->getLevel() != 0367 ) { | 1347 | 0 | errs() << "Node without an IDom " << BlockNamePrinter(BB) | 1348 | 0 | << " has a nonzero level " << TN->getLevel() << "!\n"; | 1349 | 0 | errs().flush(); | 1350 | 0 |
| 1351 | 0 | return false; | 1352 | 0 | } | 1353 | 2.83k | | 1354 | 2.83k | if (IDom && TN->getLevel() != IDom->getLevel() + 12.46k ) { | 1355 | 0 | errs() << "Node " << BlockNamePrinter(BB) << " has level " | 1356 | 0 | << TN->getLevel() << " while its IDom " | 1357 | 0 | << BlockNamePrinter(IDom->getBlock()) << " has level " | 1358 | 0 | << IDom->getLevel() << "!\n"; | 1359 | 0 | errs().flush(); | 1360 | 0 |
| 1361 | 0 | return false; | 1362 | 0 | } | 1363 | 2.83k | } | 1364 | 367 | | 1365 | 367 | return true; | 1366 | 367 | } |
llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, true> >::VerifyLevels(llvm::DominatorTreeBase<llvm::BasicBlock, true> const&) Line | Count | Source | 1339 | 348 | static bool VerifyLevels(const DomTreeT &DT) { | 1340 | 3.85k | for (auto &NodeToTN : DT.DomTreeNodes) { | 1341 | 3.85k | const TreeNodePtr TN = NodeToTN.second.get(); | 1342 | 3.85k | const NodePtr BB = TN->getBlock(); | 1343 | 3.85k | if (!BB) continue348 ; | 1344 | 3.50k | | 1345 | 3.50k | const TreeNodePtr IDom = TN->getIDom(); | 1346 | 3.50k | if (!IDom && TN->getLevel() != 00 ) { | 1347 | 0 | errs() << "Node without an IDom " << BlockNamePrinter(BB) | 1348 | 0 | << " has a nonzero level " << TN->getLevel() << "!\n"; | 1349 | 0 | errs().flush(); | 1350 | 0 |
| 1351 | 0 | return false; | 1352 | 0 | } | 1353 | 3.50k | | 1354 | 3.50k | if (IDom && TN->getLevel() != IDom->getLevel() + 1) { | 1355 | 0 | errs() << "Node " << BlockNamePrinter(BB) << " has level " | 1356 | 0 | << TN->getLevel() << " while its IDom " | 1357 | 0 | << BlockNamePrinter(IDom->getBlock()) << " has level " | 1358 | 0 | << IDom->getLevel() << "!\n"; | 1359 | 0 | errs().flush(); | 1360 | 0 |
| 1361 | 0 | return false; | 1362 | 0 | } | 1363 | 3.50k | } | 1364 | 348 | | 1365 | 348 | return true; | 1366 | 348 | } |
|
1367 | | |
1368 | | // Check if the computed DFS numbers are correct. Note that DFS info may not |
1369 | | // be valid, and when that is the case, we don't verify the numbers. |
1370 | | // Running time: O(N log(N)). |
1371 | 715 | static bool VerifyDFSNumbers(const DomTreeT &DT) { |
1372 | 715 | if (!DT.DFSInfoValid || !DT.Parent1 ) |
1373 | 714 | return true; |
1374 | 1 | |
1375 | 1 | const NodePtr RootBB = IsPostDom ? nullptr0 : DT.getRoots()[0]; |
1376 | 1 | const TreeNodePtr Root = DT.getNode(RootBB); |
1377 | 1 | |
1378 | 1 | auto PrintNodeAndDFSNums = [](const TreeNodePtr TN) { |
1379 | 0 | errs() << BlockNamePrinter(TN) << " {" << TN->getDFSNumIn() << ", " |
1380 | 0 | << TN->getDFSNumOut() << '}'; |
1381 | 0 | }; Unexecuted instantiation: llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> >::VerifyDFSNumbers(llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> const&)::'lambda'(llvm::DomTreeNodeBase<llvm::MachineBasicBlock>*)::operator()(llvm::DomTreeNodeBase<llvm::MachineBasicBlock>*) const Unexecuted instantiation: llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> >::VerifyDFSNumbers(llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> const&)::'lambda'(llvm::DomTreeNodeBase<llvm::MachineBasicBlock>*)::operator()(llvm::DomTreeNodeBase<llvm::MachineBasicBlock>*) const Unexecuted instantiation: llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, false> >::VerifyDFSNumbers(llvm::DominatorTreeBase<llvm::BasicBlock, false> const&)::'lambda'(llvm::DomTreeNodeBase<llvm::BasicBlock>*)::operator()(llvm::DomTreeNodeBase<llvm::BasicBlock>*) const Unexecuted instantiation: llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, true> >::VerifyDFSNumbers(llvm::DominatorTreeBase<llvm::BasicBlock, true> const&)::'lambda'(llvm::DomTreeNodeBase<llvm::BasicBlock>*)::operator()(llvm::DomTreeNodeBase<llvm::BasicBlock>*) const |
1382 | 1 | |
1383 | 1 | // Verify the root's DFS In number. Although DFS numbering would also work |
1384 | 1 | // if we started from some other value, we assume 0-based numbering. |
1385 | 1 | if (Root->getDFSNumIn() != 0) { |
1386 | 0 | errs() << "DFSIn number for the tree root is not:\n\t"; |
1387 | 0 | PrintNodeAndDFSNums(Root); |
1388 | 0 | errs() << '\n'; |
1389 | 0 | errs().flush(); |
1390 | 0 | return false; |
1391 | 0 | } |
1392 | 1 | |
1393 | 1 | // For each tree node verify if children's DFS numbers cover their parent's |
1394 | 1 | // DFS numbers with no gaps. |
1395 | 5 | for (const auto &NodeToTN : DT.DomTreeNodes)1 { |
1396 | 5 | const TreeNodePtr Node = NodeToTN.second.get(); |
1397 | 5 | |
1398 | 5 | // Handle tree leaves. |
1399 | 5 | if (Node->getChildren().empty()) { |
1400 | 3 | if (Node->getDFSNumIn() + 1 != Node->getDFSNumOut()) { |
1401 | 0 | errs() << "Tree leaf should have DFSOut = DFSIn + 1:\n\t"; |
1402 | 0 | PrintNodeAndDFSNums(Node); |
1403 | 0 | errs() << '\n'; |
1404 | 0 | errs().flush(); |
1405 | 0 | return false; |
1406 | 0 | } |
1407 | 3 | |
1408 | 3 | continue; |
1409 | 3 | } |
1410 | 2 | |
1411 | 2 | // Make a copy and sort it such that it is possible to check if there are |
1412 | 2 | // no gaps between DFS numbers of adjacent children. |
1413 | 2 | SmallVector<TreeNodePtr, 8> Children(Node->begin(), Node->end()); |
1414 | 2 | llvm::sort(Children, [](const TreeNodePtr Ch1, const TreeNodePtr Ch2) { |
1415 | 2 | return Ch1->getDFSNumIn() < Ch2->getDFSNumIn(); |
1416 | 2 | }); Unexecuted instantiation: llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> >::VerifyDFSNumbers(llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> const&)::'lambda'(llvm::DomTreeNodeBase<llvm::MachineBasicBlock>*, llvm::DomTreeNodeBase<llvm::MachineBasicBlock>*)::operator()(llvm::DomTreeNodeBase<llvm::MachineBasicBlock>*, llvm::DomTreeNodeBase<llvm::MachineBasicBlock>*) const Unexecuted instantiation: llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> >::VerifyDFSNumbers(llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> const&)::'lambda'(llvm::DomTreeNodeBase<llvm::MachineBasicBlock>*, llvm::DomTreeNodeBase<llvm::MachineBasicBlock>*)::operator()(llvm::DomTreeNodeBase<llvm::MachineBasicBlock>*, llvm::DomTreeNodeBase<llvm::MachineBasicBlock>*) const llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, false> >::VerifyDFSNumbers(llvm::DominatorTreeBase<llvm::BasicBlock, false> const&)::'lambda'(llvm::DomTreeNodeBase<llvm::BasicBlock>*, llvm::DomTreeNodeBase<llvm::BasicBlock>*)::operator()(llvm::DomTreeNodeBase<llvm::BasicBlock>*, llvm::DomTreeNodeBase<llvm::BasicBlock>*) const Line | Count | Source | 1414 | 2 | llvm::sort(Children, [](const TreeNodePtr Ch1, const TreeNodePtr Ch2) { | 1415 | 2 | return Ch1->getDFSNumIn() < Ch2->getDFSNumIn(); | 1416 | 2 | }); |
Unexecuted instantiation: llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, true> >::VerifyDFSNumbers(llvm::DominatorTreeBase<llvm::BasicBlock, true> const&)::'lambda'(llvm::DomTreeNodeBase<llvm::BasicBlock>*, llvm::DomTreeNodeBase<llvm::BasicBlock>*)::operator()(llvm::DomTreeNodeBase<llvm::BasicBlock>*, llvm::DomTreeNodeBase<llvm::BasicBlock>*) const |
1417 | 2 | |
1418 | 2 | auto PrintChildrenError = [Node, &Children, PrintNodeAndDFSNums]( |
1419 | 2 | const TreeNodePtr FirstCh, const TreeNodePtr SecondCh) { |
1420 | 0 | assert(FirstCh); |
1421 | 0 |
|
1422 | 0 | errs() << "Incorrect DFS numbers for:\n\tParent "; |
1423 | 0 | PrintNodeAndDFSNums(Node); |
1424 | 0 |
|
1425 | 0 | errs() << "\n\tChild "; |
1426 | 0 | PrintNodeAndDFSNums(FirstCh); |
1427 | 0 |
|
1428 | 0 | if (SecondCh) { |
1429 | 0 | errs() << "\n\tSecond child "; |
1430 | 0 | PrintNodeAndDFSNums(SecondCh); |
1431 | 0 | } |
1432 | 0 |
|
1433 | 0 | errs() << "\nAll children: "; |
1434 | 0 | for (const TreeNodePtr Ch : Children) { |
1435 | 0 | PrintNodeAndDFSNums(Ch); |
1436 | 0 | errs() << ", "; |
1437 | 0 | } |
1438 | 0 |
|
1439 | 0 | errs() << '\n'; |
1440 | 0 | errs().flush(); |
1441 | 0 | }; Unexecuted instantiation: llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> >::VerifyDFSNumbers(llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> const&)::'lambda0'(llvm::DomTreeNodeBase<llvm::MachineBasicBlock>*, llvm::DomTreeNodeBase<llvm::MachineBasicBlock>*)::operator()(llvm::DomTreeNodeBase<llvm::MachineBasicBlock>*, llvm::DomTreeNodeBase<llvm::MachineBasicBlock>*) const Unexecuted instantiation: llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> >::VerifyDFSNumbers(llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> const&)::'lambda0'(llvm::DomTreeNodeBase<llvm::MachineBasicBlock>*, llvm::DomTreeNodeBase<llvm::MachineBasicBlock>*)::operator()(llvm::DomTreeNodeBase<llvm::MachineBasicBlock>*, llvm::DomTreeNodeBase<llvm::MachineBasicBlock>*) const Unexecuted instantiation: llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, false> >::VerifyDFSNumbers(llvm::DominatorTreeBase<llvm::BasicBlock, false> const&)::'lambda0'(llvm::DomTreeNodeBase<llvm::BasicBlock>*, llvm::DomTreeNodeBase<llvm::BasicBlock>*)::operator()(llvm::DomTreeNodeBase<llvm::BasicBlock>*, llvm::DomTreeNodeBase<llvm::BasicBlock>*) const Unexecuted instantiation: llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, true> >::VerifyDFSNumbers(llvm::DominatorTreeBase<llvm::BasicBlock, true> const&)::'lambda0'(llvm::DomTreeNodeBase<llvm::BasicBlock>*, llvm::DomTreeNodeBase<llvm::BasicBlock>*)::operator()(llvm::DomTreeNodeBase<llvm::BasicBlock>*, llvm::DomTreeNodeBase<llvm::BasicBlock>*) const |
1442 | 2 | |
1443 | 2 | if (Children.front()->getDFSNumIn() != Node->getDFSNumIn() + 1) { |
1444 | 0 | PrintChildrenError(Children.front(), nullptr); |
1445 | 0 | return false; |
1446 | 0 | } |
1447 | 2 | |
1448 | 2 | if (Children.back()->getDFSNumOut() + 1 != Node->getDFSNumOut()) { |
1449 | 0 | PrintChildrenError(Children.back(), nullptr); |
1450 | 0 | return false; |
1451 | 0 | } |
1452 | 2 | |
1453 | 4 | for (size_t i = 0, e = Children.size() - 1; 2 i != e; ++i2 ) { |
1454 | 2 | if (Children[i]->getDFSNumOut() + 1 != Children[i + 1]->getDFSNumIn()) { |
1455 | 0 | PrintChildrenError(Children[i], Children[i + 1]); |
1456 | 0 | return false; |
1457 | 0 | } |
1458 | 2 | } |
1459 | 2 | } |
1460 | 1 | |
1461 | 1 | return true; |
1462 | 1 | } Unexecuted instantiation: llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> >::VerifyDFSNumbers(llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> const&) Unexecuted instantiation: llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> >::VerifyDFSNumbers(llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> const&) llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, false> >::VerifyDFSNumbers(llvm::DominatorTreeBase<llvm::BasicBlock, false> const&) Line | Count | Source | 1371 | 367 | static bool VerifyDFSNumbers(const DomTreeT &DT) { | 1372 | 367 | if (!DT.DFSInfoValid || !DT.Parent1 ) | 1373 | 366 | return true; | 1374 | 1 | | 1375 | 1 | const NodePtr RootBB = IsPostDom ? nullptr0 : DT.getRoots()[0]; | 1376 | 1 | const TreeNodePtr Root = DT.getNode(RootBB); | 1377 | 1 | | 1378 | 1 | auto PrintNodeAndDFSNums = [](const TreeNodePtr TN) { | 1379 | 1 | errs() << BlockNamePrinter(TN) << " {" << TN->getDFSNumIn() << ", " | 1380 | 1 | << TN->getDFSNumOut() << '}'; | 1381 | 1 | }; | 1382 | 1 | | 1383 | 1 | // Verify the root's DFS In number. Although DFS numbering would also work | 1384 | 1 | // if we started from some other value, we assume 0-based numbering. | 1385 | 1 | if (Root->getDFSNumIn() != 0) { | 1386 | 0 | errs() << "DFSIn number for the tree root is not:\n\t"; | 1387 | 0 | PrintNodeAndDFSNums(Root); | 1388 | 0 | errs() << '\n'; | 1389 | 0 | errs().flush(); | 1390 | 0 | return false; | 1391 | 0 | } | 1392 | 1 | | 1393 | 1 | // For each tree node verify if children's DFS numbers cover their parent's | 1394 | 1 | // DFS numbers with no gaps. | 1395 | 5 | for (const auto &NodeToTN : DT.DomTreeNodes)1 { | 1396 | 5 | const TreeNodePtr Node = NodeToTN.second.get(); | 1397 | 5 | | 1398 | 5 | // Handle tree leaves. | 1399 | 5 | if (Node->getChildren().empty()) { | 1400 | 3 | if (Node->getDFSNumIn() + 1 != Node->getDFSNumOut()) { | 1401 | 0 | errs() << "Tree leaf should have DFSOut = DFSIn + 1:\n\t"; | 1402 | 0 | PrintNodeAndDFSNums(Node); | 1403 | 0 | errs() << '\n'; | 1404 | 0 | errs().flush(); | 1405 | 0 | return false; | 1406 | 0 | } | 1407 | 3 | | 1408 | 3 | continue; | 1409 | 3 | } | 1410 | 2 | | 1411 | 2 | // Make a copy and sort it such that it is possible to check if there are | 1412 | 2 | // no gaps between DFS numbers of adjacent children. | 1413 | 2 | SmallVector<TreeNodePtr, 8> Children(Node->begin(), Node->end()); | 1414 | 2 | llvm::sort(Children, [](const TreeNodePtr Ch1, const TreeNodePtr Ch2) { | 1415 | 2 | return Ch1->getDFSNumIn() < Ch2->getDFSNumIn(); | 1416 | 2 | }); | 1417 | 2 | | 1418 | 2 | auto PrintChildrenError = [Node, &Children, PrintNodeAndDFSNums]( | 1419 | 2 | const TreeNodePtr FirstCh, const TreeNodePtr SecondCh) { | 1420 | 2 | assert(FirstCh); | 1421 | 2 | | 1422 | 2 | errs() << "Incorrect DFS numbers for:\n\tParent "; | 1423 | 2 | PrintNodeAndDFSNums(Node); | 1424 | 2 | | 1425 | 2 | errs() << "\n\tChild "; | 1426 | 2 | PrintNodeAndDFSNums(FirstCh); | 1427 | 2 | | 1428 | 2 | if (SecondCh) { | 1429 | 2 | errs() << "\n\tSecond child "; | 1430 | 2 | PrintNodeAndDFSNums(SecondCh); | 1431 | 2 | } | 1432 | 2 | | 1433 | 2 | errs() << "\nAll children: "; | 1434 | 2 | for (const TreeNodePtr Ch : Children) { | 1435 | 2 | PrintNodeAndDFSNums(Ch); | 1436 | 2 | errs() << ", "; | 1437 | 2 | } | 1438 | 2 | | 1439 | 2 | errs() << '\n'; | 1440 | 2 | errs().flush(); | 1441 | 2 | }; | 1442 | 2 | | 1443 | 2 | if (Children.front()->getDFSNumIn() != Node->getDFSNumIn() + 1) { | 1444 | 0 | PrintChildrenError(Children.front(), nullptr); | 1445 | 0 | return false; | 1446 | 0 | } | 1447 | 2 | | 1448 | 2 | if (Children.back()->getDFSNumOut() + 1 != Node->getDFSNumOut()) { | 1449 | 0 | PrintChildrenError(Children.back(), nullptr); | 1450 | 0 | return false; | 1451 | 0 | } | 1452 | 2 | | 1453 | 4 | for (size_t i = 0, e = Children.size() - 1; 2 i != e; ++i2 ) { | 1454 | 2 | if (Children[i]->getDFSNumOut() + 1 != Children[i + 1]->getDFSNumIn()) { | 1455 | 0 | PrintChildrenError(Children[i], Children[i + 1]); | 1456 | 0 | return false; | 1457 | 0 | } | 1458 | 2 | } | 1459 | 2 | } | 1460 | 1 | | 1461 | 1 | return true; | 1462 | 1 | } |
llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, true> >::VerifyDFSNumbers(llvm::DominatorTreeBase<llvm::BasicBlock, true> const&) Line | Count | Source | 1371 | 348 | static bool VerifyDFSNumbers(const DomTreeT &DT) { | 1372 | 348 | if (!DT.DFSInfoValid || !DT.Parent0 ) | 1373 | 348 | return true; | 1374 | 0 | | 1375 | 0 | const NodePtr RootBB = IsPostDom ? nullptr : DT.getRoots()[0]; | 1376 | 0 | const TreeNodePtr Root = DT.getNode(RootBB); | 1377 | 0 |
| 1378 | 0 | auto PrintNodeAndDFSNums = [](const TreeNodePtr TN) { | 1379 | 0 | errs() << BlockNamePrinter(TN) << " {" << TN->getDFSNumIn() << ", " | 1380 | 0 | << TN->getDFSNumOut() << '}'; | 1381 | 0 | }; | 1382 | 0 |
| 1383 | 0 | // Verify the root's DFS In number. Although DFS numbering would also work | 1384 | 0 | // if we started from some other value, we assume 0-based numbering. | 1385 | 0 | if (Root->getDFSNumIn() != 0) { | 1386 | 0 | errs() << "DFSIn number for the tree root is not:\n\t"; | 1387 | 0 | PrintNodeAndDFSNums(Root); | 1388 | 0 | errs() << '\n'; | 1389 | 0 | errs().flush(); | 1390 | 0 | return false; | 1391 | 0 | } | 1392 | 0 | | 1393 | 0 | // For each tree node verify if children's DFS numbers cover their parent's | 1394 | 0 | // DFS numbers with no gaps. | 1395 | 0 | for (const auto &NodeToTN : DT.DomTreeNodes) { | 1396 | 0 | const TreeNodePtr Node = NodeToTN.second.get(); | 1397 | 0 |
| 1398 | 0 | // Handle tree leaves. | 1399 | 0 | if (Node->getChildren().empty()) { | 1400 | 0 | if (Node->getDFSNumIn() + 1 != Node->getDFSNumOut()) { | 1401 | 0 | errs() << "Tree leaf should have DFSOut = DFSIn + 1:\n\t"; | 1402 | 0 | PrintNodeAndDFSNums(Node); | 1403 | 0 | errs() << '\n'; | 1404 | 0 | errs().flush(); | 1405 | 0 | return false; | 1406 | 0 | } | 1407 | 0 | | 1408 | 0 | continue; | 1409 | 0 | } | 1410 | 0 | | 1411 | 0 | // Make a copy and sort it such that it is possible to check if there are | 1412 | 0 | // no gaps between DFS numbers of adjacent children. | 1413 | 0 | SmallVector<TreeNodePtr, 8> Children(Node->begin(), Node->end()); | 1414 | 0 | llvm::sort(Children, [](const TreeNodePtr Ch1, const TreeNodePtr Ch2) { | 1415 | 0 | return Ch1->getDFSNumIn() < Ch2->getDFSNumIn(); | 1416 | 0 | }); | 1417 | 0 |
| 1418 | 0 | auto PrintChildrenError = [Node, &Children, PrintNodeAndDFSNums]( | 1419 | 0 | const TreeNodePtr FirstCh, const TreeNodePtr SecondCh) { | 1420 | 0 | assert(FirstCh); | 1421 | 0 |
| 1422 | 0 | errs() << "Incorrect DFS numbers for:\n\tParent "; | 1423 | 0 | PrintNodeAndDFSNums(Node); | 1424 | 0 |
| 1425 | 0 | errs() << "\n\tChild "; | 1426 | 0 | PrintNodeAndDFSNums(FirstCh); | 1427 | 0 |
| 1428 | 0 | if (SecondCh) { | 1429 | 0 | errs() << "\n\tSecond child "; | 1430 | 0 | PrintNodeAndDFSNums(SecondCh); | 1431 | 0 | } | 1432 | 0 |
| 1433 | 0 | errs() << "\nAll children: "; | 1434 | 0 | for (const TreeNodePtr Ch : Children) { | 1435 | 0 | PrintNodeAndDFSNums(Ch); | 1436 | 0 | errs() << ", "; | 1437 | 0 | } | 1438 | 0 |
| 1439 | 0 | errs() << '\n'; | 1440 | 0 | errs().flush(); | 1441 | 0 | }; | 1442 | 0 |
| 1443 | 0 | if (Children.front()->getDFSNumIn() != Node->getDFSNumIn() + 1) { | 1444 | 0 | PrintChildrenError(Children.front(), nullptr); | 1445 | 0 | return false; | 1446 | 0 | } | 1447 | 0 | | 1448 | 0 | if (Children.back()->getDFSNumOut() + 1 != Node->getDFSNumOut()) { | 1449 | 0 | PrintChildrenError(Children.back(), nullptr); | 1450 | 0 | return false; | 1451 | 0 | } | 1452 | 0 | | 1453 | 0 | for (size_t i = 0, e = Children.size() - 1; i != e; ++i) { | 1454 | 0 | if (Children[i]->getDFSNumOut() + 1 != Children[i + 1]->getDFSNumIn()) { | 1455 | 0 | PrintChildrenError(Children[i], Children[i + 1]); | 1456 | 0 | return false; | 1457 | 0 | } | 1458 | 0 | } | 1459 | 0 | } | 1460 | 0 |
| 1461 | 0 | return true; | 1462 | 0 | } |
|
1463 | | |
1464 | | // The below routines verify the correctness of the dominator tree relative to |
1465 | | // the CFG it's coming from. A tree is a dominator tree iff it has two |
1466 | | // properties, called the parent property and the sibling property. Tarjan |
1467 | | // and Lengauer prove (but don't explicitly name) the properties as part of |
1468 | | // the proofs in their 1972 paper, but the proofs are mostly part of proving |
1469 | | // things about semidominators and idoms, and some of them are simply asserted |
1470 | | // based on even earlier papers (see, e.g., lemma 2). Some papers refer to |
1471 | | // these properties as "valid" and "co-valid". See, e.g., "Dominators, |
1472 | | // directed bipolar orders, and independent spanning trees" by Loukas |
1473 | | // Georgiadis and Robert E. Tarjan, as well as "Dominator Tree Verification |
1474 | | // and Vertex-Disjoint Paths " by the same authors. |
1475 | | |
1476 | | // A very simple and direct explanation of these properties can be found in |
1477 | | // "An Experimental Study of Dynamic Dominators", found at |
1478 | | // https://arxiv.org/abs/1604.02711 |
1479 | | |
1480 | | // The easiest way to think of the parent property is that it's a requirement |
1481 | | // of being a dominator. Let's just take immediate dominators. For PARENT to |
1482 | | // be an immediate dominator of CHILD, all paths in the CFG must go through |
1483 | | // PARENT before they hit CHILD. This implies that if you were to cut PARENT |
1484 | | // out of the CFG, there should be no paths to CHILD that are reachable. If |
1485 | | // there are, then you now have a path from PARENT to CHILD that goes around |
1486 | | // PARENT and still reaches CHILD, which by definition, means PARENT can't be |
1487 | | // a dominator of CHILD (let alone an immediate one). |
1488 | | |
1489 | | // The sibling property is similar. It says that for each pair of sibling |
1490 | | // nodes in the dominator tree (LEFT and RIGHT) , they must not dominate each |
1491 | | // other. If sibling LEFT dominated sibling RIGHT, it means there are no |
1492 | | // paths in the CFG from sibling LEFT to sibling RIGHT that do not go through |
1493 | | // LEFT, and thus, LEFT is really an ancestor (in the dominator tree) of |
1494 | | // RIGHT, not a sibling. |
1495 | | |
1496 | | // It is possible to verify the parent and sibling properties in |
1497 | | // linear time, but the algorithms are complex. Instead, we do it in a |
1498 | | // straightforward N^2 and N^3 way below, using direct path reachability. |
1499 | | |
1500 | | // Checks if the tree has the parent property: if for all edges from V to W in |
1501 | | // the input graph, such that V is reachable, the parent of W in the tree is |
1502 | | // an ancestor of V in the tree. |
1503 | | // Running time: O(N^2). |
1504 | | // |
1505 | | // This means that if a node gets disconnected from the graph, then all of |
1506 | | // the nodes it dominated previously will now become unreachable. |
1507 | 715 | bool verifyParentProperty(const DomTreeT &DT) { |
1508 | 6.68k | for (auto &NodeToTN : DT.DomTreeNodes) { |
1509 | 6.68k | const TreeNodePtr TN = NodeToTN.second.get(); |
1510 | 6.68k | const NodePtr BB = TN->getBlock(); |
1511 | 6.68k | if (!BB || TN->getChildren().empty()6.33k ) continue3.24k ; |
1512 | 3.44k | |
1513 | 3.44k | LLVM_DEBUG(dbgs() << "Verifying parent property of node " |
1514 | 3.44k | << BlockNamePrinter(TN) << "\n"); |
1515 | 3.44k | clear(); |
1516 | 20.6k | doFullDFSWalk(DT, [BB](NodePtr From, NodePtr To) { |
1517 | 20.6k | return From != BB && To != BB19.4k ; |
1518 | 20.6k | }); Unexecuted instantiation: llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> >::verifyParentProperty(llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> const&)::'lambda'(llvm::MachineBasicBlock*, llvm::MachineBasicBlock*)::operator()(llvm::MachineBasicBlock*, llvm::MachineBasicBlock*) const Unexecuted instantiation: llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> >::verifyParentProperty(llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> const&)::'lambda'(llvm::MachineBasicBlock*, llvm::MachineBasicBlock*)::operator()(llvm::MachineBasicBlock*, llvm::MachineBasicBlock*) const llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, false> >::verifyParentProperty(llvm::DominatorTreeBase<llvm::BasicBlock, false> const&)::'lambda'(llvm::BasicBlock*, llvm::BasicBlock*)::operator()(llvm::BasicBlock*, llvm::BasicBlock*) const Line | Count | Source | 1516 | 8.06k | doFullDFSWalk(DT, [BB](NodePtr From, NodePtr To) { | 1517 | 8.06k | return From != BB && To != BB7.67k ; | 1518 | 8.06k | }); |
llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, true> >::verifyParentProperty(llvm::DominatorTreeBase<llvm::BasicBlock, true> const&)::'lambda'(llvm::BasicBlock*, llvm::BasicBlock*)::operator()(llvm::BasicBlock*, llvm::BasicBlock*) const Line | Count | Source | 1516 | 12.5k | doFullDFSWalk(DT, [BB](NodePtr From, NodePtr To) { | 1517 | 12.5k | return From != BB && To != BB11.8k ; | 1518 | 12.5k | }); |
|
1519 | 3.44k | |
1520 | 3.44k | for (TreeNodePtr Child : TN->getChildren()) |
1521 | 4.52k | if (NodeToInfo.count(Child->getBlock()) != 0) { |
1522 | 0 | errs() << "Child " << BlockNamePrinter(Child) |
1523 | 0 | << " reachable after its parent " << BlockNamePrinter(BB) |
1524 | 0 | << " is removed!\n"; |
1525 | 0 | errs().flush(); |
1526 | 0 |
|
1527 | 0 | return false; |
1528 | 0 | } |
1529 | 3.44k | } |
1530 | 715 | |
1531 | 715 | return true; |
1532 | 715 | } Unexecuted instantiation: llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> >::verifyParentProperty(llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> const&) Unexecuted instantiation: llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> >::verifyParentProperty(llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> const&) llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, false> >::verifyParentProperty(llvm::DominatorTreeBase<llvm::BasicBlock, false> const&) Line | Count | Source | 1507 | 367 | bool verifyParentProperty(const DomTreeT &DT) { | 1508 | 2.83k | for (auto &NodeToTN : DT.DomTreeNodes) { | 1509 | 2.83k | const TreeNodePtr TN = NodeToTN.second.get(); | 1510 | 2.83k | const NodePtr BB = TN->getBlock(); | 1511 | 2.83k | if (!BB || TN->getChildren().empty()) continue1.09k ; | 1512 | 1.73k | | 1513 | 1.73k | LLVM_DEBUG(dbgs() << "Verifying parent property of node " | 1514 | 1.73k | << BlockNamePrinter(TN) << "\n"); | 1515 | 1.73k | clear(); | 1516 | 1.73k | doFullDFSWalk(DT, [BB](NodePtr From, NodePtr To) { | 1517 | 1.73k | return From != BB && To != BB; | 1518 | 1.73k | }); | 1519 | 1.73k | | 1520 | 1.73k | for (TreeNodePtr Child : TN->getChildren()) | 1521 | 2.46k | if (NodeToInfo.count(Child->getBlock()) != 0) { | 1522 | 0 | errs() << "Child " << BlockNamePrinter(Child) | 1523 | 0 | << " reachable after its parent " << BlockNamePrinter(BB) | 1524 | 0 | << " is removed!\n"; | 1525 | 0 | errs().flush(); | 1526 | 0 |
| 1527 | 0 | return false; | 1528 | 0 | } | 1529 | 1.73k | } | 1530 | 367 | | 1531 | 367 | return true; | 1532 | 367 | } |
llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, true> >::verifyParentProperty(llvm::DominatorTreeBase<llvm::BasicBlock, true> const&) Line | Count | Source | 1507 | 348 | bool verifyParentProperty(const DomTreeT &DT) { | 1508 | 3.85k | for (auto &NodeToTN : DT.DomTreeNodes) { | 1509 | 3.85k | const TreeNodePtr TN = NodeToTN.second.get(); | 1510 | 3.85k | const NodePtr BB = TN->getBlock(); | 1511 | 3.85k | if (!BB || TN->getChildren().empty()3.50k ) continue2.14k ; | 1512 | 1.70k | | 1513 | 1.70k | LLVM_DEBUG(dbgs() << "Verifying parent property of node " | 1514 | 1.70k | << BlockNamePrinter(TN) << "\n"); | 1515 | 1.70k | clear(); | 1516 | 1.70k | doFullDFSWalk(DT, [BB](NodePtr From, NodePtr To) { | 1517 | 1.70k | return From != BB && To != BB; | 1518 | 1.70k | }); | 1519 | 1.70k | | 1520 | 1.70k | for (TreeNodePtr Child : TN->getChildren()) | 1521 | 2.05k | if (NodeToInfo.count(Child->getBlock()) != 0) { | 1522 | 0 | errs() << "Child " << BlockNamePrinter(Child) | 1523 | 0 | << " reachable after its parent " << BlockNamePrinter(BB) | 1524 | 0 | << " is removed!\n"; | 1525 | 0 | errs().flush(); | 1526 | 0 |
| 1527 | 0 | return false; | 1528 | 0 | } | 1529 | 1.70k | } | 1530 | 348 | | 1531 | 348 | return true; | 1532 | 348 | } |
|
1533 | | |
1534 | | // Check if the tree has sibling property: if a node V does not dominate a |
1535 | | // node W for all siblings V and W in the tree. |
1536 | | // Running time: O(N^3). |
1537 | | // |
1538 | | // This means that if a node gets disconnected from the graph, then all of its |
1539 | | // siblings will now still be reachable. |
1540 | 715 | bool verifySiblingProperty(const DomTreeT &DT) { |
1541 | 6.68k | for (auto &NodeToTN : DT.DomTreeNodes) { |
1542 | 6.68k | const TreeNodePtr TN = NodeToTN.second.get(); |
1543 | 6.68k | const NodePtr BB = TN->getBlock(); |
1544 | 6.68k | if (!BB || TN->getChildren().empty()6.33k ) continue3.24k ; |
1545 | 3.44k | |
1546 | 3.44k | const auto &Siblings = TN->getChildren(); |
1547 | 4.52k | for (const TreeNodePtr N : Siblings) { |
1548 | 4.52k | clear(); |
1549 | 4.52k | NodePtr BBN = N->getBlock(); |
1550 | 34.0k | doFullDFSWalk(DT, [BBN](NodePtr From, NodePtr To) { |
1551 | 34.0k | return From != BBN && To != BBN; |
1552 | 34.0k | }); Unexecuted instantiation: llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> >::verifySiblingProperty(llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> const&)::'lambda'(llvm::MachineBasicBlock*, llvm::MachineBasicBlock*)::operator()(llvm::MachineBasicBlock*, llvm::MachineBasicBlock*) const Unexecuted instantiation: llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> >::verifySiblingProperty(llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> const&)::'lambda'(llvm::MachineBasicBlock*, llvm::MachineBasicBlock*)::operator()(llvm::MachineBasicBlock*, llvm::MachineBasicBlock*) const llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, false> >::verifySiblingProperty(llvm::DominatorTreeBase<llvm::BasicBlock, false> const&)::'lambda'(llvm::BasicBlock*, llvm::BasicBlock*)::operator()(llvm::BasicBlock*, llvm::BasicBlock*) const Line | Count | Source | 1550 | 17.0k | doFullDFSWalk(DT, [BBN](NodePtr From, NodePtr To) { | 1551 | 17.0k | return From != BBN && To != BBN; | 1552 | 17.0k | }); |
llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, true> >::verifySiblingProperty(llvm::DominatorTreeBase<llvm::BasicBlock, true> const&)::'lambda'(llvm::BasicBlock*, llvm::BasicBlock*)::operator()(llvm::BasicBlock*, llvm::BasicBlock*) const Line | Count | Source | 1550 | 17.0k | doFullDFSWalk(DT, [BBN](NodePtr From, NodePtr To) { | 1551 | 17.0k | return From != BBN && To != BBN; | 1552 | 17.0k | }); |
|
1553 | 4.52k | |
1554 | 7.22k | for (const TreeNodePtr S : Siblings) { |
1555 | 7.22k | if (S == N) continue4.52k ; |
1556 | 2.70k | |
1557 | 2.70k | if (NodeToInfo.count(S->getBlock()) == 0) { |
1558 | 0 | errs() << "Node " << BlockNamePrinter(S) |
1559 | 0 | << " not reachable when its sibling " << BlockNamePrinter(N) |
1560 | 0 | << " is removed!\n"; |
1561 | 0 | errs().flush(); |
1562 | 0 |
|
1563 | 0 | return false; |
1564 | 0 | } |
1565 | 2.70k | } |
1566 | 4.52k | } |
1567 | 3.44k | } |
1568 | 715 | |
1569 | 715 | return true; |
1570 | 715 | } Unexecuted instantiation: llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> >::verifySiblingProperty(llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> const&) Unexecuted instantiation: llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> >::verifySiblingProperty(llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> const&) llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, false> >::verifySiblingProperty(llvm::DominatorTreeBase<llvm::BasicBlock, false> const&) Line | Count | Source | 1540 | 367 | bool verifySiblingProperty(const DomTreeT &DT) { | 1541 | 2.83k | for (auto &NodeToTN : DT.DomTreeNodes) { | 1542 | 2.83k | const TreeNodePtr TN = NodeToTN.second.get(); | 1543 | 2.83k | const NodePtr BB = TN->getBlock(); | 1544 | 2.83k | if (!BB || TN->getChildren().empty()) continue1.09k ; | 1545 | 1.73k | | 1546 | 1.73k | const auto &Siblings = TN->getChildren(); | 1547 | 2.46k | for (const TreeNodePtr N : Siblings) { | 1548 | 2.46k | clear(); | 1549 | 2.46k | NodePtr BBN = N->getBlock(); | 1550 | 2.46k | doFullDFSWalk(DT, [BBN](NodePtr From, NodePtr To) { | 1551 | 2.46k | return From != BBN && To != BBN; | 1552 | 2.46k | }); | 1553 | 2.46k | | 1554 | 4.40k | for (const TreeNodePtr S : Siblings) { | 1555 | 4.40k | if (S == N) continue2.46k ; | 1556 | 1.93k | | 1557 | 1.93k | if (NodeToInfo.count(S->getBlock()) == 0) { | 1558 | 0 | errs() << "Node " << BlockNamePrinter(S) | 1559 | 0 | << " not reachable when its sibling " << BlockNamePrinter(N) | 1560 | 0 | << " is removed!\n"; | 1561 | 0 | errs().flush(); | 1562 | 0 |
| 1563 | 0 | return false; | 1564 | 0 | } | 1565 | 1.93k | } | 1566 | 2.46k | } | 1567 | 1.73k | } | 1568 | 367 | | 1569 | 367 | return true; | 1570 | 367 | } |
llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, true> >::verifySiblingProperty(llvm::DominatorTreeBase<llvm::BasicBlock, true> const&) Line | Count | Source | 1540 | 348 | bool verifySiblingProperty(const DomTreeT &DT) { | 1541 | 3.85k | for (auto &NodeToTN : DT.DomTreeNodes) { | 1542 | 3.85k | const TreeNodePtr TN = NodeToTN.second.get(); | 1543 | 3.85k | const NodePtr BB = TN->getBlock(); | 1544 | 3.85k | if (!BB || TN->getChildren().empty()3.50k ) continue2.14k ; | 1545 | 1.70k | | 1546 | 1.70k | const auto &Siblings = TN->getChildren(); | 1547 | 2.05k | for (const TreeNodePtr N : Siblings) { | 1548 | 2.05k | clear(); | 1549 | 2.05k | NodePtr BBN = N->getBlock(); | 1550 | 2.05k | doFullDFSWalk(DT, [BBN](NodePtr From, NodePtr To) { | 1551 | 2.05k | return From != BBN && To != BBN; | 1552 | 2.05k | }); | 1553 | 2.05k | | 1554 | 2.82k | for (const TreeNodePtr S : Siblings) { | 1555 | 2.82k | if (S == N) continue2.05k ; | 1556 | 774 | | 1557 | 774 | if (NodeToInfo.count(S->getBlock()) == 0) { | 1558 | 0 | errs() << "Node " << BlockNamePrinter(S) | 1559 | 0 | << " not reachable when its sibling " << BlockNamePrinter(N) | 1560 | 0 | << " is removed!\n"; | 1561 | 0 | errs().flush(); | 1562 | 0 |
| 1563 | 0 | return false; | 1564 | 0 | } | 1565 | 774 | } | 1566 | 2.05k | } | 1567 | 1.70k | } | 1568 | 348 | | 1569 | 348 | return true; | 1570 | 348 | } |
|
1571 | | |
1572 | | // Check if the given tree is the same as a freshly computed one for the same |
1573 | | // Parent. |
1574 | | // Running time: O(N^2), but faster in practise (same as tree construction). |
1575 | | // |
1576 | | // Note that this does not check if that the tree construction algorithm is |
1577 | | // correct and should be only used for fast (but possibly unsound) |
1578 | | // verification. |
1579 | 717 | static bool IsSameAsFreshTree(const DomTreeT &DT) { |
1580 | 717 | DomTreeT FreshTree; |
1581 | 717 | FreshTree.recalculate(*DT.Parent); |
1582 | 717 | const bool Different = DT.compare(FreshTree); |
1583 | 717 | |
1584 | 717 | if (Different) { |
1585 | 2 | errs() << (DT.isPostDominator() ? "Post"1 : ""1 ) |
1586 | 2 | << "DominatorTree is different than a freshly computed one!\n" |
1587 | 2 | << "\tCurrent:\n"; |
1588 | 2 | DT.print(errs()); |
1589 | 2 | errs() << "\n\tFreshly computed tree:\n"; |
1590 | 2 | FreshTree.print(errs()); |
1591 | 2 | errs().flush(); |
1592 | 2 | } |
1593 | 717 | |
1594 | 717 | return !Different; |
1595 | 717 | } Unexecuted instantiation: llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> >::IsSameAsFreshTree(llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> const&) Unexecuted instantiation: llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> >::IsSameAsFreshTree(llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> const&) llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, false> >::IsSameAsFreshTree(llvm::DominatorTreeBase<llvm::BasicBlock, false> const&) Line | Count | Source | 1579 | 368 | static bool IsSameAsFreshTree(const DomTreeT &DT) { | 1580 | 368 | DomTreeT FreshTree; | 1581 | 368 | FreshTree.recalculate(*DT.Parent); | 1582 | 368 | const bool Different = DT.compare(FreshTree); | 1583 | 368 | | 1584 | 368 | if (Different) { | 1585 | 1 | errs() << (DT.isPostDominator() ? "Post"0 : "") | 1586 | 1 | << "DominatorTree is different than a freshly computed one!\n" | 1587 | 1 | << "\tCurrent:\n"; | 1588 | 1 | DT.print(errs()); | 1589 | 1 | errs() << "\n\tFreshly computed tree:\n"; | 1590 | 1 | FreshTree.print(errs()); | 1591 | 1 | errs().flush(); | 1592 | 1 | } | 1593 | 368 | | 1594 | 368 | return !Different; | 1595 | 368 | } |
llvm::DomTreeBuilder::SemiNCAInfo<llvm::DominatorTreeBase<llvm::BasicBlock, true> >::IsSameAsFreshTree(llvm::DominatorTreeBase<llvm::BasicBlock, true> const&) Line | Count | Source | 1579 | 349 | static bool IsSameAsFreshTree(const DomTreeT &DT) { | 1580 | 349 | DomTreeT FreshTree; | 1581 | 349 | FreshTree.recalculate(*DT.Parent); | 1582 | 349 | const bool Different = DT.compare(FreshTree); | 1583 | 349 | | 1584 | 349 | if (Different) { | 1585 | 1 | errs() << (DT.isPostDominator() ? "Post" : ""0 ) | 1586 | 1 | << "DominatorTree is different than a freshly computed one!\n" | 1587 | 1 | << "\tCurrent:\n"; | 1588 | 1 | DT.print(errs()); | 1589 | 1 | errs() << "\n\tFreshly computed tree:\n"; | 1590 | 1 | FreshTree.print(errs()); | 1591 | 1 | errs().flush(); | 1592 | 1 | } | 1593 | 349 | | 1594 | 349 | return !Different; | 1595 | 349 | } |
|
1596 | | }; |
1597 | | |
1598 | | template <class DomTreeT> |
1599 | 14.9M | void Calculate(DomTreeT &DT) { |
1600 | 14.9M | SemiNCAInfo<DomTreeT>::CalculateFromScratch(DT, nullptr); |
1601 | 14.9M | } void llvm::DomTreeBuilder::Calculate<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> >(llvm::DominatorTreeBase<llvm::MachineBasicBlock, false>&) Line | Count | Source | 1599 | 2.61M | void Calculate(DomTreeT &DT) { | 1600 | 2.61M | SemiNCAInfo<DomTreeT>::CalculateFromScratch(DT, nullptr); | 1601 | 2.61M | } |
void llvm::DomTreeBuilder::Calculate<llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> >(llvm::DominatorTreeBase<llvm::MachineBasicBlock, true>&) Line | Count | Source | 1599 | 1.50M | void Calculate(DomTreeT &DT) { | 1600 | 1.50M | SemiNCAInfo<DomTreeT>::CalculateFromScratch(DT, nullptr); | 1601 | 1.50M | } |
void llvm::DomTreeBuilder::Calculate<llvm::DominatorTreeBase<llvm::BasicBlock, false> >(llvm::DominatorTreeBase<llvm::BasicBlock, false>&) Line | Count | Source | 1599 | 10.2M | void Calculate(DomTreeT &DT) { | 1600 | 10.2M | SemiNCAInfo<DomTreeT>::CalculateFromScratch(DT, nullptr); | 1601 | 10.2M | } |
void llvm::DomTreeBuilder::Calculate<llvm::DominatorTreeBase<llvm::BasicBlock, true> >(llvm::DominatorTreeBase<llvm::BasicBlock, true>&) Line | Count | Source | 1599 | 605k | void Calculate(DomTreeT &DT) { | 1600 | 605k | SemiNCAInfo<DomTreeT>::CalculateFromScratch(DT, nullptr); | 1601 | 605k | } |
void llvm::DomTreeBuilder::Calculate<llvm::DominatorTreeBase<llvm::VPBlockBase, false> >(llvm::DominatorTreeBase<llvm::VPBlockBase, false>&) Line | Count | Source | 1599 | 28 | void Calculate(DomTreeT &DT) { | 1600 | 28 | SemiNCAInfo<DomTreeT>::CalculateFromScratch(DT, nullptr); | 1601 | 28 | } |
void llvm::DomTreeBuilder::Calculate<llvm::DominatorTreeBase<clang::CFGBlock, false> >(llvm::DominatorTreeBase<clang::CFGBlock, false>&) Line | Count | Source | 1599 | 8 | void Calculate(DomTreeT &DT) { | 1600 | 8 | SemiNCAInfo<DomTreeT>::CalculateFromScratch(DT, nullptr); | 1601 | 8 | } |
void llvm::DomTreeBuilder::Calculate<llvm::DominatorTreeBase<clang::CFGBlock, true> >(llvm::DominatorTreeBase<clang::CFGBlock, true>&) Line | Count | Source | 1599 | 107 | void Calculate(DomTreeT &DT) { | 1600 | 107 | SemiNCAInfo<DomTreeT>::CalculateFromScratch(DT, nullptr); | 1601 | 107 | } |
|
1602 | | |
1603 | | template <typename DomTreeT> |
1604 | | void CalculateWithUpdates(DomTreeT &DT, |
1605 | 52 | ArrayRef<typename DomTreeT::UpdateType> Updates) { |
1606 | 52 | // TODO: Move BUI creation in common method, reuse in ApplyUpdates. |
1607 | 52 | typename SemiNCAInfo<DomTreeT>::BatchUpdateInfo BUI; |
1608 | 52 | LLVM_DEBUG(dbgs() << "Legalizing " << BUI.Updates.size() << " updates\n"); |
1609 | 52 | cfg::LegalizeUpdates<typename DomTreeT::NodePtr>(Updates, BUI.Updates, |
1610 | 52 | DomTreeT::IsPostDominator); |
1611 | 52 | const size_t NumLegalized = BUI.Updates.size(); |
1612 | 52 | BUI.FutureSuccessors.reserve(NumLegalized); |
1613 | 52 | BUI.FuturePredecessors.reserve(NumLegalized); |
1614 | 70 | for (auto &U : BUI.Updates) { |
1615 | 70 | BUI.FutureSuccessors[U.getFrom()].push_back({U.getTo(), U.getKind()}); |
1616 | 70 | BUI.FuturePredecessors[U.getTo()].push_back({U.getFrom(), U.getKind()}); |
1617 | 70 | } |
1618 | 52 | |
1619 | 52 | SemiNCAInfo<DomTreeT>::CalculateFromScratch(DT, &BUI); |
1620 | 52 | } Unexecuted instantiation: void llvm::DomTreeBuilder::CalculateWithUpdates<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> >(llvm::DominatorTreeBase<llvm::MachineBasicBlock, false>&, llvm::ArrayRef<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false>::UpdateType>) Unexecuted instantiation: void llvm::DomTreeBuilder::CalculateWithUpdates<llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> >(llvm::DominatorTreeBase<llvm::MachineBasicBlock, true>&, llvm::ArrayRef<llvm::DominatorTreeBase<llvm::MachineBasicBlock, true>::UpdateType>) void llvm::DomTreeBuilder::CalculateWithUpdates<llvm::DominatorTreeBase<llvm::BasicBlock, false> >(llvm::DominatorTreeBase<llvm::BasicBlock, false>&, llvm::ArrayRef<llvm::DominatorTreeBase<llvm::BasicBlock, false>::UpdateType>) Line | Count | Source | 1605 | 52 | ArrayRef<typename DomTreeT::UpdateType> Updates) { | 1606 | 52 | // TODO: Move BUI creation in common method, reuse in ApplyUpdates. | 1607 | 52 | typename SemiNCAInfo<DomTreeT>::BatchUpdateInfo BUI; | 1608 | 52 | LLVM_DEBUG(dbgs() << "Legalizing " << BUI.Updates.size() << " updates\n"); | 1609 | 52 | cfg::LegalizeUpdates<typename DomTreeT::NodePtr>(Updates, BUI.Updates, | 1610 | 52 | DomTreeT::IsPostDominator); | 1611 | 52 | const size_t NumLegalized = BUI.Updates.size(); | 1612 | 52 | BUI.FutureSuccessors.reserve(NumLegalized); | 1613 | 52 | BUI.FuturePredecessors.reserve(NumLegalized); | 1614 | 70 | for (auto &U : BUI.Updates) { | 1615 | 70 | BUI.FutureSuccessors[U.getFrom()].push_back({U.getTo(), U.getKind()}); | 1616 | 70 | BUI.FuturePredecessors[U.getTo()].push_back({U.getFrom(), U.getKind()}); | 1617 | 70 | } | 1618 | 52 | | 1619 | 52 | SemiNCAInfo<DomTreeT>::CalculateFromScratch(DT, &BUI); | 1620 | 52 | } |
Unexecuted instantiation: void llvm::DomTreeBuilder::CalculateWithUpdates<llvm::DominatorTreeBase<llvm::BasicBlock, true> >(llvm::DominatorTreeBase<llvm::BasicBlock, true>&, llvm::ArrayRef<llvm::DominatorTreeBase<llvm::BasicBlock, true>::UpdateType>) |
1621 | | |
1622 | | template <class DomTreeT> |
1623 | | void InsertEdge(DomTreeT &DT, typename DomTreeT::NodePtr From, |
1624 | 4.53k | typename DomTreeT::NodePtr To) { |
1625 | 4.53k | if (DT.isPostDominator()) std::swap(From, To)142 ; |
1626 | 4.53k | SemiNCAInfo<DomTreeT>::InsertEdge(DT, nullptr, From, To); |
1627 | 4.53k | } Unexecuted instantiation: void llvm::DomTreeBuilder::InsertEdge<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> >(llvm::DominatorTreeBase<llvm::MachineBasicBlock, false>&, llvm::DominatorTreeBase<llvm::MachineBasicBlock, false>::NodePtr, llvm::DominatorTreeBase<llvm::MachineBasicBlock, false>::NodePtr) Unexecuted instantiation: void llvm::DomTreeBuilder::InsertEdge<llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> >(llvm::DominatorTreeBase<llvm::MachineBasicBlock, true>&, llvm::DominatorTreeBase<llvm::MachineBasicBlock, true>::NodePtr, llvm::DominatorTreeBase<llvm::MachineBasicBlock, true>::NodePtr) void llvm::DomTreeBuilder::InsertEdge<llvm::DominatorTreeBase<llvm::BasicBlock, false> >(llvm::DominatorTreeBase<llvm::BasicBlock, false>&, llvm::DominatorTreeBase<llvm::BasicBlock, false>::NodePtr, llvm::DominatorTreeBase<llvm::BasicBlock, false>::NodePtr) Line | Count | Source | 1624 | 4.39k | typename DomTreeT::NodePtr To) { | 1625 | 4.39k | if (DT.isPostDominator()) std::swap(From, To)0 ; | 1626 | 4.39k | SemiNCAInfo<DomTreeT>::InsertEdge(DT, nullptr, From, To); | 1627 | 4.39k | } |
void llvm::DomTreeBuilder::InsertEdge<llvm::DominatorTreeBase<llvm::BasicBlock, true> >(llvm::DominatorTreeBase<llvm::BasicBlock, true>&, llvm::DominatorTreeBase<llvm::BasicBlock, true>::NodePtr, llvm::DominatorTreeBase<llvm::BasicBlock, true>::NodePtr) Line | Count | Source | 1624 | 142 | typename DomTreeT::NodePtr To) { | 1625 | 142 | if (DT.isPostDominator()) std::swap(From, To); | 1626 | 142 | SemiNCAInfo<DomTreeT>::InsertEdge(DT, nullptr, From, To); | 1627 | 142 | } |
|
1628 | | |
1629 | | template <class DomTreeT> |
1630 | | void DeleteEdge(DomTreeT &DT, typename DomTreeT::NodePtr From, |
1631 | 12.9k | typename DomTreeT::NodePtr To) { |
1632 | 12.9k | if (DT.isPostDominator()) std::swap(From, To)182 ; |
1633 | 12.9k | SemiNCAInfo<DomTreeT>::DeleteEdge(DT, nullptr, From, To); |
1634 | 12.9k | } Unexecuted instantiation: void llvm::DomTreeBuilder::DeleteEdge<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> >(llvm::DominatorTreeBase<llvm::MachineBasicBlock, false>&, llvm::DominatorTreeBase<llvm::MachineBasicBlock, false>::NodePtr, llvm::DominatorTreeBase<llvm::MachineBasicBlock, false>::NodePtr) Unexecuted instantiation: void llvm::DomTreeBuilder::DeleteEdge<llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> >(llvm::DominatorTreeBase<llvm::MachineBasicBlock, true>&, llvm::DominatorTreeBase<llvm::MachineBasicBlock, true>::NodePtr, llvm::DominatorTreeBase<llvm::MachineBasicBlock, true>::NodePtr) void llvm::DomTreeBuilder::DeleteEdge<llvm::DominatorTreeBase<llvm::BasicBlock, false> >(llvm::DominatorTreeBase<llvm::BasicBlock, false>&, llvm::DominatorTreeBase<llvm::BasicBlock, false>::NodePtr, llvm::DominatorTreeBase<llvm::BasicBlock, false>::NodePtr) Line | Count | Source | 1631 | 12.7k | typename DomTreeT::NodePtr To) { | 1632 | 12.7k | if (DT.isPostDominator()) std::swap(From, To)0 ; | 1633 | 12.7k | SemiNCAInfo<DomTreeT>::DeleteEdge(DT, nullptr, From, To); | 1634 | 12.7k | } |
void llvm::DomTreeBuilder::DeleteEdge<llvm::DominatorTreeBase<llvm::BasicBlock, true> >(llvm::DominatorTreeBase<llvm::BasicBlock, true>&, llvm::DominatorTreeBase<llvm::BasicBlock, true>::NodePtr, llvm::DominatorTreeBase<llvm::BasicBlock, true>::NodePtr) Line | Count | Source | 1631 | 182 | typename DomTreeT::NodePtr To) { | 1632 | 182 | if (DT.isPostDominator()) std::swap(From, To); | 1633 | 182 | SemiNCAInfo<DomTreeT>::DeleteEdge(DT, nullptr, From, To); | 1634 | 182 | } |
|
1635 | | |
1636 | | template <class DomTreeT> |
1637 | | void ApplyUpdates(DomTreeT &DT, |
1638 | 521k | ArrayRef<typename DomTreeT::UpdateType> Updates) { |
1639 | 521k | SemiNCAInfo<DomTreeT>::ApplyUpdates(DT, Updates); |
1640 | 521k | } Unexecuted instantiation: void llvm::DomTreeBuilder::ApplyUpdates<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> >(llvm::DominatorTreeBase<llvm::MachineBasicBlock, false>&, llvm::ArrayRef<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false>::UpdateType>) Unexecuted instantiation: void llvm::DomTreeBuilder::ApplyUpdates<llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> >(llvm::DominatorTreeBase<llvm::MachineBasicBlock, true>&, llvm::ArrayRef<llvm::DominatorTreeBase<llvm::MachineBasicBlock, true>::UpdateType>) void llvm::DomTreeBuilder::ApplyUpdates<llvm::DominatorTreeBase<llvm::BasicBlock, false> >(llvm::DominatorTreeBase<llvm::BasicBlock, false>&, llvm::ArrayRef<llvm::DominatorTreeBase<llvm::BasicBlock, false>::UpdateType>) Line | Count | Source | 1638 | 521k | ArrayRef<typename DomTreeT::UpdateType> Updates) { | 1639 | 521k | SemiNCAInfo<DomTreeT>::ApplyUpdates(DT, Updates); | 1640 | 521k | } |
void llvm::DomTreeBuilder::ApplyUpdates<llvm::DominatorTreeBase<llvm::BasicBlock, true> >(llvm::DominatorTreeBase<llvm::BasicBlock, true>&, llvm::ArrayRef<llvm::DominatorTreeBase<llvm::BasicBlock, true>::UpdateType>) Line | Count | Source | 1638 | 326 | ArrayRef<typename DomTreeT::UpdateType> Updates) { | 1639 | 326 | SemiNCAInfo<DomTreeT>::ApplyUpdates(DT, Updates); | 1640 | 326 | } |
|
1641 | | |
1642 | | template <class DomTreeT> |
1643 | 717 | bool Verify(const DomTreeT &DT, typename DomTreeT::VerificationLevel VL) { |
1644 | 717 | SemiNCAInfo<DomTreeT> SNCA(nullptr); |
1645 | 717 | |
1646 | 717 | // Simplist check is to compare against a new tree. This will also |
1647 | 717 | // usefully print the old and new trees, if they are different. |
1648 | 717 | if (!SNCA.IsSameAsFreshTree(DT)) |
1649 | 2 | return false; |
1650 | 715 | |
1651 | 715 | // Common checks to verify the properties of the tree. O(N log N) at worst |
1652 | 715 | if (!SNCA.verifyRoots(DT) || !SNCA.verifyReachability(DT) || |
1653 | 715 | !SNCA.VerifyLevels(DT) || !SNCA.VerifyDFSNumbers(DT)) |
1654 | 0 | return false; |
1655 | 715 | |
1656 | 715 | // Extra checks depending on VerificationLevel. Up to O(N^3) |
1657 | 715 | if (VL == DomTreeT::VerificationLevel::Basic || |
1658 | 715 | VL == DomTreeT::VerificationLevel::Full) |
1659 | 715 | if (!SNCA.verifyParentProperty(DT)) |
1660 | 0 | return false; |
1661 | 715 | if (VL == DomTreeT::VerificationLevel::Full) |
1662 | 715 | if (!SNCA.verifySiblingProperty(DT)) |
1663 | 0 | return false; |
1664 | 715 | |
1665 | 715 | return true; |
1666 | 715 | } Unexecuted instantiation: bool llvm::DomTreeBuilder::Verify<llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> >(llvm::DominatorTreeBase<llvm::MachineBasicBlock, false> const&, llvm::DominatorTreeBase<llvm::MachineBasicBlock, false>::VerificationLevel) Unexecuted instantiation: bool llvm::DomTreeBuilder::Verify<llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> >(llvm::DominatorTreeBase<llvm::MachineBasicBlock, true> const&, llvm::DominatorTreeBase<llvm::MachineBasicBlock, true>::VerificationLevel) bool llvm::DomTreeBuilder::Verify<llvm::DominatorTreeBase<llvm::BasicBlock, false> >(llvm::DominatorTreeBase<llvm::BasicBlock, false> const&, llvm::DominatorTreeBase<llvm::BasicBlock, false>::VerificationLevel) Line | Count | Source | 1643 | 368 | bool Verify(const DomTreeT &DT, typename DomTreeT::VerificationLevel VL) { | 1644 | 368 | SemiNCAInfo<DomTreeT> SNCA(nullptr); | 1645 | 368 | | 1646 | 368 | // Simplist check is to compare against a new tree. This will also | 1647 | 368 | // usefully print the old and new trees, if they are different. | 1648 | 368 | if (!SNCA.IsSameAsFreshTree(DT)) | 1649 | 1 | return false; | 1650 | 367 | | 1651 | 367 | // Common checks to verify the properties of the tree. O(N log N) at worst | 1652 | 367 | if (!SNCA.verifyRoots(DT) || !SNCA.verifyReachability(DT) || | 1653 | 367 | !SNCA.VerifyLevels(DT) || !SNCA.VerifyDFSNumbers(DT)) | 1654 | 0 | return false; | 1655 | 367 | | 1656 | 367 | // Extra checks depending on VerificationLevel. Up to O(N^3) | 1657 | 367 | if (VL == DomTreeT::VerificationLevel::Basic || | 1658 | 367 | VL == DomTreeT::VerificationLevel::Full) | 1659 | 367 | if (!SNCA.verifyParentProperty(DT)) | 1660 | 0 | return false; | 1661 | 367 | if (VL == DomTreeT::VerificationLevel::Full) | 1662 | 367 | if (!SNCA.verifySiblingProperty(DT)) | 1663 | 0 | return false; | 1664 | 367 | | 1665 | 367 | return true; | 1666 | 367 | } |
bool llvm::DomTreeBuilder::Verify<llvm::DominatorTreeBase<llvm::BasicBlock, true> >(llvm::DominatorTreeBase<llvm::BasicBlock, true> const&, llvm::DominatorTreeBase<llvm::BasicBlock, true>::VerificationLevel) Line | Count | Source | 1643 | 349 | bool Verify(const DomTreeT &DT, typename DomTreeT::VerificationLevel VL) { | 1644 | 349 | SemiNCAInfo<DomTreeT> SNCA(nullptr); | 1645 | 349 | | 1646 | 349 | // Simplist check is to compare against a new tree. This will also | 1647 | 349 | // usefully print the old and new trees, if they are different. | 1648 | 349 | if (!SNCA.IsSameAsFreshTree(DT)) | 1649 | 1 | return false; | 1650 | 348 | | 1651 | 348 | // Common checks to verify the properties of the tree. O(N log N) at worst | 1652 | 348 | if (!SNCA.verifyRoots(DT) || !SNCA.verifyReachability(DT) || | 1653 | 348 | !SNCA.VerifyLevels(DT) || !SNCA.VerifyDFSNumbers(DT)) | 1654 | 0 | return false; | 1655 | 348 | | 1656 | 348 | // Extra checks depending on VerificationLevel. Up to O(N^3) | 1657 | 348 | if (VL == DomTreeT::VerificationLevel::Basic || | 1658 | 348 | VL == DomTreeT::VerificationLevel::Full) | 1659 | 348 | if (!SNCA.verifyParentProperty(DT)) | 1660 | 0 | return false; | 1661 | 348 | if (VL == DomTreeT::VerificationLevel::Full) | 1662 | 348 | if (!SNCA.verifySiblingProperty(DT)) | 1663 | 0 | return false; | 1664 | 348 | | 1665 | 348 | return true; | 1666 | 348 | } |
|
1667 | | |
1668 | | } // namespace DomTreeBuilder |
1669 | | } // namespace llvm |
1670 | | |
1671 | | #undef DEBUG_TYPE |
1672 | | |
1673 | | #endif |