summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAnna Zaks <ganna@apple.com>2012-03-30 05:48:10 +0000
committerAnna Zaks <ganna@apple.com>2012-03-30 05:48:10 +0000
commit54fd4a076695a480ca55f2c35444fc82842a5bc7 (patch)
treed54cd8fb618456c71aad8407573495ca31609cc4
parentbc15335e580bd29695df04c30d19c3b5a8192552 (diff)
downloadbcm5719-llvm-54fd4a076695a480ca55f2c35444fc82842a5bc7.tar.gz
bcm5719-llvm-54fd4a076695a480ca55f2c35444fc82842a5bc7.zip
[analyzer] Do not inline functions which previously reached max block
count. This is an optimization for "retry without inlining" option. Here, if we failed to inline a function due to reaching the basic block max count, we are going to store this information and not try to inline it again in the translation unit. This can be viewed as a function summary. On sqlite, with this optimization, we are 30% faster then before and cover 10% more basic blocks (partially because the number of times we reach timeout is decreased by 20%). llvm-svn: 153730
-rw-r--r--clang/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h25
-rw-r--r--clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h7
-rw-r--r--clang/lib/StaticAnalyzer/Core/ExprEngine.cpp10
-rw-r--r--clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp3
-rw-r--r--clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp6
5 files changed, 46 insertions, 5 deletions
diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h
index be4c649133d..f8f7e25d8bb 100644
--- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h
+++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h
@@ -32,6 +32,31 @@ namespace ento {
typedef llvm::SmallPtrSet<const Decl*,24> SetOfDecls;
+class FunctionSummariesTy {
+ struct FunctionSummary {
+ /// True if this function has reached a max block count while inlined from
+ /// at least one call site.
+ bool MayReachMaxBlockCount;
+ FunctionSummary() : MayReachMaxBlockCount(false) {}
+ };
+
+ typedef llvm::DenseMap<const Decl*, FunctionSummary> MapTy;
+ MapTy Map;
+
+public:
+ void markReachedMaxBlockCount(const Decl* D) {
+ Map[D].MayReachMaxBlockCount = true;
+ }
+
+ bool hasReachedMaxBlockCount(const Decl* D) {
+ MapTy::const_iterator I = Map.find(D);
+ if (I != Map.end())
+ return I->second.MayReachMaxBlockCount;
+ return false;
+ }
+
+};
+
class AnalysisManager : public BugReporterData {
virtual void anchor();
AnalysisDeclContextManager AnaCtxMgr;
diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
index c0c6ef3fb46..f4d2e6027b5 100644
--- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
+++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
@@ -90,8 +90,13 @@ class ExprEngine : public SubEngine {
/// destructor is called before the rest of the ExprEngine is destroyed.
GRBugReporter BR;
+ /// The information about functions shared by the whole translation unit.
+ /// (This data is owned by AnalysisConsumer.)
+ FunctionSummariesTy *FunctionSummaries;
+
public:
- ExprEngine(AnalysisManager &mgr, bool gcEnabled, SetOfDecls *VisitedCallees);
+ ExprEngine(AnalysisManager &mgr, bool gcEnabled, SetOfDecls *VisitedCallees,
+ FunctionSummariesTy *FS);
~ExprEngine();
diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
index fc2a756eb39..4789f354e49 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -67,7 +67,8 @@ static inline Selector GetNullarySelector(const char* name, ASTContext &Ctx) {
//===----------------------------------------------------------------------===//
ExprEngine::ExprEngine(AnalysisManager &mgr, bool gcEnabled,
- SetOfDecls *VisitedCallees)
+ SetOfDecls *VisitedCallees,
+ FunctionSummariesTy *FS)
: AMgr(mgr),
AnalysisDeclContexts(mgr.getAnalysisDeclContextManager()),
Engine(*this, VisitedCallees),
@@ -81,7 +82,7 @@ ExprEngine::ExprEngine(AnalysisManager &mgr, bool gcEnabled,
currentStmt(NULL), currentStmtIdx(0), currentBuilderContext(0),
NSExceptionII(NULL), NSExceptionInstanceRaiseSelectors(NULL),
RaiseSel(GetNullarySelector("raise", getContext())),
- ObjCGCEnabled(gcEnabled), BR(mgr, *this) {
+ ObjCGCEnabled(gcEnabled), BR(mgr, *this), FunctionSummaries(FS) {
if (mgr.shouldEagerlyTrimExplodedGraph()) {
// Enable eager node reclaimation when constructing the ExplodedGraph.
@@ -1046,9 +1047,12 @@ void ExprEngine::processCFGBlockEntrance(const BlockEdge &L,
// Check if we stopped at the top level function or not.
// Root node should have the location context of the top most function.
const LocationContext *CalleeLC = pred->getLocation().getLocationContext();
+ const LocationContext *CalleeSF = CalleeLC->getCurrentStackFrame();
const LocationContext *RootLC =
(*G.roots_begin())->getLocation().getLocationContext();
- if (RootLC->getCurrentStackFrame() != CalleeLC->getCurrentStackFrame()) {
+ if (RootLC->getCurrentStackFrame() != CalleeSF) {
+ FunctionSummaries->markReachedMaxBlockCount(CalleeSF->getDecl());
+
// Re-run the call evaluation without inlining it, by storing the
// no-inlining policy in the state and enqueuing the new work item on
// the list. Replay should almost never fail. Use the stats to catch it
diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
index 1746b5c529e..fead0862fa8 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
@@ -137,6 +137,9 @@ bool ExprEngine::shouldInlineDecl(const FunctionDecl *FD, ExplodedNode *Pred) {
== AMgr.InlineMaxStackDepth)
return false;
+ if (FunctionSummaries->hasReachedMaxBlockCount(FD))
+ return false;
+
if (CalleeCFG->getNumBlockIDs() > AMgr.InlineMaxFunctionSize)
return false;
diff --git a/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp b/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
index b1d2f31df0e..3b9deda2bac 100644
--- a/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
+++ b/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
@@ -104,6 +104,10 @@ public:
/// Time the analyzes time of each translation unit.
static llvm::Timer* TUTotalTimer;
+ /// The information about analyzed functions shared throughout the
+ /// translation unit.
+ FunctionSummariesTy FunctionSummaries;
+
AnalysisConsumer(const Preprocessor& pp,
const std::string& outdir,
const AnalyzerOptions& opts,
@@ -449,7 +453,7 @@ void AnalysisConsumer::ActionExprEngine(Decl *D, bool ObjCGCEnabled,
if (!Mgr->getCFG(D))
return;
- ExprEngine Eng(*Mgr, ObjCGCEnabled, VisitedCallees);
+ ExprEngine Eng(*Mgr, ObjCGCEnabled, VisitedCallees, &FunctionSummaries);
// Set the graph auditor.
OwningPtr<ExplodedNode::Auditor> Auditor;
OpenPOWER on IntegriCloud