1// RUN: %clang_cc1 -Wno-return-type -Wno-unused-value -emit-llvm %s -o - | FileCheck %s
2
3// CHECK: @i = common global [[INT:i[0-9]+]] 0
4volatile int i, j, k;
5volatile int ar[5];
6volatile char c;
7// CHECK: @ci = common 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// 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()
26void test() {
27  // CHECK: load volatile [[INT]]* @i
28  i;
29  // CHECK-NEXT: load volatile [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 0), align 4
30  // CHECK-NEXT: load volatile [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 1), align 4
31  // CHECK-NEXT: sitofp [[INT]]
32  (float)(ci);
33  // CHECK-NEXT: load volatile [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 0), align 4
34  // CHECK-NEXT: load volatile [[INT]]* getelementptr inbounds ([[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]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 0), align 4
40  // CHECK-NEXT: [[I:%.*]] = load volatile [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 1), align 4
41  // CHECK-NEXT: store volatile [[INT]] [[R]], [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 0), align 4
42  // CHECK-NEXT: store volatile [[INT]] [[I]], [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 1), align 4
43  (void)(ci=ci);
44  // CHECK-NEXT: [[T:%.*]] = load volatile [[INT]]* @j
45  // CHECK-NEXT: store volatile [[INT]] [[T]], [[INT]]* @i
46  (void)(i=j);
47  // CHECK-NEXT: [[R1:%.*]] = load volatile [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 0), align 4
48  // CHECK-NEXT: [[I1:%.*]] = load volatile [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 1), align 4
49  // CHECK-NEXT: [[R2:%.*]] = load volatile [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 0), align 4
50  // CHECK-NEXT: [[I2:%.*]] = load volatile [[INT]]* getelementptr inbounds ([[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]]* @ci, i32 0, i32 0), align 4
55  // CHECK-NEXT: store volatile [[INT]] [[I]], [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 1), align 4
56  ci+=ci;
57
58  // CHECK-NEXT: [[R1:%.*]] = load volatile [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 0), align 4
59  // CHECK-NEXT: [[I1:%.*]] = load volatile [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 1), align 4
60  // CHECK-NEXT: [[R2:%.*]] = load volatile [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 0), align 4
61  // CHECK-NEXT: [[I2:%.*]] = load volatile [[INT]]* getelementptr inbounds ([[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]]* @ci, i32 0, i32 0), align 4
65  // CHECK-NEXT: store volatile [[INT]] [[I]], [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 1), align 4
66  // CHECK-NEXT: [[R2:%.*]] = load volatile [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 0), align 4
67  // CHECK-NEXT: [[I2:%.*]] = load volatile [[INT]]* getelementptr inbounds ([[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]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 1)
196  // CHECK-NEXT: store volatile [[INT]] [[T]], [[INT]]* getelementptr inbounds ([[CINT]]* @ci, i32 0, i32 1)
197  // CHECK-NEXT: store volatile [[INT]] [[T]], [[INT]]* getelementptr inbounds ([[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
305extern volatile enum X x;
306// CHECK-LABEL: define void @test1()
307void 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()
318int test2() {
319  // CHECK: load volatile i32*
320  // CHECK-NEXT: load volatile i32*
321  // CHECK-NEXT: load volatile 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