• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // RUN: %clang_cc1 -Wno-return-type -Wno-unused-value -emit-llvm %s -w -o - | FileCheck %s
2 
3 // CHECK: @i = {{(dso_local )?}}global [[INT:i[0-9]+]] 0
4 volatile int i, j, k;
5 volatile int ar[5];
6 volatile char c;
7 // CHECK: @ci = {{(dso_local )?}}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 // Note that these test results are very much specific to C!
21 // Assignments in C++ yield l-values, not r-values, and the situations
22 // that do implicit lvalue-to-rvalue conversion are substantially
23 // reduced.
24 
25 // CHECK-LABEL: define {{.*}}void @test()
test()26 void test() {
27   // CHECK: load volatile [[INT]], [[INT]]* @i
28   i;
29   // CHECK-NEXT: load volatile [[INT]], [[INT]]* getelementptr inbounds ([[CINT]], [[CINT]]* @ci, i32 0, i32 0), align 4
30   // CHECK-NEXT: load volatile [[INT]], [[INT]]* getelementptr inbounds ([[CINT]], [[CINT]]* @ci, i32 0, i32 1), align 4
31   // CHECK-NEXT: sitofp [[INT]]
32   (float)(ci);
33   // CHECK-NEXT: load volatile [[INT]], [[INT]]* getelementptr inbounds ([[CINT]], [[CINT]]* @ci, i32 0, i32 0), align 4
34   // CHECK-NEXT: load volatile [[INT]], [[INT]]* getelementptr inbounds ([[CINT]], [[CINT]]* @ci, i32 0, i32 1), align 4
35   (void)ci;
36   // CHECK-NEXT: bitcast
37   // CHECK-NEXT: memcpy
38   (void)a;
39   // CHECK-NEXT: [[R:%.*]] = load volatile [[INT]], [[INT]]* getelementptr inbounds ([[CINT]], [[CINT]]* @ci, i32 0, i32 0), align 4
40   // CHECK-NEXT: [[I:%.*]] = load volatile [[INT]], [[INT]]* getelementptr inbounds ([[CINT]], [[CINT]]* @ci, i32 0, i32 1), align 4
41   // CHECK-NEXT: store volatile [[INT]] [[R]], [[INT]]* getelementptr inbounds ([[CINT]], [[CINT]]* @ci, i32 0, i32 0), align 4
42   // CHECK-NEXT: store volatile [[INT]] [[I]], [[INT]]* getelementptr inbounds ([[CINT]], [[CINT]]* @ci, i32 0, i32 1), align 4
43   (void)(ci=ci);
44   // CHECK-NEXT: [[T:%.*]] = load volatile [[INT]], [[INT]]* @j
45   // CHECK-NEXT: store volatile [[INT]] [[T]], [[INT]]* @i
46   (void)(i=j);
47   // CHECK-NEXT: [[R1:%.*]] = load volatile [[INT]], [[INT]]* getelementptr inbounds ([[CINT]], [[CINT]]* @ci, i32 0, i32 0), align 4
48   // CHECK-NEXT: [[I1:%.*]] = load volatile [[INT]], [[INT]]* getelementptr inbounds ([[CINT]], [[CINT]]* @ci, i32 0, i32 1), align 4
49   // CHECK-NEXT: [[R2:%.*]] = load volatile [[INT]], [[INT]]* getelementptr inbounds ([[CINT]], [[CINT]]* @ci, i32 0, i32 0), align 4
50   // CHECK-NEXT: [[I2:%.*]] = load volatile [[INT]], [[INT]]* getelementptr inbounds ([[CINT]], [[CINT]]* @ci, i32 0, i32 1), align 4
51   // Not sure why they're ordered this way.
52   // CHECK-NEXT: [[R:%.*]] = add [[INT]] [[R2]], [[R1]]
53   // CHECK-NEXT: [[I:%.*]] = add [[INT]] [[I2]], [[I1]]
54   // CHECK-NEXT: store volatile [[INT]] [[R]], [[INT]]* getelementptr inbounds ([[CINT]], [[CINT]]* @ci, i32 0, i32 0), align 4
55   // CHECK-NEXT: store volatile [[INT]] [[I]], [[INT]]* getelementptr inbounds ([[CINT]], [[CINT]]* @ci, i32 0, i32 1), align 4
56   ci+=ci;
57 
58   // CHECK-NEXT: [[R1:%.*]] = load volatile [[INT]], [[INT]]* getelementptr inbounds ([[CINT]], [[CINT]]* @ci, i32 0, i32 0), align 4
59   // CHECK-NEXT: [[I1:%.*]] = load volatile [[INT]], [[INT]]* getelementptr inbounds ([[CINT]], [[CINT]]* @ci, i32 0, i32 1), align 4
60   // CHECK-NEXT: [[R2:%.*]] = load volatile [[INT]], [[INT]]* getelementptr inbounds ([[CINT]], [[CINT]]* @ci, i32 0, i32 0), align 4
61   // CHECK-NEXT: [[I2:%.*]] = load volatile [[INT]], [[INT]]* getelementptr inbounds ([[CINT]], [[CINT]]* @ci, i32 0, i32 1), align 4
62   // CHECK-NEXT: [[R:%.*]] = add [[INT]] [[R2]], [[R1]]
63   // CHECK-NEXT: [[I:%.*]] = add [[INT]] [[I2]], [[I1]]
64   // CHECK-NEXT: store volatile [[INT]] [[R]], [[INT]]* getelementptr inbounds ([[CINT]], [[CINT]]* @ci, i32 0, i32 0), align 4
65   // CHECK-NEXT: store volatile [[INT]] [[I]], [[INT]]* getelementptr inbounds ([[CINT]], [[CINT]]* @ci, i32 0, i32 1), align 4
66   // CHECK-NEXT: [[R2:%.*]] = load volatile [[INT]], [[INT]]* getelementptr inbounds ([[CINT]], [[CINT]]* @ci, i32 0, i32 0), align 4
67   // CHECK-NEXT: [[I2:%.*]] = load volatile [[INT]], [[INT]]* getelementptr inbounds ([[CINT]], [[CINT]]* @ci, i32 0, i32 1), align 4
68   // These additions can be elided
69   // CHECK-NEXT: add [[INT]] [[R]], [[R2]]
70   // CHECK-NEXT: add [[INT]] [[I]], [[I2]]
71   (ci += ci) + ci;
72   // CHECK-NEXT: call void asm
73   asm("nop");
74   // CHECK-NEXT: load volatile
75   // CHECK-NEXT: load volatile
76   // CHECK-NEXT: add nsw [[INT]]
77   // CHECK-NEXT: store volatile
78   // CHECK-NEXT: load volatile
79   // CHECK-NEXT: add nsw [[INT]]
80   (i += j) + k;
81   // CHECK-NEXT: call void asm
82   asm("nop");
83   // CHECK-NEXT: load volatile
84   // CHECK-NEXT: load volatile
85   // CHECK-NEXT: add nsw [[INT]]
86   // CHECK-NEXT: store volatile
87   // CHECK-NEXT: add nsw [[INT]]
88   (i += j) + 1;
89   // CHECK-NEXT: call void asm
90   asm("nop");
91   // CHECK-NEXT: load volatile
92   // CHECK-NEXT: load volatile
93   // CHECK-NEXT: load volatile
94   // CHECK-NEXT: load volatile
95   // CHECK-NEXT: add [[INT]]
96   // CHECK-NEXT: add [[INT]]
97   ci+ci;
98 
99   // CHECK-NEXT: load volatile
100   __real i;
101   // CHECK-NEXT: load volatile
102   // CHECK-NEXT: load volatile
103   +ci;
104   // CHECK-NEXT: call void asm
105   asm("nop");
106   // CHECK-NEXT: load volatile
107   // CHECK-NEXT: store volatile
108   (void)(i=i);
109   // CHECK-NEXT: load volatile
110   // CHECK-NEXT: store volatile
111   // CHECK-NEXT: sitofp
112   (float)(i=i);
113   // CHECK-NEXT: load volatile
114   (void)i;
115   // CHECK-NEXT: load volatile
116   // CHECK-NEXT: store volatile
117   i=i;
118   // CHECK-NEXT: load volatile
119   // CHECK-NEXT: store volatile
120   // CHECK-NEXT: store volatile
121   i=i=i;
122 #ifndef __cplusplus
123   // CHECK-NEXT: load volatile
124   // CHECK-NEXT: store volatile
125   (void)__builtin_choose_expr(0, i=i, j=j);
126 #endif
127   // CHECK-NEXT: load volatile
128   // CHECK-NEXT: icmp
129   // CHECK-NEXT: br i1
130   // CHECK: load volatile
131   // CHECK-NEXT: store volatile
132   // CHECK-NEXT: br label
133   // CHECK: load volatile
134   // CHECK-NEXT: store volatile
135   // CHECK-NEXT: br label
136   k ? (i=i) : (j=j);
137   // CHECK: phi
138   // CHECK-NEXT: load volatile
139   // CHECK-NEXT: load volatile
140   // CHECK-NEXT: store volatile
141   (void)(i,(i=i));
142   // CHECK-NEXT: load volatile
143   // CHECK-NEXT: store volatile
144   // CHECK-NEXT: load volatile
145   i=i,i;
146   // CHECK-NEXT: load volatile
147   // CHECK-NEXT: store volatile
148   // CHECK-NEXT: load volatile
149   // CHECK-NEXT: store volatile
150   (i=j,k=j);
151   // CHECK-NEXT: load volatile
152   // CHECK-NEXT: store volatile
153   // CHECK-NEXT: load volatile
154   (i=j,k);
155   // CHECK-NEXT: load volatile
156   // CHECK-NEXT: load volatile
157   (i,j);
158   // CHECK-NEXT: load volatile
159   // CHECK-NEXT: trunc
160   // CHECK-NEXT: store volatile
161   // CHECK-NEXT: sext
162   // CHECK-NEXT: store volatile
163   i=c=k;
164   // CHECK-NEXT: load volatile
165   // CHECK-NEXT: load volatile
166   // CHECK-NEXT: add nsw [[INT]]
167   // CHECK-NEXT: store volatile
168   i+=k;
169   // CHECK-NEXT: load volatile
170   // CHECK-NEXT: load volatile
171   ci;
172 #ifndef __cplusplus
173   // CHECK-NEXT: load volatile
174   // CHECK-NEXT: load volatile
175   (int)ci;
176   // CHECK-NEXT: load volatile
177   // CHECK-NEXT: load volatile
178   // CHECK-NEXT: icmp ne
179   // CHECK-NEXT: icmp ne
180   // CHECK-NEXT: or i1
181   (_Bool)ci;
182 #endif
183   // CHECK-NEXT: load volatile
184   // CHECK-NEXT: load volatile
185   // CHECK-NEXT: store volatile
186   // CHECK-NEXT: store volatile
187   ci=ci;
188   // CHECK-NEXT: load volatile
189   // CHECK-NEXT: load volatile
190   // CHECK-NEXT: store volatile
191   // CHECK-NEXT: store volatile
192   // CHECK-NEXT: store volatile
193   // CHECK-NEXT: store volatile
194   ci=ci=ci;
195   // CHECK-NEXT: [[T:%.*]] = load volatile [[INT]], [[INT]]* getelementptr inbounds ([[CINT]], [[CINT]]* @ci, i32 0, i32 1)
196   // CHECK-NEXT: store volatile [[INT]] [[T]], [[INT]]* getelementptr inbounds ([[CINT]], [[CINT]]* @ci, i32 0, i32 1)
197   // CHECK-NEXT: store volatile [[INT]] [[T]], [[INT]]* getelementptr inbounds ([[CINT]], [[CINT]]* @ci, i32 0, i32 1)
198   __imag ci = __imag ci = __imag ci;
199   // CHECK-NEXT: load volatile
200   // CHECK-NEXT: store volatile
201   __real (i = j);
202   // CHECK-NEXT: load volatile
203   __imag i;
204 
205   // ============================================================
206   // FIXME: Test cases we get wrong.
207 
208   // A use.  We load all of a into a copy of a, then load i.  gcc forgets to do
209   // the assignment.
210   // (a = a).i;
211 
212   // ============================================================
213   // Test cases where we intentionally differ from gcc, due to suspected bugs in
214   // gcc.
215 
216   // Not a use.  gcc forgets to do the assignment.
217   // CHECK-NEXT: call void @llvm.memcpy{{.*}}, i1 true
218   // CHECK-NEXT: bitcast
219   // CHECK-NEXT: call void @llvm.memcpy{{.*}}, i1 true
220   ((a=a),a);
221 
222   // Not a use.  gcc gets this wrong, it doesn't emit the copy!
223   // (void)(a=a);
224 
225   // Not a use.  gcc got this wrong in 4.2 and omitted the side effects
226   // entirely, but it is fixed in 4.4.0.
227   // CHECK-NEXT: load volatile
228   // CHECK-NEXT: store volatile
229   __imag (i = j);
230 
231 #ifndef __cplusplus
232   // A use of the real part
233   // CHECK-NEXT: load volatile
234   // CHECK-NEXT: load volatile
235   // CHECK-NEXT: store volatile
236   // CHECK-NEXT: store volatile
237   // CHECK-NEXT: sitofp
238   (float)(ci=ci);
239   // Not a use, bug?  gcc treats this as not a use, that's probably a bug due to
240   // tree folding ignoring volatile.
241   // CHECK-NEXT: load volatile
242   // CHECK-NEXT: load volatile
243   // CHECK-NEXT: store volatile
244   // CHECK-NEXT: store volatile
245   (int)(ci=ci);
246 #endif
247 
248   // A use.
249   // CHECK-NEXT: load volatile
250   // CHECK-NEXT: store volatile
251   // CHECK-NEXT: sitofp
252   (float)(i=i);
253   // A use.  gcc treats this as not a use, that's probably a bug due to tree
254   // folding ignoring volatile.
255   // CHECK-NEXT: load volatile
256   // CHECK-NEXT: store volatile
257   (int)(i=i);
258 
259   // A use.
260   // CHECK-NEXT: load volatile
261   // CHECK-NEXT: store volatile
262   // CHECK-NEXT: sub
263   -(i=j);
264   // A use.  gcc treats this a not a use, that's probably a bug due to tree
265   // folding ignoring volatile.
266   // CHECK-NEXT: load volatile
267   // CHECK-NEXT: store volatile
268   +(i=k);
269 
270   // A use. gcc treats this a not a use, that's probably a bug due to tree
271   // folding ignoring volatile.
272   // CHECK-NEXT: load volatile
273   // CHECK-NEXT: load volatile
274   // CHECK-NEXT: store volatile
275   // CHECK-NEXT: store volatile
276   __real (ci=ci);
277 
278   // A use.
279   // CHECK-NEXT: load volatile
280   // CHECK-NEXT: add
281   i + 0;
282   // A use.
283   // CHECK-NEXT: load volatile
284   // CHECK-NEXT: store volatile
285   // CHECK-NEXT: load volatile
286   // CHECK-NEXT: add
287   (i=j) + i;
288   // A use.  gcc treats this as not a use, that's probably a bug due to tree
289   // folding ignoring volatile.
290   // CHECK-NEXT: load volatile
291   // CHECK-NEXT: store volatile
292   // CHECK-NEXT: add
293   (i=j) + 0;
294 
295 #ifdef __cplusplus
296   (i,j)=k;
297   (j=k,i)=i;
298   struct { int x; } s, s1;
299   printf("s is at %p\n", &s);
300   printf("s is at %p\n", &(s = s1));
301   printf("s.x is at %p\n", &((s = s1).x));
302 #endif
303 }
304 
305 extern volatile enum X x;
306 // CHECK-LABEL: define {{.*}}void @test1()
test1()307 void test1() {
308   extern void test1_helper(void);
309   test1_helper();
310   // CHECK: call {{.*}}void @test1_helper()
311   // CHECK-NEXT: ret void
312   x;
313   (void) x;
314   return x;
315 }
316 
317 // CHECK: define {{.*}} @test2()
test2()318 int test2() {
319   // CHECK: load volatile i32, i32*
320   // CHECK-NEXT: load volatile i32, i32*
321   // CHECK-NEXT: load volatile i32, i32*
322   // CHECK-NEXT: add i32
323   // CHECK-NEXT: add i32
324   // CHECK-NEXT: store volatile i32
325   // CHECK-NEXT: ret i32
326   return i += ci;
327 }
328