Translate WASM shl to CLIF ishl

Note how, according to the spec (see https://github.com/WebAssembly/simd/blob/master/proposals/simd/SIMD.md#left-shift-by-scalar), the shift count is computed modulo the lane width. E.g., a shift count of 17 on an i16x8 should not result in all zeroes as it does with Cranelift's `ishl` and x86's `PSSLW`--it should shift once to the left.
This commit is contained in:
Andrew Brown
2019-10-02 13:55:44 -07:00
parent 6460fe705f
commit 808885ce56

View File

@@ -1111,6 +1111,15 @@ pub fn translate_operator<FE: FuncEnvironment + ?Sized>(
let (a, b) = state.pop2(); let (a, b) = state.pop2();
state.push1(builder.ins().bxor(a, b)); state.push1(builder.ins().bxor(a, b));
} }
Operator::I16x8Shl | Operator::I32x4Shl | Operator::I64x2Shl => {
let (a, b) = state.pop2();
let bitcast_a = optionally_bitcast_vector(a, type_of(op), builder);
let bitwidth = i64::from(builder.func.dfg.value_type(a).bits());
// The spec expects to shift with `b mod lanewidth`; so, e.g., for 16 bit lane-width
// we do `b AND 15`; this means fewer instructions than `iconst + urem`.
let b_mod_bitwidth = builder.ins().band_imm(b, bitwidth - 1);
state.push1(builder.ins().ishl(bitcast_a, b_mod_bitwidth))
}
Operator::I8x16Eq Operator::I8x16Eq
| Operator::I8x16Ne | Operator::I8x16Ne
| Operator::I8x16LtS | Operator::I8x16LtS
@@ -1162,17 +1171,14 @@ pub fn translate_operator<FE: FuncEnvironment + ?Sized>(
| Operator::I8x16Mul | Operator::I8x16Mul
| Operator::I16x8AnyTrue | Operator::I16x8AnyTrue
| Operator::I16x8AllTrue | Operator::I16x8AllTrue
| Operator::I16x8Shl
| Operator::I16x8ShrS | Operator::I16x8ShrS
| Operator::I16x8ShrU | Operator::I16x8ShrU
| Operator::I32x4AnyTrue | Operator::I32x4AnyTrue
| Operator::I32x4AllTrue | Operator::I32x4AllTrue
| Operator::I32x4Shl
| Operator::I32x4ShrS | Operator::I32x4ShrS
| Operator::I32x4ShrU | Operator::I32x4ShrU
| Operator::I64x2AnyTrue | Operator::I64x2AnyTrue
| Operator::I64x2AllTrue | Operator::I64x2AllTrue
| Operator::I64x2Shl
| Operator::I64x2ShrS | Operator::I64x2ShrS
| Operator::I64x2ShrU | Operator::I64x2ShrU
| Operator::F32x4Abs | Operator::F32x4Abs