[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