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