blob: 8a1e97626d6cc2e6487fec452870c4193cb643ac [file] [log] [blame]
Tim Northovere0e3aef2013-01-31 12:12:40 +00001; RUN: llc -march=aarch64 -verify-machineinstrs < %s | FileCheck %s
2
3@var8 = global i8 0
4@var16 = global i16 0
5@var32 = global i32 0
6@var64 = global i64 0
7
8define i8 @test_atomic_load_add_i8(i8 %offset) nounwind {
9; CHECK: test_atomic_load_add_i8:
10 %old = atomicrmw add i8* @var8, i8 %offset seq_cst
11; CHECK: dmb ish
12; CHECK: adrp [[TMPADDR:x[0-9]+]], var8
13; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], #:lo12:var8
14
15; CHECK: .LBB{{[0-9]+}}_1:
16; CHECK-NEXT: ldxrb w[[OLD:[0-9]+]], [x[[ADDR]]]
17 ; w0 below is a reasonable guess but could change: it certainly comes into the
18 ; function there.
19; CHECK-NEXT: add [[NEW:w[0-9]+]], w[[OLD]], w0
20; CHECK-NEXT: stxrb [[STATUS:w[0-9]+]], [[NEW]], [x[[ADDR]]]
21; CHECK-NEXT: cmp [[STATUS]], #0
22; CHECK-NEXT: b.ne .LBB{{[0-9]+}}_1
23; CHECK: dmb ish
24
25; CHECK: mov x0, x[[OLD]]
26 ret i8 %old
27}
28
29define i16 @test_atomic_load_add_i16(i16 %offset) nounwind {
30; CHECK: test_atomic_load_add_i16:
31 %old = atomicrmw add i16* @var16, i16 %offset seq_cst
32; CHECK: dmb ish
33; CHECK: adrp [[TMPADDR:x[0-9]+]], var16
34; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], #:lo12:var16
35
36; CHECK: .LBB{{[0-9]+}}_1:
37; CHECK-NEXT: ldxrh w[[OLD:[0-9]+]], [x[[ADDR]]]
38 ; w0 below is a reasonable guess but could change: it certainly comes into the
39 ; function there.
40; CHECK-NEXT: add [[NEW:w[0-9]+]], w[[OLD]], w0
41; CHECK-NEXT: stxrh [[STATUS:w[0-9]+]], [[NEW]], [x[[ADDR]]]
42; CHECK-NEXT: cmp [[STATUS]], #0
43; CHECK-NEXT: b.ne .LBB{{[0-9]+}}_1
44; CHECK: dmb ish
45
46; CHECK: mov x0, x[[OLD]]
47 ret i16 %old
48}
49
50define i32 @test_atomic_load_add_i32(i32 %offset) nounwind {
51; CHECK: test_atomic_load_add_i32:
52 %old = atomicrmw add i32* @var32, i32 %offset seq_cst
53; CHECK: dmb ish
54; CHECK: adrp [[TMPADDR:x[0-9]+]], var32
55; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], #:lo12:var32
56
57; CHECK: .LBB{{[0-9]+}}_1:
58; CHECK-NEXT: ldxr w[[OLD:[0-9]+]], [x[[ADDR]]]
59 ; w0 below is a reasonable guess but could change: it certainly comes into the
60 ; function there.
61; CHECK-NEXT: add [[NEW:w[0-9]+]], w[[OLD]], w0
62; CHECK-NEXT: stxr [[STATUS:w[0-9]+]], [[NEW]], [x[[ADDR]]]
63; CHECK-NEXT: cmp [[STATUS]], #0
64; CHECK-NEXT: b.ne .LBB{{[0-9]+}}_1
65; CHECK: dmb ish
66
67; CHECK: mov x0, x[[OLD]]
68 ret i32 %old
69}
70
71define i64 @test_atomic_load_add_i64(i64 %offset) nounwind {
72; CHECK: test_atomic_load_add_i64:
73 %old = atomicrmw add i64* @var64, i64 %offset seq_cst
74; CHECK: dmb ish
75; CHECK: adrp [[TMPADDR:x[0-9]+]], var64
76; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], #:lo12:var64
77
78; CHECK: .LBB{{[0-9]+}}_1:
79; CHECK-NEXT: ldxr x[[OLD:[0-9]+]], [x[[ADDR]]]
80 ; x0 below is a reasonable guess but could change: it certainly comes into the
81 ; function there.
82; CHECK-NEXT: add [[NEW:x[0-9]+]], x[[OLD]], x0
83; CHECK-NEXT: stxr [[STATUS:w[0-9]+]], [[NEW]], [x[[ADDR]]]
84; CHECK-NEXT: cmp [[STATUS]], #0
85; CHECK-NEXT: b.ne .LBB{{[0-9]+}}_1
86; CHECK: dmb ish
87
88; CHECK: mov x0, x[[OLD]]
89 ret i64 %old
90}
91
92define i8 @test_atomic_load_sub_i8(i8 %offset) nounwind {
93; CHECK: test_atomic_load_sub_i8:
94 %old = atomicrmw sub i8* @var8, i8 %offset seq_cst
95; CHECK: dmb ish
96; CHECK: adrp [[TMPADDR:x[0-9]+]], var8
97; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], #:lo12:var8
98
99; CHECK: .LBB{{[0-9]+}}_1:
100; CHECK-NEXT: ldxrb w[[OLD:[0-9]+]], [x[[ADDR]]]
101 ; w0 below is a reasonable guess but could change: it certainly comes into the
102 ; function there.
103; CHECK-NEXT: sub [[NEW:w[0-9]+]], w[[OLD]], w0
104; CHECK-NEXT: stxrb [[STATUS:w[0-9]+]], [[NEW]], [x[[ADDR]]]
105; CHECK-NEXT: cmp [[STATUS]], #0
106; CHECK-NEXT: b.ne .LBB{{[0-9]+}}_1
107; CHECK: dmb ish
108
109; CHECK: mov x0, x[[OLD]]
110 ret i8 %old
111}
112
113define i16 @test_atomic_load_sub_i16(i16 %offset) nounwind {
114; CHECK: test_atomic_load_sub_i16:
115 %old = atomicrmw sub i16* @var16, i16 %offset seq_cst
116; CHECK: dmb ish
117; CHECK: adrp [[TMPADDR:x[0-9]+]], var16
118; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], #:lo12:var16
119
120; CHECK: .LBB{{[0-9]+}}_1:
121; CHECK-NEXT: ldxrh w[[OLD:[0-9]+]], [x[[ADDR]]]
122 ; w0 below is a reasonable guess but could change: it certainly comes into the
123 ; function there.
124; CHECK-NEXT: sub [[NEW:w[0-9]+]], w[[OLD]], w0
125; CHECK-NEXT: stxrh [[STATUS:w[0-9]+]], [[NEW]], [x[[ADDR]]]
126; CHECK-NEXT: cmp [[STATUS]], #0
127; CHECK-NEXT: b.ne .LBB{{[0-9]+}}_1
128; CHECK: dmb ish
129
130; CHECK: mov x0, x[[OLD]]
131 ret i16 %old
132}
133
134define i32 @test_atomic_load_sub_i32(i32 %offset) nounwind {
135; CHECK: test_atomic_load_sub_i32:
136 %old = atomicrmw sub i32* @var32, i32 %offset seq_cst
137; CHECK: dmb ish
138; CHECK: adrp [[TMPADDR:x[0-9]+]], var32
139; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], #:lo12:var32
140
141; CHECK: .LBB{{[0-9]+}}_1:
142; CHECK-NEXT: ldxr w[[OLD:[0-9]+]], [x[[ADDR]]]
143 ; w0 below is a reasonable guess but could change: it certainly comes into the
144 ; function there.
145; CHECK-NEXT: sub [[NEW:w[0-9]+]], w[[OLD]], w0
146; CHECK-NEXT: stxr [[STATUS:w[0-9]+]], [[NEW]], [x[[ADDR]]]
147; CHECK-NEXT: cmp [[STATUS]], #0
148; CHECK-NEXT: b.ne .LBB{{[0-9]+}}_1
149; CHECK: dmb ish
150
151; CHECK: mov x0, x[[OLD]]
152 ret i32 %old
153}
154
155define i64 @test_atomic_load_sub_i64(i64 %offset) nounwind {
156; CHECK: test_atomic_load_sub_i64:
157 %old = atomicrmw sub i64* @var64, i64 %offset seq_cst
158; CHECK: dmb ish
159; CHECK: adrp [[TMPADDR:x[0-9]+]], var64
160; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], #:lo12:var64
161
162; CHECK: .LBB{{[0-9]+}}_1:
163; CHECK-NEXT: ldxr x[[OLD:[0-9]+]], [x[[ADDR]]]
164 ; x0 below is a reasonable guess but could change: it certainly comes into the
165 ; function there.
166; CHECK-NEXT: sub [[NEW:x[0-9]+]], x[[OLD]], x0
167; CHECK-NEXT: stxr [[STATUS:w[0-9]+]], [[NEW]], [x[[ADDR]]]
168; CHECK-NEXT: cmp [[STATUS]], #0
169; CHECK-NEXT: b.ne .LBB{{[0-9]+}}_1
170; CHECK: dmb ish
171
172; CHECK: mov x0, x[[OLD]]
173 ret i64 %old
174}
175
176define i8 @test_atomic_load_and_i8(i8 %offset) nounwind {
177; CHECK: test_atomic_load_and_i8:
178 %old = atomicrmw and i8* @var8, i8 %offset seq_cst
179; CHECK: dmb ish
180; CHECK: adrp [[TMPADDR:x[0-9]+]], var8
181; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], #:lo12:var8
182
183; CHECK: .LBB{{[0-9]+}}_1:
184; CHECK-NEXT: ldxrb w[[OLD:[0-9]+]], [x[[ADDR]]]
185 ; w0 below is a reasonable guess but could change: it certainly comes into the
186 ; function there.
187; CHECK-NEXT: and [[NEW:w[0-9]+]], w[[OLD]], w0
188; CHECK-NEXT: stxrb [[STATUS:w[0-9]+]], [[NEW]], [x[[ADDR]]]
189; CHECK-NEXT: cmp [[STATUS]], #0
190; CHECK-NEXT: b.ne .LBB{{[0-9]+}}_1
191; CHECK: dmb ish
192
193; CHECK: mov x0, x[[OLD]]
194 ret i8 %old
195}
196
197define i16 @test_atomic_load_and_i16(i16 %offset) nounwind {
198; CHECK: test_atomic_load_and_i16:
199 %old = atomicrmw and i16* @var16, i16 %offset seq_cst
200; CHECK: dmb ish
201; CHECK: adrp [[TMPADDR:x[0-9]+]], var16
202; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], #:lo12:var16
203
204; CHECK: .LBB{{[0-9]+}}_1:
205; CHECK-NEXT: ldxrh w[[OLD:[0-9]+]], [x[[ADDR]]]
206 ; w0 below is a reasonable guess but could change: it certainly comes into the
207 ; function there.
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: cmp [[STATUS]], #0
211; CHECK-NEXT: b.ne .LBB{{[0-9]+}}_1
212; CHECK: dmb ish
213
214; CHECK: mov x0, x[[OLD]]
215 ret i16 %old
216}
217
218define i32 @test_atomic_load_and_i32(i32 %offset) nounwind {
219; CHECK: test_atomic_load_and_i32:
220 %old = atomicrmw and i32* @var32, i32 %offset seq_cst
221; CHECK: dmb ish
222; CHECK: adrp [[TMPADDR:x[0-9]+]], var32
223; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], #:lo12:var32
224
225; CHECK: .LBB{{[0-9]+}}_1:
226; CHECK-NEXT: ldxr w[[OLD:[0-9]+]], [x[[ADDR]]]
227 ; w0 below is a reasonable guess but could change: it certainly comes into the
228 ; function there.
229; CHECK-NEXT: and [[NEW:w[0-9]+]], w[[OLD]], w0
230; CHECK-NEXT: stxr [[STATUS:w[0-9]+]], [[NEW]], [x[[ADDR]]]
231; CHECK-NEXT: cmp [[STATUS]], #0
232; CHECK-NEXT: b.ne .LBB{{[0-9]+}}_1
233; CHECK: dmb ish
234
235; CHECK: mov x0, x[[OLD]]
236 ret i32 %old
237}
238
239define i64 @test_atomic_load_and_i64(i64 %offset) nounwind {
240; CHECK: test_atomic_load_and_i64:
241 %old = atomicrmw and i64* @var64, i64 %offset seq_cst
242; CHECK: dmb ish
243; CHECK: adrp [[TMPADDR:x[0-9]+]], var64
244; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], #:lo12:var64
245
246; CHECK: .LBB{{[0-9]+}}_1:
247; CHECK-NEXT: ldxr x[[OLD:[0-9]+]], [x[[ADDR]]]
248 ; x0 below is a reasonable guess but could change: it certainly comes into the
249 ; function there.
250; CHECK-NEXT: and [[NEW:x[0-9]+]], x[[OLD]], x0
251; CHECK-NEXT: stxr [[STATUS:w[0-9]+]], [[NEW]], [x[[ADDR]]]
252; CHECK-NEXT: cmp [[STATUS]], #0
253; CHECK-NEXT: b.ne .LBB{{[0-9]+}}_1
254; CHECK: dmb ish
255
256; CHECK: mov x0, x[[OLD]]
257 ret i64 %old
258}
259
260define i8 @test_atomic_load_or_i8(i8 %offset) nounwind {
261; CHECK: test_atomic_load_or_i8:
262 %old = atomicrmw or i8* @var8, i8 %offset seq_cst
263; CHECK: dmb ish
264; CHECK: adrp [[TMPADDR:x[0-9]+]], var8
265; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], #:lo12:var8
266
267; CHECK: .LBB{{[0-9]+}}_1:
268; CHECK-NEXT: ldxrb w[[OLD:[0-9]+]], [x[[ADDR]]]
269 ; w0 below is a reasonable guess but could change: it certainly comes into the
270 ; function there.
271; CHECK-NEXT: orr [[NEW:w[0-9]+]], w[[OLD]], w0
272; CHECK-NEXT: stxrb [[STATUS:w[0-9]+]], [[NEW]], [x[[ADDR]]]
273; CHECK-NEXT: cmp [[STATUS]], #0
274; CHECK-NEXT: b.ne .LBB{{[0-9]+}}_1
275; CHECK: dmb ish
276
277; CHECK: mov x0, x[[OLD]]
278 ret i8 %old
279}
280
281define i16 @test_atomic_load_or_i16(i16 %offset) nounwind {
282; CHECK: test_atomic_load_or_i16:
283 %old = atomicrmw or i16* @var16, i16 %offset seq_cst
284; CHECK: dmb ish
285; CHECK: adrp [[TMPADDR:x[0-9]+]], var16
286; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], #:lo12:var16
287
288; CHECK: .LBB{{[0-9]+}}_1:
289; CHECK-NEXT: ldxrh w[[OLD:[0-9]+]], [x[[ADDR]]]
290 ; w0 below is a reasonable guess but could change: it certainly comes into the
291 ; function there.
292; CHECK-NEXT: orr [[NEW:w[0-9]+]], w[[OLD]], w0
293; CHECK-NEXT: stxrh [[STATUS:w[0-9]+]], [[NEW]], [x[[ADDR]]]
294; CHECK-NEXT: cmp [[STATUS]], #0
295; CHECK-NEXT: b.ne .LBB{{[0-9]+}}_1
296; CHECK: dmb ish
297
298; CHECK: mov x0, x[[OLD]]
299 ret i16 %old
300}
301
302define i32 @test_atomic_load_or_i32(i32 %offset) nounwind {
303; CHECK: test_atomic_load_or_i32:
304 %old = atomicrmw or i32* @var32, i32 %offset seq_cst
305; CHECK: dmb ish
306; CHECK: adrp [[TMPADDR:x[0-9]+]], var32
307; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], #:lo12:var32
308
309; CHECK: .LBB{{[0-9]+}}_1:
310; CHECK-NEXT: ldxr w[[OLD:[0-9]+]], [x[[ADDR]]]
311 ; w0 below is a reasonable guess but could change: it certainly comes into the
312 ; function there.
313; CHECK-NEXT: orr [[NEW:w[0-9]+]], w[[OLD]], w0
314; CHECK-NEXT: stxr [[STATUS:w[0-9]+]], [[NEW]], [x[[ADDR]]]
315; CHECK-NEXT: cmp [[STATUS]], #0
316; CHECK-NEXT: b.ne .LBB{{[0-9]+}}_1
317; CHECK: dmb ish
318
319; CHECK: mov x0, x[[OLD]]
320 ret i32 %old
321}
322
323define i64 @test_atomic_load_or_i64(i64 %offset) nounwind {
324; CHECK: test_atomic_load_or_i64:
325 %old = atomicrmw or i64* @var64, i64 %offset seq_cst
326; CHECK: dmb ish
327; CHECK: adrp [[TMPADDR:x[0-9]+]], var64
328; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], #:lo12:var64
329
330; CHECK: .LBB{{[0-9]+}}_1:
331; CHECK-NEXT: ldxr x[[OLD:[0-9]+]], [x[[ADDR]]]
332 ; x0 below is a reasonable guess but could change: it certainly comes into the
333 ; function there.
334; CHECK-NEXT: orr [[NEW:x[0-9]+]], x[[OLD]], x0
335; CHECK-NEXT: stxr [[STATUS:w[0-9]+]], [[NEW]], [x[[ADDR]]]
336; CHECK-NEXT: cmp [[STATUS]], #0
337; CHECK-NEXT: b.ne .LBB{{[0-9]+}}_1
338; CHECK: dmb ish
339
340; CHECK: mov x0, x[[OLD]]
341 ret i64 %old
342}
343
344define i8 @test_atomic_load_xor_i8(i8 %offset) nounwind {
345; CHECK: test_atomic_load_xor_i8:
346 %old = atomicrmw xor i8* @var8, i8 %offset seq_cst
347; CHECK: dmb ish
348; CHECK: adrp [[TMPADDR:x[0-9]+]], var8
349; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], #:lo12:var8
350
351; CHECK: .LBB{{[0-9]+}}_1:
352; CHECK-NEXT: ldxrb w[[OLD:[0-9]+]], [x[[ADDR]]]
353 ; w0 below is a reasonable guess but could change: it certainly comes into the
354 ; function there.
355; CHECK-NEXT: eor [[NEW:w[0-9]+]], w[[OLD]], w0
356; CHECK-NEXT: stxrb [[STATUS:w[0-9]+]], [[NEW]], [x[[ADDR]]]
357; CHECK-NEXT: cmp [[STATUS]], #0
358; CHECK-NEXT: b.ne .LBB{{[0-9]+}}_1
359; CHECK: dmb ish
360
361; CHECK: mov x0, x[[OLD]]
362 ret i8 %old
363}
364
365define i16 @test_atomic_load_xor_i16(i16 %offset) nounwind {
366; CHECK: test_atomic_load_xor_i16:
367 %old = atomicrmw xor i16* @var16, i16 %offset seq_cst
368; CHECK: dmb ish
369; CHECK: adrp [[TMPADDR:x[0-9]+]], var16
370; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], #:lo12:var16
371
372; CHECK: .LBB{{[0-9]+}}_1:
373; CHECK-NEXT: ldxrh w[[OLD:[0-9]+]], [x[[ADDR]]]
374 ; w0 below is a reasonable guess but could change: it certainly comes into the
375 ; function there.
376; CHECK-NEXT: eor [[NEW:w[0-9]+]], w[[OLD]], w0
377; CHECK-NEXT: stxrh [[STATUS:w[0-9]+]], [[NEW]], [x[[ADDR]]]
378; CHECK-NEXT: cmp [[STATUS]], #0
379; CHECK-NEXT: b.ne .LBB{{[0-9]+}}_1
380; CHECK: dmb ish
381
382; CHECK: mov x0, x[[OLD]]
383 ret i16 %old
384}
385
386define i32 @test_atomic_load_xor_i32(i32 %offset) nounwind {
387; CHECK: test_atomic_load_xor_i32:
388 %old = atomicrmw xor i32* @var32, i32 %offset seq_cst
389; CHECK: dmb ish
390; CHECK: adrp [[TMPADDR:x[0-9]+]], var32
391; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], #:lo12:var32
392
393; CHECK: .LBB{{[0-9]+}}_1:
394; CHECK-NEXT: ldxr w[[OLD:[0-9]+]], [x[[ADDR]]]
395 ; w0 below is a reasonable guess but could change: it certainly comes into the
396 ; function there.
397; CHECK-NEXT: eor [[NEW:w[0-9]+]], w[[OLD]], w0
398; CHECK-NEXT: stxr [[STATUS:w[0-9]+]], [[NEW]], [x[[ADDR]]]
399; CHECK-NEXT: cmp [[STATUS]], #0
400; CHECK-NEXT: b.ne .LBB{{[0-9]+}}_1
401; CHECK: dmb ish
402
403; CHECK: mov x0, x[[OLD]]
404 ret i32 %old
405}
406
407define i64 @test_atomic_load_xor_i64(i64 %offset) nounwind {
408; CHECK: test_atomic_load_xor_i64:
409 %old = atomicrmw xor i64* @var64, i64 %offset seq_cst
410; CHECK: dmb ish
411; CHECK: adrp [[TMPADDR:x[0-9]+]], var64
412; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], #:lo12:var64
413
414; CHECK: .LBB{{[0-9]+}}_1:
415; CHECK-NEXT: ldxr x[[OLD:[0-9]+]], [x[[ADDR]]]
416 ; x0 below is a reasonable guess but could change: it certainly comes into the
417 ; function there.
418; CHECK-NEXT: eor [[NEW:x[0-9]+]], x[[OLD]], x0
419; CHECK-NEXT: stxr [[STATUS:w[0-9]+]], [[NEW]], [x[[ADDR]]]
420; CHECK-NEXT: cmp [[STATUS]], #0
421; CHECK-NEXT: b.ne .LBB{{[0-9]+}}_1
422; CHECK: dmb ish
423
424; CHECK: mov x0, x[[OLD]]
425 ret i64 %old
426}
427
428define i8 @test_atomic_load_xchg_i8(i8 %offset) nounwind {
429; CHECK: test_atomic_load_xchg_i8:
430 %old = atomicrmw xchg i8* @var8, i8 %offset seq_cst
431; CHECK: dmb ish
432; CHECK: adrp [[TMPADDR:x[0-9]+]], var8
433; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], #:lo12:var8
434
435; CHECK: .LBB{{[0-9]+}}_1:
436; CHECK-NEXT: ldxrb w[[OLD:[0-9]+]], [x[[ADDR]]]
437 ; w0 below is a reasonable guess but could change: it certainly comes into the
438 ; function there.
439; CHECK-NEXT: stxrb [[STATUS:w[0-9]+]], w0, [x[[ADDR]]]
440; CHECK-NEXT: cmp [[STATUS]], #0
441; CHECK-NEXT: b.ne .LBB{{[0-9]+}}_1
442; CHECK: dmb ish
443
444; CHECK: mov x0, x[[OLD]]
445 ret i8 %old
446}
447
448define i16 @test_atomic_load_xchg_i16(i16 %offset) nounwind {
449; CHECK: test_atomic_load_xchg_i16:
450 %old = atomicrmw xchg i16* @var16, i16 %offset seq_cst
451; CHECK: dmb ish
452; CHECK: adrp [[TMPADDR:x[0-9]+]], var16
453; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], #:lo12:var16
454
455; CHECK: .LBB{{[0-9]+}}_1:
456; CHECK-NEXT: ldxrh w[[OLD:[0-9]+]], [x[[ADDR]]]
457 ; w0 below is a reasonable guess but could change: it certainly comes into the
458 ; function there.
459; CHECK-NEXT: stxrh [[STATUS:w[0-9]+]], w0, [x[[ADDR]]]
460; CHECK-NEXT: cmp [[STATUS]], #0
461; CHECK-NEXT: b.ne .LBB{{[0-9]+}}_1
462; CHECK: dmb ish
463
464; CHECK: mov x0, x[[OLD]]
465 ret i16 %old
466}
467
468define i32 @test_atomic_load_xchg_i32(i32 %offset) nounwind {
469; CHECK: test_atomic_load_xchg_i32:
470 %old = atomicrmw xchg i32* @var32, i32 %offset seq_cst
471; CHECK: dmb ish
472; CHECK: adrp [[TMPADDR:x[0-9]+]], var32
473; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], #:lo12:var32
474
475; CHECK: .LBB{{[0-9]+}}_1:
476; CHECK-NEXT: ldxr w[[OLD:[0-9]+]], [x[[ADDR]]]
477 ; w0 below is a reasonable guess but could change: it certainly comes into the
478 ; function there.
479; CHECK-NEXT: stxr [[STATUS:w[0-9]+]], w0, [x[[ADDR]]]
480; CHECK-NEXT: cmp [[STATUS]], #0
481; CHECK-NEXT: b.ne .LBB{{[0-9]+}}_1
482; CHECK: dmb ish
483
484; CHECK: mov x0, x[[OLD]]
485 ret i32 %old
486}
487
488define i64 @test_atomic_load_xchg_i64(i64 %offset) nounwind {
489; CHECK: test_atomic_load_xchg_i64:
490 %old = atomicrmw xchg i64* @var64, i64 %offset seq_cst
491; CHECK: dmb ish
492; CHECK: adrp [[TMPADDR:x[0-9]+]], var64
493; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], #:lo12:var64
494
495; CHECK: .LBB{{[0-9]+}}_1:
496; CHECK-NEXT: ldxr x[[OLD:[0-9]+]], [x[[ADDR]]]
497 ; x0 below is a reasonable guess but could change: it certainly comes into the
498 ; function there.
499; CHECK-NEXT: stxr [[STATUS:w[0-9]+]], x0, [x[[ADDR]]]
500; CHECK-NEXT: cmp [[STATUS]], #0
501; CHECK-NEXT: b.ne .LBB{{[0-9]+}}_1
502; CHECK: dmb ish
503
504; CHECK: mov x0, x[[OLD]]
505 ret i64 %old
506}
507
508
509define i8 @test_atomic_load_min_i8(i8 %offset) nounwind {
510; CHECK: test_atomic_load_min_i8:
511 %old = atomicrmw min i8* @var8, i8 %offset seq_cst
512; CHECK: dmb ish
513; CHECK: adrp [[TMPADDR:x[0-9]+]], var8
514; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], #:lo12:var8
515
516; CHECK: .LBB{{[0-9]+}}_1:
517; CHECK-NEXT: ldxrb w[[OLD:[0-9]+]], [x[[ADDR]]]
518 ; w0 below is a reasonable guess but could change: it certainly comes into the
519 ; function there.
520; CHECK-NEXT: cmp w0, w[[OLD]], sxtb
521; CHECK-NEXT: csel [[NEW:w[0-9]+]], w[[OLD]], w0, gt
522; CHECK-NEXT: stxrb [[STATUS:w[0-9]+]], [[NEW]], [x[[ADDR]]]
523; CHECK-NEXT: cmp [[STATUS]], #0
524; CHECK-NEXT: b.ne .LBB{{[0-9]+}}_1
525; CHECK: dmb ish
526
527; CHECK: mov x0, x[[OLD]]
528 ret i8 %old
529}
530
531define i16 @test_atomic_load_min_i16(i16 %offset) nounwind {
532; CHECK: test_atomic_load_min_i16:
533 %old = atomicrmw min i16* @var16, i16 %offset seq_cst
534; CHECK: dmb ish
535; CHECK: adrp [[TMPADDR:x[0-9]+]], var16
536; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], #:lo12:var16
537
538; CHECK: .LBB{{[0-9]+}}_1:
539; CHECK-NEXT: ldxrh w[[OLD:[0-9]+]], [x[[ADDR]]]
540 ; w0 below is a reasonable guess but could change: it certainly comes into the
541 ; function there.
542; CHECK-NEXT: cmp w0, w[[OLD]], sxth
543; CHECK-NEXT: csel [[NEW:w[0-9]+]], w[[OLD]], w0, gt
544; CHECK-NEXT: stxrh [[STATUS:w[0-9]+]], [[NEW]], [x[[ADDR]]]
545; CHECK-NEXT: cmp [[STATUS]], #0
546; CHECK-NEXT: b.ne .LBB{{[0-9]+}}_1
547; CHECK: dmb ish
548
549; CHECK: mov x0, x[[OLD]]
550 ret i16 %old
551}
552
553define i32 @test_atomic_load_min_i32(i32 %offset) nounwind {
554; CHECK: test_atomic_load_min_i32:
555 %old = atomicrmw min i32* @var32, i32 %offset seq_cst
556; CHECK: dmb ish
557; CHECK: adrp [[TMPADDR:x[0-9]+]], var32
558; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], #:lo12:var32
559
560; CHECK: .LBB{{[0-9]+}}_1:
561; CHECK-NEXT: ldxr w[[OLD:[0-9]+]], [x[[ADDR]]]
562 ; w0 below is a reasonable guess but could change: it certainly comes into the
563 ; function there.
564; CHECK-NEXT: cmp w0, w[[OLD]]
565; CHECK-NEXT: csel [[NEW:w[0-9]+]], w[[OLD]], w0, gt
566; CHECK-NEXT: stxr [[STATUS:w[0-9]+]], [[NEW]], [x[[ADDR]]]
567; CHECK-NEXT: cmp [[STATUS]], #0
568; CHECK-NEXT: b.ne .LBB{{[0-9]+}}_1
569; CHECK: dmb ish
570
571; CHECK: mov x0, x[[OLD]]
572 ret i32 %old
573}
574
575define i64 @test_atomic_load_min_i64(i64 %offset) nounwind {
576; CHECK: test_atomic_load_min_i64:
577 %old = atomicrmw min i64* @var64, i64 %offset seq_cst
578; CHECK: dmb ish
579; CHECK: adrp [[TMPADDR:x[0-9]+]], var64
580; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], #:lo12:var64
581
582; CHECK: .LBB{{[0-9]+}}_1:
583; CHECK-NEXT: ldxr x[[OLD:[0-9]+]], [x[[ADDR]]]
584 ; x0 below is a reasonable guess but could change: it certainly comes into the
585 ; function there.
586; CHECK-NEXT: cmp x0, x[[OLD]]
587; CHECK-NEXT: csel [[NEW:x[0-9]+]], x[[OLD]], x0, gt
588; CHECK-NEXT: stxr [[STATUS:w[0-9]+]], [[NEW]], [x[[ADDR]]]
589; CHECK-NEXT: cmp [[STATUS]], #0
590; CHECK-NEXT: b.ne .LBB{{[0-9]+}}_1
591; CHECK: dmb ish
592
593; CHECK: mov x0, x[[OLD]]
594 ret i64 %old
595}
596
597define i8 @test_atomic_load_max_i8(i8 %offset) nounwind {
598; CHECK: test_atomic_load_max_i8:
599 %old = atomicrmw max i8* @var8, i8 %offset seq_cst
600; CHECK: dmb ish
601; CHECK: adrp [[TMPADDR:x[0-9]+]], var8
602; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], #:lo12:var8
603
604; CHECK: .LBB{{[0-9]+}}_1:
605; CHECK-NEXT: ldxrb w[[OLD:[0-9]+]], [x[[ADDR]]]
606 ; w0 below is a reasonable guess but could change: it certainly comes into the
607 ; function there.
608; CHECK-NEXT: cmp w0, w[[OLD]], sxtb
609; CHECK-NEXT: csel [[NEW:w[0-9]+]], w[[OLD]], w0, lt
610; CHECK-NEXT: stxrb [[STATUS:w[0-9]+]], [[NEW]], [x[[ADDR]]]
611; CHECK-NEXT: cmp [[STATUS]], #0
612; CHECK-NEXT: b.ne .LBB{{[0-9]+}}_1
613; CHECK: dmb ish
614
615; CHECK: mov x0, x[[OLD]]
616 ret i8 %old
617}
618
619define i16 @test_atomic_load_max_i16(i16 %offset) nounwind {
620; CHECK: test_atomic_load_max_i16:
621 %old = atomicrmw max i16* @var16, i16 %offset seq_cst
622; CHECK: dmb ish
623; CHECK: adrp [[TMPADDR:x[0-9]+]], var16
624; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], #:lo12:var16
625
626; CHECK: .LBB{{[0-9]+}}_1:
627; CHECK-NEXT: ldxrh w[[OLD:[0-9]+]], [x[[ADDR]]]
628 ; w0 below is a reasonable guess but could change: it certainly comes into the
629 ; function there.
630; CHECK-NEXT: cmp w0, w[[OLD]], sxth
631; CHECK-NEXT: csel [[NEW:w[0-9]+]], w[[OLD]], w0, lt
632; CHECK-NEXT: stxrh [[STATUS:w[0-9]+]], [[NEW]], [x[[ADDR]]]
633; CHECK-NEXT: cmp [[STATUS]], #0
634; CHECK-NEXT: b.ne .LBB{{[0-9]+}}_1
635; CHECK: dmb ish
636
637; CHECK: mov x0, x[[OLD]]
638 ret i16 %old
639}
640
641define i32 @test_atomic_load_max_i32(i32 %offset) nounwind {
642; CHECK: test_atomic_load_max_i32:
643 %old = atomicrmw max i32* @var32, i32 %offset seq_cst
644; CHECK: dmb ish
645; CHECK: adrp [[TMPADDR:x[0-9]+]], var32
646; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], #:lo12:var32
647
648; CHECK: .LBB{{[0-9]+}}_1:
649; CHECK-NEXT: ldxr w[[OLD:[0-9]+]], [x[[ADDR]]]
650 ; w0 below is a reasonable guess but could change: it certainly comes into the
651 ; function there.
652; CHECK-NEXT: cmp w0, w[[OLD]]
653; CHECK-NEXT: csel [[NEW:w[0-9]+]], w[[OLD]], w0, lt
654; CHECK-NEXT: stxr [[STATUS:w[0-9]+]], [[NEW]], [x[[ADDR]]]
655; CHECK-NEXT: cmp [[STATUS]], #0
656; CHECK-NEXT: b.ne .LBB{{[0-9]+}}_1
657; CHECK: dmb ish
658
659; CHECK: mov x0, x[[OLD]]
660 ret i32 %old
661}
662
663define i64 @test_atomic_load_max_i64(i64 %offset) nounwind {
664; CHECK: test_atomic_load_max_i64:
665 %old = atomicrmw max i64* @var64, i64 %offset seq_cst
666; CHECK: dmb ish
667; CHECK: adrp [[TMPADDR:x[0-9]+]], var64
668; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], #:lo12:var64
669
670; CHECK: .LBB{{[0-9]+}}_1:
671; CHECK-NEXT: ldxr x[[OLD:[0-9]+]], [x[[ADDR]]]
672 ; x0 below is a reasonable guess but could change: it certainly comes into the
673 ; function there.
674; CHECK-NEXT: cmp x0, x[[OLD]]
675; CHECK-NEXT: csel [[NEW:x[0-9]+]], x[[OLD]], x0, lt
676; CHECK-NEXT: stxr [[STATUS:w[0-9]+]], [[NEW]], [x[[ADDR]]]
677; CHECK-NEXT: cmp [[STATUS]], #0
678; CHECK-NEXT: b.ne .LBB{{[0-9]+}}_1
679; CHECK: dmb ish
680
681; CHECK: mov x0, x[[OLD]]
682 ret i64 %old
683}
684
685define i8 @test_atomic_load_umin_i8(i8 %offset) nounwind {
686; CHECK: test_atomic_load_umin_i8:
687 %old = atomicrmw umin i8* @var8, i8 %offset seq_cst
688; CHECK: dmb ish
689; CHECK: adrp [[TMPADDR:x[0-9]+]], var8
690; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], #:lo12:var8
691
692; CHECK: .LBB{{[0-9]+}}_1:
693; CHECK-NEXT: ldxrb w[[OLD:[0-9]+]], [x[[ADDR]]]
694 ; w0 below is a reasonable guess but could change: it certainly comes into the
695 ; function there.
696; CHECK-NEXT: cmp w0, w[[OLD]], uxtb
697; CHECK-NEXT: csel [[NEW:w[0-9]+]], w[[OLD]], w0, hi
698; CHECK-NEXT: stxrb [[STATUS:w[0-9]+]], [[NEW]], [x[[ADDR]]]
699; CHECK-NEXT: cmp [[STATUS]], #0
700; CHECK-NEXT: b.ne .LBB{{[0-9]+}}_1
701; CHECK: dmb ish
702
703; CHECK: mov x0, x[[OLD]]
704 ret i8 %old
705}
706
707define i16 @test_atomic_load_umin_i16(i16 %offset) nounwind {
708; CHECK: test_atomic_load_umin_i16:
709 %old = atomicrmw umin i16* @var16, i16 %offset seq_cst
710; CHECK: dmb ish
711; CHECK: adrp [[TMPADDR:x[0-9]+]], var16
712; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], #:lo12:var16
713
714; CHECK: .LBB{{[0-9]+}}_1:
715; CHECK-NEXT: ldxrh w[[OLD:[0-9]+]], [x[[ADDR]]]
716 ; w0 below is a reasonable guess but could change: it certainly comes into the
717 ; function there.
718; CHECK-NEXT: cmp w0, w[[OLD]], uxth
719; CHECK-NEXT: csel [[NEW:w[0-9]+]], w[[OLD]], w0, hi
720; CHECK-NEXT: stxrh [[STATUS:w[0-9]+]], [[NEW]], [x[[ADDR]]]
721; CHECK-NEXT: cmp [[STATUS]], #0
722; CHECK-NEXT: b.ne .LBB{{[0-9]+}}_1
723; CHECK: dmb ish
724
725; CHECK: mov x0, x[[OLD]]
726 ret i16 %old
727}
728
729define i32 @test_atomic_load_umin_i32(i32 %offset) nounwind {
730; CHECK: test_atomic_load_umin_i32:
731 %old = atomicrmw umin i32* @var32, i32 %offset seq_cst
732; CHECK: dmb ish
733; CHECK: adrp [[TMPADDR:x[0-9]+]], var32
734; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], #:lo12:var32
735
736; CHECK: .LBB{{[0-9]+}}_1:
737; CHECK-NEXT: ldxr w[[OLD:[0-9]+]], [x[[ADDR]]]
738 ; w0 below is a reasonable guess but could change: it certainly comes into the
739 ; function there.
740; CHECK-NEXT: cmp w0, w[[OLD]]
741; CHECK-NEXT: csel [[NEW:w[0-9]+]], w[[OLD]], w0, hi
742; CHECK-NEXT: stxr [[STATUS:w[0-9]+]], [[NEW]], [x[[ADDR]]]
743; CHECK-NEXT: cmp [[STATUS]], #0
744; CHECK-NEXT: b.ne .LBB{{[0-9]+}}_1
745; CHECK: dmb ish
746
747; CHECK: mov x0, x[[OLD]]
748 ret i32 %old
749}
750
751define i64 @test_atomic_load_umin_i64(i64 %offset) nounwind {
752; CHECK: test_atomic_load_umin_i64:
753 %old = atomicrmw umin i64* @var64, i64 %offset seq_cst
754; CHECK: dmb ish
755; CHECK: adrp [[TMPADDR:x[0-9]+]], var64
756; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], #:lo12:var64
757
758; CHECK: .LBB{{[0-9]+}}_1:
759; CHECK-NEXT: ldxr x[[OLD:[0-9]+]], [x[[ADDR]]]
760 ; x0 below is a reasonable guess but could change: it certainly comes into the
761 ; function there.
762; CHECK-NEXT: cmp x0, x[[OLD]]
763; CHECK-NEXT: csel [[NEW:x[0-9]+]], x[[OLD]], x0, hi
764; CHECK-NEXT: stxr [[STATUS:w[0-9]+]], [[NEW]], [x[[ADDR]]]
765; CHECK-NEXT: cmp [[STATUS]], #0
766; CHECK-NEXT: b.ne .LBB{{[0-9]+}}_1
767; CHECK: dmb ish
768
769; CHECK: mov x0, x[[OLD]]
770 ret i64 %old
771}
772
773define i8 @test_atomic_load_umax_i8(i8 %offset) nounwind {
774; CHECK: test_atomic_load_umax_i8:
775 %old = atomicrmw umax i8* @var8, i8 %offset seq_cst
776; CHECK: dmb ish
777; CHECK: adrp [[TMPADDR:x[0-9]+]], var8
778; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], #:lo12:var8
779
780; CHECK: .LBB{{[0-9]+}}_1:
781; CHECK-NEXT: ldxrb w[[OLD:[0-9]+]], [x[[ADDR]]]
782 ; w0 below is a reasonable guess but could change: it certainly comes into the
783 ; function there.
784; CHECK-NEXT: cmp w0, w[[OLD]], uxtb
785; CHECK-NEXT: csel [[NEW:w[0-9]+]], w[[OLD]], w0, lo
786; CHECK-NEXT: stxrb [[STATUS:w[0-9]+]], [[NEW]], [x[[ADDR]]]
787; CHECK-NEXT: cmp [[STATUS]], #0
788; CHECK-NEXT: b.ne .LBB{{[0-9]+}}_1
789; CHECK: dmb ish
790
791; CHECK: mov x0, x[[OLD]]
792 ret i8 %old
793}
794
795define i16 @test_atomic_load_umax_i16(i16 %offset) nounwind {
796; CHECK: test_atomic_load_umax_i16:
797 %old = atomicrmw umax i16* @var16, i16 %offset seq_cst
798; CHECK: dmb ish
799; CHECK: adrp [[TMPADDR:x[0-9]+]], var16
800; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], #:lo12:var16
801
802; CHECK: .LBB{{[0-9]+}}_1:
803; CHECK-NEXT: ldxrh w[[OLD:[0-9]+]], [x[[ADDR]]]
804 ; w0 below is a reasonable guess but could change: it certainly comes into the
805 ; function there.
806; CHECK-NEXT: cmp w0, w[[OLD]], uxth
807; CHECK-NEXT: csel [[NEW:w[0-9]+]], w[[OLD]], w0, lo
808; CHECK-NEXT: stxrh [[STATUS:w[0-9]+]], [[NEW]], [x[[ADDR]]]
809; CHECK-NEXT: cmp [[STATUS]], #0
810; CHECK-NEXT: b.ne .LBB{{[0-9]+}}_1
811; CHECK: dmb ish
812
813; CHECK: mov x0, x[[OLD]]
814 ret i16 %old
815}
816
817define i32 @test_atomic_load_umax_i32(i32 %offset) nounwind {
818; CHECK: test_atomic_load_umax_i32:
819 %old = atomicrmw umax i32* @var32, i32 %offset seq_cst
820; CHECK: dmb ish
821; CHECK: adrp [[TMPADDR:x[0-9]+]], var32
822; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], #:lo12:var32
823
824; CHECK: .LBB{{[0-9]+}}_1:
825; CHECK-NEXT: ldxr w[[OLD:[0-9]+]], [x[[ADDR]]]
826 ; w0 below is a reasonable guess but could change: it certainly comes into the
827 ; function there.
828; CHECK-NEXT: cmp w0, w[[OLD]]
829; CHECK-NEXT: csel [[NEW:w[0-9]+]], w[[OLD]], w0, lo
830; CHECK-NEXT: stxr [[STATUS:w[0-9]+]], [[NEW]], [x[[ADDR]]]
831; CHECK-NEXT: cmp [[STATUS]], #0
832; CHECK-NEXT: b.ne .LBB{{[0-9]+}}_1
833; CHECK: dmb ish
834
835; CHECK: mov x0, x[[OLD]]
836 ret i32 %old
837}
838
839define i64 @test_atomic_load_umax_i64(i64 %offset) nounwind {
840; CHECK: test_atomic_load_umax_i64:
841 %old = atomicrmw umax i64* @var64, i64 %offset seq_cst
842; CHECK: dmb ish
843; CHECK: adrp [[TMPADDR:x[0-9]+]], var64
844; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], #:lo12:var64
845
846; CHECK: .LBB{{[0-9]+}}_1:
847; CHECK-NEXT: ldxr x[[OLD:[0-9]+]], [x[[ADDR]]]
848 ; x0 below is a reasonable guess but could change: it certainly comes into the
849 ; function there.
850; CHECK-NEXT: cmp x0, x[[OLD]]
851; CHECK-NEXT: csel [[NEW:x[0-9]+]], x[[OLD]], x0, lo
852; CHECK-NEXT: stxr [[STATUS:w[0-9]+]], [[NEW]], [x[[ADDR]]]
853; CHECK-NEXT: cmp [[STATUS]], #0
854; CHECK-NEXT: b.ne .LBB{{[0-9]+}}_1
855; CHECK: dmb ish
856
857; CHECK: mov x0, x[[OLD]]
858 ret i64 %old
859}
860
861define i8 @test_atomic_cmpxchg_i8(i8 %wanted, i8 %new) nounwind {
862; CHECK: test_atomic_cmpxchg_i8:
863 %old = cmpxchg i8* @var8, i8 %wanted, i8 %new seq_cst
864; CHECK: dmb ish
865; CHECK: adrp [[TMPADDR:x[0-9]+]], var8
866; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], #:lo12:var8
867
868; CHECK: [[STARTAGAIN:.LBB[0-9]+_[0-9]+]]:
869; CHECK-NEXT: ldxrb w[[OLD:[0-9]+]], [x[[ADDR]]]
870 ; w0 below is a reasonable guess but could change: it certainly comes into the
871 ; function there.
872; CHECK-NEXT: cmp w[[OLD]], w0
873; CHECK-NEXT: b.ne [[GET_OUT:.LBB[0-9]+_[0-9]+]]
874 ; As above, w1 is a reasonable guess.
875; CHECK: stxrb [[STATUS:w[0-9]+]], w1, [x[[ADDR]]]
876; CHECK-NEXT: cmp [[STATUS]], #0
877; CHECK-NEXT: b.ne [[STARTAGAIN]]
878; CHECK: dmb ish
879
880; CHECK: mov x0, x[[OLD]]
881 ret i8 %old
882}
883
884define i16 @test_atomic_cmpxchg_i16(i16 %wanted, i16 %new) nounwind {
885; CHECK: test_atomic_cmpxchg_i16:
886 %old = cmpxchg i16* @var16, i16 %wanted, i16 %new seq_cst
887; CHECK: dmb ish
888; CHECK: adrp [[TMPADDR:x[0-9]+]], var16
889; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], #:lo12:var16
890
891; CHECK: [[STARTAGAIN:.LBB[0-9]+_[0-9]+]]:
892; CHECK-NEXT: ldxrh w[[OLD:[0-9]+]], [x[[ADDR]]]
893 ; w0 below is a reasonable guess but could change: it certainly comes into the
894 ; function there.
895; CHECK-NEXT: cmp w[[OLD]], w0
896; CHECK-NEXT: b.ne [[GET_OUT:.LBB[0-9]+_[0-9]+]]
897 ; As above, w1 is a reasonable guess.
898; CHECK: stxrh [[STATUS:w[0-9]+]], w1, [x[[ADDR]]]
899; CHECK-NEXT: cmp [[STATUS]], #0
900; CHECK-NEXT: b.ne [[STARTAGAIN]]
901; CHECK: dmb ish
902
903; CHECK: mov x0, x[[OLD]]
904 ret i16 %old
905}
906
907define i32 @test_atomic_cmpxchg_i32(i32 %wanted, i32 %new) nounwind {
908; CHECK: test_atomic_cmpxchg_i32:
909 %old = cmpxchg i32* @var32, i32 %wanted, i32 %new seq_cst
910; CHECK: dmb ish
911; CHECK: adrp [[TMPADDR:x[0-9]+]], var32
912; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], #:lo12:var32
913
914; CHECK: [[STARTAGAIN:.LBB[0-9]+_[0-9]+]]:
915; CHECK-NEXT: ldxr w[[OLD:[0-9]+]], [x[[ADDR]]]
916 ; w0 below is a reasonable guess but could change: it certainly comes into the
917 ; function there.
918; CHECK-NEXT: cmp w[[OLD]], w0
919; CHECK-NEXT: b.ne [[GET_OUT:.LBB[0-9]+_[0-9]+]]
920 ; As above, w1 is a reasonable guess.
921; CHECK: stxr [[STATUS:w[0-9]+]], w1, [x[[ADDR]]]
922; CHECK-NEXT: cmp [[STATUS]], #0
923; CHECK-NEXT: b.ne [[STARTAGAIN]]
924; CHECK: dmb ish
925
926; CHECK: mov x0, x[[OLD]]
927 ret i32 %old
928}
929
930define i64 @test_atomic_cmpxchg_i64(i64 %wanted, i64 %new) nounwind {
931; CHECK: test_atomic_cmpxchg_i64:
932 %old = cmpxchg i64* @var64, i64 %wanted, i64 %new seq_cst
933; CHECK: dmb ish
934; CHECK: adrp [[TMPADDR:x[0-9]+]], var64
935; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], #:lo12:var64
936
937; CHECK: [[STARTAGAIN:.LBB[0-9]+_[0-9]+]]:
938; CHECK-NEXT: ldxr x[[OLD:[0-9]+]], [x[[ADDR]]]
939 ; w0 below is a reasonable guess but could change: it certainly comes into the
940 ; function there.
941; CHECK-NEXT: cmp x[[OLD]], x0
942; CHECK-NEXT: b.ne [[GET_OUT:.LBB[0-9]+_[0-9]+]]
943 ; As above, w1 is a reasonable guess.
944; CHECK: stxr [[STATUS:w[0-9]+]], x1, [x[[ADDR]]]
945; CHECK-NEXT: cmp [[STATUS]], #0
946; CHECK-NEXT: b.ne [[STARTAGAIN]]
947; CHECK: dmb ish
948
949; CHECK: mov x0, x[[OLD]]
950 ret i64 %old
951}
952
953define i8 @test_atomic_load_monotonic_i8() nounwind {
954; CHECK: test_atomic_load_monotonic_i8:
955 %val = load atomic i8* @var8 monotonic, align 1
956; CHECK-NOT: dmb
957; CHECK: adrp x[[HIADDR:[0-9]+]], var8
958; CHECK: ldrb w0, [x[[HIADDR]], #:lo12:var8]
959; CHECK-NOT: dmb
960
961 ret i8 %val
962}
963
964define i8 @test_atomic_load_monotonic_regoff_i8(i64 %base, i64 %off) nounwind {
965; CHECK: test_atomic_load_monotonic_regoff_i8:
966 %addr_int = add i64 %base, %off
967 %addr = inttoptr i64 %addr_int to i8*
968
969 %val = load atomic i8* %addr monotonic, align 1
970; CHECK-NOT: dmb
971; CHECK: ldrb w0, [x0, x1]
972; CHECK-NOT: dmb
973
974 ret i8 %val
975}
976
977define i8 @test_atomic_load_acquire_i8() nounwind {
978; CHECK: test_atomic_load_acquire_i8:
979 %val = load atomic i8* @var8 acquire, align 1
980; CHECK: adrp [[TMPADDR:x[0-9]+]], var8
981; CHECK: add x[[ADDR:[0-9]+]], [[TMPADDR]], #:lo12:var8
982
983; CHECK: ldarb w0, [x[[ADDR]]]
984 ret i8 %val
985}
986
987define i8 @test_atomic_load_seq_cst_i8() nounwind {
988; CHECK: test_atomic_load_seq_cst_i8:
989 %val = load atomic i8* @var8 seq_cst, align 1
990; CHECK: adrp x[[HIADDR:[0-9]+]], var8
991; CHECK: ldrb w0, [x[[HIADDR]], #:lo12:var8]
992; CHECK: dmb ish
993 ret i8 %val
994}
995
996define i16 @test_atomic_load_monotonic_i16() nounwind {
997; CHECK: test_atomic_load_monotonic_i16:
998 %val = load atomic i16* @var16 monotonic, align 2
999; CHECK-NOT: dmb
1000; CHECK: adrp x[[HIADDR:[0-9]+]], var16
1001; CHECK: ldrh w0, [x[[HIADDR]], #:lo12:var16]
1002; CHECK-NOT: dmb
1003
1004 ret i16 %val
1005}
1006
1007define i32 @test_atomic_load_monotonic_regoff_i32(i64 %base, i64 %off) nounwind {
1008; CHECK: test_atomic_load_monotonic_regoff_i32:
1009 %addr_int = add i64 %base, %off
1010 %addr = inttoptr i64 %addr_int to i32*
1011
1012 %val = load atomic i32* %addr monotonic, align 4
1013; CHECK-NOT: dmb
1014; CHECK: ldr w0, [x0, x1]
1015; CHECK-NOT: dmb
1016
1017 ret i32 %val
1018}
1019
1020define i64 @test_atomic_load_seq_cst_i64() nounwind {
1021; CHECK: test_atomic_load_seq_cst_i64:
1022 %val = load atomic i64* @var64 seq_cst, align 8
1023; CHECK: adrp x[[HIADDR:[0-9]+]], var64
1024; CHECK: ldr x0, [x[[HIADDR]], #:lo12:var64]
1025; CHECK: dmb ish
1026 ret i64 %val
1027}
1028
1029define void @test_atomic_store_monotonic_i8(i8 %val) nounwind {
1030; CHECK: test_atomic_store_monotonic_i8:
1031 store atomic i8 %val, i8* @var8 monotonic, align 1
1032; CHECK: adrp x[[HIADDR:[0-9]+]], var8
1033; CHECK: strb w0, [x[[HIADDR]], #:lo12:var8]
1034
1035 ret void
1036}
1037
1038define void @test_atomic_store_monotonic_regoff_i8(i64 %base, i64 %off, i8 %val) nounwind {
1039; CHECK: test_atomic_store_monotonic_regoff_i8:
1040
1041 %addr_int = add i64 %base, %off
1042 %addr = inttoptr i64 %addr_int to i8*
1043
1044 store atomic i8 %val, i8* %addr monotonic, align 1
1045; CHECK: strb w2, [x0, x1]
1046
1047 ret void
1048}
1049define void @test_atomic_store_release_i8(i8 %val) nounwind {
1050; CHECK: test_atomic_store_release_i8:
1051 store atomic i8 %val, i8* @var8 release, align 1
1052; CHECK: adrp [[HIADDR:x[0-9]+]], var8
1053; CHECK: add x[[ADDR:[0-9]+]], [[HIADDR]], #:lo12:var8
1054; CHECK: stlrb w0, [x[[ADDR]]]
1055
1056 ret void
1057}
1058
1059define void @test_atomic_store_seq_cst_i8(i8 %val) nounwind {
1060; CHECK: test_atomic_store_seq_cst_i8:
1061 store atomic i8 %val, i8* @var8 seq_cst, align 1
1062; CHECK: adrp [[HIADDR:x[0-9]+]], var8
1063; CHECK: add x[[ADDR:[0-9]+]], [[HIADDR]], #:lo12:var8
1064; CHECK: stlrb w0, [x[[ADDR]]]
1065; CHECK: dmb ish
1066
1067 ret void
1068}
1069
1070define void @test_atomic_store_monotonic_i16(i16 %val) nounwind {
1071; CHECK: test_atomic_store_monotonic_i16:
1072 store atomic i16 %val, i16* @var16 monotonic, align 2
1073; CHECK: adrp x[[HIADDR:[0-9]+]], var16
1074; CHECK: strh w0, [x[[HIADDR]], #:lo12:var16]
1075
1076 ret void
1077}
1078
1079define void @test_atomic_store_monotonic_regoff_i32(i64 %base, i64 %off, i32 %val) nounwind {
1080; CHECK: test_atomic_store_monotonic_regoff_i32:
1081
1082 %addr_int = add i64 %base, %off
1083 %addr = inttoptr i64 %addr_int to i32*
1084
1085 store atomic i32 %val, i32* %addr monotonic, align 4
1086; CHECK: str w2, [x0, x1]
1087
1088 ret void
1089}
1090
1091define void @test_atomic_store_release_i64(i64 %val) nounwind {
1092; CHECK: test_atomic_store_release_i64:
1093 store atomic i64 %val, i64* @var64 release, align 8
1094; CHECK: adrp [[HIADDR:x[0-9]+]], var64
1095; CHECK: add x[[ADDR:[0-9]+]], [[HIADDR]], #:lo12:var64
1096; CHECK: stlr x0, [x[[ADDR]]]
1097
1098 ret void
1099}