• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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