From: Jordan Rose Date: Tue, 23 Oct 2012 23:59:05 +0000 (+0000) Subject: [analyzer] Replace -analyzer-no-eagerly-trim-egraph with graph-trim-interval. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=4d9e497a2b1eab3b1214848216050c64fc3acfd6;p=clang [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 --- 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; 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 PruneNullReturnPaths; + /// \sa getGraphTrimInterval + llvm::Optional 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