Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions scripts/gen-s-parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -549,6 +549,7 @@
("i16x8.trunc_sat_f16x8_u", "makeUnary(UnaryOp::TruncSatUVecF16x8ToVecI16x8)"),
("f16x8.convert_i16x8_s", "makeUnary(UnaryOp::ConvertSVecI16x8ToVecF16x8)"),
("f16x8.convert_i16x8_u", "makeUnary(UnaryOp::ConvertUVecI16x8ToVecF16x8)"),
("f32x4.promote_low_f16x8", "makeUnary(UnaryOp::PromoteLowVecF16x8ToVecF32x4)"),
("f16x8.madd", "makeSIMDTernary(SIMDTernaryOp::MaddVecF16x8)"),
("f16x8.nmadd", "makeSIMDTernary(SIMDTernaryOp::NmaddVecF16x8)"),

Expand Down
3 changes: 3 additions & 0 deletions src/binaryen-c.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1021,6 +1021,9 @@ BinaryenOp BinaryenDemoteZeroVecF64x2ToVecF32x4(void) {
BinaryenOp BinaryenPromoteLowVecF32x4ToVecF64x2(void) {
return PromoteLowVecF32x4ToVecF64x2;
}
BinaryenOp BinaryenPromoteLowVecF16x8ToVecF32x4(void) {
return PromoteLowVecF16x8ToVecF32x4;
}
BinaryenOp BinaryenRelaxedTruncSVecF32x4ToVecI32x4(void) {
return RelaxedTruncSVecF32x4ToVecI32x4;
}
Expand Down
1 change: 1 addition & 0 deletions src/binaryen-c.h
Original file line number Diff line number Diff line change
Expand Up @@ -684,6 +684,7 @@ BINARYEN_API BinaryenOp BinaryenTruncSatZeroSVecF64x2ToVecI32x4(void);
BINARYEN_API BinaryenOp BinaryenTruncSatZeroUVecF64x2ToVecI32x4(void);
BINARYEN_API BinaryenOp BinaryenDemoteZeroVecF64x2ToVecF32x4(void);
BINARYEN_API BinaryenOp BinaryenPromoteLowVecF32x4ToVecF64x2(void);
BINARYEN_API BinaryenOp BinaryenPromoteLowVecF16x8ToVecF32x4(void);
BINARYEN_API BinaryenOp BinaryenRelaxedTruncSVecF32x4ToVecI32x4(void);
BINARYEN_API BinaryenOp BinaryenRelaxedTruncUVecF32x4ToVecI32x4(void);
BINARYEN_API BinaryenOp BinaryenRelaxedTruncZeroSVecF64x2ToVecI32x4(void);
Expand Down
29 changes: 20 additions & 9 deletions src/gen-s-parser.inc
Original file line number Diff line number Diff line change
Expand Up @@ -1127,16 +1127,27 @@ switch (buf[0]) {
}
}
case 'p': {
switch (buf[8]) {
case 'a':
if (op == "f32x4.pmax"sv) {
CHECK_ERR(makeBinary(ctx, pos, annotations, BinaryOp::PMaxVecF32x4));
return Ok{};
switch (buf[7]) {
case 'm': {
switch (buf[8]) {
case 'a':
if (op == "f32x4.pmax"sv) {
CHECK_ERR(makeBinary(ctx, pos, annotations, BinaryOp::PMaxVecF32x4));
return Ok{};
}
goto parse_error;
case 'i':
if (op == "f32x4.pmin"sv) {
CHECK_ERR(makeBinary(ctx, pos, annotations, BinaryOp::PMinVecF32x4));
return Ok{};
}
goto parse_error;
default: goto parse_error;
}
goto parse_error;
case 'i':
if (op == "f32x4.pmin"sv) {
CHECK_ERR(makeBinary(ctx, pos, annotations, BinaryOp::PMinVecF32x4));
}
case 'r':
if (op == "f32x4.promote_low_f16x8"sv) {
CHECK_ERR(makeUnary(ctx, pos, annotations, UnaryOp::PromoteLowVecF16x8ToVecF32x4));
return Ok{};
}
goto parse_error;
Expand Down
1 change: 1 addition & 0 deletions src/ir/child-typer.h
Original file line number Diff line number Diff line change
Expand Up @@ -447,6 +447,7 @@ template<typename Subtype> struct ChildTyper : OverriddenVisitor<Subtype> {
case TruncSatUVecF16x8ToVecI16x8:
case ConvertSVecI16x8ToVecF16x8:
case ConvertUVecI16x8ToVecF16x8:
case PromoteLowVecF16x8ToVecF32x4:
case AnyTrueVec128:
case AllTrueVecI8x16:
case AllTrueVecI16x8:
Expand Down
1 change: 1 addition & 0 deletions src/ir/cost.h
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,7 @@ struct CostAnalyzer : public OverriddenVisitor<CostAnalyzer, CostType> {
case TruncSatUVecF16x8ToVecI16x8:
case ConvertSVecI16x8ToVecF16x8:
case ConvertUVecI16x8ToVecF16x8:
case PromoteLowVecF16x8ToVecF32x4:
ret = 1;
break;
case InvalidUnary:
Expand Down
1 change: 1 addition & 0 deletions src/literal.h
Original file line number Diff line number Diff line change
Expand Up @@ -723,6 +723,7 @@ class Literal {
Literal truncSatZeroUToI32x4() const;
Literal demoteZeroToF32x4() const;
Literal promoteLowToF64x2() const;
Literal promoteLowF16x8ToF32x4() const;
Literal truncSatToSI16x8() const;
Literal truncSatToUI16x8() const;
Literal convertSToF16x8() const;
Expand Down
3 changes: 3 additions & 0 deletions src/passes/Print.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1401,6 +1401,9 @@ struct PrintExpressionContents
case ConvertUVecI16x8ToVecF16x8:
o << "f16x8.convert_i16x8_u";
break;
case PromoteLowVecF16x8ToVecF32x4:
o << "f32x4.promote_low_f16x8";
break;
case InvalidUnary:
WASM_UNREACHABLE("unvalid unary operator");
}
Expand Down
3 changes: 2 additions & 1 deletion src/tools/fuzzing/fuzzing.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4526,7 +4526,8 @@ Expression* TranslateToFuzzReader::makeUnary(Type type) {
TruncSatSVecF16x8ToVecI16x8,
TruncSatUVecF16x8ToVecI16x8,
ConvertSVecI16x8ToVecF16x8,
ConvertUVecI16x8ToVecF16x8)),
ConvertUVecI16x8ToVecF16x8,
PromoteLowVecF16x8ToVecF32x4)),
make(Type::v128)});
}
WASM_UNREACHABLE("invalid value");
Expand Down
1 change: 1 addition & 0 deletions src/wasm-binary.h
Original file line number Diff line number Diff line change
Expand Up @@ -1126,6 +1126,7 @@ enum ASTNodes {
I16x8TruncSatF16x8U = 0x146,
F16x8ConvertI16x8S = 0x147,
F16x8ConvertI16x8U = 0x148,
F32x4PromoteLowF16x8 = 0x14b,

// bulk memory opcodes

Expand Down
2 changes: 2 additions & 0 deletions src/wasm-interpreter.h
Original file line number Diff line number Diff line change
Expand Up @@ -1164,6 +1164,8 @@ class ExpressionRunner : public OverriddenVisitor<SubType, Flow> {
return value.convertSToF16x8();
case ConvertUVecI16x8ToVecF16x8:
return value.convertUToF16x8();
case PromoteLowVecF16x8ToVecF32x4:
return value.promoteLowF16x8ToF32x4();
case InvalidUnary:
WASM_UNREACHABLE("invalid unary op");
}
Expand Down
1 change: 1 addition & 0 deletions src/wasm.h
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,7 @@ enum UnaryOp {
TruncSatUVecF16x8ToVecI16x8,
ConvertSVecI16x8ToVecF16x8,
ConvertUVecI16x8ToVecF16x8,
PromoteLowVecF16x8ToVecF32x4,

InvalidUnary
};
Expand Down
8 changes: 8 additions & 0 deletions src/wasm/literal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2915,6 +2915,14 @@ Literal Literal::demoteZeroToF32x4() const {
Literal Literal::promoteLowToF64x2() const {
return extendF32<LaneOrder::Low>(*this);
}
Literal Literal::promoteLowF16x8ToF32x4() const {
auto lanes = getLanesF16x8();
LaneArray<4> result;
for (size_t i = 0; i < 4; ++i) {
result[i] = lanes[i];
}
return Literal(result);
}

Literal Literal::swizzleI8x16(const Literal& other) const {
auto lanes = getLanesUI8x16();
Expand Down
2 changes: 2 additions & 0 deletions src/wasm/wasm-binary.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4474,6 +4474,8 @@ Result<> WasmBinaryReader::readInst() {
return builder.makeUnary(ConvertSVecI16x8ToVecF16x8);
case BinaryConsts::F16x8ConvertI16x8U:
return builder.makeUnary(ConvertUVecI16x8ToVecF16x8);
case BinaryConsts::F32x4PromoteLowF16x8:
return builder.makeUnary(PromoteLowVecF16x8ToVecF32x4);
case BinaryConsts::I8x16ExtractLaneS:
return builder.makeSIMDExtract(ExtractLaneSVecI8x16,
getLaneIndex(16));
Expand Down
4 changes: 4 additions & 0 deletions src/wasm/wasm-stack.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1459,6 +1459,10 @@ void BinaryInstWriter::visitUnary(Unary* curr) {
o << static_cast<int8_t>(BinaryConsts::SIMDPrefix)
<< U32LEB(BinaryConsts::F16x8ConvertI16x8U);
break;
case PromoteLowVecF16x8ToVecF32x4:
o << static_cast<int8_t>(BinaryConsts::SIMDPrefix)
<< U32LEB(BinaryConsts::F32x4PromoteLowF16x8);
break;
case InvalidUnary:
WASM_UNREACHABLE("invalid unary op");
}
Expand Down
1 change: 1 addition & 0 deletions src/wasm/wasm-validator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2380,6 +2380,7 @@ void FunctionValidator::visitUnary(Unary* curr) {
case TruncSatZeroUVecF64x2ToVecI32x4:
case DemoteZeroVecF64x2ToVecF32x4:
case PromoteLowVecF32x4ToVecF64x2:
case PromoteLowVecF16x8ToVecF32x4:
case RelaxedTruncSVecF32x4ToVecI32x4:
case RelaxedTruncUVecF32x4ToVecI32x4:
case RelaxedTruncZeroSVecF64x2ToVecI32x4:
Expand Down
1 change: 1 addition & 0 deletions src/wasm/wasm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -714,6 +714,7 @@ void Unary::finalize() {
case TruncSatUVecF16x8ToVecI16x8:
case ConvertSVecI16x8ToVecF16x8:
case ConvertUVecI16x8ToVecF16x8:
case PromoteLowVecF16x8ToVecF32x4:
type = Type::v128;
break;
case AnyTrueVec128:
Expand Down
22 changes: 22 additions & 0 deletions test/lit/basic/f16.wast
Original file line number Diff line number Diff line change
Expand Up @@ -597,6 +597,22 @@
(local.get $0)
)
)

;; CHECK-TEXT: (func $f32x4.promote_low_f16x8 (type $1) (param $0 v128) (result v128)
;; CHECK-TEXT-NEXT: (f32x4.promote_low_f16x8
;; CHECK-TEXT-NEXT: (local.get $0)
;; CHECK-TEXT-NEXT: )
;; CHECK-TEXT-NEXT: )
;; CHECK-BIN: (func $f32x4.promote_low_f16x8 (type $1) (param $0 v128) (result v128)
;; CHECK-BIN-NEXT: (f32x4.promote_low_f16x8
;; CHECK-BIN-NEXT: (local.get $0)
;; CHECK-BIN-NEXT: )
;; CHECK-BIN-NEXT: )
(func $f32x4.promote_low_f16x8 (param $0 v128) (result v128)
(f32x4.promote_low_f16x8
(local.get $0)
)
)
)
;; CHECK-BIN-NODEBUG: (type $0 (func (param v128 v128) (result v128)))

Expand Down Expand Up @@ -827,3 +843,9 @@
;; CHECK-BIN-NODEBUG-NEXT: (local.get $0)
;; CHECK-BIN-NODEBUG-NEXT: )
;; CHECK-BIN-NODEBUG-NEXT: )

;; CHECK-BIN-NODEBUG: (func $32 (type $1) (param $0 v128) (result v128)
;; CHECK-BIN-NODEBUG-NEXT: (f32x4.promote_low_f16x8
;; CHECK-BIN-NODEBUG-NEXT: (local.get $0)
;; CHECK-BIN-NODEBUG-NEXT: )
;; CHECK-BIN-NODEBUG-NEXT: )
21 changes: 21 additions & 0 deletions test/spec/f16.wast
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
(func (export "i16x8.trunc_sat_f16x8_u") (param $0 v128) (result v128) (i16x8.trunc_sat_f16x8_u (local.get $0)))
(func (export "f16x8.convert_i16x8_s") (param $0 v128) (result v128) (f16x8.convert_i16x8_s (local.get $0)))
(func (export "f16x8.convert_i16x8_u") (param $0 v128) (result v128) (f16x8.convert_i16x8_u (local.get $0)))
(func (export "f32x4.promote_low_f16x8") (param $0 v128) (result v128) (f32x4.promote_low_f16x8 (local.get $0)))
;; Multiple operation tests:
(func (export "splat_replace") (result v128) (f16x8.replace_lane 0 (f16x8.splat (f32.const 1)) (f32.const 99))
)
Expand Down Expand Up @@ -247,3 +248,23 @@
(v128.const i16x8 0 1 -1 -32 0 0 0 0))
;; 1 inf 65504
(v128.const i16x8 0 0x3c00 0x7c00 0x7bff 0 0 0 0))

(assert_return (invoke "f32x4.promote_low_f16x8"
;; 1.0 -1.0 2.0 -2.0 0 0 0 0
(v128.const i16x8 0x3c00 0xbc00 0x4000 0xc000 0 0 0 0))
;; 1.0 -1.0 2.0 -2.0
(v128.const i32x4 0x3f800000 0xbf800000 0x40000000 0xc0000000))

;; Edge cases: Infinities, NaNs, Zeros
(assert_return (invoke "f32x4.promote_low_f16x8"
;; inf -inf nan -0.0 0 0 0 0
(v128.const i16x8 0x7c00 0xfc00 0x7e00 0x8000 0 0 0 0))
;; inf -inf nan -0.0
(v128.const i32x4 0x7f800000 0xff800000 0x7fc00000 0x80000000))

;; Edge cases: Denormal
(assert_return (invoke "f32x4.promote_low_f16x8"
;; denormal
(v128.const i16x8 0x0001 0 0 0 0 0 0 0))
;; 2^-24
(v128.const i32x4 0x33800000 0 0 0))
Loading