AVX-512: fixed a bug in getLoadStoreRegOpcode() for AVX-512 target
[oota-llvm.git] / test / CodeGen / ARM / atomic-ops-v8.ll
1 ; RUN: llc -mtriple=armv8-none-linux-gnu -verify-machineinstrs < %s | FileCheck %s
2 ; RUN: llc -mtriple=thumbv8-none-linux-gnu -verify-machineinstrs < %s | FileCheck %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-NOT: mcr
14 ; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var8
15 ; CHECK: movt r[[ADDR]], :upper16:var8
16
17 ; CHECK: .LBB{{[0-9]+}}_1:
18 ; CHECK-NEXT: ldaexb r[[OLD:[0-9]+]], [r[[ADDR]]]
19   ; r0 below is a reasonable guess but could change: it certainly comes into the
20   ;  function there.
21 ; CHECK-NEXT: add{{s?}} [[NEW:r[0-9]+]], r[[OLD]], r0
22 ; CHECK-NEXT: stlexb [[STATUS:r[0-9]+]], [[NEW]], [r[[ADDR]]]
23 ; CHECK-NEXT: cmp [[STATUS]], #0
24 ; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
25 ; CHECK-NOT: dmb
26 ; CHECK-NOT: mcr
27
28 ; CHECK: mov r0, r[[OLD]]
29    ret i8 %old
30 }
31
32 define i16 @test_atomic_load_add_i16(i16 %offset) nounwind {
33 ; CHECK-LABEL: test_atomic_load_add_i16:
34    %old = atomicrmw add i16* @var16, i16 %offset acquire
35 ; CHECK-NOT: dmb
36 ; CHECK-NOT: mcr
37 ; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var16
38 ; CHECK: movt r[[ADDR]], :upper16:var16
39
40 ; CHECK: .LBB{{[0-9]+}}_1:
41 ; CHECK-NEXT: ldaexh r[[OLD:[0-9]+]], [r[[ADDR]]]
42   ; r0 below is a reasonable guess but could change: it certainly comes into the
43   ;  function there.
44 ; CHECK-NEXT: add{{s?}} [[NEW:r[0-9]+]], r[[OLD]], r0
45 ; CHECK-NEXT: strexh [[STATUS:r[0-9]+]], [[NEW]], [r[[ADDR]]]
46 ; CHECK-NEXT: cmp [[STATUS]], #0
47 ; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
48 ; CHECK-NOT: dmb
49 ; CHECK-NOT: mcr
50
51 ; CHECK: mov r0, r[[OLD]]
52    ret i16 %old
53 }
54
55 define i32 @test_atomic_load_add_i32(i32 %offset) nounwind {
56 ; CHECK-LABEL: test_atomic_load_add_i32:
57    %old = atomicrmw add i32* @var32, i32 %offset release
58 ; CHECK-NOT: dmb
59 ; CHECK-NOT: mcr
60 ; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var32
61 ; CHECK: movt r[[ADDR]], :upper16:var32
62
63 ; CHECK: .LBB{{[0-9]+}}_1:
64 ; CHECK-NEXT: ldrex r[[OLD:[0-9]+]], [r[[ADDR]]]
65   ; r0 below is a reasonable guess but could change: it certainly comes into the
66   ;  function there.
67 ; CHECK-NEXT: add{{s?}} [[NEW:r[0-9]+]], r[[OLD]], r0
68 ; CHECK-NEXT: stlex [[STATUS:r[0-9]+]], [[NEW]], [r[[ADDR]]]
69 ; CHECK-NEXT: cmp [[STATUS]], #0
70 ; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
71 ; CHECK-NOT: dmb
72 ; CHECK-NOT: mcr
73
74 ; CHECK: mov r0, r[[OLD]]
75    ret i32 %old
76 }
77
78 define i64 @test_atomic_load_add_i64(i64 %offset) nounwind {
79 ; CHECK-LABEL: test_atomic_load_add_i64:
80    %old = atomicrmw add i64* @var64, i64 %offset monotonic
81 ; CHECK-NOT: dmb
82 ; CHECK-NOT: mcr
83 ; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var64
84 ; CHECK: movt r[[ADDR]], :upper16:var64
85
86 ; CHECK: .LBB{{[0-9]+}}_1:
87 ; CHECK-NEXT: ldrexd r[[OLD1:[0-9]+]], r[[OLD2:[0-9]+]], [r[[ADDR]]]
88   ; r0, r1 below is a reasonable guess but could change: it certainly comes into the
89   ; function there.
90 ; CHECK-NEXT: adds [[NEW1:r[0-9]+]], r[[OLD1]], r0
91 ; CHECK-NEXT: adc{{(\.w)?}}  [[NEW2:r[0-9]+]], r[[OLD2]], r1
92 ; CHECK-NEXT: strexd [[STATUS:r[0-9]+]], [[NEW1]], [[NEW2]], [r[[ADDR]]]
93 ; CHECK-NEXT: cmp [[STATUS]], #0
94 ; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
95 ; CHECK-NOT: dmb
96 ; CHECK-NOT: mcr
97
98 ; CHECK: mov r0, r[[OLD1]]
99 ; CHECK-NEXT: mov r1, r[[OLD2]]
100    ret i64 %old
101 }
102
103 define i8 @test_atomic_load_sub_i8(i8 %offset) nounwind {
104 ; CHECK-LABEL: test_atomic_load_sub_i8:
105    %old = atomicrmw sub i8* @var8, i8 %offset monotonic
106 ; CHECK-NOT: dmb
107 ; CHECK-NOT: mcr
108 ; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var8
109 ; CHECK: movt r[[ADDR]], :upper16:var8
110
111 ; CHECK: .LBB{{[0-9]+}}_1:
112 ; CHECK-NEXT: ldrexb r[[OLD:[0-9]+]], [r[[ADDR]]]
113   ; r0 below is a reasonable guess but could change: it certainly comes into the
114   ;  function there.
115 ; CHECK-NEXT: sub{{s?}} [[NEW:r[0-9]+]], r[[OLD]], r0
116 ; CHECK-NEXT: strexb [[STATUS:r[0-9]+]], [[NEW]], [r[[ADDR]]]
117 ; CHECK-NEXT: cmp [[STATUS]], #0
118 ; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
119 ; CHECK-NOT: dmb
120 ; CHECK-NOT: mcr
121
122 ; CHECK: mov r0, r[[OLD]]
123    ret i8 %old
124 }
125
126 define i16 @test_atomic_load_sub_i16(i16 %offset) nounwind {
127 ; CHECK-LABEL: test_atomic_load_sub_i16:
128    %old = atomicrmw sub i16* @var16, i16 %offset release
129 ; CHECK-NOT: dmb
130 ; CHECK-NOT: mcr
131 ; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var16
132 ; CHECK: movt r[[ADDR]], :upper16:var16
133
134 ; CHECK: .LBB{{[0-9]+}}_1:
135 ; CHECK-NEXT: ldrexh r[[OLD:[0-9]+]], [r[[ADDR]]]
136   ; r0 below is a reasonable guess but could change: it certainly comes into the
137   ;  function there.
138 ; CHECK-NEXT: sub{{s?}} [[NEW:r[0-9]+]], r[[OLD]], r0
139 ; CHECK-NEXT: stlexh [[STATUS:r[0-9]+]], [[NEW]], [r[[ADDR]]]
140 ; CHECK-NEXT: cmp [[STATUS]], #0
141 ; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
142 ; CHECK-NOT: dmb
143 ; CHECK-NOT: mcr
144
145 ; CHECK: mov r0, r[[OLD]]
146    ret i16 %old
147 }
148
149 define i32 @test_atomic_load_sub_i32(i32 %offset) nounwind {
150 ; CHECK-LABEL: test_atomic_load_sub_i32:
151    %old = atomicrmw sub i32* @var32, i32 %offset acquire
152 ; CHECK-NOT: dmb
153 ; CHECK-NOT: mcr
154 ; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var32
155 ; CHECK: movt r[[ADDR]], :upper16:var32
156
157 ; CHECK: .LBB{{[0-9]+}}_1:
158 ; CHECK-NEXT: ldaex r[[OLD:[0-9]+]], [r[[ADDR]]]
159   ; r0 below is a reasonable guess but could change: it certainly comes into the
160   ;  function there.
161 ; CHECK-NEXT: sub{{s?}} [[NEW:r[0-9]+]], r[[OLD]], r0
162 ; CHECK-NEXT: strex [[STATUS:r[0-9]+]], [[NEW]], [r[[ADDR]]]
163 ; CHECK-NEXT: cmp [[STATUS]], #0
164 ; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
165 ; CHECK-NOT: dmb
166 ; CHECK-NOT: mcr
167
168 ; CHECK: mov r0, r[[OLD]]
169    ret i32 %old
170 }
171
172 define i64 @test_atomic_load_sub_i64(i64 %offset) nounwind {
173 ; CHECK-LABEL: test_atomic_load_sub_i64:
174    %old = atomicrmw sub i64* @var64, i64 %offset seq_cst
175 ; CHECK-NOT: dmb
176 ; CHECK-NOT: mcr
177 ; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var64
178 ; CHECK: movt r[[ADDR]], :upper16:var64
179
180 ; CHECK: .LBB{{[0-9]+}}_1:
181 ; CHECK-NEXT: ldaexd r[[OLD1:[0-9]+]], r[[OLD2:[0-9]+]], [r[[ADDR]]]
182   ; r0, r1 below is a reasonable guess but could change: it certainly comes into the
183   ; function there.
184 ; CHECK-NEXT: subs [[NEW1:r[0-9]+]], r[[OLD1]], r0
185 ; CHECK-NEXT: sbc{{(\.w)?}}  [[NEW2:r[0-9]+]], r[[OLD2]], r1
186 ; CHECK-NEXT: stlexd [[STATUS:r[0-9]+]], [[NEW1]], [[NEW2]], [r[[ADDR]]]
187 ; CHECK-NEXT: cmp [[STATUS]], #0
188 ; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
189 ; CHECK-NOT: dmb
190 ; CHECK-NOT: mcr
191
192 ; CHECK: mov r0, r[[OLD1]]
193 ; CHECK-NEXT: mov r1, r[[OLD2]]
194    ret i64 %old
195 }
196
197 define i8 @test_atomic_load_and_i8(i8 %offset) nounwind {
198 ; CHECK-LABEL: test_atomic_load_and_i8:
199    %old = atomicrmw and i8* @var8, i8 %offset release
200 ; CHECK-NOT: dmb
201 ; CHECK-NOT: mcr
202 ; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var8
203 ; CHECK: movt r[[ADDR]], :upper16:var8
204
205 ; CHECK: .LBB{{[0-9]+}}_1:
206 ; CHECK-NEXT: ldrexb r[[OLD:[0-9]+]], [r[[ADDR]]]
207   ; r0 below is a reasonable guess but could change: it certainly comes into the
208   ;  function there.
209 ; CHECK-NEXT: and{{(\.w)?}} [[NEW:r[0-9]+]], r[[OLD]], r0
210 ; CHECK-NEXT: stlexb [[STATUS:r[0-9]+]], [[NEW]], [r[[ADDR]]]
211 ; CHECK-NEXT: cmp [[STATUS]], #0
212 ; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
213 ; CHECK-NOT: dmb
214 ; CHECK-NOT: mcr
215
216 ; CHECK: mov r0, r[[OLD]]
217    ret i8 %old
218 }
219
220 define i16 @test_atomic_load_and_i16(i16 %offset) nounwind {
221 ; CHECK-LABEL: test_atomic_load_and_i16:
222    %old = atomicrmw and i16* @var16, i16 %offset monotonic
223 ; CHECK-NOT: dmb
224 ; CHECK-NOT: mcr
225 ; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var16
226 ; CHECK: movt r[[ADDR]], :upper16:var16
227
228 ; CHECK: .LBB{{[0-9]+}}_1:
229 ; CHECK-NEXT: ldrexh r[[OLD:[0-9]+]], [r[[ADDR]]]
230   ; r0 below is a reasonable guess but could change: it certainly comes into the
231   ;  function there.
232 ; CHECK-NEXT: and{{(\.w)?}} [[NEW:r[0-9]+]], r[[OLD]], r0
233 ; CHECK-NEXT: strexh [[STATUS:r[0-9]+]], [[NEW]], [r[[ADDR]]]
234 ; CHECK-NEXT: cmp [[STATUS]], #0
235 ; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
236 ; CHECK-NOT: dmb
237 ; CHECK-NOT: mcr
238
239 ; CHECK: mov r0, r[[OLD]]
240    ret i16 %old
241 }
242
243 define i32 @test_atomic_load_and_i32(i32 %offset) nounwind {
244 ; CHECK-LABEL: test_atomic_load_and_i32:
245    %old = atomicrmw and i32* @var32, i32 %offset seq_cst
246 ; CHECK-NOT: dmb
247 ; CHECK-NOT: mcr
248 ; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var32
249 ; CHECK: movt r[[ADDR]], :upper16:var32
250
251 ; CHECK: .LBB{{[0-9]+}}_1:
252 ; CHECK-NEXT: ldaex r[[OLD:[0-9]+]], [r[[ADDR]]]
253   ; r0 below is a reasonable guess but could change: it certainly comes into the
254   ;  function there.
255 ; CHECK-NEXT: and{{(\.w)?}} [[NEW:r[0-9]+]], r[[OLD]], r0
256 ; CHECK-NEXT: stlex [[STATUS:r[0-9]+]], [[NEW]], [r[[ADDR]]]
257 ; CHECK-NEXT: cmp [[STATUS]], #0
258 ; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
259 ; CHECK-NOT: dmb
260 ; CHECK-NOT: mcr
261
262 ; CHECK: mov r0, r[[OLD]]
263    ret i32 %old
264 }
265
266 define i64 @test_atomic_load_and_i64(i64 %offset) nounwind {
267 ; CHECK-LABEL: test_atomic_load_and_i64:
268    %old = atomicrmw and i64* @var64, i64 %offset acquire
269 ; CHECK-NOT: dmb
270 ; CHECK-NOT: mcr
271 ; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var64
272 ; CHECK: movt r[[ADDR]], :upper16:var64
273
274 ; CHECK: .LBB{{[0-9]+}}_1:
275 ; CHECK-NEXT: ldaexd r[[OLD1:[0-9]+]], r[[OLD2:[0-9]+]], [r[[ADDR]]]
276   ; r0, r1 below is a reasonable guess but could change: it certainly comes into the
277   ; function there.
278 ; CHECK-NEXT: and{{(\.w)?}} [[NEW1:r[0-9]+]], r[[OLD1]], r0
279 ; CHECK-NEXT: and{{(\.w)?}} [[NEW2:r[0-9]+]], r[[OLD2]], r1
280 ; CHECK-NEXT: strexd [[STATUS:r[0-9]+]], [[NEW1]], [[NEW2]], [r[[ADDR]]]
281 ; CHECK-NEXT: cmp [[STATUS]], #0
282 ; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
283 ; CHECK-NOT: dmb
284 ; CHECK-NOT: mcr
285
286 ; CHECK: mov r0, r[[OLD1]]
287 ; CHECK-NEXT: mov r1, r[[OLD2]]
288    ret i64 %old
289 }
290
291 define i8 @test_atomic_load_or_i8(i8 %offset) nounwind {
292 ; CHECK-LABEL: test_atomic_load_or_i8:
293    %old = atomicrmw or i8* @var8, i8 %offset seq_cst
294 ; CHECK-NOT: dmb
295 ; CHECK-NOT: mcr
296 ; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var8
297 ; CHECK: movt r[[ADDR]], :upper16:var8
298
299 ; CHECK: .LBB{{[0-9]+}}_1:
300 ; CHECK-NEXT: ldaexb r[[OLD:[0-9]+]], [r[[ADDR]]]
301   ; r0 below is a reasonable guess but could change: it certainly comes into the
302   ;  function there.
303 ; CHECK-NEXT: orr{{(\.w)?}} [[NEW:r[0-9]+]], r[[OLD]], r0
304 ; CHECK-NEXT: stlexb [[STATUS:r[0-9]+]], [[NEW]], [r[[ADDR]]]
305 ; CHECK-NEXT: cmp [[STATUS]], #0
306 ; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
307 ; CHECK-NOT: dmb
308 ; CHECK-NOT: mcr
309
310 ; CHECK: mov r0, r[[OLD]]
311    ret i8 %old
312 }
313
314 define i16 @test_atomic_load_or_i16(i16 %offset) nounwind {
315 ; CHECK-LABEL: test_atomic_load_or_i16:
316    %old = atomicrmw or i16* @var16, i16 %offset monotonic
317 ; CHECK-NOT: dmb
318 ; CHECK-NOT: mcr
319 ; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var16
320 ; CHECK: movt r[[ADDR]], :upper16:var16
321
322 ; CHECK: .LBB{{[0-9]+}}_1:
323 ; CHECK-NEXT: ldrexh r[[OLD:[0-9]+]], [r[[ADDR]]]
324   ; r0 below is a reasonable guess but could change: it certainly comes into the
325   ;  function there.
326 ; CHECK-NEXT: orr{{(\.w)?}} [[NEW:r[0-9]+]], r[[OLD]], r0
327 ; CHECK-NEXT: strexh [[STATUS:r[0-9]+]], [[NEW]], [r[[ADDR]]]
328 ; CHECK-NEXT: cmp [[STATUS]], #0
329 ; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
330 ; CHECK-NOT: dmb
331 ; CHECK-NOT: mcr
332
333 ; CHECK: mov r0, r[[OLD]]
334    ret i16 %old
335 }
336
337 define i32 @test_atomic_load_or_i32(i32 %offset) nounwind {
338 ; CHECK-LABEL: test_atomic_load_or_i32:
339    %old = atomicrmw or i32* @var32, i32 %offset acquire
340 ; CHECK-NOT: dmb
341 ; CHECK-NOT: mcr
342 ; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var32
343 ; CHECK: movt r[[ADDR]], :upper16:var32
344
345 ; CHECK: .LBB{{[0-9]+}}_1:
346 ; CHECK-NEXT: ldaex r[[OLD:[0-9]+]], [r[[ADDR]]]
347   ; r0 below is a reasonable guess but could change: it certainly comes into the
348   ;  function there.
349 ; CHECK-NEXT: orr{{(\.w)?}} [[NEW:r[0-9]+]], r[[OLD]], r0
350 ; CHECK-NEXT: strex [[STATUS:r[0-9]+]], [[NEW]], [r[[ADDR]]]
351 ; CHECK-NEXT: cmp [[STATUS]], #0
352 ; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
353 ; CHECK-NOT: dmb
354 ; CHECK-NOT: mcr
355
356 ; CHECK: mov r0, r[[OLD]]
357    ret i32 %old
358 }
359
360 define i64 @test_atomic_load_or_i64(i64 %offset) nounwind {
361 ; CHECK-LABEL: test_atomic_load_or_i64:
362    %old = atomicrmw or i64* @var64, i64 %offset release
363 ; CHECK-NOT: dmb
364 ; CHECK-NOT: mcr
365 ; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var64
366 ; CHECK: movt r[[ADDR]], :upper16:var64
367
368 ; CHECK: .LBB{{[0-9]+}}_1:
369 ; CHECK-NEXT: ldrexd r[[OLD1:[0-9]+]], r[[OLD2:[0-9]+]], [r[[ADDR]]]
370   ; r0, r1 below is a reasonable guess but could change: it certainly comes into the
371   ; function there.
372 ; CHECK-NEXT: orr{{(\.w)?}} [[NEW1:r[0-9]+]], r[[OLD1]], r0
373 ; CHECK-NEXT: orr{{(\.w)?}} [[NEW2:r[0-9]+]], r[[OLD2]], r1
374 ; CHECK-NEXT: stlexd [[STATUS:r[0-9]+]], [[NEW1]], [[NEW2]], [r[[ADDR]]]
375 ; CHECK-NEXT: cmp [[STATUS]], #0
376 ; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
377 ; CHECK-NOT: dmb
378 ; CHECK-NOT: mcr
379
380 ; CHECK: mov r0, r[[OLD1]]
381 ; CHECK-NEXT: mov r1, r[[OLD2]]
382    ret i64 %old
383 }
384
385 define i8 @test_atomic_load_xor_i8(i8 %offset) nounwind {
386 ; CHECK-LABEL: test_atomic_load_xor_i8:
387    %old = atomicrmw xor i8* @var8, i8 %offset acquire
388 ; CHECK-NOT: dmb
389 ; CHECK-NOT: mcr
390 ; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var8
391 ; CHECK: movt r[[ADDR]], :upper16:var8
392
393 ; CHECK: .LBB{{[0-9]+}}_1:
394 ; CHECK-NEXT: ldaexb r[[OLD:[0-9]+]], [r[[ADDR]]]
395   ; r0 below is a reasonable guess but could change: it certainly comes into the
396   ;  function there.
397 ; CHECK-NEXT: eor{{(\.w)?}} [[NEW:r[0-9]+]], r[[OLD]], r0
398 ; CHECK-NEXT: strexb [[STATUS:r[0-9]+]], [[NEW]], [r[[ADDR]]]
399 ; CHECK-NEXT: cmp [[STATUS]], #0
400 ; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
401 ; CHECK-NOT: dmb
402 ; CHECK-NOT: mcr
403
404 ; CHECK: mov r0, r[[OLD]]
405    ret i8 %old
406 }
407
408 define i16 @test_atomic_load_xor_i16(i16 %offset) nounwind {
409 ; CHECK-LABEL: test_atomic_load_xor_i16:
410    %old = atomicrmw xor i16* @var16, i16 %offset release
411 ; CHECK-NOT: dmb
412 ; CHECK-NOT: mcr
413 ; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var16
414 ; CHECK: movt r[[ADDR]], :upper16:var16
415
416 ; CHECK: .LBB{{[0-9]+}}_1:
417 ; CHECK-NEXT: ldrexh r[[OLD:[0-9]+]], [r[[ADDR]]]
418   ; r0 below is a reasonable guess but could change: it certainly comes into the
419   ;  function there.
420 ; CHECK-NEXT: eor{{(\.w)?}} [[NEW:r[0-9]+]], r[[OLD]], r0
421 ; CHECK-NEXT: stlexh [[STATUS:r[0-9]+]], [[NEW]], [r[[ADDR]]]
422 ; CHECK-NEXT: cmp [[STATUS]], #0
423 ; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
424 ; CHECK-NOT: dmb
425 ; CHECK-NOT: mcr
426
427 ; CHECK: mov r0, r[[OLD]]
428    ret i16 %old
429 }
430
431 define i32 @test_atomic_load_xor_i32(i32 %offset) nounwind {
432 ; CHECK-LABEL: test_atomic_load_xor_i32:
433    %old = atomicrmw xor i32* @var32, i32 %offset seq_cst
434 ; CHECK-NOT: dmb
435 ; CHECK-NOT: mcr
436 ; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var32
437 ; CHECK: movt r[[ADDR]], :upper16:var32
438
439 ; CHECK: .LBB{{[0-9]+}}_1:
440 ; CHECK-NEXT: ldaex r[[OLD:[0-9]+]], [r[[ADDR]]]
441   ; r0 below is a reasonable guess but could change: it certainly comes into the
442   ;  function there.
443 ; CHECK-NEXT: eor{{(\.w)?}} [[NEW:r[0-9]+]], r[[OLD]], r0
444 ; CHECK-NEXT: stlex [[STATUS:r[0-9]+]], [[NEW]], [r[[ADDR]]]
445 ; CHECK-NEXT: cmp [[STATUS]], #0
446 ; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
447 ; CHECK-NOT: dmb
448 ; CHECK-NOT: mcr
449
450 ; CHECK: mov r0, r[[OLD]]
451    ret i32 %old
452 }
453
454 define i64 @test_atomic_load_xor_i64(i64 %offset) nounwind {
455 ; CHECK-LABEL: test_atomic_load_xor_i64:
456    %old = atomicrmw xor i64* @var64, i64 %offset monotonic
457 ; CHECK-NOT: dmb
458 ; CHECK-NOT: mcr
459 ; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var64
460 ; CHECK: movt r[[ADDR]], :upper16:var64
461
462 ; CHECK: .LBB{{[0-9]+}}_1:
463 ; CHECK-NEXT: ldrexd r[[OLD1:[0-9]+]], r[[OLD2:[0-9]+]], [r[[ADDR]]]
464   ; r0, r1 below is a reasonable guess but could change: it certainly comes into the
465   ; function there.
466 ; CHECK-NEXT: eor{{(\.w)?}} [[NEW1:r[0-9]+]], r[[OLD1]], r0
467 ; CHECK-NEXT: eor{{(\.w)?}} [[NEW2:r[0-9]+]], r[[OLD2]], r1
468 ; CHECK-NEXT: strexd [[STATUS:r[0-9]+]], [[NEW1]], [[NEW2]], [r[[ADDR]]]
469 ; CHECK-NEXT: cmp [[STATUS]], #0
470 ; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
471 ; CHECK-NOT: dmb
472 ; CHECK-NOT: mcr
473
474 ; CHECK: mov r0, r[[OLD1]]
475 ; CHECK-NEXT: mov r1, r[[OLD2]]
476    ret i64 %old
477 }
478
479 define i8 @test_atomic_load_xchg_i8(i8 %offset) nounwind {
480 ; CHECK-LABEL: test_atomic_load_xchg_i8:
481    %old = atomicrmw xchg i8* @var8, i8 %offset monotonic
482 ; CHECK-NOT: dmb
483 ; CHECK-NOT: mcr
484 ; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var8
485 ; CHECK: movt r[[ADDR]], :upper16:var8
486
487 ; CHECK: .LBB{{[0-9]+}}_1:
488 ; CHECK-NEXT: ldrexb r[[OLD:[0-9]+]], [r[[ADDR]]]
489   ; r0 below is a reasonable guess but could change: it certainly comes into the
490   ;  function there.
491 ; CHECK-NEXT: strexb [[STATUS:r[0-9]+]], r0, [r[[ADDR]]]
492 ; CHECK-NEXT: cmp [[STATUS]], #0
493 ; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
494 ; CHECK-NOT: dmb
495 ; CHECK-NOT: mcr
496
497 ; CHECK: mov r0, r[[OLD]]
498    ret i8 %old
499 }
500
501 define i16 @test_atomic_load_xchg_i16(i16 %offset) nounwind {
502 ; CHECK-LABEL: test_atomic_load_xchg_i16:
503    %old = atomicrmw xchg i16* @var16, i16 %offset seq_cst
504 ; CHECK-NOT: dmb
505 ; CHECK-NOT: mcr
506 ; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var16
507 ; CHECK: movt r[[ADDR]], :upper16:var16
508
509 ; CHECK: .LBB{{[0-9]+}}_1:
510 ; CHECK-NEXT: ldaexh r[[OLD:[0-9]+]], [r[[ADDR]]]
511   ; r0 below is a reasonable guess but could change: it certainly comes into the
512   ;  function there.
513 ; CHECK-NEXT: stlexh [[STATUS:r[0-9]+]], r0, [r[[ADDR]]]
514 ; CHECK-NEXT: cmp [[STATUS]], #0
515 ; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
516 ; CHECK-NOT: dmb
517 ; CHECK-NOT: mcr
518
519 ; CHECK: mov r0, r[[OLD]]
520    ret i16 %old
521 }
522
523 define i32 @test_atomic_load_xchg_i32(i32 %offset) nounwind {
524 ; CHECK-LABEL: test_atomic_load_xchg_i32:
525    %old = atomicrmw xchg i32* @var32, i32 %offset release
526 ; CHECK-NOT: dmb
527 ; CHECK-NOT: mcr
528 ; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var32
529 ; CHECK: movt r[[ADDR]], :upper16:var32
530
531 ; CHECK: .LBB{{[0-9]+}}_1:
532 ; CHECK-NEXT: ldrex r[[OLD:[0-9]+]], [r[[ADDR]]]
533   ; r0 below is a reasonable guess but could change: it certainly comes into the
534   ;  function there.
535 ; CHECK-NEXT: stlex [[STATUS:r[0-9]+]], r0, [r[[ADDR]]]
536 ; CHECK-NEXT: cmp [[STATUS]], #0
537 ; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
538 ; CHECK-NOT: dmb
539 ; CHECK-NOT: mcr
540
541 ; CHECK: mov r0, r[[OLD]]
542    ret i32 %old
543 }
544
545 define i64 @test_atomic_load_xchg_i64(i64 %offset) nounwind {
546 ; CHECK-LABEL: test_atomic_load_xchg_i64:
547    %old = atomicrmw xchg i64* @var64, i64 %offset acquire
548 ; CHECK-NOT: dmb
549 ; CHECK-NOT: mcr
550 ; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var64
551 ; CHECK: movt r[[ADDR]], :upper16:var64
552
553 ; CHECK: .LBB{{[0-9]+}}_1:
554 ; CHECK-NEXT: ldaexd r[[OLD1:[0-9]+]], r[[OLD2:[0-9]+]], [r[[ADDR]]]
555   ; r0, r1 below is a reasonable guess but could change: it certainly comes into the
556   ; function there.
557 ; CHECK-NEXT: strexd [[STATUS:r[0-9]+]], r0, r1, [r[[ADDR]]]
558 ; CHECK-NEXT: cmp [[STATUS]], #0
559 ; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
560 ; CHECK-NOT: dmb
561 ; CHECK-NOT: mcr
562
563 ; CHECK: mov r0, r[[OLD1]]
564 ; CHECK-NEXT: mov r1, r[[OLD2]]
565    ret i64 %old
566 }
567
568 define i8 @test_atomic_load_min_i8(i8 %offset) nounwind {
569 ; CHECK-LABEL: test_atomic_load_min_i8:
570    %old = atomicrmw min i8* @var8, i8 %offset acquire
571 ; CHECK-NOT: dmb
572 ; CHECK-NOT: mcr
573 ; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var8
574 ; CHECK: movt r[[ADDR]], :upper16:var8
575
576 ; CHECK: .LBB{{[0-9]+}}_1:
577 ; CHECK-NEXT: ldaexb r[[OLD:[0-9]+]], [r[[ADDR]]]
578 ; CHECK-NEXT: sxtb r[[OLDX:[0-9]+]], r[[OLD]]
579   ; r0 below is a reasonable guess but could change: it certainly comes into the
580   ;  function there.
581 ; CHECK-NEXT: cmp r[[OLDX]], r0
582 ; Thumb mode: it ge
583 ; CHECK:      movge r[[OLDX]], r0
584 ; CHECK-NEXT: strexb [[STATUS:r[0-9]+]], r[[OLDX]], [r[[ADDR]]]
585 ; CHECK-NEXT: cmp [[STATUS]], #0
586 ; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
587 ; CHECK-NOT: dmb
588 ; CHECK-NOT: mcr
589
590 ; CHECK: mov r0, r[[OLD]]
591    ret i8 %old
592 }
593
594 define i16 @test_atomic_load_min_i16(i16 %offset) nounwind {
595 ; CHECK-LABEL: test_atomic_load_min_i16:
596    %old = atomicrmw min i16* @var16, i16 %offset release
597 ; CHECK-NOT: dmb
598 ; CHECK-NOT: mcr
599 ; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var16
600 ; CHECK: movt r[[ADDR]], :upper16:var16
601
602 ; CHECK: .LBB{{[0-9]+}}_1:
603 ; CHECK-NEXT: ldrexh r[[OLD:[0-9]+]], [r[[ADDR]]]
604 ; CHECK-NEXT: sxth r[[OLDX:[0-9]+]], r[[OLD]]
605   ; r0 below is a reasonable guess but could change: it certainly comes into the
606   ;  function there.
607 ; CHECK-NEXT: cmp r[[OLDX]], r0
608 ; Thumb mode: it ge
609 ; CHECK:      movge r[[OLDX]], r0
610 ; CHECK-NEXT: stlexh [[STATUS:r[0-9]+]], r[[OLDX]], [r[[ADDR]]]
611 ; CHECK-NEXT: cmp [[STATUS]], #0
612 ; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
613 ; CHECK-NOT: dmb
614 ; CHECK-NOT: mcr
615
616 ; CHECK: mov r0, r[[OLD]]
617    ret i16 %old
618 }
619
620 define i32 @test_atomic_load_min_i32(i32 %offset) nounwind {
621 ; CHECK-LABEL: test_atomic_load_min_i32:
622    %old = atomicrmw min i32* @var32, i32 %offset monotonic
623 ; CHECK-NOT: dmb
624 ; CHECK-NOT: mcr
625 ; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var32
626 ; CHECK: movt r[[ADDR]], :upper16:var32
627
628 ; CHECK: .LBB{{[0-9]+}}_1:
629 ; CHECK-NEXT: ldrex r[[OLD:[0-9]+]], [r[[ADDR]]]
630   ; r0 below is a reasonable guess but could change: it certainly comes into the
631   ;  function there.
632 ; CHECK-NEXT: mov r[[NEW:[0-9]+]], r0
633 ; CHECK-NEXT: cmp r[[OLD]], r0
634 ; Thumb mode: it lt
635 ; CHECK:      movlt r[[NEW]], r[[OLD]]
636 ; CHECK-NEXT: strex [[STATUS:r[0-9]+]], r[[NEW]], [r[[ADDR]]]
637 ; CHECK-NEXT: cmp [[STATUS]], #0
638 ; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
639 ; CHECK-NOT: dmb
640 ; CHECK-NOT: mcr
641
642 ; CHECK: mov r0, r[[OLD]]
643    ret i32 %old
644 }
645
646 define i64 @test_atomic_load_min_i64(i64 %offset) nounwind {
647 ; CHECK-LABEL: test_atomic_load_min_i64:
648    %old = atomicrmw min i64* @var64, i64 %offset seq_cst
649 ; CHECK-NOT: dmb
650 ; CHECK-NOT: mcr
651 ; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var64
652 ; CHECK: movt r[[ADDR]], :upper16:var64
653
654 ; CHECK: .LBB{{[0-9]+}}_1:
655 ; CHECK-NEXT: ldaexd r[[OLD1:[0-9]+]], r[[OLD2:[0-9]+]], [r[[ADDR]]]
656   ; r0, r1 below is a reasonable guess but could change: it certainly comes into the
657   ; function there.
658 ; CHECK-NEXT: subs [[NEW:r[0-9]+]], r[[OLD1]], r0
659 ; CHECK-NEXT: sbcs{{(\.w)?}} [[NEW]], r[[OLD2]], r1
660 ; CHECK-NEXT: blt .LBB{{[0-9]+}}_3
661 ; CHECK-NEXT: BB#2:
662 ; CHECK-NEXT: stlexd [[STATUS:r[0-9]+]], r0, r1, [r[[ADDR]]]
663 ; CHECK-NEXT: cmp [[STATUS]], #0
664 ; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
665 ; CHECK-NOT: dmb
666 ; CHECK-NOT: mcr
667
668 ; CHECK: mov r0, r[[OLD1]]
669 ; CHECK-NEXT: mov r1, r[[OLD2]]
670    ret i64 %old
671 }
672
673 define i8 @test_atomic_load_max_i8(i8 %offset) nounwind {
674 ; CHECK-LABEL: test_atomic_load_max_i8:
675    %old = atomicrmw max i8* @var8, i8 %offset seq_cst
676 ; CHECK-NOT: dmb
677 ; CHECK-NOT: mcr
678 ; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var8
679 ; CHECK: movt r[[ADDR]], :upper16:var8
680
681 ; CHECK: .LBB{{[0-9]+}}_1:
682 ; CHECK-NEXT: ldaexb r[[OLD:[0-9]+]], [r[[ADDR]]]
683 ; CHECK-NEXT: sxtb r[[OLDX:[0-9]+]], r[[OLD]]
684   ; r0 below is a reasonable guess but could change: it certainly comes into the
685   ;  function there.
686 ; CHECK-NEXT: cmp r[[OLDX]], r0
687 ; Thumb mode: it le
688 ; CHECK:      movle r[[OLDX]], r0
689 ; CHECK-NEXT: stlexb [[STATUS:r[0-9]+]], r[[OLDX]], [r[[ADDR]]]
690 ; CHECK-NEXT: cmp [[STATUS]], #0
691 ; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
692 ; CHECK-NOT: dmb
693 ; CHECK-NOT: mcr
694
695 ; CHECK: mov r0, r[[OLD]]
696    ret i8 %old
697 }
698
699 define i16 @test_atomic_load_max_i16(i16 %offset) nounwind {
700 ; CHECK-LABEL: test_atomic_load_max_i16:
701    %old = atomicrmw max i16* @var16, i16 %offset acquire
702 ; CHECK-NOT: dmb
703 ; CHECK-NOT: mcr
704 ; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var16
705 ; CHECK: movt r[[ADDR]], :upper16:var16
706
707 ; CHECK: .LBB{{[0-9]+}}_1:
708 ; CHECK-NEXT: ldaexh r[[OLD:[0-9]+]], [r[[ADDR]]]
709 ; CHECK-NEXT: sxth r[[OLDX:[0-9]+]], r[[OLD]]
710   ; r0 below is a reasonable guess but could change: it certainly comes into the
711   ;  function there.
712 ; CHECK-NEXT: cmp r[[OLDX]], r0
713 ; Thumb mode: it le
714 ; CHECK:      movle r[[OLDX]], r0
715 ; CHECK-NEXT: strexh [[STATUS:r[0-9]+]], r[[OLDX]], [r[[ADDR]]]
716 ; CHECK-NEXT: cmp [[STATUS]], #0
717 ; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
718 ; CHECK-NOT: dmb
719 ; CHECK-NOT: mcr
720
721 ; CHECK: mov r0, r[[OLD]]
722    ret i16 %old
723 }
724
725 define i32 @test_atomic_load_max_i32(i32 %offset) nounwind {
726 ; CHECK-LABEL: test_atomic_load_max_i32:
727    %old = atomicrmw max i32* @var32, i32 %offset release
728 ; CHECK-NOT: dmb
729 ; CHECK-NOT: mcr
730 ; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var32
731 ; CHECK: movt r[[ADDR]], :upper16:var32
732
733 ; CHECK: .LBB{{[0-9]+}}_1:
734 ; CHECK-NEXT: ldrex r[[OLD:[0-9]+]], [r[[ADDR]]]
735   ; r0 below is a reasonable guess but could change: it certainly comes into the
736   ;  function there.
737 ; CHECK-NEXT: mov r[[NEW:[0-9]+]], r0
738 ; CHECK-NEXT: cmp r[[OLD]], r0
739 ; Thumb mode: it gt
740 ; CHECK:      movgt r[[NEW]], r[[OLD]]
741 ; CHECK-NEXT: stlex [[STATUS:r[0-9]+]], r[[NEW]], [r[[ADDR]]]
742 ; CHECK-NEXT: cmp [[STATUS]], #0
743 ; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
744 ; CHECK-NOT: dmb
745 ; CHECK-NOT: mcr
746
747 ; CHECK: mov r0, r[[OLD]]
748    ret i32 %old
749 }
750
751 define i64 @test_atomic_load_max_i64(i64 %offset) nounwind {
752 ; CHECK-LABEL: test_atomic_load_max_i64:
753    %old = atomicrmw max i64* @var64, i64 %offset monotonic
754 ; CHECK-NOT: dmb
755 ; CHECK-NOT: mcr
756 ; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var64
757 ; CHECK: movt r[[ADDR]], :upper16:var64
758
759 ; CHECK: .LBB{{[0-9]+}}_1:
760 ; CHECK-NEXT: ldrexd r[[OLD1:[0-9]+]], r[[OLD2:[0-9]+]], [r[[ADDR]]]
761   ; r0, r1 below is a reasonable guess but could change: it certainly comes into the
762   ; function there.
763 ; CHECK-NEXT: subs [[NEW:r[0-9]+]], r[[OLD1]], r0
764 ; CHECK-NEXT: sbcs{{(\.w)?}} [[NEW]], r[[OLD2]], r1
765 ; CHECK-NEXT: bge .LBB{{[0-9]+}}_3
766 ; CHECK-NEXT: BB#2:
767 ; CHECK-NEXT: strexd [[STATUS:r[0-9]+]], r0, r1, [r[[ADDR]]]
768 ; CHECK-NEXT: cmp [[STATUS]], #0
769 ; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
770 ; CHECK-NOT: dmb
771 ; CHECK-NOT: mcr
772
773 ; CHECK: mov r0, r[[OLD1]]
774 ; CHECK-NEXT: mov r1, r[[OLD2]]
775    ret i64 %old
776 }
777
778 define i8 @test_atomic_load_umin_i8(i8 %offset) nounwind {
779 ; CHECK-LABEL: test_atomic_load_umin_i8:
780    %old = atomicrmw umin i8* @var8, i8 %offset monotonic
781 ; CHECK-NOT: dmb
782 ; CHECK-NOT: mcr
783 ; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var8
784 ; CHECK: movt r[[ADDR]], :upper16:var8
785
786 ; CHECK: .LBB{{[0-9]+}}_1:
787 ; CHECK-NEXT: ldrexb r[[OLD:[0-9]+]], [r[[ADDR]]]
788   ; r0 below is a reasonable guess but could change: it certainly comes into the
789   ;  function there.
790 ; CHECK-NEXT: mov r[[NEW:[0-9]+]], r0
791 ; CHECK-NEXT: cmp r[[OLD]], r0
792 ; Thumb mode: it lo
793 ; CHECK:      movlo r[[NEW]], r[[OLD]]
794 ; CHECK-NEXT: strexb [[STATUS:r[0-9]+]], r[[NEW]], [r[[ADDR]]]
795 ; CHECK-NEXT: cmp [[STATUS]], #0
796 ; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
797 ; CHECK-NOT: dmb
798 ; CHECK-NOT: mcr
799
800 ; CHECK: mov r0, r[[OLD]]
801    ret i8 %old
802 }
803
804 define i16 @test_atomic_load_umin_i16(i16 %offset) nounwind {
805 ; CHECK-LABEL: test_atomic_load_umin_i16:
806    %old = atomicrmw umin i16* @var16, i16 %offset acquire
807 ; CHECK-NOT: dmb
808 ; CHECK-NOT: mcr
809 ; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var16
810 ; CHECK: movt r[[ADDR]], :upper16:var16
811
812 ; CHECK: .LBB{{[0-9]+}}_1:
813 ; CHECK-NEXT: ldaexh r[[OLD:[0-9]+]], [r[[ADDR]]]
814   ; r0 below is a reasonable guess but could change: it certainly comes into the
815   ;  function there.
816 ; CHECK-NEXT: mov r[[NEW:[0-9]+]], r0
817 ; CHECK-NEXT: cmp r[[OLD]], r0
818 ; Thumb mode: it lo
819 ; CHECK:      movlo r[[NEW]], r[[OLD]]
820 ; CHECK-NEXT: strexh [[STATUS:r[0-9]+]], r[[NEW]], [r[[ADDR]]]
821 ; CHECK-NEXT: cmp [[STATUS]], #0
822 ; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
823 ; CHECK-NOT: dmb
824 ; CHECK-NOT: mcr
825
826 ; CHECK: mov r0, r[[OLD]]
827    ret i16 %old
828 }
829
830 define i32 @test_atomic_load_umin_i32(i32 %offset) nounwind {
831 ; CHECK-LABEL: test_atomic_load_umin_i32:
832    %old = atomicrmw umin i32* @var32, i32 %offset seq_cst
833 ; CHECK-NOT: dmb
834 ; CHECK-NOT: mcr
835 ; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var32
836 ; CHECK: movt r[[ADDR]], :upper16:var32
837
838 ; CHECK: .LBB{{[0-9]+}}_1:
839 ; CHECK-NEXT: ldaex r[[OLD:[0-9]+]], [r[[ADDR]]]
840   ; r0 below is a reasonable guess but could change: it certainly comes into the
841   ;  function there.
842 ; CHECK-NEXT: mov r[[NEW:[0-9]+]], r0
843 ; CHECK-NEXT: cmp r[[OLD]], r0
844 ; Thumb mode: it lo
845 ; CHECK:      movlo r[[NEW]], r[[OLD]]
846 ; CHECK-NEXT: stlex [[STATUS:r[0-9]+]], r[[NEW]], [r[[ADDR]]]
847 ; CHECK-NEXT: cmp [[STATUS]], #0
848 ; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
849 ; CHECK-NOT: dmb
850 ; CHECK-NOT: mcr
851
852 ; CHECK: mov r0, r[[OLD]]
853    ret i32 %old
854 }
855
856 define i64 @test_atomic_load_umin_i64(i64 %offset) nounwind {
857 ; CHECK-LABEL: test_atomic_load_umin_i64:
858    %old = atomicrmw umin i64* @var64, i64 %offset acq_rel
859 ; CHECK-NOT: dmb
860 ; CHECK-NOT: mcr
861 ; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var64
862 ; CHECK: movt r[[ADDR]], :upper16:var64
863
864 ; CHECK: .LBB{{[0-9]+}}_1:
865 ; CHECK-NEXT: ldaexd r[[OLD1:[0-9]+]], r[[OLD2:[0-9]+]], [r[[ADDR]]]
866   ; r0, r1 below is a reasonable guess but could change: it certainly comes into the
867   ; function there.
868 ; CHECK-NEXT: subs [[NEW:r[0-9]+]], r[[OLD1]], r0
869 ; CHECK-NEXT: sbcs{{(\.w)?}} [[NEW]], r[[OLD2]], r1
870 ; CHECK-NEXT: blo .LBB{{[0-9]+}}_3
871 ; CHECK-NEXT: BB#2:
872 ; CHECK-NEXT: stlexd [[STATUS:r[0-9]+]], r0, r1, [r[[ADDR]]]
873 ; CHECK-NEXT: cmp [[STATUS]], #0
874 ; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
875 ; CHECK-NOT: dmb
876 ; CHECK-NOT: mcr
877
878 ; CHECK: mov r0, r[[OLD1]]
879 ; CHECK-NEXT: mov r1, r[[OLD2]]
880    ret i64 %old
881 }
882
883 define i8 @test_atomic_load_umax_i8(i8 %offset) nounwind {
884 ; CHECK-LABEL: test_atomic_load_umax_i8:
885    %old = atomicrmw umax i8* @var8, i8 %offset acq_rel
886 ; CHECK-NOT: dmb
887 ; CHECK-NOT: mcr
888 ; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var8
889 ; CHECK: movt r[[ADDR]], :upper16:var8
890
891 ; CHECK: .LBB{{[0-9]+}}_1:
892 ; CHECK-NEXT: ldaexb r[[OLD:[0-9]+]], [r[[ADDR]]]
893   ; r0 below is a reasonable guess but could change: it certainly comes into the
894   ;  function there.
895 ; CHECK-NEXT: mov r[[NEW:[0-9]+]], r0
896 ; CHECK-NEXT: cmp r[[OLD]], r0
897 ; Thumb mode: it hi
898 ; CHECK:      movhi r[[NEW]], r[[OLD]]
899 ; CHECK-NEXT: stlexb [[STATUS:r[0-9]+]], r[[NEW]], [r[[ADDR]]]
900 ; CHECK-NEXT: cmp [[STATUS]], #0
901 ; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
902 ; CHECK-NOT: dmb
903 ; CHECK-NOT: mcr
904
905 ; CHECK: mov r0, r[[OLD]]
906    ret i8 %old
907 }
908
909 define i16 @test_atomic_load_umax_i16(i16 %offset) nounwind {
910 ; CHECK-LABEL: test_atomic_load_umax_i16:
911    %old = atomicrmw umax i16* @var16, i16 %offset monotonic
912 ; CHECK-NOT: dmb
913 ; CHECK-NOT: mcr
914 ; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var16
915 ; CHECK: movt r[[ADDR]], :upper16:var16
916
917 ; CHECK: .LBB{{[0-9]+}}_1:
918 ; CHECK-NEXT: ldrexh r[[OLD:[0-9]+]], [r[[ADDR]]]
919   ; r0 below is a reasonable guess but could change: it certainly comes into the
920   ;  function there.
921 ; CHECK-NEXT: mov r[[NEW:[0-9]+]], r0
922 ; CHECK-NEXT: cmp r[[OLD]], r0
923 ; Thumb mode: it hi
924 ; CHECK:      movhi r[[NEW]], r[[OLD]]
925 ; CHECK-NEXT: strexh [[STATUS:r[0-9]+]], r[[NEW]], [r[[ADDR]]]
926 ; CHECK-NEXT: cmp [[STATUS]], #0
927 ; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
928 ; CHECK-NOT: dmb
929 ; CHECK-NOT: mcr
930
931 ; CHECK: mov r0, r[[OLD]]
932    ret i16 %old
933 }
934
935 define i32 @test_atomic_load_umax_i32(i32 %offset) nounwind {
936 ; CHECK-LABEL: test_atomic_load_umax_i32:
937    %old = atomicrmw umax i32* @var32, i32 %offset seq_cst
938 ; CHECK-NOT: dmb
939 ; CHECK-NOT: mcr
940 ; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var32
941 ; CHECK: movt r[[ADDR]], :upper16:var32
942
943 ; CHECK: .LBB{{[0-9]+}}_1:
944 ; CHECK-NEXT: ldaex r[[OLD:[0-9]+]], [r[[ADDR]]]
945   ; r0 below is a reasonable guess but could change: it certainly comes into the
946   ;  function there.
947 ; CHECK-NEXT: mov r[[NEW:[0-9]+]], r0
948 ; CHECK-NEXT: cmp r[[OLD]], r0
949 ; Thumb mode: it hi
950 ; CHECK:      movhi r[[NEW]], r[[OLD]]
951 ; CHECK-NEXT: stlex [[STATUS:r[0-9]+]], r[[NEW]], [r[[ADDR]]]
952 ; CHECK-NEXT: cmp [[STATUS]], #0
953 ; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
954 ; CHECK-NOT: dmb
955 ; CHECK-NOT: mcr
956
957 ; CHECK: mov r0, r[[OLD]]
958    ret i32 %old
959 }
960
961 define i64 @test_atomic_load_umax_i64(i64 %offset) nounwind {
962 ; CHECK-LABEL: test_atomic_load_umax_i64:
963    %old = atomicrmw umax i64* @var64, i64 %offset release
964 ; CHECK-NOT: dmb
965 ; CHECK-NOT: mcr
966 ; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var64
967 ; CHECK: movt r[[ADDR]], :upper16:var64
968
969 ; CHECK: .LBB{{[0-9]+}}_1:
970 ; CHECK-NEXT: ldrexd r[[OLD1:[0-9]+]], r[[OLD2:[0-9]+]], [r[[ADDR]]]
971   ; r0, r1 below is a reasonable guess but could change: it certainly comes into the
972   ; function there.
973 ; CHECK-NEXT: subs [[NEW:r[0-9]+]], r[[OLD1]], r0
974 ; CHECK-NEXT: sbcs{{(\.w)?}} [[NEW]], r[[OLD2]], r1
975 ; CHECK-NEXT: bhs .LBB{{[0-9]+}}_3
976 ; CHECK-NEXT: BB#2:
977 ; CHECK-NEXT: stlexd [[STATUS:r[0-9]+]], r0, r1, [r[[ADDR]]]
978 ; CHECK-NEXT: cmp [[STATUS]], #0
979 ; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
980 ; CHECK-NOT: dmb
981 ; CHECK-NOT: mcr
982
983 ; CHECK: mov r0, r[[OLD1]]
984 ; CHECK-NEXT: mov r1, r[[OLD2]]
985    ret i64 %old
986 }
987
988 define i8 @test_atomic_cmpxchg_i8(i8 %wanted, i8 %new) nounwind {
989 ; CHECK-LABEL: test_atomic_cmpxchg_i8:
990    %old = cmpxchg i8* @var8, i8 %wanted, i8 %new acquire
991 ; CHECK-NOT: dmb
992 ; CHECK-NOT: mcr
993 ; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var8
994 ; CHECK: movt r[[ADDR]], :upper16:var8
995
996 ; CHECK: .LBB{{[0-9]+}}_1:
997 ; CHECK-NEXT: ldaexb r[[OLD:[0-9]+]], [r[[ADDR]]]
998   ; r0 below is a reasonable guess but could change: it certainly comes into the
999   ;  function there.
1000 ; CHECK-NEXT: cmp r[[OLD]], r0
1001 ; CHECK-NEXT: bne .LBB{{[0-9]+}}_3
1002 ; CHECK-NEXT: BB#2:
1003   ; As above, r1 is a reasonable guess.
1004 ; CHECK-NEXT: strexb [[STATUS:r[0-9]+]], r1, [r[[ADDR]]]
1005 ; CHECK-NEXT: cmp [[STATUS]], #0
1006 ; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
1007 ; CHECK-NOT: dmb
1008 ; CHECK-NOT: mcr
1009
1010 ; CHECK: mov r0, r[[OLD]]
1011    ret i8 %old
1012 }
1013
1014 define i16 @test_atomic_cmpxchg_i16(i16 %wanted, i16 %new) nounwind {
1015 ; CHECK-LABEL: test_atomic_cmpxchg_i16:
1016    %old = cmpxchg i16* @var16, i16 %wanted, i16 %new seq_cst
1017 ; CHECK-NOT: dmb
1018 ; CHECK-NOT: mcr
1019 ; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var16
1020 ; CHECK: movt r[[ADDR]], :upper16:var16
1021
1022 ; CHECK: .LBB{{[0-9]+}}_1:
1023 ; CHECK-NEXT: ldaexh r[[OLD:[0-9]+]], [r[[ADDR]]]
1024   ; r0 below is a reasonable guess but could change: it certainly comes into the
1025   ;  function there.
1026 ; CHECK-NEXT: cmp r[[OLD]], r0
1027 ; CHECK-NEXT: bne .LBB{{[0-9]+}}_3
1028 ; CHECK-NEXT: BB#2:
1029   ; As above, r1 is a reasonable guess.
1030 ; CHECK-NEXT: stlexh [[STATUS:r[0-9]+]], r1, [r[[ADDR]]]
1031 ; CHECK-NEXT: cmp [[STATUS]], #0
1032 ; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
1033 ; CHECK-NOT: dmb
1034 ; CHECK-NOT: mcr
1035
1036 ; CHECK: mov r0, r[[OLD]]
1037    ret i16 %old
1038 }
1039
1040 define i32 @test_atomic_cmpxchg_i32(i32 %wanted, i32 %new) nounwind {
1041 ; CHECK-LABEL: test_atomic_cmpxchg_i32:
1042    %old = cmpxchg i32* @var32, i32 %wanted, i32 %new release
1043 ; CHECK-NOT: dmb
1044 ; CHECK-NOT: mcr
1045 ; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var32
1046 ; CHECK: movt r[[ADDR]], :upper16:var32
1047
1048 ; CHECK: .LBB{{[0-9]+}}_1:
1049 ; CHECK-NEXT: ldrex r[[OLD:[0-9]+]], [r[[ADDR]]]
1050   ; r0 below is a reasonable guess but could change: it certainly comes into the
1051   ;  function there.
1052 ; CHECK-NEXT: cmp r[[OLD]], r0
1053 ; CHECK-NEXT: bne .LBB{{[0-9]+}}_3
1054 ; CHECK-NEXT: BB#2:
1055   ; As above, r1 is a reasonable guess.
1056 ; CHECK-NEXT: stlex [[STATUS:r[0-9]+]], r1, [r[[ADDR]]]
1057 ; CHECK-NEXT: cmp [[STATUS]], #0
1058 ; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
1059 ; CHECK-NOT: dmb
1060 ; CHECK-NOT: mcr
1061
1062 ; CHECK: mov r0, r[[OLD]]
1063    ret i32 %old
1064 }
1065
1066 define i64 @test_atomic_cmpxchg_i64(i64 %wanted, i64 %new) nounwind {
1067 ; CHECK-LABEL: test_atomic_cmpxchg_i64:
1068    %old = cmpxchg i64* @var64, i64 %wanted, i64 %new monotonic
1069 ; CHECK-NOT: dmb
1070 ; CHECK-NOT: mcr
1071 ; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var64
1072 ; CHECK: movt r[[ADDR]], :upper16:var64
1073
1074 ; CHECK: .LBB{{[0-9]+}}_1:
1075 ; CHECK-NEXT: ldrexd [[OLD1:r[0-9]+|lr]], [[OLD2:r[0-9]+|lr]], [r[[ADDR]]]
1076   ; r0, r1 below is a reasonable guess but could change: it certainly comes into the
1077   ; function there.
1078 ; CHECK-NEXT: cmp   [[OLD1]], r0
1079 ; Thumb mode: it eq
1080 ; CHECK:      cmpeq [[OLD2]], r1
1081 ; CHECK-NEXT: bne .LBB{{[0-9]+}}_3
1082 ; CHECK-NEXT: BB#2:
1083   ; As above, r2, r3 is a reasonable guess.
1084 ; CHECK-NEXT: strexd [[STATUS:r[0-9]+]], r2, r3, [r[[ADDR]]]
1085 ; CHECK-NEXT: cmp [[STATUS]], #0
1086 ; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
1087 ; CHECK-NOT: dmb
1088 ; CHECK-NOT: mcr
1089
1090 ; CHECK: mov r0, [[OLD1]]
1091 ; CHECK-NEXT: mov r1, [[OLD2]]
1092    ret i64 %old
1093 }
1094
1095 define i8 @test_atomic_load_monotonic_i8() nounwind {
1096 ; CHECK-LABEL: test_atomic_load_monotonic_i8:
1097   %val = load atomic i8* @var8 monotonic, align 1
1098 ; CHECK-NOT: dmb
1099 ; CHECK-NOT: mcr
1100 ; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var8
1101 ; CHECK: movt r[[ADDR]], :upper16:var8
1102 ; CHECK: ldrb r0, [r[[ADDR]]]
1103 ; CHECK-NOT: dmb
1104 ; CHECK-NOT: mcr
1105
1106   ret i8 %val
1107 }
1108
1109 define i8 @test_atomic_load_monotonic_regoff_i8(i64 %base, i64 %off) nounwind {
1110 ; CHECK-LABEL: test_atomic_load_monotonic_regoff_i8:
1111   %addr_int = add i64 %base, %off
1112   %addr = inttoptr i64 %addr_int to i8*
1113
1114   %val = load atomic i8* %addr monotonic, align 1
1115 ; CHECK-NOT: dmb
1116 ; CHECK-NOT: mcr
1117 ; CHECK: ldrb r0, [r0, r2]
1118 ; CHECK-NOT: dmb
1119 ; CHECK-NOT: mcr
1120
1121   ret i8 %val
1122 }
1123
1124 define i8 @test_atomic_load_acquire_i8() nounwind {
1125 ; CHECK-LABEL: test_atomic_load_acquire_i8:
1126   %val = load atomic i8* @var8 acquire, align 1
1127 ; CHECK-NOT: dmb
1128 ; CHECK-NOT: mcr
1129 ; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var8
1130 ; CHECK-NOT: dmb
1131 ; CHECK-NOT: mcr
1132 ; CHECK: movt r[[ADDR]], :upper16:var8
1133 ; CHECK-NOT: dmb
1134 ; CHECK-NOT: mcr
1135 ; CHECK: ldab r0, [r[[ADDR]]]
1136 ; CHECK-NOT: dmb
1137 ; CHECK-NOT: mcr
1138   ret i8 %val
1139 }
1140
1141 define i8 @test_atomic_load_seq_cst_i8() nounwind {
1142 ; CHECK-LABEL: test_atomic_load_seq_cst_i8:
1143   %val = load atomic i8* @var8 seq_cst, align 1
1144 ; CHECK-NOT: dmb
1145 ; CHECK-NOT: mcr
1146 ; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var8
1147 ; CHECK-NOT: dmb
1148 ; CHECK-NOT: mcr
1149 ; CHECK: movt r[[ADDR]], :upper16:var8
1150 ; CHECK-NOT: dmb
1151 ; CHECK-NOT: mcr
1152 ; CHECK: ldab r0, [r[[ADDR]]]
1153 ; CHECK-NOT: dmb
1154 ; CHECK-NOT: mcr
1155   ret i8 %val
1156 }
1157
1158 define i16 @test_atomic_load_monotonic_i16() nounwind {
1159 ; CHECK-LABEL: test_atomic_load_monotonic_i16:
1160   %val = load atomic i16* @var16 monotonic, align 2
1161 ; CHECK-NOT: dmb
1162 ; CHECK-NOT: mcr
1163 ; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var16
1164 ; CHECK-NOT: dmb
1165 ; CHECK-NOT: mcr
1166 ; CHECK: movt r[[ADDR]], :upper16:var16
1167 ; CHECK-NOT: dmb
1168 ; CHECK-NOT: mcr
1169 ; CHECK: ldrh r0, [r[[ADDR]]]
1170 ; CHECK-NOT: dmb
1171 ; CHECK-NOT: mcr
1172
1173   ret i16 %val
1174 }
1175
1176 define i32 @test_atomic_load_monotonic_regoff_i32(i64 %base, i64 %off) nounwind {
1177 ; CHECK-LABEL: test_atomic_load_monotonic_regoff_i32:
1178   %addr_int = add i64 %base, %off
1179   %addr = inttoptr i64 %addr_int to i32*
1180
1181   %val = load atomic i32* %addr monotonic, align 4
1182 ; CHECK-NOT: dmb
1183 ; CHECK-NOT: mcr
1184 ; CHECK: ldr r0, [r0, r2]
1185 ; CHECK-NOT: dmb
1186 ; CHECK-NOT: mcr
1187
1188   ret i32 %val
1189 }
1190
1191 define i64 @test_atomic_load_seq_cst_i64() nounwind {
1192 ; CHECK-LABEL: test_atomic_load_seq_cst_i64:
1193   %val = load atomic i64* @var64 seq_cst, align 8
1194 ; CHECK-NOT: dmb
1195 ; CHECK-NOT: mcr
1196 ; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var64
1197 ; CHECK-NOT: dmb
1198 ; CHECK-NOT: mcr
1199 ; CHECK: movt r[[ADDR]], :upper16:var64
1200 ; CHECK-NOT: dmb
1201 ; CHECK-NOT: mcr
1202 ; CHECK: ldaexd r0, r1, [r[[ADDR]]]
1203 ; CHECK-NOT: dmb
1204 ; CHECK-NOT: mcr
1205   ret i64 %val
1206 }
1207
1208 define void @test_atomic_store_monotonic_i8(i8 %val) nounwind {
1209 ; CHECK-LABEL: test_atomic_store_monotonic_i8:
1210   store atomic i8 %val, i8* @var8 monotonic, align 1
1211 ; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var8
1212 ; CHECK: movt r[[ADDR]], :upper16:var8
1213 ; CHECK: strb r0, [r[[ADDR]]]
1214
1215   ret void
1216 }
1217
1218 define void @test_atomic_store_monotonic_regoff_i8(i64 %base, i64 %off, i8 %val) nounwind {
1219 ; CHECK-LABEL: test_atomic_store_monotonic_regoff_i8:
1220
1221   %addr_int = add i64 %base, %off
1222   %addr = inttoptr i64 %addr_int to i8*
1223
1224   store atomic i8 %val, i8* %addr monotonic, align 1
1225 ; CHECK: ldrb{{(\.w)?}} [[VAL:r[0-9]+]], [sp]
1226 ; CHECK: strb [[VAL]], [r0, r2]
1227
1228   ret void
1229 }
1230
1231 define void @test_atomic_store_release_i8(i8 %val) nounwind {
1232 ; CHECK-LABEL: test_atomic_store_release_i8:
1233   store atomic i8 %val, i8* @var8 release, align 1
1234 ; CHECK-NOT: dmb
1235 ; CHECK-NOT: mcr
1236 ; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var8
1237 ; CHECK-NOT: dmb
1238 ; CHECK-NOT: mcr
1239 ; CHECK: movt r[[ADDR]], :upper16:var8
1240 ; CHECK-NOT: dmb
1241 ; CHECK-NOT: mcr
1242 ; CHECK: stlb r0, [r[[ADDR]]]
1243 ; CHECK-NOT: dmb
1244 ; CHECK-NOT: mcr
1245   ret void
1246 }
1247
1248 define void @test_atomic_store_seq_cst_i8(i8 %val) nounwind {
1249 ; CHECK-LABEL: test_atomic_store_seq_cst_i8:
1250   store atomic i8 %val, i8* @var8 seq_cst, align 1
1251 ; CHECK-NOT: dmb
1252 ; CHECK-NOT: mcr
1253 ; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var8
1254 ; CHECK-NOT: dmb
1255 ; CHECK-NOT: mcr
1256 ; CHECK: movt r[[ADDR]], :upper16:var8
1257 ; CHECK-NOT: dmb
1258 ; CHECK-NOT: mcr
1259 ; CHECK: stlb r0, [r[[ADDR]]]
1260 ; CHECK-NOT: dmb
1261 ; CHECK-NOT: mcr
1262   ret void
1263 }
1264
1265 define void @test_atomic_store_monotonic_i16(i16 %val) nounwind {
1266 ; CHECK-LABEL: test_atomic_store_monotonic_i16:
1267   store atomic i16 %val, i16* @var16 monotonic, align 2
1268 ; CHECK-NOT: dmb
1269 ; CHECK-NOT: mcr
1270 ; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var16
1271 ; CHECK-NOT: dmb
1272 ; CHECK-NOT: mcr
1273 ; CHECK: movt r[[ADDR]], :upper16:var16
1274 ; CHECK-NOT: dmb
1275 ; CHECK-NOT: mcr
1276 ; CHECK: strh r0, [r[[ADDR]]]
1277 ; CHECK-NOT: dmb
1278 ; CHECK-NOT: mcr
1279   ret void
1280 }
1281
1282 define void @test_atomic_store_monotonic_regoff_i32(i64 %base, i64 %off, i32 %val) nounwind {
1283 ; CHECK-LABEL: test_atomic_store_monotonic_regoff_i32:
1284
1285   %addr_int = add i64 %base, %off
1286   %addr = inttoptr i64 %addr_int to i32*
1287
1288   store atomic i32 %val, i32* %addr monotonic, align 4
1289 ; CHECK-NOT: dmb
1290 ; CHECK-NOT: mcr
1291 ; CHECK: ldr [[VAL:r[0-9]+]], [sp]
1292 ; CHECK-NOT: dmb
1293 ; CHECK-NOT: mcr
1294 ; CHECK: str [[VAL]], [r0, r2]
1295 ; CHECK-NOT: dmb
1296 ; CHECK-NOT: mcr
1297
1298   ret void
1299 }
1300
1301 define void @test_atomic_store_release_i64(i64 %val) nounwind {
1302 ; CHECK-LABEL: test_atomic_store_release_i64:
1303   store atomic i64 %val, i64* @var64 release, align 8
1304 ; CHECK-NOT: dmb
1305 ; CHECK-NOT: mcr
1306 ; CHECK: movw r[[ADDR:[0-9]+]], :lower16:var64
1307 ; CHECK: movt r[[ADDR]], :upper16:var64
1308
1309 ; CHECK: .LBB{{[0-9]+}}_1:
1310   ; r0, r1 below is a reasonable guess but could change: it certainly comes into the
1311   ; function there.
1312 ; CHECK: stlexd [[STATUS:r[0-9]+]], r0, r1, [r[[ADDR]]]
1313 ; CHECK-NEXT: cmp [[STATUS]], #0
1314 ; CHECK-NEXT: bne .LBB{{[0-9]+}}_1
1315 ; CHECK-NOT: dmb
1316 ; CHECK-NOT: mcr
1317
1318   ret void
1319 }
1320
1321 define i32 @not.barriers(i32* %var, i1 %cond) {
1322 ; CHECK-LABEL: not.barriers:
1323   br i1 %cond, label %atomic_ver, label %simple_ver
1324 simple_ver:
1325   %oldval = load i32* %var
1326   %newval = add nsw i32 %oldval, -1
1327   store i32 %newval, i32* %var
1328   br label %somewhere
1329 atomic_ver:
1330   fence seq_cst
1331   %val = atomicrmw add i32* %var, i32 -1 monotonic
1332   fence seq_cst
1333   br label %somewhere
1334 ; CHECK: dmb
1335 ; CHECK: ldrex
1336 ; CHECK: dmb
1337   ; The key point here is that the second dmb isn't immediately followed by the
1338   ; simple_ver basic block, which LLVM attempted to do when DMB had been marked
1339   ; with isBarrier. For now, look for something that looks like "somewhere".
1340 ; CHECK-NEXT: mov
1341 somewhere:
1342   %combined = phi i32 [ %val, %atomic_ver ], [ %newval, %simple_ver]
1343   ret i32 %combined
1344 }