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