r175857 - [analyzer] Place all inlining policy checks into one palce

Jordan Rose jordan_rose at apple.com
Fri Feb 22 09:25:53 PST 2013


YAY. I could not figure out how to do this, especially with the block part.

A few comments.


On Feb 21, 2013, at 18:59 , Anna Zaks <ganna at apple.com> wrote:

> Author: zaks
> Date: Thu Feb 21 20:59:24 2013
> New Revision: 175857
> 
> URL: http://llvm.org/viewvc/llvm-project?rev=175857&view=rev
> Log:
> [analyzer] Place all inlining policy checks into one palce
> 
> Previously, we had the decisions about inlining spread out
> over multiple functions.
> 
> In addition to the refactor, this commit ensures
> that we will always inline BodyFarm functions as long as the Decl
> is available. This fixes false positives due to those functions
> not being inlined when no or minimal inlining is enabled such (as
> shallow mode).
> 
> Modified:
>    cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
>    cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
>    cfe/trunk/test/Analysis/NSString.m
> 

> +  const LocationContext *ParentOfCallee = CallerSFC;
> +  if (Call.getKind() == CE_Block) {
>     const BlockDataRegion *BR = cast<BlockCall>(Call).getBlockRegion();

This should probably just use dyn_cast now -- more idiomatic.


> +static bool shouldInlineCallKind(const CallEvent &Call,
> +                                      const ExplodedNode *Pred,
> +                                      AnalyzerOptions &Opts) {

Indentation is wrong.


> +bool ExprEngine::shouldInlineCall(const CallEvent &Call, const Decl *D,
> +                                  const ExplodedNode *Pred) {
> +  if (!D )
> +    return false;

Extra space?


> +  AnalyzerOptions &Opts = getAnalysisManager().options;
> +  AnalysisDeclContext *CalleeADC =
> +    Call.getLocationContext()->getAnalysisDeclContext()->
> +    getManager()->getContext(D);

AnalysisManager &AMgr = getAnalysisManager();
AnalyzerOptions &Opts = AMgr.options;
AnalysisDeclContextManager &ADCMgr = AMgr.getAnalysisDeclContextManager();

AnalysisDeclContext *CalleeADC = ADCMgr.getContext(D);


> +  // The auto-synthesized bodies are essential to inline as they are
> +  // usually small and commonly used. note, we should do this check early on to
> +  // ensure we always inline these calls.

Capitalization. (Also, conventionally a colon instead of a comma after "Note".)


> +  if (CalleeADC->isBodyAutosynthesized())
> +    return true;
> +
> +  if (HowToInline == Inline_None)
> +    return false;
> +
> +  // Check if we should inline a call based on it's kind.

s/it's/its/


> +  if (!shouldInlineCallKind(Call, Pred, Opts))
> +    return false;
> +
> +  // It is possible that the CFG cannot be constructed.
> +  // Be safe, and check if the CalleeCFG is valid.
> +  const CFG *CalleeCFG = CalleeADC->getCFG();
> +  if (!CalleeCFG)
> +    return false;
> +
> +  // Do not inline if recursive or we've reached max stack frame count.
> +  bool IsRecursive = false;
> +  unsigned StackDepth = 0;
> +  examineStackFrames(D, Pred->getLocationContext(), IsRecursive, StackDepth);
> +  if ((StackDepth >= Opts.InlineMaxStackDepth) &&
> +      ((CalleeCFG->getNumBlockIDs() > Opts.getAlwaysInlineSize())
> +       || IsRecursive))
> +    return false;
> +
> +  // Do not inline if it took too long to inline previously.
> +  if (Engine.FunctionSummaries->hasReachedMaxBlockCount(D))
> +    return false;
> +
> +  // Or if the function is too big.
> +  if (CalleeCFG->getNumBlockIDs() > Opts.getMaxInlinableSize())
> +    return false;
> +
> +  // Do not inline variadic calls (for now).
> +  if (const BlockDecl *BD = dyn_cast<BlockDecl>(D)) {
> +    if (BD->isVariadic())
> +      return false;
> +  }
> +  else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
> +    if (FD->isVariadic())
> +      return false;
> +  }

Now that there's a CallEvent here, we should make a CallEvent::isVariadic, since ObjC method calls can be variadic as well.


> +  // Check our template policy.
> +  if (getContext().getLangOpts().CPlusPlus) {
> +    if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
> +      // Conditionally allow the inlining of template functions.
> +      if (!Opts.mayInlineTemplateFunctions())
> +        if (FD->getTemplatedKind() != FunctionDecl::TK_NonTemplate)
> +          return false;
> +
> +      // Conditionally allow the inlining of C++ standard library functions.
> +      if (!Opts.mayInlineCXXStandardLibrary())
> +        if (getContext().getSourceManager().isInSystemHeader(FD->getLocation()))
> +          if (IsInStdNamespace(FD))
> +            return false;
> +    }
> +  }
> +
> +  // It is possible that the live variables analysis cannot be
> +  // run.  If so, bail out.
> +  if (!CalleeADC->getAnalysis<RelaxedLiveVariables>())
> +    return false;
> +
> +  // Do not inline large functions too many times.
> +  if (Engine.FunctionSummaries->getNumTimesInlined(D) >
> +      Opts.getMaxTimesInlineLarge() &&
> +      CalleeCFG->getNumBlockIDs() > 13) {

The indentation here confused me at first; IMHO, "Opts.getMaxTimesInlineLarge()" should be extra-indented, or perhaps the comparison should be wrapped in parens. The magic number 13 is pretty bad, too...

(I realize these aren't new problems, but they're here.)





More information about the cfe-commits mailing list