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
4 volatile int i, j, k;
5 volatile int ar[5];
6 volatile char c;
7 // CHECK: @ci = global [[CINT:.*]] zeroinitializer
8 volatile _Complex int ci;
9 volatile 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;
17 int printf(const char *, ...);
18 
19 
20 // CHECK: define void @{{.*}}test
test()21 void 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]], [[INT]]* getelementptr inbounds ([[CINT]], [[CINT]]* @ci, i32 0, i32 0)
30   // CHECK-NEXT: load volatile [[INT]], [[INT]]* getelementptr inbounds ([[CINT]], [[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]], [[INT]]* getelementptr inbounds ([[CINT]], [[CINT]]* @ci, i32 0, i32 0)
41   // CHECK-NEXT: [[I:%.*]] = load volatile [[INT]], [[INT]]* getelementptr inbounds ([[CINT]], [[CINT]]* @ci, i32 0, i32 1)
42   // CHECK-NEXT: store volatile [[INT]] [[R]], [[INT]]* getelementptr inbounds ([[CINT]], [[CINT]]* @ci, i32 0, i32 0)
43   // CHECK-NEXT: store volatile [[INT]] [[I]], [[INT]]* getelementptr inbounds ([[CINT]], [[CINT]]* @ci, i32 0, i32 1)
44 
45   (void)(i=j);
46   // CHECK-NEXT: [[T:%.*]] = load volatile [[INT]], [[INT]]* @j
47   // CHECK-NEXT: store volatile [[INT]] [[T]], [[INT]]* @i
48 
49   ci+=ci;
50   // CHECK-NEXT: [[R1:%.*]] = load volatile [[INT]], [[INT]]* getelementptr inbounds ([[CINT]], [[CINT]]* @ci, i32 0, i32 0)
51   // CHECK-NEXT: [[I1:%.*]] = load volatile [[INT]], [[INT]]* getelementptr inbounds ([[CINT]], [[CINT]]* @ci, i32 0, i32 1)
52   // CHECK-NEXT: [[R2:%.*]] = load volatile [[INT]], [[INT]]* getelementptr inbounds ([[CINT]], [[CINT]]* @ci, i32 0, i32 0)
53   // CHECK-NEXT: [[I2:%.*]] = load volatile [[INT]], [[INT]]* getelementptr inbounds ([[CINT]], [[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]], [[CINT]]* @ci, i32 0, i32 0)
58   // CHECK-NEXT: store volatile [[INT]] [[I]], [[INT]]* getelementptr inbounds ([[CINT]], [[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]], [[INT]]* getelementptr inbounds ([[CINT]], [[CINT]]* @ci, i32 0, i32 0)
63   // CHECK-NEXT: [[I1:%.*]] = load volatile [[INT]], [[INT]]* getelementptr inbounds ([[CINT]], [[CINT]]* @ci, i32 0, i32 1)
64   // CHECK-NEXT: [[R2:%.*]] = load volatile [[INT]], [[INT]]* getelementptr inbounds ([[CINT]], [[CINT]]* @ci, i32 0, i32 0)
65   // CHECK-NEXT: [[I2:%.*]] = load volatile [[INT]], [[INT]]* getelementptr inbounds ([[CINT]], [[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]], [[CINT]]* @ci, i32 0, i32 0)
69   // CHECK-NEXT: store volatile [[INT]] [[I]], [[INT]]* getelementptr inbounds ([[CINT]], [[CINT]]* @ci, i32 0, i32 1)
70   // CHECK-NEXT: [[R1:%.*]] = load volatile [[INT]], [[INT]]* getelementptr inbounds ([[CINT]], [[CINT]]* @ci, i32 0, i32 0)
71   // CHECK-NEXT: [[I1:%.*]] = load volatile [[INT]], [[INT]]* getelementptr inbounds ([[CINT]], [[CINT]]* @ci, i32 0, i32 1)
72   // CHECK-NEXT: [[R2:%.*]] = load volatile [[INT]], [[INT]]* getelementptr inbounds ([[CINT]], [[CINT]]* @ci, i32 0, i32 0)
73   // CHECK-NEXT: [[I2:%.*]] = load volatile [[INT]], [[INT]]* getelementptr inbounds ([[CINT]], [[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]], [[INT]]* @i
164   // CHECK-NEXT: store volatile {{.*}}, [[INT]]* @i
165 
166   (i=j,k=j);
167   // CHECK-NEXT: load volatile [[INT]], [[INT]]* @j
168   // CHECK-NEXT: store volatile {{.*}}, [[INT]]* @i
169   // CHECK-NEXT: load volatile [[INT]], [[INT]]* @j
170   // CHECK-NEXT: store volatile {{.*}}, [[INT]]* @k
171 
172   (i=j,k);
173   // CHECK-NEXT: load volatile [[INT]], [[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]], [[INT]]* getelementptr inbounds ([[CINT]], [[CINT]]* @ci, i32 0, i32 1)
229   // CHECK-NEXT: store volatile [[INT]] [[T]], [[INT]]* getelementptr inbounds ([[CINT]], [[CINT]]* @ci, i32 0, i32 1)
230   // CHECK-NEXT: [[T:%.*]] = load volatile [[INT]], [[INT]]* getelementptr inbounds ([[CINT]], [[CINT]]* @ci, i32 0, i32 1)
231   // CHECK-NEXT: store volatile [[INT]] [[T]], [[INT]]* getelementptr inbounds ([[CINT]], [[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]], [[INT]]* @k
343   // CHECK-NEXT: store volatile {{.*}}, [[INT]]* @j
344 
345   (j=k,i)=i;
346   // CHECK-NEXT: load volatile [[INT]], [[INT]]* @i
347   // CHECK-NEXT: load volatile [[INT]], [[INT]]* @k
348   // CHECK-NEXT: store volatile {{.*}}, [[INT]]* @j
349   // CHECK-NEXT: store volatile {{.*}}, [[INT]]* @i
350 
351   // CHECK-NEXT: ret void
352 }
353