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/Scope.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/Scope.cpp')
-rw-r--r-- | clang/lib/Sema/Scope.cpp | 24 |
1 files changed, 7 insertions, 17 deletions
diff --git a/clang/lib/Sema/Scope.cpp b/clang/lib/Sema/Scope.cpp index eae5a328bfa..5a46ba26d29 100644 --- a/clang/lib/Sema/Scope.cpp +++ b/clang/lib/Sema/Scope.cpp @@ -92,7 +92,6 @@ void Scope::Init(Scope *parent, unsigned flags) { UsingDirectives.clear(); Entity = nullptr; ErrorTrap.reset(); - NRVO.setPointerAndInt(nullptr, 0); } bool Scope::containedInPrototypeScope() const { @@ -119,19 +118,15 @@ void Scope::AddFlags(unsigned FlagsToSet) { Flags |= FlagsToSet; } -void Scope::mergeNRVOIntoParent() { - if (VarDecl *Candidate = NRVO.getPointer()) { - if (isDeclScope(Candidate)) - Candidate->setNRVOVariable(true); +void Scope::setNRVOCandidate(VarDecl *Candidate) { + for (Decl *D : DeclsInScope) { + VarDecl *VD = dyn_cast<VarDecl>(D); + if (VD && VD != Candidate && VD->isNRVOCandidate()) + VD->setNRVOVariable(false); } - if (getEntity()) - return; - - if (NRVO.getInt()) - getParent()->setNoNRVO(); - else if (NRVO.getPointer()) - getParent()->addNRVOCandidate(NRVO.getPointer()); + if (Scope *parent = getParent()) + parent->setNRVOCandidate(Candidate); } LLVM_DUMP_METHOD void Scope::dump() const { dumpImpl(llvm::errs()); } @@ -191,9 +186,4 @@ void Scope::dumpImpl(raw_ostream &OS) const { OS << "MSCurManglingNumber: " << getMSCurManglingNumber() << '\n'; if (const DeclContext *DC = getEntity()) OS << "Entity : (clang::DeclContext*)" << DC << '\n'; - - if (NRVO.getInt()) - OS << "NRVO not allowed\n"; - else if (NRVO.getPointer()) - OS << "NRVO candidate : (clang::VarDecl*)" << NRVO.getPointer() << '\n'; } |