Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / clang / test / CodeGen / nrvo-tracking.cpp
blob1189a867b766db7d245586ab8aeb7dde62773fca
1 // RUN: %clang_cc1 -std=c++20 -fblocks -Wno-return-stack-address -triple x86_64-unknown-unknown-gnu -emit-llvm -O1 -o - %s | FileCheck %s
3 struct alignas(4) X {
4 X();
5 X(const X &);
6 X(X &&);
7 };
9 #define L(A, B, C) void l##A() { \
10 auto t = []<class T = X>() -> C { \
11 T t; \
12 return B; \
13 }(); \
16 // CHECK-LABEL: define{{.*}} void @_Z2l1v
17 // CHECK: call {{.*}} @_ZN1XC1Ev
18 // CHECK-NEXT: call void @llvm.lifetime.end
19 // CHECK-NEXT: ret void
20 L(1, t, X);
22 // CHECK-LABEL: define{{.*}} void @_Z2l2v
23 // CHECK: call {{.*}} @_ZN1XC1Ev
24 // CHECK-NEXT: call void @llvm.lifetime.end
25 // CHECK-NEXT: call {{.*}} @_ZN1XC1ERKS_
26 // CHECK-NEXT: call void @llvm.lifetime.end
27 // CHECK-NEXT: ret void
28 L(2, t, X&);
30 // CHECK-LABEL: define{{.*}} void @_Z2l3v
31 // CHECK: call {{.*}} @_ZN1XC1Ev
32 // CHECK-NEXT: call void @llvm.lifetime.end
33 // CHECK-NEXT: ret void
34 L(3, t, T);
36 // CHECK-LABEL: define{{.*}} void @_Z2l4v
37 // CHECK: call {{.*}} @_ZN1XC1Ev
38 // CHECK-NEXT: call void @llvm.lifetime.end
39 // CHECK-NEXT: call {{.*}} @_ZN1XC1ERKS_
40 // CHECK-NEXT: call void @llvm.lifetime.end
41 // CHECK-NEXT: ret void
42 L(4, t, T&);
44 // CHECK-LABEL: define{{.*}} void @_Z2l5v
45 // CHECK: call {{.*}} @_ZN1XC1Ev
46 // CHECK-NEXT: call {{.*}} @_ZN1XC1EOS_
47 // CHECK-NEXT: call void @llvm.lifetime.end
48 // CHECK-NEXT: call void @llvm.lifetime.end
49 // CHECK-NEXT: ret void
50 L(5, t, auto);
52 // CHECK-LABEL: define{{.*}} void @_Z2l6v
53 // CHECK: call {{.*}} @_ZN1XC1Ev
54 // CHECK-NEXT: call void @llvm.lifetime.end
55 // CHECK-NEXT: call {{.*}} @_ZN1XC1ERKS_
56 // CHECK-NEXT: call void @llvm.lifetime.end
57 // CHECK-NEXT: ret void
58 L(6, t, auto&);
60 // CHECK-LABEL: define{{.*}} void @_Z2l7v
61 // CHECK: call {{.*}} @_ZN1XC1Ev
62 // CHECK-NEXT: call {{.*}} @_ZN1XC1EOS_
63 // CHECK-NEXT: call void @llvm.lifetime.end
64 // CHECK-NEXT: call void @llvm.lifetime.end
65 // CHECK-NEXT: ret void
66 L(7, t, decltype(auto));
68 // CHECK-LABEL: define{{.*}} void @_Z2l8v
69 // CHECK: call {{.*}} @_ZN1XC1Ev
70 // CHECK-NEXT: call void @llvm.lifetime.end
71 // CHECK-NEXT: call {{.*}} @_ZN1XC1ERKS_
72 // CHECK-NEXT: call void @llvm.lifetime.end
73 // CHECK-NEXT: ret void
74 L(8, (t), decltype(auto));
76 #undef L
78 #define F(A, B, C) template<class T = X> static inline auto tf##A() -> C { \
79 T t; \
80 return B; \
81 } \
82 void f##A() { auto t = tf##A(); } \
84 // CHECK-LABEL: define{{.*}} void @_Z2f1v
85 // CHECK: call {{.*}} @_ZN1XC1Ev
86 // CHECK-NEXT: call void @llvm.lifetime.end
87 // CHECK-NEXT: ret void
88 F(1, t, X);
90 // CHECK-LABEL: define{{.*}} void @_Z2f2v
91 // CHECK: call {{.*}} @_ZN1XC1Ev
92 // CHECK-NEXT: call void @llvm.lifetime.end
93 // CHECK-NEXT: call {{.*}} @_ZN1XC1ERKS_
94 // CHECK-NEXT: call void @llvm.lifetime.end
95 // CHECK-NEXT: ret void
96 F(2, t, X&);
98 // CHECK-LABEL: define{{.*}} void @_Z2f3v
99 // CHECK: call {{.*}} @_ZN1XC1Ev
100 // CHECK-NEXT: call void @llvm.lifetime.end
101 // CHECK-NEXT: ret void
102 F(3, t, T);
104 // CHECK-LABEL: define{{.*}} void @_Z2f4v
105 // CHECK: call {{.*}} @_ZN1XC1Ev
106 // CHECK-NEXT: call void @llvm.lifetime.end
107 // CHECK-NEXT: call {{.*}} @_ZN1XC1ERKS_
108 // CHECK-NEXT: call void @llvm.lifetime.end
109 // CHECK-NEXT: ret void
110 F(4, t, T&);
112 // CHECK-LABEL: define{{.*}} void @_Z2f5v
113 // CHECK: call {{.*}} @_ZN1XC1Ev
114 // CHECK-NEXT: call {{.*}} @_ZN1XC1EOS_
115 // CHECK-NEXT: call void @llvm.lifetime.end
116 // CHECK-NEXT: call void @llvm.lifetime.end
117 // CHECK-NEXT: ret void
118 F(5, t, auto);
120 // CHECK-LABEL: define{{.*}} void @_Z2f6v
121 // CHECK: call {{.*}} @_ZN1XC1Ev
122 // CHECK-NEXT: call void @llvm.lifetime.end
123 // CHECK-NEXT: call {{.*}} @_ZN1XC1ERKS_
124 // CHECK-NEXT: call void @llvm.lifetime.end
125 // CHECK-NEXT: ret void
126 F(6, t, auto&);
128 // CHECK-LABEL: define{{.*}} void @_Z2f7v
129 // CHECK: call {{.*}} @_ZN1XC1Ev
130 // CHECK-NEXT: call {{.*}} @_ZN1XC1EOS_
131 // CHECK-NEXT: call void @llvm.lifetime.end
132 // CHECK-NEXT: call void @llvm.lifetime.end
133 // CHECK-NEXT: ret void
134 F(7, t, decltype(auto));
136 // CHECK-LABEL: define{{.*}} void @_Z2f8v
137 // CHECK: call {{.*}} @_ZN1XC1Ev
138 // CHECK-NEXT: call void @llvm.lifetime.end
139 // CHECK-NEXT: call {{.*}} @_ZN1XC1ERKS_
140 // CHECK-NEXT: call void @llvm.lifetime.end
141 // CHECK-NEXT: ret void
142 F(8, (t), decltype(auto));
144 #undef F
146 #define B(A, B) void b##A() { \
147 auto t = []<class T = X>() { return ^ B () { \
148 T t; \
149 return t; \
150 }; }()(); \
153 // CHECK-LABEL: define{{.*}} void @_Z2b1v
154 // CHECK: call {{.*}} @_ZN1XC1Ev
155 // CHECK-NEXT: call void @llvm.lifetime.end
156 // CHECK-NEXT: ret void
157 B(1, X);
159 // CHECK-LABEL: define{{.*}} void @_Z2b2v
160 // CHECK: call {{.*}} @_ZN1XC1Ev
161 // CHECK-NEXT: call void @llvm.lifetime.end
162 // CHECK-NEXT: call {{.*}} @_ZN1XC1ERKS_
163 // CHECK-NEXT: call void @llvm.lifetime.end
164 // CHECK-NEXT: ret void
165 B(2, X&);
167 // CHECK-LABEL: define{{.*}} void @_Z2b3v
168 // CHECK: call {{.*}} @_ZN1XC1Ev
169 // CHECK-NEXT: call void @llvm.lifetime.end
170 // CHECK-NEXT: ret void
171 B(3, T);
173 // CHECK-LABEL: define{{.*}} void @_Z2b4v
174 // CHECK: call {{.*}} @_ZN1XC1Ev
175 // CHECK-NEXT: call void @llvm.lifetime.end
176 // CHECK-NEXT: call {{.*}} @_ZN1XC1ERKS_
177 // CHECK-NEXT: call void @llvm.lifetime.end
178 // CHECK-NEXT: ret void
179 B(4, T&);
181 // CHECK-LABEL: define{{.*}} void @_Z2b5v
182 // CHECK: call {{.*}} @_ZN1XC1Ev
183 // CHECK-NEXT: call {{.*}} @_ZN1XC1EOS_
184 // CHECK-NEXT: call void @llvm.lifetime.end
185 // CHECK-NEXT: call void @llvm.lifetime.end
186 // CHECK-NEXT: ret void
187 B(5, );
189 #undef B
191 // CHECK-LABEL: define{{.*}} void @_Z6f_attrv
192 // CHECK: call {{.*}} @_ZN1XC1Ev
193 // CHECK-NEXT: call void @llvm.lifetime.end
194 // CHECK-NEXT: ret void
195 template<class T = X> [[gnu::cdecl]] static inline auto tf_attr() -> X {
196 T t;
197 return t;
199 void f_attr() { auto t = tf_attr(); }
201 // CHECK-LABEL: define{{.*}} void @_Z6b_attrv
202 // CHECK: call {{.*}} @_ZN1XC1Ev
203 // CHECK-NEXT: call void @llvm.lifetime.end
204 // CHECK-NEXT: ret void
205 void b_attr() {
206 auto t = []<class T = X>() {
207 return ^X() [[clang::vectorcall]] {
208 T t;
209 return t;
211 }()();
214 namespace test_alignas {
216 template <int A> X t1() {
217 X a [[gnu::aligned(A)]];
218 return a;
221 // CHECK-LABEL: define{{.*}} void @_ZN12test_alignas2t1ILi1EEE1Xv
222 // CHECK: call {{.*}} @_ZN1XC1Ev
223 // CHECK-NEXT: ret void
224 template X t1<1>();
226 // CHECK-LABEL: define{{.*}} void @_ZN12test_alignas2t1ILi4EEE1Xv
227 // CHECK: call {{.*}} @_ZN1XC1Ev
228 // CHECK-NEXT: ret void
229 template X t1<4>();
231 // CHECK-LABEL: define{{.*}} void @_ZN12test_alignas2t1ILi8EEE1Xv
232 // CHECK: call {{.*}} @_ZN1XC1Ev
233 // CHECK-NEXT: call {{.*}} @_ZN1XC1EOS_
234 // CHECK-NEXT: call void @llvm.lifetime.end
235 template X t1<8>();
237 template <int A> X t2() {
238 X a [[gnu::aligned(1)]] [[gnu::aligned(A)]] [[gnu::aligned(2)]];
239 return a;
242 // CHECK-LABEL: define{{.*}} void @_ZN12test_alignas2t2ILi1EEE1Xv
243 // CHECK: call {{.*}} @_ZN1XC1Ev
244 // CHECK-NEXT: ret void
245 template X t2<1>();
247 // CHECK-LABEL: define{{.*}} void @_ZN12test_alignas2t2ILi4EEE1Xv
248 // CHECK: call {{.*}} @_ZN1XC1Ev
249 // CHECK-NEXT: ret void
250 template X t2<4>();
252 // CHECK-LABEL: define{{.*}} void @_ZN12test_alignas2t2ILi8EEE1Xv
253 // CHECK: call {{.*}} @_ZN1XC1Ev
254 // CHECK-NEXT: call {{.*}} @_ZN1XC1EOS_
255 // CHECK-NEXT: call void @llvm.lifetime.end
256 template X t2<8>();
258 // CHECK-LABEL: define{{.*}} void @_ZN12test_alignas2t3Ev
259 // CHECK: call {{.*}} @_ZN1XC1Ev
260 // CHECK-NEXT: ret void
261 X t3() {
262 X a [[gnu::aligned(1)]];
263 return a;
266 // CHECK-LABEL: define{{.*}} void @_ZN12test_alignas2t4Ev
267 // CHECK: call {{.*}} @_ZN1XC1Ev
268 // CHECK-NEXT: call {{.*}} @_ZN1XC1EOS_
269 // CHECK-NEXT: call void @llvm.lifetime.end
270 X t4() {
271 X a [[gnu::aligned(8)]];
272 return a;
275 // CHECK-LABEL: define{{.*}} void @_ZN12test_alignas2t5Ev
276 // CHECK: call {{.*}} @_ZN1XC1Ev
277 // CHECK-NEXT: call {{.*}} @_ZN1XC1EOS_
278 // CHECK-NEXT: call void @llvm.lifetime.end
279 X t5() {
280 X a [[gnu::aligned(1)]] [[gnu::aligned(8)]];
281 return a;
284 } // namespace test_alignas
286 namespace PR51862 {
288 template <class T> T test() {
289 T a;
290 T b;
291 if (0)
292 return a;
293 return b;
296 struct A {
297 A();
298 A(A &);
299 A(int);
300 operator int();
303 // CHECK-LABEL: define{{.*}} void @_ZN7PR518624testINS_1AEEET_v
304 // CHECK: call noundef i32 @_ZN7PR518621AcviEv
305 // CHECK-NEXT: call void @_ZN7PR518621AC1Ei
306 // CHECK-NEXT: call void @llvm.lifetime.end
307 template A test<A>();
309 struct BSub {};
310 struct B : BSub {
311 B();
312 B(B &);
313 B(const BSub &);
316 // CHECK-LABEL: define{{.*}} void @_ZN7PR518624testINS_1BEEET_v
317 // CHECK: call void @_ZN7PR518621BC1ERKNS_4BSubE
318 // CHECK-NEXT: call void @llvm.lifetime.end
319 template B test<B>();
321 } // namespace PR51862