summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema/SemaDecl.cpp
diff options
context:
space:
mode:
authorTaiju Tsuiki <tzik@google.com>2018-05-30 03:53:16 +0000
committerTaiju Tsuiki <tzik@google.com>2018-05-30 03:53:16 +0000
commit44f9c585b94ed9f15bd64f6c2fc32bbd397ff4af (patch)
treed837c1d976e080268135c1304ca5985510362ee0 /clang/lib/Sema/SemaDecl.cpp
parente9ce661e3294dd5581d0d124e69d191112e24776 (diff)
downloadbcm5719-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.cpp33
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:
OpenPOWER on IntegriCloud