summaryrefslogtreecommitdiffstats
path: root/test/CodeGenCXX/nrvo.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
commit91f75751594865638d42325edebf781bbb6c8293 (patch)
treef173eff5604e3e5989737ef8dbc12794e2e1a9ef /test/CodeGenCXX/nrvo.cpp
parent7a3b3665c7782ff7a4a7468a60201227587b4774 (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.cpp51
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 }