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 |