diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/gen-s-parser.inc | 49 | ||||
-rw-r--r-- | src/ir/child-typer.h | 4 | ||||
-rw-r--r-- | src/ir/cost.h | 4 | ||||
-rw-r--r-- | src/literal.h | 8 | ||||
-rw-r--r-- | src/passes/Print.cpp | 12 | ||||
-rw-r--r-- | src/support/safe_integer.cpp | 10 | ||||
-rw-r--r-- | src/support/safe_integer.h | 2 | ||||
-rw-r--r-- | src/tools/fuzzing/fuzzing.cpp | 6 | ||||
-rw-r--r-- | src/wasm-binary.h | 4 | ||||
-rw-r--r-- | src/wasm-interpreter.h | 8 | ||||
-rw-r--r-- | src/wasm.h | 4 | ||||
-rw-r--r-- | src/wasm/literal.cpp | 43 | ||||
-rw-r--r-- | src/wasm/wasm-binary.cpp | 16 | ||||
-rw-r--r-- | src/wasm/wasm-stack.cpp | 16 | ||||
-rw-r--r-- | src/wasm/wasm-validator.cpp | 4 | ||||
-rw-r--r-- | src/wasm/wasm.cpp | 4 |
16 files changed, 188 insertions, 6 deletions
diff --git a/src/gen-s-parser.inc b/src/gen-s-parser.inc index f7d12a1be..75fda4f7a 100644 --- a/src/gen-s-parser.inc +++ b/src/gen-s-parser.inc @@ -326,12 +326,34 @@ switch (buf[0]) { default: goto parse_error; } } - case 'c': - if (op == "f16x8.ceil"sv) { - CHECK_ERR(makeUnary(ctx, pos, annotations, UnaryOp::CeilVecF16x8)); - return Ok{}; + case 'c': { + switch (buf[7]) { + case 'e': + if (op == "f16x8.ceil"sv) { + CHECK_ERR(makeUnary(ctx, pos, annotations, UnaryOp::CeilVecF16x8)); + return Ok{}; + } + goto parse_error; + case 'o': { + switch (buf[20]) { + case 's': + if (op == "f16x8.convert_i16x8_s"sv) { + CHECK_ERR(makeUnary(ctx, pos, annotations, UnaryOp::ConvertSVecI16x8ToVecF16x8)); + return Ok{}; + } + goto parse_error; + case 'u': + if (op == "f16x8.convert_i16x8_u"sv) { + CHECK_ERR(makeUnary(ctx, pos, annotations, UnaryOp::ConvertUVecI16x8ToVecF16x8)); + return Ok{}; + } + goto parse_error; + default: goto parse_error; + } + } + default: goto parse_error; } - goto parse_error; + } case 'd': if (op == "f16x8.div"sv) { CHECK_ERR(makeBinary(ctx, pos, annotations, BinaryOp::DivVecF16x8)); @@ -2038,6 +2060,23 @@ switch (buf[0]) { default: goto parse_error; } } + case 't': { + switch (buf[22]) { + case 's': + if (op == "i16x8.trunc_sat_f16x8_s"sv) { + CHECK_ERR(makeUnary(ctx, pos, annotations, UnaryOp::TruncSatSVecF16x8ToVecI16x8)); + return Ok{}; + } + goto parse_error; + case 'u': + if (op == "i16x8.trunc_sat_f16x8_u"sv) { + CHECK_ERR(makeUnary(ctx, pos, annotations, UnaryOp::TruncSatUVecF16x8ToVecI16x8)); + return Ok{}; + } + goto parse_error; + default: goto parse_error; + } + } default: goto parse_error; } } diff --git a/src/ir/child-typer.h b/src/ir/child-typer.h index 638bb9c33..499a7e4dd 100644 --- a/src/ir/child-typer.h +++ b/src/ir/child-typer.h @@ -423,6 +423,10 @@ template<typename Subtype> struct ChildTyper : OverriddenVisitor<Subtype> { case RelaxedTruncUVecF32x4ToVecI32x4: case RelaxedTruncZeroSVecF64x2ToVecI32x4: case RelaxedTruncZeroUVecF64x2ToVecI32x4: + case TruncSatSVecF16x8ToVecI16x8: + case TruncSatUVecF16x8ToVecI16x8: + case ConvertSVecI16x8ToVecF16x8: + case ConvertUVecI16x8ToVecF16x8: case AnyTrueVec128: case AllTrueVecI8x16: case AllTrueVecI16x8: diff --git a/src/ir/cost.h b/src/ir/cost.h index d11a9bfac..fcee6c18e 100644 --- a/src/ir/cost.h +++ b/src/ir/cost.h @@ -257,6 +257,10 @@ struct CostAnalyzer : public OverriddenVisitor<CostAnalyzer, CostType> { case RelaxedTruncUVecF32x4ToVecI32x4: case RelaxedTruncZeroSVecF64x2ToVecI32x4: case RelaxedTruncZeroUVecF64x2ToVecI32x4: + case TruncSatSVecF16x8ToVecI16x8: + case TruncSatUVecF16x8ToVecI16x8: + case ConvertSVecI16x8ToVecF16x8: + case ConvertUVecI16x8ToVecF16x8: ret = 1; break; case InvalidUnary: diff --git a/src/literal.h b/src/literal.h index 6aa348084..50666083e 100644 --- a/src/literal.h +++ b/src/literal.h @@ -377,14 +377,18 @@ public: Literal extendS32() const; Literal wrapToI32() const; + Literal convertSIToF16() const; + Literal convertUIToF16() const; Literal convertSIToF32() const; Literal convertUIToF32() const; Literal convertSIToF64() const; Literal convertUIToF64() const; Literal convertF32ToF16() const; + Literal truncSatToSI16() const; Literal truncSatToSI32() const; Literal truncSatToSI64() const; + Literal truncSatToUI16() const; Literal truncSatToUI32() const; Literal truncSatToUI64() const; @@ -693,6 +697,10 @@ public: Literal truncSatZeroUToI32x4() const; Literal demoteZeroToF32x4() const; Literal promoteLowToF64x2() const; + Literal truncSatToSI16x8() const; + Literal truncSatToUI16x8() const; + Literal convertSToF16x8() const; + Literal convertUToF16x8() const; Literal swizzleI8x16(const Literal& other) const; Literal relaxedMaddF16x8(const Literal& left, const Literal& right) const; Literal relaxedNmaddF16x8(const Literal& left, const Literal& right) const; diff --git a/src/passes/Print.cpp b/src/passes/Print.cpp index 427bff329..854934204 100644 --- a/src/passes/Print.cpp +++ b/src/passes/Print.cpp @@ -1368,6 +1368,18 @@ struct PrintExpressionContents case RelaxedTruncZeroUVecF64x2ToVecI32x4: o << "i32x4.relaxed_trunc_f64x2_u_zero"; break; + case TruncSatSVecF16x8ToVecI16x8: + o << "i16x8.trunc_sat_f16x8_s"; + break; + case TruncSatUVecF16x8ToVecI16x8: + o << "i16x8.trunc_sat_f16x8_u"; + break; + case ConvertSVecI16x8ToVecF16x8: + o << "f16x8.convert_i16x8_s"; + break; + case ConvertUVecI16x8ToVecF16x8: + o << "f16x8.convert_i16x8_u"; + break; case InvalidUnary: WASM_UNREACHABLE("unvalid unary operator"); } diff --git a/src/support/safe_integer.cpp b/src/support/safe_integer.cpp index 3a50b50ea..86ba2547a 100644 --- a/src/support/safe_integer.cpp +++ b/src/support/safe_integer.cpp @@ -98,6 +98,11 @@ int64_t wasm::toSInteger64(double x) { * 1 11111111 111...11 => 0xffffffff => -nan(0x7fffff) */ +bool wasm::isInRangeI16TruncS(int32_t i) { + uint32_t u = i; + return (u < 0x47000000U) || (u >= 0x80000000U && u <= 0xc7000000U); +} + bool wasm::isInRangeI32TruncS(int32_t i) { uint32_t u = i; return (u < 0x4f000000U) || (u >= 0x80000000U && u <= 0xcf000000U); @@ -108,6 +113,11 @@ bool wasm::isInRangeI64TruncS(int32_t i) { return (u < 0x5f000000U) || (u >= 0x80000000U && u <= 0xdf000000U); } +bool wasm::isInRangeI16TruncU(int32_t i) { + uint32_t u = i; + return (u < 0x47800000) || (u >= 0x80000000U && u < 0xbf800000U); +} + bool wasm::isInRangeI32TruncU(int32_t i) { uint32_t u = i; return (u < 0x4f800000U) || (u >= 0x80000000U && u < 0xbf800000U); diff --git a/src/support/safe_integer.h b/src/support/safe_integer.h index 031c6c323..6888ab25f 100644 --- a/src/support/safe_integer.h +++ b/src/support/safe_integer.h @@ -32,8 +32,10 @@ uint64_t toUInteger64(double x); int64_t toSInteger64(double x); // The isInRange* functions all expect to be passed the binary representation // of a float or double. +bool isInRangeI16TruncS(int32_t i); bool isInRangeI32TruncS(int32_t i); bool isInRangeI64TruncS(int32_t i); +bool isInRangeI16TruncU(int32_t i); bool isInRangeI32TruncU(int32_t i); bool isInRangeI64TruncU(int32_t i); bool isInRangeI32TruncS(int64_t i); diff --git a/src/tools/fuzzing/fuzzing.cpp b/src/tools/fuzzing/fuzzing.cpp index a66fa6772..a8b8f7855 100644 --- a/src/tools/fuzzing/fuzzing.cpp +++ b/src/tools/fuzzing/fuzzing.cpp @@ -3143,7 +3143,11 @@ Expression* TranslateToFuzzReader::makeUnary(Type type) { CeilVecF16x8, FloorVecF16x8, TruncVecF16x8, - NearestVecF16x8)), + NearestVecF16x8, + TruncSatSVecF16x8ToVecI16x8, + TruncSatUVecF16x8ToVecI16x8, + ConvertSVecI16x8ToVecF16x8, + ConvertUVecI16x8ToVecF16x8)), make(Type::v128)}); } WASM_UNREACHABLE("invalid value"); diff --git a/src/wasm-binary.h b/src/wasm-binary.h index 5021b6a29..35f131952 100644 --- a/src/wasm-binary.h +++ b/src/wasm-binary.h @@ -1039,6 +1039,10 @@ enum ASTNodes { F16x8Max = 0x142, F16x8Pmin = 0x143, F16x8Pmax = 0x144, + I16x8TruncSatF16x8S = 0x145, + I16x8TruncSatF16x8U = 0x146, + F16x8ConvertI16x8S = 0x147, + F16x8ConvertI16x8U = 0x148, // bulk memory opcodes diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h index 25303abfe..9659a5c34 100644 --- a/src/wasm-interpreter.h +++ b/src/wasm-interpreter.h @@ -632,6 +632,14 @@ public: return value.demoteZeroToF32x4(); case PromoteLowVecF32x4ToVecF64x2: return value.promoteLowToF64x2(); + case TruncSatSVecF16x8ToVecI16x8: + return value.truncSatToSI16x8(); + case TruncSatUVecF16x8ToVecI16x8: + return value.truncSatToUI16x8(); + case ConvertSVecI16x8ToVecF16x8: + return value.convertSToF16x8(); + case ConvertUVecI16x8ToVecF16x8: + return value.convertUToF16x8(); case InvalidUnary: WASM_UNREACHABLE("invalid unary op"); } diff --git a/src/wasm.h b/src/wasm.h index a86f77013..e54d628bd 100644 --- a/src/wasm.h +++ b/src/wasm.h @@ -238,6 +238,10 @@ enum UnaryOp { // Half precision SIMD SplatVecF16x8, + TruncSatSVecF16x8ToVecI16x8, + TruncSatUVecF16x8ToVecI16x8, + ConvertSVecI16x8ToVecF16x8, + ConvertUVecI16x8ToVecF16x8, InvalidUnary }; diff --git a/src/wasm/literal.cpp b/src/wasm/literal.cpp index 6aaba729a..b53378cfa 100644 --- a/src/wasm/literal.cpp +++ b/src/wasm/literal.cpp @@ -798,6 +798,20 @@ Literal Literal::wrapToI32() const { return Literal((int32_t)i64); } +Literal Literal::convertSIToF16() const { + if (type == Type::i32) { + return Literal(fp16_ieee_from_fp32_value(float(i32))); + } + WASM_UNREACHABLE("invalid type"); +} + +Literal Literal::convertUIToF16() const { + if (type == Type::i32) { + return Literal(fp16_ieee_from_fp32_value(float(uint16_t(i32)))); + } + WASM_UNREACHABLE("invalid type"); +} + Literal Literal::convertSIToF32() const { if (type == Type::i32) { return Literal(float(i32)); @@ -861,6 +875,14 @@ static Literal saturating_trunc(typename AsInt<F>::type val) { return Literal(I(std::trunc(bit_cast<F>(val)))); } +Literal Literal::truncSatToSI16() const { + if (type == Type::f32) { + return saturating_trunc<float, int16_t, isInRangeI16TruncS>( + Literal(*this).castToI32().geti32()); + } + WASM_UNREACHABLE("invalid type"); +} + Literal Literal::truncSatToSI32() const { if (type == Type::f32) { return saturating_trunc<float, int32_t, isInRangeI32TruncS>( @@ -885,6 +907,14 @@ Literal Literal::truncSatToSI64() const { WASM_UNREACHABLE("invalid type"); } +Literal Literal::truncSatToUI16() const { + if (type == Type::f32) { + return saturating_trunc<float, uint16_t, isInRangeI16TruncU>( + Literal(*this).castToI32().geti32()); + } + WASM_UNREACHABLE("invalid type"); +} + Literal Literal::truncSatToUI32() const { if (type == Type::f32) { return saturating_trunc<float, uint32_t, isInRangeI32TruncU>( @@ -1997,6 +2027,19 @@ Literal Literal::convertUToF32x4() const { return unary<4, &Literal::getLanesI32x4, &Literal::convertUIToF32>(*this); } +Literal Literal::truncSatToSI16x8() const { + return unary<8, &Literal::getLanesF16x8, &Literal::truncSatToSI16>(*this); +} +Literal Literal::truncSatToUI16x8() const { + return unary<8, &Literal::getLanesF16x8, &Literal::truncSatToUI16>(*this); +} +Literal Literal::convertSToF16x8() const { + return unary<8, &Literal::getLanesSI16x8, &Literal::convertSIToF16>(*this); +} +Literal Literal::convertUToF16x8() const { + return unary<8, &Literal::getLanesSI16x8, &Literal::convertUIToF16>(*this); +} + Literal Literal::anyTrueV128() const { auto lanes = getLanesI32x4(); for (size_t i = 0; i < 4; ++i) { diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp index cb9ea3731..3bb33529b 100644 --- a/src/wasm/wasm-binary.cpp +++ b/src/wasm/wasm-binary.cpp @@ -6522,6 +6522,22 @@ bool WasmBinaryReader::maybeVisitSIMDUnary(Expression*& out, uint32_t code) { curr = allocator.alloc<Unary>(); curr->op = RelaxedTruncZeroUVecF64x2ToVecI32x4; break; + case BinaryConsts::I16x8TruncSatF16x8S: + curr = allocator.alloc<Unary>(); + curr->op = TruncSatSVecF16x8ToVecI16x8; + break; + case BinaryConsts::I16x8TruncSatF16x8U: + curr = allocator.alloc<Unary>(); + curr->op = TruncSatUVecF16x8ToVecI16x8; + break; + case BinaryConsts::F16x8ConvertI16x8S: + curr = allocator.alloc<Unary>(); + curr->op = ConvertSVecI16x8ToVecF16x8; + break; + case BinaryConsts::F16x8ConvertI16x8U: + curr = allocator.alloc<Unary>(); + curr->op = ConvertUVecI16x8ToVecF16x8; + break; default: return false; } diff --git a/src/wasm/wasm-stack.cpp b/src/wasm/wasm-stack.cpp index a1446c2de..7194229fe 100644 --- a/src/wasm/wasm-stack.cpp +++ b/src/wasm/wasm-stack.cpp @@ -1324,6 +1324,22 @@ void BinaryInstWriter::visitUnary(Unary* curr) { o << int8_t(BinaryConsts::SIMDPrefix) << U32LEB(BinaryConsts::I32x4RelaxedTruncF64x2UZero); break; + case TruncSatSVecF16x8ToVecI16x8: + o << int8_t(BinaryConsts::SIMDPrefix) + << U32LEB(BinaryConsts::I16x8TruncSatF16x8S); + break; + case TruncSatUVecF16x8ToVecI16x8: + o << int8_t(BinaryConsts::SIMDPrefix) + << U32LEB(BinaryConsts::I16x8TruncSatF16x8U); + break; + case ConvertSVecI16x8ToVecF16x8: + o << int8_t(BinaryConsts::SIMDPrefix) + << U32LEB(BinaryConsts::F16x8ConvertI16x8S); + break; + case ConvertUVecI16x8ToVecF16x8: + o << int8_t(BinaryConsts::SIMDPrefix) + << U32LEB(BinaryConsts::F16x8ConvertI16x8U); + break; case InvalidUnary: WASM_UNREACHABLE("invalid unary op"); } diff --git a/src/wasm/wasm-validator.cpp b/src/wasm/wasm-validator.cpp index 40726d7cd..a86187fa7 100644 --- a/src/wasm/wasm-validator.cpp +++ b/src/wasm/wasm-validator.cpp @@ -2160,6 +2160,10 @@ void FunctionValidator::visitUnary(Unary* curr) { case RelaxedTruncUVecF32x4ToVecI32x4: case RelaxedTruncZeroSVecF64x2ToVecI32x4: case RelaxedTruncZeroUVecF64x2ToVecI32x4: + case TruncSatSVecF16x8ToVecI16x8: + case TruncSatUVecF16x8ToVecI16x8: + case ConvertSVecI16x8ToVecF16x8: + case ConvertUVecI16x8ToVecF16x8: 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 87ae6ac5a..84fd9a06f 100644 --- a/src/wasm/wasm.cpp +++ b/src/wasm/wasm.cpp @@ -703,6 +703,10 @@ void Unary::finalize() { case RelaxedTruncUVecF32x4ToVecI32x4: case RelaxedTruncZeroSVecF64x2ToVecI32x4: case RelaxedTruncZeroUVecF64x2ToVecI32x4: + case TruncSatSVecF16x8ToVecI16x8: + case TruncSatUVecF16x8ToVecI16x8: + case ConvertSVecI16x8ToVecF16x8: + case ConvertUVecI16x8ToVecF16x8: type = Type::v128; break; case AnyTrueVec128: |