diff options
| author | Taiju Tsuiki <tzik@google.com> | 2018-05-30 03:53:16 +0000 |
|---|---|---|
| committer | Taiju Tsuiki <tzik@google.com> | 2018-05-30 03:53:16 +0000 |
| commit | 44f9c585b94ed9f15bd64f6c2fc32bbd397ff4af (patch) | |
| tree | d837c1d976e080268135c1304ca5985510362ee0 /clang/lib/Sema/SemaDecl.cpp | |
| parent | e9ce661e3294dd5581d0d124e69d191112e24776 (diff) | |
| download | bcm5719-llvm-44f9c585b94ed9f15bd64f6c2fc32bbd397ff4af.tar.gz bcm5719-llvm-44f9c585b94ed9f15bd64f6c2fc32bbd397ff4af.zip | |
Update NRVO logic to support early return
Summary:
The previous implementation misses an opportunity to apply NRVO (Named Return Value
Optimization) below. That discourages user to write early return code.
```
struct Foo {};
Foo f(bool b) {
if (b)
return Foo();
Foo oo;
return oo;
}
```
That is, we can/should apply RVO for a local variable if:
* It's directly returned by at least one return statement.
* And, all reachable return statements in its scope returns the variable directly.
While, the previous implementation disables the RVO in a scope if there are multiple return
statements that refers different variables.
On the new algorithm, local variables are in NRVO_Candidate state at first, and a return
statement changes it to NRVO_Disabled for all visible variables but the return statement refers.
Then, at the end of the function AST traversal, NRVO is enabled for variables in NRVO_Candidate
state and refers from at least one return statement.
Reviewers: rsmith
Reviewed By: rsmith
Subscribers: xbolva00, Quuxplusone, arthur.j.odwyer, cfe-commits
Differential Revision: https://reviews.llvm.org/D47067
llvm-svn: 333500
Diffstat (limited to 'clang/lib/Sema/SemaDecl.cpp')
| -rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 33 |
1 files changed, 15 insertions, 18 deletions
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 9a6a286db78..e0be9efe966 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -1798,8 +1798,6 @@ static void CheckPoppedLabel(LabelDecl *L, Sema &S) { } void Sema::ActOnPopScope(SourceLocation Loc, Scope *S) { - S->mergeNRVOIntoParent(); - if (S->decl_empty()) return; assert((S->getFlags() & (Scope::DeclScope | Scope::TemplateParamScope)) && "Scope shouldn't contain decls!"); @@ -12611,21 +12609,24 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D, /// optimization. /// /// Each of the variables that is subject to the named return value -/// optimization will be marked as NRVO variables in the AST, and any +/// optimization will be marked as NRVO variable candidates in the AST, and any /// return statement that has a marked NRVO variable as its NRVO candidate can /// use the named return value optimization. /// -/// This function applies a very simplistic algorithm for NRVO: if every return -/// statement in the scope of a variable has the same NRVO candidate, that -/// candidate is an NRVO variable. +/// This function applies a very simplistic algorithm for NRVO: if every +/// reachable return statement in the scope of a variable has the same NRVO +/// candidate, that candidate is an NRVO variable. void Sema::computeNRVO(Stmt *Body, FunctionScopeInfo *Scope) { - ReturnStmt **Returns = Scope->Returns.data(); + for (ReturnStmt *Return : Scope->Returns) { + const VarDecl *Candidate = Return->getNRVOCandidate(); + if (!Candidate) + continue; - for (unsigned I = 0, E = Scope->Returns.size(); I != E; ++I) { - if (const VarDecl *NRVOCandidate = Returns[I]->getNRVOCandidate()) { - if (!NRVOCandidate->isNRVOVariable()) - Returns[I]->setNRVOCandidate(nullptr); - } + if (Candidate->isNRVOCandidate()) + const_cast<VarDecl*>(Candidate)->setNRVOVariable(true); + + if (!Candidate->isNRVOVariable()) + Return->setNRVOCandidate(nullptr); } } @@ -12754,12 +12755,8 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body, else if (CXXDestructorDecl *Destructor = dyn_cast<CXXDestructorDecl>(FD)) MarkVTableUsed(FD->getLocation(), Destructor->getParent()); - // Try to apply the named return value optimization. We have to check - // if we can do this here because lambdas keep return statements around - // to deduce an implicit return type. - if (FD->getReturnType()->isRecordType() && - (!getLangOpts().CPlusPlus || !FD->isDependentContext())) - computeNRVO(Body, getCurFunction()); + // Try to apply the named return value optimization. + computeNRVO(Body, getCurFunction()); } // GNU warning -Wmissing-prototypes: |

