diff options
author | Anna Zaks <ganna@apple.com> | 2012-04-12 22:36:48 +0000 |
---|---|---|
committer | Anna Zaks <ganna@apple.com> | 2012-04-12 22:36:48 +0000 |
commit | 6a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3 (patch) | |
tree | cf41e29ac97fff116c78975aeecda1a68594e741 /include | |
parent | 273ed9870aa064992fb3c25a1f4d8973b10ad36e (diff) |
[analyzer] PCH deserialization optimization.
We should not deserialize unused declarations from the PCH file. Achieve
this by storing the top level declarations during parsing
(HandleTopLevelDecl ASTConsumer callback) and analyzing/building a call
graph only for those.
Tested the patch on a sample ObjC file that uses PCH. With the patch,
the analyzes is 17.5% faster and clang consumes 40% less memory.
Got about 10% overall build/analyzes time decrease on a large Objective
C project.
A bit of CallGraph refactoring/cleanup as well..
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@154625 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'include')
4 files changed, 50 insertions, 11 deletions
diff --git a/include/clang/Analysis/CallGraph.h b/include/clang/Analysis/CallGraph.h index f1b6e64772..9b6807343c 100644 --- a/include/clang/Analysis/CallGraph.h +++ b/include/clang/Analysis/CallGraph.h @@ -18,6 +18,7 @@ #define LLVM_CLANG_ANALYSIS_CALLGRAPH #include "clang/AST/DeclBase.h" +#include "clang/AST/RecursiveASTVisitor.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/GraphTraits.h" #include "llvm/ADT/SetVector.h" @@ -25,8 +26,14 @@ namespace clang { class CallGraphNode; -class CallGraph { +/// \class The AST-based call graph. +/// +/// The call graph extends itself with the given declarations by implementing +/// the recursive AST visitor, which constructs the graph by visiting the given +/// declarations. +class CallGraph : public RecursiveASTVisitor<CallGraph> { friend class CallGraphNode; + typedef llvm::DenseMap<const Decl *, CallGraphNode *> FunctionMapTy; /// FunctionMap owns all CallGraphNodes. @@ -45,19 +52,23 @@ public: CallGraph(); ~CallGraph(); - /// \brief Add the given declaration to the call graph. - void addToCallGraph(Decl *D, bool IsGlobal); + /// \brief Populate the call graph with the functions in the given + /// declaration. + /// + /// Recursively walks the declaration to find all the dependent Decls as well. + void addToCallGraph(Decl *D) { + TraverseDecl(D); + } - /// \brief Populate the call graph with the functions in the given translation - /// unit. - void addToCallGraph(TranslationUnitDecl *TU); + /// \brief Determine if a declaration should be included in the graph. + static bool includeInGraph(const Decl *D); /// \brief Lookup the node for the given declaration. CallGraphNode *getNode(const Decl *) const; /// \brief Lookup the node for the given declaration. If none found, insert /// one into the graph. - CallGraphNode *getOrInsertFunction(Decl *); + CallGraphNode *getOrInsertNode(Decl *); /// Iterators through all the elements in the graph. Note, this gives /// non-deterministic order. @@ -90,6 +101,32 @@ public: void print(raw_ostream &os) const; void dump() const; void viewGraph() const; + + /// Part of recursive declaration visitation. + bool VisitFunctionDecl(FunctionDecl *FD) { + // We skip function template definitions, as their semantics is + // only determined when they are instantiated. + if (includeInGraph(FD)) + // If this function has external linkage, anything could call it. + // Note, we are not precise here. For example, the function could have + // its address taken. + addNodeForDecl(FD, FD->isGlobal()); + return true; + } + + /// Part of recursive declaration visitation. + bool VisitObjCMethodDecl(ObjCMethodDecl *MD) { + if (includeInGraph(MD)) + addNodeForDecl(MD, true); + return true; + } + +private: + /// \brief Add the given declaration to the call graph. + void addNodeForDecl(Decl *D, bool IsGlobal); + + /// \brief Allocate a new node in the graph. + CallGraphNode *allocateNewNode(Decl *); }; class CallGraphNode { diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h b/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h index d9156441db..59136fc314 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h @@ -82,7 +82,7 @@ private: /// The functions which have been analyzed through inlining. This is owned by /// AnalysisConsumer. It can be null. - SetOfDecls *AnalyzedCallees; + SetOfConstDecls *AnalyzedCallees; /// The information about functions shared by the whole translation unit. /// (This data is owned by AnalysisConsumer.) @@ -109,7 +109,7 @@ private: public: /// Construct a CoreEngine object to analyze the provided CFG using /// a DFS exploration of the exploded graph. - CoreEngine(SubEngine& subengine, SetOfDecls *VisitedCallees, + CoreEngine(SubEngine& subengine, SetOfConstDecls *VisitedCallees, FunctionSummariesTy *FS) : SubEng(subengine), G(new ExplodedGraph()), WList(WorkList::makeBFS()), diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h index 7b31172e33..2a21a03e9a 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h @@ -91,7 +91,8 @@ class ExprEngine : public SubEngine { GRBugReporter BR; public: - ExprEngine(AnalysisManager &mgr, bool gcEnabled, SetOfDecls *VisitedCallees, + ExprEngine(AnalysisManager &mgr, bool gcEnabled, + SetOfConstDecls *VisitedCallees, FunctionSummariesTy *FS); ~ExprEngine(); diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/FunctionSummary.h b/include/clang/StaticAnalyzer/Core/PathSensitive/FunctionSummary.h index 33943d9f1c..42adff3e2b 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/FunctionSummary.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/FunctionSummary.h @@ -21,7 +21,8 @@ namespace clang { namespace ento { -typedef llvm::SmallPtrSet<const Decl*,24> SetOfDecls; +typedef llvm::SmallPtrSet<Decl*, 24> SetOfDecls; +typedef llvm::SmallPtrSet<const Decl*, 24> SetOfConstDecls; class FunctionSummariesTy { struct FunctionSummary { |