llvm.org GIT mirror llvm / 2207215
[Dominators] Move root-finding out of DomTreeBase and simplify it Summary: This patch moves root-finding logic from DominatorTreeBase to GenericDomTreeConstruction.h. It makes the behavior simpler and more consistent by always adding a virtual root to PostDominatorTrees. Reviewers: dberlin, davide, grosser, sanjoy Reviewed By: dberlin Subscribers: llvm-commits Differential Revision: https://reviews.llvm.org/D35597 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@309146 91177308-0d34-0410-b5e6-96231b3b80d8 Jakub Kuderski 3 years ago
4 changed file(s) with 71 addition(s) and 75 deletion(s). Raw diff Collapse all Expand all
4040 using BBDomTree = DomTreeBase;
4141 using BBPostDomTree = PostDomTreeBase;
4242
43 extern template void Calculate(BBDomTree &DT, Function &F);
44 extern template void Calculate(BBPostDomTree &DT,
45 Function &F);
43 extern template void Calculate(BBDomTree &DT);
44 extern template void Calculate(BBPostDomTree &DT);
4645
4746 extern template void InsertEdge(BBDomTree &DT, BasicBlock *From,
4847 BasicBlock *To);
1313 /// graph types.
1414 ///
1515 /// Unlike ADT/* graph algorithms, generic dominator tree has more requirements
16 /// on the graph's NodeRef. The NodeRef should be a pointer and, depending on
17 /// the implementation, e.g. NodeRef->getParent() return the parent node.
16 /// on the graph's NodeRef. The NodeRef should be a pointer and,
17 /// NodeRef->getParent() must return the parent node that is also a pointer.
1818 ///
1919 /// FIXME: Maybe GenericDomTree needs a TreeTraits, instead of GraphTraits.
2020 ///
186186
187187 namespace DomTreeBuilder {
188188 // The routines below are provided in a separate header but referenced here.
189 template
190 void Calculate(DomTreeT &DT, FuncT &F);
189 template
190 void Calculate(DomTreeT &DT);
191191
192192 template
193193 void InsertEdge(DomTreeT &DT, typename DomTreeT::NodePtr From,
207207 /// various graphs in the LLVM IR or in the code generator.
208208 template
209209 class DominatorTreeBase {
210 protected:
211 std::vector Roots;
212
213 using DomTreeNodeMapType =
214 DenseMap>>;
215 DomTreeNodeMapType DomTreeNodes;
216 DomTreeNodeBase *RootNode;
217 using ParentPtr = decltype(std::declval()->getParent());
218 ParentPtr Parent = nullptr;
219
220 mutable bool DFSInfoValid = false;
221 mutable unsigned int SlowQueries = 0;
222
223 friend struct DomTreeBuilder::SemiNCAInfo;
224
225210 public:
226211 static_assert(std::is_pointer::NodeRef>::value,
227212 "Currently DominatorTreeBase supports only pointer nodes");
228213 using NodeType = NodeT;
229214 using NodePtr = NodeT *;
215 using ParentPtr = decltype(std::declval()->getParent());
216 static_assert(std::is_pointer::value,
217 "Currently NodeT's parent must be a pointer type");
218 using ParentType = typename std::remove_pointer::type;
230219 static constexpr bool IsPostDominator = IsPostDom;
231220
221 protected:
222 std::vector Roots;
223
224 using DomTreeNodeMapType =
225 DenseMap>>;
226 DomTreeNodeMapType DomTreeNodes;
227 DomTreeNodeBase *RootNode;
228 ParentPtr Parent = nullptr;
229
230 mutable bool DFSInfoValid = false;
231 mutable unsigned int SlowQueries = 0;
232
233 friend struct DomTreeBuilder::SemiNCAInfo;
234
235 public:
232236 DominatorTreeBase() {}
233237
234238 DominatorTreeBase(DominatorTreeBase &&Arg)
649653 }
650654
651655 /// recalculate - compute a dominator tree for the given function
652 template void recalculate(FT &F) {
653 using TraitsTy = GraphTraits;
656 void recalculate(ParentType &Func) {
654657 reset();
655 Parent = &F;
656
657 if (!IsPostDominator) {
658 // Initialize root
659 NodeT *entry = TraitsTy::getEntryNode(&F);
660 addRoot(entry);
661 } else {
662 // Initialize the roots list
663 for (auto *Node : nodes(&F))
664 if (TraitsTy::child_begin(Node) == TraitsTy::child_end(Node))
665 addRoot(Node);
666 }
667
668 DomTreeBuilder::Calculate(*this, F);
658 Parent = &Func;
659 DomTreeBuilder::Calculate(*this);
669660 }
670661
671662 /// verify - check parent and sibling property
130130 // Custom DFS implementation which can skip nodes based on a provided
131131 // predicate. It also collects ReverseChildren so that we don't have to spend
132132 // time getting predecessors in SemiNCA.
133 template <bool Inverse, typename DescendCondition>
133 template <typename DescendCondition>
134134 unsigned runDFS(NodePtr V, unsigned LastNum, DescendCondition Condition,
135135 unsigned AttachToNum) {
136136 assert(V);
147147 BBInfo.Label = BB;
148148 NumToNode.push_back(BB);
149149
150 for (const NodePtr Succ : ChildrenGetternverse>::Get(BB)) {
150 for (const NodePtr Succ : ChildrenGettersPostDom>::Get(BB)) {
151151 const auto SIT = NodeToInfo.find(Succ);
152152 // Don't visit nodes more than once but remember to collect
153153 // RerverseChildren.
259259 unsigned doFullDFSWalk(const DomTreeT &DT, DescendCondition DC) {
260260 unsigned Num = 0;
261261
262 if (DT.Roots.size() > 1) {
262 // If the DT is a PostDomTree, always add a virtual root.
263 if (IsPostDom) {
263264 auto &BBInfo = NodeToInfo[nullptr];
264265 BBInfo.DFSNum = BBInfo.Semi = ++Num;
265266 BBInfo.Label = nullptr;
267268 NumToNode.push_back(nullptr); // NumToNode[n] = V;
268269 }
269270
270 if (DT.isPostDominator()) {
271 for (auto *Root : DT.Roots) Num = runDFS(Root, Num, DC, 1);
271 const unsigned InitialNum = Num;
272 for (auto *Root : DT.Roots) Num = runDFS(Root, Num, DC, InitialNum);
273
274 return Num;
275 }
276
277 static void FindAndAddRoots(DomTreeT &DT) {
278 assert(DT.Parent && "Parent pointer is not set");
279 using TraitsTy = GraphTraits;
280
281 if (!IsPostDom) {
282 // Dominators have a single root that is the function's entry.
283 NodeT *entry = TraitsTy::getEntryNode(DT.Parent);
284 DT.addRoot(entry);
272285 } else {
273 assert(DT.Roots.size() == 1);
274 Num = runDFS(DT.Roots[0], Num, DC, Num);
275 }
276
277 return Num;
278 }
279
280 void calculateFromScratch(DomTreeT &DT, const unsigned NumBlocks) {
286 // Initialize the roots list for PostDominators.
287 for (auto *Node : nodes(DT.Parent))
288 if (TraitsTy::child_begin(Node) == TraitsTy::child_end(Node))
289 DT.addRoot(Node);
290 }
291 }
292
293 void calculateFromScratch(DomTreeT &DT) {
281294 // Step #0: Number blocks in depth-first order and initialize variables used
282295 // in later stages of the algorithm.
283 const unsigned LastDFSNum = doFullDFSWalk(DT, AlwaysDescend);
296 FindAndAddRoots(DT);
297 doFullDFSWalk(DT, AlwaysDescend);
284298
285299 runSemiNCA(DT);
286300
287301 if (DT.Roots.empty()) return;
288302
289 // Add a node for the root. This node might be the actual root, if there is
290 // one exit block, or it may be the virtual exit (denoted by
291 // (BasicBlock *)0) which postdominates all real exits if there are multiple
292 // exit blocks, or an infinite loop.
293 // It might be that some blocks did not get a DFS number (e.g., blocks of
294 // infinite loops). In these cases an artificial exit node is required.
295 const bool MultipleRoots = DT.Roots.size() > 1 || (DT.isPostDominator() &&
296 LastDFSNum != NumBlocks);
297 NodePtr Root = !MultipleRoots ? DT.Roots[0] : nullptr;
303 // Add a node for the root. If the tree is a PostDominatorTree it will be
304 // the virtual exit (denoted by (BasicBlock *) nullptr) which postdominates
305 // all real exits (including multiple exit blocks, infinite loops).
306 NodePtr Root = IsPostDom ? nullptr : DT.Roots[0];
298307
299308 DT.RootNode = (DT.DomTreeNodes[Root] =
300309 llvm::make_unique>(Root, nullptr))
522531 };
523532
524533 SemiNCAInfo SNCA;
525 SNCA.runDFS(Root, 0, UnreachableDescender, 0);
534 SNCA.runDFS(Root, 0, UnreachableDescender, 0);
526535 SNCA.runSemiNCA(DT);
527536 SNCA.attachNewSubtree(DT, Incoming);
528537
637646 DEBUG(dbgs() << "\tTop of subtree: " << BlockNamePrinter(ToIDomTN) << "\n");
638647
639648 SemiNCAInfo SNCA;
640 SNCA.runDFS(ToIDom, 0, DescendBelow, 0);
649 SNCA.runDFS(ToIDom, 0, DescendBelow, 0);
641650 DEBUG(dbgs() << "\tRunning Semi-NCA\n");
642651 SNCA.runSemiNCA(DT, Level);
643652 SNCA.reattachExistingSubtree(DT, PrevIDomSubTree);
691700
692701 SemiNCAInfo SNCA;
693702 unsigned LastDFSNum =
694 SNCA.runDFS(ToTN->getBlock(), 0, DescendAndCollect, 0);
703 SNCA.runDFS(ToTN->getBlock(), 0, DescendAndCollect, 0);
695704
696705 TreeNodePtr MinNode = ToTN;
697706
743752 const TreeNodePtr ToTN = DT.getNode(To);
744753 return ToTN && ToTN->getLevel() > MinLevel;
745754 };
746 SNCA.runDFS(MinNode->getBlock(), 0, DescendBelow, 0);
755 SNCA.runDFS(MinNode->getBlock(), 0, DescendBelow, 0);
747756
748757 DEBUG(dbgs() << "Previous IDom(MinNode) = " << BlockNamePrinter(PrevIDom)
749758 << "\nRunning Semi-NCA\n");
944953 }
945954 };
946955
947
948 template
949 void Calculate(DomTreeT &DT, FuncT &F) {
956 template
957 void Calculate(DomTreeT &DT) {
950958 SemiNCAInfo SNCA;
951 SNCA.calculateFromScratch(DT, GraphTraits::size(&F));
959 SNCA.calculateFromScratch(DT);
952960 }
953961
954962 template
6363 template class llvm::DominatorTreeBase; // DomTreeBase
6464 template class llvm::DominatorTreeBase; // PostDomTreeBase
6565
66 template void
67 llvm::DomTreeBuilder::Calculate(
68 DomTreeBuilder::BBDomTree &DT, Function &F);
69 template void
70 llvm::DomTreeBuilder::Calculate(
71 DomTreeBuilder::BBPostDomTree &DT, Function &F);
66 template void llvm::DomTreeBuilder::Calculate(
67 DomTreeBuilder::BBDomTree &DT);
68 template void llvm::DomTreeBuilder::Calculate(
69 DomTreeBuilder::BBPostDomTree &DT);
7270
7371 template void llvm::DomTreeBuilder::InsertEdge(
7472 DomTreeBuilder::BBDomTree &DT, BasicBlock *From, BasicBlock *To);