|
2016 | 2016 |
|
2017 | 2017 | (rule (lower (get_return_address)) |
2018 | 2018 | (aarch64_link)) |
| 2019 | + |
| 2020 | +;;; Rules for `{get,set}_pinned_reg` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
| 2021 | + |
| 2022 | +(rule (lower (get_pinned_reg)) |
| 2023 | + (pinned_reg)) |
| 2024 | + |
| 2025 | +(rule (lower (set_pinned_reg val)) |
| 2026 | + (side_effect (write_pinned_reg val))) |
| 2027 | + |
| 2028 | +;;; Rules for `bitcast` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
| 2029 | + |
| 2030 | +(rule (lower (has_type $I32 (bitcast src @ (value_type $F32)))) |
| 2031 | + (mov_from_vec src 0 (ScalarSize.Size32))) |
| 2032 | + |
| 2033 | +(rule (lower (has_type $F32 (bitcast src @ (value_type $I32)))) |
| 2034 | + (mov_to_fpu src (ScalarSize.Size32))) |
| 2035 | + |
| 2036 | +(rule (lower (has_type $I64 (bitcast src @ (value_type $F64)))) |
| 2037 | + (mov_from_vec src 0 (ScalarSize.Size64))) |
| 2038 | + |
| 2039 | +(rule (lower (has_type $F64 (bitcast src @ (value_type $I64)))) |
| 2040 | + (mov_to_fpu src (ScalarSize.Size64))) |
| 2041 | + |
| 2042 | +;;; Rules for `raw_bitcast` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
| 2043 | + |
| 2044 | +(rule (lower (raw_bitcast val)) |
| 2045 | + val) |
| 2046 | + |
| 2047 | +;;; Rules for `extractlane` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
| 2048 | + |
| 2049 | +;; extractlane with lane 0 can pass through the value unchanged; upper |
| 2050 | +;; bits are undefined when a narrower type is in a wider register. |
| 2051 | +(rule (lower (has_type (ty_scalar_float _) (extractlane val (u8_from_uimm8 0)))) |
| 2052 | + val) |
| 2053 | + |
| 2054 | +(rule (lower (has_type (ty_int_bool ty) |
| 2055 | + (extractlane val |
| 2056 | + (u8_from_uimm8 lane)))) |
| 2057 | + (mov_from_vec val lane (scalar_size ty))) |
| 2058 | + |
| 2059 | +(rule (lower (has_type (ty_scalar_float ty) |
| 2060 | + (extractlane val @ (value_type vty) |
| 2061 | + (u8_from_uimm8 lane)))) |
| 2062 | + (fpu_move_from_vec val lane (vector_size vty))) |
| 2063 | + |
| 2064 | +;;; Rules for `insertlane` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
| 2065 | + |
| 2066 | +(rule (lower (insertlane vec @ (value_type vty) |
| 2067 | + val @ (value_type (ty_int_bool _)) |
| 2068 | + (u8_from_uimm8 lane))) |
| 2069 | + (mov_to_vec vec val lane (vector_size vty))) |
| 2070 | + |
| 2071 | +(rule (lower (insertlane vec @ (value_type vty) |
| 2072 | + val @ (value_type (ty_scalar_float _)) |
| 2073 | + (u8_from_uimm8 lane))) |
| 2074 | + (mov_vec_elem vec val lane 0 (vector_size vty))) |
| 2075 | + |
| 2076 | +;;; Rules for `copy` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
| 2077 | + |
| 2078 | +(rule (lower (copy x)) |
| 2079 | + x) |
| 2080 | + |
| 2081 | +;;; Rules for `stack_addr` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
| 2082 | + |
| 2083 | +(rule (lower (stack_addr stack_slot offset)) |
| 2084 | + (compute_stack_addr stack_slot offset)) |
| 2085 | + |
| 2086 | +;;; Rules for `vhigh_bits` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
| 2087 | + |
| 2088 | +;; All three sequences use one integer temporary and two vector |
| 2089 | +;; temporaries. The shift is done early so as to give the register |
| 2090 | +;; allocator the possibility of using the same reg for `tmp_v1` and |
| 2091 | +;; `src_v` in the case that this is the last use of `src_v`. See |
| 2092 | +;; https://github.com/WebAssembly/simd/pull/201 for the background and |
| 2093 | +;; derivation of these sequences. Alternative sequences are discussed |
| 2094 | +;; in https://github.com/bytecodealliance/wasmtime/issues/2296, |
| 2095 | +;; although they are not used here. |
| 2096 | + |
| 2097 | +(rule (lower (vhigh_bits vec @ (value_type $I8X16))) |
| 2098 | + (let ( |
| 2099 | + ;; Replicate the MSB of each of the 16 byte lanes across |
| 2100 | + ;; the whole lane (sshr is an arithmetic right shift). |
| 2101 | + (shifted Reg (vec_shift_imm (VecShiftImmOp.Sshr) 7 vec (VectorSize.Size8x16))) |
| 2102 | + ;; Bitwise-and with a mask |
| 2103 | + ;; `0x80402010_08040201_80402010_08040201` to get the bit |
| 2104 | + ;; in the proper location for each group of 8 lanes. |
| 2105 | + (anded Reg (and_vec shifted (constant_f128 0x80402010_08040201_80402010_08040201) (VectorSize.Size8x16))) |
| 2106 | + ;; Produce a version of `anded` with upper 8 lanes and |
| 2107 | + ;; lower 8 lanes swapped. |
| 2108 | + (anded_swapped Reg (vec_extract anded anded 8)) |
| 2109 | + ;; Zip together the two; with the above this produces the lane permutation: |
| 2110 | + ;; 15 7 14 6 13 5 12 4 11 3 10 2 9 1 8 0 |
| 2111 | + (zipped Reg (zip1 anded anded_swapped (VectorSize.Size8x16))) |
| 2112 | + ;; Add 16-bit lanes together ("add across vector"), so we |
| 2113 | + ;; get, in the low 16 bits, 15+14+...+8 in the high byte |
| 2114 | + ;; and 7+6+...+0 in the low byte. This effectively puts |
| 2115 | + ;; the 16 MSBs together, giving our results. |
| 2116 | + ;; |
| 2117 | + ;; N.B.: `Size16x8` is not a typo! |
| 2118 | + (result Reg (addv zipped (VectorSize.Size16x8)))) |
| 2119 | + (mov_from_vec result 0 (ScalarSize.Size16)))) |
| 2120 | + |
| 2121 | +(rule (lower (vhigh_bits vec @ (value_type $I16X8))) |
| 2122 | + (let ( |
| 2123 | + ;; Replicate the MSB of each of the 8 16-bit lanes across |
| 2124 | + ;; the whole lane (sshr is an arithmetic right shift). |
| 2125 | + (shifted Reg (vec_shift_imm (VecShiftImmOp.Sshr) 15 vec (VectorSize.Size16x8))) |
| 2126 | + ;; Bitwise-and with a mask |
| 2127 | + ;; `0x0080_0040_0020_0010_0008_0004_0002_0001` to get the |
| 2128 | + ;; bit in the proper location for each group of 4 lanes. |
| 2129 | + (anded Reg (and_vec shifted (constant_f128 0x0080_0040_0020_0010_0008_0004_0002_0001) (VectorSize.Size16x8))) |
| 2130 | + ;; Add lanes together to get the 8 MSBs in the low byte. |
| 2131 | + (result Reg (addv anded (VectorSize.Size16x8)))) |
| 2132 | + (mov_from_vec result 0 (ScalarSize.Size16)))) |
| 2133 | + |
| 2134 | +(rule (lower (vhigh_bits vec @ (value_type $I32X4))) |
| 2135 | + (let ( |
| 2136 | + ;; Replicate the MSB of each of the 4 32-bit lanes across |
| 2137 | + ;; the whole lane (sshr is an arithmetic right shift). |
| 2138 | + (shifted Reg (vec_shift_imm (VecShiftImmOp.Sshr) 31 vec (VectorSize.Size32x4))) |
| 2139 | + ;; Bitwise-and with a mask |
| 2140 | + ;; `0x00000008_00000004_00000002_00000001` to get the bit |
| 2141 | + ;; in the proper location for each group of 4 lanes. |
| 2142 | + (anded Reg (and_vec shifted (constant_f128 0x00000008_00000004_00000002_00000001) (VectorSize.Size32x4))) |
| 2143 | + ;; Add lanes together to get the 4 MSBs in the low byte. |
| 2144 | + (result Reg (addv anded (VectorSize.Size32x4)))) |
| 2145 | + (mov_from_vec result 0 (ScalarSize.Size32)))) |
| 2146 | + |
| 2147 | +(rule (lower (vhigh_bits vec @ (value_type $I64X2))) |
| 2148 | + (let ( |
| 2149 | + ;; Grab the MSB out of each of the lanes, right-shift to |
| 2150 | + ;; LSB, and add with a left-shift of upper lane's MSB back |
| 2151 | + ;; to bit 1. the whole lane (sshr is an arithmetic right |
| 2152 | + ;; shift). |
| 2153 | + (upper_msb Reg (mov_from_vec vec 1 (ScalarSize.Size64))) |
| 2154 | + (lower_msb Reg (mov_from_vec vec 0 (ScalarSize.Size64))) |
| 2155 | + (upper_msb Reg (lsr_imm $I64 upper_msb (imm_shift_from_u8 63))) |
| 2156 | + (lower_msb Reg (lsr_imm $I64 lower_msb (imm_shift_from_u8 63)))) |
| 2157 | + (add_shift $I64 lower_msb upper_msb (lshl_from_u64 $I64 1)))) |
| 2158 | + |
| 2159 | +;;; Rules for `iadd_ifcout` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
| 2160 | + |
| 2161 | +;; This is a two-output instruction that is needed for the |
| 2162 | +;; legalizer's explicit heap-check sequence, among possible other |
| 2163 | +;; uses. Its second output is a flags output only ever meant to |
| 2164 | +;; check for overflow using the |
| 2165 | +;; `backend.unsigned_add_overflow_condition()` condition. |
| 2166 | +;; |
| 2167 | +;; Note that the CLIF validation will ensure that no flag-setting |
| 2168 | +;; operation comes between this IaddIfcout and its use (e.g., a |
| 2169 | +;; Trapif). Thus, we can rely on implicit communication through the |
| 2170 | +;; processor flags rather than explicitly generating flags into a |
| 2171 | +;; register. We simply use the variant of the add instruction that |
| 2172 | +;; sets flags (`adds`) here. |
| 2173 | +;; |
| 2174 | +;; Note that the second output (the flags) need not be generated, |
| 2175 | +;; because flags are never materialized into a register; the only |
| 2176 | +;; instructions that can use a value of type `iflags` or `fflags` |
| 2177 | +;; will look directly for the flags-producing instruction (which can |
| 2178 | +;; always be found, by construction) and merge it. |
| 2179 | +;; |
| 2180 | +;; Now handle the iadd as above, except use an AddS opcode that sets |
| 2181 | +;; flags. |
| 2182 | + |
| 2183 | +(rule (lower (has_type (ty_int ty) |
| 2184 | + (iadd_ifcout a b))) |
| 2185 | + (output_pair |
| 2186 | + (add_with_flags ty a b) |
| 2187 | + (invalid_reg))) |
| 2188 | + |
| 2189 | +;;; Rules for `tls_value` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
| 2190 | + |
| 2191 | +;; TODO. |
| 2192 | + |
| 2193 | +;;; Rules for `fcvt_low_from_sint` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
| 2194 | + |
| 2195 | +(rule (lower (has_type $F64X2 (fcvt_low_from_sint val))) |
| 2196 | + (let ((extended Reg (vec_extend (VecExtendOp.Sxtl) val $false (ScalarSize.Size64))) |
| 2197 | + (converted Reg (vec_misc (VecMisc2.Scvtf) extended (VectorSize.Size64x2)))) |
| 2198 | + converted)) |
| 2199 | + |
| 2200 | +;;; Rules for `fvpromote_low` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
| 2201 | + |
| 2202 | +(rule (lower (fvpromote_low val)) |
| 2203 | + (vec_rr_long (VecRRLongOp.Fcvtl32) val $false)) |
| 2204 | + |
| 2205 | +;;; Rules for `select` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
| 2206 | + |
| 2207 | +;; TODO: requires icmp/fcmp first. |
| 2208 | + |
| 2209 | +;;; Rules for `selectif` / `selectif_spectre_guard` ;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
| 2210 | + |
| 2211 | +;; TODO: requires icmp/fcmp first. |
| 2212 | + |
| 2213 | +;;; Rules for `trueif` / `trueff` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
| 2214 | + |
| 2215 | +;; TODO: requires icmp/fcmp first. |
| 2216 | + |
| 2217 | +;;; Rules for `brz`/`brnz`/`brif`/`brff`/`bricmp` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
| 2218 | + |
| 2219 | +;; TODO: requires icmp/fcmp first. |
| 2220 | + |
| 2221 | +;;; Rules for `jump` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
| 2222 | + |
| 2223 | +;; TODO. |
| 2224 | + |
| 2225 | +;;; Rules for `br_table` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
| 2226 | + |
| 2227 | +;; TODO. |
0 commit comments