[cfe-commits] r152652 - /cfe/trunk/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp

Anna Zaks ganna at apple.com
Tue Mar 13 12:32:13 PDT 2012


Author: zaks
Date: Tue Mar 13 14:32:13 2012
New Revision: 152652

URL: http://llvm.org/viewvc/llvm-project?rev=152652&view=rev
Log:
[analyzer] Use BFS over call graph when analysing functions.

BFS should give slightly better performance. Ex: Suppose, we have two
roots R1 and R2. A callee function C is reachable through both. However,
C is not inlined when analyzing R1 due to inline stack depth limit. With
DFS, C will be analyzed as top level even though it would be analyzed as
inlined through R2. On the other hand, BFS could avoid analyzing C as
top level.

Modified:
    cfe/trunk/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp

Modified: cfe/trunk/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp?rev=152652&r1=152651&r2=152652&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp Tue Mar 13 14:32:13 2012
@@ -43,6 +43,8 @@
 #include "llvm/ADT/OwningPtr.h"
 #include "llvm/ADT/Statistic.h"
 
+#include <queue>
+
 using namespace clang;
 using namespace ento;
 using llvm::SmallPtrSet;
@@ -282,31 +284,45 @@
     NumFunctionTopLevel++;
   }
 
-  // TODO: Sort TopLevelFunctions.
+  std::queue<CallGraphNode*> BFSQueue;
+  for (llvm::SmallVector<CallGraphNode*, 24>::iterator
+         TI = TopLevelFunctions.begin(), TE = TopLevelFunctions.end();
+         TI != TE; ++TI)
+    BFSQueue.push(*TI);
 
-  // DFS over all of the top level nodes. Use external Visited set, which is
+  // BFS over all of the functions, while skipping the ones inlined into
+  // the previously processed functions. Use external Visited set, which is
   // also modified when we inline a function.
   SmallPtrSet<CallGraphNode*,24> Visited;
-  for (llvm::SmallVector<CallGraphNode*, 24>::iterator
-         TI = TopLevelFunctions.begin(), TE = TopLevelFunctions.end();
-         TI != TE; ++TI) {
-    for (llvm::df_ext_iterator<CallGraphNode*, SmallPtrSet<CallGraphNode*,24> >
-        DFI = llvm::df_ext_begin(*TI, Visited),
-        E = llvm::df_ext_end(*TI, Visited);
-        DFI != E; ++DFI) {
-      SetOfDecls VisitedCallees;
-      Decl *D = (*DFI)->getDecl();
-      assert(D);
-      HandleCode(D, ANALYSIS_PATH,
-                 (Mgr->InliningMode == All ? 0 : &VisitedCallees));
-
-      // Add the visited callees to the global visited set.
-      for (SetOfDecls::const_iterator I = VisitedCallees.begin(),
-                                      E = VisitedCallees.end(); I != E; ++I) {
-        CallGraphNode *VN = CG.getNode(*I);
-        if (VN)
-          Visited.insert(VN);
-      }
+  while(!BFSQueue.empty()) {
+    CallGraphNode *N = BFSQueue.front();
+    BFSQueue.pop();
+
+    // Skip the functions which have been processed already or previously
+    // inlined.
+    if (Visited.count(N))
+      continue;
+
+    // Analyze the function.
+    SetOfDecls VisitedCallees;
+    Decl *D = N->getDecl();
+    assert(D);
+    HandleCode(D, ANALYSIS_PATH,
+               (Mgr->InliningMode == All ? 0 : &VisitedCallees));
+
+    // Add the visited callees to the global visited set.
+    for (SetOfDecls::const_iterator I = VisitedCallees.begin(),
+                                    E = VisitedCallees.end(); I != E; ++I) {
+      CallGraphNode *VN = CG.getNode(*I);
+      if (VN)
+        Visited.insert(VN);
+    }
+    Visited.insert(N);
+
+    // Push the children into the queue.
+    for (CallGraphNode::const_iterator CI = N->begin(),
+                                       CE = N->end(); CI != CE; ++CI) {
+      BFSQueue.push(*CI);
     }
   }
 }





More information about the cfe-commits mailing list