r174245 - [analyzer] Always inline functions with bodies generated by BodyFarm.
Jordan Rose
jordan_rose at apple.com
Fri Feb 1 16:57:37 PST 2013
On Feb 1, 2013, at 16:30 , Anna Zaks <ganna at apple.com> wrote:
> Author: zaks
> Date: Fri Feb 1 18:30:04 2013
> New Revision: 174245
>
> URL: http://llvm.org/viewvc/llvm-project?rev=174245&view=rev
> Log:
> [analyzer] Always inline functions with bodies generated by BodyFarm.
>
> Inlining these functions is essential for correctness. We often have
> cases where we do not inline calls. For example, the shallow mode and
> when reanalyzing previously inlined ObjC methods as top level.
>
> Modified:
> cfe/trunk/include/clang/Analysis/AnalysisContext.h
> cfe/trunk/lib/Analysis/AnalysisDeclContext.cpp
> cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
> cfe/trunk/test/Analysis/NSString.m
>
> Modified: cfe/trunk/include/clang/Analysis/AnalysisContext.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/AnalysisContext.h?rev=174245&r1=174244&r2=174245&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/Analysis/AnalysisContext.h (original)
> +++ cfe/trunk/include/clang/Analysis/AnalysisContext.h Fri Feb 1 18:30:04 2013
> @@ -133,7 +133,21 @@ public:
> void registerForcedBlockExpression(const Stmt *stmt);
> const CFGBlock *getBlockForRegisteredExpression(const Stmt *stmt);
>
> + /// \brief Get the body of the Declaration.
> Stmt *getBody() const;
> +
> + /// \brief Get the body of the Declaration.
> + /// \param IsAutosynthesized Output parameter that specifies if the body is
> + /// auto-generated by the BodyFarm.
Nitpick: you can specify output parameters in Doxygen with \param[out].
> + Stmt *getBody(bool &IsAutosynthesized) const;
> +
> + /// \brief Checks if the body of the Decl is generated by the BodyFarm.
> + ///
> + /// Note, the lookup is not free. We are going to call getBody behind
> + /// the sceines.
Typo: "sceines"
> + /// \sa getBody
> + bool isBodyAutosynthesized() const;
> +
> CFG *getCFG();
>
> CFGStmtMap *getCFGStmtMap();
>
> Modified: cfe/trunk/lib/Analysis/AnalysisDeclContext.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/AnalysisDeclContext.cpp?rev=174245&r1=174244&r2=174245&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Analysis/AnalysisDeclContext.cpp (original)
> +++ cfe/trunk/lib/Analysis/AnalysisDeclContext.cpp Fri Feb 1 18:30:04 2013
> @@ -86,11 +86,13 @@ static BodyFarm &getBodyFarm(ASTContext
> return *BF;
> }
>
> -Stmt *AnalysisDeclContext::getBody() const {
> +Stmt *AnalysisDeclContext::getBody(bool &IsAutosynthesized) const {
> if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
> Stmt *Body = FD->getBody();
> - if (!Body && Manager && Manager->synthesizeBodies())
> + if (!Body && Manager && Manager->synthesizeBodies()) {
> + IsAutosynthesized = true;
> return getBodyFarm(getASTContext()).getBody(FD);
> + }
> return Body;
> }
> else if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D))
> @@ -104,6 +106,17 @@ Stmt *AnalysisDeclContext::getBody() con
> llvm_unreachable("unknown code decl");
> }
>
> +Stmt *AnalysisDeclContext::getBody() const {
> + bool Tmp;
> + return getBody(Tmp);
> +}
> +
> +bool AnalysisDeclContext::isBodyAutosynthesized() const {
> + bool Tmp;
> + getBody(Tmp);
> + return Tmp;
> +}
> +
> const ImplicitParamDecl *AnalysisDeclContext::getSelfDecl() const {
> if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D))
> return MD->getSelfDecl();
>
> Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp?rev=174245&r1=174244&r2=174245&view=diff
> ==============================================================================
> --- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp (original)
> +++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp Fri Feb 1 18:30:04 2013
> @@ -733,13 +733,27 @@ void ExprEngine::conservativeEvalCall(co
> Bldr.generateNode(Call.getProgramPoint(), State, Pred);
> }
>
> +static bool isEssentialToInline(const CallEvent &Call) {
> + const Decl *D = Call.getDecl();
> + if (D) {
> + AnalysisDeclContext *AD =
> + Call.getLocationContext()->getAnalysisDeclContext()->
> + getManager()->getContext(D);
> +
> + // The auto-synthesized bodies are essential to inline as they are
> + // usually small and commonly used.
> + return AD->isBodyAutosynthesized();
> + }
> + return false;
> +}
> +
> void ExprEngine::defaultEvalCall(NodeBuilder &Bldr, ExplodedNode *Pred,
> const CallEvent &CallTemplate) {
> // Make sure we have the most recent state attached to the call.
> ProgramStateRef State = Pred->getState();
> CallEventRef<> Call = CallTemplate.cloneWithState(State);
>
> - if (HowToInline == Inline_None) {
> + if (HowToInline == Inline_None && !isEssentialToInline(CallTemplate)) {
> conservativeEvalCall(*Call, Bldr, Pred, State);
> return;
> }
>
> Modified: cfe/trunk/test/Analysis/NSString.m
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/NSString.m?rev=174245&r1=174244&r2=174245&view=diff
> ==============================================================================
> --- cfe/trunk/test/Analysis/NSString.m (original)
> +++ cfe/trunk/test/Analysis/NSString.m Fri Feb 1 18:30:04 2013
> @@ -404,3 +404,27 @@ void testOSCompareAndSwapXXBarrier_param
> else
> return;
> }
> +
> + at interface AlwaysInlineBodyFarmBodies : NSObject {
> + NSString *_value;
> +}
> + - (NSString *)_value;
> + - (void)callValue;
> + at end
> +
> + at implementation AlwaysInlineBodyFarmBodies
> +
> +- (NSString *)_value {
> + if (!_value) {
> + NSString *s = [[NSString alloc] init];
> + if (!OSAtomicCompareAndSwapPtr(0, s, (void**)&_value)) {
> + [s release];
> + }
> + }
> + return _value;
> +}
> +
> +- (void)callValue {
> + [self _value];
> +}
> + at end
It would be nice to have a note here that this is only testing the feature because of the re-analyzing behavior for Objective-C methods. Alternately, maybe the test should be moved to an explicit no-inlining file…except that we probably have a control higher up that will stop inlining altogether in this case.
Jordan
More information about the cfe-commits
mailing list