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