| OLD | NEW |
| 1 ; This tests each of the supported NaCl atomic instructions for every | 1 ; This tests each of the supported NaCl atomic instructions for every |
| 2 ; size allowed. | 2 ; size allowed. |
| 3 | 3 |
| 4 ; RUN: %llvm2ice -O2 --verbose none %s \ | 4 ; RUN: %llvm2ice -O2 --verbose none %s \ |
| 5 ; RUN: | llvm-mc -triple=i686-none-nacl -x86-asm-syntax=intel -filetype=obj \ | 5 ; RUN: | llvm-mc -triple=i686-none-nacl -x86-asm-syntax=intel -filetype=obj \ |
| 6 ; RUN: | llvm-objdump -d --symbolize -x86-asm-syntax=intel - | FileCheck %s | 6 ; RUN: | llvm-objdump -d --symbolize -x86-asm-syntax=intel - | FileCheck %s |
| 7 ; RUN: %llvm2ice -O2 --verbose none %s \ | 7 ; RUN: %llvm2ice -O2 --verbose none %s \ |
| 8 ; RUN: | llvm-mc -triple=i686-none-nacl -x86-asm-syntax=intel -filetype=obj \ | 8 ; RUN: | llvm-mc -triple=i686-none-nacl -x86-asm-syntax=intel -filetype=obj \ |
| 9 ; RUN: | llvm-objdump -d --symbolize -x86-asm-syntax=intel - \ | 9 ; RUN: | llvm-objdump -d --symbolize -x86-asm-syntax=intel - \ |
| 10 ; RUN: | FileCheck --check-prefix=CHECKO2 %s | 10 ; RUN: | FileCheck --check-prefix=CHECKO2 %s |
| 11 ; RUN: %llvm2ice -Om1 --verbose none %s \ | 11 ; RUN: %llvm2ice -Om1 --verbose none %s \ |
| 12 ; RUN: | llvm-mc -triple=i686-none-nacl -x86-asm-syntax=intel -filetype=obj \ | 12 ; RUN: | llvm-mc -triple=i686-none-nacl -x86-asm-syntax=intel -filetype=obj \ |
| 13 ; RUN: | llvm-objdump -d --symbolize -x86-asm-syntax=intel - | FileCheck %s | 13 ; RUN: | llvm-objdump -d --symbolize -x86-asm-syntax=intel - | FileCheck %s |
| 14 ; RUN: %llvm2ice --verbose none %s | FileCheck --check-prefix=ERRORS %s | 14 ; RUN: %llvm2ice --verbose none %s | FileCheck --check-prefix=ERRORS %s |
| 15 ; RUN: %llvm2iceinsts %s | %szdiff %s | FileCheck --check-prefix=DUMP %s | 15 ; RUN: %llvm2iceinsts %s | %szdiff %s | FileCheck --check-prefix=DUMP %s |
| 16 ; RUN: %llvm2iceinsts --pnacl %s | %szdiff %s \ | 16 ; RUN: %llvm2iceinsts --pnacl %s | %szdiff %s \ |
| 17 ; RUN: | FileCheck --check-prefix=DUMP %s | 17 ; RUN: | FileCheck --check-prefix=DUMP %s |
| 18 | 18 |
| 19 ; TODO(jvoung): Uh... normally pnacl-llc is not supposed to separate the | |
| 20 ; lock from its instruction w/ bundle padding, but when processing .s | |
| 21 ; files with llvm-mc it seems be ocassionally wrong! | |
| 22 ; https://code.google.com/p/nativeclient/issues/detail?id=3929 | |
| 23 ; That makes the current "lock" checks avoid using CHECK-NEXT. | |
| 24 | |
| 25 declare i8 @llvm.nacl.atomic.load.i8(i8*, i32) | 19 declare i8 @llvm.nacl.atomic.load.i8(i8*, i32) |
| 26 declare i16 @llvm.nacl.atomic.load.i16(i16*, i32) | 20 declare i16 @llvm.nacl.atomic.load.i16(i16*, i32) |
| 27 declare i32 @llvm.nacl.atomic.load.i32(i32*, i32) | 21 declare i32 @llvm.nacl.atomic.load.i32(i32*, i32) |
| 28 declare i64 @llvm.nacl.atomic.load.i64(i64*, i32) | 22 declare i64 @llvm.nacl.atomic.load.i64(i64*, i32) |
| 29 declare void @llvm.nacl.atomic.store.i8(i8, i8*, i32) | 23 declare void @llvm.nacl.atomic.store.i8(i8, i8*, i32) |
| 30 declare void @llvm.nacl.atomic.store.i16(i16, i16*, i32) | 24 declare void @llvm.nacl.atomic.store.i16(i16, i16*, i32) |
| 31 declare void @llvm.nacl.atomic.store.i32(i32, i32*, i32) | 25 declare void @llvm.nacl.atomic.store.i32(i32, i32*, i32) |
| 32 declare void @llvm.nacl.atomic.store.i64(i64, i64*, i32) | 26 declare void @llvm.nacl.atomic.store.i64(i64, i64*, i32) |
| 33 declare i8 @llvm.nacl.atomic.rmw.i8(i32, i8*, i8, i32) | 27 declare i8 @llvm.nacl.atomic.rmw.i8(i32, i8*, i8, i32) |
| 34 declare i16 @llvm.nacl.atomic.rmw.i16(i32, i16*, i16, i32) | 28 declare i16 @llvm.nacl.atomic.rmw.i16(i32, i16*, i16, i32) |
| (...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 217 define i32 @test_atomic_rmw_add_16(i32 %iptr, i32 %v) { | 211 define i32 @test_atomic_rmw_add_16(i32 %iptr, i32 %v) { |
| 218 entry: | 212 entry: |
| 219 %trunc = trunc i32 %v to i16 | 213 %trunc = trunc i32 %v to i16 |
| 220 %ptr = inttoptr i32 %iptr to i16* | 214 %ptr = inttoptr i32 %iptr to i16* |
| 221 %a = call i16 @llvm.nacl.atomic.rmw.i16(i32 1, i16* %ptr, i16 %trunc, i32 6) | 215 %a = call i16 @llvm.nacl.atomic.rmw.i16(i32 1, i16* %ptr, i16 %trunc, i32 6) |
| 222 %a_ext = zext i16 %a to i32 | 216 %a_ext = zext i16 %a to i32 |
| 223 ret i32 %a_ext | 217 ret i32 %a_ext |
| 224 } | 218 } |
| 225 ; CHECK-LABEL: test_atomic_rmw_add_16 | 219 ; CHECK-LABEL: test_atomic_rmw_add_16 |
| 226 ; CHECK: lock | 220 ; CHECK: lock |
| 227 ; Should be using NEXT: see issue 3929 | 221 ; CHECK-NEXT: xadd word {{.*}}, [[REG:.*]] |
| 228 ; CHECK: xadd word {{.*}}, [[REG:.*]] | |
| 229 ; CHECK: mov {{.*}}, [[REG]] | 222 ; CHECK: mov {{.*}}, [[REG]] |
| 230 | 223 |
| 231 define i32 @test_atomic_rmw_add_32(i32 %iptr, i32 %v) { | 224 define i32 @test_atomic_rmw_add_32(i32 %iptr, i32 %v) { |
| 232 entry: | 225 entry: |
| 233 %ptr = inttoptr i32 %iptr to i32* | 226 %ptr = inttoptr i32 %iptr to i32* |
| 234 %a = call i32 @llvm.nacl.atomic.rmw.i32(i32 1, i32* %ptr, i32 %v, i32 6) | 227 %a = call i32 @llvm.nacl.atomic.rmw.i32(i32 1, i32* %ptr, i32 %v, i32 6) |
| 235 ret i32 %a | 228 ret i32 %a |
| 236 } | 229 } |
| 237 ; CHECK-LABEL: test_atomic_rmw_add_32 | 230 ; CHECK-LABEL: test_atomic_rmw_add_32 |
| 238 ; CHECK: lock | 231 ; CHECK: lock |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 347 entry: | 340 entry: |
| 348 %trunc = trunc i32 %v to i8 | 341 %trunc = trunc i32 %v to i8 |
| 349 %ptr = inttoptr i32 %iptr to i8* | 342 %ptr = inttoptr i32 %iptr to i8* |
| 350 %a = call i8 @llvm.nacl.atomic.rmw.i8(i32 2, i8* %ptr, i8 %trunc, i32 6) | 343 %a = call i8 @llvm.nacl.atomic.rmw.i8(i32 2, i8* %ptr, i8 %trunc, i32 6) |
| 351 %a_ext = zext i8 %a to i32 | 344 %a_ext = zext i8 %a to i32 |
| 352 ret i32 %a_ext | 345 ret i32 %a_ext |
| 353 } | 346 } |
| 354 ; CHECK-LABEL: test_atomic_rmw_sub_8 | 347 ; CHECK-LABEL: test_atomic_rmw_sub_8 |
| 355 ; CHECK: neg [[REG:.*]] | 348 ; CHECK: neg [[REG:.*]] |
| 356 ; CHECK: lock | 349 ; CHECK: lock |
| 357 ; Should be using NEXT: see issue 3929 | 350 ; CHECK-NEXT: xadd byte {{.*}}, [[REG]] |
| 358 ; CHECK: xadd byte {{.*}}, [[REG]] | |
| 359 ; CHECK: mov {{.*}}, [[REG]] | 351 ; CHECK: mov {{.*}}, [[REG]] |
| 360 | 352 |
| 361 define i32 @test_atomic_rmw_sub_16(i32 %iptr, i32 %v) { | 353 define i32 @test_atomic_rmw_sub_16(i32 %iptr, i32 %v) { |
| 362 entry: | 354 entry: |
| 363 %trunc = trunc i32 %v to i16 | 355 %trunc = trunc i32 %v to i16 |
| 364 %ptr = inttoptr i32 %iptr to i16* | 356 %ptr = inttoptr i32 %iptr to i16* |
| 365 %a = call i16 @llvm.nacl.atomic.rmw.i16(i32 2, i16* %ptr, i16 %trunc, i32 6) | 357 %a = call i16 @llvm.nacl.atomic.rmw.i16(i32 2, i16* %ptr, i16 %trunc, i32 6) |
| 366 %a_ext = zext i16 %a to i32 | 358 %a_ext = zext i16 %a to i32 |
| 367 ret i32 %a_ext | 359 ret i32 %a_ext |
| 368 } | 360 } |
| (...skipping 23 matching lines...) Expand all Loading... |
| 392 } | 384 } |
| 393 ; CHECK-LABEL: test_atomic_rmw_sub_64 | 385 ; CHECK-LABEL: test_atomic_rmw_sub_64 |
| 394 ; CHECK: push ebx | 386 ; CHECK: push ebx |
| 395 ; CHECK: mov eax, dword ptr [{{.*}}] | 387 ; CHECK: mov eax, dword ptr [{{.*}}] |
| 396 ; CHECK: mov edx, dword ptr [{{.*}} + 4] | 388 ; CHECK: mov edx, dword ptr [{{.*}} + 4] |
| 397 ; CHECK: mov ebx, eax | 389 ; CHECK: mov ebx, eax |
| 398 ; CHECK: sub ebx, {{.*e.[^x]}} | 390 ; CHECK: sub ebx, {{.*e.[^x]}} |
| 399 ; CHECK: mov ecx, edx | 391 ; CHECK: mov ecx, edx |
| 400 ; CHECK: sbb ecx, {{.*e.[^x]}} | 392 ; CHECK: sbb ecx, {{.*e.[^x]}} |
| 401 ; CHECK: lock | 393 ; CHECK: lock |
| 402 ; Should be using NEXT: see issue 3929 | 394 ; CHECK-NEXT: cmpxchg8b qword ptr [e{{.[^x]}}] |
| 403 ; CHECK: cmpxchg8b qword ptr [e{{.[^x]}}] | |
| 404 ; CHECK: jne -{{[0-9]}} | 395 ; CHECK: jne -{{[0-9]}} |
| 405 | 396 |
| 406 | 397 |
| 407 define i32 @test_atomic_rmw_sub_32_ignored(i32 %iptr, i32 %v) { | 398 define i32 @test_atomic_rmw_sub_32_ignored(i32 %iptr, i32 %v) { |
| 408 entry: | 399 entry: |
| 409 %ptr = inttoptr i32 %iptr to i32* | 400 %ptr = inttoptr i32 %iptr to i32* |
| 410 %ignored = call i32 @llvm.nacl.atomic.rmw.i32(i32 2, i32* %ptr, i32 %v, i32 6) | 401 %ignored = call i32 @llvm.nacl.atomic.rmw.i32(i32 2, i32* %ptr, i32 %v, i32 6) |
| 411 ret i32 %v | 402 ret i32 %v |
| 412 } | 403 } |
| 413 ; Could use "lock sub" instead of "neg; lock xadd" | 404 ; Could use "lock sub" instead of "neg; lock xadd" |
| (...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 564 entry: | 555 entry: |
| 565 %ptr = inttoptr i32 %iptr to i32* | 556 %ptr = inttoptr i32 %iptr to i32* |
| 566 %ignored = call i32 @llvm.nacl.atomic.rmw.i32(i32 4, i32* %ptr, i32 %v, i32 6) | 557 %ignored = call i32 @llvm.nacl.atomic.rmw.i32(i32 4, i32* %ptr, i32 %v, i32 6) |
| 567 ret i32 %v | 558 ret i32 %v |
| 568 } | 559 } |
| 569 ; CHECK-LABEL: test_atomic_rmw_and_32_ignored | 560 ; CHECK-LABEL: test_atomic_rmw_and_32_ignored |
| 570 ; Could just "lock and" | 561 ; Could just "lock and" |
| 571 ; CHECK: mov eax, dword ptr | 562 ; CHECK: mov eax, dword ptr |
| 572 ; CHECK: and | 563 ; CHECK: and |
| 573 ; CHECK: lock | 564 ; CHECK: lock |
| 574 ; Should be using NEXT: see issue 3929 | 565 ; CHECK-NEXT: cmpxchg dword ptr [e{{[^a].}}] |
| 575 ; CHECK: cmpxchg dword ptr [e{{[^a].}}] | |
| 576 ; CHECK: jne -{{[0-9]}} | 566 ; CHECK: jne -{{[0-9]}} |
| 577 | 567 |
| 578 ;; xor | 568 ;; xor |
| 579 | 569 |
| 580 define i32 @test_atomic_rmw_xor_8(i32 %iptr, i32 %v) { | 570 define i32 @test_atomic_rmw_xor_8(i32 %iptr, i32 %v) { |
| 581 entry: | 571 entry: |
| 582 %trunc = trunc i32 %v to i8 | 572 %trunc = trunc i32 %v to i8 |
| 583 %ptr = inttoptr i32 %iptr to i8* | 573 %ptr = inttoptr i32 %iptr to i8* |
| 584 %a = call i8 @llvm.nacl.atomic.rmw.i8(i32 5, i8* %ptr, i8 %trunc, i32 6) | 574 %a = call i8 @llvm.nacl.atomic.rmw.i8(i32 5, i8* %ptr, i8 %trunc, i32 6) |
| 585 %a_ext = zext i8 %a to i32 | 575 %a_ext = zext i8 %a to i32 |
| (...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 765 i64 %desired, i32 6, i32 6) | 755 i64 %desired, i32 6, i32 6) |
| 766 ret i64 %old | 756 ret i64 %old |
| 767 } | 757 } |
| 768 ; CHECK-LABEL: test_atomic_cmpxchg_64 | 758 ; CHECK-LABEL: test_atomic_cmpxchg_64 |
| 769 ; CHECK: push ebx | 759 ; CHECK: push ebx |
| 770 ; CHECK-DAG: mov edx | 760 ; CHECK-DAG: mov edx |
| 771 ; CHECK-DAG: mov eax | 761 ; CHECK-DAG: mov eax |
| 772 ; CHECK-DAG: mov ecx | 762 ; CHECK-DAG: mov ecx |
| 773 ; CHECK-DAG: mov ebx | 763 ; CHECK-DAG: mov ebx |
| 774 ; CHECK: lock | 764 ; CHECK: lock |
| 775 ; Should be using NEXT: see issue 3929 | 765 ; CHECK-NEXT: cmpxchg8b qword ptr [e{{.[^x]}}] |
| 776 ; CHECK: cmpxchg8b qword ptr [e{{.[^x]}}] | |
| 777 ; edx and eax are already the return registers, so they don't actually | 766 ; edx and eax are already the return registers, so they don't actually |
| 778 ; need to be reshuffled via movs. The next test stores the result | 767 ; need to be reshuffled via movs. The next test stores the result |
| 779 ; somewhere, so in that case they do need to be mov'ed. | 768 ; somewhere, so in that case they do need to be mov'ed. |
| 780 | 769 |
| 781 ; Test a case where %old really does need to be copied out of edx:eax. | 770 ; Test a case where %old really does need to be copied out of edx:eax. |
| 782 define void @test_atomic_cmpxchg_64_store(i32 %ret_iptr, i32 %iptr, i64 %expecte
d, i64 %desired) { | 771 define void @test_atomic_cmpxchg_64_store(i32 %ret_iptr, i32 %iptr, i64 %expecte
d, i64 %desired) { |
| 783 entry: | 772 entry: |
| 784 %ptr = inttoptr i32 %iptr to i64* | 773 %ptr = inttoptr i32 %iptr to i64* |
| 785 %old = call i64 @llvm.nacl.atomic.cmpxchg.i64(i64* %ptr, i64 %expected, | 774 %old = call i64 @llvm.nacl.atomic.cmpxchg.i64(i64* %ptr, i64 %expected, |
| 786 i64 %desired, i32 6, i32 6) | 775 i64 %desired, i32 6, i32 6) |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 820 ; CHECK-DAG: mov edx | 809 ; CHECK-DAG: mov edx |
| 821 ; CHECK-DAG: mov eax | 810 ; CHECK-DAG: mov eax |
| 822 ; CHECK-DAG: mov ecx | 811 ; CHECK-DAG: mov ecx |
| 823 ; CHECK-DAG: mov ebx | 812 ; CHECK-DAG: mov ebx |
| 824 ; Ptr cannot be eax, ebx, ecx, or edx (used up for the expected and desired). | 813 ; Ptr cannot be eax, ebx, ecx, or edx (used up for the expected and desired). |
| 825 ; It also cannot be ebp since we use that for alloca. Also make sure it's | 814 ; It also cannot be ebp since we use that for alloca. Also make sure it's |
| 826 ; not esp, since that's the stack pointer and mucking with it will break | 815 ; not esp, since that's the stack pointer and mucking with it will break |
| 827 ; the later use_ptr function call. | 816 ; the later use_ptr function call. |
| 828 ; That pretty much leaves esi, or edi as the only viable registers. | 817 ; That pretty much leaves esi, or edi as the only viable registers. |
| 829 ; CHECK: lock | 818 ; CHECK: lock |
| 830 ; Should be using NEXT: see issue 3929 | 819 ; CHECK-NEXT: cmpxchg8b qword ptr [e{{[ds]}}i] |
| 831 ; CHECK: cmpxchg8b qword ptr [e{{[ds]}}i] | |
| 832 ; CHECK: call use_ptr | 820 ; CHECK: call use_ptr |
| 833 | 821 |
| 834 define i32 @test_atomic_cmpxchg_32_ignored(i32 %iptr, i32 %expected, i32 %desire
d) { | 822 define i32 @test_atomic_cmpxchg_32_ignored(i32 %iptr, i32 %expected, i32 %desire
d) { |
| 835 entry: | 823 entry: |
| 836 %ptr = inttoptr i32 %iptr to i32* | 824 %ptr = inttoptr i32 %iptr to i32* |
| 837 %ignored = call i32 @llvm.nacl.atomic.cmpxchg.i32(i32* %ptr, i32 %expected, | 825 %ignored = call i32 @llvm.nacl.atomic.cmpxchg.i32(i32* %ptr, i32 %expected, |
| 838 i32 %desired, i32 6, i32 6) | 826 i32 %desired, i32 6, i32 6) |
| 839 ret i32 0 | 827 ret i32 0 |
| 840 } | 828 } |
| 841 ; CHECK-LABEL: test_atomic_cmpxchg_32_ignored | 829 ; CHECK-LABEL: test_atomic_cmpxchg_32_ignored |
| 842 ; CHECK: mov eax, {{.*}} | 830 ; CHECK: mov eax, {{.*}} |
| 843 ; CHECK: lock | 831 ; CHECK: lock |
| 844 ; CHECK-NEXT: cmpxchg dword ptr [e{{[^a].}}] | 832 ; CHECK-NEXT: cmpxchg dword ptr [e{{[^a].}}] |
| 845 | 833 |
| 846 define i64 @test_atomic_cmpxchg_64_ignored(i32 %iptr, i64 %expected, i64 %desire
d) { | 834 define i64 @test_atomic_cmpxchg_64_ignored(i32 %iptr, i64 %expected, i64 %desire
d) { |
| 847 entry: | 835 entry: |
| 848 %ptr = inttoptr i32 %iptr to i64* | 836 %ptr = inttoptr i32 %iptr to i64* |
| 849 %ignored = call i64 @llvm.nacl.atomic.cmpxchg.i64(i64* %ptr, i64 %expected, | 837 %ignored = call i64 @llvm.nacl.atomic.cmpxchg.i64(i64* %ptr, i64 %expected, |
| 850 i64 %desired, i32 6, i32 6) | 838 i64 %desired, i32 6, i32 6) |
| 851 ret i64 0 | 839 ret i64 0 |
| 852 } | 840 } |
| 853 ; CHECK-LABEL: test_atomic_cmpxchg_64_ignored | 841 ; CHECK-LABEL: test_atomic_cmpxchg_64_ignored |
| 854 ; CHECK: push ebx | 842 ; CHECK: push ebx |
| 855 ; CHECK-DAG: mov edx | 843 ; CHECK-DAG: mov edx |
| 856 ; CHECK-DAG: mov eax | 844 ; CHECK-DAG: mov eax |
| 857 ; CHECK-DAG: mov ecx | 845 ; CHECK-DAG: mov ecx |
| 858 ; CHECK-DAG: mov ebx | 846 ; CHECK-DAG: mov ebx |
| 859 ; CHECK: lock | 847 ; CHECK: lock |
| 860 ; Should be using NEXT: see issue 3929 | 848 ; CHECK-NEXT: cmpxchg8b qword ptr [e{{.[^x]}}] |
| 861 ; CHECK: cmpxchg8b qword ptr [e{{.[^x]}}] | |
| 862 | 849 |
| 863 ;;;; Fence and is-lock-free. | 850 ;;;; Fence and is-lock-free. |
| 864 | 851 |
| 865 define void @test_atomic_fence() { | 852 define void @test_atomic_fence() { |
| 866 entry: | 853 entry: |
| 867 call void @llvm.nacl.atomic.fence(i32 6) | 854 call void @llvm.nacl.atomic.fence(i32 6) |
| 868 ret void | 855 ret void |
| 869 } | 856 } |
| 870 ; CHECK-LABEL: test_atomic_fence | 857 ; CHECK-LABEL: test_atomic_fence |
| 871 ; CHECK: mfence | 858 ; CHECK: mfence |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 930 ret i32 %z | 917 ret i32 %z |
| 931 } | 918 } |
| 932 ; CHECK-LABEL: test_atomic_is_lock_free_can_dce | 919 ; CHECK-LABEL: test_atomic_is_lock_free_can_dce |
| 933 ; CHECK: mov {{.*}}, 1 | 920 ; CHECK: mov {{.*}}, 1 |
| 934 ; CHECK: ret | 921 ; CHECK: ret |
| 935 ; CHECK: add | 922 ; CHECK: add |
| 936 ; CHECK: ret | 923 ; CHECK: ret |
| 937 | 924 |
| 938 ; ERRORS-NOT: ICE translation error | 925 ; ERRORS-NOT: ICE translation error |
| 939 ; DUMP-NOT: SZ | 926 ; DUMP-NOT: SZ |
| OLD | NEW |