1 ; RUN: llc -mtriple=aarch64-none-linux-gnu -verify-machineinstrs < %s | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-AARCH64
2 ; RUN: llc -mtriple=aarch64-none-linux-gnu -verify-machineinstrs < %s | FileCheck --check-prefix=CHECK-REG %s
3 ; RUN: llc -mtriple=arm64-none-linux-gnu -verify-machineinstrs < %s | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-ARM64
4 ; RUN: llc -mtriple=arm64-none-linux-gnu -verify-machineinstrs < %s | FileCheck %s --check-prefix=CHECK-REG
7 ; Point of CHECK-REG is to make sure UNPREDICTABLE instructions aren't created
8 ; (i.e. reusing a register for status & data in store exclusive).
9 ; CHECK-REG-NOT: stlxrb w[[NEW:[0-9]+]], w[[NEW]], [x{{[0-9]+}}]
10 ; CHECK-REG-NOT: stlxrb w[[NEW:[0-9]+]], x[[NEW]], [x{{[0-9]+}}]
17 define i8 @test_atomic_load_add_i8(i8 %offset) nounwind {
18 ; CHECK-LABEL: test_atomic_load_add_i8:
19 %old = atomicrmw add i8* @var8, i8 %offset seq_cst
21 ; CHECK: adrp [[TMPADDR:x[0-9]+]], var8
22 ; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], {{#?}}:lo12:var8
24 ; CHECK: .LBB{{[0-9]+}}_1:
25 ; CHECK: ldaxrb w[[OLD:[0-9]+]], [x[[ADDR]]]
26 ; w0 below is a reasonable guess but could change: it certainly comes into the
28 ; CHECK-NEXT: add [[NEW:w[0-9]+]], w[[OLD]], w0
29 ; CHECK-NEXT: stlxrb [[STATUS:w[0-9]+]], [[NEW]], [x[[ADDR]]]
30 ; CHECK-NEXT: cbnz [[STATUS]], .LBB{{[0-9]+}}_1
33 ; CHECK: mov {{[xw]}}0, {{[xw]}}[[OLD]]
37 define i16 @test_atomic_load_add_i16(i16 %offset) nounwind {
38 ; CHECK-LABEL: test_atomic_load_add_i16:
39 %old = atomicrmw add i16* @var16, i16 %offset acquire
41 ; CHECK: adrp [[TMPADDR:x[0-9]+]], var16
42 ; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], {{#?}}:lo12:var16
44 ; CHECK: .LBB{{[0-9]+}}_1:
45 ; ; CHECK: ldaxrh w[[OLD:[0-9]+]], [x[[ADDR]]]
46 ; w0 below is a reasonable guess but could change: it certainly comes into the
48 ; CHECK-NEXT: add [[NEW:w[0-9]+]], w[[OLD]], w0
49 ; CHECK-NEXT: stxrh [[STATUS:w[0-9]+]], [[NEW]], [x[[ADDR]]]
50 ; CHECK-NEXT: cbnz [[STATUS]], .LBB{{[0-9]+}}_1
53 ; CHECK: mov {{[xw]}}0, {{[xw]}}[[OLD]]
57 define i32 @test_atomic_load_add_i32(i32 %offset) nounwind {
58 ; CHECK-LABEL: test_atomic_load_add_i32:
59 %old = atomicrmw add i32* @var32, i32 %offset release
61 ; CHECK: adrp [[TMPADDR:x[0-9]+]], var32
62 ; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], {{#?}}:lo12:var32
64 ; CHECK: .LBB{{[0-9]+}}_1:
65 ; ; CHECK: ldxr w[[OLD:[0-9]+]], [x[[ADDR]]]
66 ; w0 below is a reasonable guess but could change: it certainly comes into the
68 ; CHECK-NEXT: add [[NEW:w[0-9]+]], w[[OLD]], w0
69 ; CHECK-NEXT: stlxr [[STATUS:w[0-9]+]], [[NEW]], [x[[ADDR]]]
70 ; CHECK-NEXT: cbnz [[STATUS]], .LBB{{[0-9]+}}_1
73 ; CHECK: mov {{[xw]}}0, {{[xw]}}[[OLD]]
77 define i64 @test_atomic_load_add_i64(i64 %offset) nounwind {
78 ; CHECK-LABEL: test_atomic_load_add_i64:
79 %old = atomicrmw add i64* @var64, i64 %offset monotonic
81 ; CHECK: adrp [[TMPADDR:x[0-9]+]], var64
82 ; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], {{#?}}:lo12:var64
84 ; CHECK: .LBB{{[0-9]+}}_1:
85 ; ; CHECK: ldxr x[[OLD:[0-9]+]], [x[[ADDR]]]
86 ; x0 below is a reasonable guess but could change: it certainly comes into the
88 ; CHECK-NEXT: add [[NEW:x[0-9]+]], x[[OLD]], x0
89 ; CHECK-NEXT: stxr [[STATUS:w[0-9]+]], [[NEW]], [x[[ADDR]]]
90 ; CHECK-NEXT: cbnz [[STATUS]], .LBB{{[0-9]+}}_1
93 ; CHECK: mov x0, x[[OLD]]
97 define i8 @test_atomic_load_sub_i8(i8 %offset) nounwind {
98 ; CHECK-LABEL: test_atomic_load_sub_i8:
99 %old = atomicrmw sub i8* @var8, i8 %offset monotonic
101 ; CHECK: adrp [[TMPADDR:x[0-9]+]], var8
102 ; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], {{#?}}:lo12:var8
104 ; CHECK: .LBB{{[0-9]+}}_1:
105 ; ; CHECK: ldxrb w[[OLD:[0-9]+]], [x[[ADDR]]]
106 ; w0 below is a reasonable guess but could change: it certainly comes into the
108 ; CHECK-NEXT: sub [[NEW:w[0-9]+]], w[[OLD]], w0
109 ; CHECK-NEXT: stxrb [[STATUS:w[0-9]+]], [[NEW]], [x[[ADDR]]]
110 ; CHECK-NEXT: cbnz [[STATUS]], .LBB{{[0-9]+}}_1
113 ; CHECK: mov {{[xw]}}0, {{[xw]}}[[OLD]]
117 define i16 @test_atomic_load_sub_i16(i16 %offset) nounwind {
118 ; CHECK-LABEL: test_atomic_load_sub_i16:
119 %old = atomicrmw sub i16* @var16, i16 %offset release
121 ; CHECK: adrp [[TMPADDR:x[0-9]+]], var16
122 ; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], {{#?}}:lo12:var16
124 ; CHECK: .LBB{{[0-9]+}}_1:
125 ; ; CHECK: ldxrh w[[OLD:[0-9]+]], [x[[ADDR]]]
126 ; w0 below is a reasonable guess but could change: it certainly comes into the
128 ; CHECK-NEXT: sub [[NEW:w[0-9]+]], w[[OLD]], w0
129 ; CHECK-NEXT: stlxrh [[STATUS:w[0-9]+]], [[NEW]], [x[[ADDR]]]
130 ; CHECK-NEXT: cbnz [[STATUS]], .LBB{{[0-9]+}}_1
133 ; CHECK: mov {{[xw]}}0, {{[xw]}}[[OLD]]
137 define i32 @test_atomic_load_sub_i32(i32 %offset) nounwind {
138 ; CHECK-LABEL: test_atomic_load_sub_i32:
139 %old = atomicrmw sub i32* @var32, i32 %offset acquire
141 ; CHECK: adrp [[TMPADDR:x[0-9]+]], var32
142 ; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], {{#?}}:lo12:var32
144 ; CHECK: .LBB{{[0-9]+}}_1:
145 ; ; CHECK: ldaxr w[[OLD:[0-9]+]], [x[[ADDR]]]
146 ; w0 below is a reasonable guess but could change: it certainly comes into the
148 ; CHECK-NEXT: sub [[NEW:w[0-9]+]], w[[OLD]], w0
149 ; CHECK-NEXT: stxr [[STATUS:w[0-9]+]], [[NEW]], [x[[ADDR]]]
150 ; CHECK-NEXT: cbnz [[STATUS]], .LBB{{[0-9]+}}_1
153 ; CHECK: mov {{[xw]}}0, {{[xw]}}[[OLD]]
157 define i64 @test_atomic_load_sub_i64(i64 %offset) nounwind {
158 ; CHECK-LABEL: test_atomic_load_sub_i64:
159 %old = atomicrmw sub i64* @var64, i64 %offset seq_cst
161 ; CHECK: adrp [[TMPADDR:x[0-9]+]], var64
162 ; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], {{#?}}:lo12:var64
164 ; CHECK: .LBB{{[0-9]+}}_1:
165 ; ; CHECK: ldaxr x[[OLD:[0-9]+]], [x[[ADDR]]]
166 ; x0 below is a reasonable guess but could change: it certainly comes into the
168 ; CHECK-NEXT: sub [[NEW:x[0-9]+]], x[[OLD]], x0
169 ; CHECK-NEXT: stlxr [[STATUS:w[0-9]+]], [[NEW]], [x[[ADDR]]]
170 ; CHECK-NEXT: cbnz [[STATUS]], .LBB{{[0-9]+}}_1
173 ; CHECK: mov x0, x[[OLD]]
177 define i8 @test_atomic_load_and_i8(i8 %offset) nounwind {
178 ; CHECK-LABEL: test_atomic_load_and_i8:
179 %old = atomicrmw and i8* @var8, i8 %offset release
181 ; CHECK: adrp [[TMPADDR:x[0-9]+]], var8
182 ; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], {{#?}}:lo12:var8
184 ; CHECK: .LBB{{[0-9]+}}_1:
185 ; ; CHECK: ldxrb w[[OLD:[0-9]+]], [x[[ADDR]]]
186 ; w0 below is a reasonable guess but could change: it certainly comes into the
188 ; CHECK-NEXT: and [[NEW:w[0-9]+]], w[[OLD]], w0
189 ; CHECK-NEXT: stlxrb [[STATUS:w[0-9]+]], [[NEW]], [x[[ADDR]]]
190 ; CHECK-NEXT: cbnz [[STATUS]], .LBB{{[0-9]+}}_1
193 ; CHECK: mov {{[xw]}}0, {{[xw]}}[[OLD]]
197 define i16 @test_atomic_load_and_i16(i16 %offset) nounwind {
198 ; CHECK-LABEL: test_atomic_load_and_i16:
199 %old = atomicrmw and i16* @var16, i16 %offset monotonic
201 ; CHECK: adrp [[TMPADDR:x[0-9]+]], var16
202 ; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], {{#?}}:lo12:var16
204 ; CHECK: .LBB{{[0-9]+}}_1:
205 ; ; CHECK: ldxrh w[[OLD:[0-9]+]], [x[[ADDR]]]
206 ; w0 below is a reasonable guess but could change: it certainly comes into the
208 ; CHECK-NEXT: and [[NEW:w[0-9]+]], w[[OLD]], w0
209 ; CHECK-NEXT: stxrh [[STATUS:w[0-9]+]], [[NEW]], [x[[ADDR]]]
210 ; CHECK-NEXT: cbnz [[STATUS]], .LBB{{[0-9]+}}_1
213 ; CHECK: mov {{[xw]}}0, {{[xw]}}[[OLD]]
217 define i32 @test_atomic_load_and_i32(i32 %offset) nounwind {
218 ; CHECK-LABEL: test_atomic_load_and_i32:
219 %old = atomicrmw and i32* @var32, i32 %offset seq_cst
221 ; CHECK: adrp [[TMPADDR:x[0-9]+]], var32
222 ; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], {{#?}}:lo12:var32
224 ; CHECK: .LBB{{[0-9]+}}_1:
225 ; ; CHECK: ldaxr w[[OLD:[0-9]+]], [x[[ADDR]]]
226 ; w0 below is a reasonable guess but could change: it certainly comes into the
228 ; CHECK-NEXT: and [[NEW:w[0-9]+]], w[[OLD]], w0
229 ; CHECK-NEXT: stlxr [[STATUS:w[0-9]+]], [[NEW]], [x[[ADDR]]]
230 ; CHECK-NEXT: cbnz [[STATUS]], .LBB{{[0-9]+}}_1
233 ; CHECK: mov {{[xw]}}0, {{[xw]}}[[OLD]]
237 define i64 @test_atomic_load_and_i64(i64 %offset) nounwind {
238 ; CHECK-LABEL: test_atomic_load_and_i64:
239 %old = atomicrmw and i64* @var64, i64 %offset acquire
241 ; CHECK: adrp [[TMPADDR:x[0-9]+]], var64
242 ; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], {{#?}}:lo12:var64
244 ; CHECK: .LBB{{[0-9]+}}_1:
245 ; ; CHECK: ldaxr x[[OLD:[0-9]+]], [x[[ADDR]]]
246 ; x0 below is a reasonable guess but could change: it certainly comes into the
248 ; CHECK-NEXT: and [[NEW:x[0-9]+]], x[[OLD]], x0
249 ; CHECK-NEXT: stxr [[STATUS:w[0-9]+]], [[NEW]], [x[[ADDR]]]
250 ; CHECK-NEXT: cbnz [[STATUS]], .LBB{{[0-9]+}}_1
253 ; CHECK: mov x0, x[[OLD]]
257 define i8 @test_atomic_load_or_i8(i8 %offset) nounwind {
258 ; CHECK-LABEL: test_atomic_load_or_i8:
259 %old = atomicrmw or i8* @var8, i8 %offset seq_cst
261 ; CHECK: adrp [[TMPADDR:x[0-9]+]], var8
262 ; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], {{#?}}:lo12:var8
264 ; CHECK: .LBB{{[0-9]+}}_1:
265 ; ; CHECK: ldaxrb w[[OLD:[0-9]+]], [x[[ADDR]]]
266 ; w0 below is a reasonable guess but could change: it certainly comes into the
268 ; CHECK-NEXT: orr [[NEW:w[0-9]+]], w[[OLD]], w0
269 ; CHECK-NEXT: stlxrb [[STATUS:w[0-9]+]], [[NEW]], [x[[ADDR]]]
270 ; CHECK-NEXT: cbnz [[STATUS]], .LBB{{[0-9]+}}_1
273 ; CHECK: mov {{[xw]}}0, {{[xw]}}[[OLD]]
277 define i16 @test_atomic_load_or_i16(i16 %offset) nounwind {
278 ; CHECK-LABEL: test_atomic_load_or_i16:
279 %old = atomicrmw or i16* @var16, i16 %offset monotonic
281 ; CHECK: adrp [[TMPADDR:x[0-9]+]], var16
282 ; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], {{#?}}:lo12:var16
284 ; CHECK: .LBB{{[0-9]+}}_1:
285 ; ; CHECK: ldxrh w[[OLD:[0-9]+]], [x[[ADDR]]]
286 ; w0 below is a reasonable guess but could change: it certainly comes into the
288 ; CHECK-NEXT: orr [[NEW:w[0-9]+]], w[[OLD]], w0
289 ; CHECK-NEXT: stxrh [[STATUS:w[0-9]+]], [[NEW]], [x[[ADDR]]]
290 ; CHECK-NEXT: cbnz [[STATUS]], .LBB{{[0-9]+}}_1
293 ; CHECK: mov {{[xw]}}0, {{[xw]}}[[OLD]]
297 define i32 @test_atomic_load_or_i32(i32 %offset) nounwind {
298 ; CHECK-LABEL: test_atomic_load_or_i32:
299 %old = atomicrmw or i32* @var32, i32 %offset acquire
301 ; CHECK: adrp [[TMPADDR:x[0-9]+]], var32
302 ; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], {{#?}}:lo12:var32
304 ; CHECK: .LBB{{[0-9]+}}_1:
305 ; ; CHECK: ldaxr w[[OLD:[0-9]+]], [x[[ADDR]]]
306 ; w0 below is a reasonable guess but could change: it certainly comes into the
308 ; CHECK-NEXT: orr [[NEW:w[0-9]+]], w[[OLD]], w0
309 ; CHECK-NEXT: stxr [[STATUS:w[0-9]+]], [[NEW]], [x[[ADDR]]]
310 ; CHECK-NEXT: cbnz [[STATUS]], .LBB{{[0-9]+}}_1
313 ; CHECK: mov {{[xw]}}0, {{[xw]}}[[OLD]]
317 define i64 @test_atomic_load_or_i64(i64 %offset) nounwind {
318 ; CHECK-LABEL: test_atomic_load_or_i64:
319 %old = atomicrmw or i64* @var64, i64 %offset release
321 ; CHECK: adrp [[TMPADDR:x[0-9]+]], var64
322 ; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], {{#?}}:lo12:var64
324 ; CHECK: .LBB{{[0-9]+}}_1:
325 ; ; CHECK: ldxr x[[OLD:[0-9]+]], [x[[ADDR]]]
326 ; x0 below is a reasonable guess but could change: it certainly comes into the
328 ; CHECK-NEXT: orr [[NEW:x[0-9]+]], x[[OLD]], x0
329 ; CHECK-NEXT: stlxr [[STATUS:w[0-9]+]], [[NEW]], [x[[ADDR]]]
330 ; CHECK-NEXT: cbnz [[STATUS]], .LBB{{[0-9]+}}_1
333 ; CHECK: mov x0, x[[OLD]]
337 define i8 @test_atomic_load_xor_i8(i8 %offset) nounwind {
338 ; CHECK-LABEL: test_atomic_load_xor_i8:
339 %old = atomicrmw xor i8* @var8, i8 %offset acquire
341 ; CHECK: adrp [[TMPADDR:x[0-9]+]], var8
342 ; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], {{#?}}:lo12:var8
344 ; CHECK: .LBB{{[0-9]+}}_1:
345 ; ; CHECK: ldaxrb w[[OLD:[0-9]+]], [x[[ADDR]]]
346 ; w0 below is a reasonable guess but could change: it certainly comes into the
348 ; CHECK-NEXT: eor [[NEW:w[0-9]+]], w[[OLD]], w0
349 ; CHECK-NEXT: stxrb [[STATUS:w[0-9]+]], [[NEW]], [x[[ADDR]]]
350 ; CHECK-NEXT: cbnz [[STATUS]], .LBB{{[0-9]+}}_1
353 ; CHECK: mov {{[xw]}}0, {{[xw]}}[[OLD]]
357 define i16 @test_atomic_load_xor_i16(i16 %offset) nounwind {
358 ; CHECK-LABEL: test_atomic_load_xor_i16:
359 %old = atomicrmw xor i16* @var16, i16 %offset release
361 ; CHECK: adrp [[TMPADDR:x[0-9]+]], var16
362 ; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], {{#?}}:lo12:var16
364 ; CHECK: .LBB{{[0-9]+}}_1:
365 ; ; CHECK: ldxrh w[[OLD:[0-9]+]], [x[[ADDR]]]
366 ; w0 below is a reasonable guess but could change: it certainly comes into the
368 ; CHECK-NEXT: eor [[NEW:w[0-9]+]], w[[OLD]], w0
369 ; CHECK-NEXT: stlxrh [[STATUS:w[0-9]+]], [[NEW]], [x[[ADDR]]]
370 ; CHECK-NEXT: cbnz [[STATUS]], .LBB{{[0-9]+}}_1
373 ; CHECK: mov {{[xw]}}0, {{[xw]}}[[OLD]]
377 define i32 @test_atomic_load_xor_i32(i32 %offset) nounwind {
378 ; CHECK-LABEL: test_atomic_load_xor_i32:
379 %old = atomicrmw xor i32* @var32, i32 %offset seq_cst
381 ; CHECK: adrp [[TMPADDR:x[0-9]+]], var32
382 ; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], {{#?}}:lo12:var32
384 ; CHECK: .LBB{{[0-9]+}}_1:
385 ; ; CHECK: ldaxr w[[OLD:[0-9]+]], [x[[ADDR]]]
386 ; w0 below is a reasonable guess but could change: it certainly comes into the
388 ; CHECK-NEXT: eor [[NEW:w[0-9]+]], w[[OLD]], w0
389 ; CHECK-NEXT: stlxr [[STATUS:w[0-9]+]], [[NEW]], [x[[ADDR]]]
390 ; CHECK-NEXT: cbnz [[STATUS]], .LBB{{[0-9]+}}_1
393 ; CHECK: mov {{[xw]}}0, {{[xw]}}[[OLD]]
397 define i64 @test_atomic_load_xor_i64(i64 %offset) nounwind {
398 ; CHECK-LABEL: test_atomic_load_xor_i64:
399 %old = atomicrmw xor i64* @var64, i64 %offset monotonic
401 ; CHECK: adrp [[TMPADDR:x[0-9]+]], var64
402 ; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], {{#?}}:lo12:var64
404 ; CHECK: .LBB{{[0-9]+}}_1:
405 ; ; CHECK: ldxr x[[OLD:[0-9]+]], [x[[ADDR]]]
406 ; x0 below is a reasonable guess but could change: it certainly comes into the
408 ; CHECK-NEXT: eor [[NEW:x[0-9]+]], x[[OLD]], x0
409 ; CHECK-NEXT: stxr [[STATUS:w[0-9]+]], [[NEW]], [x[[ADDR]]]
410 ; CHECK-NEXT: cbnz [[STATUS]], .LBB{{[0-9]+}}_1
413 ; CHECK: mov x0, x[[OLD]]
417 define i8 @test_atomic_load_xchg_i8(i8 %offset) nounwind {
418 ; CHECK-LABEL: test_atomic_load_xchg_i8:
419 %old = atomicrmw xchg i8* @var8, i8 %offset monotonic
421 ; CHECK: adrp [[TMPADDR:x[0-9]+]], var8
422 ; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], {{#?}}:lo12:var8
424 ; CHECK: .LBB{{[0-9]+}}_1:
425 ; ; CHECK: ldxrb w[[OLD:[0-9]+]], [x[[ADDR]]]
426 ; w0 below is a reasonable guess but could change: it certainly comes into the
428 ; CHECK-NEXT: stxrb [[STATUS:w[0-9]+]], w0, [x[[ADDR]]]
429 ; CHECK-NEXT: cbnz [[STATUS]], .LBB{{[0-9]+}}_1
432 ; CHECK: mov {{[xw]}}0, {{[xw]}}[[OLD]]
436 define i16 @test_atomic_load_xchg_i16(i16 %offset) nounwind {
437 ; CHECK-LABEL: test_atomic_load_xchg_i16:
438 %old = atomicrmw xchg i16* @var16, i16 %offset seq_cst
440 ; CHECK: adrp [[TMPADDR:x[0-9]+]], var16
441 ; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], {{#?}}:lo12:var16
443 ; CHECK: .LBB{{[0-9]+}}_1:
444 ; ; CHECK: ldaxrh w[[OLD:[0-9]+]], [x[[ADDR]]]
445 ; w0 below is a reasonable guess but could change: it certainly comes into the
447 ; CHECK-NEXT: stlxrh [[STATUS:w[0-9]+]], w0, [x[[ADDR]]]
448 ; CHECK-NEXT: cbnz [[STATUS]], .LBB{{[0-9]+}}_1
451 ; CHECK: mov {{[xw]}}0, {{[xw]}}[[OLD]]
455 define i32 @test_atomic_load_xchg_i32(i32 %offset) nounwind {
456 ; CHECK-LABEL: test_atomic_load_xchg_i32:
457 %old = atomicrmw xchg i32* @var32, i32 %offset release
459 ; CHECK: adrp [[TMPADDR:x[0-9]+]], var32
460 ; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], {{#?}}:lo12:var32
462 ; CHECK: .LBB{{[0-9]+}}_1:
463 ; ; CHECK: ldxr w[[OLD:[0-9]+]], [x[[ADDR]]]
464 ; w0 below is a reasonable guess but could change: it certainly comes into the
466 ; CHECK-NEXT: stlxr [[STATUS:w[0-9]+]], w0, [x[[ADDR]]]
467 ; CHECK-NEXT: cbnz [[STATUS]], .LBB{{[0-9]+}}_1
470 ; CHECK: mov {{[xw]}}0, {{[xw]}}[[OLD]]
474 define i64 @test_atomic_load_xchg_i64(i64 %offset) nounwind {
475 ; CHECK-LABEL: test_atomic_load_xchg_i64:
476 %old = atomicrmw xchg i64* @var64, i64 %offset acquire
478 ; CHECK: adrp [[TMPADDR:x[0-9]+]], var64
479 ; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], {{#?}}:lo12:var64
481 ; CHECK: .LBB{{[0-9]+}}_1:
482 ; ; CHECK: ldaxr x[[OLD:[0-9]+]], [x[[ADDR]]]
483 ; x0 below is a reasonable guess but could change: it certainly comes into the
485 ; CHECK-NEXT: stxr [[STATUS:w[0-9]+]], x0, [x[[ADDR]]]
486 ; CHECK-NEXT: cbnz [[STATUS]], .LBB{{[0-9]+}}_1
489 ; CHECK: mov x0, x[[OLD]]
494 define i8 @test_atomic_load_min_i8(i8 %offset) nounwind {
495 ; CHECK-LABEL: test_atomic_load_min_i8:
496 %old = atomicrmw min i8* @var8, i8 %offset acquire
498 ; CHECK: adrp [[TMPADDR:x[0-9]+]], var8
499 ; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], {{#?}}:lo12:var8
501 ; CHECK: .LBB{{[0-9]+}}_1:
502 ; CHECK: ldaxrb w[[OLD:[0-9]+]], [x[[ADDR]]]
503 ; w0 below is a reasonable guess but could change: it certainly comes into the
505 ; CHECK-AARCH64-NEXT: cmp w0, w[[OLD]], sxtb
506 ; CHECK-AARCH64-NEXT: csel [[NEW:w[0-9]+]], w[[OLD]], w0, gt
508 ; CHECK-ARM64-NEXT: sxtb w[[OLD_EXT:[0-9]+]], w[[OLD]]
509 ; CHECK-ARM64-NEXT: cmp w[[OLD_EXT]], w0, sxtb
510 ; CHECK-ARM64-NEXT: csel [[NEW:w[0-9]+]], w[[OLD]], w0, le
512 ; CHECK-NEXT: stxrb [[STATUS:w[0-9]+]], [[NEW]], [x[[ADDR]]]
513 ; CHECK-NEXT: cbnz [[STATUS]], .LBB{{[0-9]+}}_1
516 ; CHECK: mov {{[xw]}}0, {{[xw]}}[[OLD]]
520 define i16 @test_atomic_load_min_i16(i16 %offset) nounwind {
521 ; CHECK-LABEL: test_atomic_load_min_i16:
522 %old = atomicrmw min i16* @var16, i16 %offset release
524 ; CHECK: adrp [[TMPADDR:x[0-9]+]], var16
525 ; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], {{#?}}:lo12:var16
527 ; CHECK: .LBB{{[0-9]+}}_1:
528 ; CHECK: ldxrh w[[OLD:[0-9]+]], [x[[ADDR]]]
529 ; w0 below is a reasonable guess but could change: it certainly comes into the
531 ; CHECK-AARCH64-NEXT: cmp w0, w[[OLD]], sxth
532 ; CHECK-AARCH64-NEXT: csel [[NEW:w[0-9]+]], w[[OLD]], w0, gt
534 ; CHECK-ARM64-NEXT: sxth w[[OLD_EXT:[0-9]+]], w[[OLD]]
535 ; CHECK-ARM64-NEXT: cmp w[[OLD_EXT]], w0, sxth
536 ; CHECK-ARM64-NEXT: csel [[NEW:w[0-9]+]], w[[OLD]], w0, le
539 ; CHECK-NEXT: stlxrh [[STATUS:w[0-9]+]], [[NEW]], [x[[ADDR]]]
540 ; CHECK-NEXT: cbnz [[STATUS]], .LBB{{[0-9]+}}_1
543 ; CHECK: mov {{[xw]}}0, {{[xw]}}[[OLD]]
547 define i32 @test_atomic_load_min_i32(i32 %offset) nounwind {
548 ; CHECK-LABEL: test_atomic_load_min_i32:
549 %old = atomicrmw min i32* @var32, i32 %offset monotonic
551 ; CHECK: adrp [[TMPADDR:x[0-9]+]], var32
552 ; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], {{#?}}:lo12:var32
554 ; CHECK: .LBB{{[0-9]+}}_1:
555 ; CHECK: ldxr w[[OLD:[0-9]+]], [x[[ADDR]]]
556 ; w0 below is a reasonable guess but could change: it certainly comes into the
558 ; CHECK-AARCH64-NEXT: cmp w0, w[[OLD]]
559 ; CHECK-AARCH64-NEXT: csel [[NEW:w[0-9]+]], w[[OLD]], w0, gt
561 ; CHECK-ARM64-NEXT: cmp w[[OLD]], w0
562 ; CHECK-ARM64-NEXT: csel [[NEW:w[0-9]+]], w[[OLD]], w0, le
565 ; CHECK-NEXT: stxr [[STATUS:w[0-9]+]], [[NEW]], [x[[ADDR]]]
566 ; CHECK-NEXT: cbnz [[STATUS]], .LBB{{[0-9]+}}_1
569 ; CHECK: mov {{[xw]}}0, {{[xw]}}[[OLD]]
573 define i64 @test_atomic_load_min_i64(i64 %offset) nounwind {
574 ; CHECK-LABEL: test_atomic_load_min_i64:
575 %old = atomicrmw min i64* @var64, i64 %offset seq_cst
577 ; CHECK: adrp [[TMPADDR:x[0-9]+]], var64
578 ; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], {{#?}}:lo12:var64
580 ; CHECK: .LBB{{[0-9]+}}_1:
581 ; CHECK: ldaxr x[[OLD:[0-9]+]], [x[[ADDR]]]
582 ; x0 below is a reasonable guess but could change: it certainly comes into the
584 ; CHECK-AARCH64-NEXT: cmp x0, x[[OLD]]
585 ; CHECK-AARCH64-NEXT: csel [[NEW:x[0-9]+]], x[[OLD]], x0, gt
587 ; CHECK-ARM64-NEXT: cmp x[[OLD]], x0
588 ; CHECK-ARM64-NEXT: csel [[NEW:x[0-9]+]], x[[OLD]], x0, le
591 ; CHECK-NEXT: stlxr [[STATUS:w[0-9]+]], [[NEW]], [x[[ADDR]]]
592 ; CHECK-NEXT: cbnz [[STATUS]], .LBB{{[0-9]+}}_1
595 ; CHECK: mov x0, x[[OLD]]
599 define i8 @test_atomic_load_max_i8(i8 %offset) nounwind {
600 ; CHECK-LABEL: test_atomic_load_max_i8:
601 %old = atomicrmw max i8* @var8, i8 %offset seq_cst
603 ; CHECK: adrp [[TMPADDR:x[0-9]+]], var8
604 ; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], {{#?}}:lo12:var8
606 ; CHECK: .LBB{{[0-9]+}}_1:
607 ; CHECK: ldaxrb w[[OLD:[0-9]+]], [x[[ADDR]]]
608 ; w0 below is a reasonable guess but could change: it certainly comes into the
610 ; CHECK-AARCH64-NEXT: cmp w0, w[[OLD]], sxtb
611 ; CHECK-AARCH64-NEXT: csel [[NEW:w[0-9]+]], w[[OLD]], w0, lt
613 ; CHECK-ARM64-NEXT: sxtb w[[OLD_EXT:[0-9]+]], w[[OLD]]
614 ; CHECK-ARM64-NEXT: cmp w[[OLD_EXT]], w0, sxtb
615 ; CHECK-ARM64-NEXT: csel [[NEW:w[0-9]+]], w[[OLD]], w0, gt
618 ; CHECK-NEXT: stlxrb [[STATUS:w[0-9]+]], [[NEW]], [x[[ADDR]]]
619 ; CHECK-NEXT: cbnz [[STATUS]], .LBB{{[0-9]+}}_1
622 ; CHECK: mov {{[xw]}}0, {{[xw]}}[[OLD]]
626 define i16 @test_atomic_load_max_i16(i16 %offset) nounwind {
627 ; CHECK-LABEL: test_atomic_load_max_i16:
628 %old = atomicrmw max i16* @var16, i16 %offset acquire
630 ; CHECK: adrp [[TMPADDR:x[0-9]+]], var16
631 ; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], {{#?}}:lo12:var16
633 ; CHECK: .LBB{{[0-9]+}}_1:
634 ; CHECK: ldaxrh w[[OLD:[0-9]+]], [x[[ADDR]]]
635 ; w0 below is a reasonable guess but could change: it certainly comes into the
637 ; CHECK-AARCH64-NEXT: cmp w0, w[[OLD]], sxth
638 ; CHECK-AARCH64-NEXT: csel [[NEW:w[0-9]+]], w[[OLD]], w0, lt
640 ; CHECK-ARM64-NEXT: sxth w[[OLD_EXT:[0-9]+]], w[[OLD]]
641 ; CHECK-ARM64-NEXT: cmp w[[OLD_EXT]], w0, sxth
642 ; CHECK-ARM64-NEXT: csel [[NEW:w[0-9]+]], w[[OLD]], w0, gt
645 ; CHECK-NEXT: stxrh [[STATUS:w[0-9]+]], [[NEW]], [x[[ADDR]]]
646 ; CHECK-NEXT: cbnz [[STATUS]], .LBB{{[0-9]+}}_1
649 ; CHECK: mov {{[xw]}}0, {{[xw]}}[[OLD]]
653 define i32 @test_atomic_load_max_i32(i32 %offset) nounwind {
654 ; CHECK-LABEL: test_atomic_load_max_i32:
655 %old = atomicrmw max i32* @var32, i32 %offset release
657 ; CHECK: adrp [[TMPADDR:x[0-9]+]], var32
658 ; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], {{#?}}:lo12:var32
660 ; CHECK: .LBB{{[0-9]+}}_1:
661 ; CHECK: ldxr w[[OLD:[0-9]+]], [x[[ADDR]]]
662 ; w0 below is a reasonable guess but could change: it certainly comes into the
664 ; CHECK-AARCH64-NEXT: cmp w0, w[[OLD]]
665 ; CHECK-AARCH64-NEXT: csel [[NEW:w[0-9]+]], w[[OLD]], w0, lt
667 ; CHECK-ARM64-NEXT: cmp w[[OLD]], w0
668 ; CHECK-ARM64-NEXT: csel [[NEW:w[0-9]+]], w[[OLD]], w0, gt
671 ; CHECK-NEXT: stlxr [[STATUS:w[0-9]+]], [[NEW]], [x[[ADDR]]]
672 ; CHECK-NEXT: cbnz [[STATUS]], .LBB{{[0-9]+}}_1
675 ; CHECK: mov {{[xw]}}0, {{[xw]}}[[OLD]]
679 define i64 @test_atomic_load_max_i64(i64 %offset) nounwind {
680 ; CHECK-LABEL: test_atomic_load_max_i64:
681 %old = atomicrmw max i64* @var64, i64 %offset monotonic
683 ; CHECK: adrp [[TMPADDR:x[0-9]+]], var64
684 ; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], {{#?}}:lo12:var64
686 ; CHECK: .LBB{{[0-9]+}}_1:
687 ; CHECK: ldxr x[[OLD:[0-9]+]], [x[[ADDR]]]
688 ; x0 below is a reasonable guess but could change: it certainly comes into the
690 ; CHECK-AARCH64-NEXT: cmp x0, x[[OLD]]
691 ; CHECK-AARCH64-NEXT: csel [[NEW:x[0-9]+]], x[[OLD]], x0, lt
693 ; CHECK-ARM64-NEXT: cmp x[[OLD]], x0
694 ; CHECK-ARM64-NEXT: csel [[NEW:x[0-9]+]], x[[OLD]], x0, gt
697 ; CHECK-NEXT: stxr [[STATUS:w[0-9]+]], [[NEW]], [x[[ADDR]]]
698 ; CHECK-NEXT: cbnz [[STATUS]], .LBB{{[0-9]+}}_1
701 ; CHECK: mov x0, x[[OLD]]
705 define i8 @test_atomic_load_umin_i8(i8 %offset) nounwind {
706 ; CHECK-LABEL: test_atomic_load_umin_i8:
707 %old = atomicrmw umin i8* @var8, i8 %offset monotonic
709 ; CHECK: adrp [[TMPADDR:x[0-9]+]], var8
710 ; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], {{#?}}:lo12:var8
712 ; CHECK: .LBB{{[0-9]+}}_1:
713 ; CHECK: ldxrb w[[OLD:[0-9]+]], [x[[ADDR]]]
714 ; w0 below is a reasonable guess but could change: it certainly comes into the
716 ; CHECK-AARCH64-NEXT: cmp w0, w[[OLD]], uxtb
717 ; CHECK-AARCH64-NEXT: csel [[NEW:w[0-9]+]], w[[OLD]], w0, hi
719 ; CHECK-ARM64-NEXT: cmp w[[OLD]], w0, uxtb
720 ; CHECK-ARM64-NEXT: csel [[NEW:w[0-9]+]], w[[OLD]], w0, ls
723 ; CHECK-NEXT: stxrb [[STATUS:w[0-9]+]], [[NEW]], [x[[ADDR]]]
724 ; CHECK-NEXT: cbnz [[STATUS]], .LBB{{[0-9]+}}_1
727 ; CHECK: mov {{[xw]}}0, {{[xw]}}[[OLD]]
731 define i16 @test_atomic_load_umin_i16(i16 %offset) nounwind {
732 ; CHECK-LABEL: test_atomic_load_umin_i16:
733 %old = atomicrmw umin i16* @var16, i16 %offset acquire
735 ; CHECK: adrp [[TMPADDR:x[0-9]+]], var16
736 ; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], {{#?}}:lo12:var16
738 ; CHECK: .LBB{{[0-9]+}}_1:
739 ; CHECK: ldaxrh w[[OLD:[0-9]+]], [x[[ADDR]]]
740 ; w0 below is a reasonable guess but could change: it certainly comes into the
742 ; CHECK-AARCH64-NEXT: cmp w0, w[[OLD]], uxth
743 ; CHECK-AARCH64-NEXT: csel [[NEW:w[0-9]+]], w[[OLD]], w0, hi
745 ; CHECK-ARM64-NEXT: cmp w[[OLD]], w0, uxth
746 ; CHECK-ARM64-NEXT: csel [[NEW:w[0-9]+]], w[[OLD]], w0, ls
749 ; CHECK-NEXT: stxrh [[STATUS:w[0-9]+]], [[NEW]], [x[[ADDR]]]
750 ; CHECK-NEXT: cbnz [[STATUS]], .LBB{{[0-9]+}}_1
753 ; CHECK: mov {{[xw]}}0, {{[xw]}}[[OLD]]
757 define i32 @test_atomic_load_umin_i32(i32 %offset) nounwind {
758 ; CHECK-LABEL: test_atomic_load_umin_i32:
759 %old = atomicrmw umin i32* @var32, i32 %offset seq_cst
761 ; CHECK: adrp [[TMPADDR:x[0-9]+]], var32
762 ; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], {{#?}}:lo12:var32
764 ; CHECK: .LBB{{[0-9]+}}_1:
765 ; CHECK: ldaxr w[[OLD:[0-9]+]], [x[[ADDR]]]
766 ; w0 below is a reasonable guess but could change: it certainly comes into the
768 ; CHECK-AARCH64-NEXT: cmp w0, w[[OLD]]
769 ; CHECK-AARCH64-NEXT: csel [[NEW:w[0-9]+]], w[[OLD]], w0, hi
771 ; CHECK-ARM64-NEXT: cmp w[[OLD]], w0
772 ; CHECK-ARM64-NEXT: csel [[NEW:w[0-9]+]], w[[OLD]], w0, ls
775 ; CHECK-NEXT: stlxr [[STATUS:w[0-9]+]], [[NEW]], [x[[ADDR]]]
776 ; CHECK-NEXT: cbnz [[STATUS]], .LBB{{[0-9]+}}_1
779 ; CHECK: mov {{[xw]}}0, {{[xw]}}[[OLD]]
783 define i64 @test_atomic_load_umin_i64(i64 %offset) nounwind {
784 ; CHECK-LABEL: test_atomic_load_umin_i64:
785 %old = atomicrmw umin i64* @var64, i64 %offset acq_rel
787 ; CHECK: adrp [[TMPADDR:x[0-9]+]], var64
788 ; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], {{#?}}:lo12:var64
790 ; CHECK: .LBB{{[0-9]+}}_1:
791 ; CHECK: ldaxr x[[OLD:[0-9]+]], [x[[ADDR]]]
792 ; x0 below is a reasonable guess but could change: it certainly comes into the
794 ; CHECK-AARCH64-NEXT: cmp x0, x[[OLD]]
795 ; CHECK-AARCH64-NEXT: csel [[NEW:x[0-9]+]], x[[OLD]], x0, hi
797 ; CHECK-ARM64-NEXT: cmp x[[OLD]], x0
798 ; CHECK-ARM64-NEXT: csel [[NEW:x[0-9]+]], x[[OLD]], x0, ls
801 ; CHECK-NEXT: stlxr [[STATUS:w[0-9]+]], [[NEW]], [x[[ADDR]]]
802 ; CHECK-NEXT: cbnz [[STATUS]], .LBB{{[0-9]+}}_1
805 ; CHECK: mov x0, x[[OLD]]
809 define i8 @test_atomic_load_umax_i8(i8 %offset) nounwind {
810 ; CHECK-LABEL: test_atomic_load_umax_i8:
811 %old = atomicrmw umax i8* @var8, i8 %offset acq_rel
813 ; CHECK: adrp [[TMPADDR:x[0-9]+]], var8
814 ; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], {{#?}}:lo12:var8
816 ; CHECK: .LBB{{[0-9]+}}_1:
817 ; CHECK: ldaxrb w[[OLD:[0-9]+]], [x[[ADDR]]]
818 ; w0 below is a reasonable guess but could change: it certainly comes into the
820 ; CHECK-AARCH64-NEXT: cmp w0, w[[OLD]], uxtb
821 ; CHECK-AARCH64-NEXT: csel [[NEW:w[0-9]+]], w[[OLD]], w0, lo
823 ; CHECK-ARM64-NEXT: cmp w[[OLD]], w0, uxtb
824 ; CHECK-ARM64-NEXT: csel [[NEW:w[0-9]+]], w[[OLD]], w0, hi
827 ; CHECK-NEXT: stlxrb [[STATUS:w[0-9]+]], [[NEW]], [x[[ADDR]]]
828 ; CHECK-NEXT: cbnz [[STATUS]], .LBB{{[0-9]+}}_1
831 ; CHECK: mov {{[xw]}}0, {{[xw]}}[[OLD]]
835 define i16 @test_atomic_load_umax_i16(i16 %offset) nounwind {
836 ; CHECK-LABEL: test_atomic_load_umax_i16:
837 %old = atomicrmw umax i16* @var16, i16 %offset monotonic
839 ; CHECK: adrp [[TMPADDR:x[0-9]+]], var16
840 ; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], {{#?}}:lo12:var16
842 ; CHECK: .LBB{{[0-9]+}}_1:
843 ; CHECK: ldxrh w[[OLD:[0-9]+]], [x[[ADDR]]]
844 ; w0 below is a reasonable guess but could change: it certainly comes into the
846 ; CHECK-AARCH64-NEXT: cmp w0, w[[OLD]], uxth
847 ; CHECK-AARCH64-NEXT: csel [[NEW:w[0-9]+]], w[[OLD]], w0, lo
849 ; CHECK-ARM64-NEXT: cmp w[[OLD]], w0, uxth
850 ; CHECK-ARM64-NEXT: csel [[NEW:w[0-9]+]], w[[OLD]], w0, hi
853 ; CHECK-NEXT: stxrh [[STATUS:w[0-9]+]], [[NEW]], [x[[ADDR]]]
854 ; CHECK-NEXT: cbnz [[STATUS]], .LBB{{[0-9]+}}_1
857 ; CHECK: mov {{[xw]}}0, {{[xw]}}[[OLD]]
861 define i32 @test_atomic_load_umax_i32(i32 %offset) nounwind {
862 ; CHECK-LABEL: test_atomic_load_umax_i32:
863 %old = atomicrmw umax i32* @var32, i32 %offset seq_cst
865 ; CHECK: adrp [[TMPADDR:x[0-9]+]], var32
866 ; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], {{#?}}:lo12:var32
868 ; CHECK: .LBB{{[0-9]+}}_1:
869 ; CHECK: ldaxr w[[OLD:[0-9]+]], [x[[ADDR]]]
870 ; w0 below is a reasonable guess but could change: it certainly comes into the
872 ; CHECK-AARCH64-NEXT: cmp w0, w[[OLD]]
873 ; CHECK-AARCH64-NEXT: csel [[NEW:w[0-9]+]], w[[OLD]], w0, lo
875 ; CHECK-ARM64-NEXT: cmp w[[OLD]], w0
876 ; CHECK-ARM64-NEXT: csel [[NEW:w[0-9]+]], w[[OLD]], w0, hi
879 ; CHECK-NEXT: stlxr [[STATUS:w[0-9]+]], [[NEW]], [x[[ADDR]]]
880 ; CHECK-NEXT: cbnz [[STATUS]], .LBB{{[0-9]+}}_1
883 ; CHECK: mov {{[xw]}}0, {{[xw]}}[[OLD]]
887 define i64 @test_atomic_load_umax_i64(i64 %offset) nounwind {
888 ; CHECK-LABEL: test_atomic_load_umax_i64:
889 %old = atomicrmw umax i64* @var64, i64 %offset release
891 ; CHECK: adrp [[TMPADDR:x[0-9]+]], var64
892 ; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], {{#?}}:lo12:var64
894 ; CHECK: .LBB{{[0-9]+}}_1:
895 ; CHECK: ldxr x[[OLD:[0-9]+]], [x[[ADDR]]]
896 ; x0 below is a reasonable guess but could change: it certainly comes into the
898 ; CHECK-AARCH64-NEXT: cmp x0, x[[OLD]]
899 ; CHECK-AARCH64-NEXT: csel [[NEW:x[0-9]+]], x[[OLD]], x0, lo
901 ; CHECK-ARM64-NEXT: cmp x[[OLD]], x0
902 ; CHECK-ARM64-NEXT: csel [[NEW:x[0-9]+]], x[[OLD]], x0, hi
905 ; CHECK-NEXT: stlxr [[STATUS:w[0-9]+]], [[NEW]], [x[[ADDR]]]
906 ; CHECK-NEXT: cbnz [[STATUS]], .LBB{{[0-9]+}}_1
909 ; CHECK: mov x0, x[[OLD]]
913 define i8 @test_atomic_cmpxchg_i8(i8 %wanted, i8 %new) nounwind {
914 ; CHECK-LABEL: test_atomic_cmpxchg_i8:
915 %old = cmpxchg i8* @var8, i8 %wanted, i8 %new acquire acquire
917 ; CHECK: adrp [[TMPADDR:x[0-9]+]], var8
918 ; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], {{#?}}:lo12:var8
920 ; CHECK: [[STARTAGAIN:.LBB[0-9]+_[0-9]+]]:
921 ; CHECK: ldaxrb w[[OLD:[0-9]+]], [x[[ADDR]]]
922 ; w0 below is a reasonable guess but could change: it certainly comes into the
924 ; CHECK-NEXT: cmp w[[OLD]], w0
925 ; CHECK-NEXT: b.ne [[GET_OUT:.LBB[0-9]+_[0-9]+]]
926 ; As above, w1 is a reasonable guess.
927 ; CHECK: stxrb [[STATUS:w[0-9]+]], w1, [x[[ADDR]]]
928 ; CHECK-NEXT: cbnz [[STATUS]], [[STARTAGAIN]]
931 ; CHECK: mov {{[xw]}}0, {{[xw]}}[[OLD]]
935 define i16 @test_atomic_cmpxchg_i16(i16 %wanted, i16 %new) nounwind {
936 ; CHECK-LABEL: test_atomic_cmpxchg_i16:
937 %old = cmpxchg i16* @var16, i16 %wanted, i16 %new seq_cst seq_cst
939 ; CHECK: adrp [[TMPADDR:x[0-9]+]], var16
940 ; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], {{#?}}:lo12:var16
942 ; CHECK: [[STARTAGAIN:.LBB[0-9]+_[0-9]+]]:
943 ; CHECK: ldaxrh w[[OLD:[0-9]+]], [x[[ADDR]]]
944 ; w0 below is a reasonable guess but could change: it certainly comes into the
946 ; CHECK-NEXT: cmp w[[OLD]], w0
947 ; CHECK-NEXT: b.ne [[GET_OUT:.LBB[0-9]+_[0-9]+]]
948 ; As above, w1 is a reasonable guess.
949 ; CHECK: stlxrh [[STATUS:w[0-9]+]], w1, [x[[ADDR]]]
950 ; CHECK-NEXT: cbnz [[STATUS]], [[STARTAGAIN]]
953 ; CHECK: mov {{[xw]}}0, {{[xw]}}[[OLD]]
957 define i32 @test_atomic_cmpxchg_i32(i32 %wanted, i32 %new) nounwind {
958 ; CHECK-LABEL: test_atomic_cmpxchg_i32:
959 %old = cmpxchg i32* @var32, i32 %wanted, i32 %new release monotonic
961 ; CHECK: adrp [[TMPADDR:x[0-9]+]], var32
962 ; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], {{#?}}:lo12:var32
964 ; CHECK: [[STARTAGAIN:.LBB[0-9]+_[0-9]+]]:
965 ; CHECK: ldxr w[[OLD:[0-9]+]], [x[[ADDR]]]
966 ; w0 below is a reasonable guess but could change: it certainly comes into the
968 ; CHECK-NEXT: cmp w[[OLD]], w0
969 ; CHECK-NEXT: b.ne [[GET_OUT:.LBB[0-9]+_[0-9]+]]
970 ; As above, w1 is a reasonable guess.
971 ; CHECK: stlxr [[STATUS:w[0-9]+]], w1, [x[[ADDR]]]
972 ; CHECK-NEXT: cbnz [[STATUS]], [[STARTAGAIN]]
975 ; CHECK: mov {{[xw]}}0, {{[xw]}}[[OLD]]
979 define void @test_atomic_cmpxchg_i64(i64 %wanted, i64 %new) nounwind {
980 ; CHECK-LABEL: test_atomic_cmpxchg_i64:
981 %old = cmpxchg i64* @var64, i64 %wanted, i64 %new monotonic monotonic
983 ; CHECK: adrp [[TMPADDR:x[0-9]+]], var64
984 ; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], {{#?}}:lo12:var64
986 ; CHECK: [[STARTAGAIN:.LBB[0-9]+_[0-9]+]]:
987 ; CHECK: ldxr x[[OLD:[0-9]+]], [x[[ADDR]]]
988 ; w0 below is a reasonable guess but could change: it certainly comes into the
990 ; CHECK-NEXT: cmp x[[OLD]], x0
991 ; CHECK-NEXT: b.ne [[GET_OUT:.LBB[0-9]+_[0-9]+]]
992 ; As above, w1 is a reasonable guess.
993 ; CHECK: stxr [[STATUS:w[0-9]+]], x1, [x[[ADDR]]]
994 ; CHECK-NEXT: cbnz [[STATUS]], [[STARTAGAIN]]
997 ; CHECK: str x[[OLD]],
998 store i64 %old, i64* @var64
1002 define i8 @test_atomic_load_monotonic_i8() nounwind {
1003 ; CHECK-LABEL: test_atomic_load_monotonic_i8:
1004 %val = load atomic i8* @var8 monotonic, align 1
1006 ; CHECK: adrp x[[HIADDR:[0-9]+]], var8
1007 ; CHECK: ldrb w0, [x[[HIADDR]], {{#?}}:lo12:var8]
1013 define i8 @test_atomic_load_monotonic_regoff_i8(i64 %base, i64 %off) nounwind {
1014 ; CHECK-LABEL: test_atomic_load_monotonic_regoff_i8:
1015 %addr_int = add i64 %base, %off
1016 %addr = inttoptr i64 %addr_int to i8*
1018 %val = load atomic i8* %addr monotonic, align 1
1020 ; CHECK: ldrb w0, [x0, x1]
1026 define i8 @test_atomic_load_acquire_i8() nounwind {
1027 ; CHECK-LABEL: test_atomic_load_acquire_i8:
1028 %val = load atomic i8* @var8 acquire, align 1
1030 ; CHECK: adrp [[TMPADDR:x[0-9]+]], var8
1032 ; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], {{#?}}:lo12:var8
1034 ; CHECK: ldarb w0, [x[[ADDR]]]
1039 define i8 @test_atomic_load_seq_cst_i8() nounwind {
1040 ; CHECK-LABEL: test_atomic_load_seq_cst_i8:
1041 %val = load atomic i8* @var8 seq_cst, align 1
1043 ; CHECK: adrp [[HIADDR:x[0-9]+]], var8
1045 ; CHECK: add x[[ADDR:[0-9]+]], [[HIADDR]], {{#?}}:lo12:var8
1047 ; CHECK: ldarb w0, [x[[ADDR]]]
1052 define i16 @test_atomic_load_monotonic_i16() nounwind {
1053 ; CHECK-LABEL: test_atomic_load_monotonic_i16:
1054 %val = load atomic i16* @var16 monotonic, align 2
1056 ; CHECK: adrp x[[HIADDR:[0-9]+]], var16
1058 ; CHECK: ldrh w0, [x[[HIADDR]], {{#?}}:lo12:var16]
1064 define i32 @test_atomic_load_monotonic_regoff_i32(i64 %base, i64 %off) nounwind {
1065 ; CHECK-LABEL: test_atomic_load_monotonic_regoff_i32:
1066 %addr_int = add i64 %base, %off
1067 %addr = inttoptr i64 %addr_int to i32*
1069 %val = load atomic i32* %addr monotonic, align 4
1071 ; CHECK: ldr w0, [x0, x1]
1077 define i64 @test_atomic_load_seq_cst_i64() nounwind {
1078 ; CHECK-LABEL: test_atomic_load_seq_cst_i64:
1079 %val = load atomic i64* @var64 seq_cst, align 8
1081 ; CHECK: adrp [[HIADDR:x[0-9]+]], var64
1083 ; CHECK: add x[[ADDR:[0-9]+]], [[HIADDR]], {{#?}}:lo12:var64
1085 ; CHECK: ldar x0, [x[[ADDR]]]
1090 define void @test_atomic_store_monotonic_i8(i8 %val) nounwind {
1091 ; CHECK-LABEL: test_atomic_store_monotonic_i8:
1092 store atomic i8 %val, i8* @var8 monotonic, align 1
1093 ; CHECK: adrp x[[HIADDR:[0-9]+]], var8
1094 ; CHECK: strb w0, [x[[HIADDR]], {{#?}}:lo12:var8]
1099 define void @test_atomic_store_monotonic_regoff_i8(i64 %base, i64 %off, i8 %val) nounwind {
1100 ; CHECK-LABEL: test_atomic_store_monotonic_regoff_i8:
1102 %addr_int = add i64 %base, %off
1103 %addr = inttoptr i64 %addr_int to i8*
1105 store atomic i8 %val, i8* %addr monotonic, align 1
1106 ; CHECK: strb w2, [x0, x1]
1110 define void @test_atomic_store_release_i8(i8 %val) nounwind {
1111 ; CHECK-LABEL: test_atomic_store_release_i8:
1112 store atomic i8 %val, i8* @var8 release, align 1
1114 ; CHECK: adrp [[HIADDR:x[0-9]+]], var8
1116 ; CHECK: add x[[ADDR:[0-9]+]], [[HIADDR]], {{#?}}:lo12:var8
1118 ; CHECK: stlrb w0, [x[[ADDR]]]
1123 define void @test_atomic_store_seq_cst_i8(i8 %val) nounwind {
1124 ; CHECK-LABEL: test_atomic_store_seq_cst_i8:
1125 store atomic i8 %val, i8* @var8 seq_cst, align 1
1127 ; CHECK: adrp [[HIADDR:x[0-9]+]], var8
1129 ; CHECK: add x[[ADDR:[0-9]+]], [[HIADDR]], {{#?}}:lo12:var8
1131 ; CHECK: stlrb w0, [x[[ADDR]]]
1137 define void @test_atomic_store_monotonic_i16(i16 %val) nounwind {
1138 ; CHECK-LABEL: test_atomic_store_monotonic_i16:
1139 store atomic i16 %val, i16* @var16 monotonic, align 2
1141 ; CHECK: adrp x[[HIADDR:[0-9]+]], var16
1143 ; CHECK: strh w0, [x[[HIADDR]], {{#?}}:lo12:var16]
1148 define void @test_atomic_store_monotonic_regoff_i32(i64 %base, i64 %off, i32 %val) nounwind {
1149 ; CHECK-LABEL: test_atomic_store_monotonic_regoff_i32:
1151 %addr_int = add i64 %base, %off
1152 %addr = inttoptr i64 %addr_int to i32*
1154 store atomic i32 %val, i32* %addr monotonic, align 4
1156 ; CHECK: str w2, [x0, x1]
1162 define void @test_atomic_store_release_i64(i64 %val) nounwind {
1163 ; CHECK-LABEL: test_atomic_store_release_i64:
1164 store atomic i64 %val, i64* @var64 release, align 8
1166 ; CHECK: adrp [[HIADDR:x[0-9]+]], var64
1168 ; CHECK: add x[[ADDR:[0-9]+]], [[HIADDR]], {{#?}}:lo12:var64
1170 ; CHECK: stlr x0, [x[[ADDR]]]