[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

Rafael EspĂ­ndola rafael.espindola at gmail.com
Thu Dec 20 17:32:46 PST 2012


Hi Anna,

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

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