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