diff options
Diffstat (limited to 'src/wasm')
-rw-r--r-- | src/wasm/literal.cpp | 62 | ||||
-rw-r--r-- | src/wasm/wasm-binary.cpp | 68 | ||||
-rw-r--r-- | src/wasm/wasm-stack.cpp | 61 | ||||
-rw-r--r-- | src/wasm/wasm-validator.cpp | 11 | ||||
-rw-r--r-- | src/wasm/wasm.cpp | 4 |
5 files changed, 205 insertions, 1 deletions
diff --git a/src/wasm/literal.cpp b/src/wasm/literal.cpp index 4753e5ca1..e761206bc 100644 --- a/src/wasm/literal.cpp +++ b/src/wasm/literal.cpp @@ -1610,6 +1610,32 @@ Literal Literal::copysign(const Literal& other) const { } } +Literal Literal::fma(const Literal& left, const Literal& right) const { + switch (type.getBasic()) { + case Type::f32: + return Literal(::fmaf(left.getf32(), right.getf32(), getf32())); + break; + case Type::f64: + return Literal(::fma(left.getf64(), right.getf64(), getf64())); + break; + default: + WASM_UNREACHABLE("unexpected type"); + } +} + +Literal Literal::fms(const Literal& left, const Literal& right) const { + switch (type.getBasic()) { + case Type::f32: + return Literal(::fmaf(-left.getf32(), right.getf32(), getf32())); + break; + case Type::f64: + return Literal(::fma(-left.getf64(), right.getf64(), getf64())); + break; + default: + WASM_UNREACHABLE("unexpected type"); + } +} + template<typename LaneT, int Lanes> static LaneArray<Lanes> getLanes(const Literal& val) { assert(val.type == Type::v128); @@ -2548,6 +2574,42 @@ Literal Literal::swizzleI8x16(const Literal& other) const { return Literal(result); } +namespace { +template<int Lanes, + LaneArray<Lanes> (Literal::*IntoLanes)() const, + Literal (Literal::*TernaryOp)(const Literal&, const Literal&) const> +static Literal ternary(const Literal& a, const Literal& b, const Literal& c) { + LaneArray<Lanes> x = (a.*IntoLanes)(); + LaneArray<Lanes> y = (b.*IntoLanes)(); + LaneArray<Lanes> z = (c.*IntoLanes)(); + LaneArray<Lanes> r; + for (size_t i = 0; i < Lanes; ++i) { + r[i] = (x[i].*TernaryOp)(y[i], z[i]); + } + return Literal(r); +} +} // namespace + +Literal Literal::relaxedFmaF32x4(const Literal& left, + const Literal& right) const { + return ternary<4, &Literal::getLanesF32x4, &Literal::fma>(*this, left, right); +} + +Literal Literal::relaxedFmsF32x4(const Literal& left, + const Literal& right) const { + return ternary<4, &Literal::getLanesF32x4, &Literal::fms>(*this, left, right); +} + +Literal Literal::relaxedFmaF64x2(const Literal& left, + const Literal& right) const { + return ternary<2, &Literal::getLanesF64x2, &Literal::fma>(*this, left, right); +} + +Literal Literal::relaxedFmsF64x2(const Literal& left, + const Literal& right) const { + return ternary<2, &Literal::getLanesF64x2, &Literal::fms>(*this, left, right); +} + bool Literal::isSubRtt(const Literal& other) const { assert(type.isRtt() && other.type.isRtt()); // For this literal to be a sub-rtt of the other rtt, the supers must be a diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp index 6ce2c7979..0ccb9d6db 100644 --- a/src/wasm/wasm-binary.cpp +++ b/src/wasm/wasm-binary.cpp @@ -5524,6 +5524,26 @@ bool WasmBinaryBuilder::maybeVisitSIMDBinary(Expression*& out, uint32_t code) { curr = allocator.alloc<Binary>(); curr->op = SwizzleVec8x16; break; + case BinaryConsts::I8x16RelaxedSwizzle: + curr = allocator.alloc<Binary>(); + curr->op = RelaxedSwizzleVec8x16; + break; + case BinaryConsts::F32x4RelaxedMin: + curr = allocator.alloc<Binary>(); + curr->op = RelaxedMinVecF32x4; + break; + case BinaryConsts::F32x4RelaxedMax: + curr = allocator.alloc<Binary>(); + curr->op = RelaxedMaxVecF32x4; + break; + case BinaryConsts::F64x2RelaxedMin: + curr = allocator.alloc<Binary>(); + curr->op = RelaxedMinVecF64x2; + break; + case BinaryConsts::F64x2RelaxedMax: + curr = allocator.alloc<Binary>(); + curr->op = RelaxedMaxVecF64x2; + break; default: return false; } @@ -5797,6 +5817,22 @@ bool WasmBinaryBuilder::maybeVisitSIMDUnary(Expression*& out, uint32_t code) { curr = allocator.alloc<Unary>(); curr->op = PromoteLowVecF32x4ToVecF64x2; break; + case BinaryConsts::I32x4RelaxedTruncF32x4S: + curr = allocator.alloc<Unary>(); + curr->op = RelaxedTruncSVecF32x4ToVecI32x4; + break; + case BinaryConsts::I32x4RelaxedTruncF32x4U: + curr = allocator.alloc<Unary>(); + curr->op = RelaxedTruncUVecF32x4ToVecI32x4; + break; + case BinaryConsts::I32x4RelaxedTruncF64x2SZero: + curr = allocator.alloc<Unary>(); + curr->op = RelaxedTruncZeroSVecF64x2ToVecI32x4; + break; + case BinaryConsts::I32x4RelaxedTruncF64x2UZero: + curr = allocator.alloc<Unary>(); + curr->op = RelaxedTruncZeroUVecF64x2ToVecI32x4; + break; default: return false; } @@ -5950,6 +5986,38 @@ bool WasmBinaryBuilder::maybeVisitSIMDTernary(Expression*& out, uint32_t code) { curr = allocator.alloc<SIMDTernary>(); curr->op = Bitselect; break; + case BinaryConsts::I8x16Laneselect: + curr = allocator.alloc<SIMDTernary>(); + curr->op = LaneselectI8x16; + break; + case BinaryConsts::I16x8Laneselect: + curr = allocator.alloc<SIMDTernary>(); + curr->op = LaneselectI16x8; + break; + case BinaryConsts::I32x4Laneselect: + curr = allocator.alloc<SIMDTernary>(); + curr->op = LaneselectI32x4; + break; + case BinaryConsts::I64x2Laneselect: + curr = allocator.alloc<SIMDTernary>(); + curr->op = LaneselectI64x2; + break; + case BinaryConsts::F32x4RelaxedFma: + curr = allocator.alloc<SIMDTernary>(); + curr->op = RelaxedFmaVecF32x4; + break; + case BinaryConsts::F32x4RelaxedFms: + curr = allocator.alloc<SIMDTernary>(); + curr->op = RelaxedFmsVecF32x4; + break; + case BinaryConsts::F64x2RelaxedFma: + curr = allocator.alloc<SIMDTernary>(); + curr->op = RelaxedFmaVecF64x2; + break; + case BinaryConsts::F64x2RelaxedFms: + curr = allocator.alloc<SIMDTernary>(); + curr->op = RelaxedFmsVecF64x2; + break; default: return false; } diff --git a/src/wasm/wasm-stack.cpp b/src/wasm/wasm-stack.cpp index f5be5d2c5..59398839e 100644 --- a/src/wasm/wasm-stack.cpp +++ b/src/wasm/wasm-stack.cpp @@ -546,6 +546,30 @@ void BinaryInstWriter::visitSIMDTernary(SIMDTernary* curr) { case Bitselect: o << U32LEB(BinaryConsts::V128Bitselect); break; + case LaneselectI8x16: + o << U32LEB(BinaryConsts::I8x16Laneselect); + break; + case LaneselectI16x8: + o << U32LEB(BinaryConsts::I16x8Laneselect); + break; + case LaneselectI32x4: + o << U32LEB(BinaryConsts::I32x4Laneselect); + break; + case LaneselectI64x2: + o << U32LEB(BinaryConsts::I64x2Laneselect); + break; + case RelaxedFmaVecF32x4: + o << U32LEB(BinaryConsts::F32x4RelaxedFma); + break; + case RelaxedFmsVecF32x4: + o << U32LEB(BinaryConsts::F32x4RelaxedFms); + break; + case RelaxedFmaVecF64x2: + o << U32LEB(BinaryConsts::F64x2RelaxedFma); + break; + case RelaxedFmsVecF64x2: + o << U32LEB(BinaryConsts::F64x2RelaxedFms); + break; } } @@ -1153,6 +1177,22 @@ void BinaryInstWriter::visitUnary(Unary* curr) { o << int8_t(BinaryConsts::SIMDPrefix) << U32LEB(BinaryConsts::F64x2PromoteLowF32x4); break; + case RelaxedTruncSVecF32x4ToVecI32x4: + o << int8_t(BinaryConsts::SIMDPrefix) + << U32LEB(BinaryConsts::I32x4RelaxedTruncF32x4S); + break; + case RelaxedTruncUVecF32x4ToVecI32x4: + o << int8_t(BinaryConsts::SIMDPrefix) + << U32LEB(BinaryConsts::I32x4RelaxedTruncF32x4U); + break; + case RelaxedTruncZeroSVecF64x2ToVecI32x4: + o << int8_t(BinaryConsts::SIMDPrefix) + << U32LEB(BinaryConsts::I32x4RelaxedTruncF64x2SZero); + break; + case RelaxedTruncZeroUVecF64x2ToVecI32x4: + o << int8_t(BinaryConsts::SIMDPrefix) + << U32LEB(BinaryConsts::I32x4RelaxedTruncF64x2UZero); + break; case InvalidUnary: WASM_UNREACHABLE("invalid unary op"); } @@ -1783,6 +1823,27 @@ void BinaryInstWriter::visitBinary(Binary* curr) { << U32LEB(BinaryConsts::I8x16Swizzle); break; + case RelaxedSwizzleVec8x16: + o << int8_t(BinaryConsts::SIMDPrefix) + << U32LEB(BinaryConsts::I8x16RelaxedSwizzle); + break; + case RelaxedMinVecF32x4: + o << int8_t(BinaryConsts::SIMDPrefix) + << U32LEB(BinaryConsts::F32x4RelaxedMin); + break; + case RelaxedMaxVecF32x4: + o << int8_t(BinaryConsts::SIMDPrefix) + << U32LEB(BinaryConsts::F32x4RelaxedMax); + break; + case RelaxedMinVecF64x2: + o << int8_t(BinaryConsts::SIMDPrefix) + << U32LEB(BinaryConsts::F64x2RelaxedMin); + break; + case RelaxedMaxVecF64x2: + o << int8_t(BinaryConsts::SIMDPrefix) + << U32LEB(BinaryConsts::F64x2RelaxedMax); + break; + case InvalidBinary: WASM_UNREACHABLE("invalid binary op"); } diff --git a/src/wasm/wasm-validator.cpp b/src/wasm/wasm-validator.cpp index 86b537bf5..696c50d8b 100644 --- a/src/wasm/wasm-validator.cpp +++ b/src/wasm/wasm-validator.cpp @@ -1613,6 +1613,8 @@ void FunctionValidator::visitBinary(Binary* curr) { case MaxVecF32x4: case PMinVecF32x4: case PMaxVecF32x4: + case RelaxedMinVecF32x4: + case RelaxedMaxVecF32x4: case AddVecF64x2: case SubVecF64x2: case MulVecF64x2: @@ -1621,11 +1623,14 @@ void FunctionValidator::visitBinary(Binary* curr) { case MaxVecF64x2: case PMinVecF64x2: case PMaxVecF64x2: + case RelaxedMinVecF64x2: + case RelaxedMaxVecF64x2: case NarrowSVecI16x8ToVecI8x16: case NarrowUVecI16x8ToVecI8x16: case NarrowSVecI32x4ToVecI16x8: case NarrowUVecI32x4ToVecI16x8: - case SwizzleVec8x16: { + case SwizzleVec8x16: + case RelaxedSwizzleVec8x16: { shouldBeEqualOrFirstIsUnreachable( curr->left->type, Type(Type::v128), curr, "v128 op"); shouldBeEqualOrFirstIsUnreachable( @@ -1898,6 +1903,10 @@ void FunctionValidator::visitUnary(Unary* curr) { case TruncSatZeroUVecF64x2ToVecI32x4: case DemoteZeroVecF64x2ToVecF32x4: case PromoteLowVecF32x4ToVecF64x2: + case RelaxedTruncSVecF32x4ToVecI32x4: + case RelaxedTruncUVecF32x4ToVecI32x4: + case RelaxedTruncZeroSVecF64x2ToVecI32x4: + case RelaxedTruncZeroUVecF64x2ToVecI32x4: shouldBeEqual(curr->type, Type(Type::v128), curr, "expected v128 type"); shouldBeEqual( curr->value->type, Type(Type::v128), curr, "expected v128 operand"); diff --git a/src/wasm/wasm.cpp b/src/wasm/wasm.cpp index 015df26ac..fd3cec8d8 100644 --- a/src/wasm/wasm.cpp +++ b/src/wasm/wasm.cpp @@ -711,6 +711,10 @@ void Unary::finalize() { case TruncSatZeroUVecF64x2ToVecI32x4: case DemoteZeroVecF64x2ToVecF32x4: case PromoteLowVecF32x4ToVecF64x2: + case RelaxedTruncSVecF32x4ToVecI32x4: + case RelaxedTruncUVecF32x4ToVecI32x4: + case RelaxedTruncZeroSVecF64x2ToVecI32x4: + case RelaxedTruncZeroUVecF64x2ToVecI32x4: type = Type::v128; break; case AnyTrueVec128: |