1;; Pulley instruction selection and CLIF-to-MachInst lowering. 2 3;; The main lowering constructor term: takes a clif `Inst` and returns the 4;; register(s) within which the lowered instruction's result values live. 5(decl partial lower (Inst) InstOutput) 6 7;;;; Rules for Control Flow ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 8 9;; Helper to place a conditional `Value` provided into a register. Pulley 10;; conditional values occupy the full low 32-bits of a register and so this 11;; needs to handle situations such as when the `Value` is 64-bits an explicit 12;; comparison must be made. Additionally if `Value` is smaller than 32-bits 13;; then it must be sign-extended up to at least 32 bits. 14(decl lower_cond (Value) Cond) 15(rule 0 (lower_cond val @ (value_type (fits_in_32 _))) (Cond.If32 (zext32 val))) 16(rule 1 (lower_cond val @ (value_type $I64)) 17 (Cond.IfXneq64I32 val 0)) 18 19;; Peel away explicit `uextend` values to take a look at the inner value. 20(rule 2 (lower_cond (uextend val)) (lower_cond val)) 21;; Conditional branches on `icmp`s. 22(rule 2 (lower_cond (icmp cc a b @ (value_type $I32))) (lower_cond_icmp32 cc a b)) 23(rule 2 (lower_cond (icmp cc a b @ (value_type $I64))) (lower_cond_icmp64 cc a b)) 24 25(decl lower_cond_icmp32 (IntCC Value Value) Cond) 26(rule (lower_cond_icmp32 (IntCC.Equal) a b) (Cond.IfXeq32 a b)) 27(rule (lower_cond_icmp32 (IntCC.NotEqual) a b) (Cond.IfXneq32 a b)) 28(rule (lower_cond_icmp32 (IntCC.SignedLessThan) a b) (Cond.IfXslt32 a b)) 29(rule (lower_cond_icmp32 (IntCC.SignedLessThanOrEqual) a b) (Cond.IfXslteq32 a b)) 30(rule (lower_cond_icmp32 (IntCC.UnsignedLessThan) a b) (Cond.IfXult32 a b)) 31(rule (lower_cond_icmp32 (IntCC.UnsignedLessThanOrEqual) a b) (Cond.IfXulteq32 a b)) 32;; Swap args for conditions pulley doesn't have 33(rule (lower_cond_icmp32 (IntCC.SignedGreaterThan) a b) (Cond.IfXslt32 b a)) 34(rule (lower_cond_icmp32 (IntCC.SignedGreaterThanOrEqual) a b) (Cond.IfXslteq32 b a)) 35(rule (lower_cond_icmp32 (IntCC.UnsignedGreaterThan) a b) (Cond.IfXult32 b a)) 36(rule (lower_cond_icmp32 (IntCC.UnsignedGreaterThanOrEqual) a b) (Cond.IfXulteq32 b a)) 37 38(rule 1 (lower_cond_icmp32 (IntCC.Equal) a (i32_from_iconst b)) 39 (Cond.IfXeq32I32 a b)) 40(rule 1 (lower_cond_icmp32 (IntCC.NotEqual) a (i32_from_iconst b)) 41 (Cond.IfXneq32I32 a b)) 42(rule 1 (lower_cond_icmp32 (IntCC.SignedLessThan) a (i32_from_iconst b)) 43 (Cond.IfXslt32I32 a b)) 44(rule 1 (lower_cond_icmp32 (IntCC.SignedLessThanOrEqual) a (i32_from_iconst b)) 45 (Cond.IfXslteq32I32 a b)) 46(rule 1 (lower_cond_icmp32 (IntCC.SignedGreaterThan) a (i32_from_iconst b)) 47 (Cond.IfXsgt32I32 a b)) 48(rule 1 (lower_cond_icmp32 (IntCC.SignedGreaterThanOrEqual) a (i32_from_iconst b)) 49 (Cond.IfXsgteq32I32 a b)) 50(rule 1 (lower_cond_icmp32 (IntCC.UnsignedLessThan) a (u32_from_iconst b)) 51 (Cond.IfXult32I32 a b)) 52(rule 1 (lower_cond_icmp32 (IntCC.UnsignedLessThanOrEqual) a (u32_from_iconst b)) 53 (Cond.IfXulteq32I32 a b)) 54(rule 1 (lower_cond_icmp32 (IntCC.UnsignedGreaterThan) a (u32_from_iconst b)) 55 (Cond.IfXugt32I32 a b)) 56(rule 1 (lower_cond_icmp32 (IntCC.UnsignedGreaterThanOrEqual) a (u32_from_iconst b)) 57 (Cond.IfXugteq32I32 a b)) 58 59(decl lower_cond_icmp64 (IntCC Value Value) Cond) 60(rule (lower_cond_icmp64 (IntCC.Equal) a b) (Cond.IfXeq64 a b)) 61(rule (lower_cond_icmp64 (IntCC.NotEqual) a b) (Cond.IfXneq64 a b)) 62(rule (lower_cond_icmp64 (IntCC.SignedLessThan) a b) (Cond.IfXslt64 a b)) 63(rule (lower_cond_icmp64 (IntCC.SignedLessThanOrEqual) a b) (Cond.IfXslteq64 a b)) 64(rule (lower_cond_icmp64 (IntCC.UnsignedLessThan) a b) (Cond.IfXult64 a b)) 65(rule (lower_cond_icmp64 (IntCC.UnsignedLessThanOrEqual) a b) (Cond.IfXulteq64 a b)) 66;; Swap args for conditions pulley doesn't have 67(rule (lower_cond_icmp64 (IntCC.SignedGreaterThan) a b) (Cond.IfXslt64 b a)) 68(rule (lower_cond_icmp64 (IntCC.SignedGreaterThanOrEqual) a b) (Cond.IfXslteq64 b a)) 69(rule (lower_cond_icmp64 (IntCC.UnsignedGreaterThan) a b) (Cond.IfXult64 b a)) 70(rule (lower_cond_icmp64 (IntCC.UnsignedGreaterThanOrEqual) a b) (Cond.IfXulteq64 b a)) 71 72(rule 1 (lower_cond_icmp64 (IntCC.Equal) a (i32_from_iconst b)) 73 (Cond.IfXeq64I32 a b)) 74(rule 1 (lower_cond_icmp64 (IntCC.NotEqual) a (i32_from_iconst b)) 75 (Cond.IfXneq64I32 a b)) 76(rule 1 (lower_cond_icmp64 (IntCC.SignedLessThan) a (i32_from_iconst b)) 77 (Cond.IfXslt64I32 a b)) 78(rule 1 (lower_cond_icmp64 (IntCC.SignedLessThanOrEqual) a (i32_from_iconst b)) 79 (Cond.IfXslteq64I32 a b)) 80(rule 1 (lower_cond_icmp64 (IntCC.SignedGreaterThan) a (i32_from_iconst b)) 81 (Cond.IfXsgt64I32 a b)) 82(rule 1 (lower_cond_icmp64 (IntCC.SignedGreaterThanOrEqual) a (i32_from_iconst b)) 83 (Cond.IfXsgteq64I32 a b)) 84(rule 1 (lower_cond_icmp64 (IntCC.UnsignedLessThan) a (u32_from_iconst b)) 85 (Cond.IfXult64I32 a b)) 86(rule 1 (lower_cond_icmp64 (IntCC.UnsignedLessThanOrEqual) a (u32_from_iconst b)) 87 (Cond.IfXulteq64I32 a b)) 88(rule 1 (lower_cond_icmp64 (IntCC.UnsignedGreaterThan) a (u32_from_iconst b)) 89 (Cond.IfXugt64I32 a b)) 90(rule 1 (lower_cond_icmp64 (IntCC.UnsignedGreaterThanOrEqual) a (u32_from_iconst b)) 91 (Cond.IfXugteq64I32 a b)) 92 93;; The main control-flow-lowering term: takes a control-flow instruction and 94;; target(s) and emits the necessary instructions. 95(decl partial lower_branch (Inst MachLabelSlice) Unit) 96 97;; Unconditional jumps. 98(rule (lower_branch (jump _) (single_target label)) 99 (emit_side_effect (pulley_jump label))) 100 101;; Generic case for conditional branches. 102(rule -1 (lower_branch (brif c _ _) (two_targets then else)) 103 (emit_side_effect (pulley_br_if (lower_cond c) then else))) 104 105;; Branch tables. 106(rule (lower_branch (br_table index _) (jump_table_targets default targets)) 107 (gen_br_table index default targets)) 108 109;;;; Rules for `trap` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 110 111(rule (lower (trap code)) 112 (side_effect (pulley_trap code))) 113 114;;;; Rules for `trapz` and `trapnz` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 115 116(rule (lower (trapz cond code)) 117 (side_effect (pulley_trap_if (cond_invert (lower_cond cond)) code))) 118 119(rule (lower (trapnz cond code)) 120 (side_effect (pulley_trap_if (lower_cond cond) code))) 121 122;;;; Rules for `get_stack_pointer` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 123 124(rule (lower (get_stack_pointer)) 125 (pulley_get_special (sp_reg))) 126 127;;;; Rules for `get_frame_pointer` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 128 129(rule (lower (get_frame_pointer)) (pulley_xmov_fp)) 130 131;;;; Rules for `get_return_address` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 132 133(rule (lower (get_return_address)) (pulley_xmov_lr)) 134 135;;;; Rules for `return` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 136 137;; N.B.: the `ret` itself is generated by the ABI. 138(rule (lower (return args)) 139 (lower_return args)) 140 141;; Rules for `call` and `call_indirect` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 142 143;; Direct call to a pulley function. 144(rule 1 (lower (call (func_ref_data sig_ref name (reloc_distance_near)) args)) 145 (let ((output ValueRegsVec (gen_call_output sig_ref)) 146 (abi Sig (abi_sig sig_ref)) 147 (uses CallArgList (gen_call_args abi args)) 148 (defs CallRetList (gen_call_rets abi output)) 149 (info BoxCallInfo (gen_call_info abi name uses defs (try_call_none))) 150 (_ Unit (emit_side_effect (call_impl info)))) 151 output)) 152 153;; Direct call to a host function. 154(rule (lower (call (func_ref_data sig_ref name _) args)) 155 (let ((output ValueRegsVec (gen_call_output sig_ref)) 156 (abi Sig (abi_sig sig_ref)) 157 (uses CallArgList (gen_call_args abi args)) 158 (defs CallRetList (gen_call_rets abi output)) 159 (info BoxCallIndirectHostInfo (gen_call_host_info abi name uses defs (try_call_none))) 160 (_ Unit (emit_side_effect (indirect_call_host_impl info)))) 161 output)) 162 163;; Indirect call (assumed to be pulley->pulley). 164(rule (lower (call_indirect sig_ref ptr args)) 165 (let ((output ValueRegsVec (gen_call_output sig_ref)) 166 (abi Sig (abi_sig sig_ref)) 167 (target Reg (put_in_reg ptr)) 168 (uses CallArgList (gen_call_args abi args)) 169 (defs CallRetList (gen_call_rets abi output)) 170 (info BoxCallIndInfo (gen_call_ind_info abi target uses defs (try_call_none))) 171 (_ Unit (emit_side_effect (indirect_call_impl info)))) 172 output)) 173 174;;;; Rules for `try_call` and `try_call_indirect` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 175 176;; Direct call to a pulley function. 177(rule 1 (lower_branch (try_call (func_ref_data sig_ref name (reloc_distance_near)) args et) targets) 178 (let ((abi Sig (abi_sig sig_ref)) 179 (trycall OptionTryCallInfo (try_call_info et targets)) 180 (uses CallArgList (gen_call_args abi args)) 181 (defs CallRetList (gen_try_call_rets abi)) 182 (info BoxCallInfo (gen_call_info abi name uses defs trycall))) 183 (emit_side_effect (call_impl info)))) 184 185;; Direct call to a host function. 186(rule (lower_branch (try_call (func_ref_data sig_ref name _) args et) targets) 187 (let ((abi Sig (abi_sig sig_ref)) 188 (trycall OptionTryCallInfo (try_call_info et targets)) 189 (uses CallArgList (gen_call_args abi args)) 190 (defs CallRetList (gen_try_call_rets abi)) 191 (info BoxCallIndirectHostInfo (gen_call_host_info abi name uses defs trycall))) 192 (emit_side_effect (indirect_call_host_impl info)))) 193 194;; Indirect call (assumed to be pulley->pulley). 195(rule (lower_branch (try_call_indirect ptr args et) targets) 196 (if-let (exception_sig sig_ref) et) 197 (let ((abi Sig (abi_sig sig_ref)) 198 (trycall OptionTryCallInfo (try_call_info et targets)) 199 (target Reg (put_in_reg ptr)) 200 (uses CallArgList (gen_call_args abi args)) 201 (defs CallRetList (gen_try_call_rets abi)) 202 (info BoxCallIndInfo (gen_call_ind_info abi target uses defs trycall))) 203 (emit_side_effect (indirect_call_impl info)))) 204 205;;;; Rules for `return_call` and `return_call_indirect` ;;;;;;;;;;;;;;;;;;;;;;;; 206 207;; Direct call to a pulley function. 208(rule 1 (lower (return_call (func_ref_data sig_ref name (reloc_distance_near)) args)) 209 (let ((abi Sig (abi_sig sig_ref)) 210 (uses CallArgList (gen_return_call_args abi args)) 211 (info BoxReturnCallInfo (gen_return_call_info abi name uses))) 212 (side_effect (return_call_impl info)))) 213 214;; Indirect call (assumed to be pulley->pulley). 215(rule (lower (return_call_indirect sig_ref ptr args)) 216 (let ((abi Sig (abi_sig sig_ref)) 217 (target Reg (put_in_reg ptr)) 218 (uses CallArgList (gen_return_call_args abi args)) 219 (info BoxReturnCallIndInfo (gen_return_call_ind_info abi target uses))) 220 (side_effect (return_indirect_call_impl info)))) 221 222;;;; Rules for `iconst` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 223 224(rule (lower (has_type ty (iconst c))) (imm (i64_sextend_imm64 ty c))) 225 226;;;; Rules for `f32const`;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 227 228(rule (lower (f32const (u32_from_ieee32 x))) (pulley_fconst32 x)) 229 230;;;; Rules for `f64const`;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 231 232(rule (lower (f64const (u64_from_ieee64 x))) (pulley_fconst64 x)) 233 234;;;; Rules for `iadd` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 235 236(rule 0 (lower (has_type (ty_int (fits_in_64 ty)) (iadd a b))) (pulley_xadd32 a b)) 237(rule 1 (lower (has_type $I64 (iadd a b))) (pulley_xadd64 a b)) 238 239;; Fold constants into the instruction if possible 240(rule 10 (lower (has_type (ty_int (fits_in_32 _)) (iadd a (u32_from_iconst b)))) 241 (pulley_xadd32_u32 a b)) 242(rule 11 (lower (has_type (ty_int (fits_in_32 _)) (iadd a (u8_from_iconst b)))) 243 (pulley_xadd32_u8 a b)) 244(rule 12 (lower (has_type $I64 (iadd a (u32_from_iconst b)))) 245 (pulley_xadd64_u32 a b)) 246(rule 13 (lower (has_type $I64 (iadd a (u8_from_iconst b)))) 247 (pulley_xadd64_u8 a b)) 248 249;; If the rhs is a constant and the negated version can fit within a smaller 250;; constant then switch this to a subtraction with the negated constant. 251(rule 14 (lower (has_type (ty_int (fits_in_32 _)) (iadd a b))) 252 (if-let c (u32_from_negated_iconst b)) 253 (pulley_xsub32_u32 a c)) 254(rule 15 (lower (has_type $I64 (iadd a b))) 255 (if-let c (u32_from_negated_iconst b)) 256 (pulley_xsub64_u32 a c)) 257(rule 16 (lower (has_type (ty_int (fits_in_32 _)) (iadd a b))) 258 (if-let c (u8_from_negated_iconst b)) 259 (pulley_xsub32_u8 a c)) 260(rule 17 (lower (has_type $I64 (iadd a b))) 261 (if-let c (u8_from_negated_iconst b)) 262 (pulley_xsub64_u8 a c)) 263 264;; Helper extract a constant from a `Value`, negate it, and fit it within a 265;; `u8`. 266(decl pure partial u8_from_negated_iconst (Value) u8) 267(rule (u8_from_negated_iconst (i32_from_iconst i)) 268 (if-let neg_i64 (i64_checked_neg i)) 269 (if-let neg_u8 (i64_try_into_u8 neg_i64)) 270 neg_u8) 271 272;; Helper extract a constant from a `Value`, negate it, and fit it within a 273;; `u32`. 274(decl pure partial u32_from_negated_iconst (Value) u32) 275(rule (u32_from_negated_iconst (i32_from_iconst i)) 276 (if-let neg_i64 (i64_checked_neg i)) 277 (if-let neg_u32 (i64_try_into_u32 neg_i64)) 278 neg_u32) 279 280;; 128-bit addition 281(rule 1 (lower (has_type $I128 (iadd a b))) 282 (let ((a ValueRegs a) 283 (b ValueRegs b)) 284 (pulley_xadd128 285 (value_regs_get a 0) 286 (value_regs_get a 1) 287 (value_regs_get b 0) 288 (value_regs_get b 1)))) 289 290;; vector addition 291(rule 1 (lower (has_type $I8X16 (iadd a b))) (pulley_vaddi8x16 a b)) 292(rule 1 (lower (has_type $I16X8 (iadd a b))) (pulley_vaddi16x8 a b)) 293(rule 1 (lower (has_type $I32X4 (iadd a b))) (pulley_vaddi32x4 a b)) 294(rule 1 (lower (has_type $I64X2 (iadd a b))) (pulley_vaddi64x2 a b)) 295 296(rule 1 (lower (has_type $I8X16 (sadd_sat a b))) (pulley_vaddi8x16_sat a b)) 297(rule 1 (lower (has_type $I8X16 (uadd_sat a b))) (pulley_vaddu8x16_sat a b)) 298(rule 1 (lower (has_type $I16X8 (sadd_sat a b))) (pulley_vaddi16x8_sat a b)) 299(rule 1 (lower (has_type $I16X8 (uadd_sat a b))) (pulley_vaddu16x8_sat a b)) 300 301;; Specialized lowerings for multiply-and-add 302 303(rule 2 (lower (has_type $I32 (iadd (imul a b) c))) (pulley_xmadd32 a b c)) 304(rule 3 (lower (has_type $I32 (iadd c (imul a b)))) (pulley_xmadd32 a b c)) 305(rule 2 (lower (has_type $I64 (iadd (imul a b) c))) (pulley_xmadd64 a b c)) 306(rule 3 (lower (has_type $I64 (iadd c (imul a b)))) (pulley_xmadd64 a b c)) 307 308;;;; Rules for `iadd_pairwise` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 309 310(rule (lower (has_type $I16X8 (iadd_pairwise a b))) (pulley_vaddpairwisei16x8_s a b)) 311(rule (lower (has_type $I32X4 (iadd_pairwise a b))) (pulley_vaddpairwisei32x4_s a b)) 312 313;;;; Rules for `isub` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 314 315(rule 0 (lower (has_type (ty_int (fits_in_32 _)) (isub a b))) (pulley_xsub32 a b)) 316(rule 1 (lower (has_type $I64 (isub a b))) (pulley_xsub64 a b)) 317 318;; Fold a rhs constant into the instruction if possible. 319(rule 2 (lower (has_type (ty_int (fits_in_32 _)) (isub a (u32_from_iconst b)))) 320 (pulley_xsub32_u32 a b)) 321(rule 3 (lower (has_type (ty_int (fits_in_32 _)) (isub a (u8_from_iconst b)))) 322 (pulley_xsub32_u8 a b)) 323(rule 4 (lower (has_type $I64 (isub a (u32_from_iconst b)))) 324 (pulley_xsub64_u32 a b)) 325(rule 5 (lower (has_type $I64 (isub a (u8_from_iconst b)))) 326 (pulley_xsub64_u8 a b)) 327 328;; If the rhs is a constant and the negated version can fit within a smaller 329;; constant then switch this to an addition with the negated constant. 330(rule 6 (lower (has_type (ty_int (fits_in_32 _)) (isub a b))) 331 (if-let c (u32_from_negated_iconst b)) 332 (pulley_xadd32_u32 a c)) 333(rule 7 (lower (has_type $I64 (isub a b))) 334 (if-let c (u32_from_negated_iconst b)) 335 (pulley_xadd64_u32 a c)) 336(rule 8 (lower (has_type (ty_int (fits_in_32 _)) (isub a b))) 337 (if-let c (u8_from_negated_iconst b)) 338 (pulley_xadd32_u8 a c)) 339(rule 9 (lower (has_type $I64 (isub a b))) 340 (if-let c (u8_from_negated_iconst b)) 341 (pulley_xadd64_u8 a c)) 342 343;; 128-bit subtraction 344(rule 1 (lower (has_type $I128 (isub a b))) 345 (let ((a ValueRegs a) 346 (b ValueRegs b)) 347 (pulley_xsub128 348 (value_regs_get a 0) 349 (value_regs_get a 1) 350 (value_regs_get b 0) 351 (value_regs_get b 1)))) 352 353;; vector subtraction 354(rule 1 (lower (has_type $I8X16 (isub a b))) (pulley_vsubi8x16 a b)) 355(rule 1 (lower (has_type $I16X8 (isub a b))) (pulley_vsubi16x8 a b)) 356(rule 1 (lower (has_type $I32X4 (isub a b))) (pulley_vsubi32x4 a b)) 357(rule 1 (lower (has_type $I64X2 (isub a b))) (pulley_vsubi64x2 a b)) 358 359(rule 1 (lower (has_type $I8X16 (ssub_sat a b))) (pulley_vsubi8x16_sat a b)) 360(rule 1 (lower (has_type $I8X16 (usub_sat a b))) (pulley_vsubu8x16_sat a b)) 361(rule 1 (lower (has_type $I16X8 (ssub_sat a b))) (pulley_vsubi16x8_sat a b)) 362(rule 1 (lower (has_type $I16X8 (usub_sat a b))) (pulley_vsubu16x8_sat a b)) 363 364;;;; Rules for `imul` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 365 366(rule (lower (has_type $I8 (imul a b))) (pulley_xmul32 a b)) 367(rule (lower (has_type $I16 (imul a b))) (pulley_xmul32 a b)) 368(rule (lower (has_type $I32 (imul a b))) (pulley_xmul32 a b)) 369(rule (lower (has_type $I64 (imul a b))) (pulley_xmul64 a b)) 370 371(rule 1 (lower (has_type (ty_int (fits_in_32 _)) (imul a (i32_from_iconst b)))) 372 (pulley_xmul32_s32 a b)) 373(rule 2 (lower (has_type $I64 (imul a (i32_from_iconst b)))) 374 (pulley_xmul64_s32 a b)) 375(rule 3 (lower (has_type (ty_int (fits_in_32 _)) (imul a (i8_from_iconst b)))) 376 (pulley_xmul32_s8 a b)) 377(rule 4 (lower (has_type $I64 (imul a (i8_from_iconst b)))) 378 (pulley_xmul64_s8 a b)) 379 380;; 128-bit (or wide) multiplication 381(rule 4 (lower (has_type $I128 (imul (uextend a) (uextend b)))) 382 (pulley_xwidemul64_u (zext64 a) (zext64 b))) 383(rule 4 (lower (has_type $I128 (imul (sextend a) (sextend b)))) 384 (pulley_xwidemul64_s (sext64 a) (sext64 b))) 385 386;; for I128 387(rule (lower (has_type $I128 (imul x y))) 388 (let 389 ((x_regs ValueRegs x) 390 (x_lo XReg (value_regs_get x_regs 0)) 391 (x_hi XReg (value_regs_get x_regs 1)) 392 393 ;; Get the high/low registers for `y`. 394 (y_regs ValueRegs y) 395 (y_lo XReg (value_regs_get y_regs 0)) 396 (y_hi XReg (value_regs_get y_regs 1)) 397 398 ;; 128bit mul formula: 399 ;; dst_lo = x_lo * y_lo 400 ;; dst_hi = mul_high(x_lo, y_lo) + (x_lo * y_hi) + (x_hi * y_lo) 401 (wide_regs ValueRegs (pulley_xwidemul64_u x_lo y_lo)) 402 (wide_lo XReg (value_regs_get wide_regs 0)) 403 (wide_hi XReg (value_regs_get wide_regs 1)) 404 (tmp_hi1 XReg (pulley_xmul64 x_lo y_hi)) 405 (tmp_hi2 XReg (pulley_xmul64 x_hi y_lo)) 406 (tmp_add XReg (pulley_xadd64 wide_hi tmp_hi1)) 407 (result_hi XReg (pulley_xadd64 tmp_add tmp_hi2)) 408 ) 409 (value_regs wide_lo result_hi))) 410 411;; vector multiplication 412(rule (lower (has_type $I8X16 (imul a b))) (pulley_vmuli8x16 a b)) 413(rule (lower (has_type $I16X8 (imul a b))) (pulley_vmuli16x8 a b)) 414(rule (lower (has_type $I32X4 (imul a b))) (pulley_vmuli32x4 a b)) 415(rule (lower (has_type $I64X2 (imul a b))) (pulley_vmuli64x2 a b)) 416 417;;;; Rules for `umulhi` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 418 419(rule (lower (has_type $I8 (umulhi a b))) 420 (if-let (u6_from_u8 shift) (u64_try_into_u8 8)) 421 (pulley_xshr32_u_u6 (pulley_xmul32 (zext32 a) (zext32 b)) shift)) 422 423(rule (lower (has_type $I16 (umulhi a b))) 424 (if-let (u6_from_u8 shift) (u64_try_into_u8 16)) 425 (pulley_xshr32_u_u6 (pulley_xmul32 (zext32 a) (zext32 b)) shift)) 426 427(rule (lower (has_type $I32 (umulhi a b))) 428 (if-let (u6_from_u8 shift) (u64_try_into_u8 32)) 429 (pulley_xshr64_u_u6 (pulley_xmul64 (zext64 a) (zext64 b)) shift)) 430 431(rule (lower (has_type $I64 (umulhi a b))) 432 (pulley_xmulhi64_u a b)) 433 434;;;; Rules for `smulhi` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 435 436(rule (lower (has_type $I8 (smulhi a b))) 437 (if-let (u6_from_u8 shift) (u64_try_into_u8 8)) 438 (pulley_xshr32_s_u6 (pulley_xmul32 (sext32 a) (sext32 b)) shift)) 439 440(rule (lower (has_type $I16 (smulhi a b))) 441 (if-let (u6_from_u8 shift) (u64_try_into_u8 16)) 442 (pulley_xshr32_s_u6 (pulley_xmul32 (sext32 a) (sext32 b)) shift)) 443 444(rule (lower (has_type $I32 (smulhi a b))) 445 (if-let (u6_from_u8 shift) (u64_try_into_u8 32)) 446 (pulley_xshr64_s_u6 (pulley_xmul64 (sext64 a) (sext64 b)) shift)) 447 448(rule (lower (has_type $I64 (smulhi a b))) 449 (pulley_xmulhi64_s a b)) 450 451;;;; Rules for `sqmul_round_sat` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 452 453(rule (lower (has_type $I16X8 (sqmul_round_sat a b))) (pulley_vqmulrsi16x8 a b)) 454 455;;;; Rules for `sdiv` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 456 457(rule 0 (lower (has_type (fits_in_32 _) (sdiv a b))) 458 (pulley_xdiv32_s (sext32 a) (sext32 b))) 459(rule 1 (lower (has_type $I64 (sdiv a b))) (pulley_xdiv64_s a b)) 460 461;;;; Rules for `srem` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 462 463(rule 0 (lower (has_type (fits_in_32 _) (srem a b))) 464 (pulley_xrem32_s (sext32 a) (sext32 b))) 465(rule 1 (lower (has_type $I64 (srem a b))) (pulley_xrem64_s a b)) 466 467;;;; Rules for `udiv` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 468 469(rule 0 (lower (has_type (ty_int (fits_in_32 _)) (udiv a b))) 470 (pulley_xdiv32_u (zext32 a) (zext32 b))) 471(rule 1 (lower (has_type $I64 (udiv a b))) (pulley_xdiv64_u a b)) 472 473;;;; Rules for `urem` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 474 475(rule 0 (lower (has_type (ty_int (fits_in_32 _)) (urem a b))) 476 (pulley_xrem32_u (zext32 a) (zext32 b))) 477(rule 1 (lower (has_type $I64 (urem a b))) (pulley_xrem64_u a b)) 478 479;;;; Rules for `avg_round` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 480 481(rule (lower (has_type $I8X16 (avg_round a b))) (pulley_vavground8x16 a b)) 482(rule (lower (has_type $I16X8 (avg_round a b))) (pulley_vavground16x8 a b)) 483 484;;;; Rules for `ishl` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 485 486(rule (lower (has_type $I8 (ishl a b))) 487 (pulley_xshl32 a (pulley_xband32_s8 b 7))) 488 489(rule (lower (has_type $I16 (ishl a b))) 490 (pulley_xshl32 a (pulley_xband32_s8 b 15))) 491 492(rule (lower (has_type $I32 (ishl a b))) 493 (pulley_xshl32 a b)) 494 495(rule (lower (has_type $I64 (ishl a b))) 496 (pulley_xshl64 a b)) 497 498;; Special-case constant shift amounts. 499(rule 1 (lower (has_type $I32 (ishl a b))) 500 (if-let n (u6_shift_from_iconst b)) 501 (pulley_xshl32_u6 a n)) 502(rule 1 (lower (has_type $I64 (ishl a b))) 503 (if-let n (u6_shift_from_iconst b)) 504 (pulley_xshl64_u6 a n)) 505 506;; vector shifts 507 508(rule (lower (has_type $I8X16 (ishl a b))) (pulley_vshli8x16 a b)) 509(rule (lower (has_type $I16X8 (ishl a b))) (pulley_vshli16x8 a b)) 510(rule (lower (has_type $I32X4 (ishl a b))) (pulley_vshli32x4 a b)) 511(rule (lower (has_type $I64X2 (ishl a b))) (pulley_vshli64x2 a b)) 512 513;; Helper to extract a constant from `Value`, mask it to 6 bits, and then make a 514;; `U6`. 515(decl pure partial u6_shift_from_iconst (Value) U6) 516(rule (u6_shift_from_iconst (u64_from_iconst val)) 517 (if-let (u6_from_u8 x) (u64_try_into_u8 (u64_and val 0x3f))) 518 x) 519 520(decl u6_from_u8 (U6) u8) 521(extern extractor u6_from_u8 u6_from_u8) 522 523;;;; Rules for `ushr` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 524 525(rule (lower (has_type $I8 (ushr a b))) 526 (pulley_xshr32_u (zext32 a) (pulley_xband32_s8 b 7))) 527 528(rule (lower (has_type $I16 (ushr a b))) 529 (pulley_xshr32_u (zext32 a) (pulley_xband32_s8 b 15))) 530 531(rule (lower (has_type $I32 (ushr a b))) 532 (pulley_xshr32_u a b)) 533 534(rule (lower (has_type $I64 (ushr a b))) 535 (pulley_xshr64_u a b)) 536 537;; Special-case constant shift amounts. 538(rule 1 (lower (has_type $I32 (ushr a b))) 539 (if-let n (u6_shift_from_iconst b)) 540 (pulley_xshr32_u_u6 a n)) 541(rule 1 (lower (has_type $I64 (ushr a b))) 542 (if-let n (u6_shift_from_iconst b)) 543 (pulley_xshr64_u_u6 a n)) 544 545;; vector shifts 546 547(rule (lower (has_type $I8X16 (ushr a b))) (pulley_vshri8x16_u a b)) 548(rule (lower (has_type $I16X8 (ushr a b))) (pulley_vshri16x8_u a b)) 549(rule (lower (has_type $I32X4 (ushr a b))) (pulley_vshri32x4_u a b)) 550(rule (lower (has_type $I64X2 (ushr a b))) (pulley_vshri64x2_u a b)) 551 552;;;; Rules for `sshr` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 553 554(rule (lower (has_type $I8 (sshr a b))) 555 (pulley_xshr32_u (sext32 a) (pulley_xband32_s8 b 7))) 556 557(rule (lower (has_type $I16 (sshr a b))) 558 (pulley_xshr32_u (sext32 a) (pulley_xband32_s8 b 15))) 559 560(rule (lower (has_type $I32 (sshr a b))) 561 (pulley_xshr32_s a b)) 562 563(rule (lower (has_type $I64 (sshr a b))) 564 (pulley_xshr64_s a b)) 565 566;; Special-case constant shift amounts. 567(rule 1 (lower (has_type $I32 (sshr a b))) 568 (if-let n (u6_shift_from_iconst b)) 569 (pulley_xshr32_s_u6 a n)) 570(rule 1 (lower (has_type $I64 (sshr a b))) 571 (if-let n (u6_shift_from_iconst b)) 572 (pulley_xshr64_s_u6 a n)) 573 574;; vector shifts 575 576(rule (lower (has_type $I8X16 (sshr a b))) (pulley_vshri8x16_s a b)) 577(rule (lower (has_type $I16X8 (sshr a b))) (pulley_vshri16x8_s a b)) 578(rule (lower (has_type $I32X4 (sshr a b))) (pulley_vshri32x4_s a b)) 579(rule (lower (has_type $I64X2 (sshr a b))) (pulley_vshri64x2_s a b)) 580 581;;;; Rules for `band` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 582 583(rule 0 (lower (has_type (fits_in_32 _) (band a b))) (pulley_xband32 a b)) 584(rule 1 (lower (has_type $I64 (band a b))) (pulley_xband64 a b)) 585 586(rule 3 (lower (has_type (ty_int (fits_in_32 _)) (band a (i32_from_iconst b)))) 587 (pulley_xband32_s32 a b)) 588(rule 4 (lower (has_type $I64 (band a (i32_from_iconst b)))) 589 (pulley_xband64_s32 a b)) 590(rule 5 (lower (has_type (ty_int (fits_in_32 _)) (band a (i8_from_iconst b)))) 591 (pulley_xband32_s8 a b)) 592(rule 6 (lower (has_type $I64 (band a (i8_from_iconst b)))) 593 (pulley_xband64_s8 a b)) 594 595(rule 2 (lower (has_type (ty_vec128 _) (band a b))) 596 (pulley_vband128 a b)) 597 598;;;; Rules for `bor` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 599 600(rule 0 (lower (has_type (fits_in_32 _) (bor a b))) (pulley_xbor32 a b)) 601(rule 1 (lower (has_type $I64 (bor a b))) (pulley_xbor64 a b)) 602 603(rule 3 (lower (has_type (ty_int (fits_in_32 _)) (bor a (i32_from_iconst b)))) 604 (pulley_xbor32_s32 a b)) 605(rule 4 (lower (has_type $I64 (bor a (i32_from_iconst b)))) 606 (pulley_xbor64_s32 a b)) 607(rule 5 (lower (has_type (ty_int (fits_in_32 _)) (bor a (i8_from_iconst b)))) 608 (pulley_xbor32_s8 a b)) 609(rule 6 (lower (has_type $I64 (bor a (i8_from_iconst b)))) 610 (pulley_xbor64_s8 a b)) 611 612(rule 2 (lower (has_type (ty_vec128 _) (bor a b))) 613 (pulley_vbor128 a b)) 614 615;;;; Rules for `bxor` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 616 617(rule 0 (lower (has_type (fits_in_32 _) (bxor a b))) (pulley_xbxor32 a b)) 618(rule 1 (lower (has_type $I64 (bxor a b))) (pulley_xbxor64 a b)) 619 620(rule 3 (lower (has_type (ty_int (fits_in_32 _)) (bxor a (i32_from_iconst b)))) 621 (pulley_xbxor32_s32 a b)) 622(rule 4 (lower (has_type $I64 (bxor a (i32_from_iconst b)))) 623 (pulley_xbxor64_s32 a b)) 624(rule 5 (lower (has_type (ty_int (fits_in_32 _)) (bxor a (i8_from_iconst b)))) 625 (pulley_xbxor32_s8 a b)) 626(rule 6 (lower (has_type $I64 (bxor a (i8_from_iconst b)))) 627 (pulley_xbxor64_s8 a b)) 628 629(rule 2 (lower (has_type (ty_vec128 _) (bxor a b))) 630 (pulley_vbxor128 a b)) 631 632;;;; Rules for `bnot` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 633 634(rule 0 (lower (has_type (fits_in_32 _) (bnot a))) 635 (pulley_xbnot32 a)) 636 637(rule 1 (lower (has_type $I64 (bnot a))) 638 (pulley_xbnot64 a)) 639 640(rule 2 (lower (has_type (ty_vec128 _) (bnot a))) 641 (pulley_vbnot128 a)) 642 643;;;; Rules for `bitselect` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 644 645(rule (lower (has_type (ty_vec128 _) (bitselect c x y))) 646 (pulley_vbitselect128 c x y)) 647 648;;;; Rules for `umin` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 649 650(rule 0 (lower (has_type (fits_in_32 _) (umin a b))) 651 (pulley_xmin32_u (zext32 a) (zext32 b))) 652(rule 1 (lower (has_type $I64 (umin a b))) (pulley_xmin64_u a b)) 653(rule 1 (lower (has_type $I8X16 (umin a b))) (pulley_vmin8x16_u a b)) 654(rule 1 (lower (has_type $I16X8 (umin a b))) (pulley_vmin16x8_u a b)) 655(rule 1 (lower (has_type $I32X4 (umin a b))) (pulley_vmin32x4_u a b)) 656 657;;;; Rules for `smin` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 658 659(rule 0 (lower (has_type (fits_in_32 _) (smin a b))) 660 (pulley_xmin32_s (sext32 a) (sext32 b))) 661(rule 1 (lower (has_type $I64 (smin a b))) (pulley_xmin64_s a b)) 662(rule 1 (lower (has_type $I8X16 (smin a b))) (pulley_vmin8x16_s a b)) 663(rule 1 (lower (has_type $I16X8 (smin a b))) (pulley_vmin16x8_s a b)) 664(rule 1 (lower (has_type $I32X4 (smin a b))) (pulley_vmin32x4_s a b)) 665 666;;;; Rules for `umax` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 667 668(rule 0 (lower (has_type (fits_in_32 _) (umax a b))) 669 (pulley_xmax32_u (zext32 a) (zext32 b))) 670(rule 1 (lower (has_type $I64 (umax a b))) (pulley_xmax64_u a b)) 671(rule 1 (lower (has_type $I8X16 (umax a b))) (pulley_vmax8x16_u a b)) 672(rule 1 (lower (has_type $I16X8 (umax a b))) (pulley_vmax16x8_u a b)) 673(rule 1 (lower (has_type $I32X4 (umax a b))) (pulley_vmax32x4_u a b)) 674 675;;;; Rules for `smax` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 676 677(rule 0 (lower (has_type (fits_in_32 _) (smax a b))) 678 (pulley_xmax32_s (sext32 a) (sext32 b))) 679(rule 1 (lower (has_type $I64 (smax a b))) (pulley_xmax64_s a b)) 680(rule 1 (lower (has_type $I8X16 (smax a b))) (pulley_vmax8x16_s a b)) 681(rule 1 (lower (has_type $I16X8 (smax a b))) (pulley_vmax16x8_s a b)) 682(rule 1 (lower (has_type $I32X4 (smax a b))) (pulley_vmax32x4_s a b)) 683 684;;;; Rules for `bmask` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 685 686(rule 0 (lower (has_type (ty_int (fits_in_32 _)) (bmask a @ (value_type (fits_in_32 _))))) 687 (pulley_xbmask32 (zext32 a))) 688(rule 1 (lower (has_type $I64 (bmask a))) 689 (pulley_xbmask64 (zext64 a))) 690(rule 2 (lower (bmask a @ (value_type $I64))) 691 (pulley_xbmask64 a)) 692 693;;;; Rules for `ctz` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 694 695(rule (lower (has_type $I8 (ctz a))) 696 (pulley_xctz32 (pulley_xbor32_s32 a 0x100))) 697(rule (lower (has_type $I16 (ctz a))) 698 (pulley_xctz32 (pulley_xbor32_s32 a 0x10000))) 699(rule (lower (has_type $I32 (ctz a))) (pulley_xctz32 a)) 700(rule (lower (has_type $I64 (ctz a))) (pulley_xctz64 a)) 701 702;;;; Rules for `clz` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 703 704(rule (lower (has_type $I8 (clz a))) 705 (pulley_xsub32_u8 (pulley_xclz32 (zext32 a)) 24)) 706(rule (lower (has_type $I16 (clz a))) 707 (pulley_xsub32_u8 (pulley_xclz32 (zext32 a)) 16)) 708(rule (lower (has_type $I32 (clz a))) (pulley_xclz32 a)) 709(rule (lower (has_type $I64 (clz a))) (pulley_xclz64 a)) 710 711;;;; Rules for `popcnt` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 712 713(rule 0 (lower (has_type (fits_in_32 _) (popcnt a))) (pulley_xpopcnt32 (zext32 a))) 714(rule 1 (lower (has_type $I64 (popcnt a))) (pulley_xpopcnt64 a)) 715(rule 1 (lower (has_type $I8X16 (popcnt a))) (pulley_vpopcnt8x16 a)) 716 717;;;; Rules for `rotl` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 718 719(rule (lower (has_type $I32 (rotl a b))) (pulley_xrotl32 a b)) 720(rule (lower (has_type $I64 (rotl a b))) (pulley_xrotl64 a b)) 721 722;;;; Rules for `rotr` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 723 724(rule (lower (has_type $I32 (rotr a b))) (pulley_xrotr32 a b)) 725(rule (lower (has_type $I64 (rotr a b))) (pulley_xrotr64 a b)) 726 727;;;; Rules for `icmp` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 728 729(rule (lower (icmp cc a b @ (value_type (ty_int ty)))) 730 (lower_icmp ty cc a b)) 731 732(decl lower_icmp (Type IntCC Value Value) XReg) 733 734(rule (lower_icmp $I64 (IntCC.Equal) a b) 735 (pulley_xeq64 a b)) 736 737(rule (lower_icmp $I64 (IntCC.NotEqual) a b) 738 (pulley_xneq64 a b)) 739 740(rule (lower_icmp $I64 (IntCC.SignedLessThan) a b) 741 (pulley_xslt64 a b)) 742 743(rule (lower_icmp $I64 (IntCC.SignedLessThanOrEqual) a b) 744 (pulley_xslteq64 a b)) 745 746(rule (lower_icmp $I64 (IntCC.UnsignedLessThan) a b) 747 (pulley_xult64 a b)) 748 749(rule (lower_icmp $I64 (IntCC.UnsignedLessThanOrEqual) a b) 750 (pulley_xulteq64 a b)) 751 752(rule 1 (lower_icmp (fits_in_32 _) (IntCC.Equal) a b) 753 (pulley_xeq32 (zext32 a) (zext32 b))) 754 755(rule 1 (lower_icmp (fits_in_32 _) (IntCC.NotEqual) a b) 756 (pulley_xneq32 (zext32 a) (zext32 b))) 757 758(rule 1 (lower_icmp (fits_in_32 _) (IntCC.SignedLessThan) a b) 759 (pulley_xslt32 (sext32 a) (sext32 b))) 760 761(rule 1 (lower_icmp (fits_in_32 _) (IntCC.SignedLessThanOrEqual) a b) 762 (pulley_xslteq32 (sext32 a) (sext32 b))) 763 764(rule 1 (lower_icmp (fits_in_32 _) (IntCC.UnsignedLessThan) a b) 765 (pulley_xult32 (zext32 a) (zext32 b))) 766 767(rule 1 (lower_icmp (fits_in_32 _) (IntCC.UnsignedLessThanOrEqual) a b) 768 (pulley_xulteq32 (zext32 a) (zext32 b))) 769 770;; Pulley doesn't have instructions for `>` and `>=`, so we have to reverse the 771;; operation. 772(rule (lower_icmp ty (IntCC.SignedGreaterThan) a b) 773 (lower_icmp ty (IntCC.SignedLessThan) b a)) 774(rule (lower_icmp ty (IntCC.SignedGreaterThanOrEqual) a b) 775 (lower_icmp ty (IntCC.SignedLessThanOrEqual) b a)) 776(rule (lower_icmp ty (IntCC.UnsignedGreaterThan) a b) 777 (lower_icmp ty (IntCC.UnsignedLessThan) b a)) 778(rule (lower_icmp ty (IntCC.UnsignedGreaterThanOrEqual) a b) 779 (lower_icmp ty (IntCC.UnsignedLessThanOrEqual) b a)) 780 781;; `i128` comparisons 782;; 783;; While we could pretty easily add 128-bit comparisons to the interpreter it's 784;; currently predicted that it's relatively niche to need this and that it's 785;; not performance-sensitive in an interpreter context. In lieu of adding more 786;; opcodes this is an adaptation of riscv64's lowering rules for 128-bit 787;; integers. In the future if this is a performance bottleneck it should be 788;; possible to add new opcodes to pulley for 128-bit comparisons. 789 790(rule (lower_icmp $I128 (IntCC.Equal) x y) 791 (let ((lo XReg (pulley_xbxor64 (value_regs_get x 0) (value_regs_get y 0))) 792 (hi XReg (pulley_xbxor64 (value_regs_get x 1) (value_regs_get y 1)))) 793 (pulley_xeq64 (pulley_xbor64 lo hi) (pulley_xconst8 0)))) 794(rule (lower_icmp $I128 (IntCC.NotEqual) x y) 795 (let ((lo XReg (pulley_xbxor64 (value_regs_get x 0) (value_regs_get y 0))) 796 (hi XReg (pulley_xbxor64 (value_regs_get x 1) (value_regs_get y 1)))) 797 (pulley_xneq64 (pulley_xbor64 lo hi) (pulley_xconst8 0)))) 798 799;; swap args for `>` to use `<` instead 800;;(rule 1 (lower_icmp $I128 cc @ (IntCC.SignedGreaterThan) x y) 801;; (lower_icmp $I128 (intcc_swap_args cc) y x)) 802;;(rule 1 (lower_icmp $I128 cc @ (IntCC.UnsignedGreaterThan) x y) 803;; (lower_icmp $I128 (intcc_swap_args cc) y x)) 804 805;; complement `=`-related conditions to get ones that don't use `=`. 806(rule 2 (lower_icmp $I128 cc @ (IntCC.SignedLessThanOrEqual) x y) 807 (pulley_xbxor32_s8 (lower_icmp $I128 (intcc_complement cc) x y) 1)) 808(rule 2 (lower_icmp $I128 cc @ (IntCC.SignedGreaterThanOrEqual) x y) 809 (pulley_xbxor32_s8 (lower_icmp $I128 (intcc_complement cc) x y) 1)) 810(rule 2 (lower_icmp $I128 cc @ (IntCC.UnsignedLessThanOrEqual) x y) 811 (pulley_xbxor32_s8 (lower_icmp $I128 (intcc_complement cc) x y) 1)) 812(rule 2 (lower_icmp $I128 cc @ (IntCC.UnsignedGreaterThanOrEqual) x y) 813 (pulley_xbxor32_s8 (lower_icmp $I128 (intcc_complement cc) x y) 1)) 814 815;; Compare both the bottom and upper halves of the 128-bit values. If 816;; the top half is equal use the bottom comparison, otherwise use the upper 817;; comparison. Note that the lower comparison is always unsigned since if it's 818;; used the top halves are all zeros and the semantic values are positive. 819(rule 3 (lower_icmp $I128 cc x y) 820 (if-let (IntCC.UnsignedLessThan) (intcc_unsigned cc)) 821 (let ((x_lo XReg (value_regs_get x 0)) 822 (x_hi XReg (value_regs_get x 1)) 823 (y_lo XReg (value_regs_get y 0)) 824 (y_hi XReg (value_regs_get y 1)) 825 (top_cmp XReg (lower_icmp128_hi cc x_hi y_hi)) 826 (bottom_cmp XReg (pulley_xult64 x_lo y_lo))) 827 (pulley_xselect32 828 (pulley_xeq64 (pulley_xbxor64 x_hi y_hi) (pulley_xconst8 0)) 829 bottom_cmp 830 top_cmp))) 831 832(decl lower_icmp128_hi (IntCC XReg XReg) XReg) 833(rule (lower_icmp128_hi (IntCC.SignedLessThan) a b) (pulley_xslt64 a b)) 834(rule (lower_icmp128_hi (IntCC.UnsignedLessThan) a b) (pulley_xult64 a b)) 835 836;; vector comparisons 837 838(rule 1 (lower (icmp cc a @ (value_type (ty_vec128 ty)) b)) 839 (lower_vcmp ty cc a b)) 840 841(decl lower_vcmp (Type IntCC Value Value) VReg) 842(rule (lower_vcmp $I8X16 (IntCC.Equal) a b) (pulley_veq8x16 a b)) 843(rule (lower_vcmp $I8X16 (IntCC.NotEqual) a b) (pulley_vneq8x16 a b)) 844(rule (lower_vcmp $I8X16 (IntCC.SignedLessThan) a b) (pulley_vslt8x16 a b)) 845(rule (lower_vcmp $I8X16 (IntCC.SignedLessThanOrEqual) a b) (pulley_vslteq8x16 a b)) 846(rule (lower_vcmp $I8X16 (IntCC.UnsignedLessThan) a b) (pulley_vult8x16 a b)) 847(rule (lower_vcmp $I8X16 (IntCC.UnsignedLessThanOrEqual) a b) (pulley_vulteq8x16 a b)) 848(rule (lower_vcmp $I16X8 (IntCC.Equal) a b) (pulley_veq16x8 a b)) 849(rule (lower_vcmp $I16X8 (IntCC.NotEqual) a b) (pulley_vneq16x8 a b)) 850(rule (lower_vcmp $I16X8 (IntCC.SignedLessThan) a b) (pulley_vslt16x8 a b)) 851(rule (lower_vcmp $I16X8 (IntCC.SignedLessThanOrEqual) a b) (pulley_vslteq16x8 a b)) 852(rule (lower_vcmp $I16X8 (IntCC.UnsignedLessThan) a b) (pulley_vult16x8 a b)) 853(rule (lower_vcmp $I16X8 (IntCC.UnsignedLessThanOrEqual) a b) (pulley_vulteq16x8 a b)) 854(rule (lower_vcmp $I32X4 (IntCC.Equal) a b) (pulley_veq32x4 a b)) 855(rule (lower_vcmp $I32X4 (IntCC.NotEqual) a b) (pulley_vneq32x4 a b)) 856(rule (lower_vcmp $I32X4 (IntCC.SignedLessThan) a b) (pulley_vslt32x4 a b)) 857(rule (lower_vcmp $I32X4 (IntCC.SignedLessThanOrEqual) a b) (pulley_vslteq32x4 a b)) 858(rule (lower_vcmp $I32X4 (IntCC.UnsignedLessThan) a b) (pulley_vult32x4 a b)) 859(rule (lower_vcmp $I32X4 (IntCC.UnsignedLessThanOrEqual) a b) (pulley_vulteq32x4 a b)) 860(rule (lower_vcmp $I64X2 (IntCC.Equal) a b) (pulley_veq64x2 a b)) 861(rule (lower_vcmp $I64X2 (IntCC.NotEqual) a b) (pulley_vneq64x2 a b)) 862(rule (lower_vcmp $I64X2 (IntCC.SignedLessThan) a b) (pulley_vslt64x2 a b)) 863(rule (lower_vcmp $I64X2 (IntCC.SignedLessThanOrEqual) a b) (pulley_vslteq64x2 a b)) 864(rule (lower_vcmp $I64X2 (IntCC.UnsignedLessThan) a b) (pulley_vult64x2 a b)) 865(rule (lower_vcmp $I64X2 (IntCC.UnsignedLessThanOrEqual) a b) (pulley_vulteq64x2 a b)) 866 867;; Sweap operand order of ops pulley doesn't support 868(rule (lower_vcmp ty cc @ (IntCC.SignedGreaterThan) a b) 869 (lower_vcmp ty (intcc_swap_args cc) b a)) 870(rule (lower_vcmp ty cc @ (IntCC.SignedGreaterThanOrEqual) a b) 871 (lower_vcmp ty (intcc_swap_args cc) b a)) 872(rule (lower_vcmp ty cc @ (IntCC.UnsignedGreaterThan) a b) 873 (lower_vcmp ty (intcc_swap_args cc) b a)) 874(rule (lower_vcmp ty cc @ (IntCC.UnsignedGreaterThanOrEqual) a b) 875 (lower_vcmp ty (intcc_swap_args cc) b a)) 876 877;;;; Rules for `fcmp` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 878 879(rule (lower (fcmp cc a b @ (value_type (ty_scalar_float ty)))) 880 (lower_fcmp ty cc a b)) 881 882(rule 1 (lower (fcmp cc a b @ (value_type (ty_vec128 ty)))) 883 (lower_vfcmp ty cc a b)) 884 885(decl lower_fcmp (Type FloatCC Value Value) XReg) 886 887(rule (lower_fcmp $F32 (FloatCC.Equal) a b) (pulley_feq32 a b)) 888(rule (lower_fcmp $F64 (FloatCC.Equal) a b) (pulley_feq64 a b)) 889(rule (lower_fcmp $F32 (FloatCC.NotEqual) a b) (pulley_fneq32 a b)) 890(rule (lower_fcmp $F64 (FloatCC.NotEqual) a b) (pulley_fneq64 a b)) 891(rule (lower_fcmp $F32 (FloatCC.LessThan) a b) (pulley_flt32 a b)) 892(rule (lower_fcmp $F64 (FloatCC.LessThan) a b) (pulley_flt64 a b)) 893(rule (lower_fcmp $F32 (FloatCC.LessThanOrEqual) a b) (pulley_flteq32 a b)) 894(rule (lower_fcmp $F64 (FloatCC.LessThanOrEqual) a b) (pulley_flteq64 a b)) 895 896;; Ordered == !a.is_nan() && !b.is_nan() 897(rule (lower_fcmp ty (FloatCC.Ordered) a b) 898 (pulley_xband32 (lower_fcmp ty (FloatCC.Equal) a a) (lower_fcmp ty (FloatCC.Equal) b b))) 899 900;; OrderedNotEqual == a < b || a > b 901(rule (lower_fcmp ty (FloatCC.OrderedNotEqual) a b) 902 (pulley_xbor32 (lower_fcmp ty (FloatCC.LessThan) a b) (lower_fcmp ty (FloatCC.GreaterThan) a b))) 903 904;; Pulley doesn't have instructions for `>` and `>=`, so we have to reverse the 905;; operation. 906(rule (lower_fcmp ty (FloatCC.GreaterThan) a b) 907 (lower_fcmp ty (FloatCC.LessThan) b a)) 908(rule (lower_fcmp ty (FloatCC.GreaterThanOrEqual) a b) 909 (lower_fcmp ty (FloatCC.LessThanOrEqual) b a)) 910 911;; For other `Unordered*` comparisons generate its complement and invert the result. 912(rule -1 (lower_fcmp ty cc a b) 913 (if-let true (floatcc_unordered cc)) 914 (pulley_xbxor32_s8 (lower_fcmp ty (floatcc_complement cc) a b) 1)) 915 916(decl lower_vfcmp (Type FloatCC Value Value) VReg) 917 918(rule (lower_vfcmp $F32X4 (FloatCC.Equal) a b) (pulley_veqf32x4 a b)) 919(rule (lower_vfcmp $F64X2 (FloatCC.Equal) a b) (pulley_veqf64x2 a b)) 920(rule (lower_vfcmp $F32X4 (FloatCC.NotEqual) a b) (pulley_vneqf32x4 a b)) 921(rule (lower_vfcmp $F64X2 (FloatCC.NotEqual) a b) (pulley_vneqf64x2 a b)) 922(rule (lower_vfcmp $F32X4 (FloatCC.LessThan) a b) (pulley_vltf32x4 a b)) 923(rule (lower_vfcmp $F64X2 (FloatCC.LessThan) a b) (pulley_vltf64x2 a b)) 924(rule (lower_vfcmp $F32X4 (FloatCC.LessThanOrEqual) a b) (pulley_vlteqf32x4 a b)) 925(rule (lower_vfcmp $F64X2 (FloatCC.LessThanOrEqual) a b) (pulley_vlteqf64x2 a b)) 926 927(rule (lower_vfcmp ty (FloatCC.Unordered) a b) 928 (pulley_vbor128 929 (lower_vfcmp ty (FloatCC.NotEqual) a a) 930 (lower_vfcmp ty (FloatCC.NotEqual) b b))) 931 932;; NB: Pulley doesn't have lowerings for `Ordered` or `Unordered*` `FloatCC` 933;; conditions as that's not needed by wasm at this time. 934 935;; Pulley doesn't have instructions for `>` and `>=`, so we have to reverse the 936;; operation. 937(rule (lower_vfcmp ty (FloatCC.GreaterThan) a b) 938 (lower_vfcmp ty (FloatCC.LessThan) b a)) 939(rule (lower_vfcmp ty (FloatCC.GreaterThanOrEqual) a b) 940 (lower_vfcmp ty (FloatCC.LessThanOrEqual) b a)) 941 942;;;; Rules for `load` and friends ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 943 944(rule (lower (has_type (ty_int (fits_in_64 ty)) (load flags addr offset))) 945 (gen_xload addr offset flags ty (ExtKind.None))) 946 947(rule 1 (lower (has_type (ty_scalar_float ty) (load flags addr offset))) 948 (gen_fload addr offset flags ty)) 949 950(rule 3 (lower (has_type $I128 (load flags addr offset))) 951 (if-let offsetp8 (i32_checked_add offset 8)) 952 (let ((lo XReg (pulley_xload (amode addr offset) $I64 flags)) 953 (hi XReg (pulley_xload (amode addr offsetp8) $I64 flags))) 954 (value_regs lo hi))) 955 956(rule 0 (lower (has_type (ty_int (fits_in_32 _)) (uload8 flags addr offset))) 957 (gen_xload addr offset flags $I8 (ExtKind.Zero32))) 958 959(rule 0 (lower (has_type (ty_int (fits_in_32 _)) (uload16 flags addr offset))) 960 (gen_xload addr offset flags $I16 (ExtKind.Zero32))) 961 962(rule 0 (lower (has_type (ty_int (fits_in_32 _)) (uload32 flags addr offset))) 963 (gen_xload addr offset flags $I32 (ExtKind.None))) 964 965(rule 1 (lower (has_type $I64 (uload8 flags addr offset))) 966 (gen_xload addr offset flags $I8 (ExtKind.Zero64))) 967 968(rule 1 (lower (has_type $I64 (uload16 flags addr offset))) 969 (gen_xload addr offset flags $I16 (ExtKind.Zero64))) 970 971(rule 1 (lower (has_type $I64 (uload32 flags addr offset))) 972 (gen_xload addr offset flags $I32 (ExtKind.Zero64))) 973 974(rule 0 (lower (has_type (ty_int (fits_in_32 _)) (sload8 flags addr offset))) 975 (gen_xload addr offset flags $I8 (ExtKind.Sign32))) 976 977(rule 0 (lower (has_type (ty_int (fits_in_32 _)) (sload16 flags addr offset))) 978 (gen_xload addr offset flags $I16 (ExtKind.Sign32))) 979 980(rule 0 (lower (has_type (ty_int (fits_in_32 _)) (sload32 flags addr offset))) 981 (gen_xload addr offset flags $I32 (ExtKind.None))) 982 983(rule 1 (lower (has_type $I64 (sload8 flags addr offset))) 984 (gen_xload addr offset flags $I8 (ExtKind.Sign64))) 985 986(rule 1 (lower (has_type $I64 (sload16 flags addr offset))) 987 (gen_xload addr offset flags $I16 (ExtKind.Sign64))) 988 989(rule 1 (lower (has_type $I64 (sload32 flags addr offset))) 990 (gen_xload addr offset flags $I32 (ExtKind.Sign64))) 991 992(rule 2 (lower (has_type (ty_vec128 ty) (load flags addr offset))) 993 (gen_vload addr offset flags ty (VExtKind.None))) 994 995(rule (lower (has_type ty (sload8x8 flags addr offset))) 996 (gen_vload addr offset flags ty (VExtKind.S8x8))) 997 998(rule (lower (has_type ty (uload8x8 flags addr offset))) 999 (gen_vload addr offset flags ty (VExtKind.U8x8))) 1000 1001(rule (lower (has_type ty (sload16x4 flags addr offset))) 1002 (gen_vload addr offset flags ty (VExtKind.S16x4))) 1003 1004(rule (lower (has_type ty (uload16x4 flags addr offset))) 1005 (gen_vload addr offset flags ty (VExtKind.U16x4))) 1006 1007(rule (lower (has_type ty (sload32x2 flags addr offset))) 1008 (gen_vload addr offset flags ty (VExtKind.S32x2))) 1009 1010(rule (lower (has_type ty (uload32x2 flags addr offset))) 1011 (gen_vload addr offset flags ty (VExtKind.U32x2))) 1012 1013;; Helper to generate an `xload*` instruction, of which there are many. This 1014;; falls back to the pseudo-instruction `XLoad` which has code in `emit.rs` to 1015;; emit lots of forms but it additionally supports more specific pattern-matched 1016;; versions too. 1017(decl gen_xload (Value Offset32 MemFlags Type ExtKind) XReg) 1018 1019;; Base case: use `pulley_xload` pseudo-inst for big-endian loads/stores with 1020;; no extension. This should only be used for host-things on wasm and 1021;; intentionally is minimal at this time as we don't currently need to match 1022;; all `ExtKind` variants. 1023(rule 0 (gen_xload addr offset flags ty (ExtKind.None)) 1024 (if-let true (memflags_nontrapping flags)) 1025 (if-let (Endianness.Big) (endianness flags)) 1026 (pulley_xload (amode addr offset) ty flags)) 1027 1028;; Base case: use `*_o32` addressing modes for little-endian and nontrapping 1029;; loads/stores 1030(rule 0 (gen_xload addr offset flags ty ext) 1031 (if-let true (memflags_nontrapping flags)) 1032 (if-let (Endianness.Little) (endianness flags)) 1033 (emit_addro32_xload (addro32 addr offset) ty ext)) 1034 1035(decl emit_addro32_xload (AddrO32 Type ExtKind) XReg) 1036(rule (emit_addro32_xload addr $I8 (ExtKind.None)) (pulley_xload8_u32_o32 addr)) 1037(rule (emit_addro32_xload addr $I8 (ExtKind.Sign32)) (pulley_xload8_s32_o32 addr)) 1038(rule (emit_addro32_xload addr $I8 (ExtKind.Zero32)) (pulley_xload8_u32_o32 addr)) 1039(rule (emit_addro32_xload addr $I8 (ExtKind.Sign64)) (pulley_sext32 (pulley_xload8_s32_o32 addr))) 1040(rule (emit_addro32_xload addr $I8 (ExtKind.Zero64)) (pulley_zext32 (pulley_xload8_u32_o32 addr))) 1041(rule (emit_addro32_xload addr $I16 (ExtKind.None)) (pulley_xload16le_u32_o32 addr)) 1042(rule (emit_addro32_xload addr $I16 (ExtKind.Sign32)) (pulley_xload16le_s32_o32 addr)) 1043(rule (emit_addro32_xload addr $I16 (ExtKind.Zero32)) (pulley_xload16le_u32_o32 addr)) 1044(rule (emit_addro32_xload addr $I16 (ExtKind.Sign64)) (pulley_sext32 (pulley_xload16le_s32_o32 addr))) 1045(rule (emit_addro32_xload addr $I16 (ExtKind.Zero64)) (pulley_zext32 (pulley_xload16le_u32_o32 addr))) 1046(rule (emit_addro32_xload addr $I32 (ExtKind.None)) (pulley_xload32le_o32 addr)) 1047(rule (emit_addro32_xload addr $I32 (ExtKind.Sign32)) (pulley_xload32le_o32 addr)) 1048(rule (emit_addro32_xload addr $I32 (ExtKind.Zero32)) (pulley_xload32le_o32 addr)) 1049(rule (emit_addro32_xload addr $I32 (ExtKind.Sign64)) (pulley_sext32 (pulley_xload32le_o32 addr))) 1050(rule (emit_addro32_xload addr $I32 (ExtKind.Zero64)) (pulley_zext32 (pulley_xload32le_o32 addr))) 1051(rule (emit_addro32_xload addr $I64 _ext) (pulley_xload64le_o32 addr)) 1052 1053;; Special case: wasm loads/stores that map trap use the `*_z` addressing modes 1054;; which generates a trap for load-from-null. 1055(rule 1 (gen_xload addr offset flags ty ext) 1056 (if-let true (memflags_is_wasm flags)) 1057 (emit_addrz_xload (addrz addr offset) ty ext)) 1058 1059(decl emit_addrz_xload (AddrZ Type ExtKind) XReg) 1060(rule (emit_addrz_xload addr $I8 (ExtKind.None)) (pulley_xload8_u32_z addr)) 1061(rule (emit_addrz_xload addr $I8 (ExtKind.Sign32)) (pulley_xload8_s32_z addr)) 1062(rule (emit_addrz_xload addr $I8 (ExtKind.Zero32)) (pulley_xload8_u32_z addr)) 1063(rule (emit_addrz_xload addr $I8 (ExtKind.Sign64)) (pulley_sext32 (pulley_xload8_s32_z addr))) 1064(rule (emit_addrz_xload addr $I8 (ExtKind.Zero64)) (pulley_zext32 (pulley_xload8_u32_z addr))) 1065(rule (emit_addrz_xload addr $I16 (ExtKind.None)) (pulley_xload16le_u32_z addr)) 1066(rule (emit_addrz_xload addr $I16 (ExtKind.Sign32)) (pulley_xload16le_s32_z addr)) 1067(rule (emit_addrz_xload addr $I16 (ExtKind.Zero32)) (pulley_xload16le_u32_z addr)) 1068(rule (emit_addrz_xload addr $I16 (ExtKind.Sign64)) (pulley_sext32 (pulley_xload16le_s32_z addr))) 1069(rule (emit_addrz_xload addr $I16 (ExtKind.Zero64)) (pulley_zext32 (pulley_xload16le_u32_z addr))) 1070(rule (emit_addrz_xload addr $I32 (ExtKind.None)) (pulley_xload32le_z addr)) 1071(rule (emit_addrz_xload addr $I32 (ExtKind.Sign32)) (pulley_xload32le_z addr)) 1072(rule (emit_addrz_xload addr $I32 (ExtKind.Zero32)) (pulley_xload32le_z addr)) 1073(rule (emit_addrz_xload addr $I32 (ExtKind.Sign64)) (pulley_sext32 (pulley_xload32le_z addr))) 1074(rule (emit_addrz_xload addr $I32 (ExtKind.Zero64)) (pulley_zext32 (pulley_xload32le_z addr))) 1075(rule (emit_addrz_xload addr $I64 _ext) (pulley_xload64le_z addr)) 1076 1077;; Special case: wasm loads/stores that may trap use the `*_g32` addressing 1078;; modes. This is a superset of the `*_z` modes above and requires extracting 1079;; a bounds check from within `addr` using a `select` condition. 1080(rule 2 (gen_xload addr offset flags ty ext) 1081 (if-let addrg32 (wasm_g32 addr offset flags ty)) 1082 (gen_xload_g32 addrg32 ty ext)) 1083 1084;; Base case of "g32" loads, emit the instructions 1085(decl gen_xload_g32 (G32 Type ExtKind) XReg) 1086(rule 0 (gen_xload_g32 addr ty ext) (emit_addrg32_xload addr ty ext)) 1087 1088(decl emit_addrg32_xload (AddrG32 Type ExtKind) XReg) 1089(rule (emit_addrg32_xload addr $I8 (ExtKind.None)) (pulley_xload8_u32_g32 addr)) 1090(rule (emit_addrg32_xload addr $I8 (ExtKind.Sign32)) (pulley_xload8_s32_g32 addr)) 1091(rule (emit_addrg32_xload addr $I8 (ExtKind.Zero32)) (pulley_xload8_u32_g32 addr)) 1092(rule (emit_addrg32_xload addr $I8 (ExtKind.Sign64)) (pulley_sext32 (pulley_xload8_s32_g32 addr))) 1093(rule (emit_addrg32_xload addr $I8 (ExtKind.Zero64)) (pulley_zext32 (pulley_xload8_u32_g32 addr))) 1094(rule (emit_addrg32_xload addr $I16 (ExtKind.None)) (pulley_xload16le_u32_g32 addr)) 1095(rule (emit_addrg32_xload addr $I16 (ExtKind.Sign32)) (pulley_xload16le_s32_g32 addr)) 1096(rule (emit_addrg32_xload addr $I16 (ExtKind.Zero32)) (pulley_xload16le_u32_g32 addr)) 1097(rule (emit_addrg32_xload addr $I16 (ExtKind.Sign64)) (pulley_sext32 (pulley_xload16le_s32_g32 addr))) 1098(rule (emit_addrg32_xload addr $I16 (ExtKind.Zero64)) (pulley_zext32 (pulley_xload16le_u32_g32 addr))) 1099(rule (emit_addrg32_xload addr $I32 (ExtKind.None)) (pulley_xload32le_g32 addr)) 1100(rule (emit_addrg32_xload addr $I32 (ExtKind.Sign32)) (pulley_xload32le_g32 addr)) 1101(rule (emit_addrg32_xload addr $I32 (ExtKind.Zero32)) (pulley_xload32le_g32 addr)) 1102(rule (emit_addrg32_xload addr $I32 (ExtKind.Sign64)) (pulley_sext32 (pulley_xload32le_g32 addr))) 1103(rule (emit_addrg32_xload addr $I32 (ExtKind.Zero64)) (pulley_zext32 (pulley_xload32le_g32 addr))) 1104(rule (emit_addrg32_xload addr $I64 _ext) (pulley_xload64le_g32 addr)) 1105 1106;; Special case of "g32" load - if a "g32bne" mode is possible instead use that. 1107(rule 1 (gen_xload_g32 addr ty ext) 1108 (if-let addrbne (addrg32bne addr)) 1109 (emit_addrg32bne_xload addrbne ty ext)) 1110 1111(decl emit_addrg32bne_xload (AddrG32Bne Type ExtKind) XReg) 1112(rule (emit_addrg32bne_xload addr $I8 (ExtKind.None)) (pulley_xload8_u32_g32bne addr)) 1113(rule (emit_addrg32bne_xload addr $I8 (ExtKind.Sign32)) (pulley_xload8_s32_g32bne addr)) 1114(rule (emit_addrg32bne_xload addr $I8 (ExtKind.Zero32)) (pulley_xload8_u32_g32bne addr)) 1115(rule (emit_addrg32bne_xload addr $I8 (ExtKind.Sign64)) (pulley_sext32 (pulley_xload8_s32_g32bne addr))) 1116(rule (emit_addrg32bne_xload addr $I8 (ExtKind.Zero64)) (pulley_zext32 (pulley_xload8_u32_g32bne addr))) 1117(rule (emit_addrg32bne_xload addr $I16 (ExtKind.None)) (pulley_xload16le_u32_g32bne addr)) 1118(rule (emit_addrg32bne_xload addr $I16 (ExtKind.Sign32)) (pulley_xload16le_s32_g32bne addr)) 1119(rule (emit_addrg32bne_xload addr $I16 (ExtKind.Zero32)) (pulley_xload16le_u32_g32bne addr)) 1120(rule (emit_addrg32bne_xload addr $I16 (ExtKind.Sign64)) (pulley_sext32 (pulley_xload16le_s32_g32bne addr))) 1121(rule (emit_addrg32bne_xload addr $I16 (ExtKind.Zero64)) (pulley_zext32 (pulley_xload16le_u32_g32bne addr))) 1122(rule (emit_addrg32bne_xload addr $I32 (ExtKind.None)) (pulley_xload32le_g32bne addr)) 1123(rule (emit_addrg32bne_xload addr $I32 (ExtKind.Sign32)) (pulley_xload32le_g32bne addr)) 1124(rule (emit_addrg32bne_xload addr $I32 (ExtKind.Zero32)) (pulley_xload32le_g32bne addr)) 1125(rule (emit_addrg32bne_xload addr $I32 (ExtKind.Sign64)) (pulley_sext32 (pulley_xload32le_g32bne addr))) 1126(rule (emit_addrg32bne_xload addr $I32 (ExtKind.Zero64)) (pulley_zext32 (pulley_xload32le_g32bne addr))) 1127(rule (emit_addrg32bne_xload addr $I64 _ext) (pulley_xload64le_g32bne addr)) 1128 1129;; Analog of `gen_xload`, but for floating-point registers 1130(decl gen_fload (Value Offset32 MemFlags Type) FReg) 1131 1132;; Base case: nontrapping loads/stores use the `fload` helper which bottoms out 1133;; in `emit.rs` using the `*_o32` addressing mode. 1134(rule 0 (gen_fload addr offset flags ty) 1135 (if-let true (memflags_nontrapping flags)) 1136 (pulley_fload (amode addr offset) ty flags)) 1137 1138;; Base case: use trapping loads stores with the `*_z` addressing mode for 1139;; wasm-looking loads/stores. 1140(rule 1 (gen_fload addr offset flags ty) 1141 (if-let true (memflags_is_wasm flags)) 1142 (emit_addrz_fload (addrz addr offset) ty)) 1143 1144(decl emit_addrz_fload (AddrZ Type) FReg) 1145(rule (emit_addrz_fload addr $F32) (pulley_fload32le_z addr)) 1146(rule (emit_addrz_fload addr $F64) (pulley_fload64le_z addr)) 1147 1148;; Special case: use `*_g32` addressing when the bounds-check can be 1149;; pattern-matched. 1150(rule 2 (gen_fload addr offset flags ty) 1151 (if-let addrg32 (wasm_g32 addr offset flags ty)) 1152 (emit_addrg32_fload addrg32 ty)) 1153 1154(decl emit_addrg32_fload (AddrG32 Type) FReg) 1155(rule (emit_addrg32_fload addr $F32) (pulley_fload32le_g32 addr)) 1156(rule (emit_addrg32_fload addr $F64) (pulley_fload64le_g32 addr)) 1157 1158;; Analog of `gen_xload`, but for vector registers. 1159(decl gen_vload (Value Offset32 MemFlags Type VExtKind) VReg) 1160 1161;; Base case: nontrapping loads/stores use the `*_o32` addressing mode through 1162;; helpers in `emit.rs` and the `pulley_vload` pseudo-inst. Note that this 1163;; intentionally doesn't support all extension kinds. 1164(rule 0 (gen_vload addr offset flags ty (VExtKind.None)) 1165 (if-let true (memflags_nontrapping flags)) 1166 (pulley_vload (amode addr offset) ty flags)) 1167 1168;; Base case: wasm loads/stores using the `*_z` addressing mode. 1169(rule 1 (gen_vload addr offset flags ty ext) 1170 (if-let true (memflags_is_wasm flags)) 1171 (emit_addrz_vload (addrz addr offset) ty ext)) 1172 1173(decl emit_addrz_vload (AddrZ Type VExtKind) VReg) 1174(rule (emit_addrz_vload addr (ty_vec128 _) (VExtKind.None)) (pulley_vload128le_z addr)) 1175(rule (emit_addrz_vload addr (ty_vec128 _) (VExtKind.S8x8)) (pulley_vload8x8_s_z addr)) 1176(rule (emit_addrz_vload addr (ty_vec128 _) (VExtKind.U8x8)) (pulley_vload8x8_u_z addr)) 1177(rule (emit_addrz_vload addr (ty_vec128 _) (VExtKind.S16x4)) (pulley_vload16x4le_s_z addr)) 1178(rule (emit_addrz_vload addr (ty_vec128 _) (VExtKind.U16x4)) (pulley_vload16x4le_u_z addr)) 1179(rule (emit_addrz_vload addr (ty_vec128 _) (VExtKind.S32x2)) (pulley_vload32x2le_s_z addr)) 1180(rule (emit_addrz_vload addr (ty_vec128 _) (VExtKind.U32x2)) (pulley_vload32x2le_u_z addr)) 1181 1182;; Special case: use `*_g32` addressing when the bounds-check can be 1183;; pattern-matched. 1184(rule 2 (gen_vload addr offset flags (ty_vec128 ty) (VExtKind.None)) 1185 (if-let addrg32 (wasm_g32 addr offset flags ty)) 1186 (pulley_vload128le_g32 addrg32)) 1187 1188;;;; Rules for `store` and friends ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 1189 1190(rule (lower (store flags src @ (value_type (ty_int (fits_in_64 ty))) addr offset)) 1191 (side_effect (gen_store src addr offset flags ty))) 1192 1193(rule 1 (lower (store flags src @ (value_type (ty_scalar_float ty)) addr offset)) 1194 (side_effect (gen_store src addr offset flags ty))) 1195 1196(rule (lower (istore8 flags src addr offset)) 1197 (side_effect (gen_store src addr offset flags $I8))) 1198 1199(rule (lower (istore16 flags src addr offset)) 1200 (side_effect (gen_store src addr offset flags $I16))) 1201 1202(rule (lower (istore32 flags src addr offset)) 1203 (side_effect (gen_store src addr offset flags $I32))) 1204 1205(rule 2 (lower (store flags src @ (value_type (ty_vec128 ty)) addr offset)) 1206 (side_effect (gen_store src addr offset flags ty))) 1207 1208;; i128 stores 1209 1210(rule 3 (lower (store flags src @ (value_type $I128) addr offset)) 1211 (let 1212 ((src_regs ValueRegs src) 1213 (src_lo XReg (value_regs_get src_regs 0)) 1214 (src_hi XReg (value_regs_get src_regs 1)) 1215 (addrp0 XReg addr) 1216 (addrp8 Amode (Amode.RegOffset addrp0 8))) 1217 (side_effect (emit_store_i128 flags src_lo src_hi (Amode.RegOffset addrp0 0) addrp8)))) 1218 1219;; Helper to handle big/little endian to determine which order the lo/hi 1220;; halves of the i128 are stored. 1221(decl emit_store_i128 (MemFlags XReg XReg Amode Amode) SideEffectNoResult) 1222(rule 0 (emit_store_i128 flags lo hi addrp0 addrp8) 1223 (if-let (Endianness.Little) (endianness flags)) 1224 (let ((_ InstOutput (side_effect (pulley_xstore addrp0 lo $I64 flags)))) 1225 (pulley_xstore addrp8 hi $I64 flags))) 1226(rule 1 (emit_store_i128 flags lo hi addrp0 addrp8) 1227 (if-let (Endianness.Big) (endianness flags)) 1228 (let ((_ InstOutput (side_effect (pulley_xstore addrp0 hi $I64 flags)))) 1229 (pulley_xstore addrp8 lo $I64 flags))) 1230 1231;; Helper function to store the first argument into the second argument. This 1232;; only stores up to the width of the `Type` specified, regardless of what the 1233;; type of the first argument is. 1234(decl gen_store (Value Value Offset32 MemFlags Type) SideEffectNoResult) 1235 1236;; Base cases: normal typed loads/stores 1237(rule 0 (gen_store src addr offset flags (ty_int ty)) 1238 (if-let true (memflags_nontrapping flags)) 1239 (pulley_xstore (amode addr offset) src ty flags)) 1240(rule 1 (gen_store src addr offset flags (ty_scalar_float ty)) 1241 (if-let true (memflags_nontrapping flags)) 1242 (pulley_fstore (amode addr offset) src ty flags)) 1243(rule 2 (gen_store src addr offset flags (ty_vec128 ty)) 1244 (if-let true (memflags_nontrapping flags)) 1245 (pulley_vstore (amode addr offset) src ty flags)) 1246 1247;; Base case: wasm stores 1248(rule 3 (gen_store src addr offset flags ty) 1249 (if-let true (memflags_is_wasm flags)) 1250 (emit_addrz_store (addrz addr offset) src ty)) 1251 1252(decl emit_addrz_store (AddrZ Value Type) SideEffectNoResult) 1253(rule (emit_addrz_store addr val $I8) (pulley_xstore8_z addr val)) 1254(rule (emit_addrz_store addr val $I16) (pulley_xstore16le_z addr val)) 1255(rule (emit_addrz_store addr val $I32) (pulley_xstore32le_z addr val)) 1256(rule (emit_addrz_store addr val $I64) (pulley_xstore64le_z addr val)) 1257(rule (emit_addrz_store addr val $F32) (pulley_fstore32le_z addr val)) 1258(rule (emit_addrz_store addr val $F64) (pulley_fstore64le_z addr val)) 1259(rule 1 (emit_addrz_store addr val (ty_vec128 _)) (pulley_vstore128le_z addr val)) 1260 1261;; special case: wasm stores with a folded bounds check 1262(rule 4 (gen_store src addr offset flags ty) 1263 (if-let addrg32 (wasm_g32 addr offset flags ty)) 1264 (emit_addrg32_store addrg32 src ty)) 1265 1266(decl emit_addrg32_store (AddrG32 Value Type) SideEffectNoResult) 1267(rule (emit_addrg32_store addr val $I8) (pulley_xstore8_g32 addr val)) 1268(rule (emit_addrg32_store addr val $I16) (pulley_xstore16le_g32 addr val)) 1269(rule (emit_addrg32_store addr val $I32) (pulley_xstore32le_g32 addr val)) 1270(rule (emit_addrg32_store addr val $I64) (pulley_xstore64le_g32 addr val)) 1271(rule (emit_addrg32_store addr val $F32) (pulley_fstore32le_g32 addr val)) 1272(rule (emit_addrg32_store addr val $F64) (pulley_fstore64le_g32 addr val)) 1273(rule 1 (emit_addrg32_store addr val (ty_vec128 _)) (pulley_vstore128le_g32 addr val)) 1274 1275;;;; Rules for `stack_addr` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 1276 1277(rule (lower (stack_addr stack_slot offset)) 1278 (lower_stack_addr stack_slot offset)) 1279 1280(decl lower_stack_addr (StackSlot Offset32) XReg) 1281(rule (lower_stack_addr stack_slot offset) 1282 (let ((dst WritableXReg (temp_writable_xreg)) 1283 (_ Unit (emit (abi_stackslot_addr dst stack_slot offset)))) 1284 dst)) 1285 1286;;;; Rules for `uextend` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 1287 1288(rule 0 (lower (has_type (fits_in_32 _) (uextend val))) 1289 (zext32 val)) 1290 1291(rule 1 (lower (has_type $I64 (uextend val))) 1292 (zext64 val)) 1293 1294(rule 1 (lower (has_type $I128 (uextend val))) 1295 (value_regs (zext64 val) (pulley_xzero))) 1296 1297;;;; Rules for `sextend` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 1298 1299(rule 0 (lower (has_type (fits_in_32 _) (sextend val))) 1300 (sext32 val)) 1301 1302(rule 1 (lower (has_type $I64 (sextend val))) 1303 (sext64 val)) 1304 1305(rule 1 (lower (has_type $I128 (sextend val))) 1306 (if-let (u6_from_u8 shift) (u64_try_into_u8 63)) 1307 (let ((lo XReg (sext64 val)) 1308 (hi XReg (pulley_xshr64_s_u6 lo shift))) 1309 (value_regs lo hi))) 1310 1311;;;; Rules for `ireduce` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 1312 1313(rule (lower (has_type (fits_in_64 _ty) (ireduce src))) 1314 src) 1315 1316;;;; Rules for `iconcat` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 1317 1318(rule (lower (has_type $I128 (iconcat a b))) 1319 (value_regs a b)) 1320 1321;;;; Rules for `isplit` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 1322 1323(rule (lower (isplit x @ (value_type $I128))) 1324 (let ((lo XReg (value_regs_get x 0)) 1325 (hi XReg (value_regs_get x 1))) 1326 (output_pair lo hi))) 1327 1328;;;; Rules for `uadd_overflow_trap` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 1329 1330(rule (lower (has_type $I32 (uadd_overflow_trap a b tc))) 1331 (pulley_xadd32_uoverflow_trap a b tc)) 1332 1333(rule (lower (has_type $I64 (uadd_overflow_trap a b tc))) 1334 (pulley_xadd64_uoverflow_trap a b tc)) 1335 1336;;;; Rules for `select` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 1337 1338(rule 0 (lower (has_type (ty_int (fits_in_32 _)) (select c a b))) 1339 (pulley_xselect32 (emit_cond (lower_cond c)) a b)) 1340 1341(rule 1 (lower (has_type $I64 (select c a b))) 1342 (pulley_xselect64 (emit_cond (lower_cond c)) a b)) 1343 1344(rule 1 (lower (has_type $F32 (select c a b))) 1345 (pulley_fselect32 (emit_cond (lower_cond c)) a b)) 1346 1347(rule 1 (lower (has_type $F64 (select c a b))) 1348 (pulley_fselect64 (emit_cond (lower_cond c)) a b)) 1349 1350(rule 2 (lower (has_type (ty_vec128 _) (select c a b))) 1351 (pulley_vselect (emit_cond (lower_cond c)) a b)) 1352 1353;; Helper to emit a conditional into a register itself. 1354(decl emit_cond (Cond) XReg) 1355(rule (emit_cond (Cond.If32 reg)) reg) 1356(rule (emit_cond (Cond.IfNot32 reg)) (pulley_xeq32 reg (pulley_xconst8 0))) 1357(rule (emit_cond (Cond.IfXeq32 src1 src2)) (pulley_xeq32 src1 src2)) 1358(rule (emit_cond (Cond.IfXneq32 src1 src2)) (pulley_xneq32 src1 src2)) 1359(rule (emit_cond (Cond.IfXslt32 src1 src2)) (pulley_xslt32 src1 src2)) 1360(rule (emit_cond (Cond.IfXslteq32 src1 src2)) (pulley_xslteq32 src1 src2)) 1361(rule (emit_cond (Cond.IfXult32 src1 src2)) (pulley_xult32 src1 src2)) 1362(rule (emit_cond (Cond.IfXulteq32 src1 src2)) (pulley_xulteq32 src1 src2)) 1363(rule (emit_cond (Cond.IfXeq64 src1 src2)) (pulley_xeq64 src1 src2)) 1364(rule (emit_cond (Cond.IfXneq64 src1 src2)) (pulley_xneq64 src1 src2)) 1365(rule (emit_cond (Cond.IfXslt64 src1 src2)) (pulley_xslt64 src1 src2)) 1366(rule (emit_cond (Cond.IfXslteq64 src1 src2)) (pulley_xslteq64 src1 src2)) 1367(rule (emit_cond (Cond.IfXult64 src1 src2)) (pulley_xult64 src1 src2)) 1368(rule (emit_cond (Cond.IfXulteq64 src1 src2)) (pulley_xulteq64 src1 src2)) 1369 1370(rule (emit_cond (Cond.IfXeq32I32 src1 src2)) (pulley_xeq32 src1 (imm src2))) 1371(rule (emit_cond (Cond.IfXneq32I32 src1 src2)) (pulley_xneq32 src1 (imm src2))) 1372(rule (emit_cond (Cond.IfXslt32I32 src1 src2)) (pulley_xslt32 src1 (imm src2))) 1373(rule (emit_cond (Cond.IfXslteq32I32 src1 src2)) (pulley_xslteq32 src1 (imm src2))) 1374(rule (emit_cond (Cond.IfXult32I32 src1 src2)) (pulley_xult32 src1 (imm src2))) 1375(rule (emit_cond (Cond.IfXulteq32I32 src1 src2)) (pulley_xulteq32 src1 (imm src2))) 1376 1377;; Note the operand swaps here 1378(rule (emit_cond (Cond.IfXsgt32I32 src1 src2)) (pulley_xslt32 (imm src2) src1)) 1379(rule (emit_cond (Cond.IfXsgteq32I32 src1 src2)) (pulley_xslteq32 (imm src2) src1)) 1380(rule (emit_cond (Cond.IfXugt32I32 src1 src2)) (pulley_xult32 (imm src2) src1)) 1381(rule (emit_cond (Cond.IfXugteq32I32 src1 src2)) (pulley_xulteq32 (imm src2) src1)) 1382 1383(rule (emit_cond (Cond.IfXeq64I32 src1 src2)) (pulley_xeq64 src1 (imm src2))) 1384(rule (emit_cond (Cond.IfXneq64I32 src1 src2)) (pulley_xneq64 src1 (imm src2))) 1385(rule (emit_cond (Cond.IfXslt64I32 src1 src2)) (pulley_xslt64 src1 (imm src2))) 1386(rule (emit_cond (Cond.IfXslteq64I32 src1 src2)) (pulley_xslteq64 src1 (imm src2))) 1387(rule (emit_cond (Cond.IfXult64I32 src1 src2)) (pulley_xult64 src1 (imm src2))) 1388(rule (emit_cond (Cond.IfXulteq64I32 src1 src2)) (pulley_xulteq64 src1 (imm src2))) 1389 1390;; Note the operand swaps here 1391(rule (emit_cond (Cond.IfXsgt64I32 src1 src2)) (pulley_xslt64 (imm src2) src1)) 1392(rule (emit_cond (Cond.IfXsgteq64I32 src1 src2)) (pulley_xslteq64 (imm src2) src1)) 1393(rule (emit_cond (Cond.IfXugt64I32 src1 src2)) (pulley_xult64 (imm src2) src1)) 1394(rule (emit_cond (Cond.IfXugteq64I32 src1 src2)) (pulley_xulteq64 (imm src2) src1)) 1395 1396;;;; Rules for `bitcast` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 1397 1398(rule (lower (has_type $F32 (bitcast _flags val @ (value_type $I32)))) 1399 (pulley_bitcast_float_from_int_32 val)) 1400 1401(rule (lower (has_type $F64 (bitcast _flags val @ (value_type $I64)))) 1402 (pulley_bitcast_float_from_int_64 val)) 1403 1404(rule (lower (has_type $I32 (bitcast _flags val @ (value_type $F32)))) 1405 (pulley_bitcast_int_from_float_32 val)) 1406 1407(rule (lower (has_type $I64 (bitcast _flags val @ (value_type $F64)))) 1408 (pulley_bitcast_int_from_float_64 val)) 1409 1410(rule 1 (lower (has_type (ty_vec128 _) (bitcast _flags val @ (value_type (ty_vec128 _))))) 1411 val) 1412 1413(rule 2 (lower (has_type ty (bitcast _flags a @ (value_type ty)))) a) 1414 1415;;;; Rules for `fcvt_to_{u,s}int` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 1416 1417(rule (lower (has_type $I32 (fcvt_to_uint val @ (value_type $F32)))) 1418 (pulley_x32_from_f32_u val)) 1419 1420(rule (lower (has_type $I32 (fcvt_to_uint val @ (value_type $F64)))) 1421 (pulley_x32_from_f64_u val)) 1422 1423(rule (lower (has_type $I64 (fcvt_to_uint val @ (value_type $F32)))) 1424 (pulley_x64_from_f32_u val)) 1425 1426(rule (lower (has_type $I64 (fcvt_to_uint val @ (value_type $F64)))) 1427 (pulley_x64_from_f64_u val)) 1428 1429(rule (lower (has_type $I32 (fcvt_to_sint val @ (value_type $F32)))) 1430 (pulley_x32_from_f32_s val)) 1431 1432(rule (lower (has_type $I32 (fcvt_to_sint val @ (value_type $F64)))) 1433 (pulley_x32_from_f64_s val)) 1434 1435(rule (lower (has_type $I64 (fcvt_to_sint val @ (value_type $F32)))) 1436 (pulley_x64_from_f32_s val)) 1437 1438(rule (lower (has_type $I64 (fcvt_to_sint val @ (value_type $F64)))) 1439 (pulley_x64_from_f64_s val)) 1440 1441;;;; Rules for `fcvt_from_{u,s}int` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 1442 1443(rule 0 (lower (has_type $F32 (fcvt_from_uint val @ (value_type (fits_in_32 _))))) 1444 (pulley_f32_from_x32_u (zext32 val))) 1445 1446(rule 1 (lower (has_type $F32 (fcvt_from_uint val @ (value_type $I64)))) 1447 (pulley_f32_from_x64_u val)) 1448 1449(rule 0 (lower (has_type $F64 (fcvt_from_uint val @ (value_type (fits_in_32 _))))) 1450 (pulley_f64_from_x32_u (zext32 val))) 1451 1452(rule 1 (lower (has_type $F64 (fcvt_from_uint val @ (value_type $I64)))) 1453 (pulley_f64_from_x64_u val)) 1454 1455(rule 0 (lower (has_type $F32 (fcvt_from_sint val @ (value_type (fits_in_32 _))))) 1456 (pulley_f32_from_x32_s (sext32 val))) 1457 1458(rule 1 (lower (has_type $F32 (fcvt_from_sint val @ (value_type $I64)))) 1459 (pulley_f32_from_x64_s val)) 1460 1461(rule 0 (lower (has_type $F64 (fcvt_from_sint val @ (value_type (fits_in_32 _))))) 1462 (pulley_f64_from_x32_s (sext32 val))) 1463 1464(rule 1 (lower (has_type $F64 (fcvt_from_sint val @ (value_type $I64)))) 1465 (pulley_f64_from_x64_s val)) 1466 1467(rule (lower (has_type $F32X4 (fcvt_from_sint val @ (value_type $I32X4)))) 1468 (pulley_vf32x4_from_i32x4_s val)) 1469 1470(rule (lower (has_type $F32X4 (fcvt_from_uint val @ (value_type $I32X4)))) 1471 (pulley_vf32x4_from_i32x4_u val)) 1472 1473(rule (lower (has_type $F64X2 (fcvt_from_sint val @ (value_type $I64X2)))) 1474 (pulley_vf64x2_from_i64x2_s val)) 1475 1476(rule (lower (has_type $F64X2 (fcvt_from_uint val @ (value_type $I64X2)))) 1477 (pulley_vf64x2_from_i64x2_u val)) 1478 1479;;;; Rules for `fcvt_to_{u,s}int_sat` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 1480 1481(rule (lower (has_type $I32 (fcvt_to_uint_sat val @ (value_type $F32)))) 1482 (pulley_x32_from_f32_u_sat val)) 1483 1484(rule (lower (has_type $I32 (fcvt_to_uint_sat val @ (value_type $F64)))) 1485 (pulley_x32_from_f64_u_sat val)) 1486 1487(rule (lower (has_type $I64 (fcvt_to_uint_sat val @ (value_type $F32)))) 1488 (pulley_x64_from_f32_u_sat val)) 1489 1490(rule (lower (has_type $I64 (fcvt_to_uint_sat val @ (value_type $F64)))) 1491 (pulley_x64_from_f64_u_sat val)) 1492 1493(rule (lower (has_type $I32 (fcvt_to_sint_sat val @ (value_type $F32)))) 1494 (pulley_x32_from_f32_s_sat val)) 1495 1496(rule (lower (has_type $I32 (fcvt_to_sint_sat val @ (value_type $F64)))) 1497 (pulley_x32_from_f64_s_sat val)) 1498 1499(rule (lower (has_type $I64 (fcvt_to_sint_sat val @ (value_type $F32)))) 1500 (pulley_x64_from_f32_s_sat val)) 1501 1502(rule (lower (has_type $I64 (fcvt_to_sint_sat val @ (value_type $F64)))) 1503 (pulley_x64_from_f64_s_sat val)) 1504 1505(rule (lower (has_type $I32X4 (fcvt_to_sint_sat val @ (value_type $F32X4)))) 1506 (pulley_vi32x4_from_f32x4_s val)) 1507 1508(rule (lower (has_type $I32X4 (fcvt_to_uint_sat val @ (value_type $F32X4)))) 1509 (pulley_vi32x4_from_f32x4_u val)) 1510 1511(rule (lower (has_type $I64X2 (fcvt_to_sint_sat val @ (value_type $F64X2)))) 1512 (pulley_vi64x2_from_f64x2_s val)) 1513 1514(rule (lower (has_type $I64X2 (fcvt_to_uint_sat val @ (value_type $F64X2)))) 1515 (pulley_vi64x2_from_f64x2_u val)) 1516 1517;;;; Rules for `fdemote` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 1518 1519(rule (lower (has_type $F32 (fdemote val @ (value_type $F64)))) 1520 (pulley_f32_from_f64 val)) 1521 1522;;;; Rules for `fpromote` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 1523 1524(rule (lower (has_type $F64 (fpromote val @ (value_type $F32)))) 1525 (pulley_f64_from_f32 val)) 1526 1527;;;; Rules for `fcopysign` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 1528 1529(rule (lower (has_type $F32 (fcopysign a b))) 1530 (pulley_fcopysign32 a b)) 1531 1532(rule (lower (has_type $F64 (fcopysign a b))) 1533 (pulley_fcopysign64 a b)) 1534 1535;;;; Rules for `fadd` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 1536 1537(rule (lower (has_type $F32 (fadd a b))) (pulley_fadd32 a b)) 1538(rule (lower (has_type $F64 (fadd a b))) (pulley_fadd64 a b)) 1539(rule (lower (has_type $F32X4 (fadd a b))) (pulley_vaddf32x4 a b)) 1540(rule (lower (has_type $F64X2 (fadd a b))) (pulley_vaddf64x2 a b)) 1541 1542;;;; Rules for `fsub` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 1543 1544(rule (lower (has_type $F32 (fsub a b))) (pulley_fsub32 a b)) 1545(rule (lower (has_type $F64 (fsub a b))) (pulley_fsub64 a b)) 1546(rule (lower (has_type $F32X4 (fsub a b))) (pulley_vsubf32x4 a b)) 1547(rule (lower (has_type $F64X2 (fsub a b))) (pulley_vsubf64x2 a b)) 1548 1549;;;; Rules for `fmul` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 1550 1551(rule (lower (has_type $F32 (fmul a b))) (pulley_fmul32 a b)) 1552(rule (lower (has_type $F64 (fmul a b))) (pulley_fmul64 a b)) 1553(rule (lower (has_type $F32X4 (fmul a b))) (pulley_vmulf32x4 a b)) 1554(rule (lower (has_type $F64X2 (fmul a b))) (pulley_vmulf64x2 a b)) 1555 1556;;;; Rules for `fdiv` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 1557 1558(rule (lower (has_type $F32 (fdiv a b))) (pulley_fdiv32 a b)) 1559(rule (lower (has_type $F64 (fdiv a b))) (pulley_fdiv64 a b)) 1560(rule (lower (has_type $F32X4 (fdiv a b))) (pulley_vdivf32x4 a b)) 1561(rule (lower (has_type $F64X2 (fdiv a b))) (pulley_vdivf64x2 a b)) 1562 1563;;;; Rules for `fmax` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 1564 1565(rule (lower (has_type $F32 (fmax a b))) (pulley_fmaximum32 a b)) 1566(rule (lower (has_type $F64 (fmax a b))) (pulley_fmaximum64 a b)) 1567(rule (lower (has_type $F32X4 (fmax a b))) (pulley_vmaximumf32x4 a b)) 1568(rule (lower (has_type $F64X2 (fmax a b))) (pulley_vmaximumf64x2 a b)) 1569 1570;;;; Rules for `fmin` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 1571 1572(rule (lower (has_type $F32 (fmin a b))) (pulley_fminimum32 a b)) 1573(rule (lower (has_type $F64 (fmin a b))) (pulley_fminimum64 a b)) 1574(rule (lower (has_type $F32X4 (fmin a b))) (pulley_vminimumf32x4 a b)) 1575(rule (lower (has_type $F64X2 (fmin a b))) (pulley_vminimumf64x2 a b)) 1576 1577;;;; Rules for `trunc` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 1578 1579(rule (lower (has_type $F32 (trunc a))) (pulley_ftrunc32 a)) 1580(rule (lower (has_type $F64 (trunc a))) (pulley_ftrunc64 a)) 1581(rule (lower (has_type $F32X4 (trunc a))) (pulley_vtrunc32x4 a)) 1582(rule (lower (has_type $F64X2 (trunc a))) (pulley_vtrunc64x2 a)) 1583 1584;;;; Rules for `floor` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 1585 1586(rule (lower (has_type $F32 (floor a))) (pulley_ffloor32 a)) 1587(rule (lower (has_type $F64 (floor a))) (pulley_ffloor64 a)) 1588(rule (lower (has_type $F32X4 (floor a))) 1589 (pulley_vfloor32x4 a)) 1590(rule (lower (has_type $F64X2 (floor a))) 1591 (pulley_vfloor64x2 a)) 1592 1593;;;; Rules for `ceil` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 1594 1595(rule (lower (has_type $F32 (ceil a))) (pulley_fceil32 a)) 1596(rule (lower (has_type $F64 (ceil a))) (pulley_fceil64 a)) 1597(rule (lower (has_type $F64X2 (ceil a))) 1598 (pulley_vceil64x2 a)) 1599(rule (lower (has_type $F32X4 (ceil a))) 1600 (pulley_vceil32x4 a)) 1601 1602;;;; Rules for `nearest` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 1603 1604(rule (lower (has_type $F32 (nearest a))) (pulley_fnearest32 a)) 1605(rule (lower (has_type $F64 (nearest a))) (pulley_fnearest64 a)) 1606(rule (lower (has_type $F32X4 (nearest a))) 1607 (pulley_vnearest32x4 a)) 1608(rule (lower (has_type $F64X2 (nearest a))) 1609 (pulley_vnearest64x2 a)) 1610 1611;;;; Rules for `sqrt` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 1612 1613(rule (lower (has_type $F32 (sqrt a))) (pulley_fsqrt32 a)) 1614(rule (lower (has_type $F64 (sqrt a))) (pulley_fsqrt64 a)) 1615(rule (lower (has_type $F32X4 (sqrt a))) 1616 (pulley_vsqrt32x4 a)) 1617(rule (lower (has_type $F64X2 (sqrt a))) 1618 (pulley_vsqrt64x2 a)) 1619 1620;;;; Rules for `fneg` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 1621 1622(rule (lower (has_type $F32 (fneg a))) (pulley_fneg32 a)) 1623(rule (lower (has_type $F64 (fneg a))) (pulley_fneg64 a)) 1624(rule (lower (has_type $F32X4 (fneg a))) (pulley_vnegf32x4 a)) 1625(rule (lower (has_type $F64X2 (fneg a))) (pulley_vnegf64x2 a)) 1626 1627;;;; Rules for `ineg` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 1628 1629(rule 0 (lower (has_type (fits_in_32 _) (ineg a))) (pulley_xneg32 (sext32 a))) 1630(rule 1 (lower (has_type $I64 (ineg a))) (pulley_xneg64 a)) 1631 1632;; vector negation 1633 1634(rule 1 (lower (has_type $I8X16 (ineg a))) (pulley_vneg8x16 a)) 1635(rule 1 (lower (has_type $I16X8 (ineg a))) (pulley_vneg16x8 a)) 1636(rule 1 (lower (has_type $I32X4 (ineg a))) (pulley_vneg32x4 a)) 1637(rule 1 (lower (has_type $I64X2 (ineg a))) (pulley_vneg64x2 a)) 1638 1639;;;; Rules for `fabs` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 1640 1641(rule (lower (has_type $F32 (fabs a))) (pulley_fabs32 a)) 1642(rule (lower (has_type $F64 (fabs a))) (pulley_fabs64 a)) 1643(rule (lower (has_type $F32X4 (fabs a))) (pulley_vabsf32x4 a)) 1644(rule (lower (has_type $F64X2 (fabs a))) (pulley_vabsf64x2 a)) 1645 1646;;;; Rules for `vconst` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 1647 1648(rule (lower (has_type (ty_vec128 _) (vconst (u128_from_constant a)))) (pulley_vconst128 a)) 1649 1650;;;; Rules for `bswap` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 1651 1652(rule (lower (has_type $I16 (bswap a))) 1653 (if-let (u6_from_u8 shift) (u64_try_into_u8 16)) 1654 (pulley_xshr32_u_u6 (pulley_bswap32 a) shift)) 1655(rule (lower (has_type $I32 (bswap a))) (pulley_bswap32 a)) 1656(rule (lower (has_type $I64 (bswap a))) (pulley_bswap64 a)) 1657 1658;;;; Rules for `iabs` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 1659 1660(rule 0 (lower (has_type (fits_in_32 _) (iabs a))) (pulley_xabs32 (sext32 a))) 1661(rule 1 (lower (has_type $I64 (iabs a))) (pulley_xabs64 a)) 1662(rule 1 (lower (has_type $I8X16 (iabs a))) (pulley_vabs8x16 a)) 1663(rule 1 (lower (has_type $I16X8 (iabs a))) (pulley_vabs16x8 a)) 1664(rule 1 (lower (has_type $I32X4 (iabs a))) (pulley_vabs32x4 a)) 1665(rule 1 (lower (has_type $I64X2 (iabs a))) (pulley_vabs64x2 a)) 1666 1667;;;; Rules for `splat` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 1668 1669(rule (lower (has_type $I8X16 (splat a))) (pulley_vsplatx8 a)) 1670(rule (lower (has_type $I16X8 (splat a))) (pulley_vsplatx16 a)) 1671(rule (lower (has_type $I32X4 (splat a))) (pulley_vsplatx32 a)) 1672(rule (lower (has_type $I64X2 (splat a))) (pulley_vsplatx64 a)) 1673(rule (lower (has_type $F32X4 (splat a))) (pulley_vsplatf32 a)) 1674(rule (lower (has_type $F64X2 (splat a))) (pulley_vsplatf64 a)) 1675 1676;;;; Rules for `vhigh_bits` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 1677 1678(rule (lower (has_type (fits_in_32 _) (vhigh_bits a @ (value_type $I8X16)))) 1679 (pulley_vbitmask8x16 a)) 1680(rule (lower (has_type (fits_in_32 _) (vhigh_bits a @ (value_type $I16X8)))) 1681 (pulley_vbitmask16x8 a)) 1682(rule (lower (has_type (fits_in_32 _) (vhigh_bits a @ (value_type $I32X4)))) 1683 (pulley_vbitmask32x4 a)) 1684(rule (lower (has_type (fits_in_32 _) (vhigh_bits a @ (value_type $I64X2)))) 1685 (pulley_vbitmask64x2 a)) 1686 1687;;;; Rules for `vall_true`; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 1688 1689(rule (lower (vall_true a @ (value_type $I8X16))) (pulley_valltrue8x16 a)) 1690(rule (lower (vall_true a @ (value_type $I16X8))) (pulley_valltrue16x8 a)) 1691(rule (lower (vall_true a @ (value_type $I32X4))) (pulley_valltrue32x4 a)) 1692(rule (lower (vall_true a @ (value_type $I64X2))) (pulley_valltrue64x2 a)) 1693(rule (lower (vall_true a @ (value_type $F32X4))) (pulley_valltrue32x4 a)) 1694(rule (lower (vall_true a @ (value_type $F64X2))) (pulley_valltrue64x2 a)) 1695 1696;;;; Rules for `vany_true`; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 1697 1698(rule (lower (vany_true a @ (value_type $I8X16))) (pulley_vanytrue8x16 a)) 1699(rule (lower (vany_true a @ (value_type $I16X8))) (pulley_vanytrue16x8 a)) 1700(rule (lower (vany_true a @ (value_type $I32X4))) (pulley_vanytrue32x4 a)) 1701(rule (lower (vany_true a @ (value_type $I64X2))) (pulley_vanytrue64x2 a)) 1702(rule (lower (vany_true a @ (value_type $F32X4))) (pulley_vanytrue32x4 a)) 1703(rule (lower (vany_true a @ (value_type $F64X2))) (pulley_vanytrue64x2 a)) 1704 1705;;;; Rules for `swiden_low` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 1706 1707(rule (lower (swiden_low a @ (value_type $I8X16))) (pulley_vwidenlow8x16_s a)) 1708(rule (lower (swiden_low a @ (value_type $I16X8))) (pulley_vwidenlow16x8_s a)) 1709(rule (lower (swiden_low a @ (value_type $I32X4))) (pulley_vwidenlow32x4_s a)) 1710 1711;;;; Rules for `swiden_high` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 1712 1713(rule (lower (swiden_high a @ (value_type $I8X16))) (pulley_vwidenhigh8x16_s a)) 1714(rule (lower (swiden_high a @ (value_type $I16X8))) (pulley_vwidenhigh16x8_s a)) 1715(rule (lower (swiden_high a @ (value_type $I32X4))) (pulley_vwidenhigh32x4_s a)) 1716 1717;;;; Rules for `uwiden_low` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 1718 1719(rule (lower (uwiden_low a @ (value_type $I8X16))) (pulley_vwidenlow8x16_u a)) 1720(rule (lower (uwiden_low a @ (value_type $I16X8))) (pulley_vwidenlow16x8_u a)) 1721(rule (lower (uwiden_low a @ (value_type $I32X4))) (pulley_vwidenlow32x4_u a)) 1722 1723;;;; Rules for `uwiden_high` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 1724 1725(rule (lower (uwiden_high a @ (value_type $I8X16))) (pulley_vwidenhigh8x16_u a)) 1726(rule (lower (uwiden_high a @ (value_type $I16X8))) (pulley_vwidenhigh16x8_u a)) 1727(rule (lower (uwiden_high a @ (value_type $I32X4))) (pulley_vwidenhigh32x4_u a)) 1728 1729;;;; Rules for `snarrow` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 1730 1731(rule (lower (snarrow a @ (value_type $I16X8) b)) (pulley_vnarrow16x8_s a b)) 1732(rule (lower (snarrow a @ (value_type $I32X4) b)) (pulley_vnarrow32x4_s a b)) 1733(rule (lower (snarrow a @ (value_type $I64X2) b)) (pulley_vnarrow64x2_s a b)) 1734 1735;;;; Rules for `unarrow` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 1736 1737(rule (lower (unarrow a @ (value_type $I16X8) b)) (pulley_vnarrow16x8_u a b)) 1738(rule (lower (unarrow a @ (value_type $I32X4) b)) (pulley_vnarrow32x4_u a b)) 1739 1740;;;; Rules for `uunarrow` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 1741 1742(rule (lower (uunarrow a @ (value_type $I64X2) b)) (pulley_vunarrow64x2_u a b)) 1743 1744;;;; Rules for `fvpromote_low` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 1745 1746(rule (lower (fvpromote_low a @ (value_type $F32X4))) (pulley_vfpromotelow a)) 1747 1748;;;; Rules for `fvdemote` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 1749 1750(rule (lower (fvdemote a @ (value_type $F64X2))) (pulley_vfdemote a)) 1751 1752;;;; Rules for `extractlane` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 1753 1754(rule (lower (extractlane a @ (value_type $I8X16) (u8_from_uimm8 lane))) 1755 (pulley_xextractv8x16 a lane)) 1756(rule (lower (extractlane a @ (value_type $I16X8) (u8_from_uimm8 lane))) 1757 (pulley_xextractv16x8 a lane)) 1758(rule (lower (extractlane a @ (value_type $I32X4) (u8_from_uimm8 lane))) 1759 (pulley_xextractv32x4 a lane)) 1760(rule (lower (extractlane a @ (value_type $I64X2) (u8_from_uimm8 lane))) 1761 (pulley_xextractv64x2 a lane)) 1762(rule (lower (extractlane a @ (value_type $F32X4) (u8_from_uimm8 lane))) 1763 (pulley_fextractv32x4 a lane)) 1764(rule (lower (extractlane a @ (value_type $F64X2) (u8_from_uimm8 lane))) 1765 (pulley_fextractv64x2 a lane)) 1766 1767;;;; Rules for `insertlane` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 1768 1769(rule (lower (insertlane a @ (value_type $I8X16) b (u8_from_uimm8 lane))) 1770 (pulley_vinsertx8 a b lane)) 1771(rule (lower (insertlane a @ (value_type $I16X8) b (u8_from_uimm8 lane))) 1772 (pulley_vinsertx16 a b lane)) 1773(rule (lower (insertlane a @ (value_type $I32X4) b (u8_from_uimm8 lane))) 1774 (pulley_vinsertx32 a b lane)) 1775(rule (lower (insertlane a @ (value_type $I64X2) b (u8_from_uimm8 lane))) 1776 (pulley_vinsertx64 a b lane)) 1777(rule (lower (insertlane a @ (value_type $F32X4) b (u8_from_uimm8 lane))) 1778 (pulley_vinsertf32 a b lane)) 1779(rule (lower (insertlane a @ (value_type $F64X2) b (u8_from_uimm8 lane))) 1780 (pulley_vinsertf64 a b lane)) 1781 1782;;;; Rules for `scalar_to_vector` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 1783 1784;; Note that this doesn't use special pulley instructions at this time and 1785;; generates a bytecode-wise relatively inefficient lowering. Should be 1786;; relatively easy to optimize if necessary in the future. 1787 1788(rule (lower (scalar_to_vector a @ (value_type $I8))) 1789 (pulley_vinsertx8 (pulley_vconst128 0) a 0)) 1790(rule (lower (scalar_to_vector a @ (value_type $I16))) 1791 (pulley_vinsertx16 (pulley_vconst128 0) a 0)) 1792(rule (lower (scalar_to_vector a @ (value_type $I32))) 1793 (pulley_vinsertx32 (pulley_vconst128 0) a 0)) 1794(rule (lower (scalar_to_vector a @ (value_type $I64))) 1795 (pulley_vinsertx64 (pulley_vconst128 0) a 0)) 1796(rule (lower (scalar_to_vector a @ (value_type $F32))) 1797 (pulley_vinsertf32 (pulley_vconst128 0) a 0)) 1798(rule (lower (scalar_to_vector a @ (value_type $F64))) 1799 (pulley_vinsertf64 (pulley_vconst128 0) a 0)) 1800 1801;;;; Rules for `shuffle` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 1802 1803(rule (lower (has_type $I8X16 (shuffle a b (u128_from_immediate mask)))) 1804 (pulley_vshuffle a b mask)) 1805 1806;;;; Rules for `swizzle` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 1807 1808(rule 1 (lower (has_type $I8X16 (swizzle a b))) (pulley_vswizzlei8x16 a b)) 1809 1810;;;; Rules for `fma` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 1811 1812(rule (lower (has_type $F32X4 (fma a b c))) (pulley_vfma32x4 a b c)) 1813(rule (lower (has_type $F64X2 (fma a b c))) (pulley_vfma64x2 a b c)) 1814