blob: 0569150101c7c1d6bf6e10cc030ae2141d495edc [file] [log] [blame]
John McCall83ce9d42010-11-16 23:07:28 +00001// RUN: %clang_cc1 -Wno-unused-value -emit-llvm %s -o - | FileCheck %s
2
3// CHECK: @i = global [[INT:i[0-9]+]] 0
4volatile int i, j, k;
5volatile int ar[5];
6volatile char c;
7// CHECK: @ci = global [[CINT:%.*]] zeroinitializer
8volatile _Complex int ci;
9volatile struct S {
10#ifdef __cplusplus
11 void operator =(volatile struct S&o) volatile;
12#endif
13 int i;
14} a, b;
15
16//void operator =(volatile struct S&o1, volatile struct S&o2) volatile;
17int printf(const char *, ...);
18
19
20// CHECK: define void @{{.*}}test
21void test() {
22
23 asm("nop"); // CHECK: call void asm
24
John McCall2a416372010-12-05 02:00:02 +000025 // should not load
John McCall83ce9d42010-11-16 23:07:28 +000026 i;
John McCall83ce9d42010-11-16 23:07:28 +000027
28 (float)(ci);
29 // CHECK-NEXT: volatile load [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 0)
30 // CHECK-NEXT: volatile load [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 1)
31 // CHECK-NEXT: sitofp [[INT]]
32
33 // These are not uses in C++:
34 // [expr.static.cast]p6:
35 // The lvalue-to-rvalue . . . conversions are not applied to the expression.
36 (void)ci;
37 (void)a;
38
39 (void)(ci=ci);
40 // CHECK-NEXT: [[R:%.*]] = volatile load [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 0)
41 // CHECK-NEXT: [[I:%.*]] = volatile load [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 1)
42 // CHECK-NEXT: volatile store [[INT]] [[R]], [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 0)
43 // CHECK-NEXT: volatile store [[INT]] [[I]], [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 1)
44
45 (void)(i=j);
46 // CHECK-NEXT: [[T:%.*]] = volatile load [[INT]]* @j
47 // CHECK-NEXT: volatile store [[INT]] [[T]], [[INT]]* @i
48
John McCall83ce9d42010-11-16 23:07:28 +000049 ci+=ci;
50 // CHECK-NEXT: [[R1:%.*]] = volatile load [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 0)
51 // CHECK-NEXT: [[I1:%.*]] = volatile load [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 1)
52 // CHECK-NEXT: [[R2:%.*]] = volatile load [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 0)
53 // CHECK-NEXT: [[I2:%.*]] = volatile load [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 1)
54 // Not sure why they're ordered this way.
55 // CHECK-NEXT: [[R:%.*]] = add [[INT]] [[R2]], [[R1]]
56 // CHECK-NEXT: [[I:%.*]] = add [[INT]] [[I2]], [[I1]]
57 // CHECK-NEXT: volatile store [[INT]] [[R]], [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 0)
58 // CHECK-NEXT: volatile store [[INT]] [[I]], [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 1)
John McCall83ce9d42010-11-16 23:07:28 +000059
60 // Note that C++ requires an extra volatile load over C from the LHS of the '+'.
61 (ci += ci) + ci;
62 // CHECK-NEXT: [[R1:%.*]] = volatile load [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 0)
63 // CHECK-NEXT: [[I1:%.*]] = volatile load [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 1)
64 // CHECK-NEXT: [[R2:%.*]] = volatile load [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 0)
65 // CHECK-NEXT: [[I2:%.*]] = volatile load [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 1)
66 // CHECK-NEXT: [[R:%.*]] = add [[INT]] [[R2]], [[R1]]
67 // CHECK-NEXT: [[I:%.*]] = add [[INT]] [[I2]], [[I1]]
68 // CHECK-NEXT: volatile store [[INT]] [[R]], [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 0)
69 // CHECK-NEXT: volatile store [[INT]] [[I]], [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 1)
70 // CHECK-NEXT: [[R1:%.*]] = volatile load [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 0)
71 // CHECK-NEXT: [[I1:%.*]] = volatile load [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 1)
72 // CHECK-NEXT: [[R2:%.*]] = volatile load [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 0)
73 // CHECK-NEXT: [[I2:%.*]] = volatile load [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 1)
74 // These additions can be elided.
75 // CHECK-NEXT: add [[INT]] [[R1]], [[R2]]
76 // CHECK-NEXT: add [[INT]] [[I1]], [[I2]]
77
78 asm("nop"); // CHECK-NEXT: call void asm
79
80 // Extra volatile load in C++.
81 (i += j) + k;
82 // CHECK-NEXT: volatile load
83 // CHECK-NEXT: volatile load
84 // CHECK-NEXT: add nsw [[INT]]
85 // CHECK-NEXT: volatile store
86 // CHECK-NEXT: volatile load
87 // CHECK-NEXT: volatile load
88 // CHECK-NEXT: add nsw [[INT]]
89
90 asm("nop"); // CHECK-NEXT: call void asm
91
92 // Extra volatile load in C++.
93 (i += j) + 1;
94 // CHECK-NEXT: volatile load
95 // CHECK-NEXT: volatile load
96 // CHECK-NEXT: add nsw [[INT]]
97 // CHECK-NEXT: volatile store
98 // CHECK-NEXT: volatile load
99 // CHECK-NEXT: add nsw [[INT]]
100
101 asm("nop"); // CHECK-NEXT: call void asm
102
103 ci+ci;
104 // CHECK-NEXT: volatile load
105 // CHECK-NEXT: volatile load
106 // CHECK-NEXT: volatile load
107 // CHECK-NEXT: volatile load
108 // CHECK-NEXT: add [[INT]]
109 // CHECK-NEXT: add [[INT]]
110
John McCall83ce9d42010-11-16 23:07:28 +0000111 __real i;
John McCall83ce9d42010-11-16 23:07:28 +0000112
113 +ci;
114 // CHECK-NEXT: volatile load
115 // CHECK-NEXT: volatile load
116
117 asm("nop"); // CHECK-NEXT: call void asm
118
119 (void)(i=i);
120 // CHECK-NEXT: volatile load
121 // CHECK-NEXT: volatile store
122
123 (float)(i=i);
124 // CHECK-NEXT: volatile load
125 // CHECK-NEXT: volatile store
126 // CHECK-NEXT: volatile load
127 // CHECK-NEXT: sitofp
128
129 (void)i;
130
131 i=i;
132 // CHECK-NEXT: volatile load
133 // CHECK-NEXT: volatile store
134
135 // Extra volatile load in C++.
136 i=i=i;
137 // CHECK-NEXT: volatile load
138 // CHECK-NEXT: volatile store
139 // CHECK-NEXT: volatile load
140 // CHECK-NEXT: volatile store
141
142 (void)__builtin_choose_expr(0, i=i, j=j);
143 // CHECK-NEXT: volatile load
144 // CHECK-NEXT: volatile store
145
John McCall2a416372010-12-05 02:00:02 +0000146 // FIXME: the phi-equivalent is unnecessary
John McCall83ce9d42010-11-16 23:07:28 +0000147 k ? (i=i) : (j=j);
148 // CHECK-NEXT: volatile load
149 // CHECK-NEXT: icmp
150 // CHECK-NEXT: br i1
151 // CHECK: volatile load
152 // CHECK-NEXT: volatile store
John McCall2a416372010-12-05 02:00:02 +0000153 // CHECK-NEXT: store [[INT]]* @i
John McCall83ce9d42010-11-16 23:07:28 +0000154 // CHECK-NEXT: br label
155 // CHECK: volatile load
156 // CHECK-NEXT: volatile store
John McCall2a416372010-12-05 02:00:02 +0000157 // CHECK-NEXT: store [[INT]]* @j
John McCall83ce9d42010-11-16 23:07:28 +0000158 // CHECK-NEXT: br label
John McCall2a416372010-12-05 02:00:02 +0000159 // CHECK: load [[INT]]**
John McCall83ce9d42010-11-16 23:07:28 +0000160
161 (void)(i,(i=i));
162 // CHECK-NEXT: volatile load
John McCall83ce9d42010-11-16 23:07:28 +0000163 // CHECK-NEXT: volatile store
164
John McCall83ce9d42010-11-16 23:07:28 +0000165 i=i,k;
166 // CHECK-NEXT: volatile load [[INT]]* @i
167 // CHECK-NEXT: volatile store {{.*}}, [[INT]]* @i
John McCall83ce9d42010-11-16 23:07:28 +0000168
169 (i=j,k=j);
170 // CHECK-NEXT: volatile load [[INT]]* @j
171 // CHECK-NEXT: volatile store {{.*}}, [[INT]]* @i
172 // CHECK-NEXT: volatile load [[INT]]* @j
173 // CHECK-NEXT: volatile store {{.*}}, [[INT]]* @k
174
John McCall83ce9d42010-11-16 23:07:28 +0000175 (i=j,k);
176 // CHECK-NEXT: volatile load [[INT]]* @j
177 // CHECK-NEXT: volatile store {{.*}}, [[INT]]* @i
John McCall83ce9d42010-11-16 23:07:28 +0000178
John McCall83ce9d42010-11-16 23:07:28 +0000179 (i,j);
John McCall83ce9d42010-11-16 23:07:28 +0000180
181 // Extra load in C++.
182 i=c=k;
183 // CHECK-NEXT: volatile load
184 // CHECK-NEXT: trunc
185 // CHECK-NEXT: volatile store
186 // CHECK-NEXT: volatile load
187 // CHECK-NEXT: sext
188 // CHECK-NEXT: volatile store
189
190 i+=k;
191 // CHECK-NEXT: volatile load
192 // CHECK-NEXT: volatile load
193 // CHECK-NEXT: add nsw [[INT]]
194 // CHECK-NEXT: volatile store
195
John McCall83ce9d42010-11-16 23:07:28 +0000196 ci;
John McCall83ce9d42010-11-16 23:07:28 +0000197
198 asm("nop"); // CHECK-NEXT: call void asm
199
200 (int)ci;
201 // CHECK-NEXT: volatile load {{.*}} @ci, i32 0, i32 0
202 // CHECK-NEXT: volatile load {{.*}} @ci, i32 0, i32 1
203
204 (bool)ci;
205 // CHECK-NEXT: volatile load {{.*}} @ci, i32 0, i32 0
206 // CHECK-NEXT: volatile load {{.*}} @ci, i32 0, i32 1
207 // CHECK-NEXT: icmp ne
208 // CHECK-NEXT: icmp ne
209 // CHECK-NEXT: or i1
210
John McCall83ce9d42010-11-16 23:07:28 +0000211 ci=ci;
212 // CHECK-NEXT: volatile load
213 // CHECK-NEXT: volatile load
214 // CHECK-NEXT: volatile store
215 // CHECK-NEXT: volatile store
John McCall83ce9d42010-11-16 23:07:28 +0000216
217 asm("nop"); // CHECK-NEXT: call void asm
218
John McCall83ce9d42010-11-16 23:07:28 +0000219 // Extra load in C++.
220 ci=ci=ci;
221 // CHECK-NEXT: volatile load
222 // CHECK-NEXT: volatile load
223 // CHECK-NEXT: volatile store
224 // CHECK-NEXT: volatile store
225 // CHECK-NEXT: volatile load
226 // CHECK-NEXT: volatile load
227 // CHECK-NEXT: volatile store
228 // CHECK-NEXT: volatile store
John McCall83ce9d42010-11-16 23:07:28 +0000229
230 __imag ci = __imag ci = __imag ci;
231 // CHECK-NEXT: [[T:%.*]] = volatile load [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 1)
232 // CHECK-NEXT: volatile store [[INT]] [[T]], [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 1)
233 // CHECK-NEXT: [[T:%.*]] = volatile load [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 1)
234 // CHECK-NEXT: volatile store [[INT]] [[T]], [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 1)
235
236 __real (i = j);
237 // CHECK-NEXT: volatile load
238 // CHECK-NEXT: volatile store
239
240 __imag i;
John McCall83ce9d42010-11-16 23:07:28 +0000241
242 // ============================================================
243 // FIXME: Test cases we get wrong.
244
245 // A use. We load all of a into a copy of a, then load i. gcc forgets to do
246 // the assignment.
247 // (a = a).i;
248
249 // ============================================================
250 // Test cases where we intentionally differ from gcc, due to suspected bugs in
251 // gcc.
252
253 // Not a use. gcc forgets to do the assignment.
254 // CHECK-NEXT: call
255 ((a=a),a);
256
257 // Not a use. gcc gets this wrong, it doesn't emit the copy!
258 // CHECK-NEXT: call
259 (void)(a=a);
260
261 // Not a use. gcc got this wrong in 4.2 and omitted the side effects
262 // entirely, but it is fixed in 4.4.0.
263 __imag (i = j);
264 // CHECK-NEXT: volatile load
265 // CHECK-NEXT: volatile store
266
267 // C++ does an extra load here. Note that we have to do full loads.
268 (float)(ci=ci);
269 // CHECK-NEXT: volatile load
270 // CHECK-NEXT: volatile load
271 // CHECK-NEXT: volatile store
272 // CHECK-NEXT: volatile store
273 // CHECK-NEXT: volatile load
274 // CHECK-NEXT: volatile load
275 // CHECK-NEXT: sitofp
276
277 // Not a use, bug? gcc treats this as not a use, that's probably a
278 // bug due to tree folding ignoring volatile.
279 (int)(ci=ci);
280 // CHECK-NEXT: volatile load
281 // CHECK-NEXT: volatile load
282 // CHECK-NEXT: volatile store
283 // CHECK-NEXT: volatile store
284 // CHECK-NEXT: volatile load
285 // CHECK-NEXT: volatile load
286
287 // A use.
288 (float)(i=i);
289 // CHECK-NEXT: volatile load
290 // CHECK-NEXT: volatile store
291 // CHECK-NEXT: volatile load
292 // CHECK-NEXT: sitofp
293
294 // A use. gcc treats this as not a use, that's probably a bug due to tree
295 // folding ignoring volatile.
296 (int)(i=i);
297 // CHECK-NEXT: volatile load
298 // CHECK-NEXT: volatile store
299 // CHECK-NEXT: volatile load
300
301 // A use.
302 -(i=j);
303 // CHECK-NEXT: volatile load
304 // CHECK-NEXT: volatile store
305 // CHECK-NEXT: volatile load
306 // CHECK-NEXT: sub
307
308 // A use. gcc treats this a not a use, that's probably a bug due to tree
309 // folding ignoring volatile.
310 +(i=k);
311 // CHECK-NEXT: volatile load
312 // CHECK-NEXT: volatile store
313 // CHECK-NEXT: volatile load
314
315 // A use. gcc treats this a not a use, that's probably a bug due to tree
316 // folding ignoring volatile.
John McCall83ce9d42010-11-16 23:07:28 +0000317 __real (ci=ci);
318 // CHECK-NEXT: volatile load
319 // CHECK-NEXT: volatile load
320 // CHECK-NEXT: volatile store
321 // CHECK-NEXT: volatile store
John McCall83ce9d42010-11-16 23:07:28 +0000322
323 // A use.
324 i + 0;
325 // CHECK-NEXT: volatile load
326 // CHECK-NEXT: add
327
328 // A use.
329 (i=j) + i;
330 // CHECK-NEXT: volatile load
331 // CHECK-NEXT: volatile store
332 // CHECK-NEXT: volatile load
333 // CHECK-NEXT: volatile load
334 // CHECK-NEXT: add
335
336 // A use. gcc treats this as not a use, that's probably a bug due to tree
337 // folding ignoring volatile.
338 (i=j) + 0;
339 // CHECK-NEXT: volatile load
340 // CHECK-NEXT: volatile store
341 // CHECK-NEXT: volatile load
342 // CHECK-NEXT: add
343
John McCall83ce9d42010-11-16 23:07:28 +0000344 (i,j)=k;
345 // CHECK-NEXT: volatile load [[INT]]* @k
John McCall83ce9d42010-11-16 23:07:28 +0000346 // CHECK-NEXT: volatile store {{.*}}, [[INT]]* @j
347
John McCall83ce9d42010-11-16 23:07:28 +0000348 (j=k,i)=i;
John McCallcd940a12010-12-06 06:10:02 +0000349 // CHECK-NEXT: volatile load [[INT]]* @i
John McCall83ce9d42010-11-16 23:07:28 +0000350 // CHECK-NEXT: volatile load [[INT]]* @k
351 // CHECK-NEXT: volatile store {{.*}}, [[INT]]* @j
John McCall83ce9d42010-11-16 23:07:28 +0000352 // CHECK-NEXT: volatile store {{.*}}, [[INT]]* @i
John McCall2a416372010-12-05 02:00:02 +0000353
354 // CHECK-NEXT: ret void
John McCall83ce9d42010-11-16 23:07:28 +0000355}