From dec2b41f88084d2f3c762cc64d377adc2798ea91 Mon Sep 17 00:00:00 2001 From: Lars T Hansen Date: Wed, 14 Oct 2020 09:50:46 +0000 Subject: [PATCH] Bug 1669938 - Promote fp rounding wasm SIMD instructions to accepted status. r=jseward Background: https://github.com/WebAssembly/simd/pull/232 For all the rounding SIMD instructions: - remove the internal 'Experimental' opcode suffix in the C++ code - remove the guard on experimental Wasm instructions in all the C++ decoders - move the test cases from simd/experimental.js to simd/ad-hack.js I have checked that current V8 and wasm-tools use the same opcode mappings. V8 in turn guarantees the correct mapping for LLVM and binaryen. Drive-by bug fix: the test predicate for f64 square root was wrong, it would round its argument to float. This did not matter for the test inputs we had but started to matter when I added more difficult inputs for testing rounding. Differential Revision: https://phabricator.services.mozilla.com/D92926 --- js/src/jit-test/tests/wasm/simd/ad-hack.js | 21 ++++++++- .../jit-test/tests/wasm/simd/experimental.js | 44 ------------------- js/src/jit/MacroAssembler.h | 3 +- .../x86-shared/CodeGenerator-x86-shared.cpp | 16 +++---- js/src/wasm/WasmBaselineCompile.cpp | 24 ++++------ js/src/wasm/WasmConstants.h | 16 +++---- js/src/wasm/WasmIonCompile.cpp | 18 ++++---- js/src/wasm/WasmOpIter.cpp | 16 +++---- js/src/wasm/WasmValidate.cpp | 19 ++++---- 9 files changed, 68 insertions(+), 109 deletions(-) diff --git a/js/src/jit-test/tests/wasm/simd/ad-hack.js b/js/src/jit-test/tests/wasm/simd/ad-hack.js index f76fcb26ecca0..c72f149efd06b 100644 --- a/js/src/jit-test/tests/wasm/simd/ad-hack.js +++ b/js/src/jit-test/tests/wasm/simd/ad-hack.js @@ -271,6 +271,7 @@ BigInt64Array.rectify = (x) => BigInt(x); Float32Array.inputs = [[1, -1, 1e10, -1e10], [-1, -2, -1e10, 1e10], + [5.1, -1.1, -4.3, -0], ...permute([1, -10, NaN, Infinity])]; Float32Array.rectify = (x) => Math.fround(x); @@ -812,8 +813,16 @@ function iabs(bits) { return (a) => zero_extend(a < 0 ? -a : a, bits) } function fneg(a) { return -a } function fabs(a) { return Math.abs(a) } function fsqrt(a) { return Math.fround(Math.sqrt(Math.fround(a))) } -function sqrt(a) { return Math.sqrt(Math.fround(a)) } +function dsqrt(a) { return Math.sqrt(a) } function bitnot(a) { return (~a) & 255 } +function ffloor(x) { return Math.fround(Math.floor(x)) } +function fceil(x) { return Math.fround(Math.ceil(x)) } +function ftrunc(x) { return Math.fround(Math.sign(x)*Math.floor(Math.abs(x))) } +function fnearest(x) { return Math.fround(Math.round(x)) } +function dfloor(x) { return Math.floor(x) } +function dceil(x) { return Math.ceil(x) } +function dtrunc(x) { return Math.sign(x)*Math.floor(Math.abs(x)) } +function dnearest(x) { return Math.round(x) } for ( let [op, memtype, rop, resultmemtype] of [['i8x16.neg', Int8Array, ineg(8)], @@ -828,7 +837,15 @@ for ( let [op, memtype, rop, resultmemtype] of ['f32x4.abs', Float32Array, fabs], ['f64x2.abs', Float64Array, fabs], ['f32x4.sqrt', Float32Array, fsqrt], - ['f64x2.sqrt', Float64Array, sqrt], + ['f64x2.sqrt', Float64Array, dsqrt], + ['f32x4.ceil', Float32Array, fceil], + ['f32x4.floor', Float32Array, ffloor], + ['f32x4.trunc', Float32Array, ftrunc], + ['f32x4.nearest', Float32Array, fnearest], + ['f64x2.ceil', Float64Array, dceil], + ['f64x2.floor', Float64Array, dfloor], + ['f64x2.trunc', Float64Array, dtrunc], + ['f64x2.nearest', Float64Array, dnearest], ['v128.not', Uint8Array, bitnot], ]) { diff --git a/js/src/jit-test/tests/wasm/simd/experimental.js b/js/src/jit-test/tests/wasm/simd/experimental.js index c88c768acd3eb..7f5a072180b8c 100644 --- a/js/src/jit-test/tests/wasm/simd/experimental.js +++ b/js/src/jit-test/tests/wasm/simd/experimental.js @@ -53,16 +53,6 @@ function iota(len) { function pmin(x, y) { return y < x ? y : x } function pmax(x, y) { return x < y ? y : x } -function ffloor(x) { return Math.fround(Math.floor(x)) } -function fceil(x) { return Math.fround(Math.ceil(x)) } -function ftrunc(x) { return Math.fround(Math.sign(x)*Math.floor(Math.abs(x))) } -function fnearest(x) { return Math.fround(Math.round(x)) } - -function dfloor(x) { return Math.floor(x) } -function dceil(x) { return Math.ceil(x) } -function dtrunc(x) { return Math.sign(x)*Math.floor(Math.abs(x)) } -function dnearest(x) { return Math.round(x) } - const v2vSig = {args:[], ret:VoidCode}; function V128Load(addr) { @@ -138,40 +128,6 @@ ins.exports.run(); var result = get(mem32, 0, 4); assertSame(result, ans); -// Rounding, https://github.com/WebAssembly/simd/pull/232 - -var fxs = [5.1, -1.1, -4.3, 0]; -var dxs = [5.1, -1.1]; - -for ( let [opcode, xs, operator] of [[F32x4CeilCode, fxs, fceil], - [F32x4FloorCode, fxs, ffloor], - [F32x4TruncCode, fxs, ftrunc], - [F32x4NearestCode, fxs, fnearest], - [F64x2CeilCode, dxs, dceil], - [F64x2FloorCode, dxs, dfloor], - [F64x2TruncCode, dxs, dtrunc], - [F64x2NearestCode, dxs, dnearest]] ) { - var k = xs.length; - var ans = xs.map(operator); - - var ins = wasmEval(moduleWithSections([ - sigSection([v2vSig]), - declSection([0]), - memorySection(1), - exportSection([{funcIndex: 0, name: "run"}, - {memIndex: 0, name: "mem"}]), - bodySection([ - funcBody({locals:[], - body: [...V128StoreExpr(0, [...V128Load(16), - SimdPrefix, varU32(opcode)])]})])])); - - var mem = new (k == 4 ? Float32Array : Float64Array)(ins.exports.mem.buffer); - set(mem, k, xs); - ins.exports.run(); - var result = get(mem, 0, k); - assertSame(result, ans); -} - // Zero-extending SIMD load, https://github.com/WebAssembly/simd/pull/237 for ( let [opcode, k, log2align, cons, cast] of [[V128Load32ZeroCode, 4, 2, Int32Array, Number], diff --git a/js/src/jit/MacroAssembler.h b/js/src/jit/MacroAssembler.h index 898c5df5cb3b2..8d4bf1211046d 100644 --- a/js/src/jit/MacroAssembler.h +++ b/js/src/jit/MacroAssembler.h @@ -2674,8 +2674,7 @@ class MacroAssembler : public MacroAssemblerSpecific { inline void widenDotInt16x8(FloatRegister rhs, FloatRegister lhsDest) DEFINED_ON(x86_shared, arm64); - // Floating point rounding (experimental as of August, 2020) - // https://github.com/WebAssembly/simd/pull/232 + // Floating point rounding inline void ceilFloat32x4(FloatRegister src, FloatRegister dest) DEFINED_ON(x86_shared, arm64); diff --git a/js/src/jit/x86-shared/CodeGenerator-x86-shared.cpp b/js/src/jit/x86-shared/CodeGenerator-x86-shared.cpp index 3faa629d34bcf..6e005c5f3612f 100644 --- a/js/src/jit/x86-shared/CodeGenerator-x86-shared.cpp +++ b/js/src/jit/x86-shared/CodeGenerator-x86-shared.cpp @@ -3136,28 +3136,28 @@ void CodeGenerator::visitWasmUnarySimd128(LWasmUnarySimd128* ins) { case wasm::SimdOp::I32x4Abs: masm.absInt32x4(src, dest); break; - case wasm::SimdOp::F32x4CeilExperimental: + case wasm::SimdOp::F32x4Ceil: masm.ceilFloat32x4(src, dest); break; - case wasm::SimdOp::F32x4FloorExperimental: + case wasm::SimdOp::F32x4Floor: masm.floorFloat32x4(src, dest); break; - case wasm::SimdOp::F32x4TruncExperimental: + case wasm::SimdOp::F32x4Trunc: masm.truncFloat32x4(src, dest); break; - case wasm::SimdOp::F32x4NearestExperimental: + case wasm::SimdOp::F32x4Nearest: masm.nearestFloat32x4(src, dest); break; - case wasm::SimdOp::F64x2CeilExperimental: + case wasm::SimdOp::F64x2Ceil: masm.ceilFloat64x2(src, dest); break; - case wasm::SimdOp::F64x2FloorExperimental: + case wasm::SimdOp::F64x2Floor: masm.floorFloat64x2(src, dest); break; - case wasm::SimdOp::F64x2TruncExperimental: + case wasm::SimdOp::F64x2Trunc: masm.truncFloat64x2(src, dest); break; - case wasm::SimdOp::F64x2NearestExperimental: + case wasm::SimdOp::F64x2Nearest: masm.nearestFloat64x2(src, dest); break; default: diff --git a/js/src/wasm/WasmBaselineCompile.cpp b/js/src/wasm/WasmBaselineCompile.cpp index 1250a608ebc99..31f55456c125d 100644 --- a/js/src/wasm/WasmBaselineCompile.cpp +++ b/js/src/wasm/WasmBaselineCompile.cpp @@ -15037,29 +15037,21 @@ bool BaseCompiler::emitBody() { CHECK_NEXT(dispatchVectorUnary(AbsI16x8)); case uint32_t(SimdOp::I32x4Abs): CHECK_NEXT(dispatchVectorUnary(AbsI32x4)); - case uint32_t(SimdOp::F32x4CeilExperimental): - CHECK_SIMD_EXPERIMENTAL(); + case uint32_t(SimdOp::F32x4Ceil): CHECK_NEXT(dispatchVectorUnary(CeilF32x4)); - case uint32_t(SimdOp::F32x4FloorExperimental): - CHECK_SIMD_EXPERIMENTAL(); + case uint32_t(SimdOp::F32x4Floor): CHECK_NEXT(dispatchVectorUnary(FloorF32x4)); - case uint32_t(SimdOp::F32x4TruncExperimental): - CHECK_SIMD_EXPERIMENTAL(); + case uint32_t(SimdOp::F32x4Trunc): CHECK_NEXT(dispatchVectorUnary(TruncF32x4)); - case uint32_t(SimdOp::F32x4NearestExperimental): - CHECK_SIMD_EXPERIMENTAL(); + case uint32_t(SimdOp::F32x4Nearest): CHECK_NEXT(dispatchVectorUnary(NearestF32x4)); - case uint32_t(SimdOp::F64x2CeilExperimental): - CHECK_SIMD_EXPERIMENTAL(); + case uint32_t(SimdOp::F64x2Ceil): CHECK_NEXT(dispatchVectorUnary(CeilF64x2)); - case uint32_t(SimdOp::F64x2FloorExperimental): - CHECK_SIMD_EXPERIMENTAL(); + case uint32_t(SimdOp::F64x2Floor): CHECK_NEXT(dispatchVectorUnary(FloorF64x2)); - case uint32_t(SimdOp::F64x2TruncExperimental): - CHECK_SIMD_EXPERIMENTAL(); + case uint32_t(SimdOp::F64x2Trunc): CHECK_NEXT(dispatchVectorUnary(TruncF64x2)); - case uint32_t(SimdOp::F64x2NearestExperimental): - CHECK_SIMD_EXPERIMENTAL(); + case uint32_t(SimdOp::F64x2Nearest): CHECK_NEXT(dispatchVectorUnary(NearestF64x2)); case uint32_t(SimdOp::I8x16Shl): CHECK_NEXT(dispatchVectorVariableShift(ShiftLeftI8x16)); diff --git a/js/src/wasm/WasmConstants.h b/js/src/wasm/WasmConstants.h index 0be066d6c3e18..e4d5d42785a73 100644 --- a/js/src/wasm/WasmConstants.h +++ b/js/src/wasm/WasmConstants.h @@ -642,14 +642,14 @@ enum class SimdOp { I64x2Mul = 0xd5, // MinS = 0xd6 // MinU = 0xd7 - F32x4CeilExperimental = 0xd8, - F32x4FloorExperimental = 0xd9, - F32x4TruncExperimental = 0xda, - F32x4NearestExperimental = 0xdb, - F64x2CeilExperimental = 0xdc, - F64x2FloorExperimental = 0xdd, - F64x2TruncExperimental = 0xde, - F64x2NearestExperimental = 0xdf, + F32x4Ceil = 0xd8, + F32x4Floor = 0xd9, + F32x4Trunc = 0xda, + F32x4Nearest = 0xdb, + F64x2Ceil = 0xdc, + F64x2Floor = 0xdd, + F64x2Trunc = 0xde, + F64x2Nearest = 0xdf, F32x4Abs = 0xe0, F32x4Neg = 0xe1, // Round = 0xe2 diff --git a/js/src/wasm/WasmIonCompile.cpp b/js/src/wasm/WasmIonCompile.cpp index d30f058f780c7..1a160fa14054a 100644 --- a/js/src/wasm/WasmIonCompile.cpp +++ b/js/src/wasm/WasmIonCompile.cpp @@ -4950,16 +4950,14 @@ static bool EmitBodyExprs(FunctionCompiler& f) { case uint32_t(SimdOp::I8x16Abs): case uint32_t(SimdOp::I16x8Abs): case uint32_t(SimdOp::I32x4Abs): - CHECK(EmitUnarySimd128(f, SimdOp(op.b1))); - case uint32_t(SimdOp::F32x4CeilExperimental): - case uint32_t(SimdOp::F32x4FloorExperimental): - case uint32_t(SimdOp::F32x4TruncExperimental): - case uint32_t(SimdOp::F32x4NearestExperimental): - case uint32_t(SimdOp::F64x2CeilExperimental): - case uint32_t(SimdOp::F64x2FloorExperimental): - case uint32_t(SimdOp::F64x2TruncExperimental): - case uint32_t(SimdOp::F64x2NearestExperimental): - CHECK_SIMD_EXPERIMENTAL(); + case uint32_t(SimdOp::F32x4Ceil): + case uint32_t(SimdOp::F32x4Floor): + case uint32_t(SimdOp::F32x4Trunc): + case uint32_t(SimdOp::F32x4Nearest): + case uint32_t(SimdOp::F64x2Ceil): + case uint32_t(SimdOp::F64x2Floor): + case uint32_t(SimdOp::F64x2Trunc): + case uint32_t(SimdOp::F64x2Nearest): CHECK(EmitUnarySimd128(f, SimdOp(op.b1))); case uint32_t(SimdOp::I8x16AnyTrue): case uint32_t(SimdOp::I16x8AnyTrue): diff --git a/js/src/wasm/WasmOpIter.cpp b/js/src/wasm/WasmOpIter.cpp index 6436b632c0887..e33c0b5ef827a 100644 --- a/js/src/wasm/WasmOpIter.cpp +++ b/js/src/wasm/WasmOpIter.cpp @@ -462,14 +462,14 @@ OpKind wasm::Classify(OpBytes op) { case SimdOp::I8x16Abs: case SimdOp::I16x8Abs: case SimdOp::I32x4Abs: - case SimdOp::F32x4CeilExperimental: - case SimdOp::F32x4FloorExperimental: - case SimdOp::F32x4TruncExperimental: - case SimdOp::F32x4NearestExperimental: - case SimdOp::F64x2CeilExperimental: - case SimdOp::F64x2FloorExperimental: - case SimdOp::F64x2TruncExperimental: - case SimdOp::F64x2NearestExperimental: + case SimdOp::F32x4Ceil: + case SimdOp::F32x4Floor: + case SimdOp::F32x4Trunc: + case SimdOp::F32x4Nearest: + case SimdOp::F64x2Ceil: + case SimdOp::F64x2Floor: + case SimdOp::F64x2Trunc: + case SimdOp::F64x2Nearest: WASM_SIMD_OP(OpKind::Unary); case SimdOp::I8x16Shl: case SimdOp::I8x16ShrS: diff --git a/js/src/wasm/WasmValidate.cpp b/js/src/wasm/WasmValidate.cpp index 29bfe1cd95825..7800f1ef6b698 100644 --- a/js/src/wasm/WasmValidate.cpp +++ b/js/src/wasm/WasmValidate.cpp @@ -1088,17 +1088,14 @@ static bool DecodeFunctionBodyExprs(const ModuleEnvironment& env, case uint32_t(SimdOp::I8x16Abs): case uint32_t(SimdOp::I16x8Abs): case uint32_t(SimdOp::I32x4Abs): - CHECK(iter.readUnary(ValType::V128, ¬hing)); - - case uint32_t(SimdOp::F32x4CeilExperimental): - case uint32_t(SimdOp::F32x4FloorExperimental): - case uint32_t(SimdOp::F32x4TruncExperimental): - case uint32_t(SimdOp::F32x4NearestExperimental): - case uint32_t(SimdOp::F64x2CeilExperimental): - case uint32_t(SimdOp::F64x2FloorExperimental): - case uint32_t(SimdOp::F64x2TruncExperimental): - case uint32_t(SimdOp::F64x2NearestExperimental): - CHECK_SIMD_EXPERIMENTAL(); + case uint32_t(SimdOp::F32x4Ceil): + case uint32_t(SimdOp::F32x4Floor): + case uint32_t(SimdOp::F32x4Trunc): + case uint32_t(SimdOp::F32x4Nearest): + case uint32_t(SimdOp::F64x2Ceil): + case uint32_t(SimdOp::F64x2Floor): + case uint32_t(SimdOp::F64x2Trunc): + case uint32_t(SimdOp::F64x2Nearest): CHECK(iter.readUnary(ValType::V128, ¬hing)); case uint32_t(SimdOp::I8x16Shl):