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 | 91f75751594865638d42325edebf781bbb6c8293 (patch) | |
tree | f173eff5604e3e5989737ef8dbc12794e2e1a9ef /test/CodeGenCXX/nrvo.cpp | |
parent | 7a3b3665c7782ff7a4a7468a60201227587b4774 (diff) |
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
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@333500 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'test/CodeGenCXX/nrvo.cpp')
-rw-r--r-- | test/CodeGenCXX/nrvo.cpp | 51 |
1 files changed, 44 insertions, 7 deletions
diff --git a/test/CodeGenCXX/nrvo.cpp b/test/CodeGenCXX/nrvo.cpp index 0f359b9c90..1da4308e26 100644 --- a/test/CodeGenCXX/nrvo.cpp +++ b/test/CodeGenCXX/nrvo.cpp @@ -130,17 +130,13 @@ X test2(bool B) { } // CHECK-LABEL: define void @_Z5test3b -X test3(bool B) { +X test3(bool B, X x) { // CHECK: tail call {{.*}} @_ZN1XC1Ev - // CHECK-NOT: call {{.*}} @_ZN1XC1ERKS_ - // CHECK: call {{.*}} @_ZN1XC1Ev - // CHECK: call {{.*}} @_ZN1XC1ERKS_ if (B) { X y; return y; } - // FIXME: we should NRVO this variable too. - X x; + // CHECK: tail call {{.*}} @_ZN1XC1ERKS_ return x; } @@ -191,9 +187,13 @@ X test6() { } // CHECK-LABEL: define void @_Z5test7b +// CHECK-EH-LABEL: define void @_Z5test7b X test7(bool b) { // CHECK: tail call {{.*}} @_ZN1XC1Ev // CHECK-NEXT: ret + + // CHECK-EH: tail call {{.*}} @_ZN1XC1Ev + // CHECK-EH-NEXT: ret if (b) { X x; return x; @@ -202,10 +202,14 @@ X test7(bool b) { } // CHECK-LABEL: define void @_Z5test8b +// CHECK-EH-LABEL: define void @_Z5test8b X test8(bool b) { // CHECK: tail call {{.*}} @_ZN1XC1Ev // CHECK-NEXT: ret - if (b) { + + // CHECK-EH: tail call {{.*}} @_ZN1XC1Ev + // CHECK-EH-NEXT: ret +if (b) { X x; return x; } else { @@ -221,4 +225,37 @@ Y<int> test9() { // CHECK-LABEL: define linkonce_odr void @_ZN1YIiE1fEv // CHECK: tail call {{.*}} @_ZN1YIiEC1Ev +// CHECK-LABEL: define void @_Z6test10b +X test10(bool B, X x) { + if (B) { + // CHECK: tail call {{.*}} @_ZN1XC1ERKS_ + // CHECK-EH: tail call {{.*}} @_ZN1XC1ERKS_ + return x; + } + // CHECK: tail call {{.*}} @_ZN1XC1Ev + // CHECK-NOT: call {{.*}} @_ZN1XC1ERKS_ + + // CHECK-EH: tail call {{.*}} @_ZN1XC1Ev + // CHECK-EH-NOT: call {{.*}} @_ZN1XC1ERKS_ + X y; + return y; +} + +// CHECK-LABEL: define {{.*}} void @_Z6test11I1XET_v +// CHECK-EH-LABEL: define {{.*}} void @_Z6test11I1XET_v +template <typename T> +T test11() { + // CHECK: tail call {{.*}} @_ZN1XC1Ev + // CHECK-NEXT: ret void + + // CHECK-EH: tail call {{.*}} @_ZN1XC1Ev + // CHECK-EH-NEXT: ret void + T t; + return t; +} + +void test12() { + test11<X>(); +} + // CHECK-EH-03: attributes [[NR_NUW]] = { noreturn nounwind } |