aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJordan Rose <jordan_rose@apple.com>2012-10-23 23:59:05 +0000
committerJordan Rose <jordan_rose@apple.com>2012-10-23 23:59:05 +0000
commit4d9e497a2b1eab3b1214848216050c64fc3acfd6 (patch)
tree39bb84819b593508b917613131c5d56cd4febb56
parente72faf6148aadae316ce1fa2deb8289c10ee1ab9 (diff)
[analyzer] Replace -analyzer-no-eagerly-trim-egraph with graph-trim-interval.
After every 1000 CFGElements processed, the ExplodedGraph trims out nodes that satisfy a number of criteria for being "boring" (single predecessor, single successor, and more). Rather than controlling this with a cc1 option, which can only disable this behavior, we now have an analyzer-config option, 'graph-trim-interval', which can change this interval from 1000 to something else. Setting the value to 0 disables reclamation. The next commit relies on this behavior to actually test anything. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@166528 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/Driver/CC1Options.td2
-rw-r--r--include/clang/StaticAnalyzer/Core/AnalyzerOptions.h12
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h12
-rw-r--r--lib/Frontend/CompilerInvocation.cpp1
-rw-r--r--lib/StaticAnalyzer/Core/AnalyzerOptions.cpp6
-rw-r--r--lib/StaticAnalyzer/Core/ExplodedGraph.cpp14
-rw-r--r--lib/StaticAnalyzer/Core/ExprEngine.cpp9
-rw-r--r--test/Analysis/analyzer-config.c3
-rw-r--r--test/Analysis/analyzer-config.cpp3
9 files changed, 39 insertions, 23 deletions
diff --git a/include/clang/Driver/CC1Options.td b/include/clang/Driver/CC1Options.td
index e260beab81..0c54ecc50a 100644
--- a/include/clang/Driver/CC1Options.td
+++ b/include/clang/Driver/CC1Options.td
@@ -69,8 +69,6 @@ def analyze_function : Separate<["-"], "analyze-function">,
def analyze_function_EQ : Joined<["-"], "analyze-function=">, Alias<analyze_function>;
def analyzer_eagerly_assume : Flag<["-"], "analyzer-eagerly-assume">,
HelpText<"Eagerly assume the truth/falseness of some symbolic constraints">;
-def analyzer_no_eagerly_trim_egraph : Flag<["-"], "analyzer-no-eagerly-trim-egraph">,
- HelpText<"Don't eagerly remove uninteresting ExplodedNodes from the ExplodedGraph">;
def trim_egraph : Flag<["-"], "trim-egraph">,
HelpText<"Only show error-related paths in the analysis graph">;
def analyzer_viz_egraph_graphviz : Flag<["-"], "analyzer-viz-egraph-graphviz">,
diff --git a/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h b/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h
index 4c11a675af..ac30836561 100644
--- a/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h
+++ b/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h
@@ -149,7 +149,6 @@ public:
unsigned visualizeExplodedGraphWithGraphViz : 1;
unsigned visualizeExplodedGraphWithUbiGraph : 1;
unsigned UnoptimizedCFG : 1;
- unsigned eagerlyTrimExplodedGraph : 1;
unsigned PrintStats : 1;
/// \brief Do not re-analyze paths leading to exhausted nodes with a different
@@ -188,6 +187,9 @@ private:
/// \sa shouldPruneNullReturnPaths
llvm::Optional<bool> PruneNullReturnPaths;
+ /// \sa getGraphTrimInterval
+ llvm::Optional<unsigned> GraphTrimInterval;
+
/// Interprets an option's string value as a boolean.
///
/// Accepts the strings "true" and "false".
@@ -253,6 +255,13 @@ public:
/// for well-known functions.
bool shouldSynthesizeBodies();
+ /// Returns how often nodes in the ExplodedGraph should be recycled to save
+ /// memory.
+ ///
+ /// This is controlled by the 'graph-trim-interval' config option. To disable
+ /// node reclamation, set the option to "0".
+ unsigned getGraphTrimInterval();
+
public:
AnalyzerOptions() : CXXMemberInliningMode() {
AnalysisStoreOpt = RegionStoreModel;
@@ -269,7 +278,6 @@ public:
visualizeExplodedGraphWithGraphViz = 0;
visualizeExplodedGraphWithUbiGraph = 0;
UnoptimizedCFG = 0;
- eagerlyTrimExplodedGraph = 0;
PrintStats = 0;
NoRetryExhausted = 0;
// Cap the stack depth at 4 calls (5 stack frames, base + 4 calls).
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h
index 5ce219b4ed..b112e66d30 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h
@@ -282,11 +282,13 @@ protected:
/// A list of nodes that can be reused.
NodeVector FreeNodes;
- /// A flag that indicates whether nodes should be recycled.
- bool reclaimNodes;
+ /// Determines how often nodes are reclaimed.
+ ///
+ /// If this is 0, nodes will never be reclaimed.
+ unsigned ReclaimNodeInterval;
/// Counter to determine when to reclaim nodes.
- unsigned reclaimCounter;
+ unsigned ReclaimCounter;
public:
@@ -374,7 +376,9 @@ public:
/// Enable tracking of recently allocated nodes for potential reclamation
/// when calling reclaimRecentlyAllocatedNodes().
- void enableNodeReclamation() { reclaimNodes = true; }
+ void enableNodeReclamation(unsigned Interval) {
+ ReclaimCounter = ReclaimNodeInterval = Interval;
+ }
/// Reclaim "uninteresting" nodes created since the last time this method
/// was called.
diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp
index ae11805a0e..aad63b6de3 100644
--- a/lib/Frontend/CompilerInvocation.cpp
+++ b/lib/Frontend/CompilerInvocation.cpp
@@ -1138,7 +1138,6 @@ static bool ParseAnalyzerArgs(AnalyzerOptions &Opts, ArgList &Args,
Opts.TrimGraph = Args.hasArg(OPT_trim_egraph);
Opts.MaxNodes = Args.getLastArgIntValue(OPT_analyzer_max_nodes, 150000,Diags);
Opts.maxBlockVisitOnPath = Args.getLastArgIntValue(OPT_analyzer_max_loop, 4, Diags);
- Opts.eagerlyTrimExplodedGraph = !Args.hasArg(OPT_analyzer_no_eagerly_trim_egraph);
Opts.PrintStats = Args.hasArg(OPT_analyzer_stats);
Opts.InlineMaxStackDepth =
Args.getLastArgIntValue(OPT_analyzer_inline_max_stack_depth,
diff --git a/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp b/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp
index e2b7cfc521..32073d726d 100644
--- a/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp
+++ b/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp
@@ -121,6 +121,12 @@ unsigned AnalyzerOptions::getAlwaysInlineSize() {
return AlwaysInlineSize.getValue();
}
+unsigned AnalyzerOptions::getGraphTrimInterval() {
+ if (!GraphTrimInterval.hasValue())
+ GraphTrimInterval = getOptionAsInteger("graph-trim-interval", 1000);
+ return GraphTrimInterval.getValue();
+}
+
bool AnalyzerOptions::shouldSynthesizeBodies() {
return getBooleanOption("faux-bodies", true);
}
diff --git a/lib/StaticAnalyzer/Core/ExplodedGraph.cpp b/lib/StaticAnalyzer/Core/ExplodedGraph.cpp
index 39440ccc0a..9b70d6861c 100644
--- a/lib/StaticAnalyzer/Core/ExplodedGraph.cpp
+++ b/lib/StaticAnalyzer/Core/ExplodedGraph.cpp
@@ -47,10 +47,8 @@ void ExplodedNode::SetAuditor(ExplodedNode::Auditor* A) {
// Cleanup.
//===----------------------------------------------------------------------===//
-static const unsigned CounterTop = 1000;
-
ExplodedGraph::ExplodedGraph()
- : NumNodes(0), reclaimNodes(false), reclaimCounter(CounterTop) {}
+ : NumNodes(0), ReclaimNodeInterval(0) {}
ExplodedGraph::~ExplodedGraph() {}
@@ -144,13 +142,13 @@ void ExplodedGraph::reclaimRecentlyAllocatedNodes() {
if (ChangedNodes.empty())
return;
- // Only periodically relcaim nodes so that we can build up a set of
+ // Only periodically reclaim nodes so that we can build up a set of
// nodes that meet the reclamation criteria. Freshly created nodes
// by definition have no successor, and thus cannot be reclaimed (see below).
- assert(reclaimCounter > 0);
- if (--reclaimCounter != 0)
+ assert(ReclaimCounter > 0);
+ if (--ReclaimCounter != 0)
return;
- reclaimCounter = CounterTop;
+ ReclaimCounter = ReclaimNodeInterval;
for (NodeVector::iterator it = ChangedNodes.begin(), et = ChangedNodes.end();
it != et; ++it) {
@@ -284,7 +282,7 @@ ExplodedNode *ExplodedGraph::getNode(const ProgramPoint &L,
new (V) NodeTy(L, State, IsSink);
- if (reclaimNodes)
+ if (ReclaimNodeInterval)
ChangedNodes.push_back(V);
// Insert the node into the node set and return it.
diff --git a/lib/StaticAnalyzer/Core/ExprEngine.cpp b/lib/StaticAnalyzer/Core/ExprEngine.cpp
index 213ab7ad5c..08f8405c4b 100644
--- a/lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ b/lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -72,10 +72,11 @@ ExprEngine::ExprEngine(AnalysisManager &mgr, bool gcEnabled,
ObjCGCEnabled(gcEnabled), BR(mgr, *this),
VisitedCallees(VisitedCalleesIn)
{
- if (mgr.options.eagerlyTrimExplodedGraph) {
- // Enable eager node reclaimation when constructing the ExplodedGraph.
- G.enableNodeReclamation();
- }
+ unsigned TrimInterval = mgr.options.getGraphTrimInterval();
+ if (TrimInterval != 0) {
+ // Enable eager node reclaimation when constructing the ExplodedGraph.
+ G.enableNodeReclamation(TrimInterval);
+ }
}
ExprEngine::~ExprEngine() {
diff --git a/test/Analysis/analyzer-config.c b/test/Analysis/analyzer-config.c
index e9cfd0d3e6..990f5784b4 100644
--- a/test/Analysis/analyzer-config.c
+++ b/test/Analysis/analyzer-config.c
@@ -7,6 +7,7 @@ void foo() { bar(); }
// CHECK: [config]
// CHECK-NEXT: cfg-temporary-dtors = false
// CHECK-NEXT: faux-bodies = true
+// CHECK-NEXT: graph-trim-interval = 1000
// CHECK-NEXT: ipa-always-inline-size = 3
// CHECK-NEXT: [stats]
-// CHECK-NEXT: num-entries = 3
+// CHECK-NEXT: num-entries = 4
diff --git a/test/Analysis/analyzer-config.cpp b/test/Analysis/analyzer-config.cpp
index 414324e8bc..fb142669b4 100644
--- a/test/Analysis/analyzer-config.cpp
+++ b/test/Analysis/analyzer-config.cpp
@@ -16,6 +16,7 @@ public:
// CHECK-NEXT: c++-template-inlining = true
// CHECK-NEXT: cfg-temporary-dtors = false
// CHECK-NEXT: faux-bodies = true
+// CHECK-NEXT: graph-trim-interval = 1000
// CHECK-NEXT: ipa-always-inline-size = 3
// CHECK-NEXT: [stats]
-// CHECK-NEXT: num-entries = 6
+// CHECK-NEXT: num-entries = 7