xref: /aosp_15_r20/external/clang/test/CodeGen/builtins-arm-exclusive.c (revision 67e74705e28f6214e480b399dd47ea732279e315)
1*67e74705SXin Li // RUN: %clang_cc1 -Wall -Werror -triple thumbv8-linux-gnueabi -fno-signed-char -emit-llvm -o - %s | opt -S -mem2reg | FileCheck %s
2*67e74705SXin Li // RUN: %clang_cc1 -Wall -Werror -triple arm64-apple-ios7.0 -emit-llvm -o - %s | opt -S -mem2reg | FileCheck %s --check-prefix=CHECK-ARM64
3*67e74705SXin Li 
4*67e74705SXin Li 
5*67e74705SXin Li struct Simple {
6*67e74705SXin Li   char a, b;
7*67e74705SXin Li };
8*67e74705SXin Li 
test_ldrex(char * addr,long long * addr64,float * addrfloat)9*67e74705SXin Li int test_ldrex(char *addr, long long *addr64, float *addrfloat) {
10*67e74705SXin Li // CHECK-LABEL: @test_ldrex
11*67e74705SXin Li // CHECK-ARM64-LABEL: @test_ldrex
12*67e74705SXin Li   int sum = 0;
13*67e74705SXin Li   sum += __builtin_arm_ldrex(addr);
14*67e74705SXin Li // CHECK: [[INTRES:%.*]] = call i32 @llvm.arm.ldrex.p0i8(i8* %addr)
15*67e74705SXin Li // CHECK: trunc i32 [[INTRES]] to i8
16*67e74705SXin Li 
17*67e74705SXin Li // CHECK-ARM64: [[INTRES:%.*]] = call i64 @llvm.aarch64.ldxr.p0i8(i8* %addr)
18*67e74705SXin Li // CHECK-ARM64: trunc i64 [[INTRES]] to i8
19*67e74705SXin Li 
20*67e74705SXin Li   sum += __builtin_arm_ldrex((short *)addr);
21*67e74705SXin Li // CHECK: [[ADDR16:%.*]] = bitcast i8* %addr to i16*
22*67e74705SXin Li // CHECK: [[INTRES:%.*]] = call i32 @llvm.arm.ldrex.p0i16(i16* [[ADDR16]])
23*67e74705SXin Li // CHECK: trunc i32 [[INTRES]] to i16
24*67e74705SXin Li 
25*67e74705SXin Li // CHECK-ARM64: [[ADDR16:%.*]] = bitcast i8* %addr to i16*
26*67e74705SXin Li // CHECK-ARM64: [[INTRES:%.*]] = call i64 @llvm.aarch64.ldxr.p0i16(i16* [[ADDR16]])
27*67e74705SXin Li // CHECK-ARM64: trunc i64 [[INTRES]] to i16
28*67e74705SXin Li 
29*67e74705SXin Li   sum += __builtin_arm_ldrex((int *)addr);
30*67e74705SXin Li // CHECK: [[ADDR32:%.*]] = bitcast i8* %addr to i32*
31*67e74705SXin Li // CHECK: call i32 @llvm.arm.ldrex.p0i32(i32* [[ADDR32]])
32*67e74705SXin Li 
33*67e74705SXin Li // CHECK-ARM64: [[ADDR32:%.*]] = bitcast i8* %addr to i32*
34*67e74705SXin Li // CHECK-ARM64: [[INTRES:%.*]] = call i64 @llvm.aarch64.ldxr.p0i32(i32* [[ADDR32]])
35*67e74705SXin Li // CHECK-ARM64: trunc i64 [[INTRES]] to i32
36*67e74705SXin Li 
37*67e74705SXin Li   sum += __builtin_arm_ldrex((long long *)addr);
38*67e74705SXin Li // CHECK: [[TMP4:%.*]] = bitcast i8* %addr to i64*
39*67e74705SXin Li // CHECK: [[TMP5:%.*]] = bitcast i64* [[TMP4]] to i8*
40*67e74705SXin Li // CHECK: call { i32, i32 } @llvm.arm.ldrexd(i8* [[TMP5]])
41*67e74705SXin Li 
42*67e74705SXin Li // CHECK-ARM64: [[ADDR64:%.*]] = bitcast i8* %addr to i64*
43*67e74705SXin Li // CHECK-ARM64: call i64 @llvm.aarch64.ldxr.p0i64(i64* [[ADDR64]])
44*67e74705SXin Li 
45*67e74705SXin Li   sum += __builtin_arm_ldrex(addr64);
46*67e74705SXin Li // CHECK: [[ADDR64_AS8:%.*]] = bitcast i64* %addr64 to i8*
47*67e74705SXin Li // CHECK: call { i32, i32 } @llvm.arm.ldrexd(i8* [[ADDR64_AS8]])
48*67e74705SXin Li 
49*67e74705SXin Li // CHECK-ARM64: call i64 @llvm.aarch64.ldxr.p0i64(i64* %addr64)
50*67e74705SXin Li 
51*67e74705SXin Li   sum += __builtin_arm_ldrex(addrfloat);
52*67e74705SXin Li // CHECK: [[INTADDR:%.*]] = bitcast float* %addrfloat to i32*
53*67e74705SXin Li // CHECK: [[INTRES:%.*]] = call i32 @llvm.arm.ldrex.p0i32(i32* [[INTADDR]])
54*67e74705SXin Li // CHECK: bitcast i32 [[INTRES]] to float
55*67e74705SXin Li 
56*67e74705SXin Li // CHECK-ARM64: [[INTADDR:%.*]] = bitcast float* %addrfloat to i32*
57*67e74705SXin Li // CHECK-ARM64: [[INTRES:%.*]] = call i64 @llvm.aarch64.ldxr.p0i32(i32* [[INTADDR]])
58*67e74705SXin Li // CHECK-ARM64: [[TRUNCRES:%.*]] = trunc i64 [[INTRES]] to i32
59*67e74705SXin Li // CHECK-ARM64: bitcast i32 [[TRUNCRES]] to float
60*67e74705SXin Li 
61*67e74705SXin Li   sum += __builtin_arm_ldrex((double *)addr);
62*67e74705SXin Li // CHECK: [[TMP4:%.*]] = bitcast i8* %addr to double*
63*67e74705SXin Li // CHECK: [[TMP5:%.*]] = bitcast double* [[TMP4]] to i8*
64*67e74705SXin Li // CHECK: [[STRUCTRES:%.*]] = call { i32, i32 } @llvm.arm.ldrexd(i8* [[TMP5]])
65*67e74705SXin Li // CHECK: [[RESHI:%.*]] = extractvalue { i32, i32 } [[STRUCTRES]], 1
66*67e74705SXin Li // CHECK: [[RESLO:%.*]] = extractvalue { i32, i32 } [[STRUCTRES]], 0
67*67e74705SXin Li // CHECK: [[RESHI64:%.*]] = zext i32 [[RESHI]] to i64
68*67e74705SXin Li // CHECK: [[RESLO64:%.*]] = zext i32 [[RESLO]] to i64
69*67e74705SXin Li // CHECK: [[RESHIHI:%.*]] = shl nuw i64 [[RESHI64]], 32
70*67e74705SXin Li // CHECK: [[INTRES:%.*]] = or i64 [[RESHIHI]], [[RESLO64]]
71*67e74705SXin Li // CHECK: bitcast i64 [[INTRES]] to double
72*67e74705SXin Li 
73*67e74705SXin Li // CHECK-ARM64: [[TMP4:%.*]] = bitcast i8* %addr to double*
74*67e74705SXin Li // CHECK-ARM64: [[TMP5:%.*]] = bitcast double* [[TMP4]] to i64*
75*67e74705SXin Li // CHECK-ARM64: [[INTRES:%.*]] = call i64 @llvm.aarch64.ldxr.p0i64(i64* [[TMP5]])
76*67e74705SXin Li // CHECK-ARM64: bitcast i64 [[INTRES]] to double
77*67e74705SXin Li 
78*67e74705SXin Li   sum += *__builtin_arm_ldrex((int **)addr);
79*67e74705SXin Li // CHECK: [[TMP4:%.*]] = bitcast i8* %addr to i32**
80*67e74705SXin Li // CHECK: [[TMP5:%.*]] = bitcast i32** [[TMP4]] to i32*
81*67e74705SXin Li // CHECK: [[INTRES:%.*]] = call i32 @llvm.arm.ldrex.p0i32(i32* [[TMP5]])
82*67e74705SXin Li // CHECK: inttoptr i32 [[INTRES]] to i32*
83*67e74705SXin Li 
84*67e74705SXin Li // CHECK-ARM64: [[TMP4:%.*]] = bitcast i8* %addr to i32**
85*67e74705SXin Li // CHECK-ARM64: [[TMP5:%.*]] = bitcast i32** [[TMP4]] to i64*
86*67e74705SXin Li // CHECK-ARM64: [[INTRES:%.*]] = call i64 @llvm.aarch64.ldxr.p0i64(i64* [[TMP5]])
87*67e74705SXin Li // CHECK-ARM64: inttoptr i64 [[INTRES]] to i32*
88*67e74705SXin Li 
89*67e74705SXin Li   sum += __builtin_arm_ldrex((struct Simple **)addr)->a;
90*67e74705SXin Li // CHECK: [[TMP4:%.*]] = bitcast i8* %addr to %struct.Simple**
91*67e74705SXin Li // CHECK: [[TMP5:%.*]] = bitcast %struct.Simple** [[TMP4]] to i32*
92*67e74705SXin Li // CHECK: [[INTRES:%.*]] = call i32 @llvm.arm.ldrex.p0i32(i32* [[TMP5]])
93*67e74705SXin Li // CHECK: inttoptr i32 [[INTRES]] to %struct.Simple*
94*67e74705SXin Li 
95*67e74705SXin Li // CHECK-ARM64: [[TMP4:%.*]] = bitcast i8* %addr to %struct.Simple**
96*67e74705SXin Li // CHECK-ARM64: [[TMP5:%.*]] = bitcast %struct.Simple** [[TMP4]] to i64*
97*67e74705SXin Li // CHECK-ARM64: [[INTRES:%.*]] = call i64 @llvm.aarch64.ldxr.p0i64(i64* [[TMP5]])
98*67e74705SXin Li // CHECK-ARM64: inttoptr i64 [[INTRES]] to %struct.Simple*
99*67e74705SXin Li   return sum;
100*67e74705SXin Li }
101*67e74705SXin Li 
test_ldaex(char * addr,long long * addr64,float * addrfloat)102*67e74705SXin Li int test_ldaex(char *addr, long long *addr64, float *addrfloat) {
103*67e74705SXin Li // CHECK-LABEL: @test_ldaex
104*67e74705SXin Li // CHECK-ARM64-LABEL: @test_ldaex
105*67e74705SXin Li   int sum = 0;
106*67e74705SXin Li   sum += __builtin_arm_ldaex(addr);
107*67e74705SXin Li // CHECK: [[INTRES:%.*]] = call i32 @llvm.arm.ldaex.p0i8(i8* %addr)
108*67e74705SXin Li // CHECK: trunc i32 [[INTRES]] to i8
109*67e74705SXin Li 
110*67e74705SXin Li // CHECK-ARM64: [[INTRES:%.*]] = call i64 @llvm.aarch64.ldaxr.p0i8(i8* %addr)
111*67e74705SXin Li // CHECK-ARM64: trunc i64 [[INTRES]] to i8
112*67e74705SXin Li 
113*67e74705SXin Li   sum += __builtin_arm_ldaex((short *)addr);
114*67e74705SXin Li // CHECK: [[ADDR16:%.*]] = bitcast i8* %addr to i16*
115*67e74705SXin Li // CHECK: [[INTRES:%.*]] = call i32 @llvm.arm.ldaex.p0i16(i16* [[ADDR16]])
116*67e74705SXin Li // CHECK: trunc i32 [[INTRES]] to i16
117*67e74705SXin Li 
118*67e74705SXin Li // CHECK-ARM64: [[ADDR16:%.*]] = bitcast i8* %addr to i16*
119*67e74705SXin Li // CHECK-ARM64: [[INTRES:%.*]] = call i64 @llvm.aarch64.ldaxr.p0i16(i16* [[ADDR16]])
120*67e74705SXin Li // CHECK-ARM64: [[TRUNCRES:%.*]] = trunc i64 [[INTRES]] to i16
121*67e74705SXin Li 
122*67e74705SXin Li   sum += __builtin_arm_ldaex((int *)addr);
123*67e74705SXin Li // CHECK: [[ADDR32:%.*]] = bitcast i8* %addr to i32*
124*67e74705SXin Li // CHECK:  call i32 @llvm.arm.ldaex.p0i32(i32* [[ADDR32]])
125*67e74705SXin Li 
126*67e74705SXin Li // CHECK-ARM64: [[ADDR32:%.*]] = bitcast i8* %addr to i32*
127*67e74705SXin Li // CHECK-ARM64: [[INTRES:%.*]] = call i64 @llvm.aarch64.ldaxr.p0i32(i32* [[ADDR32]])
128*67e74705SXin Li // CHECK-ARM64: trunc i64 [[INTRES]] to i32
129*67e74705SXin Li 
130*67e74705SXin Li   sum += __builtin_arm_ldaex((long long *)addr);
131*67e74705SXin Li // CHECK: [[TMP4:%.*]] = bitcast i8* %addr to i64*
132*67e74705SXin Li // CHECK: [[TMP5:%.*]] = bitcast i64* [[TMP4]] to i8*
133*67e74705SXin Li // CHECK: call { i32, i32 } @llvm.arm.ldaexd(i8* [[TMP5]])
134*67e74705SXin Li 
135*67e74705SXin Li // CHECK-ARM64: [[ADDR64:%.*]] = bitcast i8* %addr to i64*
136*67e74705SXin Li // CHECK-ARM64: call i64 @llvm.aarch64.ldaxr.p0i64(i64* [[ADDR64]])
137*67e74705SXin Li 
138*67e74705SXin Li   sum += __builtin_arm_ldaex(addr64);
139*67e74705SXin Li // CHECK: [[ADDR64_AS8:%.*]] = bitcast i64* %addr64 to i8*
140*67e74705SXin Li // CHECK: call { i32, i32 } @llvm.arm.ldaexd(i8* [[ADDR64_AS8]])
141*67e74705SXin Li 
142*67e74705SXin Li // CHECK-ARM64: call i64 @llvm.aarch64.ldaxr.p0i64(i64* %addr64)
143*67e74705SXin Li 
144*67e74705SXin Li   sum += __builtin_arm_ldaex(addrfloat);
145*67e74705SXin Li // CHECK: [[INTADDR:%.*]] = bitcast float* %addrfloat to i32*
146*67e74705SXin Li // CHECK: [[INTRES:%.*]] = call i32 @llvm.arm.ldaex.p0i32(i32* [[INTADDR]])
147*67e74705SXin Li // CHECK: bitcast i32 [[INTRES]] to float
148*67e74705SXin Li 
149*67e74705SXin Li // CHECK-ARM64: [[INTADDR:%.*]] = bitcast float* %addrfloat to i32*
150*67e74705SXin Li // CHECK-ARM64: [[INTRES:%.*]] = call i64 @llvm.aarch64.ldaxr.p0i32(i32* [[INTADDR]])
151*67e74705SXin Li // CHECK-ARM64: [[TRUNCRES:%.*]] = trunc i64 [[INTRES]] to i32
152*67e74705SXin Li // CHECK-ARM64: bitcast i32 [[TRUNCRES]] to float
153*67e74705SXin Li 
154*67e74705SXin Li   sum += __builtin_arm_ldaex((double *)addr);
155*67e74705SXin Li // CHECK: [[TMP4:%.*]] = bitcast i8* %addr to double*
156*67e74705SXin Li // CHECK: [[TMP5:%.*]] = bitcast double* [[TMP4]] to i8*
157*67e74705SXin Li // CHECK: [[STRUCTRES:%.*]] = call { i32, i32 } @llvm.arm.ldaexd(i8* [[TMP5]])
158*67e74705SXin Li // CHECK: [[RESHI:%.*]] = extractvalue { i32, i32 } [[STRUCTRES]], 1
159*67e74705SXin Li // CHECK: [[RESLO:%.*]] = extractvalue { i32, i32 } [[STRUCTRES]], 0
160*67e74705SXin Li // CHECK: [[RESHI64:%.*]] = zext i32 [[RESHI]] to i64
161*67e74705SXin Li // CHECK: [[RESLO64:%.*]] = zext i32 [[RESLO]] to i64
162*67e74705SXin Li // CHECK: [[RESHIHI:%.*]] = shl nuw i64 [[RESHI64]], 32
163*67e74705SXin Li // CHECK: [[INTRES:%.*]] = or i64 [[RESHIHI]], [[RESLO64]]
164*67e74705SXin Li // CHECK: bitcast i64 [[INTRES]] to double
165*67e74705SXin Li 
166*67e74705SXin Li // CHECK-ARM64: [[TMP4:%.*]] = bitcast i8* %addr to double*
167*67e74705SXin Li // CHECK-ARM64: [[TMP5:%.*]] = bitcast double* [[TMP4]] to i64*
168*67e74705SXin Li // CHECK-ARM64: [[INTRES:%.*]] = call i64 @llvm.aarch64.ldaxr.p0i64(i64* [[TMP5]])
169*67e74705SXin Li // CHECK-ARM64: bitcast i64 [[INTRES]] to double
170*67e74705SXin Li 
171*67e74705SXin Li   sum += *__builtin_arm_ldaex((int **)addr);
172*67e74705SXin Li // CHECK: [[TMP4:%.*]] = bitcast i8* %addr to i32**
173*67e74705SXin Li // CHECK: [[TMP5:%.*]] = bitcast i32** [[TMP4]] to i32*
174*67e74705SXin Li // CHECK: [[INTRES:%.*]] = call i32 @llvm.arm.ldaex.p0i32(i32* [[TMP5]])
175*67e74705SXin Li // CHECK: inttoptr i32 [[INTRES]] to i32*
176*67e74705SXin Li 
177*67e74705SXin Li // CHECK-ARM64: [[TMP4:%.*]] = bitcast i8* %addr to i32**
178*67e74705SXin Li // CHECK-ARM64: [[TMP5:%.*]] = bitcast i32** [[TMP4]] to i64*
179*67e74705SXin Li // CHECK-ARM64: [[INTRES:%.*]] = call i64 @llvm.aarch64.ldaxr.p0i64(i64* [[TMP5]])
180*67e74705SXin Li // CHECK-ARM64: inttoptr i64 [[INTRES]] to i32*
181*67e74705SXin Li 
182*67e74705SXin Li   sum += __builtin_arm_ldaex((struct Simple **)addr)->a;
183*67e74705SXin Li // CHECK: [[TMP4:%.*]] = bitcast i8* %addr to %struct.Simple**
184*67e74705SXin Li // CHECK: [[TMP5:%.*]] = bitcast %struct.Simple** [[TMP4]] to i32*
185*67e74705SXin Li // CHECK: [[INTRES:%.*]] = call i32 @llvm.arm.ldaex.p0i32(i32* [[TMP5]])
186*67e74705SXin Li // CHECK: inttoptr i32 [[INTRES]] to %struct.Simple*
187*67e74705SXin Li 
188*67e74705SXin Li // CHECK-ARM64: [[TMP4:%.*]] = bitcast i8* %addr to %struct.Simple**
189*67e74705SXin Li // CHECK-ARM64: [[TMP5:%.*]] = bitcast %struct.Simple** [[TMP4]] to i64*
190*67e74705SXin Li // CHECK-ARM64: [[INTRES:%.*]] = call i64 @llvm.aarch64.ldaxr.p0i64(i64* [[TMP5]])
191*67e74705SXin Li // CHECK-ARM64: inttoptr i64 [[INTRES]] to %struct.Simple*
192*67e74705SXin Li   return sum;
193*67e74705SXin Li }
194*67e74705SXin Li 
test_strex(char * addr)195*67e74705SXin Li int test_strex(char *addr) {
196*67e74705SXin Li // CHECK-LABEL: @test_strex
197*67e74705SXin Li // CHECK-ARM64-LABEL: @test_strex
198*67e74705SXin Li   int res = 0;
199*67e74705SXin Li   struct Simple var = {0};
200*67e74705SXin Li   res |= __builtin_arm_strex(4, addr);
201*67e74705SXin Li // CHECK: call i32 @llvm.arm.strex.p0i8(i32 4, i8* %addr)
202*67e74705SXin Li 
203*67e74705SXin Li // CHECK-ARM64: call i32 @llvm.aarch64.stxr.p0i8(i64 4, i8* %addr)
204*67e74705SXin Li 
205*67e74705SXin Li   res |= __builtin_arm_strex(42, (short *)addr);
206*67e74705SXin Li // CHECK: [[ADDR16:%.*]] = bitcast i8* %addr to i16*
207*67e74705SXin Li // CHECK:  call i32 @llvm.arm.strex.p0i16(i32 42, i16* [[ADDR16]])
208*67e74705SXin Li 
209*67e74705SXin Li // CHECK-ARM64: [[ADDR16:%.*]] = bitcast i8* %addr to i16*
210*67e74705SXin Li // CHECK-ARM64:  call i32 @llvm.aarch64.stxr.p0i16(i64 42, i16* [[ADDR16]])
211*67e74705SXin Li 
212*67e74705SXin Li   res |= __builtin_arm_strex(42, (int *)addr);
213*67e74705SXin Li // CHECK: [[ADDR32:%.*]] = bitcast i8* %addr to i32*
214*67e74705SXin Li // CHECK: call i32 @llvm.arm.strex.p0i32(i32 42, i32* [[ADDR32]])
215*67e74705SXin Li 
216*67e74705SXin Li // CHECK-ARM64: [[ADDR32:%.*]] = bitcast i8* %addr to i32*
217*67e74705SXin Li // CHECK-ARM64: call i32 @llvm.aarch64.stxr.p0i32(i64 42, i32* [[ADDR32]])
218*67e74705SXin Li 
219*67e74705SXin Li   res |= __builtin_arm_strex(42, (long long *)addr);
220*67e74705SXin Li // CHECK: store i64 42, i64* [[TMP:%.*]], align 8
221*67e74705SXin Li // CHECK: [[LOHI_ADDR:%.*]] = bitcast i64* [[TMP]] to { i32, i32 }*
222*67e74705SXin Li // CHECK: [[LOHI:%.*]] = load { i32, i32 }, { i32, i32 }* [[LOHI_ADDR]]
223*67e74705SXin Li // CHECK: [[LO:%.*]] = extractvalue { i32, i32 } [[LOHI]], 0
224*67e74705SXin Li // CHECK: [[HI:%.*]] = extractvalue { i32, i32 } [[LOHI]], 1
225*67e74705SXin Li // CHECK: [[TMP4:%.*]] = bitcast i8* %addr to i64*
226*67e74705SXin Li // CHECK: [[TMP5:%.*]] = bitcast i64* [[TMP4]] to i8*
227*67e74705SXin Li // CHECK: call i32 @llvm.arm.strexd(i32 [[LO]], i32 [[HI]], i8* [[TMP5]])
228*67e74705SXin Li 
229*67e74705SXin Li // CHECK-ARM64: [[ADDR64:%.*]] = bitcast i8* %addr to i64*
230*67e74705SXin Li // CHECK-ARM64: call i32 @llvm.aarch64.stxr.p0i64(i64 42, i64* [[ADDR64]])
231*67e74705SXin Li 
232*67e74705SXin Li   res |= __builtin_arm_strex(2.71828f, (float *)addr);
233*67e74705SXin Li // CHECK: [[TMP4:%.*]] = bitcast i8* %addr to float*
234*67e74705SXin Li // CHECK: [[TMP5:%.*]] = bitcast float* [[TMP4]] to i32*
235*67e74705SXin Li // CHECK: call i32 @llvm.arm.strex.p0i32(i32 1076754509, i32* [[TMP5]])
236*67e74705SXin Li 
237*67e74705SXin Li // CHECK-ARM64: [[TMP4:%.*]] = bitcast i8* %addr to float*
238*67e74705SXin Li // CHECK-ARM64: [[TMP5:%.*]] = bitcast float* [[TMP4]] to i32*
239*67e74705SXin Li // CHECK-ARM64: call i32 @llvm.aarch64.stxr.p0i32(i64 1076754509, i32* [[TMP5]])
240*67e74705SXin Li 
241*67e74705SXin Li   res |= __builtin_arm_strex(3.14159, (double *)addr);
242*67e74705SXin Li // CHECK: store double 3.141590e+00, double* [[TMP:%.*]], align 8
243*67e74705SXin Li // CHECK: [[LOHI_ADDR:%.*]] = bitcast double* [[TMP]] to { i32, i32 }*
244*67e74705SXin Li // CHECK: [[LOHI:%.*]] = load { i32, i32 }, { i32, i32 }* [[LOHI_ADDR]]
245*67e74705SXin Li // CHECK: [[LO:%.*]] = extractvalue { i32, i32 } [[LOHI]], 0
246*67e74705SXin Li // CHECK: [[HI:%.*]] = extractvalue { i32, i32 } [[LOHI]], 1
247*67e74705SXin Li // CHECK: [[TMP4:%.*]] = bitcast i8* %addr to double*
248*67e74705SXin Li // CHECK: [[TMP5:%.*]] = bitcast double* [[TMP4]] to i8*
249*67e74705SXin Li // CHECK: call i32 @llvm.arm.strexd(i32 [[LO]], i32 [[HI]], i8* [[TMP5]])
250*67e74705SXin Li 
251*67e74705SXin Li // CHECK-ARM64: [[TMP4:%.*]] = bitcast i8* %addr to double*
252*67e74705SXin Li // CHECK-ARM64: [[TMP5:%.*]] = bitcast double* [[TMP4]] to i64*
253*67e74705SXin Li // CHECK-ARM64: call i32 @llvm.aarch64.stxr.p0i64(i64 4614256650576692846, i64* [[TMP5]])
254*67e74705SXin Li 
255*67e74705SXin Li   res |= __builtin_arm_strex(&var, (struct Simple **)addr);
256*67e74705SXin Li // CHECK: [[TMP4:%.*]] = bitcast i8* %addr to %struct.Simple**
257*67e74705SXin Li // CHECK: [[TMP5:%.*]] = bitcast %struct.Simple** [[TMP4]] to i32*
258*67e74705SXin Li // CHECK: [[INTVAL:%.*]] = ptrtoint %struct.Simple* %var to i32
259*67e74705SXin Li // CHECK: call i32 @llvm.arm.strex.p0i32(i32 [[INTVAL]], i32* [[TMP5]])
260*67e74705SXin Li 
261*67e74705SXin Li // CHECK-ARM64: [[TMP4:%.*]] = bitcast i8* %addr to %struct.Simple**
262*67e74705SXin Li // CHECK-ARM64: [[TMP5:%.*]] = bitcast %struct.Simple** [[TMP4]] to i64*
263*67e74705SXin Li // CHECK-ARM64: [[INTVAL:%.*]] = ptrtoint %struct.Simple* %var to i64
264*67e74705SXin Li // CHECK-ARM64: call i32 @llvm.aarch64.stxr.p0i64(i64 [[INTVAL]], i64* [[TMP5]])
265*67e74705SXin Li 
266*67e74705SXin Li   return res;
267*67e74705SXin Li }
268*67e74705SXin Li 
test_stlex(char * addr)269*67e74705SXin Li int test_stlex(char *addr) {
270*67e74705SXin Li // CHECK-LABEL: @test_stlex
271*67e74705SXin Li // CHECK-ARM64-LABEL: @test_stlex
272*67e74705SXin Li   int res = 0;
273*67e74705SXin Li   struct Simple var = {0};
274*67e74705SXin Li   res |= __builtin_arm_stlex(4, addr);
275*67e74705SXin Li // CHECK: call i32 @llvm.arm.stlex.p0i8(i32 4, i8* %addr)
276*67e74705SXin Li 
277*67e74705SXin Li // CHECK-ARM64: call i32 @llvm.aarch64.stlxr.p0i8(i64 4, i8* %addr)
278*67e74705SXin Li 
279*67e74705SXin Li   res |= __builtin_arm_stlex(42, (short *)addr);
280*67e74705SXin Li // CHECK: [[ADDR16:%.*]] = bitcast i8* %addr to i16*
281*67e74705SXin Li // CHECK:  call i32 @llvm.arm.stlex.p0i16(i32 42, i16* [[ADDR16]])
282*67e74705SXin Li 
283*67e74705SXin Li // CHECK-ARM64: [[ADDR16:%.*]] = bitcast i8* %addr to i16*
284*67e74705SXin Li // CHECK-ARM64:  call i32 @llvm.aarch64.stlxr.p0i16(i64 42, i16* [[ADDR16]])
285*67e74705SXin Li 
286*67e74705SXin Li   res |= __builtin_arm_stlex(42, (int *)addr);
287*67e74705SXin Li // CHECK: [[ADDR32:%.*]] = bitcast i8* %addr to i32*
288*67e74705SXin Li // CHECK: call i32 @llvm.arm.stlex.p0i32(i32 42, i32* [[ADDR32]])
289*67e74705SXin Li 
290*67e74705SXin Li // CHECK-ARM64: [[ADDR32:%.*]] = bitcast i8* %addr to i32*
291*67e74705SXin Li // CHECK-ARM64: call i32 @llvm.aarch64.stlxr.p0i32(i64 42, i32* [[ADDR32]])
292*67e74705SXin Li 
293*67e74705SXin Li   res |= __builtin_arm_stlex(42, (long long *)addr);
294*67e74705SXin Li // CHECK: store i64 42, i64* [[TMP:%.*]], align 8
295*67e74705SXin Li // CHECK: [[LOHI_ADDR:%.*]] = bitcast i64* [[TMP]] to { i32, i32 }*
296*67e74705SXin Li // CHECK: [[LOHI:%.*]] = load { i32, i32 }, { i32, i32 }* [[LOHI_ADDR]]
297*67e74705SXin Li // CHECK: [[LO:%.*]] = extractvalue { i32, i32 } [[LOHI]], 0
298*67e74705SXin Li // CHECK: [[HI:%.*]] = extractvalue { i32, i32 } [[LOHI]], 1
299*67e74705SXin Li // CHECK: [[TMP4:%.*]] = bitcast i8* %addr to i64*
300*67e74705SXin Li // CHECK: [[TMP5:%.*]] = bitcast i64* [[TMP4]] to i8*
301*67e74705SXin Li // CHECK: call i32 @llvm.arm.stlexd(i32 [[LO]], i32 [[HI]], i8* [[TMP5]])
302*67e74705SXin Li 
303*67e74705SXin Li // CHECK-ARM64: [[ADDR64:%.*]] = bitcast i8* %addr to i64*
304*67e74705SXin Li // CHECK-ARM64: call i32 @llvm.aarch64.stlxr.p0i64(i64 42, i64* [[ADDR64]])
305*67e74705SXin Li 
306*67e74705SXin Li   res |= __builtin_arm_stlex(2.71828f, (float *)addr);
307*67e74705SXin Li // CHECK: [[TMP4:%.*]] = bitcast i8* %addr to float*
308*67e74705SXin Li // CHECK: [[TMP5:%.*]] = bitcast float* [[TMP4]] to i32*
309*67e74705SXin Li // CHECK: call i32 @llvm.arm.stlex.p0i32(i32 1076754509, i32* [[TMP5]])
310*67e74705SXin Li 
311*67e74705SXin Li // CHECK-ARM64: [[TMP4:%.*]] = bitcast i8* %addr to float*
312*67e74705SXin Li // CHECK-ARM64: [[TMP5:%.*]] = bitcast float* [[TMP4]] to i32*
313*67e74705SXin Li // CHECK-ARM64: call i32 @llvm.aarch64.stlxr.p0i32(i64 1076754509, i32* [[TMP5]])
314*67e74705SXin Li 
315*67e74705SXin Li   res |= __builtin_arm_stlex(3.14159, (double *)addr);
316*67e74705SXin Li // CHECK: store double 3.141590e+00, double* [[TMP:%.*]], align 8
317*67e74705SXin Li // CHECK: [[LOHI_ADDR:%.*]] = bitcast double* [[TMP]] to { i32, i32 }*
318*67e74705SXin Li // CHECK: [[LOHI:%.*]] = load { i32, i32 }, { i32, i32 }* [[LOHI_ADDR]]
319*67e74705SXin Li // CHECK: [[LO:%.*]] = extractvalue { i32, i32 } [[LOHI]], 0
320*67e74705SXin Li // CHECK: [[HI:%.*]] = extractvalue { i32, i32 } [[LOHI]], 1
321*67e74705SXin Li // CHECK: [[TMP4:%.*]] = bitcast i8* %addr to double*
322*67e74705SXin Li // CHECK: [[TMP5:%.*]] = bitcast double* [[TMP4]] to i8*
323*67e74705SXin Li // CHECK: call i32 @llvm.arm.stlexd(i32 [[LO]], i32 [[HI]], i8* [[TMP5]])
324*67e74705SXin Li 
325*67e74705SXin Li // CHECK-ARM64: [[TMP4:%.*]] = bitcast i8* %addr to double*
326*67e74705SXin Li // CHECK-ARM64: [[TMP5:%.*]] = bitcast double* [[TMP4]] to i64*
327*67e74705SXin Li // CHECK-ARM64: call i32 @llvm.aarch64.stlxr.p0i64(i64 4614256650576692846, i64* [[TMP5]])
328*67e74705SXin Li 
329*67e74705SXin Li   res |= __builtin_arm_stlex(&var, (struct Simple **)addr);
330*67e74705SXin Li // CHECK: [[TMP4:%.*]] = bitcast i8* %addr to %struct.Simple**
331*67e74705SXin Li // CHECK: [[TMP5:%.*]] = bitcast %struct.Simple** [[TMP4]] to i32*
332*67e74705SXin Li // CHECK: [[INTVAL:%.*]] = ptrtoint %struct.Simple* %var to i32
333*67e74705SXin Li // CHECK: call i32 @llvm.arm.stlex.p0i32(i32 [[INTVAL]], i32* [[TMP5]])
334*67e74705SXin Li 
335*67e74705SXin Li // CHECK-ARM64: [[TMP4:%.*]] = bitcast i8* %addr to %struct.Simple**
336*67e74705SXin Li // CHECK-ARM64: [[TMP5:%.*]] = bitcast %struct.Simple** [[TMP4]] to i64*
337*67e74705SXin Li // CHECK-ARM64: [[INTVAL:%.*]] = ptrtoint %struct.Simple* %var to i64
338*67e74705SXin Li // CHECK-ARM64: call i32 @llvm.aarch64.stlxr.p0i64(i64 [[INTVAL]], i64* [[TMP5]])
339*67e74705SXin Li 
340*67e74705SXin Li   return res;
341*67e74705SXin Li }
342*67e74705SXin Li 
test_clrex()343*67e74705SXin Li void test_clrex() {
344*67e74705SXin Li // CHECK-LABEL: @test_clrex
345*67e74705SXin Li // CHECK-ARM64-LABEL: @test_clrex
346*67e74705SXin Li 
347*67e74705SXin Li   __builtin_arm_clrex();
348*67e74705SXin Li // CHECK: call void @llvm.arm.clrex()
349*67e74705SXin Li // CHECK-ARM64: call void @llvm.aarch64.clrex()
350*67e74705SXin Li }
351*67e74705SXin Li 
352*67e74705SXin Li #ifdef __aarch64__
353*67e74705SXin Li // 128-bit tests
354*67e74705SXin Li 
test_ldrex_128(__int128 * addr)355*67e74705SXin Li __int128 test_ldrex_128(__int128 *addr) {
356*67e74705SXin Li // CHECK-ARM64-LABEL: @test_ldrex_128
357*67e74705SXin Li 
358*67e74705SXin Li   return __builtin_arm_ldrex(addr);
359*67e74705SXin Li // CHECK-ARM64: [[ADDR8:%.*]] = bitcast i128* %addr to i8*
360*67e74705SXin Li // CHECK-ARM64: [[STRUCTRES:%.*]] = call { i64, i64 } @llvm.aarch64.ldxp(i8* [[ADDR8]])
361*67e74705SXin Li // CHECK-ARM64: [[RESHI:%.*]] = extractvalue { i64, i64 } [[STRUCTRES]], 1
362*67e74705SXin Li // CHECK-ARM64: [[RESLO:%.*]] = extractvalue { i64, i64 } [[STRUCTRES]], 0
363*67e74705SXin Li // CHECK-ARM64: [[RESHI64:%.*]] = zext i64 [[RESHI]] to i128
364*67e74705SXin Li // CHECK-ARM64: [[RESLO64:%.*]] = zext i64 [[RESLO]] to i128
365*67e74705SXin Li // CHECK-ARM64: [[RESHIHI:%.*]] = shl nuw i128 [[RESHI64]], 64
366*67e74705SXin Li // CHECK-ARM64: [[INTRES:%.*]] = or i128 [[RESHIHI]], [[RESLO64]]
367*67e74705SXin Li // CHECK-ARM64: ret i128 [[INTRES]]
368*67e74705SXin Li }
369*67e74705SXin Li 
test_strex_128(__int128 * addr,__int128 val)370*67e74705SXin Li int test_strex_128(__int128 *addr, __int128 val) {
371*67e74705SXin Li // CHECK-ARM64-LABEL: @test_strex_128
372*67e74705SXin Li 
373*67e74705SXin Li   return __builtin_arm_strex(val, addr);
374*67e74705SXin Li // CHECK-ARM64: store i128 %val, i128* [[TMP:%.*]], align 16
375*67e74705SXin Li // CHECK-ARM64: [[LOHI_ADDR:%.*]] = bitcast i128* [[TMP]] to { i64, i64 }*
376*67e74705SXin Li // CHECK-ARM64: [[LOHI:%.*]] = load { i64, i64 }, { i64, i64 }* [[LOHI_ADDR]]
377*67e74705SXin Li // CHECK-ARM64: [[LO:%.*]] = extractvalue { i64, i64 } [[LOHI]], 0
378*67e74705SXin Li // CHECK-ARM64: [[HI:%.*]] = extractvalue { i64, i64 } [[LOHI]], 1
379*67e74705SXin Li // CHECK-ARM64: [[ADDR8:%.*]] = bitcast i128* %addr to i8*
380*67e74705SXin Li // CHECK-ARM64: call i32 @llvm.aarch64.stxp(i64 [[LO]], i64 [[HI]], i8* [[ADDR8]])
381*67e74705SXin Li }
382*67e74705SXin Li 
test_ldaex_128(__int128 * addr)383*67e74705SXin Li __int128 test_ldaex_128(__int128 *addr) {
384*67e74705SXin Li // CHECK-ARM64-LABEL: @test_ldaex_128
385*67e74705SXin Li 
386*67e74705SXin Li   return __builtin_arm_ldaex(addr);
387*67e74705SXin Li // CHECK-ARM64: [[ADDR8:%.*]] = bitcast i128* %addr to i8*
388*67e74705SXin Li // CHECK-ARM64: [[STRUCTRES:%.*]] = call { i64, i64 } @llvm.aarch64.ldaxp(i8* [[ADDR8]])
389*67e74705SXin Li // CHECK-ARM64: [[RESHI:%.*]] = extractvalue { i64, i64 } [[STRUCTRES]], 1
390*67e74705SXin Li // CHECK-ARM64: [[RESLO:%.*]] = extractvalue { i64, i64 } [[STRUCTRES]], 0
391*67e74705SXin Li // CHECK-ARM64: [[RESHI64:%.*]] = zext i64 [[RESHI]] to i128
392*67e74705SXin Li // CHECK-ARM64: [[RESLO64:%.*]] = zext i64 [[RESLO]] to i128
393*67e74705SXin Li // CHECK-ARM64: [[RESHIHI:%.*]] = shl nuw i128 [[RESHI64]], 64
394*67e74705SXin Li // CHECK-ARM64: [[INTRES:%.*]] = or i128 [[RESHIHI]], [[RESLO64]]
395*67e74705SXin Li // CHECK-ARM64: ret i128 [[INTRES]]
396*67e74705SXin Li }
397*67e74705SXin Li 
test_stlex_128(__int128 * addr,__int128 val)398*67e74705SXin Li int test_stlex_128(__int128 *addr, __int128 val) {
399*67e74705SXin Li // CHECK-ARM64-LABEL: @test_stlex_128
400*67e74705SXin Li 
401*67e74705SXin Li   return __builtin_arm_stlex(val, addr);
402*67e74705SXin Li // CHECK-ARM64: store i128 %val, i128* [[TMP:%.*]], align 16
403*67e74705SXin Li // CHECK-ARM64: [[LOHI_ADDR:%.*]] = bitcast i128* [[TMP]] to { i64, i64 }*
404*67e74705SXin Li // CHECK-ARM64: [[LOHI:%.*]] = load { i64, i64 }, { i64, i64 }* [[LOHI_ADDR]]
405*67e74705SXin Li // CHECK-ARM64: [[LO:%.*]] = extractvalue { i64, i64 } [[LOHI]], 0
406*67e74705SXin Li // CHECK-ARM64: [[HI:%.*]] = extractvalue { i64, i64 } [[LOHI]], 1
407*67e74705SXin Li // CHECK-ARM64: [[ADDR8:%.*]] = bitcast i128* %addr to i8*
408*67e74705SXin Li // CHECK-ARM64: [[RES:%.*]] = call i32 @llvm.aarch64.stlxp(i64 [[LO]], i64 [[HI]], i8* [[ADDR8]])
409*67e74705SXin Li }
410*67e74705SXin Li 
411*67e74705SXin Li #endif
412