diff options
-rwxr-xr-x | scripts/gen-s-parser.py | 7 | ||||
-rw-r--r-- | src/gen-s-parser.inc | 68 | ||||
-rw-r--r-- | src/ir/child-typer.h | 7 | ||||
-rw-r--r-- | src/ir/cost.h | 7 | ||||
-rw-r--r-- | src/literal.h | 7 | ||||
-rw-r--r-- | src/passes/Print.cpp | 21 | ||||
-rw-r--r-- | src/tools/fuzzing/fuzzing.cpp | 61 | ||||
-rw-r--r-- | src/wasm-binary.h | 7 | ||||
-rw-r--r-- | src/wasm-interpreter.h | 14 | ||||
-rw-r--r-- | src/wasm.h | 7 | ||||
-rw-r--r-- | src/wasm/literal.cpp | 36 | ||||
-rw-r--r-- | src/wasm/wasm-binary.cpp | 28 | ||||
-rw-r--r-- | src/wasm/wasm-stack.cpp | 22 | ||||
-rw-r--r-- | src/wasm/wasm-validator.cpp | 11 | ||||
-rw-r--r-- | src/wasm/wasm.cpp | 7 | ||||
-rw-r--r-- | test/lit/basic/f16.wast | 213 | ||||
-rw-r--r-- | test/spec/f16.wast | 40 |
17 files changed, 493 insertions, 70 deletions
diff --git a/scripts/gen-s-parser.py b/scripts/gen-s-parser.py index 39d621f48..49fa6afb6 100755 --- a/scripts/gen-s-parser.py +++ b/scripts/gen-s-parser.py @@ -452,6 +452,9 @@ instructions = [ ("i64x2.extmul_high_i32x4_s", "makeBinary(BinaryOp::ExtMulHighSVecI64x2)"), ("i64x2.extmul_low_i32x4_u", "makeBinary(BinaryOp::ExtMulLowUVecI64x2)"), ("i64x2.extmul_high_i32x4_u", "makeBinary(BinaryOp::ExtMulHighUVecI64x2)"), + ("f16x8.abs", "makeUnary(UnaryOp::AbsVecF16x8)"), + ("f16x8.neg", "makeUnary(UnaryOp::NegVecF16x8)"), + ("f16x8.sqrt", "makeUnary(UnaryOp::SqrtVecF16x8)"), ("f16x8.add", "makeBinary(BinaryOp::AddVecF16x8)"), ("f16x8.sub", "makeBinary(BinaryOp::SubVecF16x8)"), ("f16x8.mul", "makeBinary(BinaryOp::MulVecF16x8)"), @@ -460,6 +463,10 @@ instructions = [ ("f16x8.max", "makeBinary(BinaryOp::MaxVecF16x8)"), ("f16x8.pmin", "makeBinary(BinaryOp::PMinVecF16x8)"), ("f16x8.pmax", "makeBinary(BinaryOp::PMaxVecF16x8)"), + ("f16x8.ceil", "makeUnary(UnaryOp::CeilVecF16x8)"), + ("f16x8.floor", "makeUnary(UnaryOp::FloorVecF16x8)"), + ("f16x8.trunc", "makeUnary(UnaryOp::TruncVecF16x8)"), + ("f16x8.nearest", "makeUnary(UnaryOp::NearestVecF16x8)"), ("f32x4.abs", "makeUnary(UnaryOp::AbsVecF32x4)"), ("f32x4.neg", "makeUnary(UnaryOp::NegVecF32x4)"), ("f32x4.sqrt", "makeUnary(UnaryOp::SqrtVecF32x4)"), diff --git a/src/gen-s-parser.inc b/src/gen-s-parser.inc index f4afd1f1b..7d4fbe819 100644 --- a/src/gen-s-parser.inc +++ b/src/gen-s-parser.inc @@ -309,9 +309,26 @@ switch (buf[0]) { switch (buf[1]) { case '1': { switch (buf[6]) { - case 'a': - if (op == "f16x8.add"sv) { - CHECK_ERR(makeBinary(ctx, pos, annotations, BinaryOp::AddVecF16x8)); + case 'a': { + switch (buf[7]) { + case 'b': + if (op == "f16x8.abs"sv) { + CHECK_ERR(makeUnary(ctx, pos, annotations, UnaryOp::AbsVecF16x8)); + return Ok{}; + } + goto parse_error; + case 'd': + if (op == "f16x8.add"sv) { + CHECK_ERR(makeBinary(ctx, pos, annotations, BinaryOp::AddVecF16x8)); + return Ok{}; + } + goto parse_error; + default: goto parse_error; + } + } + case 'c': + if (op == "f16x8.ceil"sv) { + CHECK_ERR(makeUnary(ctx, pos, annotations, UnaryOp::CeilVecF16x8)); return Ok{}; } goto parse_error; @@ -338,6 +355,12 @@ switch (buf[0]) { default: goto parse_error; } } + case 'f': + if (op == "f16x8.floor"sv) { + CHECK_ERR(makeUnary(ctx, pos, annotations, UnaryOp::FloorVecF16x8)); + return Ok{}; + } + goto parse_error; case 'g': { switch (buf[7]) { case 'e': @@ -395,12 +418,29 @@ switch (buf[0]) { default: goto parse_error; } } - case 'n': - if (op == "f16x8.ne"sv) { - CHECK_ERR(makeBinary(ctx, pos, annotations, BinaryOp::NeVecF16x8)); - return Ok{}; + case 'n': { + switch (buf[8]) { + case '\0': + if (op == "f16x8.ne"sv) { + CHECK_ERR(makeBinary(ctx, pos, annotations, BinaryOp::NeVecF16x8)); + return Ok{}; + } + goto parse_error; + case 'a': + if (op == "f16x8.nearest"sv) { + CHECK_ERR(makeUnary(ctx, pos, annotations, UnaryOp::NearestVecF16x8)); + return Ok{}; + } + goto parse_error; + case 'g': + if (op == "f16x8.neg"sv) { + CHECK_ERR(makeUnary(ctx, pos, annotations, UnaryOp::NegVecF16x8)); + return Ok{}; + } + goto parse_error; + default: goto parse_error; } - goto parse_error; + } case 'p': { switch (buf[8]) { case 'a': @@ -432,6 +472,12 @@ switch (buf[0]) { return Ok{}; } goto parse_error; + case 'q': + if (op == "f16x8.sqrt"sv) { + CHECK_ERR(makeUnary(ctx, pos, annotations, UnaryOp::SqrtVecF16x8)); + return Ok{}; + } + goto parse_error; case 'u': if (op == "f16x8.sub"sv) { CHECK_ERR(makeBinary(ctx, pos, annotations, BinaryOp::SubVecF16x8)); @@ -441,6 +487,12 @@ switch (buf[0]) { default: goto parse_error; } } + case 't': + if (op == "f16x8.trunc"sv) { + CHECK_ERR(makeUnary(ctx, pos, annotations, UnaryOp::TruncVecF16x8)); + return Ok{}; + } + goto parse_error; default: goto parse_error; } } diff --git a/src/ir/child-typer.h b/src/ir/child-typer.h index fe65b209b..638bb9c33 100644 --- a/src/ir/child-typer.h +++ b/src/ir/child-typer.h @@ -372,6 +372,13 @@ template<typename Subtype> struct ChildTyper : OverriddenVisitor<Subtype> { case NegVecI16x8: case NegVecI32x4: case NegVecI64x2: + case AbsVecF16x8: + case NegVecF16x8: + case SqrtVecF16x8: + case CeilVecF16x8: + case FloorVecF16x8: + case TruncVecF16x8: + case NearestVecF16x8: case AbsVecF32x4: case NegVecF32x4: case SqrtVecF32x4: diff --git a/src/ir/cost.h b/src/ir/cost.h index 0b2b6315b..f541a4506 100644 --- a/src/ir/cost.h +++ b/src/ir/cost.h @@ -206,6 +206,13 @@ struct CostAnalyzer : public OverriddenVisitor<CostAnalyzer, CostType> { case NegVecI64x2: case AllTrueVecI64x2: case BitmaskVecI64x2: + case AbsVecF16x8: + case NegVecF16x8: + case SqrtVecF16x8: + case CeilVecF16x8: + case FloorVecF16x8: + case TruncVecF16x8: + case NearestVecF16x8: case AbsVecF32x4: case NegVecF32x4: case SqrtVecF32x4: diff --git a/src/literal.h b/src/literal.h index df9a16d9a..7bedab5b4 100644 --- a/src/literal.h +++ b/src/literal.h @@ -618,6 +618,9 @@ public: Literal extMulHighSI64x2(const Literal& other) const; Literal extMulLowUI64x2(const Literal& other) const; Literal extMulHighUI64x2(const Literal& other) const; + Literal absF16x8() const; + Literal negF16x8() const; + Literal sqrtF16x8() const; Literal addF16x8(const Literal& other) const; Literal subF16x8(const Literal& other) const; Literal mulF16x8(const Literal& other) const; @@ -626,6 +629,10 @@ public: Literal maxF16x8(const Literal& other) const; Literal pminF16x8(const Literal& other) const; Literal pmaxF16x8(const Literal& other) const; + Literal ceilF16x8() const; + Literal floorF16x8() const; + Literal truncF16x8() const; + Literal nearestF16x8() const; Literal absF32x4() const; Literal negF32x4() const; Literal sqrtF32x4() const; diff --git a/src/passes/Print.cpp b/src/passes/Print.cpp index 4986982c7..8f53481b7 100644 --- a/src/passes/Print.cpp +++ b/src/passes/Print.cpp @@ -1209,6 +1209,27 @@ struct PrintExpressionContents case BitmaskVecI64x2: o << "i64x2.bitmask"; break; + case AbsVecF16x8: + o << "f16x8.abs"; + break; + case NegVecF16x8: + o << "f16x8.neg"; + break; + case SqrtVecF16x8: + o << "f16x8.sqrt"; + break; + case CeilVecF16x8: + o << "f16x8.ceil"; + break; + case FloorVecF16x8: + o << "f16x8.floor"; + break; + case TruncVecF16x8: + o << "f16x8.trunc"; + break; + case NearestVecF16x8: + o << "f16x8.nearest"; + break; case AbsVecF32x4: o << "f32x4.abs"; break; diff --git a/src/tools/fuzzing/fuzzing.cpp b/src/tools/fuzzing/fuzzing.cpp index 7a3007e43..a66fa6772 100644 --- a/src/tools/fuzzing/fuzzing.cpp +++ b/src/tools/fuzzing/fuzzing.cpp @@ -3109,31 +3109,42 @@ Expression* TranslateToFuzzReader::makeUnary(Type type) { case 3: return buildUnary({SplatVecF64x2, make(Type::f64)}); case 4: - return buildUnary({pick(NotVec128, - // TODO: add additional SIMD instructions - NegVecI8x16, - NegVecI16x8, - NegVecI32x4, - NegVecI64x2, - AbsVecF32x4, - NegVecF32x4, - SqrtVecF32x4, - AbsVecF64x2, - NegVecF64x2, - SqrtVecF64x2, - TruncSatSVecF32x4ToVecI32x4, - TruncSatUVecF32x4ToVecI32x4, - ConvertSVecI32x4ToVecF32x4, - ConvertUVecI32x4ToVecF32x4, - ExtendLowSVecI8x16ToVecI16x8, - ExtendHighSVecI8x16ToVecI16x8, - ExtendLowUVecI8x16ToVecI16x8, - ExtendHighUVecI8x16ToVecI16x8, - ExtendLowSVecI16x8ToVecI32x4, - ExtendHighSVecI16x8ToVecI32x4, - ExtendLowUVecI16x8ToVecI32x4, - ExtendHighUVecI16x8ToVecI32x4), - make(Type::v128)}); + return buildUnary( + {pick(FeatureOptions<UnaryOp>() + .add(FeatureSet::SIMD, + NotVec128, + // TODO: add additional SIMD instructions + NegVecI8x16, + NegVecI16x8, + NegVecI32x4, + NegVecI64x2, + AbsVecF32x4, + NegVecF32x4, + SqrtVecF32x4, + AbsVecF64x2, + NegVecF64x2, + SqrtVecF64x2, + TruncSatSVecF32x4ToVecI32x4, + TruncSatUVecF32x4ToVecI32x4, + ConvertSVecI32x4ToVecF32x4, + ConvertUVecI32x4ToVecF32x4, + ExtendLowSVecI8x16ToVecI16x8, + ExtendHighSVecI8x16ToVecI16x8, + ExtendLowUVecI8x16ToVecI16x8, + ExtendHighUVecI8x16ToVecI16x8, + ExtendLowSVecI16x8ToVecI32x4, + ExtendHighSVecI16x8ToVecI32x4, + ExtendLowUVecI16x8ToVecI32x4, + ExtendHighUVecI16x8ToVecI32x4) + .add(FeatureSet::FP16, + AbsVecF16x8, + NegVecF16x8, + SqrtVecF16x8, + CeilVecF16x8, + FloorVecF16x8, + TruncVecF16x8, + NearestVecF16x8)), + make(Type::v128)}); } WASM_UNREACHABLE("invalid value"); } diff --git a/src/wasm-binary.h b/src/wasm-binary.h index a4439f026..9ce355b48 100644 --- a/src/wasm-binary.h +++ b/src/wasm-binary.h @@ -1059,6 +1059,13 @@ enum ASTNodes { F16x8Splat = 0x120, F16x8ExtractLane = 0x121, F16x8ReplaceLane = 0x122, + F16x8Abs = 0x130, + F16x8Neg = 0x131, + F16x8Sqrt = 0x132, + F16x8Ceil = 0x133, + F16x8Floor = 0x134, + F16x8Trunc = 0x135, + F16x8Nearest = 0x136, F16x8Eq = 0x137, F16x8Ne = 0x138, F16x8Lt = 0x139, diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h index 77349fd33..50fc296fe 100644 --- a/src/wasm-interpreter.h +++ b/src/wasm-interpreter.h @@ -531,6 +531,20 @@ public: return value.allTrueI64x2(); case BitmaskVecI64x2: return value.bitmaskI64x2(); + case AbsVecF16x8: + return value.absF16x8(); + case NegVecF16x8: + return value.negF16x8(); + case SqrtVecF16x8: + return value.sqrtF16x8(); + case CeilVecF16x8: + return value.ceilF16x8(); + case FloorVecF16x8: + return value.floorF16x8(); + case TruncVecF16x8: + return value.truncF16x8(); + case NearestVecF16x8: + return value.nearestF16x8(); case AbsVecF32x4: return value.absF32x4(); case NegVecF32x4: diff --git a/src/wasm.h b/src/wasm.h index 6f82196b7..a707ab7a4 100644 --- a/src/wasm.h +++ b/src/wasm.h @@ -179,6 +179,13 @@ enum UnaryOp { NegVecI64x2, AllTrueVecI64x2, BitmaskVecI64x2, + AbsVecF16x8, + NegVecF16x8, + SqrtVecF16x8, + CeilVecF16x8, + FloorVecF16x8, + TruncVecF16x8, + NearestVecF16x8, AbsVecF32x4, NegVecF32x4, SqrtVecF32x4, diff --git a/src/wasm/literal.cpp b/src/wasm/literal.cpp index 6a4614a90..1b84ba53c 100644 --- a/src/wasm/literal.cpp +++ b/src/wasm/literal.cpp @@ -1842,13 +1842,19 @@ Literal Literal::replaceLaneF64x2(const Literal& other, uint8_t index) const { return replace<2, &Literal::getLanesF64x2>(*this, other, index); } +static Literal passThrough(const Literal& literal) { return literal; } +static Literal toFP16(const Literal& literal) { + return literal.convertF32ToF16(); +} + template<int Lanes, LaneArray<Lanes> (Literal::*IntoLanes)() const, - Literal (Literal::*UnaryOp)(void) const> + Literal (Literal::*UnaryOp)(void) const, + Literal (*Convert)(const Literal&) = passThrough> static Literal unary(const Literal& val) { LaneArray<Lanes> lanes = (val.*IntoLanes)(); for (size_t i = 0; i < Lanes; ++i) { - lanes[i] = (lanes[i].*UnaryOp)(); + lanes[i] = Convert((lanes[i].*UnaryOp)()); } return Literal(lanes); } @@ -1885,6 +1891,27 @@ Literal Literal::negI32x4() const { Literal Literal::negI64x2() const { return unary<2, &Literal::getLanesI64x2, &Literal::neg>(*this); } +Literal Literal::absF16x8() const { + return unary<8, &Literal::getLanesF16x8, &Literal::abs, &toFP16>(*this); +} +Literal Literal::negF16x8() const { + return unary<8, &Literal::getLanesF16x8, &Literal::neg, &toFP16>(*this); +} +Literal Literal::sqrtF16x8() const { + return unary<8, &Literal::getLanesF16x8, &Literal::sqrt, &toFP16>(*this); +} +Literal Literal::ceilF16x8() const { + return unary<8, &Literal::getLanesF16x8, &Literal::ceil, &toFP16>(*this); +} +Literal Literal::floorF16x8() const { + return unary<8, &Literal::getLanesF16x8, &Literal::floor, &toFP16>(*this); +} +Literal Literal::truncF16x8() const { + return unary<8, &Literal::getLanesF16x8, &Literal::trunc, &toFP16>(*this); +} +Literal Literal::nearestF16x8() const { + return unary<8, &Literal::getLanesF16x8, &Literal::nearbyint, &toFP16>(*this); +} Literal Literal::absF32x4() const { return unary<4, &Literal::getLanesF32x4, &Literal::abs>(*this); } @@ -2271,11 +2298,6 @@ Literal Literal::geF64x2(const Literal& other) const { other); } -static Literal passThrough(const Literal& literal) { return literal; } -static Literal toFP16(const Literal& literal) { - return literal.convertF32ToF16(); -} - template<int Lanes, LaneArray<Lanes> (Literal::*IntoLanes)() const, Literal (Literal::*BinaryOp)(const Literal&) const, diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp index 06d17fdfb..16a926182 100644 --- a/src/wasm/wasm-binary.cpp +++ b/src/wasm/wasm-binary.cpp @@ -6439,6 +6439,34 @@ bool WasmBinaryReader::maybeVisitSIMDUnary(Expression*& out, uint32_t code) { curr = allocator.alloc<Unary>(); curr->op = BitmaskVecI64x2; break; + case BinaryConsts::F16x8Abs: + curr = allocator.alloc<Unary>(); + curr->op = AbsVecF16x8; + break; + case BinaryConsts::F16x8Neg: + curr = allocator.alloc<Unary>(); + curr->op = NegVecF16x8; + break; + case BinaryConsts::F16x8Sqrt: + curr = allocator.alloc<Unary>(); + curr->op = SqrtVecF16x8; + break; + case BinaryConsts::F16x8Ceil: + curr = allocator.alloc<Unary>(); + curr->op = CeilVecF16x8; + break; + case BinaryConsts::F16x8Floor: + curr = allocator.alloc<Unary>(); + curr->op = FloorVecF16x8; + break; + case BinaryConsts::F16x8Trunc: + curr = allocator.alloc<Unary>(); + curr->op = TruncVecF16x8; + break; + case BinaryConsts::F16x8Nearest: + curr = allocator.alloc<Unary>(); + curr->op = NearestVecF16x8; + break; case BinaryConsts::F32x4Abs: curr = allocator.alloc<Unary>(); curr->op = AbsVecF32x4; diff --git a/src/wasm/wasm-stack.cpp b/src/wasm/wasm-stack.cpp index b7bfea617..59593ddde 100644 --- a/src/wasm/wasm-stack.cpp +++ b/src/wasm/wasm-stack.cpp @@ -1132,6 +1132,28 @@ void BinaryInstWriter::visitUnary(Unary* curr) { o << int8_t(BinaryConsts::SIMDPrefix) << U32LEB(BinaryConsts::I64x2Bitmask); break; + case AbsVecF16x8: + o << int8_t(BinaryConsts::SIMDPrefix) << U32LEB(BinaryConsts::F16x8Abs); + break; + case NegVecF16x8: + o << int8_t(BinaryConsts::SIMDPrefix) << U32LEB(BinaryConsts::F16x8Neg); + break; + case SqrtVecF16x8: + o << int8_t(BinaryConsts::SIMDPrefix) << U32LEB(BinaryConsts::F16x8Sqrt); + break; + case CeilVecF16x8: + o << int8_t(BinaryConsts::SIMDPrefix) << U32LEB(BinaryConsts::F16x8Ceil); + break; + case FloorVecF16x8: + o << int8_t(BinaryConsts::SIMDPrefix) << U32LEB(BinaryConsts::F16x8Floor); + break; + case TruncVecF16x8: + o << int8_t(BinaryConsts::SIMDPrefix) << U32LEB(BinaryConsts::F16x8Trunc); + break; + case NearestVecF16x8: + o << int8_t(BinaryConsts::SIMDPrefix) + << U32LEB(BinaryConsts::F16x8Nearest); + break; case AbsVecF32x4: o << int8_t(BinaryConsts::SIMDPrefix) << U32LEB(BinaryConsts::F32x4Abs); break; diff --git a/src/wasm/wasm-validator.cpp b/src/wasm/wasm-validator.cpp index f77eeefe7..40726d7cd 100644 --- a/src/wasm/wasm-validator.cpp +++ b/src/wasm/wasm-validator.cpp @@ -2095,6 +2095,17 @@ void FunctionValidator::visitUnary(Unary* curr) { shouldBeEqual( curr->value->type, Type(Type::f64), curr, "expected f64 splat value"); break; + case AbsVecF16x8: + case NegVecF16x8: + case SqrtVecF16x8: + case CeilVecF16x8: + case FloorVecF16x8: + case TruncVecF16x8: + case NearestVecF16x8: + shouldBeTrue(getModule()->features.hasFP16(), + curr, + "FP16 operations require FP16 [--enable-fp16]"); + [[fallthrough]]; case NotVec128: case PopcntVecI8x16: case AbsVecI8x16: diff --git a/src/wasm/wasm.cpp b/src/wasm/wasm.cpp index e768f0dc4..98146dfbc 100644 --- a/src/wasm/wasm.cpp +++ b/src/wasm/wasm.cpp @@ -652,6 +652,13 @@ void Unary::finalize() { case NegVecI16x8: case NegVecI32x4: case NegVecI64x2: + case AbsVecF16x8: + case NegVecF16x8: + case SqrtVecF16x8: + case CeilVecF16x8: + case FloorVecF16x8: + case TruncVecF16x8: + case NearestVecF16x8: case AbsVecF32x4: case NegVecF32x4: case SqrtVecF32x4: diff --git a/test/lit/basic/f16.wast b/test/lit/basic/f16.wast index df3c0ef2d..2e5ac57dd 100644 --- a/test/lit/basic/f16.wast +++ b/test/lit/basic/f16.wast @@ -15,38 +15,42 @@ ;; CHECK-TEXT: (type $0 (func (param v128 v128) (result v128))) - ;; CHECK-TEXT: (type $1 (func (param i32) (result f32))) + ;; CHECK-TEXT: (type $1 (func (param v128) (result v128))) - ;; CHECK-TEXT: (type $2 (func (param i32 f32))) + ;; CHECK-TEXT: (type $2 (func (param i32) (result f32))) - ;; CHECK-TEXT: (type $3 (func (param f32) (result v128))) + ;; CHECK-TEXT: (type $3 (func (param i32 f32))) - ;; CHECK-TEXT: (type $4 (func (param v128) (result f32))) + ;; CHECK-TEXT: (type $4 (func (param f32) (result v128))) - ;; CHECK-TEXT: (type $5 (func (param v128 f32) (result v128))) + ;; CHECK-TEXT: (type $5 (func (param v128) (result f32))) + + ;; CHECK-TEXT: (type $6 (func (param v128 f32) (result v128))) ;; CHECK-TEXT: (memory $0 1 1) - ;; CHECK-TEXT: (func $f32.load_f16 (type $1) (param $0 i32) (result f32) + ;; CHECK-TEXT: (func $f32.load_f16 (type $2) (param $0 i32) (result f32) ;; CHECK-TEXT-NEXT: (f32.load_f16 ;; CHECK-TEXT-NEXT: (local.get $0) ;; CHECK-TEXT-NEXT: ) ;; CHECK-TEXT-NEXT: ) ;; CHECK-BIN: (type $0 (func (param v128 v128) (result v128))) - ;; CHECK-BIN: (type $1 (func (param i32) (result f32))) + ;; CHECK-BIN: (type $1 (func (param v128) (result v128))) + + ;; CHECK-BIN: (type $2 (func (param i32) (result f32))) - ;; CHECK-BIN: (type $2 (func (param i32 f32))) + ;; CHECK-BIN: (type $3 (func (param i32 f32))) - ;; CHECK-BIN: (type $3 (func (param f32) (result v128))) + ;; CHECK-BIN: (type $4 (func (param f32) (result v128))) - ;; CHECK-BIN: (type $4 (func (param v128) (result f32))) + ;; CHECK-BIN: (type $5 (func (param v128) (result f32))) - ;; CHECK-BIN: (type $5 (func (param v128 f32) (result v128))) + ;; CHECK-BIN: (type $6 (func (param v128 f32) (result v128))) ;; CHECK-BIN: (memory $0 1 1) - ;; CHECK-BIN: (func $f32.load_f16 (type $1) (param $0 i32) (result f32) + ;; CHECK-BIN: (func $f32.load_f16 (type $2) (param $0 i32) (result f32) ;; CHECK-BIN-NEXT: (f32.load_f16 ;; CHECK-BIN-NEXT: (local.get $0) ;; CHECK-BIN-NEXT: ) @@ -56,13 +60,13 @@ (local.get $0) ) ) - ;; CHECK-TEXT: (func $f32.store_f16 (type $2) (param $0 i32) (param $1 f32) + ;; CHECK-TEXT: (func $f32.store_f16 (type $3) (param $0 i32) (param $1 f32) ;; CHECK-TEXT-NEXT: (f32.store_f16 ;; CHECK-TEXT-NEXT: (local.get $0) ;; CHECK-TEXT-NEXT: (local.get $1) ;; CHECK-TEXT-NEXT: ) ;; CHECK-TEXT-NEXT: ) - ;; CHECK-BIN: (func $f32.store_f16 (type $2) (param $0 i32) (param $1 f32) + ;; CHECK-BIN: (func $f32.store_f16 (type $3) (param $0 i32) (param $1 f32) ;; CHECK-BIN-NEXT: (f32.store_f16 ;; CHECK-BIN-NEXT: (local.get $0) ;; CHECK-BIN-NEXT: (local.get $1) @@ -75,12 +79,12 @@ ) ) - ;; CHECK-TEXT: (func $f16x8.splat (type $3) (param $0 f32) (result v128) + ;; CHECK-TEXT: (func $f16x8.splat (type $4) (param $0 f32) (result v128) ;; CHECK-TEXT-NEXT: (f16x8.splat ;; CHECK-TEXT-NEXT: (local.get $0) ;; CHECK-TEXT-NEXT: ) ;; CHECK-TEXT-NEXT: ) - ;; CHECK-BIN: (func $f16x8.splat (type $3) (param $0 f32) (result v128) + ;; CHECK-BIN: (func $f16x8.splat (type $4) (param $0 f32) (result v128) ;; CHECK-BIN-NEXT: (f16x8.splat ;; CHECK-BIN-NEXT: (local.get $0) ;; CHECK-BIN-NEXT: ) @@ -91,12 +95,12 @@ ) ) - ;; CHECK-TEXT: (func $f16x8.extract_lane (type $4) (param $0 v128) (result f32) + ;; CHECK-TEXT: (func $f16x8.extract_lane (type $5) (param $0 v128) (result f32) ;; CHECK-TEXT-NEXT: (f16x8.extract_lane 0 ;; CHECK-TEXT-NEXT: (local.get $0) ;; CHECK-TEXT-NEXT: ) ;; CHECK-TEXT-NEXT: ) - ;; CHECK-BIN: (func $f16x8.extract_lane (type $4) (param $0 v128) (result f32) + ;; CHECK-BIN: (func $f16x8.extract_lane (type $5) (param $0 v128) (result f32) ;; CHECK-BIN-NEXT: (f16x8.extract_lane 0 ;; CHECK-BIN-NEXT: (local.get $0) ;; CHECK-BIN-NEXT: ) @@ -107,13 +111,13 @@ ) ) - ;; CHECK-TEXT: (func $f16x8.replace_lane (type $5) (param $0 v128) (param $1 f32) (result v128) + ;; CHECK-TEXT: (func $f16x8.replace_lane (type $6) (param $0 v128) (param $1 f32) (result v128) ;; CHECK-TEXT-NEXT: (f16x8.replace_lane 0 ;; CHECK-TEXT-NEXT: (local.get $0) ;; CHECK-TEXT-NEXT: (local.get $1) ;; CHECK-TEXT-NEXT: ) ;; CHECK-TEXT-NEXT: ) - ;; CHECK-BIN: (func $f16x8.replace_lane (type $5) (param $0 v128) (param $1 f32) (result v128) + ;; CHECK-BIN: (func $f16x8.replace_lane (type $6) (param $0 v128) (param $1 f32) (result v128) ;; CHECK-BIN-NEXT: (f16x8.replace_lane 0 ;; CHECK-BIN-NEXT: (local.get $0) ;; CHECK-BIN-NEXT: (local.get $1) @@ -377,47 +381,154 @@ (local.get $1) ) ) + ;; CHECK-TEXT: (func $f16x8.abs (type $1) (param $0 v128) (result v128) + ;; CHECK-TEXT-NEXT: (f16x8.abs + ;; CHECK-TEXT-NEXT: (local.get $0) + ;; CHECK-TEXT-NEXT: ) + ;; CHECK-TEXT-NEXT: ) + ;; CHECK-BIN: (func $f16x8.abs (type $1) (param $0 v128) (result v128) + ;; CHECK-BIN-NEXT: (f16x8.abs + ;; CHECK-BIN-NEXT: (local.get $0) + ;; CHECK-BIN-NEXT: ) + ;; CHECK-BIN-NEXT: ) + (func $f16x8.abs (param $0 v128) (result v128) + (f16x8.abs + (local.get $0) + ) + ) + ;; CHECK-TEXT: (func $f16x8.neg (type $1) (param $0 v128) (result v128) + ;; CHECK-TEXT-NEXT: (f16x8.neg + ;; CHECK-TEXT-NEXT: (local.get $0) + ;; CHECK-TEXT-NEXT: ) + ;; CHECK-TEXT-NEXT: ) + ;; CHECK-BIN: (func $f16x8.neg (type $1) (param $0 v128) (result v128) + ;; CHECK-BIN-NEXT: (f16x8.neg + ;; CHECK-BIN-NEXT: (local.get $0) + ;; CHECK-BIN-NEXT: ) + ;; CHECK-BIN-NEXT: ) + (func $f16x8.neg (param $0 v128) (result v128) + (f16x8.neg + (local.get $0) + ) + ) + ;; CHECK-TEXT: (func $f16x8.sqrt (type $1) (param $0 v128) (result v128) + ;; CHECK-TEXT-NEXT: (f16x8.sqrt + ;; CHECK-TEXT-NEXT: (local.get $0) + ;; CHECK-TEXT-NEXT: ) + ;; CHECK-TEXT-NEXT: ) + ;; CHECK-BIN: (func $f16x8.sqrt (type $1) (param $0 v128) (result v128) + ;; CHECK-BIN-NEXT: (f16x8.sqrt + ;; CHECK-BIN-NEXT: (local.get $0) + ;; CHECK-BIN-NEXT: ) + ;; CHECK-BIN-NEXT: ) + (func $f16x8.sqrt (param $0 v128) (result v128) + (f16x8.sqrt + (local.get $0) + ) + ) + ;; CHECK-TEXT: (func $f16x8.ceil (type $1) (param $0 v128) (result v128) + ;; CHECK-TEXT-NEXT: (f16x8.ceil + ;; CHECK-TEXT-NEXT: (local.get $0) + ;; CHECK-TEXT-NEXT: ) + ;; CHECK-TEXT-NEXT: ) + ;; CHECK-BIN: (func $f16x8.ceil (type $1) (param $0 v128) (result v128) + ;; CHECK-BIN-NEXT: (f16x8.ceil + ;; CHECK-BIN-NEXT: (local.get $0) + ;; CHECK-BIN-NEXT: ) + ;; CHECK-BIN-NEXT: ) + (func $f16x8.ceil (param $0 v128) (result v128) + (f16x8.ceil + (local.get $0) + ) + ) + ;; CHECK-TEXT: (func $f16x8.floor (type $1) (param $0 v128) (result v128) + ;; CHECK-TEXT-NEXT: (f16x8.floor + ;; CHECK-TEXT-NEXT: (local.get $0) + ;; CHECK-TEXT-NEXT: ) + ;; CHECK-TEXT-NEXT: ) + ;; CHECK-BIN: (func $f16x8.floor (type $1) (param $0 v128) (result v128) + ;; CHECK-BIN-NEXT: (f16x8.floor + ;; CHECK-BIN-NEXT: (local.get $0) + ;; CHECK-BIN-NEXT: ) + ;; CHECK-BIN-NEXT: ) + (func $f16x8.floor (param $0 v128) (result v128) + (f16x8.floor + (local.get $0) + ) + ) + ;; CHECK-TEXT: (func $f16x8.trunc (type $1) (param $0 v128) (result v128) + ;; CHECK-TEXT-NEXT: (f16x8.trunc + ;; CHECK-TEXT-NEXT: (local.get $0) + ;; CHECK-TEXT-NEXT: ) + ;; CHECK-TEXT-NEXT: ) + ;; CHECK-BIN: (func $f16x8.trunc (type $1) (param $0 v128) (result v128) + ;; CHECK-BIN-NEXT: (f16x8.trunc + ;; CHECK-BIN-NEXT: (local.get $0) + ;; CHECK-BIN-NEXT: ) + ;; CHECK-BIN-NEXT: ) + (func $f16x8.trunc (param $0 v128) (result v128) + (f16x8.trunc + (local.get $0) + ) + ) + ;; CHECK-TEXT: (func $f16x8.nearest (type $1) (param $0 v128) (result v128) + ;; CHECK-TEXT-NEXT: (f16x8.nearest + ;; CHECK-TEXT-NEXT: (local.get $0) + ;; CHECK-TEXT-NEXT: ) + ;; CHECK-TEXT-NEXT: ) + ;; CHECK-BIN: (func $f16x8.nearest (type $1) (param $0 v128) (result v128) + ;; CHECK-BIN-NEXT: (f16x8.nearest + ;; CHECK-BIN-NEXT: (local.get $0) + ;; CHECK-BIN-NEXT: ) + ;; CHECK-BIN-NEXT: ) + (func $f16x8.nearest (param $0 v128) (result v128) + (f16x8.nearest + (local.get $0) + ) + ) ) ;; CHECK-BIN-NODEBUG: (type $0 (func (param v128 v128) (result v128))) -;; CHECK-BIN-NODEBUG: (type $1 (func (param i32) (result f32))) +;; CHECK-BIN-NODEBUG: (type $1 (func (param v128) (result v128))) -;; CHECK-BIN-NODEBUG: (type $2 (func (param i32 f32))) +;; CHECK-BIN-NODEBUG: (type $2 (func (param i32) (result f32))) -;; CHECK-BIN-NODEBUG: (type $3 (func (param f32) (result v128))) +;; CHECK-BIN-NODEBUG: (type $3 (func (param i32 f32))) -;; CHECK-BIN-NODEBUG: (type $4 (func (param v128) (result f32))) +;; CHECK-BIN-NODEBUG: (type $4 (func (param f32) (result v128))) -;; CHECK-BIN-NODEBUG: (type $5 (func (param v128 f32) (result v128))) +;; CHECK-BIN-NODEBUG: (type $5 (func (param v128) (result f32))) + +;; CHECK-BIN-NODEBUG: (type $6 (func (param v128 f32) (result v128))) ;; CHECK-BIN-NODEBUG: (memory $0 1 1) -;; CHECK-BIN-NODEBUG: (func $0 (type $1) (param $0 i32) (result f32) +;; CHECK-BIN-NODEBUG: (func $0 (type $2) (param $0 i32) (result f32) ;; CHECK-BIN-NODEBUG-NEXT: (f32.load_f16 ;; CHECK-BIN-NODEBUG-NEXT: (local.get $0) ;; CHECK-BIN-NODEBUG-NEXT: ) ;; CHECK-BIN-NODEBUG-NEXT: ) -;; CHECK-BIN-NODEBUG: (func $1 (type $2) (param $0 i32) (param $1 f32) +;; CHECK-BIN-NODEBUG: (func $1 (type $3) (param $0 i32) (param $1 f32) ;; CHECK-BIN-NODEBUG-NEXT: (f32.store_f16 ;; CHECK-BIN-NODEBUG-NEXT: (local.get $0) ;; CHECK-BIN-NODEBUG-NEXT: (local.get $1) ;; CHECK-BIN-NODEBUG-NEXT: ) ;; CHECK-BIN-NODEBUG-NEXT: ) -;; CHECK-BIN-NODEBUG: (func $2 (type $3) (param $0 f32) (result v128) +;; CHECK-BIN-NODEBUG: (func $2 (type $4) (param $0 f32) (result v128) ;; CHECK-BIN-NODEBUG-NEXT: (f16x8.splat ;; CHECK-BIN-NODEBUG-NEXT: (local.get $0) ;; CHECK-BIN-NODEBUG-NEXT: ) ;; CHECK-BIN-NODEBUG-NEXT: ) -;; CHECK-BIN-NODEBUG: (func $3 (type $4) (param $0 v128) (result f32) +;; CHECK-BIN-NODEBUG: (func $3 (type $5) (param $0 v128) (result f32) ;; CHECK-BIN-NODEBUG-NEXT: (f16x8.extract_lane 0 ;; CHECK-BIN-NODEBUG-NEXT: (local.get $0) ;; CHECK-BIN-NODEBUG-NEXT: ) ;; CHECK-BIN-NODEBUG-NEXT: ) -;; CHECK-BIN-NODEBUG: (func $4 (type $5) (param $0 v128) (param $1 f32) (result v128) +;; CHECK-BIN-NODEBUG: (func $4 (type $6) (param $0 v128) (param $1 f32) (result v128) ;; CHECK-BIN-NODEBUG-NEXT: (f16x8.replace_lane 0 ;; CHECK-BIN-NODEBUG-NEXT: (local.get $0) ;; CHECK-BIN-NODEBUG-NEXT: (local.get $1) @@ -521,3 +632,45 @@ ;; CHECK-BIN-NODEBUG-NEXT: (local.get $1) ;; CHECK-BIN-NODEBUG-NEXT: ) ;; CHECK-BIN-NODEBUG-NEXT: ) + +;; CHECK-BIN-NODEBUG: (func $19 (type $1) (param $0 v128) (result v128) +;; CHECK-BIN-NODEBUG-NEXT: (f16x8.abs +;; CHECK-BIN-NODEBUG-NEXT: (local.get $0) +;; CHECK-BIN-NODEBUG-NEXT: ) +;; CHECK-BIN-NODEBUG-NEXT: ) + +;; CHECK-BIN-NODEBUG: (func $20 (type $1) (param $0 v128) (result v128) +;; CHECK-BIN-NODEBUG-NEXT: (f16x8.neg +;; CHECK-BIN-NODEBUG-NEXT: (local.get $0) +;; CHECK-BIN-NODEBUG-NEXT: ) +;; CHECK-BIN-NODEBUG-NEXT: ) + +;; CHECK-BIN-NODEBUG: (func $21 (type $1) (param $0 v128) (result v128) +;; CHECK-BIN-NODEBUG-NEXT: (f16x8.sqrt +;; CHECK-BIN-NODEBUG-NEXT: (local.get $0) +;; CHECK-BIN-NODEBUG-NEXT: ) +;; CHECK-BIN-NODEBUG-NEXT: ) + +;; CHECK-BIN-NODEBUG: (func $22 (type $1) (param $0 v128) (result v128) +;; CHECK-BIN-NODEBUG-NEXT: (f16x8.ceil +;; CHECK-BIN-NODEBUG-NEXT: (local.get $0) +;; CHECK-BIN-NODEBUG-NEXT: ) +;; CHECK-BIN-NODEBUG-NEXT: ) + +;; CHECK-BIN-NODEBUG: (func $23 (type $1) (param $0 v128) (result v128) +;; CHECK-BIN-NODEBUG-NEXT: (f16x8.floor +;; CHECK-BIN-NODEBUG-NEXT: (local.get $0) +;; CHECK-BIN-NODEBUG-NEXT: ) +;; CHECK-BIN-NODEBUG-NEXT: ) + +;; CHECK-BIN-NODEBUG: (func $24 (type $1) (param $0 v128) (result v128) +;; CHECK-BIN-NODEBUG-NEXT: (f16x8.trunc +;; CHECK-BIN-NODEBUG-NEXT: (local.get $0) +;; CHECK-BIN-NODEBUG-NEXT: ) +;; CHECK-BIN-NODEBUG-NEXT: ) + +;; CHECK-BIN-NODEBUG: (func $25 (type $1) (param $0 v128) (result v128) +;; CHECK-BIN-NODEBUG-NEXT: (f16x8.nearest +;; CHECK-BIN-NODEBUG-NEXT: (local.get $0) +;; CHECK-BIN-NODEBUG-NEXT: ) +;; CHECK-BIN-NODEBUG-NEXT: ) diff --git a/test/spec/f16.wast b/test/spec/f16.wast index 70d0043f7..09ee9328b 100644 --- a/test/spec/f16.wast +++ b/test/spec/f16.wast @@ -25,6 +25,13 @@ (func (export "f16x8.max") (param $0 v128) (param $1 v128) (result v128) (f16x8.max (local.get $0) (local.get $1))) (func (export "f16x8.pmin") (param $0 v128) (param $1 v128) (result v128) (f16x8.pmin (local.get $0) (local.get $1))) (func (export "f16x8.pmax") (param $0 v128) (param $1 v128) (result v128) (f16x8.pmax (local.get $0) (local.get $1))) + (func (export "f16x8.abs") (param $0 v128) (result v128) (f16x8.abs (local.get $0))) + (func (export "f16x8.neg") (param $0 v128) (result v128) (f16x8.neg (local.get $0))) + (func (export "f16x8.sqrt") (param $0 v128) (result v128) (f16x8.sqrt (local.get $0))) + (func (export "f16x8.ceil") (param $0 v128) (result v128) (f16x8.ceil (local.get $0))) + (func (export "f16x8.floor") (param $0 v128) (result v128) (f16x8.floor (local.get $0))) + (func (export "f16x8.trunc") (param $0 v128) (result v128) (f16x8.trunc (local.get $0))) + (func (export "f16x8.nearest") (param $0 v128) (result v128) (f16x8.nearest (local.get $0))) ) (assert_return (invoke "f32.load_f16") (f32.const 42.0)) @@ -147,3 +154,36 @@ (v128.const i16x8 0x5140 0xfe00 0x7c00 0x3e00 0 0x3c00 0 0x3c00)) ;; nan -nan inf 1.5 0 1 1 1 (v128.const i16x8 0x7e00 0xfe00 0x7c00 0x3e00 0 0x3c00 0x3c00 0x3c00)) + +;; unary arithmetic +(assert_return (invoke "f16x8.abs" + ;; nan -nan inf -inf -1 1 1.5 1.2... + (v128.const i16x8 0x7e00 0xfe00 0x7c00 0xfc00 0xbc00 0x3c00 0x3e00 0x3ccd)) + ;; nan nan inf inf 1 1 1.5 1.2... + (v128.const i16x8 0x7e00 0x7e00 0x7c00 0x7c00 0x3c00 0x3c00 0x3e00 0x3ccd)) +(assert_return (invoke "f16x8.neg" + ;; nan -nan inf -inf -1 1 1.5 1.2... + (v128.const i16x8 0x7e00 0xfe00 0x7c00 0xfc00 0xbc00 0x3c00 0x3e00 0x3ccd)) + ;; -nan nan -inf inf 1 -1 -1.5 -1.2... + (v128.const i16x8 0xfe00 0x7e00 0xfc00 0x7c00 0x3c00 0xbc00 0xbe00 0xbccd)) +;; XXX Avoid tests that return -nan since it's non-deterministic. +(assert_return (invoke "f16x8.sqrt" + ;; nan 0 inf 4 16 1 1.5 1.2... + (v128.const i16x8 0x7e00 0 0x7c00 0x4400 0x4c00 0x3c00 0x3e00 0x3ccd)) + ;; nan 0 inf 2 4 1 1.22.. 1.09... + (v128.const i16x8 0x7e00 0 0x7c00 0x4000 0x4400 0x3c00 0x3ce6 0x3c62)) +(assert_return (invoke "f16x8.ceil" + ;; nan 0 inf -inf -1 1 1.5 1.2... + (v128.const i16x8 0x7e00 0 0x7c00 0xfc00 0xbc00 0x3c00 0x3e00 0x3ccd)) + ;; nan 0 inf -inf -1 1 2 2 + (v128.const i16x8 0x7e00 0 0x7c00 0xfc00 0xbc00 0x3c00 0x4000 0x4000)) +(assert_return (invoke "f16x8.floor" + ;; nan 0 inf -inf -1 1 1.5 1.2... + (v128.const i16x8 0x7e00 0 0x7c00 0xfc00 0xbc00 0x3c00 0x3e00 0x3ccd)) + ;; nan 0 inf -inf -1 1 1 1 + (v128.const i16x8 0x7e00 0 0x7c00 0xfc00 0xbc00 0x3c00 0x3c00 0x3c00)) +(assert_return (invoke "f16x8.nearest" + ;; nan 0 inf -inf -1 1 1.5 1.2... + (v128.const i16x8 0x7e00 0 0x7c00 0xfc00 0xbc00 0x3c00 0x3e00 0x3ccd)) + ;; nan 0 inf -inf -1 1 2 1 + (v128.const i16x8 0x7e00 0 0x7c00 0xfc00 0xbc00 0x3c00 0x4000 0x3c00)) |