Home | History | Annotate | Download | only in llvm2ice_tests
      1 ; This tests each of the supported NaCl atomic instructions for every
      2 ; size allowed.
      3 
      4 ; RUN: %p2i -i %s --filetype=obj --disassemble --args -O2 \
      5 ; RUN:   -allow-externally-defined-symbols | FileCheck %s
      6 ; RUN: %p2i -i %s --filetype=obj --disassemble --args -O2 \
      7 ; RUN:   -allow-externally-defined-symbols | FileCheck --check-prefix=O2 %s
      8 ; RUN: %p2i -i %s --filetype=obj --disassemble --args -Om1 \
      9 ; RUN:   -allow-externally-defined-symbols | FileCheck %s
     10 
     11 ; RUN: %if --need=allow_dump --need=target_ARM32 --command %p2i --filetype=asm \
     12 ; RUN:   --target arm32 -i %s --args -O2 \
     13 ; RUN:   -allow-externally-defined-symbols \
     14 ; RUN:   | %if --need=allow_dump --need=target_ARM32 --command FileCheck %s \
     15 ; RUN:   --check-prefix=ARM32
     16 
     17 ; RUN: %if --need=allow_dump --need=target_ARM32 --command %p2i --filetype=asm \
     18 ; RUN:   --target arm32 -i %s --args -O2 \
     19 ; RUN:   -allow-externally-defined-symbols \
     20 ; RUN:   | %if --need=allow_dump --need=target_ARM32 --command FileCheck %s \
     21 ; RUN:   --check-prefix=ARM32O2
     22 
     23 ; RUN: %if --need=allow_dump --need=target_ARM32 --command %p2i --filetype=asm \
     24 ; RUN:   --target arm32 -i %s --args -Om1 \
     25 ; RUN:   -allow-externally-defined-symbols \
     26 ; RUN:   | %if --need=allow_dump --need=target_ARM32 --command FileCheck %s \
     27 ; RUN:   --check-prefix=ARM32
     28 
     29 ; RUN: %if --need=allow_dump --need=target_MIPS32 --command %p2i --filetype=asm\
     30 ; RUN:   --target mips32 -i %s --args -O2 \
     31 ; RUN:   -allow-externally-defined-symbols \
     32 ; RUN:   | %if --need=allow_dump --need=target_MIPS32 --command FileCheck %s \
     33 ; RUN:   --check-prefix=MIPS32O2 --check-prefix=MIPS32
     34 
     35 ; RUN: %if --need=allow_dump --need=target_MIPS32 --command %p2i --filetype=asm\
     36 ; RUN:   --target mips32 -i %s --args -Om1 \
     37 ; RUN:   -allow-externally-defined-symbols \
     38 ; RUN:   | %if --need=allow_dump --need=target_MIPS32 --command FileCheck %s \
     39 ; RUN:   --check-prefix=MIPS32OM1 --check-prefix=MIPS32
     40 
     41 declare i8 @llvm.nacl.atomic.load.i8(i8*, i32)
     42 declare i16 @llvm.nacl.atomic.load.i16(i16*, i32)
     43 declare i32 @llvm.nacl.atomic.load.i32(i32*, i32)
     44 declare i64 @llvm.nacl.atomic.load.i64(i64*, i32)
     45 declare void @llvm.nacl.atomic.store.i8(i8, i8*, i32)
     46 declare void @llvm.nacl.atomic.store.i16(i16, i16*, i32)
     47 declare void @llvm.nacl.atomic.store.i32(i32, i32*, i32)
     48 declare void @llvm.nacl.atomic.store.i64(i64, i64*, i32)
     49 declare i8 @llvm.nacl.atomic.rmw.i8(i32, i8*, i8, i32)
     50 declare i16 @llvm.nacl.atomic.rmw.i16(i32, i16*, i16, i32)
     51 declare i32 @llvm.nacl.atomic.rmw.i32(i32, i32*, i32, i32)
     52 declare i64 @llvm.nacl.atomic.rmw.i64(i32, i64*, i64, i32)
     53 declare i8 @llvm.nacl.atomic.cmpxchg.i8(i8*, i8, i8, i32, i32)
     54 declare i16 @llvm.nacl.atomic.cmpxchg.i16(i16*, i16, i16, i32, i32)
     55 declare i32 @llvm.nacl.atomic.cmpxchg.i32(i32*, i32, i32, i32, i32)
     56 declare i64 @llvm.nacl.atomic.cmpxchg.i64(i64*, i64, i64, i32, i32)
     57 declare void @llvm.nacl.atomic.fence(i32)
     58 declare void @llvm.nacl.atomic.fence.all()
     59 declare i1 @llvm.nacl.atomic.is.lock.free(i32, i8*)
     60 
     61 @SzGlobal8 = internal global [1 x i8] zeroinitializer, align 1
     62 @SzGlobal16 = internal global [2 x i8] zeroinitializer, align 2
     63 @SzGlobal32 = internal global [4 x i8] zeroinitializer, align 4
     64 @SzGlobal64 = internal global [8 x i8] zeroinitializer, align 8
     65 
     66 ; NOTE: The LLC equivalent for 16-bit atomic operations are expanded
     67 ; as 32-bit operations. For Subzero, assume that real 16-bit operations
     68 ; will be usable (the validator will be fixed):
     69 ; https://code.google.com/p/nativeclient/issues/detail?id=2981
     70 
     71 ;;; Load
     72 
     73 ; x86 guarantees load/store to be atomic if naturally aligned.
     74 ; The PNaCl IR requires all atomic accesses to be naturally aligned.
     75 
     76 define internal i32 @test_atomic_load_8(i32 %iptr) {
     77 entry:
     78   %ptr = inttoptr i32 %iptr to i8*
     79   ; parameter value "6" is for the sequential consistency memory order.
     80   %i = call i8 @llvm.nacl.atomic.load.i8(i8* %ptr, i32 6)
     81   %i2 = sub i8 %i, 0
     82   %r = zext i8 %i2 to i32
     83   ret i32 %r
     84 }
     85 ; CHECK-LABEL: test_atomic_load_8
     86 ; CHECK: mov {{.*}},DWORD
     87 ; CHECK: mov {{.*}},BYTE
     88 ; ARM32-LABEL: test_atomic_load_8
     89 ; ARM32: ldrb r{{[0-9]+}}, [r{{[0-9]+}}
     90 ; ARM32: dmb
     91 ; MIPS32-LABEL: test_atomic_load_8
     92 ; MIPS32: sync
     93 ; MIPS32: ll
     94 ; MIPS32: sc
     95 ; MIPS32: sync
     96 
     97 define internal i32 @test_atomic_load_16(i32 %iptr) {
     98 entry:
     99   %ptr = inttoptr i32 %iptr to i16*
    100   %i = call i16 @llvm.nacl.atomic.load.i16(i16* %ptr, i32 6)
    101   %i2 = sub i16 %i, 0
    102   %r = zext i16 %i2 to i32
    103   ret i32 %r
    104 }
    105 ; CHECK-LABEL: test_atomic_load_16
    106 ; CHECK: mov {{.*}},DWORD
    107 ; CHECK: mov {{.*}},WORD
    108 ; ARM32-LABEL: test_atomic_load_16
    109 ; ARM32: ldrh r{{[0-9]+}}, [r{{[0-9]+}}
    110 ; ARM32: dmb
    111 ; MIPS32-LABEL: test_atomic_load_16
    112 ; MIPS32: sync
    113 ; MIPS32: ll
    114 ; MIPS32: sc
    115 ; MIPS32: sync
    116 
    117 define internal i32 @test_atomic_load_32(i32 %iptr) {
    118 entry:
    119   %ptr = inttoptr i32 %iptr to i32*
    120   %r = call i32 @llvm.nacl.atomic.load.i32(i32* %ptr, i32 6)
    121   ret i32 %r
    122 }
    123 ; CHECK-LABEL: test_atomic_load_32
    124 ; CHECK: mov {{.*}},DWORD
    125 ; CHECK: mov {{.*}},DWORD
    126 ; ARM32-LABEL: test_atomic_load_32
    127 ; ARM32: ldr r{{[0-9]+}}, [r{{[0-9]+}}
    128 ; ARM32: dmb
    129 ; MIPS32-LABEL: test_atomic_load_32
    130 ; MIPS32: sync
    131 ; MIPS32: ll
    132 ; MIPS32: sc
    133 ; MIPS32: sync
    134 
    135 define internal i64 @test_atomic_load_64(i32 %iptr) {
    136 entry:
    137   %ptr = inttoptr i32 %iptr to i64*
    138   %r = call i64 @llvm.nacl.atomic.load.i64(i64* %ptr, i32 6)
    139   ret i64 %r
    140 }
    141 ; CHECK-LABEL: test_atomic_load_64
    142 ; CHECK: movq x{{.*}},QWORD
    143 ; CHECK: movq QWORD {{.*}},x{{.*}}
    144 ; ARM32-LABEL: test_atomic_load_64
    145 ; ARM32: ldrexd r{{[0-9]+}}, r{{[0-9]+}}, [r{{[0-9]+}}
    146 ; ARM32: dmb
    147 ; MIPS32-LABEL: test_atomic_load_64
    148 ; MIPS32: jal __sync_val_compare_and_swap_8
    149 ; MIPS32: sync
    150 
    151 define internal i32 @test_atomic_load_32_with_arith(i32 %iptr) {
    152 entry:
    153   br label %next
    154 
    155 next:
    156   %ptr = inttoptr i32 %iptr to i32*
    157   %r = call i32 @llvm.nacl.atomic.load.i32(i32* %ptr, i32 6)
    158   %r2 = sub i32 32, %r
    159   ret i32 %r2
    160 }
    161 ; CHECK-LABEL: test_atomic_load_32_with_arith
    162 ; CHECK: mov {{.*}},DWORD
    163 ; The next instruction may be a separate load or folded into an add.
    164 ;
    165 ; In O2 mode, we know that the load and sub are going to be fused.
    166 ; O2-LABEL: test_atomic_load_32_with_arith
    167 ; O2: mov {{.*}},DWORD
    168 ; O2: sub {{.*}},DWORD
    169 ; ARM32-LABEL: test_atomic_load_32_with_arith
    170 ; ARM32: ldr r{{[0-9]+}}, [r{{[0-9]+}}
    171 ; ARM32: dmb
    172 ; MIPS32-LABEL: test_atomic_load_32_with_arith
    173 ; MIPS32: sync
    174 ; MIPS32: ll
    175 ; MIPS32: sc
    176 ; MIPS32: sync
    177 ; MIPS32: subu
    178 
    179 define internal i32 @test_atomic_load_32_ignored(i32 %iptr) {
    180 entry:
    181   %ptr = inttoptr i32 %iptr to i32*
    182   %ignored = call i32 @llvm.nacl.atomic.load.i32(i32* %ptr, i32 6)
    183   ret i32 0
    184 }
    185 ; CHECK-LABEL: test_atomic_load_32_ignored
    186 ; CHECK: mov {{.*}},DWORD
    187 ; CHECK: mov {{.*}},DWORD
    188 ; O2-LABEL: test_atomic_load_32_ignored
    189 ; O2: mov {{.*}},DWORD
    190 ; O2: mov {{.*}},DWORD
    191 ; ARM32-LABEL: test_atomic_load_32_ignored
    192 ; ARM32: ldr r{{[0-9]+}}, [r{{[0-9]+}}
    193 ; ARM32: dmb
    194 ; MIPS32-LABEL: test_atomic_load_32_ignored
    195 ; MIPS32: sync
    196 ; MIPS32: ll
    197 ; MIPS32: sc
    198 ; MIPS32: sync
    199 
    200 define internal i64 @test_atomic_load_64_ignored(i32 %iptr) {
    201 entry:
    202   %ptr = inttoptr i32 %iptr to i64*
    203   %ignored = call i64 @llvm.nacl.atomic.load.i64(i64* %ptr, i32 6)
    204   ret i64 0
    205 }
    206 ; CHECK-LABEL: test_atomic_load_64_ignored
    207 ; CHECK: movq x{{.*}},QWORD
    208 ; CHECK: movq QWORD {{.*}},x{{.*}}
    209 ; ARM32-LABEL: test_atomic_load_64_ignored
    210 ; ARM32: ldrexd r{{[0-9]+}}, r{{[0-9]+}}, [r{{[0-9]+}}
    211 ; ARM32: dmb
    212 ; MIPS32-LABEL: test_atomic_load_64_ignored
    213 ; MIPS32: jal	__sync_val_compare_and_swap_8
    214 ; MIPS32: sync
    215 
    216 ;;; Store
    217 
    218 define internal void @test_atomic_store_8(i32 %iptr, i32 %v) {
    219 entry:
    220   %truncv = trunc i32 %v to i8
    221   %ptr = inttoptr i32 %iptr to i8*
    222   call void @llvm.nacl.atomic.store.i8(i8 %truncv, i8* %ptr, i32 6)
    223   ret void
    224 }
    225 ; CHECK-LABEL: test_atomic_store_8
    226 ; CHECK: mov BYTE
    227 ; CHECK: mfence
    228 ; ARM32-LABEL: test_atomic_store_8
    229 ; ARM32: dmb
    230 ; ARM32: strb r{{[0-9]+}}, [r{{[0-9]+}}
    231 ; ARM32: dmb
    232 ; MIPS32-LABEL: test_atomic_store_8
    233 ; MIPS32: sync
    234 ; MIPS32: ll
    235 ; MIPS32: sc
    236 ; MIPS32: sync
    237 
    238 define internal void @test_atomic_store_16(i32 %iptr, i32 %v) {
    239 entry:
    240   %truncv = trunc i32 %v to i16
    241   %ptr = inttoptr i32 %iptr to i16*
    242   call void @llvm.nacl.atomic.store.i16(i16 %truncv, i16* %ptr, i32 6)
    243   ret void
    244 }
    245 ; CHECK-LABEL: test_atomic_store_16
    246 ; CHECK: mov WORD
    247 ; CHECK: mfence
    248 ; ARM32-LABEL: test_atomic_store_16
    249 ; ARM32: dmb
    250 ; ARM32: strh r{{[0-9]+}}, [r{{[0-9]+}}
    251 ; ARM32: dmb
    252 ; MIPS32-LABEL: test_atomic_store_16
    253 ; MIPS32: sync
    254 ; MIPS32: ll
    255 ; MIPS32: sc
    256 ; MIPS32: sync
    257 
    258 define internal void @test_atomic_store_32(i32 %iptr, i32 %v) {
    259 entry:
    260   %ptr = inttoptr i32 %iptr to i32*
    261   call void @llvm.nacl.atomic.store.i32(i32 %v, i32* %ptr, i32 6)
    262   ret void
    263 }
    264 ; CHECK-LABEL: test_atomic_store_32
    265 ; CHECK: mov DWORD
    266 ; CHECK: mfence
    267 ; ARM32-LABEL: test_atomic_store_32
    268 ; ARM32: dmb
    269 ; ARM32: str r{{[0-9]+}}, [r{{[0-9]+}}
    270 ; ARM32: dmb
    271 ; MIPS32-LABEL: test_atomic_store_32
    272 ; MIPS32: sync
    273 ; MIPS32: ll
    274 ; MIPS32: sc
    275 ; MIPS32: sync
    276 
    277 define internal void @test_atomic_store_64(i32 %iptr, i64 %v) {
    278 entry:
    279   %ptr = inttoptr i32 %iptr to i64*
    280   call void @llvm.nacl.atomic.store.i64(i64 %v, i64* %ptr, i32 6)
    281   ret void
    282 }
    283 ; CHECK-LABEL: test_atomic_store_64
    284 ; CHECK: movq x{{.*}},QWORD
    285 ; CHECK: movq QWORD {{.*}},x{{.*}}
    286 ; CHECK: mfence
    287 ; ARM32-LABEL: test_atomic_store_64
    288 ; ARM32: dmb
    289 ; ARM32: ldrexd r{{[0-9]+}}, r{{[0-9]+}}, [[MEM:.*]]
    290 ; ARM32: strexd [[S:r[0-9]+]], r{{[0-9]+}}, r{{[0-9]+}}, [[MEM]]
    291 ; ARM32: cmp [[S]], #0
    292 ; ARM32: bne
    293 ; ARM32: dmb
    294 ; MIPS32-LABEL: test_atomic_store_64
    295 ; MIPS32: sync
    296 ; MIPS32: jal	__sync_lock_test_and_set_8
    297 ; MIPS32: sync
    298 
    299 define internal void @test_atomic_store_64_const(i32 %iptr) {
    300 entry:
    301   %ptr = inttoptr i32 %iptr to i64*
    302   call void @llvm.nacl.atomic.store.i64(i64 12345678901234, i64* %ptr, i32 6)
    303   ret void
    304 }
    305 ; CHECK-LABEL: test_atomic_store_64_const
    306 ; CHECK: mov {{.*}},0x73ce2ff2
    307 ; CHECK: mov {{.*}},0xb3a
    308 ; CHECK: movq x{{.*}},QWORD
    309 ; CHECK: movq QWORD {{.*}},x{{.*}}
    310 ; CHECK: mfence
    311 ; ARM32-LABEL: test_atomic_store_64_const
    312 ; ARM32: movw [[T0:r[0-9]+]], #12274
    313 ; ARM32: movt [[T0]], #29646
    314 ; ARM32: movw r{{[0-9]+}}, #2874
    315 ; ARM32: dmb
    316 ; ARM32: .L[[RETRY:.*]]:
    317 ; ARM32: ldrexd r{{[0-9]+}}, r{{[0-9]+}}, [[MEM:.*]]
    318 ; ARM32: strexd [[S:r[0-9]+]], r{{[0-9]+}}, r{{[0-9]+}}, [[MEM]]
    319 ; ARM32: cmp [[S]], #0
    320 ; ARM32: bne .L[[RETRY]]
    321 ; ARM32: dmb
    322 ; MIPS32-LABEL: test_atomic_store_64_const
    323 ; MIPS32: sync
    324 ; MIPS32: lui	{{.*}}, 29646
    325 ; MIPS32: ori	{{.*}},{{.*}}, 12274
    326 ; MIPS32: addiu	{{.*}}, $zero, 2874
    327 ; MIPS32: jal	__sync_lock_test_and_set_8
    328 ; MIPS32: sync
    329 
    330 ;;; RMW
    331 
    332 ;; add
    333 
    334 define internal i32 @test_atomic_rmw_add_8(i32 %iptr, i32 %v) {
    335 entry:
    336   %trunc = trunc i32 %v to i8
    337   %ptr = inttoptr i32 %iptr to i8*
    338   ; "1" is an atomic add, and "6" is sequential consistency.
    339   %a = call i8 @llvm.nacl.atomic.rmw.i8(i32 1, i8* %ptr, i8 %trunc, i32 6)
    340   %a_ext = zext i8 %a to i32
    341   ret i32 %a_ext
    342 }
    343 ; CHECK-LABEL: test_atomic_rmw_add_8
    344 ; CHECK: lock xadd BYTE {{.*}},[[REG:.*]]
    345 ; CHECK: {{mov|movzx}} {{.*}},[[REG]]
    346 ; ARM32-LABEL: test_atomic_rmw_add_8
    347 ; ARM32: dmb
    348 ; ARM32: ldrexb
    349 ; ARM32: add
    350 ; ARM32: strexb
    351 ; ARM32: bne
    352 ; ARM32: dmb
    353 ; MIPS32-LABEL: test_atomic_rmw_add_8
    354 ; MIPS32: sync
    355 ; MIPS32: addiu	{{.*}}, $zero, -4
    356 ; MIPS32: and
    357 ; MIPS32: andi	{{.*}}, {{.*}}, 3
    358 ; MIPS32: sll	{{.*}}, {{.*}}, 3
    359 ; MIPS32: ori	{{.*}}, $zero, 255
    360 ; MIPS32: sllv
    361 ; MIPS32: nor
    362 ; MIPS32: sllv
    363 ; MIPS32: ll
    364 ; MIPS32: addu
    365 ; MIPS32: and
    366 ; MIPS32: and
    367 ; MIPS32: or
    368 ; MIPS32: sc
    369 ; MIPS32: beq	{{.*}}, $zero, {{.*}}
    370 ; MIPS32: and
    371 ; MIPS32: srlv
    372 ; MIPS32: sll	{{.*}}, {{.*}}, 24
    373 ; MIPS32: sra	{{.*}}, {{.*}}, 24
    374 ; MIPS32: sync
    375 
    376 define internal i32 @test_atomic_rmw_add_16(i32 %iptr, i32 %v) {
    377 entry:
    378   %trunc = trunc i32 %v to i16
    379   %ptr = inttoptr i32 %iptr to i16*
    380   %a = call i16 @llvm.nacl.atomic.rmw.i16(i32 1, i16* %ptr, i16 %trunc, i32 6)
    381   %a_ext = zext i16 %a to i32
    382   ret i32 %a_ext
    383 }
    384 ; CHECK-LABEL: test_atomic_rmw_add_16
    385 ; CHECK: lock xadd WORD {{.*}},[[REG:.*]]
    386 ; CHECK: {{mov|movzx}} {{.*}},[[REG]]
    387 ; ARM32-LABEL: test_atomic_rmw_add_16
    388 ; ARM32: dmb
    389 ; ARM32: ldrexh
    390 ; ARM32: add
    391 ; ARM32: strexh
    392 ; ARM32: bne
    393 ; ARM32: dmb
    394 ; MIPS32-LABEL: test_atomic_rmw_add_16
    395 ; MIPS32: sync
    396 ; MIPS32: addiu	{{.*}}, $zero, -4
    397 ; MIPS32: and
    398 ; MIPS32: andi	{{.*}}, {{.*}}, 3
    399 ; MIPS32: sll	{{.*}}, {{.*}}, 3
    400 ; MIPS32: ori	{{.*}}, {{.*}}, 65535
    401 ; MIPS32: sllv
    402 ; MIPS32: nor
    403 ; MIPS32: sllv
    404 ; MIPS32: ll
    405 ; MIPS32: addu
    406 ; MIPS32: and
    407 ; MIPS32: and
    408 ; MIPS32: or
    409 ; MIPS32: sc
    410 ; MIPS32: beq	{{.*}}, $zero, {{.*}}
    411 ; MIPS32: and
    412 ; MIPS32: srlv
    413 ; MIPS32: sll	{{.*}}, {{.*}}, 16
    414 ; MIPS32: sra	{{.*}}, {{.*}}, 16
    415 ; MIPS32: sync
    416 
    417 define internal i32 @test_atomic_rmw_add_32(i32 %iptr, i32 %v) {
    418 entry:
    419   %ptr = inttoptr i32 %iptr to i32*
    420   %a = call i32 @llvm.nacl.atomic.rmw.i32(i32 1, i32* %ptr, i32 %v, i32 6)
    421   ret i32 %a
    422 }
    423 ; CHECK-LABEL: test_atomic_rmw_add_32
    424 ; CHECK: lock xadd DWORD {{.*}},[[REG:.*]]
    425 ; CHECK: mov {{.*}},[[REG]]
    426 ; ARM32-LABEL: test_atomic_rmw_add_32
    427 ; ARM32: dmb
    428 ; ARM32: ldrex
    429 ; ARM32: add
    430 ; ARM32: strex
    431 ; ARM32: bne
    432 ; ARM32: dmb
    433 ; MIPS32-LABEL: test_atomic_rmw_add_32
    434 ; MIPS32: sync
    435 ; MIPS32: ll
    436 ; MIPS32: addu
    437 ; MIPS32: sc
    438 ; MIPS32: beq	{{.*}}, $zero, {{.*}}
    439 ; MIPS32: sync
    440 
    441 define internal i64 @test_atomic_rmw_add_64(i32 %iptr, i64 %v) {
    442 entry:
    443   %ptr = inttoptr i32 %iptr to i64*
    444   %a = call i64 @llvm.nacl.atomic.rmw.i64(i32 1, i64* %ptr, i64 %v, i32 6)
    445   ret i64 %a
    446 }
    447 ; CHECK-LABEL: test_atomic_rmw_add_64
    448 ; CHECK: push ebx
    449 ; CHECK: mov eax,DWORD PTR [{{.*}}]
    450 ; CHECK: mov edx,DWORD PTR [{{.*}}+0x4]
    451 ; CHECK: [[LABEL:[^ ]*]]: {{.*}} mov ebx,eax
    452 ; RHS of add cannot be any of the e[abcd]x regs because they are
    453 ; clobbered in the loop, and the RHS needs to be remain live.
    454 ; CHECK: add ebx,{{.*e.[^x]}}
    455 ; CHECK: mov ecx,edx
    456 ; CHECK: adc ecx,{{.*e.[^x]}}
    457 ; Ptr cannot be eax, ebx, ecx, or edx (used up for the expected and desired).
    458 ; It can be esi, edi, or ebp though, for example (so we need to be careful
    459 ; about rejecting eb* and ed*.)
    460 ; CHECK: lock cmpxchg8b QWORD PTR [e{{.[^x]}}
    461 ; CHECK: jne [[LABEL]]
    462 ; ARM32-LABEL: test_atomic_rmw_add_64
    463 ; ARM32: dmb
    464 ; ARM32: ldrexd r{{[0-9]+}}, r{{[0-9]+}}, [r{{[0-9]+}}]
    465 ; ARM32: adds
    466 ; ARM32: adc
    467 ; ARM32: strexd r{{[0-9]+}}, r{{[0-9]+}}, r{{[0-9]+}}, [r{{[0-9]+}}]
    468 ; ARM32: bne
    469 ; ARM32: dmb
    470 ; MIPS32-LABEL: test_atomic_rmw_add_64
    471 ; MIPS32: sync
    472 ; MIPS32: jal	__sync_fetch_and_add_8
    473 ; MIPS32: sync
    474 
    475 ; Same test as above, but with a global address to test FakeUse issues.
    476 define internal i64 @test_atomic_rmw_add_64_global(i64 %v) {
    477 entry:
    478   %ptr = bitcast [8 x i8]* @SzGlobal64 to i64*
    479   %a = call i64 @llvm.nacl.atomic.rmw.i64(i32 1, i64* %ptr, i64 %v, i32 6)
    480   ret i64 %a
    481 }
    482 ; CHECK-LABEL: test_atomic_rmw_add_64_global
    483 ; ARM32-LABEL: test_atomic_rmw_add_64_global
    484 ; ARM32: dmb
    485 ; ARM32: ldrexd r{{[0-9]+}}, r{{[0-9]+}}, [r{{[0-9]+}}]
    486 ; ARM32: adds
    487 ; ARM32: adc
    488 ; ARM32: strexd r{{[0-9]+}}, r{{[0-9]+}}, r{{[0-9]+}}, [r{{[0-9]+}}]
    489 ; ARM32: bne
    490 ; ARM32: dmb
    491 ; MIPS32-LABEL: test_atomic_rmw_add_64_global
    492 ; MIPS32: sync
    493 ; MIPS32: jal	__sync_fetch_and_add_8
    494 ; MIPS32: sync
    495 
    496 ; Test with some more register pressure. When we have an alloca, ebp is
    497 ; used to manage the stack frame, so it cannot be used as a register either.
    498 declare void @use_ptr(i32 %iptr)
    499 
    500 define internal i64 @test_atomic_rmw_add_64_alloca(i32 %iptr, i64 %v) {
    501 entry:
    502   br label %eblock  ; Disable alloca optimization
    503 eblock:
    504   %alloca_ptr = alloca i8, i32 16, align 16
    505   %ptr = inttoptr i32 %iptr to i64*
    506   %old = call i64 @llvm.nacl.atomic.rmw.i64(i32 1, i64* %ptr, i64 %v, i32 6)
    507   store i8 0, i8* %alloca_ptr, align 1
    508   store i8 1, i8* %alloca_ptr, align 1
    509   store i8 2, i8* %alloca_ptr, align 1
    510   store i8 3, i8* %alloca_ptr, align 1
    511   %__5 = ptrtoint i8* %alloca_ptr to i32
    512   call void @use_ptr(i32 %__5)
    513   ret i64 %old
    514 }
    515 ; CHECK-LABEL: test_atomic_rmw_add_64_alloca
    516 ; CHECK: push ebx
    517 ; CHECK-DAG: mov edx
    518 ; CHECK-DAG: mov eax
    519 ; CHECK-DAG: mov ecx
    520 ; CHECK-DAG: mov ebx
    521 ; Ptr cannot be eax, ebx, ecx, or edx (used up for the expected and desired).
    522 ; It also cannot be ebp since we use that for alloca. Also make sure it's
    523 ; not esp, since that's the stack pointer and mucking with it will break
    524 ; the later use_ptr function call.
    525 ; That pretty much leaves esi, or edi as the only viable registers.
    526 ; CHECK: lock cmpxchg8b QWORD PTR [e{{[ds]}}i]
    527 ; CHECK: call {{.*}} R_{{.*}} use_ptr
    528 ; ARM32-LABEL: test_atomic_rmw_add_64_alloca
    529 ; ARM32: dmb
    530 ; ARM32: ldrexd r{{[0-9]+}}, r{{[0-9]+}}, [r{{[0-9]+}}]
    531 ; ARM32: adds
    532 ; ARM32: adc
    533 ; ARM32: strexd r{{[0-9]+}}, r{{[0-9]+}}, r{{[0-9]+}}, [r{{[0-9]+}}]
    534 ; ARM32: bne
    535 ; ARM32: dmb
    536 ; MIPS32-LABEL: test_atomic_rmw_add_64_alloca
    537 ; MIPS32: sync
    538 ; MIPS32: jal	__sync_fetch_and_add_8
    539 ; MIPS32: sync
    540 
    541 define internal i32 @test_atomic_rmw_add_32_ignored(i32 %iptr, i32 %v) {
    542 entry:
    543   %ptr = inttoptr i32 %iptr to i32*
    544   %ignored = call i32 @llvm.nacl.atomic.rmw.i32(i32 1, i32* %ptr, i32 %v, i32 6)
    545   ret i32 %v
    546 }
    547 ; Technically this could use "lock add" instead of "lock xadd", if liveness
    548 ; tells us that the destination variable is dead.
    549 ; CHECK-LABEL: test_atomic_rmw_add_32_ignored
    550 ; CHECK: lock xadd DWORD {{.*}},[[REG:.*]]
    551 ; ARM32-LABEL: test_atomic_rmw_add_32_ignored
    552 ; ARM32: dmb
    553 ; ARM32: ldrex
    554 ; ARM32: add
    555 ; ARM32: strex
    556 ; ARM32: bne
    557 ; ARM32: dmb
    558 ; MIPS32-LABEL: test_atomic_rmw_add_32_ignored
    559 ; MIPS32: sync
    560 ; MIPS32: ll
    561 ; MIPS32: addu
    562 ; MIPS32: sc
    563 ; MIPS32: beq	{{.*}}, $zero, {{.*}}
    564 ; MIPS32: sync
    565 
    566 ; Atomic RMW 64 needs to be expanded into its own loop.
    567 ; Make sure that works w/ non-trivial function bodies.
    568 define internal i64 @test_atomic_rmw_add_64_loop(i32 %iptr, i64 %v) {
    569 entry:
    570   %x = icmp ult i64 %v, 100
    571   br i1 %x, label %err, label %loop
    572 
    573 loop:
    574   %v_next = phi i64 [ %v, %entry ], [ %next, %loop ]
    575   %ptr = inttoptr i32 %iptr to i64*
    576   %next = call i64 @llvm.nacl.atomic.rmw.i64(i32 1, i64* %ptr, i64 %v_next, i32 6)
    577   %success = icmp eq i64 %next, 100
    578   br i1 %success, label %done, label %loop
    579 
    580 done:
    581   ret i64 %next
    582 
    583 err:
    584   ret i64 0
    585 }
    586 ; CHECK-LABEL: test_atomic_rmw_add_64_loop
    587 ; CHECK: push ebx
    588 ; CHECK: mov eax,DWORD PTR [{{.*}}]
    589 ; CHECK: mov edx,DWORD PTR [{{.*}}+0x4]
    590 ; CHECK: [[LABEL:[^ ]*]]: {{.*}} mov ebx,eax
    591 ; CHECK: add ebx,{{.*e.[^x]}}
    592 ; CHECK: mov ecx,edx
    593 ; CHECK: adc ecx,{{.*e.[^x]}}
    594 ; CHECK: lock cmpxchg8b QWORD PTR [e{{.[^x]}}+0x0]
    595 ; CHECK: jne [[LABEL]]
    596 ; ARM32-LABEL: test_atomic_rmw_add_64_loop
    597 ; ARM32: dmb
    598 ; ARM32: ldrexd r{{[0-9]+}}, r{{[0-9]+}}, [r{{[0-9]+}}]
    599 ; ARM32: adds
    600 ; ARM32: adc
    601 ; ARM32: strexd r{{[0-9]+}}, r{{[0-9]+}}, r{{[0-9]+}}, [r{{[0-9]+}}]
    602 ; ARM32: bne
    603 ; ARM32: dmb
    604 ; ARM32: b
    605 ; MIPS32-LABEL: test_atomic_rmw_add_64_loop
    606 ; MIPS32: sync
    607 ; MIPS32: jal	__sync_fetch_and_add_8
    608 ; MIPS32: sync
    609 
    610 ;; sub
    611 
    612 define internal i32 @test_atomic_rmw_sub_8(i32 %iptr, i32 %v) {
    613 entry:
    614   %trunc = trunc i32 %v to i8
    615   %ptr = inttoptr i32 %iptr to i8*
    616   %a = call i8 @llvm.nacl.atomic.rmw.i8(i32 2, i8* %ptr, i8 %trunc, i32 6)
    617   %a_ext = zext i8 %a to i32
    618   ret i32 %a_ext
    619 }
    620 ; CHECK-LABEL: test_atomic_rmw_sub_8
    621 ; CHECK: neg [[REG:.*]]
    622 ; CHECK: lock xadd BYTE {{.*}},[[REG]]
    623 ; CHECK: {{mov|movzx}} {{.*}},[[REG]]
    624 ; ARM32-LABEL: test_atomic_rmw_sub_8
    625 ; ARM32: dmb
    626 ; ARM32: ldrexb
    627 ; ARM32: sub
    628 ; ARM32: strexb
    629 ; ARM32: bne
    630 ; ARM32: dmb
    631 ; MIPS32-LABEL: test_atomic_rmw_sub_8
    632 ; MIPS32: sync
    633 ; MIPS32: addiu	{{.*}}, $zero, -4
    634 ; MIPS32: and
    635 ; MIPS32: andi	{{.*}}, {{.*}}, 3
    636 ; MIPS32: sll	{{.*}}, {{.*}}, 3
    637 ; MIPS32: ori	{{.*}}, $zero, 255
    638 ; MIPS32: sllv
    639 ; MIPS32: nor
    640 ; MIPS32: sllv
    641 ; MIPS32: ll
    642 ; MIPS32: subu
    643 ; MIPS32: and
    644 ; MIPS32: and
    645 ; MIPS32: or
    646 ; MIPS32: sc
    647 ; MIPS32: beq	{{.*}}, $zero, {{.*}}
    648 ; MIPS32: and
    649 ; MIPS32: srlv
    650 ; MIPS32: sll	{{.*}}, {{.*}}, 24
    651 ; MIPS32: sra	{{.*}}, {{.*}}, 24
    652 ; MIPS32: sync
    653 
    654 define internal i32 @test_atomic_rmw_sub_16(i32 %iptr, i32 %v) {
    655 entry:
    656   %trunc = trunc i32 %v to i16
    657   %ptr = inttoptr i32 %iptr to i16*
    658   %a = call i16 @llvm.nacl.atomic.rmw.i16(i32 2, i16* %ptr, i16 %trunc, i32 6)
    659   %a_ext = zext i16 %a to i32
    660   ret i32 %a_ext
    661 }
    662 ; CHECK-LABEL: test_atomic_rmw_sub_16
    663 ; CHECK: neg [[REG:.*]]
    664 ; CHECK: lock xadd WORD {{.*}},[[REG]]
    665 ; CHECK: {{mov|movzx}} {{.*}},[[REG]]
    666 ; ARM32-LABEL: test_atomic_rmw_sub_16
    667 ; ARM32: dmb
    668 ; ARM32: ldrexh
    669 ; ARM32: sub
    670 ; ARM32: strexh
    671 ; ARM32: bne
    672 ; ARM32: dmb
    673 ; MIPS32-LABEL: test_atomic_rmw_sub_16
    674 ; MIPS32: sync
    675 ; MIPS32: addiu	{{.*}}, $zero, -4
    676 ; MIPS32: and
    677 ; MIPS32: andi	{{.*}}, {{.*}}, 3
    678 ; MIPS32: sll	{{.*}}, {{.*}}, 3
    679 ; MIPS32: ori	{{.*}}, {{.*}}, 65535
    680 ; MIPS32: sllv
    681 ; MIPS32: nor
    682 ; MIPS32: sllv
    683 ; MIPS32: ll
    684 ; MIPS32: subu
    685 ; MIPS32: and
    686 ; MIPS32: and
    687 ; MIPS32: or
    688 ; MIPS32: sc
    689 ; MIPS32: beq	{{.*}}, $zero, {{.*}}
    690 ; MIPS32: and
    691 ; MIPS32: srlv
    692 ; MIPS32: sll	{{.*}}, {{.*}}, 16
    693 ; MIPS32: sra	{{.*}}, {{.*}}, 16
    694 ; MIPS32: sync
    695 
    696 define internal i32 @test_atomic_rmw_sub_32(i32 %iptr, i32 %v) {
    697 entry:
    698   %ptr = inttoptr i32 %iptr to i32*
    699   %a = call i32 @llvm.nacl.atomic.rmw.i32(i32 2, i32* %ptr, i32 %v, i32 6)
    700   ret i32 %a
    701 }
    702 ; CHECK-LABEL: test_atomic_rmw_sub_32
    703 ; CHECK: neg [[REG:.*]]
    704 ; CHECK: lock xadd DWORD {{.*}},[[REG]]
    705 ; CHECK: mov {{.*}},[[REG]]
    706 ; ARM32-LABEL: test_atomic_rmw_sub_32
    707 ; ARM32: dmb
    708 ; ARM32: ldrex
    709 ; ARM32: sub
    710 ; ARM32: strex
    711 ; ARM32: bne
    712 ; ARM32: dmb
    713 ; MIPS32-LABEL: test_atomic_rmw_sub_32
    714 ; MIPS32: sync
    715 ; MIPS32: ll
    716 ; MIPS32: subu
    717 ; MIPS32: sc
    718 ; MIPS32: beq	{{.*}}, $zero, {{.*}}
    719 ; MIPS32: sync
    720 
    721 define internal i64 @test_atomic_rmw_sub_64(i32 %iptr, i64 %v) {
    722 entry:
    723   %ptr = inttoptr i32 %iptr to i64*
    724   %a = call i64 @llvm.nacl.atomic.rmw.i64(i32 2, i64* %ptr, i64 %v, i32 6)
    725   ret i64 %a
    726 }
    727 ; CHECK-LABEL: test_atomic_rmw_sub_64
    728 ; CHECK: push ebx
    729 ; CHECK: mov eax,DWORD PTR [{{.*}}]
    730 ; CHECK: mov edx,DWORD PTR [{{.*}}+0x4]
    731 ; CHECK: [[LABEL:[^ ]*]]: {{.*}} mov ebx,eax
    732 ; CHECK: sub ebx,{{.*e.[^x]}}
    733 ; CHECK: mov ecx,edx
    734 ; CHECK: sbb ecx,{{.*e.[^x]}}
    735 ; CHECK: lock cmpxchg8b QWORD PTR [e{{.[^x]}}
    736 ; CHECK: jne [[LABEL]]
    737 ; ARM32-LABEL: test_atomic_rmw_sub_64
    738 ; ARM32: dmb
    739 ; ARM32: ldrexd r{{[0-9]+}}, r{{[0-9]+}}, [r{{[0-9]+}}]
    740 ; ARM32: subs
    741 ; ARM32: sbc
    742 ; ARM32: strexd r{{[0-9]+}}, r{{[0-9]+}}, r{{[0-9]+}}, [r{{[0-9]+}}]
    743 ; ARM32: bne
    744 ; ARM32: dmb
    745 ; MIPS32-LABEL: test_atomic_rmw_sub_64
    746 ; MIPS32: sync
    747 ; MIPS32: jal	__sync_fetch_and_sub_8
    748 ; MIPS32: sync
    749 
    750 define internal i32 @test_atomic_rmw_sub_32_ignored(i32 %iptr, i32 %v) {
    751 entry:
    752   %ptr = inttoptr i32 %iptr to i32*
    753   %ignored = call i32 @llvm.nacl.atomic.rmw.i32(i32 2, i32* %ptr, i32 %v, i32 6)
    754   ret i32 %v
    755 }
    756 ; Could use "lock sub" instead of "neg; lock xadd"
    757 ; CHECK-LABEL: test_atomic_rmw_sub_32_ignored
    758 ; CHECK: neg [[REG:.*]]
    759 ; CHECK: lock xadd DWORD {{.*}},[[REG]]
    760 ; ARM32-LABEL: test_atomic_rmw_sub_32_ignored
    761 ; ARM32: dmb
    762 ; ARM32: ldrex
    763 ; ARM32: sub
    764 ; ARM32: strex
    765 ; ARM32: bne
    766 ; ARM32: dmb
    767 ; MIPS32-LABEL: test_atomic_rmw_sub_32_ignored
    768 ; MIPS32: sync
    769 ; MIPS32: ll
    770 ; MIPS32: subu
    771 ; MIPS32: sc
    772 ; MIPS32: beq	{{.*}}, $zero, {{.*}}
    773 ; MIPS32: sync
    774 
    775 ;; or
    776 
    777 define internal i32 @test_atomic_rmw_or_8(i32 %iptr, i32 %v) {
    778 entry:
    779   %trunc = trunc i32 %v to i8
    780   %ptr = inttoptr i32 %iptr to i8*
    781   %a = call i8 @llvm.nacl.atomic.rmw.i8(i32 3, i8* %ptr, i8 %trunc, i32 6)
    782   %a_ext = zext i8 %a to i32
    783   ret i32 %a_ext
    784 }
    785 ; CHECK-LABEL: test_atomic_rmw_or_8
    786 ; CHECK: mov al,BYTE PTR
    787 ; Dest cannot be eax here, because eax is used for the old value. Also want
    788 ; to make sure that cmpxchg's source is the same register.
    789 ; CHECK: or [[REG:[^a].]]
    790 ; CHECK: lock cmpxchg BYTE PTR [e{{[^a].}}],[[REG]]
    791 ; CHECK: jne
    792 ; ARM32-LABEL: test_atomic_rmw_or_8
    793 ; ARM32: dmb
    794 ; ARM32: ldrexb
    795 ; ARM32: orr
    796 ; ARM32: strexb
    797 ; ARM32: bne
    798 ; ARM32: dmb
    799 ; MIPS32-LABEL: test_atomic_rmw_or_8
    800 ; MIPS32: sync
    801 ; MIPS32: addiu	{{.*}}, $zero, -4
    802 ; MIPS32: and
    803 ; MIPS32: andi	{{.*}}, {{.*}}, 3
    804 ; MIPS32: sll	{{.*}}, {{.*}}, 3
    805 ; MIPS32: ori	{{.*}}, $zero, 255
    806 ; MIPS32: sllv
    807 ; MIPS32: nor
    808 ; MIPS32: sllv
    809 ; MIPS32: ll
    810 ; MIPS32: or
    811 ; MIPS32: and
    812 ; MIPS32: and
    813 ; MIPS32: or
    814 ; MIPS32: sc
    815 ; MIPS32: beq	{{.*}}, $zero, {{.*}}
    816 ; MIPS32: and
    817 ; MIPS32: srlv
    818 ; MIPS32: sll	{{.*}}, {{.*}}, 24
    819 ; MIPS32: sra	{{.*}}, {{.*}}, 24
    820 ; MIPS32: sync
    821 
    822 ; Same test as above, but with a global address to test FakeUse issues.
    823 define internal i32 @test_atomic_rmw_or_8_global(i32 %v) {
    824 entry:
    825   %trunc = trunc i32 %v to i8
    826   %ptr = bitcast [1 x i8]* @SzGlobal8 to i8*
    827   %a = call i8 @llvm.nacl.atomic.rmw.i8(i32 3, i8* %ptr, i8 %trunc, i32 6)
    828   %a_ext = zext i8 %a to i32
    829   ret i32 %a_ext
    830 }
    831 ; CHECK-LABEL: test_atomic_rmw_or_8_global
    832 ; ARM32-LABEL: test_atomic_rmw_or_8_global
    833 ; ARM32: dmb
    834 ; ARM32: movw [[PTR:r[0-9]+]], #:lower16:SzGlobal8
    835 ; ARM32: movt [[PTR]], #:upper16:SzGlobal8
    836 ; ARM32: ldrexb r{{[0-9]+}}, {{[[]}}[[PTR]]{{[]]}}
    837 ; ARM32: orr
    838 ; ARM32: strexb
    839 ; ARM32: bne
    840 ; ARM32: dmb
    841 ; MIPS32-LABEL: test_atomic_rmw_or_8_global
    842 ; MIPS32: sync
    843 ; MIPS32: addiu	{{.*}}, $zero, -4
    844 ; MIPS32: and
    845 ; MIPS32: andi	{{.*}}, {{.*}}, 3
    846 ; MIPS32: sll	{{.*}}, {{.*}}, 3
    847 ; MIPS32: ori	{{.*}}, $zero, 255
    848 ; MIPS32: sllv
    849 ; MIPS32: nor
    850 ; MIPS32: sllv
    851 ; MIPS32: ll
    852 ; MIPS32: or
    853 ; MIPS32: and
    854 ; MIPS32: and
    855 ; MIPS32: or
    856 ; MIPS32: sc
    857 ; MIPS32: beq	{{.*}}, $zero, {{.*}}
    858 ; MIPS32: and
    859 ; MIPS32: srlv
    860 ; MIPS32: sll	{{.*}}, {{.*}}, 24
    861 ; MIPS32: sra	{{.*}}, {{.*}}, 24
    862 ; MIPS32: sync
    863 
    864 define internal i32 @test_atomic_rmw_or_16(i32 %iptr, i32 %v) {
    865 entry:
    866   %trunc = trunc i32 %v to i16
    867   %ptr = inttoptr i32 %iptr to i16*
    868   %a = call i16 @llvm.nacl.atomic.rmw.i16(i32 3, i16* %ptr, i16 %trunc, i32 6)
    869   %a_ext = zext i16 %a to i32
    870   ret i32 %a_ext
    871 }
    872 ; CHECK-LABEL: test_atomic_rmw_or_16
    873 ; CHECK: mov ax,WORD PTR
    874 ; CHECK: or [[REG:[^a].]]
    875 ; CHECK: lock cmpxchg WORD PTR [e{{[^a].}}],[[REG]]
    876 ; CHECK: jne
    877 ; ARM32-LABEL: test_atomic_rmw_or_16
    878 ; ARM32: dmb
    879 ; ARM32: ldrexh
    880 ; ARM32: orr
    881 ; ARM32: strexh
    882 ; ARM32: bne
    883 ; ARM32: dmb
    884 ; MIPS32-LABEL: test_atomic_rmw_or_16
    885 ; MIPS32: sync
    886 ; MIPS32: addiu	{{.*}}, $zero, -4
    887 ; MIPS32: and
    888 ; MIPS32: andi	{{.*}}, {{.*}}, 3
    889 ; MIPS32: sll	{{.*}}, {{.*}}, 3
    890 ; MIPS32: ori	{{.*}}, {{.*}}, 65535
    891 ; MIPS32: sllv
    892 ; MIPS32: nor
    893 ; MIPS32: sllv
    894 ; MIPS32: ll
    895 ; MIPS32: or
    896 ; MIPS32: and
    897 ; MIPS32: and
    898 ; MIPS32: or
    899 ; MIPS32: sc
    900 ; MIPS32: beq	{{.*}}, $zero, {{.*}}
    901 ; MIPS32: and
    902 ; MIPS32: srlv
    903 ; MIPS32: sll	{{.*}}, {{.*}}, 16
    904 ; MIPS32: sra	{{.*}}, {{.*}}, 16
    905 ; MIPS32: sync
    906 
    907 ; Same test as above, but with a global address to test FakeUse issues.
    908 define internal i32 @test_atomic_rmw_or_16_global(i32 %v) {
    909 entry:
    910   %trunc = trunc i32 %v to i16
    911   %ptr = bitcast [2 x i8]* @SzGlobal16 to i16*
    912   %a = call i16 @llvm.nacl.atomic.rmw.i16(i32 3, i16* %ptr, i16 %trunc, i32 6)
    913   %a_ext = zext i16 %a to i32
    914   ret i32 %a_ext
    915 }
    916 ; CHECK-LABEL: test_atomic_rmw_or_16_global
    917 ; ARM32-LABEL: test_atomic_rmw_or_16_global
    918 ; ARM32: dmb
    919 ; ARM32: movw [[PTR:r[0-9]+]], #:lower16:SzGlobal16
    920 ; ARM32: movt [[PTR]], #:upper16:SzGlobal16
    921 ; ARM32: ldrexh r{{[0-9]+}}, {{[[]}}[[PTR]]{{[]]}}
    922 ; ARM32: orr
    923 ; ARM32: strexh
    924 ; ARM32: bne
    925 ; ARM32: dmb
    926 ; MIPS32-LABEL: test_atomic_rmw_or_16_global
    927 ; MIPS32: sync
    928 ; MIPS32: addiu	{{.*}}, $zero, -4
    929 ; MIPS32: and
    930 ; MIPS32: andi	{{.*}}, {{.*}}, 3
    931 ; MIPS32: sll	{{.*}}, {{.*}}, 3
    932 ; MIPS32: ori	{{.*}}, {{.*}}, 65535
    933 ; MIPS32: sllv
    934 ; MIPS32: nor
    935 ; MIPS32: sllv
    936 ; MIPS32: ll
    937 ; MIPS32: or
    938 ; MIPS32: and
    939 ; MIPS32: and
    940 ; MIPS32: or
    941 ; MIPS32: sc
    942 ; MIPS32: beq	{{.*}}, $zero, {{.*}}
    943 ; MIPS32: and
    944 ; MIPS32: srlv
    945 ; MIPS32: sll	{{.*}}, {{.*}}, 16
    946 ; MIPS32: sra	{{.*}}, {{.*}}, 16
    947 ; MIPS32: sync
    948 
    949 define internal i32 @test_atomic_rmw_or_32(i32 %iptr, i32 %v) {
    950 entry:
    951   %ptr = inttoptr i32 %iptr to i32*
    952   %a = call i32 @llvm.nacl.atomic.rmw.i32(i32 3, i32* %ptr, i32 %v, i32 6)
    953   ret i32 %a
    954 }
    955 ; CHECK-LABEL: test_atomic_rmw_or_32
    956 ; CHECK: mov eax,DWORD PTR
    957 ; CHECK: or [[REG:e[^a].]]
    958 ; CHECK: lock cmpxchg DWORD PTR [e{{[^a].}}],[[REG]]
    959 ; CHECK: jne
    960 ; ARM32-LABEL: test_atomic_rmw_or_32
    961 ; ARM32: dmb
    962 ; ARM32: ldrex
    963 ; ARM32: orr
    964 ; ARM32: strex
    965 ; ARM32: bne
    966 ; ARM32: dmb
    967 ; MIPS32-LABEL: test_atomic_rmw_or_32
    968 ; MIPS32: sync
    969 ; MIPS32: ll
    970 ; MIPS32: or
    971 ; MIPS32: sc
    972 ; MIPS32: beq	{{.*}}, $zero, {{.*}}
    973 ; MIPS32: sync
    974 
    975 ; Same test as above, but with a global address to test FakeUse issues.
    976 define internal i32 @test_atomic_rmw_or_32_global(i32 %v) {
    977 entry:
    978   %ptr = bitcast [4 x i8]* @SzGlobal32 to i32*
    979   %a = call i32 @llvm.nacl.atomic.rmw.i32(i32 3, i32* %ptr, i32 %v, i32 6)
    980   ret i32 %a
    981 }
    982 ; CHECK-LABEL: test_atomic_rmw_or_32_global
    983 ; ARM32-LABEL: test_atomic_rmw_or_32_global
    984 ; ARM32: dmb
    985 ; ARM32: movw [[PTR:r[0-9]+]], #:lower16:SzGlobal32
    986 ; ARM32: movt [[PTR]], #:upper16:SzGlobal32
    987 ; ARM32: ldrex r{{[0-9]+}}, {{[[]}}[[PTR]]{{[]]}}
    988 ; ARM32: orr
    989 ; ARM32: strex
    990 ; ARM32: bne
    991 ; ARM32: dmb
    992 ; MIPS32-LABEL: test_atomic_rmw_or_32_global
    993 ; MIPS32: sync
    994 ; MIPS32: ll
    995 ; MIPS32: or
    996 ; MIPS32: sc
    997 ; MIPS32: beq	{{.*}}, $zero, {{.*}}
    998 ; MIPS32: sync
    999 
   1000 define internal i64 @test_atomic_rmw_or_64(i32 %iptr, i64 %v) {
   1001 entry:
   1002   %ptr = inttoptr i32 %iptr to i64*
   1003   %a = call i64 @llvm.nacl.atomic.rmw.i64(i32 3, i64* %ptr, i64 %v, i32 6)
   1004   ret i64 %a
   1005 }
   1006 ; CHECK-LABEL: test_atomic_rmw_or_64
   1007 ; CHECK: push ebx
   1008 ; CHECK: mov eax,DWORD PTR [{{.*}}]
   1009 ; CHECK: mov edx,DWORD PTR [{{.*}}+0x4]
   1010 ; CHECK: [[LABEL:[^ ]*]]: {{.*}} mov ebx,eax
   1011 ; CHECK: or ebx,{{.*e.[^x]}}
   1012 ; CHECK: mov ecx,edx
   1013 ; CHECK: or ecx,{{.*e.[^x]}}
   1014 ; CHECK: lock cmpxchg8b QWORD PTR [e{{.[^x]}}
   1015 ; CHECK: jne [[LABEL]]
   1016 ; ARM32-LABEL: test_atomic_rmw_or_64
   1017 ; ARM32: dmb
   1018 ; ARM32: ldrexd r{{[0-9]+}}, r{{[0-9]+}}, [r{{[0-9]+}}]
   1019 ; ARM32: orr
   1020 ; ARM32: orr
   1021 ; ARM32: strexd r{{[0-9]+}}, r{{[0-9]+}}, r{{[0-9]+}}, [r{{[0-9]+}}]
   1022 ; ARM32: bne
   1023 ; ARM32: dmb
   1024 ; MIPS32-LABEL: test_atomic_rmw_or_64
   1025 ; MIPS32: sync
   1026 ; MIPS32: jal	__sync_fetch_and_or_8
   1027 ; MIPS32: sync
   1028 
   1029 define internal i32 @test_atomic_rmw_or_32_ignored(i32 %iptr, i32 %v) {
   1030 entry:
   1031   %ptr = inttoptr i32 %iptr to i32*
   1032   %ignored = call i32 @llvm.nacl.atomic.rmw.i32(i32 3, i32* %ptr, i32 %v, i32 6)
   1033   ret i32 %v
   1034 }
   1035 ; CHECK-LABEL: test_atomic_rmw_or_32_ignored
   1036 ; Could just "lock or", if we inspect the liveness information first.
   1037 ; Would also need a way to introduce "lock"'edness to binary
   1038 ; operators without introducing overhead on the more common binary ops.
   1039 ; CHECK: mov eax,DWORD PTR
   1040 ; CHECK: or [[REG:e[^a].]]
   1041 ; CHECK: lock cmpxchg DWORD PTR [e{{[^a].}}],[[REG]]
   1042 ; CHECK: jne
   1043 ; ARM32-LABEL: test_atomic_rmw_or_32_ignored
   1044 ; ARM32: dmb
   1045 ; ARM32: ldrex
   1046 ; ARM32: orr
   1047 ; ARM32: strex
   1048 ; ARM32: bne
   1049 ; ARM32: dmb
   1050 ; MIPS32-LABEL: test_atomic_rmw_or_32_ignored
   1051 ; MIPS32: sync
   1052 ; MIPS32: ll
   1053 ; MIPS32: or
   1054 ; MIPS32: sc
   1055 ; MIPS32: beq	{{.*}}, $zero, {{.*}}
   1056 ; MIPS32: sync
   1057 
   1058 ;; and
   1059 
   1060 define internal i32 @test_atomic_rmw_and_8(i32 %iptr, i32 %v) {
   1061 entry:
   1062   %trunc = trunc i32 %v to i8
   1063   %ptr = inttoptr i32 %iptr to i8*
   1064   %a = call i8 @llvm.nacl.atomic.rmw.i8(i32 4, i8* %ptr, i8 %trunc, i32 6)
   1065   %a_ext = zext i8 %a to i32
   1066   ret i32 %a_ext
   1067 }
   1068 ; CHECK-LABEL: test_atomic_rmw_and_8
   1069 ; CHECK: mov al,BYTE PTR
   1070 ; CHECK: and [[REG:[^a].]]
   1071 ; CHECK: lock cmpxchg BYTE PTR [e{{[^a].}}],[[REG]]
   1072 ; CHECK: jne
   1073 ; ARM32-LABEL: test_atomic_rmw_and_8
   1074 ; ARM32: dmb
   1075 ; ARM32: ldrexb
   1076 ; ARM32: and
   1077 ; ARM32: strexb
   1078 ; ARM32: bne
   1079 ; ARM32: dmb
   1080 ; MIPS32-LABEL: test_atomic_rmw_and_8
   1081 ; MIPS32: sync
   1082 ; MIPS32: addiu	{{.*}}, $zero, -4
   1083 ; MIPS32: and
   1084 ; MIPS32: andi	{{.*}}, {{.*}}, 3
   1085 ; MIPS32: sll	{{.*}}, {{.*}}, 3
   1086 ; MIPS32: ori	{{.*}}, $zero, 255
   1087 ; MIPS32: sllv
   1088 ; MIPS32: nor
   1089 ; MIPS32: sllv
   1090 ; MIPS32: ll
   1091 ; MIPS32: and
   1092 ; MIPS32: and
   1093 ; MIPS32: and
   1094 ; MIPS32: or
   1095 ; MIPS32: sc
   1096 ; MIPS32: beq	{{.*}}, $zero, {{.*}}
   1097 ; MIPS32: and
   1098 ; MIPS32: srlv
   1099 ; MIPS32: sll	{{.*}}, {{.*}}, 24
   1100 ; MIPS32: sra	{{.*}}, {{.*}}, 24
   1101 ; MIPS32: sync
   1102 
   1103 define internal i32 @test_atomic_rmw_and_16(i32 %iptr, i32 %v) {
   1104 entry:
   1105   %trunc = trunc i32 %v to i16
   1106   %ptr = inttoptr i32 %iptr to i16*
   1107   %a = call i16 @llvm.nacl.atomic.rmw.i16(i32 4, i16* %ptr, i16 %trunc, i32 6)
   1108   %a_ext = zext i16 %a to i32
   1109   ret i32 %a_ext
   1110 }
   1111 ; CHECK-LABEL: test_atomic_rmw_and_16
   1112 ; CHECK: mov ax,WORD PTR
   1113 ; CHECK: and
   1114 ; CHECK: lock cmpxchg WORD PTR [e{{[^a].}}]
   1115 ; CHECK: jne
   1116 ; ARM32-LABEL: test_atomic_rmw_and_16
   1117 ; ARM32: dmb
   1118 ; ARM32: ldrexh
   1119 ; ARM32: and
   1120 ; ARM32: strexh
   1121 ; ARM32: bne
   1122 ; ARM32: dmb
   1123 ; MIPS32-LABEL: test_atomic_rmw_and_16
   1124 ; MIPS32: sync
   1125 ; MIPS32: addiu	{{.*}}, $zero, -4
   1126 ; MIPS32: and
   1127 ; MIPS32: andi	{{.*}}, {{.*}}, 3
   1128 ; MIPS32: sll	{{.*}}, {{.*}}, 3
   1129 ; MIPS32: ori	{{.*}}, {{.*}}, 65535
   1130 ; MIPS32: sllv
   1131 ; MIPS32: nor
   1132 ; MIPS32: sllv
   1133 ; MIPS32: ll
   1134 ; MIPS32: and
   1135 ; MIPS32: and
   1136 ; MIPS32: and
   1137 ; MIPS32: or
   1138 ; MIPS32: sc
   1139 ; MIPS32: beq	{{.*}}, $zero, {{.*}}
   1140 ; MIPS32: and
   1141 ; MIPS32: srlv
   1142 ; MIPS32: sll	{{.*}}, {{.*}}, 16
   1143 ; MIPS32: sra	{{.*}}, {{.*}}, 16
   1144 ; MIPS32: sync
   1145 
   1146 define internal i32 @test_atomic_rmw_and_32(i32 %iptr, i32 %v) {
   1147 entry:
   1148   %ptr = inttoptr i32 %iptr to i32*
   1149   %a = call i32 @llvm.nacl.atomic.rmw.i32(i32 4, i32* %ptr, i32 %v, i32 6)
   1150   ret i32 %a
   1151 }
   1152 ; CHECK-LABEL: test_atomic_rmw_and_32
   1153 ; CHECK: mov eax,DWORD PTR
   1154 ; CHECK: and
   1155 ; CHECK: lock cmpxchg DWORD PTR [e{{[^a].}}]
   1156 ; CHECK: jne
   1157 ; ARM32-LABEL: test_atomic_rmw_and_32
   1158 ; ARM32: dmb
   1159 ; ARM32: ldrex
   1160 ; ARM32: and
   1161 ; ARM32: strex
   1162 ; ARM32: bne
   1163 ; ARM32: dmb
   1164 ; MIPS32-LABEL: test_atomic_rmw_and_32
   1165 ; MIPS32: sync
   1166 ; MIPS32: ll
   1167 ; MIPS32: and
   1168 ; MIPS32: sc
   1169 ; MIPS32: beq	{{.*}}, $zero, {{.*}}
   1170 ; MIPS32: sync
   1171 
   1172 define internal i64 @test_atomic_rmw_and_64(i32 %iptr, i64 %v) {
   1173 entry:
   1174   %ptr = inttoptr i32 %iptr to i64*
   1175   %a = call i64 @llvm.nacl.atomic.rmw.i64(i32 4, i64* %ptr, i64 %v, i32 6)
   1176   ret i64 %a
   1177 }
   1178 ; CHECK-LABEL: test_atomic_rmw_and_64
   1179 ; CHECK: push ebx
   1180 ; CHECK: mov eax,DWORD PTR [{{.*}}]
   1181 ; CHECK: mov edx,DWORD PTR [{{.*}}+0x4]
   1182 ; CHECK: [[LABEL:[^ ]*]]: {{.*}} mov ebx,eax
   1183 ; CHECK: and ebx,{{.*e.[^x]}}
   1184 ; CHECK: mov ecx,edx
   1185 ; CHECK: and ecx,{{.*e.[^x]}}
   1186 ; CHECK: lock cmpxchg8b QWORD PTR [e{{.[^x]}}
   1187 ; CHECK: jne [[LABEL]]
   1188 ; ARM32-LABEL: test_atomic_rmw_and_64
   1189 ; ARM32: dmb
   1190 ; ARM32: ldrexd r{{[0-9]+}}, r{{[0-9]+}}, [r{{[0-9]+}}]
   1191 ; ARM32: and
   1192 ; ARM32: and
   1193 ; ARM32: strexd r{{[0-9]+}}, r{{[0-9]+}}, r{{[0-9]+}}, [r{{[0-9]+}}]
   1194 ; ARM32: bne
   1195 ; ARM32: dmb
   1196 ; MIPS32-LABEL: test_atomic_rmw_and_64
   1197 ; MIPS32: sync
   1198 ; MIPS32: jal	__sync_fetch_and_and_8
   1199 ; MIPS32: sync
   1200 
   1201 define internal i32 @test_atomic_rmw_and_32_ignored(i32 %iptr, i32 %v) {
   1202 entry:
   1203   %ptr = inttoptr i32 %iptr to i32*
   1204   %ignored = call i32 @llvm.nacl.atomic.rmw.i32(i32 4, i32* %ptr, i32 %v, i32 6)
   1205   ret i32 %v
   1206 }
   1207 ; CHECK-LABEL: test_atomic_rmw_and_32_ignored
   1208 ; Could just "lock and"
   1209 ; CHECK: mov eax,DWORD PTR
   1210 ; CHECK: and
   1211 ; CHECK: lock cmpxchg DWORD PTR [e{{[^a].}}]
   1212 ; CHECK: jne
   1213 ; ARM32-LABEL: test_atomic_rmw_and_32_ignored
   1214 ; ARM32: dmb
   1215 ; ARM32: ldrex
   1216 ; ARM32: and
   1217 ; ARM32: strex
   1218 ; ARM32: bne
   1219 ; ARM32: dmb
   1220 ; MIPS32-LABEL: test_atomic_rmw_and_32_ignored
   1221 ; MIPS32: sync
   1222 ; MIPS32: ll
   1223 ; MIPS32: and
   1224 ; MIPS32: sc
   1225 ; MIPS32: beq	{{.*}}, $zero, {{.*}}
   1226 ; MIPS32: sync
   1227 
   1228 ;; xor
   1229 
   1230 define internal i32 @test_atomic_rmw_xor_8(i32 %iptr, i32 %v) {
   1231 entry:
   1232   %trunc = trunc i32 %v to i8
   1233   %ptr = inttoptr i32 %iptr to i8*
   1234   %a = call i8 @llvm.nacl.atomic.rmw.i8(i32 5, i8* %ptr, i8 %trunc, i32 6)
   1235   %a_ext = zext i8 %a to i32
   1236   ret i32 %a_ext
   1237 }
   1238 ; CHECK-LABEL: test_atomic_rmw_xor_8
   1239 ; CHECK: mov al,BYTE PTR
   1240 ; CHECK: xor [[REG:[^a].]]
   1241 ; CHECK: lock cmpxchg BYTE PTR [e{{[^a].}}],[[REG]]
   1242 ; CHECK: jne
   1243 ; ARM32-LABEL: test_atomic_rmw_xor_8
   1244 ; ARM32: dmb
   1245 ; ARM32: ldrexb
   1246 ; ARM32: eor
   1247 ; ARM32: strexb
   1248 ; ARM32: bne
   1249 ; ARM32: dmb
   1250 ; MIPS32-LABEL: test_atomic_rmw_xor_8
   1251 ; MIPS32: sync
   1252 ; MIPS32: addiu	{{.*}}, $zero, -4
   1253 ; MIPS32: and
   1254 ; MIPS32: andi	{{.*}}, {{.*}}, 3
   1255 ; MIPS32: sll	{{.*}}, {{.*}}, 3
   1256 ; MIPS32: ori	{{.*}}, $zero, 255
   1257 ; MIPS32: sllv
   1258 ; MIPS32: nor
   1259 ; MIPS32: sllv
   1260 ; MIPS32: ll
   1261 ; MIPS32: xor
   1262 ; MIPS32: and
   1263 ; MIPS32: and
   1264 ; MIPS32: or
   1265 ; MIPS32: sc
   1266 ; MIPS32: beq	{{.*}}, $zero, {{.*}}
   1267 ; MIPS32: and
   1268 ; MIPS32: srlv
   1269 ; MIPS32: sll	{{.*}}, {{.*}}, 24
   1270 ; MIPS32: sra	{{.*}}, {{.*}}, 24
   1271 ; MIPS32: sync
   1272 
   1273 define internal i32 @test_atomic_rmw_xor_16(i32 %iptr, i32 %v) {
   1274 entry:
   1275   %trunc = trunc i32 %v to i16
   1276   %ptr = inttoptr i32 %iptr to i16*
   1277   %a = call i16 @llvm.nacl.atomic.rmw.i16(i32 5, i16* %ptr, i16 %trunc, i32 6)
   1278   %a_ext = zext i16 %a to i32
   1279   ret i32 %a_ext
   1280 }
   1281 ; CHECK-LABEL: test_atomic_rmw_xor_16
   1282 ; CHECK: mov ax,WORD PTR
   1283 ; CHECK: xor
   1284 ; CHECK: lock cmpxchg WORD PTR [e{{[^a].}}]
   1285 ; CHECK: jne
   1286 ; ARM32-LABEL: test_atomic_rmw_xor_16
   1287 ; ARM32: dmb
   1288 ; ARM32: ldrexh
   1289 ; ARM32: eor
   1290 ; ARM32: strexh
   1291 ; ARM32: bne
   1292 ; ARM32: dmb
   1293 ; MIPS32-LABEL: test_atomic_rmw_xor_16
   1294 ; MIPS32: sync
   1295 ; MIPS32: addiu	{{.*}}, $zero, -4
   1296 ; MIPS32: and
   1297 ; MIPS32: andi	{{.*}}, {{.*}}, 3
   1298 ; MIPS32: sll	{{.*}}, {{.*}}, 3
   1299 ; MIPS32: ori	{{.*}}, {{.*}}, 65535
   1300 ; MIPS32: sllv
   1301 ; MIPS32: nor
   1302 ; MIPS32: sllv
   1303 ; MIPS32: ll
   1304 ; MIPS32: xor
   1305 ; MIPS32: and
   1306 ; MIPS32: and
   1307 ; MIPS32: or
   1308 ; MIPS32: sc
   1309 ; MIPS32: beq	{{.*}}, $zero, {{.*}}
   1310 ; MIPS32: and
   1311 ; MIPS32: srlv
   1312 ; MIPS32: sll	{{.*}}, {{.*}}, 16
   1313 ; MIPS32: sra	{{.*}}, {{.*}}, 16
   1314 ; MIPS32: sync
   1315 
   1316 define internal i32 @test_atomic_rmw_xor_32(i32 %iptr, i32 %v) {
   1317 entry:
   1318   %ptr = inttoptr i32 %iptr to i32*
   1319   %a = call i32 @llvm.nacl.atomic.rmw.i32(i32 5, i32* %ptr, i32 %v, i32 6)
   1320   ret i32 %a
   1321 }
   1322 ; CHECK-LABEL: test_atomic_rmw_xor_32
   1323 ; CHECK: mov eax,DWORD PTR
   1324 ; CHECK: xor
   1325 ; CHECK: lock cmpxchg DWORD PTR [e{{[^a].}}]
   1326 ; CHECK: jne
   1327 ; ARM32-LABEL: test_atomic_rmw_xor_32
   1328 ; ARM32: dmb
   1329 ; ARM32: ldrex
   1330 ; ARM32: eor
   1331 ; ARM32: strex
   1332 ; ARM32: bne
   1333 ; ARM32: dmb
   1334 ; MIPS32-LABEL: test_atomic_rmw_xor_32
   1335 ; MIPS32: sync
   1336 ; MIPS32: ll
   1337 ; MIPS32: xor
   1338 ; MIPS32: sc
   1339 ; MIPS32: beq	{{.*}}, $zero, {{.*}}
   1340 ; MIPS32: sync
   1341 
   1342 define internal i64 @test_atomic_rmw_xor_64(i32 %iptr, i64 %v) {
   1343 entry:
   1344   %ptr = inttoptr i32 %iptr to i64*
   1345   %a = call i64 @llvm.nacl.atomic.rmw.i64(i32 5, i64* %ptr, i64 %v, i32 6)
   1346   ret i64 %a
   1347 }
   1348 ; CHECK-LABEL: test_atomic_rmw_xor_64
   1349 ; CHECK: push ebx
   1350 ; CHECK: mov eax,DWORD PTR [{{.*}}]
   1351 ; CHECK: mov edx,DWORD PTR [{{.*}}+0x4]
   1352 ; CHECK: mov ebx,eax
   1353 ; CHECK: or ebx,{{.*e.[^x]}}
   1354 ; CHECK: mov ecx,edx
   1355 ; CHECK: or ecx,{{.*e.[^x]}}
   1356 ; CHECK: lock cmpxchg8b QWORD PTR [e{{.[^x]}}
   1357 ; CHECK: jne
   1358 ; ARM32-LABEL: test_atomic_rmw_xor_64
   1359 ; ARM32: dmb
   1360 ; ARM32: ldrexd r{{[0-9]+}}, r{{[0-9]+}}, [r{{[0-9]+}}]
   1361 ; ARM32: eor
   1362 ; ARM32: eor
   1363 ; ARM32: strexd r{{[0-9]+}}, r{{[0-9]+}}, r{{[0-9]+}}, [r{{[0-9]+}}]
   1364 ; ARM32: bne
   1365 ; ARM32: dmb
   1366 ; MIPS32-LABEL: test_atomic_rmw_xor_64
   1367 ; MIPS32: sync
   1368 ; MIPS32: jal	__sync_fetch_and_xor_8
   1369 ; MIPS32: sync
   1370 
   1371 define internal i32 @test_atomic_rmw_xor_32_ignored(i32 %iptr, i32 %v) {
   1372 entry:
   1373   %ptr = inttoptr i32 %iptr to i32*
   1374   %ignored = call i32 @llvm.nacl.atomic.rmw.i32(i32 5, i32* %ptr, i32 %v, i32 6)
   1375   ret i32 %v
   1376 }
   1377 ; CHECK-LABEL: test_atomic_rmw_xor_32_ignored
   1378 ; CHECK: mov eax,DWORD PTR
   1379 ; CHECK: xor
   1380 ; CHECK: lock cmpxchg DWORD PTR [e{{[^a].}}]
   1381 ; CHECK: jne
   1382 ; ARM32-LABEL: test_atomic_rmw_xor_32_ignored
   1383 ; ARM32: dmb
   1384 ; ARM32: ldrex
   1385 ; ARM32: eor
   1386 ; ARM32: strex
   1387 ; ARM32: bne
   1388 ; ARM32: dmb
   1389 ; MIPS32-LABEL: test_atomic_rmw_xor_32_ignored
   1390 ; MIPS32: sync
   1391 ; MIPS32: ll
   1392 ; MIPS32: xor
   1393 ; MIPS32: sc
   1394 ; MIPS32: beq	{{.*}}, $zero, {{.*}}
   1395 ; MIPS32: sync
   1396 
   1397 ;; exchange
   1398 
   1399 define internal i32 @test_atomic_rmw_xchg_8(i32 %iptr, i32 %v) {
   1400 entry:
   1401   %trunc = trunc i32 %v to i8
   1402   %ptr = inttoptr i32 %iptr to i8*
   1403   %a = call i8 @llvm.nacl.atomic.rmw.i8(i32 6, i8* %ptr, i8 %trunc, i32 6)
   1404   %a_ext = zext i8 %a to i32
   1405   ret i32 %a_ext
   1406 }
   1407 ; CHECK-LABEL: test_atomic_rmw_xchg_8
   1408 ; CHECK: xchg BYTE PTR {{.*}},[[REG:.*]]
   1409 ; ARM32-LABEL: test_atomic_rmw_xchg_8
   1410 ; ARM32: dmb
   1411 ; ARM32: ldrexb
   1412 ; ARM32: strexb
   1413 ; ARM32: cmp
   1414 ; ARM32: bne
   1415 ; ARM32: dmb
   1416 ; MIPS32-LABEL: test_atomic_rmw_xchg_8
   1417 ; MIPS32: sync
   1418 ; MIPS32: addiu	{{.*}}, $zero, -4
   1419 ; MIPS32: and
   1420 ; MIPS32: andi	{{.*}}, {{.*}}, 3
   1421 ; MIPS32: sll	{{.*}}, {{.*}}, 3
   1422 ; MIPS32: ori	{{.*}}, $zero, 255
   1423 ; MIPS32: sllv
   1424 ; MIPS32: nor
   1425 ; MIPS32: sllv
   1426 ; MIPS32: ll
   1427 ; MIPS32: and
   1428 ; MIPS32: or
   1429 ; MIPS32: sc
   1430 ; MIPS32: beq	{{.*}}, $zero, {{.*}}
   1431 ; MIPS32: and
   1432 ; MIPS32: srlv
   1433 ; MIPS32: sll	{{.*}}, {{.*}}, 24
   1434 ; MIPS32: sra	{{.*}}, {{.*}}, 24
   1435 ; MIPS32: sync
   1436 
   1437 define internal i32 @test_atomic_rmw_xchg_16(i32 %iptr, i32 %v) {
   1438 entry:
   1439   %trunc = trunc i32 %v to i16
   1440   %ptr = inttoptr i32 %iptr to i16*
   1441   %a = call i16 @llvm.nacl.atomic.rmw.i16(i32 6, i16* %ptr, i16 %trunc, i32 6)
   1442   %a_ext = zext i16 %a to i32
   1443   ret i32 %a_ext
   1444 }
   1445 ; CHECK-LABEL: test_atomic_rmw_xchg_16
   1446 ; CHECK: xchg WORD PTR {{.*}},[[REG:.*]]
   1447 ; ARM32-LABEL: test_atomic_rmw_xchg_16
   1448 ; ARM32: dmb
   1449 ; ARM32: ldrexh
   1450 ; ARM32: strexh
   1451 ; ARM32: cmp
   1452 ; ARM32: bne
   1453 ; ARM32: dmb
   1454 ; MIPS32-LABEL: test_atomic_rmw_xchg_16
   1455 ; MIPS32: sync
   1456 ; MIPS32: addiu	{{.*}}, $zero, -4
   1457 ; MIPS32: and
   1458 ; MIPS32: andi	{{.*}}, {{.*}}, 3
   1459 ; MIPS32: sll	{{.*}}, {{.*}}, 3
   1460 ; MIPS32: ori	{{.*}}, {{.*}}, 65535
   1461 ; MIPS32: sllv
   1462 ; MIPS32: nor
   1463 ; MIPS32: sllv
   1464 ; MIPS32: ll
   1465 ; MIPS32: and
   1466 ; MIPS32: or
   1467 ; MIPS32: sc
   1468 ; MIPS32: beq	{{.*}}, $zero, {{.*}}
   1469 ; MIPS32: and
   1470 ; MIPS32: srlv
   1471 ; MIPS32: sll	{{.*}}, {{.*}}, 16
   1472 ; MIPS32: sra	{{.*}}, {{.*}}, 16
   1473 ; MIPS32: sync
   1474 
   1475 define internal i32 @test_atomic_rmw_xchg_32(i32 %iptr, i32 %v) {
   1476 entry:
   1477   %ptr = inttoptr i32 %iptr to i32*
   1478   %a = call i32 @llvm.nacl.atomic.rmw.i32(i32 6, i32* %ptr, i32 %v, i32 6)
   1479   ret i32 %a
   1480 }
   1481 ; CHECK-LABEL: test_atomic_rmw_xchg_32
   1482 ; CHECK: xchg DWORD PTR {{.*}},[[REG:.*]]
   1483 ; ARM32-LABEL: test_atomic_rmw_xchg_32
   1484 ; ARM32: dmb
   1485 ; ARM32: ldrex
   1486 ; ARM32: strex
   1487 ; ARM32: cmp
   1488 ; ARM32: bne
   1489 ; ARM32: dmb
   1490 ; MIPS32-LABEL: test_atomic_rmw_xchg_32
   1491 ; MIPS32: sync
   1492 ; MIPS32: ll
   1493 ; MIPS32: move
   1494 ; MIPS32: sc
   1495 ; MIPS32: beq	{{.*}}, $zero, {{.*}}
   1496 ; MIPS32: sync
   1497 
   1498 define internal i64 @test_atomic_rmw_xchg_64(i32 %iptr, i64 %v) {
   1499 entry:
   1500   %ptr = inttoptr i32 %iptr to i64*
   1501   %a = call i64 @llvm.nacl.atomic.rmw.i64(i32 6, i64* %ptr, i64 %v, i32 6)
   1502   ret i64 %a
   1503 }
   1504 ; CHECK-LABEL: test_atomic_rmw_xchg_64
   1505 ; CHECK: push ebx
   1506 ; CHECK-DAG: mov edx
   1507 ; CHECK-DAG: mov eax
   1508 ; CHECK-DAG: mov ecx
   1509 ; CHECK-DAG: mov ebx
   1510 ; CHECK: lock cmpxchg8b QWORD PTR [{{e.[^x]}}
   1511 ; CHECK: jne
   1512 ; ARM32-LABEL: test_atomic_rmw_xchg_64
   1513 ; ARM32: dmb
   1514 ; ARM32: ldrexd r{{[0-9]+}}, r{{[0-9]+}}, {{[[]}}[[PTR:r[0-9]+]]{{[]]}}
   1515 ; ARM32: strexd r{{[0-9]+}}, r{{[0-9]+}}, r{{[0-9]+}}, {{[[]}}[[PTR]]{{[]]}}
   1516 ; ARM32: cmp
   1517 ; ARM32: bne
   1518 ; ARM32: dmb
   1519 ; MIPS32-LABEL: test_atomic_rmw_xchg_64
   1520 ; MIPS32: sync
   1521 ; MIPS32: jal	__sync_lock_test_and_set_8
   1522 ; MIPS32: sync
   1523 
   1524 define internal i32 @test_atomic_rmw_xchg_32_ignored(i32 %iptr, i32 %v) {
   1525 entry:
   1526   %ptr = inttoptr i32 %iptr to i32*
   1527   %ignored = call i32 @llvm.nacl.atomic.rmw.i32(i32 6, i32* %ptr, i32 %v, i32 6)
   1528   ret i32 %v
   1529 }
   1530 ; In this case, ignoring the return value doesn't help. The xchg is
   1531 ; used to do an atomic store.
   1532 ; CHECK-LABEL: test_atomic_rmw_xchg_32_ignored
   1533 ; CHECK: xchg DWORD PTR {{.*}},[[REG:.*]]
   1534 ; ARM32-LABEL: test_atomic_rmw_xchg_32_ignored
   1535 ; ARM32: dmb
   1536 ; ARM32: ldrex
   1537 ; ARM32: strex
   1538 ; ARM32: cmp
   1539 ; ARM32: bne
   1540 ; ARM32: dmb
   1541 ; MIPS32-LABEL: test_atomic_rmw_xchg_32_ignored
   1542 ; MIPS32: sync
   1543 ; MIPS32: ll
   1544 ; MIPS32: move
   1545 ; MIPS32: sc
   1546 ; MIPS32: beq	{{.*}}, $zero, {{.*}}
   1547 ; MIPS32: sync
   1548 
   1549 ;;;; Cmpxchg
   1550 
   1551 define internal i32 @test_atomic_cmpxchg_8(i32 %iptr, i32 %expected,
   1552                                            i32 %desired) {
   1553 entry:
   1554   %trunc_exp = trunc i32 %expected to i8
   1555   %trunc_des = trunc i32 %desired to i8
   1556   %ptr = inttoptr i32 %iptr to i8*
   1557   %old = call i8 @llvm.nacl.atomic.cmpxchg.i8(i8* %ptr, i8 %trunc_exp,
   1558                                               i8 %trunc_des, i32 6, i32 6)
   1559   %old_ext = zext i8 %old to i32
   1560   ret i32 %old_ext
   1561 }
   1562 ; CHECK-LABEL: test_atomic_cmpxchg_8
   1563 ; CHECK: mov eax,{{.*}}
   1564 ; Need to check that eax isn't used as the address register or the desired.
   1565 ; since it is already used as the *expected* register.
   1566 ; CHECK: lock cmpxchg BYTE PTR [e{{[^a].}}],{{[^a]}}l
   1567 ; ARM32-LABEL: test_atomic_cmpxchg_8
   1568 ; ARM32: dmb
   1569 ; ARM32: ldrexb [[V:r[0-9]+]], {{[[]}}[[A:r[0-9]+]]{{[]]}}
   1570 ; ARM32: lsl [[VV:r[0-9]+]], [[V]], #24
   1571 ; ARM32: cmp [[VV]], {{r[0-9]+}}, lsl #24
   1572 ; ARM32: movne [[SUCCESS:r[0-9]+]],
   1573 ; ARM32: strexbeq [[SUCCESS]], {{r[0-9]+}}, {{[[]}}[[A]]{{[]]}}
   1574 ; ARM32: cmp [[SUCCESS]], #0
   1575 ; ARM32: bne
   1576 ; ARM32: dmb
   1577 ; MIPS32-LABEL: test_atomic_cmpxchg_8
   1578 ; MIPS32: addiu	{{.*}}, $zero, -4
   1579 ; MIPS32: and
   1580 ; MIPS32: andi	{{.*}}, {{.*}}, 3
   1581 ; MIPS32: sll	{{.*}}, {{.*}}, 3
   1582 ; MIPS32: ori	{{.*}}, $zero, 255
   1583 ; MIPS32: sllv
   1584 ; MIPS32: nor
   1585 ; MIPS32: andi	{{.*}}, {{.*}}, 255
   1586 ; MIPS32: sllv
   1587 ; MIPS32: andi	{{.*}}, {{.*}}, 255
   1588 ; MIPS32: sllv
   1589 ; MIPS32: sync
   1590 ; MIPS32: ll
   1591 ; MIPS32: and
   1592 ; MIPS32: bne
   1593 ; MIPS32: and
   1594 ; MIPS32: or
   1595 ; MIPS32: sc
   1596 ; MIPS32: beq	$zero, {{.*}}, {{.*}}
   1597 ; MIPS32: srlv
   1598 ; MIPS32: sll	{{.*}}, {{.*}}, 24
   1599 ; MIPS32: sra	{{.*}}, {{.*}}, 24
   1600 ; MIPS32: sync
   1601 
   1602 define internal i32 @test_atomic_cmpxchg_16(i32 %iptr, i32 %expected,
   1603                                             i32 %desired) {
   1604 entry:
   1605   %trunc_exp = trunc i32 %expected to i16
   1606   %trunc_des = trunc i32 %desired to i16
   1607   %ptr = inttoptr i32 %iptr to i16*
   1608   %old = call i16 @llvm.nacl.atomic.cmpxchg.i16(i16* %ptr, i16 %trunc_exp,
   1609                                                i16 %trunc_des, i32 6, i32 6)
   1610   %old_ext = zext i16 %old to i32
   1611   ret i32 %old_ext
   1612 }
   1613 ; CHECK-LABEL: test_atomic_cmpxchg_16
   1614 ; CHECK: mov {{ax|eax}},{{.*}}
   1615 ; CHECK: lock cmpxchg WORD PTR [e{{[^a].}}],{{[^a]}}x
   1616 ; ARM32-LABEL: test_atomic_cmpxchg_16
   1617 ; ARM32: dmb
   1618 ; ARM32: ldrexh [[V:r[0-9]+]], {{[[]}}[[A:r[0-9]+]]{{[]]}}
   1619 ; ARM32: lsl [[VV:r[0-9]+]], [[V]], #16
   1620 ; ARM32: cmp [[VV]], {{r[0-9]+}}, lsl #16
   1621 ; ARM32: movne [[SUCCESS:r[0-9]+]],
   1622 ; ARM32: strexheq [[SUCCESS]], {{r[0-9]+}}, {{[[]}}[[A]]{{[]]}}
   1623 ; ARM32: cmp [[SUCCESS]], #0
   1624 ; ARM32: bne
   1625 ; ARM32: dmb
   1626 ; MIPS32-LABEL: test_atomic_cmpxchg_16
   1627 ; MIPS32: addiu	{{.*}}, $zero, -4
   1628 ; MIPS32: and
   1629 ; MIPS32: andi	{{.*}}, {{.*}}, 3
   1630 ; MIPS32: sll	{{.*}}, {{.*}}, 3
   1631 ; MIPS32: ori	{{.*}}, {{.*}}, 65535
   1632 ; MIPS32: sllv
   1633 ; MIPS32: nor
   1634 ; MIPS32: andi	{{.*}}, {{.*}}, 65535
   1635 ; MIPS32: sllv
   1636 ; MIPS32: andi	{{.*}}, {{.*}}, 65535
   1637 ; MIPS32: sllv
   1638 ; MIPS32: sync
   1639 ; MIPS32: ll
   1640 ; MIPS32: and
   1641 ; MIPS32: bne
   1642 ; MIPS32: and
   1643 ; MIPS32: or
   1644 ; MIPS32: sc
   1645 ; MIPS32: beq	$zero, {{.*}}, {{.*}}
   1646 ; MIPS32: srlv
   1647 ; MIPS32: sll	{{.*}}, {{.*}}, 16
   1648 ; MIPS32: sra	{{.*}}, {{.*}}, 16
   1649 ; MIPS32: sync
   1650 
   1651 define internal i32 @test_atomic_cmpxchg_32(i32 %iptr, i32 %expected,
   1652                                             i32 %desired) {
   1653 entry:
   1654   %ptr = inttoptr i32 %iptr to i32*
   1655   %old = call i32 @llvm.nacl.atomic.cmpxchg.i32(i32* %ptr, i32 %expected,
   1656                                                i32 %desired, i32 6, i32 6)
   1657   ret i32 %old
   1658 }
   1659 ; CHECK-LABEL: test_atomic_cmpxchg_32
   1660 ; CHECK: mov eax,{{.*}}
   1661 ; CHECK: lock cmpxchg DWORD PTR [e{{[^a].}}],e{{[^a]}}
   1662 ; ARM32-LABEL: test_atomic_cmpxchg_32
   1663 ; ARM32: dmb
   1664 ; ARM32: ldrex [[V:r[0-9]+]], {{[[]}}[[A:r[0-9]+]]{{[]]}}
   1665 ; ARM32: cmp [[V]], {{r[0-9]+}}
   1666 ; ARM32: movne [[SUCCESS:r[0-9]+]],
   1667 ; ARM32: strexeq [[SUCCESS]], {{r[0-9]+}}, {{[[]}}[[A]]{{[]]}}
   1668 ; ARM32: cmp [[SUCCESS]], #0
   1669 ; ARM32: bne
   1670 ; ARM32: dmb
   1671 ; MIPS32-LABEL: test_atomic_cmpxchg_32
   1672 ; MIPS32: sync
   1673 ; MIPS32: ll
   1674 ; MIPS32: bne
   1675 ; MIPS32: sc
   1676 ; MIPS32: beq	{{.*}}, $zero, {{.*}}
   1677 ; MIPS32: sync
   1678 
   1679 define internal i64 @test_atomic_cmpxchg_64(i32 %iptr, i64 %expected,
   1680                                             i64 %desired) {
   1681 entry:
   1682   %ptr = inttoptr i32 %iptr to i64*
   1683   %old = call i64 @llvm.nacl.atomic.cmpxchg.i64(i64* %ptr, i64 %expected,
   1684                                                i64 %desired, i32 6, i32 6)
   1685   ret i64 %old
   1686 }
   1687 ; CHECK-LABEL: test_atomic_cmpxchg_64
   1688 ; CHECK: push ebx
   1689 ; CHECK-DAG: mov edx
   1690 ; CHECK-DAG: mov eax
   1691 ; CHECK-DAG: mov ecx
   1692 ; CHECK-DAG: mov ebx
   1693 ; CHECK: lock cmpxchg8b QWORD PTR [e{{.[^x]}}+0x0]
   1694 ; edx and eax are already the return registers, so they don't actually
   1695 ; need to be reshuffled via movs. The next test stores the result
   1696 ; somewhere, so in that case they do need to be mov'ed.
   1697 ; ARM32-LABEL: test_atomic_cmpxchg_64
   1698 ; ARM32: dmb
   1699 ; ARM32: ldrexd [[V0:r[0-9]+]], [[V1:r[0-9]+]], {{[[]}}[[A:r[0-9]+]]{{[]]}}
   1700 ; ARM32: cmp [[V0]], {{r[0-9]+}}
   1701 ; ARM32: cmpeq [[V1]], {{r[0-9]+}}
   1702 ; ARM32: movne [[SUCCESS:r[0-9]+]],
   1703 ; ARM32: strexdeq [[SUCCESS]], r{{[0-9]+}}, r{{[0-9]+}}, {{[[]}}[[A]]{{[]]}}
   1704 ; ARM32: cmp [[SUCCESS]], #0
   1705 ; ARM32: bne
   1706 ; ARM32: dmb
   1707 ; MIPS32-LABEL: test_atomic_cmpxchg_64
   1708 ; MIPS32: sync
   1709 ; MIPS32: jal	__sync_val_compare_and_swap_8
   1710 ; MIPS32: sync
   1711 
   1712 
   1713 define internal i64 @test_atomic_cmpxchg_64_undef(i32 %iptr, i64 %desired) {
   1714 entry:
   1715   %ptr = inttoptr i32 %iptr to i64*
   1716   %old = call i64 @llvm.nacl.atomic.cmpxchg.i64(i64* %ptr, i64 undef,
   1717                                                i64 %desired, i32 6, i32 6)
   1718   ret i64 %old
   1719 }
   1720 ; CHECK-LABEL: test_atomic_cmpxchg_64_undef
   1721 ; CHECK: lock cmpxchg8b QWORD PTR [e{{.[^x]}}+0x0]
   1722 ; ARM32-LABEL: test_atomic_cmpxchg_64_undef
   1723 ; ARM32: mov r{{[0-9]+}}, #0
   1724 ; ARM32: mov r{{[0-9]+}}, #0
   1725 ; ARM32: dmb
   1726 ; ARM32: ldrexd [[V0:r[0-9]+]], [[V1:r[0-9]+]], {{[[]}}[[A:r[0-9]+]]{{[]]}}
   1727 ; ARM32: cmp [[V0]], {{r[0-9]+}}
   1728 ; ARM32: cmpeq [[V1]], {{r[0-9]+}}
   1729 ; ARM32: movne [[SUCCESS:r[0-9]+]],
   1730 ; ARM32: strexdeq [[SUCCESS]], r{{[0-9]+}}, r{{[0-9]+}}, {{[[]}}[[A]]{{[]]}}
   1731 ; ARM32: cmp [[SUCCESS]], #0
   1732 ; ARM32: bne
   1733 ; ARM32: dmb
   1734 ; MIPS32-LABEL: test_atomic_cmpxchg_64_undef
   1735 ; MIPS32: sync
   1736 ; MIPS32: jal	__sync_val_compare_and_swap_8
   1737 ; MIPS32: sync
   1738 
   1739 ; Test a case where %old really does need to be copied out of edx:eax.
   1740 define internal void @test_atomic_cmpxchg_64_store(
   1741     i32 %ret_iptr, i32 %iptr, i64 %expected, i64 %desired) {
   1742 entry:
   1743   %ptr = inttoptr i32 %iptr to i64*
   1744   %old = call i64 @llvm.nacl.atomic.cmpxchg.i64(i64* %ptr, i64 %expected,
   1745                                                 i64 %desired, i32 6, i32 6)
   1746   %__6 = inttoptr i32 %ret_iptr to i64*
   1747   store i64 %old, i64* %__6, align 1
   1748   ret void
   1749 }
   1750 ; CHECK-LABEL: test_atomic_cmpxchg_64_store
   1751 ; CHECK: push ebx
   1752 ; CHECK-DAG: mov edx
   1753 ; CHECK-DAG: mov eax
   1754 ; CHECK-DAG: mov ecx
   1755 ; CHECK-DAG: mov ebx
   1756 ; CHECK: lock cmpxchg8b QWORD PTR [e{{.[^x]}}
   1757 ; CHECK-DAG: mov {{.*}},edx
   1758 ; CHECK-DAG: mov {{.*}},eax
   1759 ; ARM32-LABEL: test_atomic_cmpxchg_64_store
   1760 ; ARM32: dmb
   1761 ; ARM32: ldrexd [[V0:r[0-9]+]], [[V1:r[0-9]+]], {{[[]}}[[A:r[0-9]+]]{{[]]}}
   1762 ; ARM32: cmp [[V0]], {{r[0-9]+}}
   1763 ; ARM32: cmpeq [[V1]], {{r[0-9]+}}
   1764 ; ARM32: movne [[SUCCESS:r[0-9]+]],
   1765 ; ARM32: strexdeq [[SUCCESS]], r{{[0-9]+}}, r{{[0-9]+}}, {{[[]}}[[A]]{{[]]}}
   1766 ; ARM32: cmp [[SUCCESS]], #0
   1767 ; ARM32: bne
   1768 ; ARM32: dmb
   1769 ; ARM32: str
   1770 ; ARM32: str
   1771 ; MIPS32-LABEL: test_atomic_cmpxchg_64_store
   1772 ; MIPS32: sync
   1773 ; MIPS32: jal	__sync_val_compare_and_swap_8
   1774 ; MIPS32: sync
   1775 
   1776 
   1777 ; Test with some more register pressure. When we have an alloca, ebp is
   1778 ; used to manage the stack frame, so it cannot be used as a register either.
   1779 define internal i64 @test_atomic_cmpxchg_64_alloca(i32 %iptr, i64 %expected,
   1780                                                    i64 %desired) {
   1781 entry:
   1782   br label %eblock  ; Disable alloca optimization
   1783 eblock:
   1784   %alloca_ptr = alloca i8, i32 16, align 16
   1785   %ptr = inttoptr i32 %iptr to i64*
   1786   %old = call i64 @llvm.nacl.atomic.cmpxchg.i64(i64* %ptr, i64 %expected,
   1787                                                 i64 %desired, i32 6, i32 6)
   1788   store i8 0, i8* %alloca_ptr, align 1
   1789   store i8 1, i8* %alloca_ptr, align 1
   1790   store i8 2, i8* %alloca_ptr, align 1
   1791   store i8 3, i8* %alloca_ptr, align 1
   1792   %__6 = ptrtoint i8* %alloca_ptr to i32
   1793   call void @use_ptr(i32 %__6)
   1794   ret i64 %old
   1795 }
   1796 ; CHECK-LABEL: test_atomic_cmpxchg_64_alloca
   1797 ; CHECK: push ebx
   1798 ; CHECK-DAG: mov edx
   1799 ; CHECK-DAG: mov eax
   1800 ; CHECK-DAG: mov ecx
   1801 ; CHECK-DAG: mov ebx
   1802 ; Ptr cannot be eax, ebx, ecx, or edx (used up for the expected and desired).
   1803 ; It also cannot be ebp since we use that for alloca. Also make sure it's
   1804 ; not esp, since that's the stack pointer and mucking with it will break
   1805 ; the later use_ptr function call.
   1806 ; That pretty much leaves esi, or edi as the only viable registers.
   1807 ; CHECK: lock cmpxchg8b QWORD PTR [e{{[ds]}}i]
   1808 ; CHECK: call {{.*}} R_{{.*}} use_ptr
   1809 ; ARM32-LABEL: test_atomic_cmpxchg_64_alloca
   1810 ; ARM32: dmb
   1811 ; ARM32: ldrexd [[V0:r[0-9]+]], [[V1:r[0-9]+]], {{[[]}}[[A:r[0-9]+]]{{[]]}}
   1812 ; ARM32: cmp [[V0]], {{r[0-9]+}}
   1813 ; ARM32: cmpeq [[V1]], {{r[0-9]+}}
   1814 ; ARM32: movne [[SUCCESS:r[0-9]+]],
   1815 ; ARM32: strexdeq [[SUCCESS]], r{{[0-9]+}}, r{{[0-9]+}}, {{[[]}}[[A]]{{[]]}}
   1816 ; ARM32: cmp [[SUCCESS]], #0
   1817 ; ARM32: bne
   1818 ; ARM32: dmb
   1819 ; MIPS32-LABEL: test_atomic_cmpxchg_64_alloca
   1820 ; MIPS32: sync
   1821 ; MIPS32: jal	__sync_val_compare_and_swap_8
   1822 ; MIPS32: sync
   1823 
   1824 define internal i32 @test_atomic_cmpxchg_32_ignored(i32 %iptr, i32 %expected,
   1825                                                     i32 %desired) {
   1826 entry:
   1827   %ptr = inttoptr i32 %iptr to i32*
   1828   %ignored = call i32 @llvm.nacl.atomic.cmpxchg.i32(i32* %ptr, i32 %expected,
   1829                                                     i32 %desired, i32 6, i32 6)
   1830   ret i32 0
   1831 }
   1832 ; CHECK-LABEL: test_atomic_cmpxchg_32_ignored
   1833 ; CHECK: mov eax,{{.*}}
   1834 ; CHECK: lock cmpxchg DWORD PTR [e{{[^a].}}]
   1835 ; ARM32-LABEL: test_atomic_cmpxchg_32_ignored
   1836 ; ARM32: dmb
   1837 ; ARM32: ldrex [[V:r[0-9]+]], {{[[]}}[[A:r[0-9]+]]{{[]]}}
   1838 ; ARM32: cmp [[V]], {{r[0-9]+}}
   1839 ; ARM32: movne [[SUCCESS:r[0-9]+]],
   1840 ; ARM32: strexeq [[SUCCESS]]
   1841 ; ARM32: cmp [[SUCCESS]], #0
   1842 ; ARM32: bne
   1843 ; ARM32: dmb
   1844 ; MIPS32-LABEL: test_atomic_cmpxchg_32_ignored
   1845 ; MIPS32: sync
   1846 ; MIPS32: ll
   1847 ; MIPS32: bne
   1848 ; MIPS32: sc
   1849 ; MIPS32: beq	{{.*}}, $zero, {{.*}}
   1850 ; MIPS32: sync
   1851 
   1852 define internal i64 @test_atomic_cmpxchg_64_ignored(i32 %iptr, i64 %expected,
   1853                                                     i64 %desired) {
   1854 entry:
   1855   %ptr = inttoptr i32 %iptr to i64*
   1856   %ignored = call i64 @llvm.nacl.atomic.cmpxchg.i64(i64* %ptr, i64 %expected,
   1857                                                     i64 %desired, i32 6, i32 6)
   1858   ret i64 0
   1859 }
   1860 ; CHECK-LABEL: test_atomic_cmpxchg_64_ignored
   1861 ; CHECK: push ebx
   1862 ; CHECK-DAG: mov edx
   1863 ; CHECK-DAG: mov eax
   1864 ; CHECK-DAG: mov ecx
   1865 ; CHECK-DAG: mov ebx
   1866 ; CHECK: lock cmpxchg8b QWORD PTR [e{{.[^x]}}+0x0]
   1867 ; ARM32-LABEL: test_atomic_cmpxchg_64_ignored
   1868 ; ARM32: dmb
   1869 ; ARM32: ldrexd [[V0:r[0-9]+]], [[V1:r[0-9]+]], {{[[]}}[[A:r[0-9]+]]{{[]]}}
   1870 ; ARM32: cmp [[V0]], {{r[0-9]+}}
   1871 ; ARM32: cmpeq [[V1]], {{r[0-9]+}}
   1872 ; ARM32: movne [[SUCCESS:r[0-9]+]],
   1873 ; ARM32: strexdeq [[SUCCESS]], r{{[0-9]+}}, r{{[0-9]+}}, {{[[]}}[[PTR]]{{[]]}}
   1874 ; ARM32: cmp [[SUCCESS]], #0
   1875 ; ARM32: bne
   1876 ; ARM32: dmb
   1877 ; MIPS32-LABEL: test_atomic_cmpxchg_64_ignored
   1878 ; MIPS32: sync
   1879 ; MIPS32: jal	__sync_val_compare_and_swap_8
   1880 ; MIPS32: sync
   1881 
   1882 ;;;; Fence and is-lock-free.
   1883 
   1884 define internal void @test_atomic_fence() {
   1885 entry:
   1886   call void @llvm.nacl.atomic.fence(i32 6)
   1887   ret void
   1888 }
   1889 ; CHECK-LABEL: test_atomic_fence
   1890 ; CHECK: mfence
   1891 ; ARM32-LABEL: test_atomic_fence
   1892 ; ARM32: dmb sy
   1893 ; MIPS32-LABEL: test_atomic_fence
   1894 ; MIPS32: sync
   1895 
   1896 define internal void @test_atomic_fence_all() {
   1897 entry:
   1898   call void @llvm.nacl.atomic.fence.all()
   1899   ret void
   1900 }
   1901 ; CHECK-LABEL: test_atomic_fence_all
   1902 ; CHECK: mfence
   1903 ; ARM32-LABEL: test_atomic_fence_all
   1904 ; ARM32: dmb sy
   1905 ; MIPS32-LABEL: test_atomic_fence_all
   1906 ; MIPS32: sync
   1907 
   1908 define internal i32 @test_atomic_is_lock_free(i32 %iptr) {
   1909 entry:
   1910   %ptr = inttoptr i32 %iptr to i8*
   1911   %i = call i1 @llvm.nacl.atomic.is.lock.free(i32 4, i8* %ptr)
   1912   %r = zext i1 %i to i32
   1913   ret i32 %r
   1914 }
   1915 ; CHECK-LABEL: test_atomic_is_lock_free
   1916 ; CHECK: mov {{.*}},0x1
   1917 ; ARM32-LABEL: test_atomic_is_lock_free
   1918 ; ARM32: mov {{.*}}, #1
   1919 ; MIPS32-LABEL: test_atomic_is_lock_free
   1920 ; MIPS32: addiu {{.*}}, $zero, 1
   1921 
   1922 define internal i32 @test_not_lock_free(i32 %iptr) {
   1923 entry:
   1924   %ptr = inttoptr i32 %iptr to i8*
   1925   %i = call i1 @llvm.nacl.atomic.is.lock.free(i32 7, i8* %ptr)
   1926   %r = zext i1 %i to i32
   1927   ret i32 %r
   1928 }
   1929 ; CHECK-LABEL: test_not_lock_free
   1930 ; CHECK: mov {{.*}},0x0
   1931 ; ARM32-LABEL: test_not_lock_free
   1932 ; ARM32: mov {{.*}}, #0
   1933 ; MIPS32-LABEL: test_not_lock_free
   1934 ; MIPS32: addiu {{.*}}, $zero, 0
   1935 
   1936 define internal i32 @test_atomic_is_lock_free_ignored(i32 %iptr) {
   1937 entry:
   1938   %ptr = inttoptr i32 %iptr to i8*
   1939   %ignored = call i1 @llvm.nacl.atomic.is.lock.free(i32 4, i8* %ptr)
   1940   ret i32 0
   1941 }
   1942 ; CHECK-LABEL: test_atomic_is_lock_free_ignored
   1943 ; CHECK: mov {{.*}},0x0
   1944 ; This can get optimized out, because it's side-effect-free.
   1945 ; O2-LABEL: test_atomic_is_lock_free_ignored
   1946 ; O2-NOT: mov {{.*}}, 1
   1947 ; O2: mov {{.*}},0x0
   1948 ; ARM32O2-LABEL: test_atomic_is_lock_free_ignored
   1949 ; ARM32O2-NOT: mov {{.*}}, #1
   1950 ; ARM32O2: mov {{.*}}, #0
   1951 ; MIPS32O2-LABEL: test_atomic_is_lock_free
   1952 ; MIPS32O2-NOT: addiu {{.*}}, $zero, 1
   1953 ; MIPS32O2: addiu {{.*}}, $zero, 0
   1954 
   1955 ; TODO(jvoung): at some point we can take advantage of the
   1956 ; fact that nacl.atomic.is.lock.free will resolve to a constant
   1957 ; (which adds DCE opportunities). Once we optimize, the test expectations
   1958 ; for this case should change.
   1959 define internal i32 @test_atomic_is_lock_free_can_dce(i32 %iptr, i32 %x,
   1960                                                       i32 %y) {
   1961 entry:
   1962   %ptr = inttoptr i32 %iptr to i8*
   1963   %i = call i1 @llvm.nacl.atomic.is.lock.free(i32 4, i8* %ptr)
   1964   %i_ext = zext i1 %i to i32
   1965   %cmp = icmp eq i32 %i_ext, 1
   1966   br i1 %cmp, label %lock_free, label %not_lock_free
   1967 lock_free:
   1968   ret i32 %i_ext
   1969 
   1970 not_lock_free:
   1971   %z = add i32 %x, %y
   1972   ret i32 %z
   1973 }
   1974 ; CHECK-LABEL: test_atomic_is_lock_free_can_dce
   1975 ; CHECK: mov {{.*}},0x1
   1976 ; CHECK: ret
   1977 ; CHECK: add
   1978 ; CHECK: ret
   1979 
   1980 ; Test the liveness / register allocation properties of the xadd instruction.
   1981 ; Make sure we model that the Src register is modified and therefore it can't
   1982 ; share a register with an overlapping live range, even if the result of the
   1983 ; xadd instruction is unused.
   1984 define internal void @test_xadd_regalloc() {
   1985 entry:
   1986   br label %body
   1987 body:
   1988   %i = phi i32 [ 1, %entry ], [ %i_plus_1, %body ]
   1989   %g = bitcast [4 x i8]* @SzGlobal32 to i32*
   1990   %unused = call i32 @llvm.nacl.atomic.rmw.i32(i32 1, i32* %g, i32 %i, i32 6)
   1991   %i_plus_1 = add i32 %i, 1
   1992   %cmp = icmp eq i32 %i_plus_1, 1001
   1993   br i1 %cmp, label %done, label %body
   1994 done:
   1995   ret void
   1996 }
   1997 ; O2-LABEL: test_xadd_regalloc
   1998 ;;; Some register will be used in the xadd instruction.
   1999 ; O2: lock xadd DWORD PTR {{.*}},[[REG:e..]]
   2000 ;;; Make sure that register isn't used again, e.g. as the induction variable.
   2001 ; O2-NOT: ,[[REG]]
   2002 ; O2: ret
   2003 
   2004 ; Do the same test for the xchg instruction instead of xadd.
   2005 define internal void @test_xchg_regalloc() {
   2006 entry:
   2007   br label %body
   2008 body:
   2009   %i = phi i32 [ 1, %entry ], [ %i_plus_1, %body ]
   2010   %g = bitcast [4 x i8]* @SzGlobal32 to i32*
   2011   %unused = call i32 @llvm.nacl.atomic.rmw.i32(i32 6, i32* %g, i32 %i, i32 6)
   2012   %i_plus_1 = add i32 %i, 1
   2013   %cmp = icmp eq i32 %i_plus_1, 1001
   2014   br i1 %cmp, label %done, label %body
   2015 done:
   2016   ret void
   2017 }
   2018 ; O2-LABEL: test_xchg_regalloc
   2019 ;;; Some register will be used in the xchg instruction.
   2020 ; O2: xchg DWORD PTR {{.*}},[[REG:e..]]
   2021 ;;; Make sure that register isn't used again, e.g. as the induction variable.
   2022 ; O2-NOT: ,[[REG]]
   2023 ; O2: ret
   2024 
   2025 ; Same test for cmpxchg.
   2026 define internal void @test_cmpxchg_regalloc() {
   2027 entry:
   2028   br label %body
   2029 body:
   2030   %i = phi i32 [ 1, %entry ], [ %i_plus_1, %body ]
   2031   %g = bitcast [4 x i8]* @SzGlobal32 to i32*
   2032   %unused = call i32 @llvm.nacl.atomic.cmpxchg.i32(i32* %g, i32 %i, i32 %i, i32 6, i32 6)
   2033   %i_plus_1 = add i32 %i, 1
   2034   %cmp = icmp eq i32 %i_plus_1, 1001
   2035   br i1 %cmp, label %done, label %body
   2036 done:
   2037   ret void
   2038 }
   2039 ; O2-LABEL: test_cmpxchg_regalloc
   2040 ;;; eax and some other register will be used in the cmpxchg instruction.
   2041 ; O2: lock cmpxchg DWORD PTR {{.*}},[[REG:e..]]
   2042 ;;; Make sure eax isn't used again, e.g. as the induction variable.
   2043 ; O2-NOT: ,eax
   2044 ; O2: ret
   2045 
   2046 ; Same test for cmpxchg8b.
   2047 define internal void @test_cmpxchg8b_regalloc() {
   2048 entry:
   2049   br label %body
   2050 body:
   2051   %i = phi i32 [ 1, %entry ], [ %i_plus_1, %body ]
   2052   %g = bitcast [8 x i8]* @SzGlobal64 to i64*
   2053   %i_64 = zext i32 %i to i64
   2054   %unused = call i64 @llvm.nacl.atomic.cmpxchg.i64(i64* %g, i64 %i_64, i64 %i_64, i32 6, i32 6)
   2055   %i_plus_1 = add i32 %i, 1
   2056   %cmp = icmp eq i32 %i_plus_1, 1001
   2057   br i1 %cmp, label %done, label %body
   2058 done:
   2059   ret void
   2060 }
   2061 ; O2-LABEL: test_cmpxchg8b_regalloc
   2062 ;;; eax and some other register will be used in the cmpxchg instruction.
   2063 ; O2: lock cmpxchg8b QWORD PTR
   2064 ;;; Make sure eax/ecx/edx/ebx aren't used again, e.g. as the induction variable.
   2065 ; O2-NOT: ,{{eax|ecx|edx|ebx}}
   2066 ; O2: pop ebx
   2067