[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