|
7 | 7 | (type $i64 (struct (field (mut i64)))) |
8 | 8 | ;; CHECK: (type $struct (struct (field (mut (ref null $struct))))) |
9 | 9 | (type $struct (struct (field (mut (ref null $struct))))) |
10 | | - |
11 | 10 | ;; CHECK: (type $1 (func (result i32))) |
12 | 11 |
|
13 | 12 | ;; CHECK: (type $2 (func (result i64))) |
|
16 | 15 |
|
17 | 16 | ;; CHECK: (type $4 (func (param (ref null $struct) (ref null $struct)) (result (ref null $struct)))) |
18 | 17 |
|
| 18 | + ;; CHECK: (type $5 (func (param i32) (result i32))) |
| 19 | + |
| 20 | + ;; CHECK: (type $arr (array (mut i32))) |
| 21 | + (type $arr (array (mut i32))) |
| 22 | + |
19 | 23 | ;; CHECK: (func $escape-rmw (type $3) (param $0 (ref null $struct)) (result (ref null $struct)) |
20 | 24 | ;; CHECK-NEXT: (struct.atomic.rmw.xchg $struct 0 |
21 | 25 | ;; CHECK-NEXT: (local.get $0) |
|
750 | 754 | (i32.const 1) |
751 | 755 | ) |
752 | 756 | ) |
| 757 | + |
| 758 | + ;; CHECK: (func $array-rmw-add (type $1) (result i32) |
| 759 | + ;; CHECK-NEXT: (local $0 i32) |
| 760 | + ;; CHECK-NEXT: (local $1 i32) |
| 761 | + ;; CHECK-NEXT: (local $2 i32) |
| 762 | + ;; CHECK-NEXT: (local $3 i32) |
| 763 | + ;; CHECK-NEXT: (local $4 i32) |
| 764 | + ;; CHECK-NEXT: (local $5 i32) |
| 765 | + ;; CHECK-NEXT: (drop |
| 766 | + ;; CHECK-NEXT: (block (result nullref) |
| 767 | + ;; CHECK-NEXT: (local.set $2 |
| 768 | + ;; CHECK-NEXT: (i32.const 0) |
| 769 | + ;; CHECK-NEXT: ) |
| 770 | + ;; CHECK-NEXT: (local.set $3 |
| 771 | + ;; CHECK-NEXT: (i32.const 0) |
| 772 | + ;; CHECK-NEXT: ) |
| 773 | + ;; CHECK-NEXT: (local.set $0 |
| 774 | + ;; CHECK-NEXT: (local.get $2) |
| 775 | + ;; CHECK-NEXT: ) |
| 776 | + ;; CHECK-NEXT: (local.set $1 |
| 777 | + ;; CHECK-NEXT: (local.get $3) |
| 778 | + ;; CHECK-NEXT: ) |
| 779 | + ;; CHECK-NEXT: (ref.null none) |
| 780 | + ;; CHECK-NEXT: ) |
| 781 | + ;; CHECK-NEXT: ) |
| 782 | + ;; CHECK-NEXT: (local.set $5 |
| 783 | + ;; CHECK-NEXT: (i32.const 1) |
| 784 | + ;; CHECK-NEXT: ) |
| 785 | + ;; CHECK-NEXT: (local.set $4 |
| 786 | + ;; CHECK-NEXT: (local.get $0) |
| 787 | + ;; CHECK-NEXT: ) |
| 788 | + ;; CHECK-NEXT: (local.set $0 |
| 789 | + ;; CHECK-NEXT: (i32.add |
| 790 | + ;; CHECK-NEXT: (local.get $0) |
| 791 | + ;; CHECK-NEXT: (local.get $5) |
| 792 | + ;; CHECK-NEXT: ) |
| 793 | + ;; CHECK-NEXT: ) |
| 794 | + ;; CHECK-NEXT: (local.get $4) |
| 795 | + ;; CHECK-NEXT: ) |
| 796 | + (func $array-rmw-add (result i32) |
| 797 | + ;; Array atomic RMW on a non-escaping fixed-size array should be |
| 798 | + ;; optimized: the array is converted to a struct, then to locals. |
| 799 | + (array.atomic.rmw.add $arr |
| 800 | + (array.new_fixed $arr 2 |
| 801 | + (i32.const 0) |
| 802 | + (i32.const 0) |
| 803 | + ) |
| 804 | + (i32.const 0) |
| 805 | + (i32.const 1) |
| 806 | + ) |
| 807 | + ) |
| 808 | + |
| 809 | + ;; CHECK: (func $array-cmpxchg (type $1) (result i32) |
| 810 | + ;; CHECK-NEXT: (local $0 i32) |
| 811 | + ;; CHECK-NEXT: (local $1 i32) |
| 812 | + ;; CHECK-NEXT: (local $2 i32) |
| 813 | + ;; CHECK-NEXT: (local $3 i32) |
| 814 | + ;; CHECK-NEXT: (local $4 i32) |
| 815 | + ;; CHECK-NEXT: (local $5 i32) |
| 816 | + ;; CHECK-NEXT: (local $6 i32) |
| 817 | + ;; CHECK-NEXT: (drop |
| 818 | + ;; CHECK-NEXT: (block (result nullref) |
| 819 | + ;; CHECK-NEXT: (local.set $2 |
| 820 | + ;; CHECK-NEXT: (i32.const 0) |
| 821 | + ;; CHECK-NEXT: ) |
| 822 | + ;; CHECK-NEXT: (local.set $3 |
| 823 | + ;; CHECK-NEXT: (i32.const 0) |
| 824 | + ;; CHECK-NEXT: ) |
| 825 | + ;; CHECK-NEXT: (local.set $0 |
| 826 | + ;; CHECK-NEXT: (local.get $2) |
| 827 | + ;; CHECK-NEXT: ) |
| 828 | + ;; CHECK-NEXT: (local.set $1 |
| 829 | + ;; CHECK-NEXT: (local.get $3) |
| 830 | + ;; CHECK-NEXT: ) |
| 831 | + ;; CHECK-NEXT: (ref.null none) |
| 832 | + ;; CHECK-NEXT: ) |
| 833 | + ;; CHECK-NEXT: ) |
| 834 | + ;; CHECK-NEXT: (local.set $5 |
| 835 | + ;; CHECK-NEXT: (i32.const 10) |
| 836 | + ;; CHECK-NEXT: ) |
| 837 | + ;; CHECK-NEXT: (local.set $6 |
| 838 | + ;; CHECK-NEXT: (i32.const 20) |
| 839 | + ;; CHECK-NEXT: ) |
| 840 | + ;; CHECK-NEXT: (local.set $4 |
| 841 | + ;; CHECK-NEXT: (local.get $0) |
| 842 | + ;; CHECK-NEXT: ) |
| 843 | + ;; CHECK-NEXT: (if |
| 844 | + ;; CHECK-NEXT: (i32.eq |
| 845 | + ;; CHECK-NEXT: (local.get $0) |
| 846 | + ;; CHECK-NEXT: (local.get $5) |
| 847 | + ;; CHECK-NEXT: ) |
| 848 | + ;; CHECK-NEXT: (then |
| 849 | + ;; CHECK-NEXT: (local.set $0 |
| 850 | + ;; CHECK-NEXT: (local.get $6) |
| 851 | + ;; CHECK-NEXT: ) |
| 852 | + ;; CHECK-NEXT: ) |
| 853 | + ;; CHECK-NEXT: ) |
| 854 | + ;; CHECK-NEXT: (local.get $4) |
| 855 | + ;; CHECK-NEXT: ) |
| 856 | + (func $array-cmpxchg (result i32) |
| 857 | + ;; Array atomic cmpxchg on a non-escaping fixed-size array should be |
| 858 | + ;; optimized similarly. |
| 859 | + (array.atomic.rmw.cmpxchg $arr |
| 860 | + (array.new_fixed $arr 2 |
| 861 | + (i32.const 0) |
| 862 | + (i32.const 0) |
| 863 | + ) |
| 864 | + (i32.const 0) |
| 865 | + (i32.const 10) |
| 866 | + (i32.const 20) |
| 867 | + ) |
| 868 | + ) |
| 869 | + |
| 870 | + ;; CHECK: (func $array-rmw-nonconstant-index (type $5) (param $idx i32) (result i32) |
| 871 | + ;; CHECK-NEXT: (array.atomic.rmw.add $arr |
| 872 | + ;; CHECK-NEXT: (array.new_fixed $arr 2 |
| 873 | + ;; CHECK-NEXT: (i32.const 0) |
| 874 | + ;; CHECK-NEXT: (i32.const 0) |
| 875 | + ;; CHECK-NEXT: ) |
| 876 | + ;; CHECK-NEXT: (local.get $idx) |
| 877 | + ;; CHECK-NEXT: (i32.const 1) |
| 878 | + ;; CHECK-NEXT: ) |
| 879 | + ;; CHECK-NEXT: ) |
| 880 | + (func $array-rmw-nonconstant-index (param $idx i32) (result i32) |
| 881 | + ;; A non-constant index prevents the optimization, since Array2Struct |
| 882 | + ;; needs to know which struct field to access at compile time. |
| 883 | + (array.atomic.rmw.add $arr |
| 884 | + (array.new_fixed $arr 2 |
| 885 | + (i32.const 0) |
| 886 | + (i32.const 0) |
| 887 | + ) |
| 888 | + (local.get $idx) |
| 889 | + (i32.const 1) |
| 890 | + ) |
| 891 | + ) |
| 892 | + |
| 893 | + ;; CHECK: (func $array-rmw-oob (type $1) (result i32) |
| 894 | + ;; CHECK-NEXT: (drop |
| 895 | + ;; CHECK-NEXT: (block (result nullref) |
| 896 | + ;; CHECK-NEXT: (ref.null none) |
| 897 | + ;; CHECK-NEXT: ) |
| 898 | + ;; CHECK-NEXT: ) |
| 899 | + ;; CHECK-NEXT: (drop |
| 900 | + ;; CHECK-NEXT: (i32.const 1) |
| 901 | + ;; CHECK-NEXT: ) |
| 902 | + ;; CHECK-NEXT: (unreachable) |
| 903 | + ;; CHECK-NEXT: ) |
| 904 | + (func $array-rmw-oob (result i32) |
| 905 | + ;; An out-of-bounds index on a zero-size array. The access will always |
| 906 | + ;; trap, so we emit drops for operands and an unreachable. |
| 907 | + (array.atomic.rmw.add $arr |
| 908 | + (array.new_default $arr |
| 909 | + (i32.const 0) |
| 910 | + ) |
| 911 | + (i32.const 0) |
| 912 | + (i32.const 1) |
| 913 | + ) |
| 914 | + ) |
| 915 | + |
| 916 | + ;; CHECK: (func $array-cmpxchg-oob (type $1) (result i32) |
| 917 | + ;; CHECK-NEXT: (drop |
| 918 | + ;; CHECK-NEXT: (block (result nullref) |
| 919 | + ;; CHECK-NEXT: (ref.null none) |
| 920 | + ;; CHECK-NEXT: ) |
| 921 | + ;; CHECK-NEXT: ) |
| 922 | + ;; CHECK-NEXT: (drop |
| 923 | + ;; CHECK-NEXT: (i32.const 10) |
| 924 | + ;; CHECK-NEXT: ) |
| 925 | + ;; CHECK-NEXT: (drop |
| 926 | + ;; CHECK-NEXT: (i32.const 20) |
| 927 | + ;; CHECK-NEXT: ) |
| 928 | + ;; CHECK-NEXT: (unreachable) |
| 929 | + ;; CHECK-NEXT: ) |
| 930 | + (func $array-cmpxchg-oob (result i32) |
| 931 | + ;; As above, but for cmpxchg with an out-of-bounds index. |
| 932 | + (array.atomic.rmw.cmpxchg $arr |
| 933 | + (array.new_default $arr |
| 934 | + (i32.const 0) |
| 935 | + ) |
| 936 | + (i32.const 0) |
| 937 | + (i32.const 10) |
| 938 | + (i32.const 20) |
| 939 | + ) |
| 940 | + ) |
753 | 941 | ) |
0 commit comments