[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