volatile-1.cpp revision 2a41637a995affa1563f4d82a8b026e326a2faa0
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  // should not load
26  i;
27
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
49  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)
59
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
111  __real i;
112
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
146  // FIXME: the phi-equivalent is unnecessary
147  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
153  // CHECK-NEXT: store [[INT]]* @i
154  // CHECK-NEXT: br label
155  // CHECK: volatile load
156  // CHECK-NEXT: volatile store
157  // CHECK-NEXT: store [[INT]]* @j
158  // CHECK-NEXT: br label
159  // CHECK: load [[INT]]**
160
161  (void)(i,(i=i));
162  // CHECK-NEXT: volatile load
163  // CHECK-NEXT: volatile store
164
165  i=i,k;
166  // CHECK-NEXT: volatile load [[INT]]* @i
167  // CHECK-NEXT: volatile store {{.*}}, [[INT]]* @i
168
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
175  (i=j,k);
176  // CHECK-NEXT: volatile load [[INT]]* @j
177  // CHECK-NEXT: volatile store {{.*}}, [[INT]]* @i
178
179  (i,j);
180
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
196  ci;
197
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
211  ci=ci;
212  // CHECK-NEXT: volatile load
213  // CHECK-NEXT: volatile load
214  // CHECK-NEXT: volatile store
215  // CHECK-NEXT: volatile store
216
217  asm("nop"); // CHECK-NEXT: call void asm
218
219  // 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
229
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;
241
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.
317  __real (ci=ci);
318  // CHECK-NEXT: volatile load
319  // CHECK-NEXT: volatile load
320  // CHECK-NEXT: volatile store
321  // CHECK-NEXT: volatile store
322
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
344  (i,j)=k;
345  // CHECK-NEXT: volatile load [[INT]]* @k
346  // CHECK-NEXT: volatile store {{.*}}, [[INT]]* @j
347
348  (j=k,i)=i;
349  // CHECK-NEXT: volatile load [[INT]]* @k
350  // CHECK-NEXT: volatile store {{.*}}, [[INT]]* @j
351  // CHECK-NEXT: volatile load [[INT]]* @i
352  // CHECK-NEXT: volatile store {{.*}}, [[INT]]* @i
353
354  // CHECK-NEXT: ret void
355}
356