| Index: tests_lit/llvm2ice_tests/nacl-atomic-intrinsics.ll
|
| diff --git a/tests_lit/llvm2ice_tests/nacl-atomic-intrinsics.ll b/tests_lit/llvm2ice_tests/nacl-atomic-intrinsics.ll
|
| index d353c9687c2442df3b7411d44f086dcdc6ed9c9e..30a08b279ffa8c73c25d017015df67dea00eb45d 100644
|
| --- a/tests_lit/llvm2ice_tests/nacl-atomic-intrinsics.ll
|
| +++ b/tests_lit/llvm2ice_tests/nacl-atomic-intrinsics.ll
|
| @@ -8,6 +8,21 @@
|
| ; RUN: %p2i -i %s --filetype=obj --disassemble --args -Om1 \
|
| ; RUN: | FileCheck %s
|
|
|
| +; RUN: %if --need=allow_dump --need=target_ARM32 --command %p2i --filetype=asm \
|
| +; RUN: --target arm32 -i %s --args -O2 --skip-unimplemented \
|
| +; RUN: | %if --need=allow_dump --need=target_ARM32 --command FileCheck %s \
|
| +; RUN: --check-prefix=ARM32
|
| +
|
| +; RUN: %if --need=allow_dump --need=target_ARM32 --command %p2i --filetype=asm \
|
| +; RUN: --target arm32 -i %s --args -O2 --skip-unimplemented \
|
| +; RUN: | %if --need=allow_dump --need=target_ARM32 --command FileCheck %s \
|
| +; RUN: --check-prefix=ARM32O2
|
| +
|
| +; RUN: %if --need=allow_dump --need=target_ARM32 --command %p2i --filetype=asm \
|
| +; RUN: --target arm32 -i %s --args -Om1 --skip-unimplemented \
|
| +; RUN: | %if --need=allow_dump --need=target_ARM32 --command FileCheck %s \
|
| +; RUN: --check-prefix=ARM32
|
| +
|
| declare i8 @llvm.nacl.atomic.load.i8(i8*, i32)
|
| declare i16 @llvm.nacl.atomic.load.i16(i16*, i32)
|
| declare i32 @llvm.nacl.atomic.load.i32(i32*, i32)
|
| @@ -55,6 +70,9 @@ entry:
|
| ; CHECK-LABEL: test_atomic_load_8
|
| ; CHECK: mov {{.*}},DWORD
|
| ; CHECK: mov {{.*}},BYTE
|
| +; ARM32-LABEL: test_atomic_load_8
|
| +; ARM32: ldrb r{{[0-9]+}}, [r{{[0-9]+}}
|
| +; ARM32: dmb
|
|
|
| define i32 @test_atomic_load_16(i32 %iptr) {
|
| entry:
|
| @@ -67,6 +85,9 @@ entry:
|
| ; CHECK-LABEL: test_atomic_load_16
|
| ; CHECK: mov {{.*}},DWORD
|
| ; CHECK: mov {{.*}},WORD
|
| +; ARM32-LABEL: test_atomic_load_16
|
| +; ARM32: ldrh r{{[0-9]+}}, [r{{[0-9]+}}
|
| +; ARM32: dmb
|
|
|
| define i32 @test_atomic_load_32(i32 %iptr) {
|
| entry:
|
| @@ -77,6 +98,9 @@ entry:
|
| ; CHECK-LABEL: test_atomic_load_32
|
| ; CHECK: mov {{.*}},DWORD
|
| ; CHECK: mov {{.*}},DWORD
|
| +; ARM32-LABEL: test_atomic_load_32
|
| +; ARM32: ldr r{{[0-9]+}}, [r{{[0-9]+}}
|
| +; ARM32: dmb
|
|
|
| define i64 @test_atomic_load_64(i32 %iptr) {
|
| entry:
|
| @@ -87,6 +111,9 @@ entry:
|
| ; CHECK-LABEL: test_atomic_load_64
|
| ; CHECK: movq x{{.*}},QWORD
|
| ; CHECK: movq QWORD {{.*}},x{{.*}}
|
| +; ARM32-LABEL: test_atomic_load_64
|
| +; ARM32: ldrexd r{{[0-9]+}}, r{{[0-9]+}}, [r{{[0-9]+}}
|
| +; ARM32: dmb
|
|
|
| define i32 @test_atomic_load_32_with_arith(i32 %iptr) {
|
| entry:
|
| @@ -106,6 +133,9 @@ next:
|
| ; O2-LABEL: test_atomic_load_32_with_arith
|
| ; O2: mov {{.*}},DWORD
|
| ; O2: sub {{.*}},DWORD
|
| +; ARM32-LABEL: test_atomic_load_32_with_arith
|
| +; ARM32: ldr r{{[0-9]+}}, [r{{[0-9]+}}
|
| +; ARM32: dmb
|
|
|
| define i32 @test_atomic_load_32_ignored(i32 %iptr) {
|
| entry:
|
| @@ -119,6 +149,9 @@ entry:
|
| ; O2-LABEL: test_atomic_load_32_ignored
|
| ; O2: mov {{.*}},DWORD
|
| ; O2: mov {{.*}},DWORD
|
| +; ARM32-LABEL: test_atomic_load_32_ignored
|
| +; ARM32: ldr r{{[0-9]+}}, [r{{[0-9]+}}
|
| +; ARM32: dmb
|
|
|
| define i64 @test_atomic_load_64_ignored(i32 %iptr) {
|
| entry:
|
| @@ -129,6 +162,9 @@ entry:
|
| ; CHECK-LABEL: test_atomic_load_64_ignored
|
| ; CHECK: movq x{{.*}},QWORD
|
| ; CHECK: movq QWORD {{.*}},x{{.*}}
|
| +; ARM32-LABEL: test_atomic_load_64_ignored
|
| +; ARM32: ldrexd r{{[0-9]+}}, r{{[0-9]+}}, [r{{[0-9]+}}
|
| +; ARM32: dmb
|
|
|
| ;;; Store
|
|
|
| @@ -142,6 +178,10 @@ entry:
|
| ; CHECK-LABEL: test_atomic_store_8
|
| ; CHECK: mov BYTE
|
| ; CHECK: mfence
|
| +; ARM32-LABEL: test_atomic_store_8
|
| +; ARM32: dmb
|
| +; ARM32: strb r{{[0-9]+}}, [r{{[0-9]+}}
|
| +; ARM32: dmb
|
|
|
| define void @test_atomic_store_16(i32 %iptr, i32 %v) {
|
| entry:
|
| @@ -153,6 +193,10 @@ entry:
|
| ; CHECK-LABEL: test_atomic_store_16
|
| ; CHECK: mov WORD
|
| ; CHECK: mfence
|
| +; ARM32-LABEL: test_atomic_store_16
|
| +; ARM32: dmb
|
| +; ARM32: strh r{{[0-9]+}}, [r{{[0-9]+}}
|
| +; ARM32: dmb
|
|
|
| define void @test_atomic_store_32(i32 %iptr, i32 %v) {
|
| entry:
|
| @@ -163,6 +207,10 @@ entry:
|
| ; CHECK-LABEL: test_atomic_store_32
|
| ; CHECK: mov DWORD
|
| ; CHECK: mfence
|
| +; ARM32-LABEL: test_atomic_store_32
|
| +; ARM32: dmb
|
| +; ARM32: str r{{[0-9]+}}, [r{{[0-9]+}}
|
| +; ARM32: dmb
|
|
|
| define void @test_atomic_store_64(i32 %iptr, i64 %v) {
|
| entry:
|
| @@ -174,6 +222,13 @@ entry:
|
| ; CHECK: movq x{{.*}},QWORD
|
| ; CHECK: movq QWORD {{.*}},x{{.*}}
|
| ; CHECK: mfence
|
| +; ARM32-LABEL: test_atomic_store_64
|
| +; ARM32: dmb
|
| +; ARM32: ldrexd r{{[0-9]+}}, r{{[0-9]+}}, [[MEM:.*]]
|
| +; ARM32: strexd [[S:r[0-9]+]], r{{[0-9]+}}, r{{[0-9]+}}, [[MEM]]
|
| +; ARM32: cmp [[S]], #0
|
| +; ARM32: bne
|
| +; ARM32: dmb
|
|
|
| define void @test_atomic_store_64_const(i32 %iptr) {
|
| entry:
|
| @@ -187,7 +242,17 @@ entry:
|
| ; CHECK: movq x{{.*}},QWORD
|
| ; CHECK: movq QWORD {{.*}},x{{.*}}
|
| ; CHECK: mfence
|
| -
|
| +; ARM32-LABEL: test_atomic_store_64_const
|
| +; ARM32: dmb
|
| +; ARM32: movw [[T0:r[0-9]+]], #12274
|
| +; ARM32: movt [[T0]], #29646
|
| +; ARM32: movw r{{[0-9]+}}, #2874
|
| +; ARM32: .L[[RETRY:.*]]:
|
| +; ARM32: ldrexd r{{[0-9]+}}, r{{[0-9]+}}, [[MEM:.*]]
|
| +; ARM32: strexd [[S:r[0-9]+]], r{{[0-9]+}}, r{{[0-9]+}}, [[MEM]]
|
| +; ARM32: cmp [[S]], #0
|
| +; ARM32: bne .L[[RETRY]]
|
| +; ARM32: dmb
|
|
|
| ;;; RMW
|
|
|
| @@ -205,6 +270,13 @@ entry:
|
| ; CHECK-LABEL: test_atomic_rmw_add_8
|
| ; CHECK: lock xadd BYTE {{.*}},[[REG:.*]]
|
| ; CHECK: {{mov|movzx}} {{.*}},[[REG]]
|
| +; ARM32-LABEL: test_atomic_rmw_add_8
|
| +; ARM32: dmb
|
| +; ARM32: ldrexb
|
| +; ARM32: add
|
| +; ARM32: strexb
|
| +; ARM32: bne
|
| +; ARM32: dmb
|
|
|
| define i32 @test_atomic_rmw_add_16(i32 %iptr, i32 %v) {
|
| entry:
|
| @@ -217,6 +289,13 @@ entry:
|
| ; CHECK-LABEL: test_atomic_rmw_add_16
|
| ; CHECK: lock xadd WORD {{.*}},[[REG:.*]]
|
| ; CHECK: {{mov|movzx}} {{.*}},[[REG]]
|
| +; ARM32-LABEL: test_atomic_rmw_add_16
|
| +; ARM32: dmb
|
| +; ARM32: ldrexh
|
| +; ARM32: add
|
| +; ARM32: strexh
|
| +; ARM32: bne
|
| +; ARM32: dmb
|
|
|
| define i32 @test_atomic_rmw_add_32(i32 %iptr, i32 %v) {
|
| entry:
|
| @@ -227,6 +306,13 @@ entry:
|
| ; CHECK-LABEL: test_atomic_rmw_add_32
|
| ; CHECK: lock xadd DWORD {{.*}},[[REG:.*]]
|
| ; CHECK: mov {{.*}},[[REG]]
|
| +; ARM32-LABEL: test_atomic_rmw_add_32
|
| +; ARM32: dmb
|
| +; ARM32: ldrex
|
| +; ARM32: add
|
| +; ARM32: strex
|
| +; ARM32: bne
|
| +; ARM32: dmb
|
|
|
| define i64 @test_atomic_rmw_add_64(i32 %iptr, i64 %v) {
|
| entry:
|
| @@ -249,6 +335,14 @@ entry:
|
| ; about rejecting eb* and ed*.)
|
| ; CHECK: lock cmpxchg8b QWORD PTR [e{{.[^x]}}
|
| ; CHECK: jne [[LABEL]]
|
| +; ARM32-LABEL: test_atomic_rmw_add_64
|
| +; ARM32: dmb
|
| +; ARM32: ldrexd r{{[0-9]+}}, r{{[0-9]+}}, [r{{[0-9]+}}]
|
| +; ARM32: adds
|
| +; ARM32-NEXT: adc
|
| +; ARM32: strexd r{{[0-9]+}}, r{{[0-9]+}}, r{{[0-9]+}}, [r{{[0-9]+}}]
|
| +; ARM32: bne
|
| +; ARM32: dmb
|
|
|
| ; Same test as above, but with a global address to test FakeUse issues.
|
| define i64 @test_atomic_rmw_add_64_global(i64 %v) {
|
| @@ -258,6 +352,14 @@ entry:
|
| ret i64 %a
|
| }
|
| ; CHECK-LABEL: test_atomic_rmw_add_64_global
|
| +; ARM32-LABEL: test_atomic_rmw_add_64_global
|
| +; ARM32: dmb
|
| +; ARM32: ldrexd r{{[0-9]+}}, r{{[0-9]+}}, [r{{[0-9]+}}]
|
| +; ARM32: adds
|
| +; ARM32-NEXT: adc
|
| +; ARM32: strexd r{{[0-9]+}}, r{{[0-9]+}}, r{{[0-9]+}}, [r{{[0-9]+}}]
|
| +; ARM32: bne
|
| +; ARM32: dmb
|
|
|
| ; Test with some more register pressure. When we have an alloca, ebp is
|
| ; used to manage the stack frame, so it cannot be used as a register either.
|
| @@ -291,6 +393,14 @@ eblock:
|
| ; That pretty much leaves esi, or edi as the only viable registers.
|
| ; CHECK: lock cmpxchg8b QWORD PTR [e{{[ds]}}i]
|
| ; CHECK: call {{.*}} R_{{.*}} use_ptr
|
| +; ARM32-LABEL: test_atomic_rmw_add_64_alloca
|
| +; ARM32: dmb
|
| +; ARM32: ldrexd r{{[0-9]+}}, r{{[0-9]+}}, [r{{[0-9]+}}]
|
| +; ARM32: adds
|
| +; ARM32-NEXT: adc
|
| +; ARM32: strexd r{{[0-9]+}}, r{{[0-9]+}}, r{{[0-9]+}}, [r{{[0-9]+}}]
|
| +; ARM32: bne
|
| +; ARM32: dmb
|
|
|
| define i32 @test_atomic_rmw_add_32_ignored(i32 %iptr, i32 %v) {
|
| entry:
|
| @@ -302,6 +412,13 @@ entry:
|
| ; tells us that the destination variable is dead.
|
| ; CHECK-LABEL: test_atomic_rmw_add_32_ignored
|
| ; CHECK: lock xadd DWORD {{.*}},[[REG:.*]]
|
| +; ARM32-LABEL: test_atomic_rmw_add_32_ignored
|
| +; ARM32: dmb
|
| +; ARM32: ldrex
|
| +; ARM32: add
|
| +; ARM32: strex
|
| +; ARM32: bne
|
| +; ARM32: dmb
|
|
|
| ; Atomic RMW 64 needs to be expanded into its own loop.
|
| ; Make sure that works w/ non-trivial function bodies.
|
| @@ -333,6 +450,15 @@ err:
|
| ; CHECK: adc ecx,{{.*e.[^x]}}
|
| ; CHECK: lock cmpxchg8b QWORD PTR [e{{.[^x]}}+0x0]
|
| ; CHECK: jne [[LABEL]]
|
| +; ARM32-LABEL: test_atomic_rmw_add_64_loop
|
| +; ARM32: dmb
|
| +; ARM32: ldrexd r{{[0-9]+}}, r{{[0-9]+}}, [r{{[0-9]+}}]
|
| +; ARM32: adds
|
| +; ARM32-NEXT: adc
|
| +; ARM32: strexd r{{[0-9]+}}, r{{[0-9]+}}, r{{[0-9]+}}, [r{{[0-9]+}}]
|
| +; ARM32: bne
|
| +; ARM32: dmb
|
| +; ARM32: b
|
|
|
| ;; sub
|
|
|
| @@ -348,6 +474,13 @@ entry:
|
| ; CHECK: neg [[REG:.*]]
|
| ; CHECK: lock xadd BYTE {{.*}},[[REG]]
|
| ; CHECK: {{mov|movzx}} {{.*}},[[REG]]
|
| +; ARM32-LABEL: test_atomic_rmw_sub_8
|
| +; ARM32: dmb
|
| +; ARM32: ldrexb
|
| +; ARM32: sub
|
| +; ARM32: strexb
|
| +; ARM32: bne
|
| +; ARM32: dmb
|
|
|
| define i32 @test_atomic_rmw_sub_16(i32 %iptr, i32 %v) {
|
| entry:
|
| @@ -361,6 +494,13 @@ entry:
|
| ; CHECK: neg [[REG:.*]]
|
| ; CHECK: lock xadd WORD {{.*}},[[REG]]
|
| ; CHECK: {{mov|movzx}} {{.*}},[[REG]]
|
| +; ARM32-LABEL: test_atomic_rmw_sub_16
|
| +; ARM32: dmb
|
| +; ARM32: ldrexh
|
| +; ARM32: sub
|
| +; ARM32: strexh
|
| +; ARM32: bne
|
| +; ARM32: dmb
|
|
|
| define i32 @test_atomic_rmw_sub_32(i32 %iptr, i32 %v) {
|
| entry:
|
| @@ -372,6 +512,13 @@ entry:
|
| ; CHECK: neg [[REG:.*]]
|
| ; CHECK: lock xadd DWORD {{.*}},[[REG]]
|
| ; CHECK: mov {{.*}},[[REG]]
|
| +; ARM32-LABEL: test_atomic_rmw_sub_32
|
| +; ARM32: dmb
|
| +; ARM32: ldrex
|
| +; ARM32: sub
|
| +; ARM32: strex
|
| +; ARM32: bne
|
| +; ARM32: dmb
|
|
|
| define i64 @test_atomic_rmw_sub_64(i32 %iptr, i64 %v) {
|
| entry:
|
| @@ -389,7 +536,14 @@ entry:
|
| ; CHECK: sbb ecx,{{.*e.[^x]}}
|
| ; CHECK: lock cmpxchg8b QWORD PTR [e{{.[^x]}}
|
| ; CHECK: jne [[LABEL]]
|
| -
|
| +; ARM32-LABEL: test_atomic_rmw_sub_64
|
| +; ARM32: dmb
|
| +; ARM32: ldrexd r{{[0-9]+}}, r{{[0-9]+}}, [r{{[0-9]+}}]
|
| +; ARM32: subs
|
| +; ARM32-NEXT: sbc
|
| +; ARM32: strexd r{{[0-9]+}}, r{{[0-9]+}}, r{{[0-9]+}}, [r{{[0-9]+}}]
|
| +; ARM32: bne
|
| +; ARM32: dmb
|
|
|
| define i32 @test_atomic_rmw_sub_32_ignored(i32 %iptr, i32 %v) {
|
| entry:
|
| @@ -401,6 +555,13 @@ entry:
|
| ; CHECK-LABEL: test_atomic_rmw_sub_32_ignored
|
| ; CHECK: neg [[REG:.*]]
|
| ; CHECK: lock xadd DWORD {{.*}},[[REG]]
|
| +; ARM32-LABEL: test_atomic_rmw_sub_32_ignored
|
| +; ARM32: dmb
|
| +; ARM32: ldrex
|
| +; ARM32: sub
|
| +; ARM32: strex
|
| +; ARM32: bne
|
| +; ARM32: dmb
|
|
|
| ;; or
|
|
|
| @@ -419,6 +580,13 @@ entry:
|
| ; CHECK: or [[REG:[^a].]]
|
| ; CHECK: lock cmpxchg BYTE PTR [e{{[^a].}}],[[REG]]
|
| ; CHECK: jne
|
| +; ARM32-LABEL: test_atomic_rmw_or_8
|
| +; ARM32: dmb
|
| +; ARM32: ldrexb
|
| +; ARM32: orr
|
| +; ARM32: strexb
|
| +; ARM32: bne
|
| +; ARM32: dmb
|
|
|
| ; Same test as above, but with a global address to test FakeUse issues.
|
| define i32 @test_atomic_rmw_or_8_global(i32 %v) {
|
| @@ -430,6 +598,15 @@ entry:
|
| ret i32 %a_ext
|
| }
|
| ; CHECK-LABEL: test_atomic_rmw_or_8_global
|
| +; ARM32-LABEL: test_atomic_rmw_or_8_global
|
| +; ARM32: movw [[PTR:r[0-9]+]], #:lower16:Global8
|
| +; ARM32: movt [[PTR]], #:upper16:Global8
|
| +; ARM32: dmb
|
| +; ARM32: ldrexb r{{[0-9]+}}, {{[[]}}[[PTR]]{{[]]}}
|
| +; ARM32: orr
|
| +; ARM32: strexb
|
| +; ARM32: bne
|
| +; ARM32: dmb
|
|
|
| define i32 @test_atomic_rmw_or_16(i32 %iptr, i32 %v) {
|
| entry:
|
| @@ -444,6 +621,13 @@ entry:
|
| ; CHECK: or [[REG:[^a].]]
|
| ; CHECK: lock cmpxchg WORD PTR [e{{[^a].}}],[[REG]]
|
| ; CHECK: jne
|
| +; ARM32-LABEL: test_atomic_rmw_or_16
|
| +; ARM32: dmb
|
| +; ARM32: ldrexh
|
| +; ARM32: orr
|
| +; ARM32: strexh
|
| +; ARM32: bne
|
| +; ARM32: dmb
|
|
|
| ; Same test as above, but with a global address to test FakeUse issues.
|
| define i32 @test_atomic_rmw_or_16_global(i32 %v) {
|
| @@ -455,6 +639,15 @@ entry:
|
| ret i32 %a_ext
|
| }
|
| ; CHECK-LABEL: test_atomic_rmw_or_16_global
|
| +; ARM32-LABEL: test_atomic_rmw_or_16_global
|
| +; ARM32: movw [[PTR:r[0-9]+]], #:lower16:Global16
|
| +; ARM32: movt [[PTR]], #:upper16:Global16
|
| +; ARM32: dmb
|
| +; ARM32: ldrexh r{{[0-9]+}}, {{[[]}}[[PTR]]{{[]]}}
|
| +; ARM32: orr
|
| +; ARM32: strexh
|
| +; ARM32: bne
|
| +; ARM32: dmb
|
|
|
| define i32 @test_atomic_rmw_or_32(i32 %iptr, i32 %v) {
|
| entry:
|
| @@ -467,6 +660,13 @@ entry:
|
| ; CHECK: or [[REG:e[^a].]]
|
| ; CHECK: lock cmpxchg DWORD PTR [e{{[^a].}}],[[REG]]
|
| ; CHECK: jne
|
| +; ARM32-LABEL: test_atomic_rmw_or_32
|
| +; ARM32: dmb
|
| +; ARM32: ldrex
|
| +; ARM32: orr
|
| +; ARM32: strex
|
| +; ARM32: bne
|
| +; ARM32: dmb
|
|
|
| ; Same test as above, but with a global address to test FakeUse issues.
|
| define i32 @test_atomic_rmw_or_32_global(i32 %v) {
|
| @@ -476,6 +676,15 @@ entry:
|
| ret i32 %a
|
| }
|
| ; CHECK-LABEL: test_atomic_rmw_or_32_global
|
| +; ARM32-LABEL: test_atomic_rmw_or_32_global
|
| +; ARM32: movw [[PTR:r[0-9]+]], #:lower16:Global32
|
| +; ARM32: movt [[PTR]], #:upper16:Global32
|
| +; ARM32: dmb
|
| +; ARM32: ldrex r{{[0-9]+}}, {{[[]}}[[PTR]]{{[]]}}
|
| +; ARM32: orr
|
| +; ARM32: strex
|
| +; ARM32: bne
|
| +; ARM32: dmb
|
|
|
| define i64 @test_atomic_rmw_or_64(i32 %iptr, i64 %v) {
|
| entry:
|
| @@ -493,6 +702,14 @@ entry:
|
| ; CHECK: or ecx,{{.*e.[^x]}}
|
| ; CHECK: lock cmpxchg8b QWORD PTR [e{{.[^x]}}
|
| ; CHECK: jne [[LABEL]]
|
| +; ARM32-LABEL: test_atomic_rmw_or_64
|
| +; ARM32: dmb
|
| +; ARM32: ldrexd r{{[0-9]+}}, r{{[0-9]+}}, [r{{[0-9]+}}]
|
| +; ARM32: orr
|
| +; ARM32-NEXT: orr
|
| +; ARM32: strexd r{{[0-9]+}}, r{{[0-9]+}}, r{{[0-9]+}}, [r{{[0-9]+}}]
|
| +; ARM32: bne
|
| +; ARM32: dmb
|
|
|
| define i32 @test_atomic_rmw_or_32_ignored(i32 %iptr, i32 %v) {
|
| entry:
|
| @@ -508,6 +725,13 @@ entry:
|
| ; CHECK: or [[REG:e[^a].]]
|
| ; CHECK: lock cmpxchg DWORD PTR [e{{[^a].}}],[[REG]]
|
| ; CHECK: jne
|
| +; ARM32-LABEL: test_atomic_rmw_or_32_ignored
|
| +; ARM32: dmb
|
| +; ARM32: ldrex
|
| +; ARM32: orr
|
| +; ARM32: strex
|
| +; ARM32: bne
|
| +; ARM32: dmb
|
|
|
| ;; and
|
|
|
| @@ -524,6 +748,13 @@ entry:
|
| ; CHECK: and [[REG:[^a].]]
|
| ; CHECK: lock cmpxchg BYTE PTR [e{{[^a].}}],[[REG]]
|
| ; CHECK: jne
|
| +; ARM32-LABEL: test_atomic_rmw_and_8
|
| +; ARM32: dmb
|
| +; ARM32: ldrexb
|
| +; ARM32: and
|
| +; ARM32: strexb
|
| +; ARM32: bne
|
| +; ARM32: dmb
|
|
|
| define i32 @test_atomic_rmw_and_16(i32 %iptr, i32 %v) {
|
| entry:
|
| @@ -538,6 +769,13 @@ entry:
|
| ; CHECK: and
|
| ; CHECK: lock cmpxchg WORD PTR [e{{[^a].}}]
|
| ; CHECK: jne
|
| +; ARM32-LABEL: test_atomic_rmw_and_16
|
| +; ARM32: dmb
|
| +; ARM32: ldrexh
|
| +; ARM32: and
|
| +; ARM32: strexh
|
| +; ARM32: bne
|
| +; ARM32: dmb
|
|
|
| define i32 @test_atomic_rmw_and_32(i32 %iptr, i32 %v) {
|
| entry:
|
| @@ -550,6 +788,13 @@ entry:
|
| ; CHECK: and
|
| ; CHECK: lock cmpxchg DWORD PTR [e{{[^a].}}]
|
| ; CHECK: jne
|
| +; ARM32-LABEL: test_atomic_rmw_and_32
|
| +; ARM32: dmb
|
| +; ARM32: ldrex
|
| +; ARM32: and
|
| +; ARM32: strex
|
| +; ARM32: bne
|
| +; ARM32: dmb
|
|
|
| define i64 @test_atomic_rmw_and_64(i32 %iptr, i64 %v) {
|
| entry:
|
| @@ -567,6 +812,14 @@ entry:
|
| ; CHECK: and ecx,{{.*e.[^x]}}
|
| ; CHECK: lock cmpxchg8b QWORD PTR [e{{.[^x]}}
|
| ; CHECK: jne [[LABEL]]
|
| +; ARM32-LABEL: test_atomic_rmw_and_64
|
| +; ARM32: dmb
|
| +; ARM32: ldrexd r{{[0-9]+}}, r{{[0-9]+}}, [r{{[0-9]+}}]
|
| +; ARM32: and
|
| +; ARM32-NEXT: and
|
| +; ARM32: strexd r{{[0-9]+}}, r{{[0-9]+}}, r{{[0-9]+}}, [r{{[0-9]+}}]
|
| +; ARM32: bne
|
| +; ARM32: dmb
|
|
|
| define i32 @test_atomic_rmw_and_32_ignored(i32 %iptr, i32 %v) {
|
| entry:
|
| @@ -580,6 +833,13 @@ entry:
|
| ; CHECK: and
|
| ; CHECK: lock cmpxchg DWORD PTR [e{{[^a].}}]
|
| ; CHECK: jne
|
| +; ARM32-LABEL: test_atomic_rmw_and_32_ignored
|
| +; ARM32: dmb
|
| +; ARM32: ldrex
|
| +; ARM32: and
|
| +; ARM32: strex
|
| +; ARM32: bne
|
| +; ARM32: dmb
|
|
|
| ;; xor
|
|
|
| @@ -596,6 +856,13 @@ entry:
|
| ; CHECK: xor [[REG:[^a].]]
|
| ; CHECK: lock cmpxchg BYTE PTR [e{{[^a].}}],[[REG]]
|
| ; CHECK: jne
|
| +; ARM32-LABEL: test_atomic_rmw_xor_8
|
| +; ARM32: dmb
|
| +; ARM32: ldrexb
|
| +; ARM32: eor
|
| +; ARM32: strexb
|
| +; ARM32: bne
|
| +; ARM32: dmb
|
|
|
| define i32 @test_atomic_rmw_xor_16(i32 %iptr, i32 %v) {
|
| entry:
|
| @@ -610,7 +877,13 @@ entry:
|
| ; CHECK: xor
|
| ; CHECK: lock cmpxchg WORD PTR [e{{[^a].}}]
|
| ; CHECK: jne
|
| -
|
| +; ARM32-LABEL: test_atomic_rmw_xor_16
|
| +; ARM32: dmb
|
| +; ARM32: ldrexh
|
| +; ARM32: eor
|
| +; ARM32: strexh
|
| +; ARM32: bne
|
| +; ARM32: dmb
|
|
|
| define i32 @test_atomic_rmw_xor_32(i32 %iptr, i32 %v) {
|
| entry:
|
| @@ -623,6 +896,13 @@ entry:
|
| ; CHECK: xor
|
| ; CHECK: lock cmpxchg DWORD PTR [e{{[^a].}}]
|
| ; CHECK: jne
|
| +; ARM32-LABEL: test_atomic_rmw_xor_32
|
| +; ARM32: dmb
|
| +; ARM32: ldrex
|
| +; ARM32: eor
|
| +; ARM32: strex
|
| +; ARM32: bne
|
| +; ARM32: dmb
|
|
|
| define i64 @test_atomic_rmw_xor_64(i32 %iptr, i64 %v) {
|
| entry:
|
| @@ -640,6 +920,14 @@ entry:
|
| ; CHECK: or ecx,{{.*e.[^x]}}
|
| ; CHECK: lock cmpxchg8b QWORD PTR [e{{.[^x]}}
|
| ; CHECK: jne
|
| +; ARM32-LABEL: test_atomic_rmw_xor_64
|
| +; ARM32: dmb
|
| +; ARM32: ldrexd r{{[0-9]+}}, r{{[0-9]+}}, [r{{[0-9]+}}]
|
| +; ARM32: eor
|
| +; ARM32-NEXT: eor
|
| +; ARM32: strexd r{{[0-9]+}}, r{{[0-9]+}}, r{{[0-9]+}}, [r{{[0-9]+}}]
|
| +; ARM32: bne
|
| +; ARM32: dmb
|
|
|
| define i32 @test_atomic_rmw_xor_32_ignored(i32 %iptr, i32 %v) {
|
| entry:
|
| @@ -652,6 +940,13 @@ entry:
|
| ; CHECK: xor
|
| ; CHECK: lock cmpxchg DWORD PTR [e{{[^a].}}]
|
| ; CHECK: jne
|
| +; ARM32-LABEL: test_atomic_rmw_xor_32_ignored
|
| +; ARM32: dmb
|
| +; ARM32: ldrex
|
| +; ARM32: eor
|
| +; ARM32: strex
|
| +; ARM32: bne
|
| +; ARM32: dmb
|
|
|
| ;; exchange
|
|
|
| @@ -665,6 +960,13 @@ entry:
|
| }
|
| ; CHECK-LABEL: test_atomic_rmw_xchg_8
|
| ; CHECK: xchg BYTE PTR {{.*}},[[REG:.*]]
|
| +; ARM32-LABEL: test_atomic_rmw_xchg_8
|
| +; ARM32: dmb
|
| +; ARM32: ldrexb
|
| +; ARM32: strexb
|
| +; ARM32: cmp
|
| +; ARM32: bne
|
| +; ARM32: dmb
|
|
|
| define i32 @test_atomic_rmw_xchg_16(i32 %iptr, i32 %v) {
|
| entry:
|
| @@ -676,6 +978,13 @@ entry:
|
| }
|
| ; CHECK-LABEL: test_atomic_rmw_xchg_16
|
| ; CHECK: xchg WORD PTR {{.*}},[[REG:.*]]
|
| +; ARM32-LABEL: test_atomic_rmw_xchg_16
|
| +; ARM32: dmb
|
| +; ARM32: ldrexh
|
| +; ARM32: strexh
|
| +; ARM32: cmp
|
| +; ARM32: bne
|
| +; ARM32: dmb
|
|
|
| define i32 @test_atomic_rmw_xchg_32(i32 %iptr, i32 %v) {
|
| entry:
|
| @@ -685,6 +994,13 @@ entry:
|
| }
|
| ; CHECK-LABEL: test_atomic_rmw_xchg_32
|
| ; CHECK: xchg DWORD PTR {{.*}},[[REG:.*]]
|
| +; ARM32-LABEL: test_atomic_rmw_xchg_32
|
| +; ARM32: dmb
|
| +; ARM32: ldrex
|
| +; ARM32: strex
|
| +; ARM32: cmp
|
| +; ARM32: bne
|
| +; ARM32: dmb
|
|
|
| define i64 @test_atomic_rmw_xchg_64(i32 %iptr, i64 %v) {
|
| entry:
|
| @@ -700,6 +1016,13 @@ entry:
|
| ; CHECK-DAG: mov ebx
|
| ; CHECK: lock cmpxchg8b QWORD PTR [{{e.[^x]}}
|
| ; CHECK: jne
|
| +; ARM32-LABEL: test_atomic_rmw_xchg_64
|
| +; ARM32: dmb
|
| +; ARM32: ldrexd r{{[0-9]+}}, r{{[0-9]+}}, {{[[]}}[[PTR:r[0-9]+]]{{[]]}}
|
| +; ARM32: strexd r{{[0-9]+}}, r{{[0-9]+}}, r{{[0-9]+}}, {{[[]}}[[PTR]]{{[]]}}
|
| +; ARM32: cmp
|
| +; ARM32: bne
|
| +; ARM32: dmb
|
|
|
| define i32 @test_atomic_rmw_xchg_32_ignored(i32 %iptr, i32 %v) {
|
| entry:
|
| @@ -711,6 +1034,13 @@ entry:
|
| ; used to do an atomic store.
|
| ; CHECK-LABEL: test_atomic_rmw_xchg_32_ignored
|
| ; CHECK: xchg DWORD PTR {{.*}},[[REG:.*]]
|
| +; ARM32-LABEL: test_atomic_rmw_xchg_32_ignored
|
| +; ARM32: dmb
|
| +; ARM32: ldrex
|
| +; ARM32: strex
|
| +; ARM32: cmp
|
| +; ARM32: bne
|
| +; ARM32: dmb
|
|
|
| ;;;; Cmpxchg
|
|
|
| @@ -729,6 +1059,15 @@ entry:
|
| ; Need to check that eax isn't used as the address register or the desired.
|
| ; since it is already used as the *expected* register.
|
| ; CHECK: lock cmpxchg BYTE PTR [e{{[^a].}}],{{[^a]}}l
|
| +; ARM32-LABEL: test_atomic_cmpxchg_8
|
| +; ARM32: dmb
|
| +; ARM32: ldrexb
|
| +; ARM32: cmp
|
| +; ARM32: strexbeq
|
| +; ARM32: {{str|mov}}ne
|
| +; ARM32: cmpeq
|
| +; ARM32: bne
|
| +; ARM32: dmb
|
|
|
| define i32 @test_atomic_cmpxchg_16(i32 %iptr, i32 %expected, i32 %desired) {
|
| entry:
|
| @@ -743,6 +1082,15 @@ entry:
|
| ; CHECK-LABEL: test_atomic_cmpxchg_16
|
| ; CHECK: mov eax,{{.*}}
|
| ; CHECK: lock cmpxchg WORD PTR [e{{[^a].}}],{{[^a]}}x
|
| +; ARM32-LABEL: test_atomic_cmpxchg_16
|
| +; ARM32: dmb
|
| +; ARM32: ldrexh
|
| +; ARM32: cmp
|
| +; ARM32: strexheq
|
| +; ARM32: {{str|mov}}ne
|
| +; ARM32: cmpeq
|
| +; ARM32: bne
|
| +; ARM32: dmb
|
|
|
| define i32 @test_atomic_cmpxchg_32(i32 %iptr, i32 %expected, i32 %desired) {
|
| entry:
|
| @@ -754,6 +1102,15 @@ entry:
|
| ; CHECK-LABEL: test_atomic_cmpxchg_32
|
| ; CHECK: mov eax,{{.*}}
|
| ; CHECK: lock cmpxchg DWORD PTR [e{{[^a].}}],e{{[^a]}}
|
| +; ARM32-LABEL: test_atomic_cmpxchg_32
|
| +; ARM32: dmb
|
| +; ARM32: ldrex
|
| +; ARM32: cmp
|
| +; ARM32: strexeq
|
| +; ARM32: {{str|mov}}ne
|
| +; ARM32: cmpeq
|
| +; ARM32: bne
|
| +; ARM32: dmb
|
|
|
| define i64 @test_atomic_cmpxchg_64(i32 %iptr, i64 %expected, i64 %desired) {
|
| entry:
|
| @@ -772,6 +1129,17 @@ entry:
|
| ; edx and eax are already the return registers, so they don't actually
|
| ; need to be reshuffled via movs. The next test stores the result
|
| ; somewhere, so in that case they do need to be mov'ed.
|
| +; ARM32-LABEL: test_atomic_cmpxchg_64
|
| +; ARM32: dmb
|
| +; ARM32: ldrexd r{{[0-9]+}}, r{{[0-9]+}}, {{[[]}}[[PTR:r[0-9]+]]{{[]]}}
|
| +; ARM32: cmp
|
| +; ARM32-NEXT: cmpeq
|
| +; ARM32: strexdeq r{{[0-9]+}}, r{{[0-9]+}}, r{{[0-9]+}}, {{[[]}}[[PTR]]{{[]]}}
|
| +; ARM32: {{str|mov}}ne
|
| +; ARM32: {{str|mov}}ne
|
| +; ARM32: cmpeq
|
| +; ARM32: bne
|
| +; ARM32: dmb
|
|
|
| define i64 @test_atomic_cmpxchg_64_undef(i32 %iptr, i64 %desired) {
|
| entry:
|
| @@ -782,6 +1150,19 @@ entry:
|
| }
|
| ; CHECK-LABEL: test_atomic_cmpxchg_64_undef
|
| ; CHECK: lock cmpxchg8b QWORD PTR [e{{.[^x]}}+0x0]
|
| +; ARM32-LABEL: test_atomic_cmpxchg_64_undef
|
| +; ARM32: mov r{{[0-9]+}}, #0
|
| +; ARM32: mov r{{[0-9]+}}, #0
|
| +; ARM32: dmb
|
| +; ARM32: ldrexd r{{[0-9]+}}, r{{[0-9]+}}, {{[[]}}[[PTR:r[0-9]+]]{{[]]}}
|
| +; ARM32: cmp
|
| +; ARM32-NEXT: cmpeq
|
| +; ARM32: strexdeq r{{[0-9]+}}, r{{[0-9]+}}, r{{[0-9]+}}, {{[[]}}[[PTR]]{{[]]}}
|
| +; ARM32: {{str|mov}}ne
|
| +; ARM32: {{str|mov}}ne
|
| +; ARM32: cmpeq
|
| +; ARM32: bne
|
| +; ARM32: dmb
|
|
|
| ; Test a case where %old really does need to be copied out of edx:eax.
|
| define void @test_atomic_cmpxchg_64_store(i32 %ret_iptr, i32 %iptr, i64 %expected, i64 %desired) {
|
| @@ -802,6 +1183,19 @@ entry:
|
| ; CHECK: lock cmpxchg8b QWORD PTR [e{{.[^x]}}
|
| ; CHECK-DAG: mov {{.*}},edx
|
| ; CHECK-DAG: mov {{.*}},eax
|
| +; ARM32-LABEL: test_atomic_cmpxchg_64_store
|
| +; ARM32: dmb
|
| +; ARM32: ldrexd r{{[0-9]+}}, r{{[0-9]+}}, {{[[]}}[[PTR:r[0-9]+]]{{[]]}}
|
| +; ARM32: cmp
|
| +; ARM32-NEXT: cmpeq
|
| +; ARM32: strexdeq r{{[0-9]+}}, r{{[0-9]+}}, r{{[0-9]+}}, {{[[]}}[[PTR]]{{[]]}}
|
| +; ARM32: {{str|mov}}ne
|
| +; ARM32: {{str|mov}}ne
|
| +; ARM32: cmpeq
|
| +; ARM32: bne
|
| +; ARM32: dmb
|
| +; ARM32: str
|
| +; ARM32: str
|
|
|
| ; Test with some more register pressure. When we have an alloca, ebp is
|
| ; used to manage the stack frame, so it cannot be used as a register either.
|
| @@ -834,6 +1228,17 @@ eblock:
|
| ; That pretty much leaves esi, or edi as the only viable registers.
|
| ; CHECK: lock cmpxchg8b QWORD PTR [e{{[ds]}}i]
|
| ; CHECK: call {{.*}} R_{{.*}} use_ptr
|
| +; ARM32-LABEL: test_atomic_cmpxchg_64_alloca
|
| +; ARM32: dmb
|
| +; ARM32: ldrexd r{{[0-9]+}}, r{{[0-9]+}}, {{[[]}}[[PTR:r[0-9]+]]{{[]]}}
|
| +; ARM32: cmp
|
| +; ARM32-NEXT: cmpeq
|
| +; ARM32: strexdeq r{{[0-9]+}}, r{{[0-9]+}}, r{{[0-9]+}}, {{[[]}}[[PTR]]{{[]]}}
|
| +; ARM32: {{str|mov}}ne
|
| +; ARM32: {{str|mov}}ne
|
| +; ARM32: cmpeq
|
| +; ARM32: bne
|
| +; ARM32: dmb
|
|
|
| define i32 @test_atomic_cmpxchg_32_ignored(i32 %iptr, i32 %expected, i32 %desired) {
|
| entry:
|
| @@ -845,6 +1250,15 @@ entry:
|
| ; CHECK-LABEL: test_atomic_cmpxchg_32_ignored
|
| ; CHECK: mov eax,{{.*}}
|
| ; CHECK: lock cmpxchg DWORD PTR [e{{[^a].}}]
|
| +; ARM32-LABEL: test_atomic_cmpxchg_32_ignored
|
| +; ARM32: dmb
|
| +; ARM32: ldrex
|
| +; ARM32: cmp
|
| +; ARM32: strexeq
|
| +; ARM32: {{str|mov}}ne
|
| +; ARM32: cmpeq
|
| +; ARM32: bne
|
| +; ARM32: dmb
|
|
|
| define i64 @test_atomic_cmpxchg_64_ignored(i32 %iptr, i64 %expected, i64 %desired) {
|
| entry:
|
| @@ -860,6 +1274,17 @@ entry:
|
| ; CHECK-DAG: mov ecx
|
| ; CHECK-DAG: mov ebx
|
| ; CHECK: lock cmpxchg8b QWORD PTR [e{{.[^x]}}+0x0]
|
| +; ARM32-LABEL: test_atomic_cmpxchg_64_ignored
|
| +; ARM32: dmb
|
| +; ARM32: ldrexd [[R0:r[0-9]+]], [[R1:r[0-9]+]], {{[[]}}[[PTR:r[0-9]+]]{{[]]}}
|
| +; ARM32: cmp
|
| +; ARM32-NEXT: cmpeq
|
| +; ARM32: strexdeq r{{[0-9]+}}, r{{[0-9]+}}, r{{[0-9]+}}, {{[[]}}[[PTR]]{{[]]}}
|
| +; ARM32O2-NOT: {{str|mov}}ne [[R0]]
|
| +; ARM32O2-NOT: {{str|mov}}ne [[R1]]
|
| +; ARM32: cmpeq
|
| +; ARM32: bne
|
| +; ARM32: dmb
|
|
|
| ;;;; Fence and is-lock-free.
|
|
|
| @@ -870,6 +1295,8 @@ entry:
|
| }
|
| ; CHECK-LABEL: test_atomic_fence
|
| ; CHECK: mfence
|
| +; ARM32-LABEL: test_atomic_fence
|
| +; ARM32: dmb sy
|
|
|
| define void @test_atomic_fence_all() {
|
| entry:
|
| @@ -878,6 +1305,8 @@ entry:
|
| }
|
| ; CHECK-LABEL: test_atomic_fence_all
|
| ; CHECK: mfence
|
| +; ARM32-LABEL: test_atomic_fence_all
|
| +; ARM32: dmb sy
|
|
|
| define i32 @test_atomic_is_lock_free(i32 %iptr) {
|
| entry:
|
| @@ -888,6 +1317,8 @@ entry:
|
| }
|
| ; CHECK-LABEL: test_atomic_is_lock_free
|
| ; CHECK: mov {{.*}},0x1
|
| +; ARM32-LABEL: test_atomic_is_lock_free
|
| +; ARM32: movw {{.*}}, #1
|
|
|
| define i32 @test_not_lock_free(i32 %iptr) {
|
| entry:
|
| @@ -898,6 +1329,8 @@ entry:
|
| }
|
| ; CHECK-LABEL: test_not_lock_free
|
| ; CHECK: mov {{.*}},0x0
|
| +; ARM32-LABEL: test_not_lock_free
|
| +; ARM32: mov {{.*}}, #0
|
|
|
| define i32 @test_atomic_is_lock_free_ignored(i32 %iptr) {
|
| entry:
|
| @@ -911,6 +1344,9 @@ entry:
|
| ; O2-LABEL: test_atomic_is_lock_free_ignored
|
| ; O2-NOT: mov {{.*}}, 1
|
| ; O2: mov {{.*}},0x0
|
| +; ARM32O2-LABEL: test_atomic_is_lock_free_ignored
|
| +; ARM32O2-NOT: mov {{.*}}, #1
|
| +; ARM32O2: mov {{.*}}, #0
|
|
|
| ; TODO(jvoung): at some point we can take advantage of the
|
| ; fact that nacl.atomic.is.lock.free will resolve to a constant
|
|
|