[cfe-commits] r170826 - in /cfe/trunk: include/clang/Analysis/CallGraph.h lib/Analysis/CallGraph.cpp lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp test/Analysis/debug-CallGraph.c

Anna Zaks ganna at apple.com
Thu Dec 20 18:58:22 PST 2012


On Dec 20, 2012, at 5:32 PM, Rafael EspĂ­ndola <rafael.espindola at gmail.com> wrote:

> Hi Anna,
> 
> I revered this as the output of trunk/test/Analysis/debug-CallGraph.c
> was in a different order in each run.
> 

I saw that, looks like we have non-deterministic iteration in the dump routines. Thanks!

> On 20 December 2012 20:19, Anna Zaks <ganna at apple.com> wrote:
>> Author: zaks
>> Date: Thu Dec 20 19:19:22 2012
>> New Revision: 170826
>> 
>> URL: http://llvm.org/viewvc/llvm-project?rev=170826&view=rev
>> Log:
>> [analyzer] Traverse the Call Graph in topological order.
>> 
>> Modify the call graph by removing the parentless nodes. Instead all
>> nodes are children of root to ensure they are all reachable. Remove the
>> tracking of nodes that are "top level" or global. This information is
>> not used and can be obtained from the Decls stored inside
>> CallGraphNodes.
>> 
>> Instead of existing ordering hacks, analyze the functions in topological
>> order over the Call Graph.
>> 
>> Together with the addition of devirtualizable ObjC message sends and
>> blocks to the call graph, this gives around 6% performance improvement
>> on several large ObjC benchmarks.
>> 
>> Modified:
>>    cfe/trunk/include/clang/Analysis/CallGraph.h
>>    cfe/trunk/lib/Analysis/CallGraph.cpp
>>    cfe/trunk/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
>>    cfe/trunk/test/Analysis/debug-CallGraph.c
>> 
>> Modified: cfe/trunk/include/clang/Analysis/CallGraph.h
>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/CallGraph.h?rev=170826&r1=170825&r2=170826&view=diff
>> ==============================================================================
>> --- cfe/trunk/include/clang/Analysis/CallGraph.h (original)
>> +++ cfe/trunk/include/clang/Analysis/CallGraph.h Thu Dec 20 19:19:22 2012
>> @@ -39,15 +39,9 @@
>>   /// FunctionMap owns all CallGraphNodes.
>>   FunctionMapTy FunctionMap;
>> 
>> -  /// This is a virtual root node that has edges to all the global functions -
>> -  /// 'main' or functions accessible from other translation units.
>> +  /// This is a virtual root node that has edges to all the functions.
>>   CallGraphNode *Root;
>> 
>> -  /// The list of nodes that have no parent. These are unreachable from Root.
>> -  /// Declarations can get to this list due to impressions in the graph, for
>> -  /// example, we do not track functions whose addresses were taken.
>> -  llvm::SetVector<CallGraphNode *> ParentlessNodes;
>> -
>> public:
>>   CallGraph();
>>   ~CallGraph();
>> @@ -91,12 +85,6 @@
>>   /// failing to add a call edge due to the analysis imprecision.
>>   typedef llvm::SetVector<CallGraphNode *>::iterator nodes_iterator;
>>   typedef llvm::SetVector<CallGraphNode *>::const_iterator const_nodes_iterator;
>> -  nodes_iterator parentless_begin() { return ParentlessNodes.begin(); }
>> -  nodes_iterator parentless_end() { return ParentlessNodes.end(); }
>> -  const_nodes_iterator
>> -    parentless_begin() const { return ParentlessNodes.begin(); }
>> -  const_nodes_iterator
>> -    parentless_end() const { return ParentlessNodes.end(); }
>> 
>>   void print(raw_ostream &os) const;
>>   void dump() const;
>> @@ -170,7 +158,6 @@
>> 
>>   void addCallee(CallGraphNode *N, CallGraph *CG) {
>>     CalledFunctions.push_back(N);
>> -    CG->ParentlessNodes.remove(N);
>>   }
>> 
>>   Decl *getDecl() const { return FD; }
>> 
>> Modified: cfe/trunk/lib/Analysis/CallGraph.cpp
>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/CallGraph.cpp?rev=170826&r1=170825&r2=170826&view=diff
>> ==============================================================================
>> --- cfe/trunk/lib/Analysis/CallGraph.cpp (original)
>> +++ cfe/trunk/lib/Analysis/CallGraph.cpp Thu Dec 20 19:19:22 2012
>> @@ -141,14 +141,8 @@
>> void CallGraph::addNodeForDecl(Decl* D, bool IsGlobal) {
>>   assert(D);
>> 
>> -  // Do nothing if the node already exists.
>> -  if (FunctionMap.find(D) != FunctionMap.end())
>> -    return;
>> -
>>   // Allocate a new node, mark it as root, and process it's calls.
>>   CallGraphNode *Node = getOrInsertNode(D);
>> -  if (IsGlobal)
>> -    Root->addCallee(Node, this);
>> 
>>   // Process all the calls by this function as well.
>>   CGBuilder builder(this, Node);
>> @@ -168,9 +162,9 @@
>>     return Node;
>> 
>>   Node = new CallGraphNode(F);
>> -  // If not root, add to the parentless list.
>> +  // Make Root node a parent of all functions to make sure all are reachable.
>>   if (F != 0)
>> -    ParentlessNodes.insert(Node);
>> +    Root->addCallee(Node, this);
>>   return Node;
>> }
>> 
>> 
>> Modified: cfe/trunk/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp?rev=170826&r1=170825&r2=170826&view=diff
>> ==============================================================================
>> --- cfe/trunk/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp (original)
>> +++ cfe/trunk/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp Thu Dec 20 19:19:22 2012
>> @@ -39,6 +39,7 @@
>> #include "llvm/ADT/OwningPtr.h"
>> #include "llvm/ADT/SmallPtrSet.h"
>> #include "llvm/ADT/Statistic.h"
>> +#include "llvm/ADT/PostOrderIterator.h"
>> #include "llvm/Support/Path.h"
>> #include "llvm/Support/Program.h"
>> #include "llvm/Support/Timer.h"
>> @@ -417,61 +418,34 @@
>> }
>> 
>> void AnalysisConsumer::HandleDeclsCallGraph(const unsigned LocalTUDeclsSize) {
>> -  // Otherwise, use the Callgraph to derive the order.
>> -  // Build the Call Graph.
>> -  CallGraph CG;
>> -
>> -  // Add all the top level declarations to the graph.
>> +  // Build the Call Graph by adding all the top level declarations to the graph.
>>   // Note: CallGraph can trigger deserialization of more items from a pch
>>   // (though HandleInterestingDecl); triggering additions to LocalTUDecls.
>>   // We rely on random access to add the initially processed Decls to CG.
>> +  CallGraph CG;
>>   for (unsigned i = 0 ; i < LocalTUDeclsSize ; ++i) {
>>     CG.addToCallGraph(LocalTUDecls[i]);
>>   }
>> 
>> -  // Find the top level nodes - children of root + the unreachable (parentless)
>> -  // nodes.
>> -  llvm::SmallVector<CallGraphNode*, 24> TopLevelFunctions;
>> -  for (CallGraph::nodes_iterator TI = CG.parentless_begin(),
>> -                                 TE = CG.parentless_end(); TI != TE; ++TI) {
>> -    TopLevelFunctions.push_back(*TI);
>> -    NumFunctionTopLevel++;
>> -  }
>> -  CallGraphNode *Entry = CG.getRoot();
>> -  for (CallGraphNode::iterator I = Entry->begin(),
>> -                               E = Entry->end(); I != E; ++I) {
>> -    TopLevelFunctions.push_back(*I);
>> -    NumFunctionTopLevel++;
>> -  }
>> -
>> -  // Make sure the nodes are sorted in order reverse of their definition in the
>> -  // translation unit. This step is very important for performance. It ensures
>> -  // that we analyze the root functions before the externally available
>> -  // subroutines.
>> -  std::deque<CallGraphNode*> BFSQueue;
>> -  for (llvm::SmallVector<CallGraphNode*, 24>::reverse_iterator
>> -         TI = TopLevelFunctions.rbegin(), TE = TopLevelFunctions.rend();
>> -         TI != TE; ++TI)
>> -    BFSQueue.push_back(*TI);
>> -
>> -  // 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.
>> +  // Walk over all of the call graph nodes in topological order, so that we
>> +  // analyze parents before the children. Skip the functions inlined into
>> +  // the previously processed functions. Use external Visited set to identify
>> +  // inlined functions. The topological order allows the "do not reanalyze
>> +  // previously inlined function" performance heuristic to be triggered more
>> +  // often.
>>   SetOfConstDecls Visited;
>>   SetOfConstDecls VisitedAsTopLevel;
>> -  while(!BFSQueue.empty()) {
>> -    CallGraphNode *N = BFSQueue.front();
>> -    BFSQueue.pop_front();
>> -
>> -    // Push the children into the queue.
>> -    for (CallGraphNode::const_iterator CI = N->begin(),
>> -         CE = N->end(); CI != CE; ++CI) {
>> -      if (!shouldSkipFunction((*CI)->getDecl(), Visited, VisitedAsTopLevel))
>> -        BFSQueue.push_back(*CI);
>> -    }
>> +  llvm::ReversePostOrderTraversal<clang::CallGraph*> RPOT(&CG);
>> +  for (llvm::ReversePostOrderTraversal<clang::CallGraph*>::rpo_iterator
>> +         I = RPOT.begin(); I != RPOT.end(); ++I) {
>> +    NumFunctionTopLevel++;
>> 
>> +    CallGraphNode *N = *I;
>>     Decl *D = N->getDecl();
>> -    assert(D);
>> +
>> +    // Skip the abstract root node.
>> +    if (!D)
>> +      continue;
>> 
>>     // Skip the functions which have been processed already or previously
>>     // inlined.
>> 
>> Modified: cfe/trunk/test/Analysis/debug-CallGraph.c
>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/debug-CallGraph.c?rev=170826&r1=170825&r2=170826&view=diff
>> ==============================================================================
>> --- cfe/trunk/test/Analysis/debug-CallGraph.c (original)
>> +++ cfe/trunk/test/Analysis/debug-CallGraph.c Thu Dec 20 19:19:22 2012
>> @@ -1,9 +1,9 @@
>> -// RUN: %clang_cc1 -analyze -analyzer-checker=debug.DumpCallGraph %s 2>&1 | FileCheck %s
>> +// RUN: %clang_cc1 -analyze -analyzer-checker=debug.DumpCallGraph %s -fblocks 2>&1 | FileCheck %s
>> 
>> static void mmm(int y) {
>>   if (y != 0)
>>       y++;
>> -  y = y/0;
>> +  y = y/y;
>> }
>> 
>> static int foo(int x, int y) {
>> @@ -17,5 +17,17 @@
>>   foo(1,2);
>> }
>> 
>> +void bbb(int y) {
>> +  int x = (y > 2);
>> +  ^ {
>> +      foo(x, y);
>> +  }();
>> +}
>> +
>> // CHECK:--- Call graph Dump ---
>> -// CHECK: Function: < root > calls: aaa
>> +// CHECK: Function: < root > calls: mmm foo aaa < > bbb
>> +// CHECK: Function: bbb calls: < >
>> +// CHECK: Function: mmm calls:
>> +// CHECK: Function: aaa calls: foo
>> +// CHECK: Function: foo calls: mmm
>> +// CHECK: Function: < > calls: foo
>> 
>> 
>> _______________________________________________
>> cfe-commits mailing list
>> cfe-commits at cs.uiuc.edu
>> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits





More information about the cfe-commits mailing list