[llvm] r206948 - [LCG] Hoist the logic for forming a new SCC from the top of the DFSStack

Chandler Carruth chandlerc at gmail.com
Tue Apr 22 23:09:03 PDT 2014


Author: chandlerc
Date: Wed Apr 23 01:09:03 2014
New Revision: 206948

URL: http://llvm.org/viewvc/llvm-project?rev=206948&view=rev
Log:
[LCG] Hoist the logic for forming a new SCC from the top of the DFSStack
into a helper function. I plan to re-use it for doing incremental
DFS-based updates to the SCCs when we mutate the call graph.

Modified:
    llvm/trunk/include/llvm/Analysis/LazyCallGraph.h
    llvm/trunk/lib/Analysis/LazyCallGraph.cpp

Modified: llvm/trunk/include/llvm/Analysis/LazyCallGraph.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/LazyCallGraph.h?rev=206948&r1=206947&r2=206948&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Analysis/LazyCallGraph.h (original)
+++ llvm/trunk/include/llvm/Analysis/LazyCallGraph.h Wed Apr 23 01:09:03 2014
@@ -364,6 +364,11 @@ private:
   /// \brief Helper to update pointers back to the graph object during moves.
   void updateGraphPtrs();
 
+  /// \brief Helper to form a new SCC out of the top of a DFSStack-like
+  /// structure.
+  SCC *formSCCFromDFSStack(
+      SmallVectorImpl<std::pair<Node *, Node::iterator>> &DFSStack);
+
   /// \brief Retrieve the next node in the post-order SCC walk of the call graph.
   SCC *getNextSCCInPostOrder();
 };

Modified: llvm/trunk/lib/Analysis/LazyCallGraph.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/LazyCallGraph.cpp?rev=206948&r1=206947&r2=206948&view=diff
==============================================================================
--- llvm/trunk/lib/Analysis/LazyCallGraph.cpp (original)
+++ llvm/trunk/lib/Analysis/LazyCallGraph.cpp Wed Apr 23 01:09:03 2014
@@ -151,45 +151,8 @@ void LazyCallGraph::updateGraphPtrs() {
   }
 }
 
-LazyCallGraph::SCC *LazyCallGraph::getNextSCCInPostOrder() {
-  // When the stack is empty, there are no more SCCs to walk in this graph.
-  if (DFSStack.empty()) {
-    // If we've handled all candidate entry nodes to the SCC forest, we're done.
-    if (SCCEntryNodes.empty())
-      return nullptr;
-
-    Node *N = get(*SCCEntryNodes.pop_back_val());
-    DFSStack.push_back(std::make_pair(N, N->begin()));
-  }
-
-  Node *N = DFSStack.back().first;
-  if (N->DFSNumber == 0) {
-    // This node hasn't been visited before, assign it a DFS number and remove
-    // it from the entry set.
-    N->LowLink = N->DFSNumber = NextDFSNumber++;
-    SCCEntryNodes.remove(&N->getFunction());
-  }
-
-  for (auto I = DFSStack.back().second, E = N->end(); I != E; ++I) {
-    Node *ChildN = *I;
-    if (ChildN->DFSNumber == 0) {
-      // Mark that we should start at this child when next this node is the
-      // top of the stack. We don't start at the next child to ensure this
-      // child's lowlink is reflected.
-      // FIXME: I don't actually think this is required, and we could start
-      // at the next child.
-      DFSStack.back().second = I;
-
-      // Recurse onto this node via a tail call.
-      DFSStack.push_back(std::make_pair(ChildN, ChildN->begin()));
-      return LazyCallGraph::getNextSCCInPostOrder();
-    }
-
-    // Track the lowest link of the childen, if any are still in the stack.
-    if (ChildN->LowLink < N->LowLink && !SCCMap.count(&ChildN->getFunction()))
-      N->LowLink = ChildN->LowLink;
-  }
-
+LazyCallGraph::SCC *LazyCallGraph::formSCCFromDFSStack(
+    SmallVectorImpl<std::pair<Node *, Node::iterator>> &DFSStack) {
   // The tail of the stack is the new SCC. Allocate the SCC and pop the stack
   // into it.
   SCC *NewSCC = new (SCCBPA.Allocate()) SCC();
@@ -197,10 +160,10 @@ LazyCallGraph::SCC *LazyCallGraph::getNe
   // Because we don't follow the strict Tarjan recursive formulation, walk
   // from the top of the stack down, propagating the lowest link and stopping
   // when the DFS number is the lowest link.
-  int LowestLink = N->LowLink;
+  int LowestLink = DFSStack.back().first->LowLink;
   do {
     Node *SCCN = DFSStack.pop_back_val().first;
-    SCCMap.insert(std::make_pair(&SCCN->getFunction(), NewSCC));
+    SCCMap[&SCCN->getFunction()] = NewSCC;
     NewSCC->Nodes.push_back(SCCN);
     LowestLink = std::min(LowestLink, SCCN->LowLink);
     bool Inserted =
@@ -233,6 +196,49 @@ LazyCallGraph::SCC *LazyCallGraph::getNe
   return NewSCC;
 }
 
+LazyCallGraph::SCC *LazyCallGraph::getNextSCCInPostOrder() {
+  // When the stack is empty, there are no more SCCs to walk in this graph.
+  if (DFSStack.empty()) {
+    // If we've handled all candidate entry nodes to the SCC forest, we're done.
+    if (SCCEntryNodes.empty())
+      return nullptr;
+
+    Node *N = get(*SCCEntryNodes.pop_back_val());
+    DFSStack.push_back(std::make_pair(N, N->begin()));
+  }
+
+  Node *N = DFSStack.back().first;
+  if (N->DFSNumber == 0) {
+    // This node hasn't been visited before, assign it a DFS number and remove
+    // it from the entry set.
+    N->LowLink = N->DFSNumber = NextDFSNumber++;
+    SCCEntryNodes.remove(&N->getFunction());
+  }
+
+  for (auto I = DFSStack.back().second, E = N->end(); I != E; ++I) {
+    Node *ChildN = *I;
+    if (ChildN->DFSNumber == 0) {
+      // Mark that we should start at this child when next this node is the
+      // top of the stack. We don't start at the next child to ensure this
+      // child's lowlink is reflected.
+      // FIXME: I don't actually think this is required, and we could start
+      // at the next child.
+      DFSStack.back().second = I;
+
+      // Recurse onto this node via a tail call.
+      DFSStack.push_back(std::make_pair(ChildN, ChildN->begin()));
+      return LazyCallGraph::getNextSCCInPostOrder();
+    }
+
+    // Track the lowest link of the childen, if any are still in the stack.
+    if (ChildN->LowLink < N->LowLink && !SCCMap.count(&ChildN->getFunction()))
+      N->LowLink = ChildN->LowLink;
+  }
+
+  // Form the new SCC out of the top of the DFS stack.
+  return formSCCFromDFSStack(DFSStack);
+}
+
 char LazyCallGraphAnalysis::PassID;
 
 LazyCallGraphPrinterPass::LazyCallGraphPrinterPass(raw_ostream &OS) : OS(OS) {}





More information about the llvm-commits mailing list