xref: /llvm-project/clang/test/CodeGenCXX/conditional-temporaries.cpp (revision 1b1c8d83d3567a60280291c0adb95d1d60335509)
1 // REQUIRES: amdgpu-registered-target
2 // RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-apple-darwin9 -O2 -disable-llvm-passes | FileCheck %s --check-prefixes=CHECK,CHECK-NOOPT
3 // RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-apple-darwin9 -O2 | FileCheck %s --check-prefixes=CHECK,CHECK-OPT
4 // RUN: %clang_cc1 -emit-llvm %s -o - -triple=amdgcn-amd-amdhsa -O2 | FileCheck %s --check-prefixes=CHECK,CHECK-OPT
5 
6 namespace {
7 
8 static int ctorcalls;
9 static int dtorcalls;
10 
11 struct A {
A__anon49fae3590111::A12   A() : i(0) { ctorcalls++; }
~A__anon49fae3590111::A13   ~A() { dtorcalls++; }
14   int i;
15 
operator <<(const A & a,int n)16   friend const A& operator<<(const A& a, int n) {
17     return a;
18   }
19 };
20 
g(int)21 void g(int) { }
g(const A &)22 void g(const A&) { }
23 
f1(bool b)24 void f1(bool b) {
25   g(b ? A().i : 0);
26   g(b || A().i);
27   g(b && A().i);
28   g(b ? A() << 1 : A() << 2);
29 }
30 
31 struct Checker {
Checker__anon49fae3590111::Checker32   Checker() {
33     f1(true);
34     f1(false);
35   }
36 };
37 
38 Checker c;
39 
40 }
41 
42 // CHECK-OPT-LABEL: define{{.*}} i32 @_Z12getCtorCallsv()
getCtorCalls()43 int getCtorCalls() {
44   // CHECK-OPT: ret i32 5
45   return ctorcalls;
46 }
47 
48 // CHECK-OPT-LABEL: define{{.*}} i32 @_Z12getDtorCallsv()
getDtorCalls()49 int getDtorCalls() {
50   // CHECK-OPT: ret i32 5
51   return dtorcalls;
52 }
53 
54 // CHECK-OPT-LABEL: define{{.*}} zeroext i1 @_Z7successv()
success()55 bool success() {
56   // CHECK-OPT: ret i1 true
57   return ctorcalls == dtorcalls;
58 }
59 
60 struct X { ~X(); int f(); };
61 int g(int, int, int);
62 // CHECK-LABEL: @_Z16lifetime_nontriv
lifetime_nontriv(bool cond)63 int lifetime_nontriv(bool cond) {
64   // CHECK-NOOPT: store i1 false,
65   // CHECK-NOOPT: store i1 false,
66   // CHECK-NOOPT: store i1 false,
67   // CHECK-NOOPT: store i1 false,
68   // CHECK-NOOPT: store i1 false,
69   // CHECK-NOOPT: store i1 false,
70   // CHECK-NOOPT: br i1
71   //
72   // CHECK-NOOPT: call void @llvm.lifetime.start
73   // CHECK-NOOPT: store i1 true,
74   // CHECK-NOOPT: store i1 true,
75   // CHECK-NOOPT: call noundef i32 @_ZN1X1fEv(
76   // CHECK-NOOPT: call void @llvm.lifetime.start
77   // CHECK-NOOPT: store i1 true,
78   // CHECK-NOOPT: store i1 true,
79   // CHECK-NOOPT: call noundef i32 @_ZN1X1fEv(
80   // CHECK-NOOPT: call void @llvm.lifetime.start
81   // CHECK-NOOPT: store i1 true,
82   // CHECK-NOOPT: store i1 true,
83   // CHECK-NOOPT: call noundef i32 @_ZN1X1fEv(
84   // CHECK-NOOPT: call noundef i32 @_Z1giii(
85   // CHECK-NOOPT: br label
86   //
87   // CHECK-NOOPT: call noundef i32 @_Z1giii(i32 noundef 1, i32 noundef 2, i32 noundef 3)
88   // CHECK-NOOPT: br label
89   //
90   // CHECK-NOOPT: load i1,
91   // CHECK-NOOPT: br i1
92   // CHECK-NOOPT: call void @_ZN1XD1Ev(
93   // CHECK-NOOPT: br label
94   //
95   // CHECK-NOOPT: load i1,
96   // CHECK-NOOPT: br i1
97   // CHECK-NOOPT: call void @llvm.lifetime.end
98   // CHECK-NOOPT: br label
99   //
100   // CHECK-NOOPT: load i1,
101   // CHECK-NOOPT: br i1
102   // CHECK-NOOPT: call void @_ZN1XD1Ev(
103   // CHECK-NOOPT: br label
104   //
105   // CHECK-NOOPT: load i1,
106   // CHECK-NOOPT: br i1
107   // CHECK-NOOPT: call void @llvm.lifetime.end
108   // CHECK-NOOPT: br label
109   //
110   // CHECK-NOOPT: load i1,
111   // CHECK-NOOPT: br i1
112   // CHECK-NOOPT: call void @_ZN1XD1Ev(
113   // CHECK-NOOPT: br label
114   //
115   // CHECK-NOOPT: load i1,
116   // CHECK-NOOPT: br i1
117   // CHECK-NOOPT: call void @llvm.lifetime.end
118   // CHECK-NOOPT: br label
119   //
120   // CHECK-NOOPT: ret
121 
122   // CHECK-OPT: br i1
123   //
124   // CHECK-OPT: call void @llvm.lifetime.start
125   // CHECK-OPT: call noundef i32 @_ZN1X1fEv(
126   // CHECK-OPT: call void @llvm.lifetime.start
127   // CHECK-OPT: call noundef i32 @_ZN1X1fEv(
128   // CHECK-OPT: call void @llvm.lifetime.start
129   // CHECK-OPT: call noundef i32 @_ZN1X1fEv(
130   // CHECK-OPT: call noundef i32 @_Z1giii(
131   // CHECK-OPT: call void @_ZN1XD1Ev(
132   // CHECK-OPT: call void @llvm.lifetime.end
133   // CHECK-OPT: call void @_ZN1XD1Ev(
134   // CHECK-OPT: call void @llvm.lifetime.end
135   // CHECK-OPT: call void @_ZN1XD1Ev(
136   // CHECK-OPT: call void @llvm.lifetime.end
137   // CHECK-OPT: br label
138   return cond ? g(X().f(), X().f(), X().f()) : g(1, 2, 3);
139 }
140 
141 struct Y { int f(); };
142 int g(int, int, int);
143 // CHECK-LABEL: @_Z13lifetime_triv
lifetime_triv(bool cond)144 int lifetime_triv(bool cond) {
145   // CHECK-NOOPT: call void @llvm.lifetime.start
146   // CHECK-NOOPT: call void @llvm.lifetime.start
147   // CHECK-NOOPT: call void @llvm.lifetime.start
148   // CHECK-NOOPT: br i1
149   //
150   // CHECK-NOOPT: call noundef i32 @_ZN1Y1fEv(
151   // CHECK-NOOPT: call noundef i32 @_ZN1Y1fEv(
152   // CHECK-NOOPT: call noundef i32 @_ZN1Y1fEv(
153   // CHECK-NOOPT: call noundef i32 @_Z1giii(
154   // CHECK-NOOPT: br label
155   //
156   // CHECK-NOOPT: call noundef i32 @_Z1giii(i32 noundef 1, i32 noundef 2, i32 noundef 3)
157   // CHECK-NOOPT: br label
158   //
159   // CHECK-NOOPT: call void @llvm.lifetime.end
160   // CHECK-NOOPT-NOT: br
161   // CHECK-NOOPT: call void @llvm.lifetime.end
162   // CHECK-NOOPT-NOT: br
163   // CHECK-NOOPT: call void @llvm.lifetime.end
164   //
165   // CHECK-NOOPT: ret
166 
167   // FIXME: LLVM isn't smart enough to remove the lifetime markers from the
168   // g(1, 2, 3) path here.
169 
170   // CHECK-OPT: call void @llvm.lifetime.start
171   // CHECK-OPT: call void @llvm.lifetime.start
172   // CHECK-OPT: call void @llvm.lifetime.start
173   // CHECK-OPT: br i1
174   //
175   // CHECK-OPT: call noundef i32 @_ZN1Y1fEv(
176   // CHECK-OPT: call noundef i32 @_ZN1Y1fEv(
177   // CHECK-OPT: call noundef i32 @_ZN1Y1fEv(
178   // CHECK-OPT: call noundef i32 @_Z1giii(
179   // CHECK-OPT: br label
180   //
181   // CHECK-OPT: call void @llvm.lifetime.end
182   // CHECK-OPT: call void @llvm.lifetime.end
183   // CHECK-OPT: call void @llvm.lifetime.end
184   return cond ? g(Y().f(), Y().f(), Y().f()) : g(1, 2, 3);
185 }
186 
~ZZ187 struct Z { ~Z() {} int f(); };
188 int g(int, int, int);
189 // CHECK-LABEL: @_Z22lifetime_nontriv_empty
lifetime_nontriv_empty(bool cond)190 int lifetime_nontriv_empty(bool cond) {
191   // CHECK-OPT: br i1
192   //
193   // CHECK-OPT: call void @llvm.lifetime.start
194   // CHECK-OPT: call noundef i32 @_ZN1Z1fEv(
195   // CHECK-OPT: call void @llvm.lifetime.start
196   // CHECK-OPT: call noundef i32 @_ZN1Z1fEv(
197   // CHECK-OPT: call void @llvm.lifetime.start
198   // CHECK-OPT: call noundef i32 @_ZN1Z1fEv(
199   // CHECK-OPT: call noundef i32 @_Z1giii(
200   // CHECK-OPT: call void @llvm.lifetime.end
201   // CHECK-OPT: call void @llvm.lifetime.end
202   // CHECK-OPT: call void @llvm.lifetime.end
203   // CHECK-OPT: br label
204   return cond ? g(Z().f(), Z().f(), Z().f()) : g(1, 2, 3);
205 }
206