volatile-1.cpp revision 83ce9d4a552987d34cbd500e983db8d770232379
1// 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
25  // FIXME: should not load
26  i;
27  // CHECK-NEXT: volatile load [[INT]]* @i
28
29  (float)(ci);
30  // CHECK-NEXT: volatile load [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 0)
31  // CHECK-NEXT: volatile load [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 1)
32  // CHECK-NEXT: sitofp [[INT]]
33
34  // These are not uses in C++:
35  //   [expr.static.cast]p6:
36  //     The lvalue-to-rvalue . . . conversions are not applied to the expression.
37  (void)ci;
38  (void)a;
39
40  (void)(ci=ci);
41  // CHECK-NEXT: [[R:%.*]] = volatile load [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 0)
42  // CHECK-NEXT: [[I:%.*]] = volatile load [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 1)
43  // CHECK-NEXT: volatile store [[INT]] [[R]], [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 0)
44  // CHECK-NEXT: volatile store [[INT]] [[I]], [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 1)
45
46  (void)(i=j);
47  // CHECK-NEXT: [[T:%.*]] = volatile load [[INT]]* @j
48  // CHECK-NEXT: volatile store [[INT]] [[T]], [[INT]]* @i
49
50  // FIXME: extra load at end!
51  ci+=ci;
52  // CHECK-NEXT: [[R1:%.*]] = volatile load [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 0)
53  // CHECK-NEXT: [[I1:%.*]] = volatile load [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 1)
54  // CHECK-NEXT: [[R2:%.*]] = volatile load [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 0)
55  // CHECK-NEXT: [[I2:%.*]] = volatile load [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 1)
56  // Not sure why they're ordered this way.
57  // CHECK-NEXT: [[R:%.*]] = add [[INT]] [[R2]], [[R1]]
58  // CHECK-NEXT: [[I:%.*]] = add [[INT]] [[I2]], [[I1]]
59  // CHECK-NEXT: volatile store [[INT]] [[R]], [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 0)
60  // CHECK-NEXT: volatile store [[INT]] [[I]], [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 1)
61  // CHECK-NEXT: [[R1:%.*]] = volatile load [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 0)
62  // CHECK-NEXT: [[I1:%.*]] = volatile load [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 1)
63
64  // Note that C++ requires an extra volatile load over C from the LHS of the '+'.
65  (ci += ci) + ci;
66  // CHECK-NEXT: [[R1:%.*]] = volatile load [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 0)
67  // CHECK-NEXT: [[I1:%.*]] = volatile load [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 1)
68  // CHECK-NEXT: [[R2:%.*]] = volatile load [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 0)
69  // CHECK-NEXT: [[I2:%.*]] = volatile load [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 1)
70  // CHECK-NEXT: [[R:%.*]] = add [[INT]] [[R2]], [[R1]]
71  // CHECK-NEXT: [[I:%.*]] = add [[INT]] [[I2]], [[I1]]
72  // CHECK-NEXT: volatile store [[INT]] [[R]], [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 0)
73  // CHECK-NEXT: volatile store [[INT]] [[I]], [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 1)
74  // CHECK-NEXT: [[R1:%.*]] = volatile load [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 0)
75  // CHECK-NEXT: [[I1:%.*]] = volatile load [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 1)
76  // CHECK-NEXT: [[R2:%.*]] = volatile load [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 0)
77  // CHECK-NEXT: [[I2:%.*]] = volatile load [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 1)
78  // These additions can be elided.
79  // CHECK-NEXT: add [[INT]] [[R1]], [[R2]]
80  // CHECK-NEXT: add [[INT]] [[I1]], [[I2]]
81
82  asm("nop"); // CHECK-NEXT: call void asm
83
84  // Extra volatile load in C++.
85  (i += j) + k;
86  // CHECK-NEXT: volatile load
87  // CHECK-NEXT: volatile load
88  // CHECK-NEXT: add nsw [[INT]]
89  // CHECK-NEXT: volatile store
90  // CHECK-NEXT: volatile load
91  // CHECK-NEXT: volatile load
92  // CHECK-NEXT: add nsw [[INT]]
93
94  asm("nop"); // CHECK-NEXT: call void asm
95
96  // Extra volatile load in C++.
97  (i += j) + 1;
98  // CHECK-NEXT: volatile load
99  // CHECK-NEXT: volatile load
100  // CHECK-NEXT: add nsw [[INT]]
101  // CHECK-NEXT: volatile store
102  // CHECK-NEXT: volatile load
103  // CHECK-NEXT: add nsw [[INT]]
104
105  asm("nop"); // CHECK-NEXT: call void asm
106
107  ci+ci;
108  // CHECK-NEXT: volatile load
109  // CHECK-NEXT: volatile load
110  // CHECK-NEXT: volatile load
111  // CHECK-NEXT: volatile load
112  // CHECK-NEXT: add [[INT]]
113  // CHECK-NEXT: add [[INT]]
114
115  // FIXME: should not load
116  __real i;
117  // CHECK-NEXT: volatile load
118
119  +ci;
120  // CHECK-NEXT: volatile load
121  // CHECK-NEXT: volatile load
122
123  asm("nop"); // CHECK-NEXT: call void asm
124
125  (void)(i=i);
126  // CHECK-NEXT: volatile load
127  // CHECK-NEXT: volatile store
128
129  (float)(i=i);
130  // CHECK-NEXT: volatile load
131  // CHECK-NEXT: volatile store
132  // CHECK-NEXT: volatile load
133  // CHECK-NEXT: sitofp
134
135  (void)i;
136
137  i=i;
138  // CHECK-NEXT: volatile load
139  // CHECK-NEXT: volatile store
140
141  // Extra volatile load in C++.
142  i=i=i;
143  // CHECK-NEXT: volatile load
144  // CHECK-NEXT: volatile store
145  // CHECK-NEXT: volatile load
146  // CHECK-NEXT: volatile store
147
148  (void)__builtin_choose_expr(0, i=i, j=j);
149  // CHECK-NEXT: volatile load
150  // CHECK-NEXT: volatile store
151
152  // FIXME: shouldn't get these extra loads here, or the phi
153  k ? (i=i) : (j=j);
154  // CHECK-NEXT: volatile load
155  // CHECK-NEXT: icmp
156  // CHECK-NEXT: br i1
157  // CHECK: volatile load
158  // CHECK-NEXT: volatile store
159  // CHECK-NEXT: volatile load
160  // CHECK-NEXT: br label
161  // CHECK: volatile load
162  // CHECK-NEXT: volatile store
163  // CHECK-NEXT: volatile load
164  // CHECK-NEXT: br label
165  // CHECK: phi
166
167  (void)(i,(i=i));
168  // CHECK-NEXT: volatile load
169  // CHECK-NEXT: volatile load
170  // CHECK-NEXT: volatile store
171
172  // FIXME: should not load k
173  i=i,k;
174  // CHECK-NEXT: volatile load [[INT]]* @i
175  // CHECK-NEXT: volatile store {{.*}}, [[INT]]* @i
176  // CHECK-NEXT: volatile load [[INT]]* @k
177
178  (i=j,k=j);
179  // CHECK-NEXT: volatile load [[INT]]* @j
180  // CHECK-NEXT: volatile store {{.*}}, [[INT]]* @i
181  // CHECK-NEXT: volatile load [[INT]]* @j
182  // CHECK-NEXT: volatile store {{.*}}, [[INT]]* @k
183
184  // FIXME: should not load 'k'
185  (i=j,k);
186  // CHECK-NEXT: volatile load [[INT]]* @j
187  // CHECK-NEXT: volatile store {{.*}}, [[INT]]* @i
188  // CHECK-NEXT: volatile load [[INT]]* @k
189
190  // FIXME: should not load either
191  (i,j);
192  // CHECK-NEXT: volatile load [[INT]]* @i
193  // CHECK-NEXT: volatile load [[INT]]* @j
194
195  // Extra load in C++.
196  i=c=k;
197  // CHECK-NEXT: volatile load
198  // CHECK-NEXT: trunc
199  // CHECK-NEXT: volatile store
200  // CHECK-NEXT: volatile load
201  // CHECK-NEXT: sext
202  // CHECK-NEXT: volatile store
203
204  i+=k;
205  // CHECK-NEXT: volatile load
206  // CHECK-NEXT: volatile load
207  // CHECK-NEXT: add nsw [[INT]]
208  // CHECK-NEXT: volatile store
209
210  // FIXME: should not load!
211  ci;
212  // CHECK-NEXT: volatile load {{.*}} @ci, i32 0, i32 0
213  // CHECK-NEXT: volatile load {{.*}} @ci, i32 0, i32 1
214
215  asm("nop"); // CHECK-NEXT: call void asm
216
217  (int)ci;
218  // CHECK-NEXT: volatile load {{.*}} @ci, i32 0, i32 0
219  // CHECK-NEXT: volatile load {{.*}} @ci, i32 0, i32 1
220
221  (bool)ci;
222  // CHECK-NEXT: volatile load {{.*}} @ci, i32 0, i32 0
223  // CHECK-NEXT: volatile load {{.*}} @ci, i32 0, i32 1
224  // CHECK-NEXT: icmp ne
225  // CHECK-NEXT: icmp ne
226  // CHECK-NEXT: or i1
227
228  // FIXME: should not load!
229  ci=ci;
230  // CHECK-NEXT: volatile load
231  // CHECK-NEXT: volatile load
232  // CHECK-NEXT: volatile store
233  // CHECK-NEXT: volatile store
234  // CHECK-NEXT: volatile load
235  // CHECK-NEXT: volatile load
236
237  asm("nop"); // CHECK-NEXT: call void asm
238
239  // FIXME: should not load at end
240  // Extra load in C++.
241  ci=ci=ci;
242  // CHECK-NEXT: volatile load
243  // CHECK-NEXT: volatile load
244  // CHECK-NEXT: volatile store
245  // CHECK-NEXT: volatile store
246  // CHECK-NEXT: volatile load
247  // CHECK-NEXT: volatile load
248  // CHECK-NEXT: volatile store
249  // CHECK-NEXT: volatile store
250  // CHECK-NEXT: volatile load
251  // CHECK-NEXT: volatile load
252
253  __imag ci = __imag ci = __imag ci;
254  // CHECK-NEXT: [[T:%.*]] = volatile load [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 1)
255  // CHECK-NEXT: volatile store [[INT]] [[T]], [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 1)
256  // CHECK-NEXT: [[T:%.*]] = volatile load [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 1)
257  // CHECK-NEXT: volatile store [[INT]] [[T]], [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 1)
258
259  __real (i = j);
260  // CHECK-NEXT: volatile load
261  // CHECK-NEXT: volatile store
262
263  __imag i;
264  // CHECK-NEXT: volatile load
265
266  // ============================================================
267  // FIXME: Test cases we get wrong.
268
269  // A use.  We load all of a into a copy of a, then load i.  gcc forgets to do
270  // the assignment.
271  // (a = a).i;
272
273  // ============================================================
274  // Test cases where we intentionally differ from gcc, due to suspected bugs in
275  // gcc.
276
277  // Not a use.  gcc forgets to do the assignment.
278  // CHECK-NEXT: call
279  ((a=a),a);
280
281  // Not a use.  gcc gets this wrong, it doesn't emit the copy!
282  // CHECK-NEXT: call
283  (void)(a=a);
284
285  // Not a use.  gcc got this wrong in 4.2 and omitted the side effects
286  // entirely, but it is fixed in 4.4.0.
287  __imag (i = j);
288  // CHECK-NEXT: volatile load
289  // CHECK-NEXT: volatile store
290
291  // C++ does an extra load here.  Note that we have to do full loads.
292  (float)(ci=ci);
293  // CHECK-NEXT: volatile load
294  // CHECK-NEXT: volatile load
295  // CHECK-NEXT: volatile store
296  // CHECK-NEXT: volatile store
297  // CHECK-NEXT: volatile load
298  // CHECK-NEXT: volatile load
299  // CHECK-NEXT: sitofp
300
301  // Not a use, bug?  gcc treats this as not a use, that's probably a
302  // bug due to tree folding ignoring volatile.
303  (int)(ci=ci);
304  // CHECK-NEXT: volatile load
305  // CHECK-NEXT: volatile load
306  // CHECK-NEXT: volatile store
307  // CHECK-NEXT: volatile store
308  // CHECK-NEXT: volatile load
309  // CHECK-NEXT: volatile load
310
311  // A use.
312  (float)(i=i);
313  // CHECK-NEXT: volatile load
314  // CHECK-NEXT: volatile store
315  // CHECK-NEXT: volatile load
316  // CHECK-NEXT: sitofp
317
318  // A use.  gcc treats this as not a use, that's probably a bug due to tree
319  // folding ignoring volatile.
320  (int)(i=i);
321  // CHECK-NEXT: volatile load
322  // CHECK-NEXT: volatile store
323  // CHECK-NEXT: volatile load
324
325  // A use.
326  -(i=j);
327  // CHECK-NEXT: volatile load
328  // CHECK-NEXT: volatile store
329  // CHECK-NEXT: volatile load
330  // CHECK-NEXT: sub
331
332  // A use.  gcc treats this a not a use, that's probably a bug due to tree
333  // folding ignoring volatile.
334  +(i=k);
335  // CHECK-NEXT: volatile load
336  // CHECK-NEXT: volatile store
337  // CHECK-NEXT: volatile load
338
339  // A use. gcc treats this a not a use, that's probably a bug due to tree
340  // folding ignoring volatile.
341  // FIXME: extra load at end
342  __real (ci=ci);
343  // CHECK-NEXT: volatile load
344  // CHECK-NEXT: volatile load
345  // CHECK-NEXT: volatile store
346  // CHECK-NEXT: volatile store
347  // CHECK-NEXT: volatile load
348
349  // A use.
350  i + 0;
351  // CHECK-NEXT: volatile load
352  // CHECK-NEXT: add
353
354  // A use.
355  (i=j) + i;
356  // CHECK-NEXT: volatile load
357  // CHECK-NEXT: volatile store
358  // CHECK-NEXT: volatile load
359  // CHECK-NEXT: volatile load
360  // CHECK-NEXT: add
361
362  // A use.  gcc treats this as not a use, that's probably a bug due to tree
363  // folding ignoring volatile.
364  (i=j) + 0;
365  // CHECK-NEXT: volatile load
366  // CHECK-NEXT: volatile store
367  // CHECK-NEXT: volatile load
368  // CHECK-NEXT: add
369
370  // FIXME: extra load of 'i'
371  (i,j)=k;
372  // CHECK-NEXT: volatile load [[INT]]* @k
373  // CHECK-NEXT: volatile load [[INT]]* @i
374  // CHECK-NEXT: volatile store {{.*}}, [[INT]]* @j
375
376  // FIXME: extra load of 'j'
377  (j=k,i)=i;
378  // CHECK-NEXT: volatile load [[INT]]* @i
379  // CHECK-NEXT: volatile load [[INT]]* @k
380  // CHECK-NEXT: volatile store {{.*}}, [[INT]]* @j
381  // CHECK-NEXT: volatile load [[INT]]* @j
382  // CHECK-NEXT: volatile store {{.*}}, [[INT]]* @i
383}
384