From: Jakub Kuderski Date: Wed, 26 Jul 2017 18:07:40 +0000 (+0000) Subject: [Dominators] Move root-finding out of DomTreeBase and simplify it X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=c271dea0a7924b6c284ec0bf944fc1f020e5866f;p=platform%2Fupstream%2Fllvm.git [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 llvm-svn: 309146 --- diff --git a/llvm/include/llvm/IR/Dominators.h b/llvm/include/llvm/IR/Dominators.h index 5b21a2c..66e8934 100644 --- a/llvm/include/llvm/IR/Dominators.h +++ b/llvm/include/llvm/IR/Dominators.h @@ -41,9 +41,8 @@ namespace DomTreeBuilder { using BBDomTree = DomTreeBase; using BBPostDomTree = PostDomTreeBase; -extern template void Calculate(BBDomTree &DT, Function &F); -extern template void Calculate(BBPostDomTree &DT, - Function &F); +extern template void Calculate(BBDomTree &DT); +extern template void Calculate(BBPostDomTree &DT); extern template void InsertEdge(BBDomTree &DT, BasicBlock *From, BasicBlock *To); diff --git a/llvm/include/llvm/Support/GenericDomTree.h b/llvm/include/llvm/Support/GenericDomTree.h index 706320f..b94310f 100644 --- a/llvm/include/llvm/Support/GenericDomTree.h +++ b/llvm/include/llvm/Support/GenericDomTree.h @@ -14,8 +14,8 @@ /// graph types. /// /// Unlike ADT/* graph algorithms, generic dominator tree has more requirements -/// on the graph's NodeRef. The NodeRef should be a pointer and, depending on -/// the implementation, e.g. NodeRef->getParent() return the parent node. +/// on the graph's NodeRef. The NodeRef should be a pointer and, +/// NodeRef->getParent() must return the parent node that is also a pointer. /// /// FIXME: Maybe GenericDomTree needs a TreeTraits, instead of GraphTraits. /// @@ -187,8 +187,8 @@ void PrintDomTree(const DomTreeNodeBase *N, raw_ostream &O, namespace DomTreeBuilder { // The routines below are provided in a separate header but referenced here. -template -void Calculate(DomTreeT &DT, FuncT &F); +template +void Calculate(DomTreeT &DT); template void InsertEdge(DomTreeT &DT, typename DomTreeT::NodePtr From, @@ -208,6 +208,17 @@ bool Verify(const DomTreeT &DT); /// various graphs in the LLVM IR or in the code generator. template class DominatorTreeBase { + public: + static_assert(std::is_pointer::NodeRef>::value, + "Currently DominatorTreeBase supports only pointer nodes"); + using NodeType = NodeT; + using NodePtr = NodeT *; + using ParentPtr = decltype(std::declval()->getParent()); + static_assert(std::is_pointer::value, + "Currently NodeT's parent must be a pointer type"); + using ParentType = typename std::remove_pointer::type; + static constexpr bool IsPostDominator = IsPostDom; + protected: std::vector Roots; @@ -215,7 +226,6 @@ class DominatorTreeBase { DenseMap>>; DomTreeNodeMapType DomTreeNodes; DomTreeNodeBase *RootNode; - using ParentPtr = decltype(std::declval()->getParent()); ParentPtr Parent = nullptr; mutable bool DFSInfoValid = false; @@ -224,12 +234,6 @@ class DominatorTreeBase { friend struct DomTreeBuilder::SemiNCAInfo; public: - static_assert(std::is_pointer::NodeRef>::value, - "Currently DominatorTreeBase supports only pointer nodes"); - using NodeType = NodeT; - using NodePtr = NodeT *; - static constexpr bool IsPostDominator = IsPostDom; - DominatorTreeBase() {} DominatorTreeBase(DominatorTreeBase &&Arg) @@ -650,23 +654,10 @@ public: } /// recalculate - compute a dominator tree for the given function - template void recalculate(FT &F) { - using TraitsTy = GraphTraits; + void recalculate(ParentType &Func) { reset(); - Parent = &F; - - if (!IsPostDominator) { - // Initialize root - NodeT *entry = TraitsTy::getEntryNode(&F); - addRoot(entry); - } else { - // Initialize the roots list - for (auto *Node : nodes(&F)) - if (TraitsTy::child_begin(Node) == TraitsTy::child_end(Node)) - addRoot(Node); - } - - DomTreeBuilder::Calculate(*this, F); + Parent = &Func; + DomTreeBuilder::Calculate(*this); } /// verify - check parent and sibling property diff --git a/llvm/include/llvm/Support/GenericDomTreeConstruction.h b/llvm/include/llvm/Support/GenericDomTreeConstruction.h index be90afa..6fd182b 100644 --- a/llvm/include/llvm/Support/GenericDomTreeConstruction.h +++ b/llvm/include/llvm/Support/GenericDomTreeConstruction.h @@ -131,7 +131,7 @@ struct SemiNCAInfo { // Custom DFS implementation which can skip nodes based on a provided // predicate. It also collects ReverseChildren so that we don't have to spend // time getting predecessors in SemiNCA. - template + template unsigned runDFS(NodePtr V, unsigned LastNum, DescendCondition Condition, unsigned AttachToNum) { assert(V); @@ -148,7 +148,7 @@ struct SemiNCAInfo { BBInfo.Label = BB; NumToNode.push_back(BB); - for (const NodePtr Succ : ChildrenGetter::Get(BB)) { + for (const NodePtr Succ : ChildrenGetter::Get(BB)) { const auto SIT = NodeToInfo.find(Succ); // Don't visit nodes more than once but remember to collect // RerverseChildren. @@ -260,7 +260,8 @@ struct SemiNCAInfo { unsigned doFullDFSWalk(const DomTreeT &DT, DescendCondition DC) { unsigned Num = 0; - if (DT.Roots.size() > 1) { + // If the DT is a PostDomTree, always add a virtual root. + if (IsPostDom) { auto &BBInfo = NodeToInfo[nullptr]; BBInfo.DFSNum = BBInfo.Semi = ++Num; BBInfo.Label = nullptr; @@ -268,34 +269,42 @@ struct SemiNCAInfo { NumToNode.push_back(nullptr); // NumToNode[n] = V; } - if (DT.isPostDominator()) { - for (auto *Root : DT.Roots) Num = runDFS(Root, Num, DC, 1); - } else { - assert(DT.Roots.size() == 1); - Num = runDFS(DT.Roots[0], Num, DC, Num); - } + const unsigned InitialNum = Num; + for (auto *Root : DT.Roots) Num = runDFS(Root, Num, DC, InitialNum); return Num; } - void calculateFromScratch(DomTreeT &DT, const unsigned NumBlocks) { + static void FindAndAddRoots(DomTreeT &DT) { + assert(DT.Parent && "Parent pointer is not set"); + using TraitsTy = GraphTraits; + + if (!IsPostDom) { + // Dominators have a single root that is the function's entry. + NodeT *entry = TraitsTy::getEntryNode(DT.Parent); + DT.addRoot(entry); + } else { + // Initialize the roots list for PostDominators. + for (auto *Node : nodes(DT.Parent)) + if (TraitsTy::child_begin(Node) == TraitsTy::child_end(Node)) + DT.addRoot(Node); + } + } + + void calculateFromScratch(DomTreeT &DT) { // Step #0: Number blocks in depth-first order and initialize variables used // in later stages of the algorithm. - const unsigned LastDFSNum = doFullDFSWalk(DT, AlwaysDescend); + FindAndAddRoots(DT); + doFullDFSWalk(DT, AlwaysDescend); runSemiNCA(DT); if (DT.Roots.empty()) return; - // Add a node for the root. This node might be the actual root, if there is - // one exit block, or it may be the virtual exit (denoted by - // (BasicBlock *)0) which postdominates all real exits if there are multiple - // exit blocks, or an infinite loop. - // It might be that some blocks did not get a DFS number (e.g., blocks of - // infinite loops). In these cases an artificial exit node is required. - const bool MultipleRoots = DT.Roots.size() > 1 || (DT.isPostDominator() && - LastDFSNum != NumBlocks); - NodePtr Root = !MultipleRoots ? DT.Roots[0] : nullptr; + // Add a node for the root. If the tree is a PostDominatorTree it will be + // the virtual exit (denoted by (BasicBlock *) nullptr) which postdominates + // all real exits (including multiple exit blocks, infinite loops). + NodePtr Root = IsPostDom ? nullptr : DT.Roots[0]; DT.RootNode = (DT.DomTreeNodes[Root] = llvm::make_unique>(Root, nullptr)) @@ -523,7 +532,7 @@ struct SemiNCAInfo { }; SemiNCAInfo SNCA; - SNCA.runDFS(Root, 0, UnreachableDescender, 0); + SNCA.runDFS(Root, 0, UnreachableDescender, 0); SNCA.runSemiNCA(DT); SNCA.attachNewSubtree(DT, Incoming); @@ -638,7 +647,7 @@ struct SemiNCAInfo { DEBUG(dbgs() << "\tTop of subtree: " << BlockNamePrinter(ToIDomTN) << "\n"); SemiNCAInfo SNCA; - SNCA.runDFS(ToIDom, 0, DescendBelow, 0); + SNCA.runDFS(ToIDom, 0, DescendBelow, 0); DEBUG(dbgs() << "\tRunning Semi-NCA\n"); SNCA.runSemiNCA(DT, Level); SNCA.reattachExistingSubtree(DT, PrevIDomSubTree); @@ -692,7 +701,7 @@ struct SemiNCAInfo { SemiNCAInfo SNCA; unsigned LastDFSNum = - SNCA.runDFS(ToTN->getBlock(), 0, DescendAndCollect, 0); + SNCA.runDFS(ToTN->getBlock(), 0, DescendAndCollect, 0); TreeNodePtr MinNode = ToTN; @@ -744,7 +753,7 @@ struct SemiNCAInfo { const TreeNodePtr ToTN = DT.getNode(To); return ToTN && ToTN->getLevel() > MinLevel; }; - SNCA.runDFS(MinNode->getBlock(), 0, DescendBelow, 0); + SNCA.runDFS(MinNode->getBlock(), 0, DescendBelow, 0); DEBUG(dbgs() << "Previous IDom(MinNode) = " << BlockNamePrinter(PrevIDom) << "\nRunning Semi-NCA\n"); @@ -945,11 +954,10 @@ struct SemiNCAInfo { } }; - -template -void Calculate(DomTreeT &DT, FuncT &F) { +template +void Calculate(DomTreeT &DT) { SemiNCAInfo SNCA; - SNCA.calculateFromScratch(DT, GraphTraits::size(&F)); + SNCA.calculateFromScratch(DT); } template diff --git a/llvm/lib/IR/Dominators.cpp b/llvm/lib/IR/Dominators.cpp index 4d7e304..993ef1d 100644 --- a/llvm/lib/IR/Dominators.cpp +++ b/llvm/lib/IR/Dominators.cpp @@ -64,12 +64,10 @@ template class llvm::DomTreeNodeBase; template class llvm::DominatorTreeBase; // DomTreeBase template class llvm::DominatorTreeBase; // PostDomTreeBase -template void -llvm::DomTreeBuilder::Calculate( - DomTreeBuilder::BBDomTree &DT, Function &F); -template void -llvm::DomTreeBuilder::Calculate( - DomTreeBuilder::BBPostDomTree &DT, Function &F); +template void llvm::DomTreeBuilder::Calculate( + DomTreeBuilder::BBDomTree &DT); +template void llvm::DomTreeBuilder::Calculate( + DomTreeBuilder::BBPostDomTree &DT); template void llvm::DomTreeBuilder::InsertEdge( DomTreeBuilder::BBDomTree &DT, BasicBlock *From, BasicBlock *To);