Clang Project

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