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