summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/gen-s-parser.inc23
-rw-r--r--src/ir/child-typer.h2
-rw-r--r--src/ir/cost.h1
-rw-r--r--src/literal.h4
-rw-r--r--src/passes/Print.cpp9
-rw-r--r--src/tools/fuzzing/fuzzing.cpp1
-rw-r--r--src/wasm-binary.h3
-rw-r--r--src/wasm-interpreter.h6
-rw-r--r--src/wasm.h5
-rw-r--r--src/wasm/literal.cpp19
-rw-r--r--src/wasm/wasm-binary.cpp14
-rw-r--r--src/wasm/wasm-stack.cpp9
-rw-r--r--src/wasm/wasm-validator.cpp9
-rw-r--r--src/wasm/wasm.cpp2
14 files changed, 107 insertions, 0 deletions
diff --git a/src/gen-s-parser.inc b/src/gen-s-parser.inc
index c54a0de54..33cddcb26 100644
--- a/src/gen-s-parser.inc
+++ b/src/gen-s-parser.inc
@@ -307,6 +307,29 @@ switch (buf[0]) {
}
case 'f': {
switch (buf[1]) {
+ case '1': {
+ switch (buf[6]) {
+ case 'e':
+ if (op == "f16x8.extract_lane"sv) {
+ CHECK_ERR(makeSIMDExtract(ctx, pos, annotations, SIMDExtractOp::ExtractLaneVecF16x8, 8));
+ return Ok{};
+ }
+ goto parse_error;
+ case 'r':
+ if (op == "f16x8.replace_lane"sv) {
+ CHECK_ERR(makeSIMDReplace(ctx, pos, annotations, SIMDReplaceOp::ReplaceLaneVecF16x8, 8));
+ return Ok{};
+ }
+ goto parse_error;
+ case 's':
+ if (op == "f16x8.splat"sv) {
+ CHECK_ERR(makeUnary(ctx, pos, annotations, UnaryOp::SplatVecF16x8));
+ return Ok{};
+ }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
case '3': {
switch (buf[3]) {
case '.': {
diff --git a/src/ir/child-typer.h b/src/ir/child-typer.h
index 5e2dc237d..17717a32c 100644
--- a/src/ir/child-typer.h
+++ b/src/ir/child-typer.h
@@ -228,6 +228,7 @@ template<typename Subtype> struct ChildTyper : OverriddenVisitor<Subtype> {
case ReplaceLaneVecI64x2:
note(&curr->value, Type::i64);
break;
+ case ReplaceLaneVecF16x8:
case ReplaceLaneVecF32x4:
note(&curr->value, Type::f32);
break;
@@ -337,6 +338,7 @@ template<typename Subtype> struct ChildTyper : OverriddenVisitor<Subtype> {
case TruncSatUFloat32ToInt64:
case ReinterpretFloat32:
case PromoteFloat32:
+ case SplatVecF16x8:
case SplatVecF32x4:
note(&curr->value, Type::f32);
break;
diff --git a/src/ir/cost.h b/src/ir/cost.h
index 38c74a203..06512d656 100644
--- a/src/ir/cost.h
+++ b/src/ir/cost.h
@@ -184,6 +184,7 @@ struct CostAnalyzer : public OverriddenVisitor<CostAnalyzer, CostType> {
case SplatVecI16x8:
case SplatVecI32x4:
case SplatVecI64x2:
+ case SplatVecF16x8:
case SplatVecF32x4:
case SplatVecF64x2:
case NotVec128:
diff --git a/src/literal.h b/src/literal.h
index 190fe0eec..63bbf6e74 100644
--- a/src/literal.h
+++ b/src/literal.h
@@ -444,6 +444,7 @@ public:
std::array<Literal, 8> getLanesUI16x8() const;
std::array<Literal, 4> getLanesI32x4() const;
std::array<Literal, 2> getLanesI64x2() const;
+ std::array<Literal, 8> getLanesF16x8() const;
std::array<Literal, 4> getLanesF32x4() const;
std::array<Literal, 2> getLanesF64x2() const;
@@ -463,6 +464,9 @@ public:
Literal splatI64x2() const;
Literal extractLaneI64x2(uint8_t index) const;
Literal replaceLaneI64x2(const Literal& other, uint8_t index) const;
+ Literal splatF16x8() const;
+ Literal extractLaneF16x8(uint8_t index) const;
+ Literal replaceLaneF16x8(const Literal& other, uint8_t index) const;
Literal splatF32x4() const;
Literal extractLaneF32x4(uint8_t index) const;
Literal replaceLaneF32x4(const Literal& other, uint8_t index) const;
diff --git a/src/passes/Print.cpp b/src/passes/Print.cpp
index aca43924d..fd22f1b71 100644
--- a/src/passes/Print.cpp
+++ b/src/passes/Print.cpp
@@ -703,6 +703,9 @@ struct PrintExpressionContents
case ExtractLaneVecI64x2:
o << "i64x2.extract_lane";
break;
+ case ExtractLaneVecF16x8:
+ o << "f16x8.extract_lane";
+ break;
case ExtractLaneVecF32x4:
o << "f32x4.extract_lane";
break;
@@ -728,6 +731,9 @@ struct PrintExpressionContents
case ReplaceLaneVecI64x2:
o << "i64x2.replace_lane";
break;
+ case ReplaceLaneVecF16x8:
+ o << "f16x8.replace_lane";
+ break;
case ReplaceLaneVecF32x4:
o << "f32x4.replace_lane";
break;
@@ -1137,6 +1143,9 @@ struct PrintExpressionContents
case SplatVecI64x2:
o << "i64x2.splat";
break;
+ case SplatVecF16x8:
+ o << "f16x8.splat";
+ break;
case SplatVecF32x4:
o << "f32x4.splat";
break;
diff --git a/src/tools/fuzzing/fuzzing.cpp b/src/tools/fuzzing/fuzzing.cpp
index 2aff7146e..fd0dfb26c 100644
--- a/src/tools/fuzzing/fuzzing.cpp
+++ b/src/tools/fuzzing/fuzzing.cpp
@@ -3579,6 +3579,7 @@ Expression* TranslateToFuzzReader::makeSIMDExtract(Type type) {
break;
case ExtractLaneSVecI16x8:
case ExtractLaneUVecI16x8:
+ case ExtractLaneVecF16x8:
index = upTo(8);
break;
case ExtractLaneVecI32x4:
diff --git a/src/wasm-binary.h b/src/wasm-binary.h
index 5fae1b64d..38bf5d475 100644
--- a/src/wasm-binary.h
+++ b/src/wasm-binary.h
@@ -1054,6 +1054,9 @@ enum ASTNodes {
// half precision opcodes
F32_F16LoadMem = 0x30,
F32_F16StoreMem = 0x31,
+ F16x8Splat = 0x120,
+ F16x8ExtractLane = 0x121,
+ F16x8ReplaceLane = 0x122,
// bulk memory opcodes
diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h
index 3e62d5335..f59a005b6 100644
--- a/src/wasm-interpreter.h
+++ b/src/wasm-interpreter.h
@@ -479,6 +479,8 @@ public:
return value.splatI32x4();
case SplatVecI64x2:
return value.splatI64x2();
+ case SplatVecF16x8:
+ return value.splatF16x8();
case SplatVecF32x4:
return value.splatF32x4();
case SplatVecF64x2:
@@ -1070,6 +1072,8 @@ public:
return vec.extractLaneI32x4(curr->index);
case ExtractLaneVecI64x2:
return vec.extractLaneI64x2(curr->index);
+ case ExtractLaneVecF16x8:
+ return vec.extractLaneF16x8(curr->index);
case ExtractLaneVecF32x4:
return vec.extractLaneF32x4(curr->index);
case ExtractLaneVecF64x2:
@@ -1098,6 +1102,8 @@ public:
return vec.replaceLaneI32x4(value, curr->index);
case ReplaceLaneVecI64x2:
return vec.replaceLaneI64x2(value, curr->index);
+ case ReplaceLaneVecF16x8:
+ return vec.replaceLaneF16x8(value, curr->index);
case ReplaceLaneVecF32x4:
return vec.replaceLaneF32x4(value, curr->index);
case ReplaceLaneVecF64x2:
diff --git a/src/wasm.h b/src/wasm.h
index 4a4ed561f..56e94fef7 100644
--- a/src/wasm.h
+++ b/src/wasm.h
@@ -229,6 +229,9 @@ enum UnaryOp {
RelaxedTruncZeroSVecF64x2ToVecI32x4,
RelaxedTruncZeroUVecF64x2ToVecI32x4,
+ // Half precision SIMD
+ SplatVecF16x8,
+
InvalidUnary
};
@@ -490,6 +493,7 @@ enum SIMDExtractOp {
ExtractLaneUVecI16x8,
ExtractLaneVecI32x4,
ExtractLaneVecI64x2,
+ ExtractLaneVecF16x8,
ExtractLaneVecF32x4,
ExtractLaneVecF64x2
};
@@ -499,6 +503,7 @@ enum SIMDReplaceOp {
ReplaceLaneVecI16x8,
ReplaceLaneVecI32x4,
ReplaceLaneVecI64x2,
+ ReplaceLaneVecF16x8,
ReplaceLaneVecF32x4,
ReplaceLaneVecF64x2,
};
diff --git a/src/wasm/literal.cpp b/src/wasm/literal.cpp
index f2100ea71..a532b92d0 100644
--- a/src/wasm/literal.cpp
+++ b/src/wasm/literal.cpp
@@ -20,6 +20,7 @@
#include <cmath>
#include "emscripten-optimizer/simple_ast.h"
+#include "fp16.h"
#include "ir/bits.h"
#include "pretty_printing.h"
#include "support/bits.h"
@@ -1729,6 +1730,13 @@ LaneArray<4> Literal::getLanesI32x4() const {
LaneArray<2> Literal::getLanesI64x2() const {
return getLanes<int64_t, 2>(*this);
}
+LaneArray<8> Literal::getLanesF16x8() const {
+ auto lanes = getLanesUI16x8();
+ for (size_t i = 0; i < lanes.size(); ++i) {
+ lanes[i] = Literal(fp16_ieee_to_fp32_value(lanes[i].geti32()));
+ }
+ return lanes;
+}
LaneArray<4> Literal::getLanesF32x4() const {
auto lanes = getLanesI32x4();
for (size_t i = 0; i < lanes.size(); ++i) {
@@ -1766,6 +1774,10 @@ Literal Literal::splatI8x16() const { return splat<Type::i32, 16>(*this); }
Literal Literal::splatI16x8() const { return splat<Type::i32, 8>(*this); }
Literal Literal::splatI32x4() const { return splat<Type::i32, 4>(*this); }
Literal Literal::splatI64x2() const { return splat<Type::i64, 2>(*this); }
+Literal Literal::splatF16x8() const {
+ uint16_t f16 = fp16_ieee_from_fp32_value(getf32());
+ return splat<Type::i32, 8>(Literal(f16));
+}
Literal Literal::splatF32x4() const { return splat<Type::f32, 4>(*this); }
Literal Literal::splatF64x2() const { return splat<Type::f64, 2>(*this); }
@@ -1787,6 +1799,9 @@ Literal Literal::extractLaneI32x4(uint8_t index) const {
Literal Literal::extractLaneI64x2(uint8_t index) const {
return getLanesI64x2().at(index);
}
+Literal Literal::extractLaneF16x8(uint8_t index) const {
+ return getLanesF16x8().at(index);
+}
Literal Literal::extractLaneF32x4(uint8_t index) const {
return getLanesF32x4().at(index);
}
@@ -1815,6 +1830,10 @@ Literal Literal::replaceLaneI32x4(const Literal& other, uint8_t index) const {
Literal Literal::replaceLaneI64x2(const Literal& other, uint8_t index) const {
return replace<2, &Literal::getLanesI64x2>(*this, other, index);
}
+Literal Literal::replaceLaneF16x8(const Literal& other, uint8_t index) const {
+ return replace<8, &Literal::getLanesF16x8>(
+ *this, Literal(fp16_ieee_from_fp32_value(other.getf32())), index);
+}
Literal Literal::replaceLaneF32x4(const Literal& other, uint8_t index) const {
return replace<4, &Literal::getLanesF32x4>(*this, other, index);
}
diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp
index b9645ab8f..5eaa84515 100644
--- a/src/wasm/wasm-binary.cpp
+++ b/src/wasm/wasm-binary.cpp
@@ -6239,6 +6239,10 @@ bool WasmBinaryReader::maybeVisitSIMDUnary(Expression*& out, uint32_t code) {
curr = allocator.alloc<Unary>();
curr->op = SplatVecI64x2;
break;
+ case BinaryConsts::F16x8Splat:
+ curr = allocator.alloc<Unary>();
+ curr->op = SplatVecF16x8;
+ break;
case BinaryConsts::F32x4Splat:
curr = allocator.alloc<Unary>();
curr->op = SplatVecF32x4;
@@ -6569,6 +6573,11 @@ bool WasmBinaryReader::maybeVisitSIMDExtract(Expression*& out, uint32_t code) {
curr->op = ExtractLaneVecI64x2;
curr->index = getLaneIndex(2);
break;
+ case BinaryConsts::F16x8ExtractLane:
+ curr = allocator.alloc<SIMDExtract>();
+ curr->op = ExtractLaneVecF16x8;
+ curr->index = getLaneIndex(8);
+ break;
case BinaryConsts::F32x4ExtractLane:
curr = allocator.alloc<SIMDExtract>();
curr->op = ExtractLaneVecF32x4;
@@ -6611,6 +6620,11 @@ bool WasmBinaryReader::maybeVisitSIMDReplace(Expression*& out, uint32_t code) {
curr->op = ReplaceLaneVecI64x2;
curr->index = getLaneIndex(2);
break;
+ case BinaryConsts::F16x8ReplaceLane:
+ curr = allocator.alloc<SIMDReplace>();
+ curr->op = ReplaceLaneVecF16x8;
+ curr->index = getLaneIndex(8);
+ break;
case BinaryConsts::F32x4ReplaceLane:
curr = allocator.alloc<SIMDReplace>();
curr->op = ReplaceLaneVecF32x4;
diff --git a/src/wasm/wasm-stack.cpp b/src/wasm/wasm-stack.cpp
index 35db3b322..19b98769b 100644
--- a/src/wasm/wasm-stack.cpp
+++ b/src/wasm/wasm-stack.cpp
@@ -590,6 +590,9 @@ void BinaryInstWriter::visitSIMDExtract(SIMDExtract* curr) {
case ExtractLaneVecI64x2:
o << U32LEB(BinaryConsts::I64x2ExtractLane);
break;
+ case ExtractLaneVecF16x8:
+ o << U32LEB(BinaryConsts::F16x8ExtractLane);
+ break;
case ExtractLaneVecF32x4:
o << U32LEB(BinaryConsts::F32x4ExtractLane);
break;
@@ -615,6 +618,9 @@ void BinaryInstWriter::visitSIMDReplace(SIMDReplace* curr) {
case ReplaceLaneVecI64x2:
o << U32LEB(BinaryConsts::I64x2ReplaceLane);
break;
+ case ReplaceLaneVecF16x8:
+ o << U32LEB(BinaryConsts::F16x8ReplaceLane);
+ break;
case ReplaceLaneVecF32x4:
o << U32LEB(BinaryConsts::F32x4ReplaceLane);
break;
@@ -1050,6 +1056,9 @@ void BinaryInstWriter::visitUnary(Unary* curr) {
case SplatVecI64x2:
o << int8_t(BinaryConsts::SIMDPrefix) << U32LEB(BinaryConsts::I64x2Splat);
break;
+ case SplatVecF16x8:
+ o << int8_t(BinaryConsts::SIMDPrefix) << U32LEB(BinaryConsts::F16x8Splat);
+ break;
case SplatVecF32x4:
o << int8_t(BinaryConsts::SIMDPrefix) << U32LEB(BinaryConsts::F32x4Splat);
break;
diff --git a/src/wasm/wasm-validator.cpp b/src/wasm/wasm-validator.cpp
index b32917432..6e59ce8d8 100644
--- a/src/wasm/wasm-validator.cpp
+++ b/src/wasm/wasm-validator.cpp
@@ -1272,6 +1272,10 @@ void FunctionValidator::visitSIMDExtract(SIMDExtract* curr) {
lane_t = Type::i64;
lanes = 2;
break;
+ case ExtractLaneVecF16x8:
+ lane_t = Type::f32;
+ lanes = 8;
+ break;
case ExtractLaneVecF32x4:
lane_t = Type::f32;
lanes = 4;
@@ -1318,6 +1322,10 @@ void FunctionValidator::visitSIMDReplace(SIMDReplace* curr) {
lane_t = Type::i64;
lanes = 2;
break;
+ case ReplaceLaneVecF16x8:
+ lane_t = Type::f32;
+ lanes = 8;
+ break;
case ReplaceLaneVecF32x4:
lane_t = Type::f32;
lanes = 4;
@@ -2036,6 +2044,7 @@ void FunctionValidator::visitUnary(Unary* curr) {
shouldBeEqual(
curr->value->type, Type(Type::i64), curr, "expected i64 splat value");
break;
+ case SplatVecF16x8:
case SplatVecF32x4:
shouldBeEqual(
curr->type, Type(Type::v128), curr, "expected splat to have v128 type");
diff --git a/src/wasm/wasm.cpp b/src/wasm/wasm.cpp
index b17250e6c..ae70e4a22 100644
--- a/src/wasm/wasm.cpp
+++ b/src/wasm/wasm.cpp
@@ -386,6 +386,7 @@ void SIMDExtract::finalize() {
case ExtractLaneVecI64x2:
type = Type::i64;
break;
+ case ExtractLaneVecF16x8:
case ExtractLaneVecF32x4:
type = Type::f32;
break;
@@ -636,6 +637,7 @@ void Unary::finalize() {
case SplatVecI16x8:
case SplatVecI32x4:
case SplatVecI64x2:
+ case SplatVecF16x8:
case SplatVecF32x4:
case SplatVecF64x2:
case NotVec128: