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