diff options
author | Brendan Dahl <brendan.dahl@gmail.com> | 2024-09-26 15:35:47 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-09-26 15:35:47 -0700 |
commit | c3a71ff46d8f38e29896c321d89b6d0c3b90fbc1 (patch) | |
tree | 04c4751da10f8e548e0ff94945d2635939b34f58 /src/wasm | |
parent | 3856a2dc909b3c713497ef311fe4051078ee74b9 (diff) | |
download | binaryen-c3a71ff46d8f38e29896c321d89b6d0c3b90fbc1.tar.gz binaryen-c3a71ff46d8f38e29896c321d89b6d0c3b90fbc1.tar.bz2 binaryen-c3a71ff46d8f38e29896c321d89b6d0c3b90fbc1.zip |
[FP16] Implement conversion operations. (#6974)
Note: FP16 is a little different from F32/F64 since it can't represent
the full 2^16 integer range. 65504 is the max whole integer. This leads
to some slightly strange behavior when converting integers greater than
65504 since they become infinity.
Specified at
https://github.com/WebAssembly/half-precision/blob/main/proposals/half-precision/Overview.md
Diffstat (limited to 'src/wasm')
-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 |
5 files changed, 83 insertions, 0 deletions
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: |