[llvm] r306579 - [Dominators] Move helper functions into SemiNCAInfo
Jakub Kuderski via llvm-commits
llvm-commits at lists.llvm.org
Wed Jun 28 11:15:45 PDT 2017
Author: kuhar
Date: Wed Jun 28 11:15:45 2017
New Revision: 306579
URL: http://llvm.org/viewvc/llvm-project?rev=306579&view=rev
Log:
[Dominators] Move helper functions into SemiNCAInfo
Summary: Helper functions (DFSPass, ReverseDFSPass, Eval) need SemiNCAInfo anyway, so it's simpler to have them there as member functions. This also makes them simpler by removing template boilerplate.
Reviewers: dberlin, sanjoy, chandlerc
Reviewed By: dberlin
Subscribers: llvm-commits
Differential Revision: https://reviews.llvm.org/D34427
Modified:
llvm/trunk/include/llvm/Support/GenericDomTree.h
llvm/trunk/include/llvm/Support/GenericDomTreeConstruction.h
Modified: llvm/trunk/include/llvm/Support/GenericDomTree.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Support/GenericDomTree.h?rev=306579&r1=306578&r2=306579&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Support/GenericDomTree.h (original)
+++ llvm/trunk/include/llvm/Support/GenericDomTree.h Wed Jun 28 11:15:45 2017
@@ -660,7 +660,7 @@ protected:
friend void Calculate(DominatorTreeBaseByGraphTraits<GraphTraits<NodeTy>> &DT,
FuncT &F);
- void addRoot(NodeT *BB) { this->Roots.push_back(BB); }
+ void addRoot(NodeT *BB) { this->Roots.push_back(BB); }
public:
/// updateDFSNumbers - Assign In and Out numbers to the nodes while walking
Modified: llvm/trunk/include/llvm/Support/GenericDomTreeConstruction.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Support/GenericDomTreeConstruction.h?rev=306579&r1=306578&r2=306579&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Support/GenericDomTreeConstruction.h (original)
+++ llvm/trunk/include/llvm/Support/GenericDomTreeConstruction.h Wed Jun 28 11:15:45 2017
@@ -76,229 +76,222 @@ struct SemiNCAInfo {
llvm::make_unique<DomTreeNodeBase<NodeT>>(BB, IDomNode)))
.get();
}
-};
-} // namespace DomTreeBuilder
-
-// External storage for depth first iterator that reuses the info lookup map
-// domtree already has. We don't have a set, but a map instead, so we are
-// converting the one argument insert calls.
-template <class NodeRef, class InfoType> struct df_iterator_dom_storage {
-public:
- using BaseSet = DenseMap<NodeRef, InfoType>;
- df_iterator_dom_storage(BaseSet &Storage) : Storage(Storage) {}
-
- using iterator = typename BaseSet::iterator;
- std::pair<iterator, bool> insert(NodeRef N) {
- return Storage.insert({N, InfoType()});
- }
- void completed(NodeRef) {}
-private:
- BaseSet &Storage;
-};
+ // External storage for depth first iterator that reuses the info lookup map
+ // SemiNCAInfo already has. We don't have a set, but a map instead, so we are
+ // converting the one argument insert calls.
+ struct df_iterator_dom_storage {
+ public:
+ using BaseSet = decltype(NodeToInfo);
+ df_iterator_dom_storage(BaseSet &Storage) : Storage(Storage) {}
+
+ using iterator = typename BaseSet::iterator;
+ std::pair<iterator, bool> insert(NodePtr N) {
+ return Storage.insert({N, InfoRec()});
+ }
+ void completed(NodePtr) {}
-template <class NodePtr,
- class NodeT = typename std::remove_pointer<NodePtr>::type>
-unsigned ReverseDFSPass(NodePtr V, DomTreeBuilder::SemiNCAInfo<NodeT> &SNCA,
- unsigned N) {
- using SNCAInfoTy = DomTreeBuilder::SemiNCAInfo<NodeT>;
- df_iterator_dom_storage<NodePtr, typename SNCAInfoTy::InfoRec> DFStorage(
- SNCA.NodeToInfo);
-
- bool IsChildOfArtificialExit = (N != 0);
- for (auto I = idf_ext_begin(V, DFStorage), E = idf_ext_end(V, DFStorage);
- I != E; ++I) {
- NodePtr BB = *I;
- auto &BBInfo = SNCA.NodeToInfo[BB];
- BBInfo.DFSNum = BBInfo.Semi = ++N;
- BBInfo.Label = BB;
- // Set the parent to the top of the visited stack. The stack includes us,
- // and is 1 based, so we subtract to account for both of these.
- if (I.getPathLength() > 1)
- BBInfo.Parent = SNCA.NodeToInfo[I.getPath(I.getPathLength() - 2)].DFSNum;
- SNCA.NumToNode.push_back(BB); // NumToNode[n] = V;
+ private:
+ BaseSet &Storage;
+ };
+
+ df_iterator_dom_storage getStorage() { return {NodeToInfo}; }
+
+ unsigned runReverseDFS(NodePtr V, unsigned N) {
+ auto DFStorage = getStorage();
+
+ bool IsChildOfArtificialExit = (N != 0);
+ for (auto I = idf_ext_begin(V, DFStorage), E = idf_ext_end(V, DFStorage);
+ I != E; ++I) {
+ NodePtr BB = *I;
+ auto &BBInfo = NodeToInfo[BB];
+ BBInfo.DFSNum = BBInfo.Semi = ++N;
+ BBInfo.Label = BB;
+ // Set the parent to the top of the visited stack. The stack includes us,
+ // and is 1 based, so we subtract to account for both of these.
+ if (I.getPathLength() > 1)
+ BBInfo.Parent = NodeToInfo[I.getPath(I.getPathLength() - 2)].DFSNum;
+ NumToNode.push_back(BB); // NumToNode[n] = V;
- if (IsChildOfArtificialExit)
- BBInfo.Parent = 1;
+ if (IsChildOfArtificialExit)
+ BBInfo.Parent = 1;
- IsChildOfArtificialExit = false;
+ IsChildOfArtificialExit = false;
+ }
+ return N;
}
- return N;
-}
-template <class NodePtr,
- class NodeT = typename std::remove_pointer<NodePtr>::type>
-unsigned DFSPass(NodePtr V, DomTreeBuilder::SemiNCAInfo<NodeT> &SNCA, unsigned N) {
- using SNCAInfoTy = DomTreeBuilder::SemiNCAInfo<NodeT>;
- df_iterator_dom_storage<NodePtr, typename SNCAInfoTy::InfoRec> DFStorage(
- SNCA.NodeToInfo);
-
- for (auto I = df_ext_begin(V, DFStorage), E = df_ext_end(V, DFStorage);
- I != E; ++I) {
- NodePtr BB = *I;
- auto &BBInfo = SNCA.NodeToInfo[BB];
- BBInfo.DFSNum = BBInfo.Semi = ++N;
- BBInfo.Label = BB;
- // Set the parent to the top of the visited stack. The stack includes us,
- // and is 1 based, so we subtract to account for both of these.
- if (I.getPathLength() > 1)
- BBInfo.Parent = SNCA.NodeToInfo[I.getPath(I.getPathLength() - 2)].DFSNum;
- SNCA.NumToNode.push_back(BB); // NumToNode[n] = V;
- }
- return N;
-}
+ unsigned runDFS(NodePtr V, unsigned N) {
+ auto DFStorage = getStorage();
-template <class NodePtr,
- class NodeT = typename std::remove_pointer<NodePtr>::type>
-NodePtr Eval(NodePtr VIn, DomTreeBuilder::SemiNCAInfo<NodeT> &SNCA,
- unsigned LastLinked) {
- auto &VInInfo = SNCA.NodeToInfo[VIn];
- if (VInInfo.DFSNum < LastLinked)
- return VIn;
-
- SmallVector<NodePtr, 32> Work;
- SmallPtrSet<NodePtr, 32> Visited;
-
- if (VInInfo.Parent >= LastLinked)
- Work.push_back(VIn);
-
- while (!Work.empty()) {
- NodePtr V = Work.back();
- auto &VInfo = SNCA.NodeToInfo[V];
- NodePtr VAncestor = SNCA.NumToNode[VInfo.Parent];
-
- // Process Ancestor first
- if (Visited.insert(VAncestor).second && VInfo.Parent >= LastLinked) {
- Work.push_back(VAncestor);
- continue;
- }
- Work.pop_back();
-
- // Update VInfo based on Ancestor info
- if (VInfo.Parent < LastLinked)
- continue;
-
- auto &VAInfo = SNCA.NodeToInfo[VAncestor];
- NodePtr VAncestorLabel = VAInfo.Label;
- NodePtr VLabel = VInfo.Label;
- if (SNCA.NodeToInfo[VAncestorLabel].Semi < SNCA.NodeToInfo[VLabel].Semi)
- VInfo.Label = VAncestorLabel;
- VInfo.Parent = VAInfo.Parent;
+ for (auto I = df_ext_begin(V, DFStorage), E = df_ext_end(V, DFStorage);
+ I != E; ++I) {
+ NodePtr BB = *I;
+ auto &BBInfo = NodeToInfo[BB];
+ BBInfo.DFSNum = BBInfo.Semi = ++N;
+ BBInfo.Label = BB;
+ // Set the parent to the top of the visited stack. The stack includes us,
+ // and is 1 based, so we subtract to account for both of these.
+ if (I.getPathLength() > 1)
+ BBInfo.Parent = NodeToInfo[I.getPath(I.getPathLength() - 2)].DFSNum;
+ NumToNode.push_back(BB); // NumToNode[n] = V;
+ }
+ return N;
}
- return VInInfo.Label;
-}
+ NodePtr eval(NodePtr VIn, unsigned LastLinked) {
+ auto &VInInfo = NodeToInfo[VIn];
+ if (VInInfo.DFSNum < LastLinked)
+ return VIn;
-template <class FuncT, class NodeT>
-void Calculate(DominatorTreeBaseByGraphTraits<GraphTraits<NodeT>> &DT,
- FuncT &F) {
- using GraphT = GraphTraits<NodeT>;
- using NodePtr = typename GraphT::NodeRef;
- static_assert(std::is_pointer<NodePtr>::value,
- "NodePtr should be a pointer type");
- using NodeType = typename std::remove_pointer<NodePtr>::type;
+ SmallVector<NodePtr, 32> Work;
+ SmallPtrSet<NodePtr, 32> Visited;
- unsigned N = 0;
- DomTreeBuilder::SemiNCAInfo<NodeType> SNCA(DT);
- SNCA.NumToNode.push_back(nullptr);
-
- bool MultipleRoots = (DT.Roots.size() > 1);
- if (MultipleRoots) {
- auto &BBInfo = SNCA.NodeToInfo[nullptr];
- BBInfo.DFSNum = BBInfo.Semi = ++N;
- BBInfo.Label = nullptr;
+ if (VInInfo.Parent >= LastLinked)
+ Work.push_back(VIn);
- SNCA.NumToNode.push_back(nullptr); // NumToNode[n] = V;
- }
+ while (!Work.empty()) {
+ NodePtr V = Work.back();
+ auto &VInfo = NodeToInfo[V];
+ NodePtr VAncestor = NumToNode[VInfo.Parent];
- // Step #1: Number blocks in depth-first order and initialize variables used
- // in later stages of the algorithm.
- if (DT.isPostDominator()){
- for (unsigned i = 0, e = static_cast<unsigned>(DT.Roots.size());
- i != e; ++i)
- N = ReverseDFSPass<NodePtr>(DT.Roots[i], SNCA, N);
- } else {
- N = DFSPass<NodePtr>(DT.Roots[0], SNCA, N);
- }
+ // Process Ancestor first
+ if (Visited.insert(VAncestor).second && VInfo.Parent >= LastLinked) {
+ Work.push_back(VAncestor);
+ continue;
+ }
+ Work.pop_back();
- // 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.
- MultipleRoots |= (DT.isPostDominator() && N != GraphTraits<FuncT*>::size(&F));
-
- // Initialize IDoms to spanning tree parents.
- for (unsigned i = 1; i <= N; ++i) {
- const NodePtr V = SNCA.NumToNode[i];
- auto &VInfo = SNCA.NodeToInfo[V];
- VInfo.IDom = SNCA.NumToNode[VInfo.Parent];
- }
+ // Update VInfo based on Ancestor info
+ if (VInfo.Parent < LastLinked)
+ continue;
+
+ auto &VAInfo = NodeToInfo[VAncestor];
+ NodePtr VAncestorLabel = VAInfo.Label;
+ NodePtr VLabel = VInfo.Label;
+ if (NodeToInfo[VAncestorLabel].Semi < NodeToInfo[VLabel].Semi)
+ VInfo.Label = VAncestorLabel;
+ VInfo.Parent = VAInfo.Parent;
+ }
- // Step #2: Calculate the semidominators of all vertices.
- for (unsigned i = N; i >= 2; --i) {
- NodePtr W = SNCA.NumToNode[i];
- auto &WInfo = SNCA.NodeToInfo[W];
-
- // Initialize the semi dominator to point to the parent node.
- WInfo.Semi = WInfo.Parent;
- for (const auto &N : inverse_children<NodeT>(W))
- if (SNCA.NodeToInfo.count(N)) { // Only if this predecessor is reachable!
- unsigned SemiU = SNCA.NodeToInfo[Eval<NodePtr>(N, SNCA, i + 1)].Semi;
- if (SemiU < WInfo.Semi)
- WInfo.Semi = SemiU;
- }
+ return VInInfo.Label;
}
+ template <typename NodeType>
+ void runSemiNCA(unsigned NumBlocks) {
+ unsigned N = 0;
+ NumToNode.push_back(nullptr);
- // Step #3: Explicitly define the immediate dominator of each vertex.
- // IDom[i] = NCA(SDom[i], SpanningTreeParent(i)).
- // Note that the parents were stored in IDoms and later got invalidated during
- // path compression in Eval.
- for (unsigned i = 2; i <= N; ++i) {
- const NodePtr W = SNCA.NumToNode[i];
- auto &WInfo = SNCA.NodeToInfo[W];
- const unsigned SDomNum = SNCA.NodeToInfo[SNCA.NumToNode[WInfo.Semi]].DFSNum;
- NodePtr WIDomCandidate = WInfo.IDom;
- while (SNCA.NodeToInfo[WIDomCandidate].DFSNum > SDomNum)
- WIDomCandidate = SNCA.NodeToInfo[WIDomCandidate].IDom;
+ bool MultipleRoots = (DT.Roots.size() > 1);
+ if (MultipleRoots) {
+ auto &BBInfo = NodeToInfo[nullptr];
+ BBInfo.DFSNum = BBInfo.Semi = ++N;
+ BBInfo.Label = nullptr;
- WInfo.IDom = WIDomCandidate;
- }
+ NumToNode.push_back(nullptr); // NumToNode[n] = V;
+ }
+
+ // Step #1: Number blocks in depth-first order and initialize variables used
+ // in later stages of the algorithm.
+ if (DT.isPostDominator()){
+ for (unsigned i = 0, e = static_cast<unsigned>(DT.Roots.size());
+ i != e; ++i)
+ N = runReverseDFS(DT.Roots[i], N);
+ } else {
+ N = runDFS(DT.Roots[0], N);
+ }
+
+ // 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.
+ MultipleRoots |= (DT.isPostDominator() && N != NumBlocks);
+
+ // Initialize IDoms to spanning tree parents.
+ for (unsigned i = 1; i <= N; ++i) {
+ const NodePtr V = NumToNode[i];
+ auto &VInfo = NodeToInfo[V];
+ VInfo.IDom = NumToNode[VInfo.Parent];
+ }
+
+ // Step #2: Calculate the semidominators of all vertices.
+ for (unsigned i = N; i >= 2; --i) {
+ NodePtr W = NumToNode[i];
+ auto &WInfo = NodeToInfo[W];
+
+ // Initialize the semi dominator to point to the parent node.
+ WInfo.Semi = WInfo.Parent;
+ for (const auto &N : inverse_children<NodeType>(W))
+ if (NodeToInfo.count(N)) { // Only if this predecessor is reachable!
+ unsigned SemiU = NodeToInfo[eval(N, i + 1)].Semi;
+ if (SemiU < WInfo.Semi)
+ WInfo.Semi = SemiU;
+ }
+ }
+
+ // Step #3: Explicitly define the immediate dominator of each vertex.
+ // IDom[i] = NCA(SDom[i], SpanningTreeParent(i)).
+ // Note that the parents were stored in IDoms and later got invalidated
+ // during path compression in Eval.
+ for (unsigned i = 2; i <= N; ++i) {
+ const NodePtr W = NumToNode[i];
+ auto &WInfo = NodeToInfo[W];
+ const unsigned SDomNum = NodeToInfo[NumToNode[WInfo.Semi]].DFSNum;
+ NodePtr WIDomCandidate = WInfo.IDom;
+ while (NodeToInfo[WIDomCandidate].DFSNum > SDomNum)
+ WIDomCandidate = NodeToInfo[WIDomCandidate].IDom;
+
+ WInfo.IDom = WIDomCandidate;
+ }
+
+ if (DT.Roots.empty()) return;
- 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.
+ NodePtr Root = !MultipleRoots ? DT.Roots[0] : nullptr;
+
+ DT.RootNode =
+ (DT.DomTreeNodes[Root] =
+ llvm::make_unique<DomTreeNodeBase<NodeT>>(Root, nullptr))
+ .get();
+
+ // Loop over all of the reachable blocks in the function...
+ for (unsigned i = 2; i <= N; ++i) {
+ NodePtr W = NumToNode[i];
+
+ // Don't replace this with 'count', the insertion side effect is important
+ if (DT.DomTreeNodes[W])
+ continue; // Haven't calculated this node yet?
+
+ NodePtr ImmDom = getIDom(W);
+
+ assert(ImmDom || DT.DomTreeNodes[nullptr]);
+
+ // Get or calculate the node for the immediate dominator
+ TreeNodePtr IDomNode = getNodeForBlock(ImmDom);
+
+ // Add a new tree node for this BasicBlock, and link it as a child of
+ // IDomNode
+ DT.DomTreeNodes[W] = IDomNode->addChild(
+ llvm::make_unique<DomTreeNodeBase<NodeT>>(W, IDomNode));
+ }
- // 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.
- NodePtr Root = !MultipleRoots ? DT.Roots[0] : nullptr;
-
- DT.RootNode =
- (DT.DomTreeNodes[Root] =
- llvm::make_unique<DomTreeNodeBase<NodeType>>(Root, nullptr))
- .get();
-
- // Loop over all of the reachable blocks in the function...
- for (unsigned i = 2; i <= N; ++i) {
- NodePtr W = SNCA.NumToNode[i];
-
- // Don't replace this with 'count', the insertion side effect is important
- if (DT.DomTreeNodes[W])
- continue; // Haven't calculated this node yet?
-
- NodePtr ImmDom = SNCA.getIDom(W);
-
- assert(ImmDom || DT.DomTreeNodes[nullptr]);
-
- // Get or calculate the node for the immediate dominator
- DomTreeNodeBase<NodeType> *IDomNode = SNCA.getNodeForBlock(ImmDom);
-
- // Add a new tree node for this BasicBlock, and link it as a child of
- // IDomNode
- DT.DomTreeNodes[W] = IDomNode->addChild(
- llvm::make_unique<DomTreeNodeBase<NodeType>>(W, IDomNode));
+ DT.updateDFSNumbers();
}
+};
+} // namespace DomTreeBuilder
+
+template <class FuncT, class NodeT>
+void Calculate(DominatorTreeBaseByGraphTraits<GraphTraits<NodeT>> &DT,
+ FuncT &F) {
+ using NodePtr = typename GraphTraits<NodeT>::NodeRef;
+ static_assert(std::is_pointer<NodePtr>::value,
+ "NodePtr should be a pointer type");
- DT.updateDFSNumbers();
+ DomTreeBuilder::SemiNCAInfo<typename std::remove_pointer<NodePtr>::type>
+ SNCA(DT);
+ SNCA.template runSemiNCA<NodeT>(GraphTraits<FuncT *>::size(&F));
}
-} // namespace DomTreeBuilder
+} // namespace llvm
#endif
More information about the llvm-commits
mailing list