mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-12-11 17:08:42 +00:00
[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. llvm-svn: 166528
This commit is contained in:
parent
a96da4773c
commit
746c06d0bc
@ -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">,
|
||||
|
@ -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).
|
||||
|
@ -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.
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -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() {
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user