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