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 f76fcb26ecca08..c72f149efd06ba 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 c88c768acd3eb6..7f5a072180b8c0 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 898c5df5cb3b2c..8d4bf1211046d2 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 3faa629d34bcfd..6e005c5f3612fc 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 1250a608ebc992..31f55456c125d5 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 0be066d6c3e18c..e4d5d42785a73a 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 d30f058f780c7d..1a160fa14054a9 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 6436b632c08876..e33c0b5ef827a7 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 29bfe1cd958253..7800f1ef6b6989 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):