Clang Project

clang_source_code/test/CodeGenCXX/nrvo.cpp
1// RUN: %clang_cc1 -triple i386-unknown-unknown -emit-llvm -O1 -o - %s | FileCheck %s
2// RUN: %clang_cc1 -triple i386-unknown-unknown -emit-llvm -O1 -fcxx-exceptions -fexceptions -std=c++03 -o - %s | FileCheck --check-prefixes=CHECK-EH,CHECK-EH-03 %s
3// RUN: %clang_cc1 -triple i386-unknown-unknown -emit-llvm -O1 -fcxx-exceptions -fexceptions -std=c++11 -o - %s | FileCheck --check-prefixes=CHECK-EH,CHECK-EH-11 %s
4
5// Test code generation for the named return value optimization.
6class X {
7public:
8  X();
9  X(const X&);
10  ~X();
11};
12
13template<typename T> struct Y {
14  Y();
15  static Y f() {
16    Y y;
17    return y;
18  }
19};
20
21// CHECK-LABEL: define void @_Z5test0v
22// CHECK-EH-LABEL: define void @_Z5test0v
23X test0() {
24  X x;
25  // CHECK:          call {{.*}} @_ZN1XC1Ev
26  // CHECK-NEXT:     ret void
27
28  // CHECK-EH:       call {{.*}} @_ZN1XC1Ev
29  // CHECK-EH-NEXT:  ret void
30  return x;
31}
32
33// CHECK-LABEL: define void @_Z5test1b(
34// CHECK-EH-LABEL: define void @_Z5test1b(
35X test1(bool B) {
36  // CHECK:      tail call {{.*}} @_ZN1XC1Ev
37  // CHECK-NEXT: ret void
38  X x;
39  if (B)
40    return (x);
41  return x;
42  // CHECK-EH:      tail call {{.*}} @_ZN1XC1Ev
43  // CHECK-EH-NEXT: ret void
44}
45
46// CHECK-LABEL: define void @_Z5test2b
47// CHECK-EH-LABEL: define void @_Z5test2b
48// CHECK-EH-SAME:  personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
49X test2(bool B) {
50  // No NRVO.
51
52  X x;
53  X y;
54  if (B)
55    return y;
56  return x;
57
58  // CHECK: call {{.*}} @_ZN1XC1Ev
59  // CHECK-NEXT: {{.*}} getelementptr inbounds %class.X, %class.X* %y, i32 0, i32 0
60  // CHECK-NEXT: call void @llvm.lifetime.start
61  // CHECK-NEXT: call {{.*}} @_ZN1XC1Ev
62  // CHECK: call {{.*}} @_ZN1XC1ERKS_
63  // CHECK: call {{.*}} @_ZN1XC1ERKS_
64  // CHECK: call {{.*}} @_ZN1XD1Ev
65  // CHECK-NEXT: call void @llvm.lifetime.end
66  // CHECK: call {{.*}} @_ZN1XD1Ev
67  // CHECK-NEXT: call void @llvm.lifetime.end
68  // CHECK: ret void
69
70  // The block ordering in the -fexceptions IR is unfortunate.
71
72  // CHECK-EH:      call void @llvm.lifetime.start
73  // CHECK-EH-NEXT: call {{.*}} @_ZN1XC1Ev
74  // CHECK-EH:      call void @llvm.lifetime.start
75  // CHECK-EH-NEXT: invoke {{.*}} @_ZN1XC1Ev
76  // -> %invoke.cont, %lpad
77
78  // %invoke.cont:
79  // CHECK-EH:      br i1
80  // -> %if.then, %if.end
81
82  // %if.then: returning 'x'
83  // CHECK-EH:      invoke {{.*}} @_ZN1XC1ERKS_
84  // -> %cleanup, %lpad1
85
86  // %lpad: landing pad for ctor of 'y', dtor of 'y'
87  // CHECK-EH:      [[CAUGHTVAL:%.*]] = landingpad { i8*, i32 }
88  // CHECK-EH-NEXT:   cleanup
89  // CHECK-EH-NEXT: extractvalue { i8*, i32 } [[CAUGHTVAL]], 0
90  // CHECK-EH-NEXT: extractvalue { i8*, i32 } [[CAUGHTVAL]], 1
91  // CHECK-EH-NEXT: br label
92  // -> %eh.cleanup
93
94  // %lpad1: landing pad for return copy ctors, EH cleanup for 'y'
95  // CHECK-EH-03: invoke {{.*}} @_ZN1XD1Ev
96  // -> %eh.cleanup, %terminate.lpad
97  // CHECK-EH-11: call   {{.*}} @_ZN1XD1Ev
98
99  // %if.end: returning 'y'
100  // CHECK-EH: invoke {{.*}} @_ZN1XC1ERKS_
101  // -> %cleanup, %lpad1
102
103  // %cleanup: normal cleanup for 'y'
104  // CHECK-EH-03: invoke {{.*}} @_ZN1XD1Ev
105  // -> %invoke.cont11, %lpad
106  // CHECK-EH-11: call   {{.*}} @_ZN1XD1Ev
107
108  // %invoke.cont11: normal cleanup for 'x'
109  // CHECK-EH:      call void @llvm.lifetime.end
110  // CHECK-EH-NEXT: call {{.*}} @_ZN1XD1Ev
111  // CHECK-EH-NEXT: call void @llvm.lifetime.end
112  // CHECK-EH-NEXT: ret void
113
114  // %eh.cleanup:  EH cleanup for 'x'
115  // CHECK-EH-03: invoke {{.*}} @_ZN1XD1Ev
116  // -> %invoke.cont17, %terminate.lpad
117  // CHECK-EH-11: call   {{.*}} @_ZN1XD1Ev
118
119  // %invoke.cont17: rethrow block for %eh.cleanup.
120  // This really should be elsewhere in the function.
121  // CHECK-EH:      resume { i8*, i32 }
122
123  // %terminate.lpad: terminate landing pad.
124  // CHECK-EH-03:      [[T0:%.*]] = landingpad { i8*, i32 }
125  // CHECK-EH-03-NEXT:   catch i8* null
126  // CHECK-EH-03-NEXT: [[T1:%.*]] = extractvalue { i8*, i32 } [[T0]], 0
127  // CHECK-EH-03-NEXT: call void @__clang_call_terminate(i8* [[T1]]) [[NR_NUW:#[0-9]+]]
128  // CHECK-EH-03-NEXT: unreachable
129
130}
131
132// CHECK-LABEL: define void @_Z5test3b
133X test3(bool B) {
134  // CHECK: tail call {{.*}} @_ZN1XC1Ev
135  // CHECK-NOT: call {{.*}} @_ZN1XC1ERKS_
136  // CHECK: call {{.*}} @_ZN1XC1Ev
137  // CHECK: call {{.*}} @_ZN1XC1ERKS_
138  if (B) {
139    X y;
140    return y;
141  }
142  // FIXME: we should NRVO this variable too.
143  X x;
144  return x;
145}
146
147extern "C" void exit(int) throw();
148
149// CHECK-LABEL: define void @_Z5test4b
150X test4(bool B) {
151  {
152    // CHECK: tail call {{.*}} @_ZN1XC1Ev
153    X x;
154    // CHECK: br i1
155    if (B)
156      return x;
157  }
158  // CHECK: tail call {{.*}} @_ZN1XD1Ev
159  // CHECK: tail call void @exit(i32 1)
160  exit(1);
161}
162
163#ifdef __EXCEPTIONS
164// CHECK-EH-LABEL: define void @_Z5test5
165void may_throw();
166X test5() {
167  try {
168    may_throw();
169  } catch (X x) {
170    // CHECK-EH: invoke {{.*}} @_ZN1XC1ERKS_
171    // CHECK-EH: call void @__cxa_end_catch()
172    // CHECK-EH: ret void
173    return x;
174  }
175}
176#endif
177
178// rdar://problem/10430868
179// CHECK-LABEL: define void @_Z5test6v
180X test6() {
181  X a __attribute__((aligned(8)));
182  return a;
183  // CHECK:      [[A:%.*]] = alloca [[X:%.*]], align 8
184  // CHECK-NEXT: [[PTR:%.*]] = getelementptr inbounds %class.X, %class.X* [[A]], i32 0, i32 0
185  // CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 1, i8* nonnull [[PTR]])
186  // CHECK-NEXT: call {{.*}} @_ZN1XC1Ev([[X]]* nonnull [[A]])
187  // CHECK-NEXT: call {{.*}} @_ZN1XC1ERKS_([[X]]* {{%.*}}, [[X]]* nonnull dereferenceable({{[0-9]+}}) [[A]])
188  // CHECK-NEXT: call {{.*}} @_ZN1XD1Ev([[X]]* nonnull [[A]])
189  // CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 1, i8* nonnull [[PTR]])
190  // CHECK-NEXT: ret void
191}
192
193// CHECK-LABEL: define void @_Z5test7b
194X test7(bool b) {
195  // CHECK: tail call {{.*}} @_ZN1XC1Ev
196  // CHECK-NEXT: ret
197  if (b) {
198    X x;
199    return x;
200  }
201  return X();
202}
203
204// CHECK-LABEL: define void @_Z5test8b
205X test8(bool b) {
206  // CHECK: tail call {{.*}} @_ZN1XC1Ev
207  // CHECK-NEXT: ret
208  if (b) {
209    X x;
210    return x;
211  } else {
212    X y;
213    return y;
214  }
215}
216
217Y<int> test9() {
218  Y<int>::f();
219}
220
221// CHECK-LABEL: define linkonce_odr void @_ZN1YIiE1fEv
222// CHECK: tail call {{.*}} @_ZN1YIiEC1Ev
223
224// CHECK-EH-03: attributes [[NR_NUW]] = { noreturn nounwind }
225