зеркало из https://github.com/microsoft/clang-1.git
[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:
Родитель
f4c3db1751
Коммит
8235f9c9c8
|
@ -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"
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче