Refactor to avoid too strict assertion. Fix for 3160 and 3161.

Assertion was intended for SIMD lowering of F64x2ConvertLowI32x4U
This commit is contained in:
Johnnie Birch
2021-08-18 14:25:31 -07:00
parent 2776074dfc
commit e3aae9e498
2 changed files with 106 additions and 53 deletions

View File

@@ -4528,8 +4528,9 @@ fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
Opcode::FcvtFromUint => { Opcode::FcvtFromUint => {
let dst = get_output_reg(ctx, outputs[0]).only_reg().unwrap(); let dst = get_output_reg(ctx, outputs[0]).only_reg().unwrap();
let ty = ty.unwrap(); let ty = ty.unwrap();
let input_ty = ctx.input_ty(insn, 0); let input_ty = ctx.input_ty(insn, 0);
let output_ty = ctx.output_ty(insn, 0);
if !ty.is_vector() { if !ty.is_vector() {
match input_ty { match input_ty {
types::I8 | types::I16 | types::I32 => { types::I8 | types::I16 | types::I32 => {
@@ -4572,7 +4573,8 @@ fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
} }
_ => panic!("unexpected input type for FcvtFromUint: {:?}", input_ty), _ => panic!("unexpected input type for FcvtFromUint: {:?}", input_ty),
}; };
} else if let Some(uwiden) = matches_input(ctx, inputs[0], Opcode::UwidenLow) { } else if output_ty == types::F64X2 {
if let Some(uwiden) = matches_input(ctx, inputs[0], Opcode::UwidenLow) {
let uwiden_input = InsnInput { let uwiden_input = InsnInput {
insn: uwiden, insn: uwiden,
input: 0, input: 0,
@@ -4580,11 +4582,10 @@ fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
let src = put_input_in_reg(ctx, uwiden_input); let src = put_input_in_reg(ctx, uwiden_input);
let dst = get_output_reg(ctx, outputs[0]).only_reg().unwrap(); let dst = get_output_reg(ctx, outputs[0]).only_reg().unwrap();
let input_ty = ctx.input_ty(uwiden, 0); let input_ty = ctx.input_ty(uwiden, 0);
let output_ty = ctx.output_ty(insn, 0);
// Matches_input further obfuscates which Wasm instruction this is ultimately // Matches_input further obfuscates which Wasm instruction this is ultimately
// lowering. Check here that the types are as expected for F64x2ConvertLowI32x4U. // lowering. Check here that the types are as expected for F64x2ConvertLowI32x4U.
debug_assert!(input_ty == types::I32X4 || output_ty == types::F64X2); debug_assert!(input_ty == types::I32X4);
// Algorithm uses unpcklps to help create a float that is equivalent // Algorithm uses unpcklps to help create a float that is equivalent
// 0x1.0p52 + double(src). 0x1.0p52 is unique because at this exponent // 0x1.0p52 + double(src). 0x1.0p52 is unique because at this exponent
@@ -4594,11 +4595,12 @@ fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
ctx.emit(Inst::gen_move(dst, src, types::I32X4)); ctx.emit(Inst::gen_move(dst, src, types::I32X4));
static UINT_MASK: [u8; 16] = [ static UINT_MASK: [u8; 16] = [
0x00, 0x00, 0x30, 0x43, 0x00, 0x00, 0x30, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x43, 0x00, 0x00, 0x30, 0x43, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
]; ];
let uint_mask_const = ctx.use_constant(VCodeConstantData::WellKnown(&UINT_MASK)); let uint_mask_const =
ctx.use_constant(VCodeConstantData::WellKnown(&UINT_MASK));
ctx.emit(Inst::xmm_load_const( ctx.emit(Inst::xmm_load_const(
uint_mask_const, uint_mask_const,
@@ -4614,8 +4616,8 @@ fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
)); ));
static UINT_MASK_HIGH: [u8; 16] = [ static UINT_MASK_HIGH: [u8; 16] = [
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x43, 0x00, 0x00, 0x00, 0x00,
0x00, 0x30, 0x43, 0x00, 0x00, 0x30, 0x43,
]; ];
let uint_mask_high_const = let uint_mask_high_const =
@@ -4633,6 +4635,9 @@ fn lower_insn_to_regs<C: LowerCtx<I = Inst>>(
RegMem::from(uint_mask_high), RegMem::from(uint_mask_high),
dst, dst,
)); ));
} else {
panic!("Unsupported FcvtFromUint conversion types: {}", ty);
}
} else { } else {
assert_eq!(ctx.input_ty(insn, 0), types::I32X4); assert_eq!(ctx.input_ty(insn, 0), types::I32X4);
let src = put_input_in_reg(ctx, inputs[0]); let src = put_input_in_reg(ctx, inputs[0]);

View File

@@ -0,0 +1,48 @@
;; Tests inspired by https://github.com/bytecodealliance/wasmtime/issues/3161
;; which found issue in lowering Opcode::FcvtFromUint where valid instruction
;; patterns were rejected
(module
(func (export "i16x8.extend_low_i8x16_s") (param v128) (result v128)
local.get 0
i16x8.extend_low_i8x16_s
f32x4.convert_i32x4_u)
(func (export "i16x8.extend_low_i8x16_u") (param v128) (result v128)
local.get 0
i16x8.extend_low_i8x16_u
f32x4.convert_i32x4_u)
(func (export "i32x4.extend_low_i16x8_s") (param v128) (result v128)
local.get 0
i32x4.extend_low_i16x8_s
f32x4.convert_i32x4_u)
(func (export "i32x4.extend_low_i16x8_u") (param v128) (result v128)
local.get 0
i32x4.extend_low_i16x8_u
f32x4.convert_i32x4_u)
(func (export "i64x2.extend_low_i32x4_s") (param v128) (result v128)
local.get 0
i64x2.extend_low_i32x4_s
f32x4.convert_i32x4_u)
(func (export "i64x2.extend_low_i32x4_u") (param v128) (result v128)
local.get 0
i64x2.extend_low_i32x4_u
f32x4.convert_i32x4_u)
)
(assert_return (invoke "i16x8.extend_low_i8x16_s" (v128.const i32x4 0x00000000 0x00000000 0x00000000 0x00000000))
(v128.const f32x4 0 0 0 0))
(assert_return (invoke "i16x8.extend_low_i8x16_u" (v128.const i32x4 0x00000000 0x00000000 0x00000000 0x00000000))
(v128.const f32x4 0 0 0 0))
(assert_return (invoke "i32x4.extend_low_i16x8_s" (v128.const i32x4 0x00000000 0x00000000 0x00000000 0x00000000))
(v128.const f32x4 0 0 0 0))
(assert_return (invoke "i32x4.extend_low_i16x8_u" (v128.const i32x4 0x00000000 0x00000000 0x00000000 0x00000000))
(v128.const f32x4 0 0 0 0))
(assert_return (invoke "i64x2.extend_low_i32x4_s" (v128.const i32x4 0x00000000 0x00000000 0x00000000 0x00000000))
(v128.const f32x4 0 0 0 0))
(assert_return (invoke "i64x2.extend_low_i32x4_u" (v128.const i32x4 0x00000000 0x00000000 0x00000000 0x00000000))
(v128.const f32x4 0 0 0 0))