[analyzer] Bound the size of the functions being inlined + provide

command line options for inlining tuning.

This adds the option for stack depth bound as well as function size
bound. 

+ minor doxygenification

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@151930 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Anna Zaks 2012-03-02 19:05:03 +00:00
Родитель f4c3db1751
Коммит 8235f9c9c8
8 изменённых файлов: 60 добавлений и 21 удалений

Просмотреть файл

@ -81,7 +81,11 @@ def analyzer_viz_egraph_graphviz : Flag<"-analyzer-viz-egraph-graphviz">,
def analyzer_viz_egraph_ubigraph : Flag<"-analyzer-viz-egraph-ubigraph">,
HelpText<"Display exploded graph using Ubigraph">;
def analyzer_inline_call : Flag<"-analyzer-inline-call">,
HelpText<"Experimental transfer function inlining callees when its definition is available.">;
HelpText<"Experimental: Inline callees when their definitions are available">;
def analyzer_inline_max_stack_depth : Separate<"-analyzer-inline-max-stack-depth">,
HelpText<"Bound on stack depth while inlining (4 by default)">;
def analyzer_inline_max_function_size : Separate<"-analyzer-inline-max-function-size">,
HelpText<"Bound on the number of basic blocks in an inlined function (10 by default)">;
def analyzer_max_nodes : Separate<"-analyzer-max-nodes">,
HelpText<"The maximum number of nodes the analyzer can generate (150000 default, 0 = no limit)">;
def analyzer_max_loop : Separate<"-analyzer-max-loop">,

Просмотреть файл

@ -85,6 +85,8 @@ public:
unsigned CFGAddInitializers : 1;
unsigned EagerlyTrimEGraph : 1;
unsigned PrintStats : 1;
unsigned InlineMaxStackDepth;
unsigned InlineMaxFunctionSize;
public:
AnalyzerOptions() {
@ -106,6 +108,9 @@ public:
CFGAddInitializers = 0;
EagerlyTrimEGraph = 0;
PrintStats = 0;
// Cap the stack depth at 4 calls (5 stack frames, base + 4 calls).
InlineMaxStackDepth = 5;
InlineMaxFunctionSize = 10;
}
};

Просмотреть файл

@ -53,28 +53,39 @@ class AnalysisManager : public BugReporterData {
enum AnalysisScope { ScopeTU, ScopeDecl } AScope;
// The maximum number of exploded nodes the analyzer will generate.
/// \brief The maximum number of exploded nodes the analyzer will generate.
unsigned MaxNodes;
// The maximum number of times the analyzer visit a block.
/// \brief The maximum number of times the analyzer visits a block.
unsigned MaxVisit;
bool VisualizeEGDot;
bool VisualizeEGUbi;
AnalysisPurgeMode PurgeDead;
/// EargerlyAssume - A flag indicating how the engine should handle
// expressions such as: 'x = (y != 0)'. When this flag is true then
// the subexpression 'y != 0' will be eagerly assumed to be true or false,
// thus evaluating it to the integers 0 or 1 respectively. The upside
// is that this can increase analysis precision until we have a better way
// to lazily evaluate such logic. The downside is that it eagerly
// bifurcates paths.
/// \brief The flag regulates if we should eagerly assume evaluations of
/// conditionals, thus, bifurcating the path.
///
/// EagerlyAssume - A flag indicating how the engine should handle
/// expressions such as: 'x = (y != 0)'. When this flag is true then
/// the subexpression 'y != 0' will be eagerly assumed to be true or false,
/// thus evaluating it to the integers 0 or 1 respectively. The upside
/// is that this can increase analysis precision until we have a better way
/// to lazily evaluate such logic. The downside is that it eagerly
/// bifurcates paths.
bool EagerlyAssume;
bool TrimGraph;
bool InlineCall;
bool EagerlyTrimEGraph;
public:
// Settings for inlining tuning.
/// \brief The inlining stack depth limit.
unsigned InlineMaxStackDepth;
/// \brief The max number of basic blocks in a function being inlined.
unsigned InlineMaxFunctionSize;
public:
AnalysisManager(ASTContext &ctx, DiagnosticsEngine &diags,
const LangOptions &lang, PathDiagnosticConsumer *pd,
@ -87,7 +98,9 @@ public:
bool eager, bool trim,
bool inlinecall, bool useUnoptimizedCFG,
bool addImplicitDtors, bool addInitializers,
bool eagerlyTrimEGraph);
bool eagerlyTrimEGraph,
unsigned inlineMaxStack,
unsigned inlineMaxFunctionSize);
/// Construct a clone of the given AnalysisManager with the given ASTContext
/// and DiagnosticsEngine.

Просмотреть файл

@ -1047,6 +1047,12 @@ static bool ParseAnalyzerArgs(AnalyzerOptions &Opts, ArgList &Args,
if (Args.hasArg(OPT_analyzer_inline_call))
Opts.InlineCall = 1;
Opts.PrintStats = Args.hasArg(OPT_analyzer_stats);
Opts.InlineMaxStackDepth =
Args.getLastArgIntValue(OPT_analyzer_inline_max_stack_depth,
Opts.InlineMaxStackDepth, Diags);
Opts.InlineMaxFunctionSize =
Args.getLastArgIntValue(OPT_analyzer_inline_max_function_size,
Opts.InlineMaxFunctionSize, Diags);
Opts.CheckersControlList.clear();
for (arg_iterator it = Args.filtered_begin(OPT_analyzer_checker,

Просмотреть файл

@ -29,7 +29,9 @@ AnalysisManager::AnalysisManager(ASTContext &ctx, DiagnosticsEngine &diags,
bool eager, bool trim,
bool inlinecall, bool useUnoptimizedCFG,
bool addImplicitDtors, bool addInitializers,
bool eagerlyTrimEGraph)
bool eagerlyTrimEGraph,
unsigned inlineMaxStack,
unsigned inlineMaxFunctionSize)
: AnaCtxMgr(useUnoptimizedCFG, addImplicitDtors, addInitializers),
Ctx(ctx), Diags(diags), LangInfo(lang), PD(pd),
CreateStoreMgr(storemgr), CreateConstraintMgr(constraintmgr),
@ -37,7 +39,9 @@ AnalysisManager::AnalysisManager(ASTContext &ctx, DiagnosticsEngine &diags,
AScope(ScopeDecl), MaxNodes(maxnodes), MaxVisit(maxvisit),
VisualizeEGDot(vizdot), VisualizeEGUbi(vizubi), PurgeDead(purge),
EagerlyAssume(eager), TrimGraph(trim), InlineCall(inlinecall),
EagerlyTrimEGraph(eagerlyTrimEGraph)
EagerlyTrimEGraph(eagerlyTrimEGraph),
InlineMaxStackDepth(inlineMaxStack),
InlineMaxFunctionSize(inlineMaxFunctionSize)
{
AnaCtxMgr.getCFGBuildOptions().setAllAlwaysAdd();
}
@ -62,7 +66,9 @@ AnalysisManager::AnalysisManager(ASTContext &ctx, DiagnosticsEngine &diags,
EagerlyAssume(ParentAM.EagerlyAssume),
TrimGraph(ParentAM.TrimGraph),
InlineCall(ParentAM.InlineCall),
EagerlyTrimEGraph(ParentAM.EagerlyTrimEGraph)
EagerlyTrimEGraph(ParentAM.EagerlyTrimEGraph),
InlineMaxStackDepth(ParentAM.InlineMaxStackDepth),
InlineMaxFunctionSize(ParentAM.InlineMaxFunctionSize)
{
AnaCtxMgr.getCFGBuildOptions().setAllAlwaysAdd();
}

Просмотреть файл

@ -142,13 +142,16 @@ bool ExprEngine::InlineCall(ExplodedNodeSet &Dst,
// FIXME: Handle C++.
break;
case Stmt::CallExprClass: {
// Cap the stack depth at 4 calls (5 stack frames, base + 4 calls).
// These heuristics are a WIP.
if (getNumberStackFrames(Pred->getLocationContext()) == 5)
if (getNumberStackFrames(Pred->getLocationContext())
== AMgr.InlineMaxStackDepth)
return false;
// Construct a new stack frame for the callee.
AnalysisDeclContext *CalleeADC = AMgr.getAnalysisDeclContext(FD);
const CFG *CalleeCFG = CalleeADC->getCFG();
if (CalleeCFG->getNumBlockIDs() > AMgr.InlineMaxFunctionSize)
return false;
// Construct a new stack frame for the callee.
const StackFrameContext *CallerSFC =
Pred->getLocationContext()->getCurrentStackFrame();
const StackFrameContext *CalleeSFC =

Просмотреть файл

@ -157,7 +157,9 @@ public:
Opts.TrimGraph, Opts.InlineCall,
Opts.UnoptimizedCFG, Opts.CFGAddImplicitDtors,
Opts.CFGAddInitializers,
Opts.EagerlyTrimEGraph));
Opts.EagerlyTrimEGraph,
Opts.InlineMaxStackDepth,
Opts.InlineMaxFunctionSize));
if (Opts.PrintStats)
llvm::EnableStatistics();
}

Просмотреть файл

@ -1,4 +1,4 @@
// RUN: %clang_cc1 -analyze -analyzer-checker=unix.Malloc -analyzer-inline-call -analyzer-store=region -verify %s
// RUN: %clang_cc1 -analyze -analyzer-checker=unix.Malloc -analyzer-inline-call -analyzer-inline-max-stack-depth 5 -analyzer-inline-max-function-size 6 -analyzer-store=region -verify %s
#include "system-header-simulator.h"