summaryrefslogtreecommitdiff
path: root/src/wasm
diff options
context:
space:
mode:
Diffstat (limited to 'src/wasm')
-rw-r--r--src/wasm/literal.cpp62
-rw-r--r--src/wasm/wasm-binary.cpp68
-rw-r--r--src/wasm/wasm-stack.cpp61
-rw-r--r--src/wasm/wasm-validator.cpp11
-rw-r--r--src/wasm/wasm.cpp4
5 files changed, 205 insertions, 1 deletions
diff --git a/src/wasm/literal.cpp b/src/wasm/literal.cpp
index 4753e5ca1..e761206bc 100644
--- a/src/wasm/literal.cpp
+++ b/src/wasm/literal.cpp
@@ -1610,6 +1610,32 @@ Literal Literal::copysign(const Literal& other) const {
}
}
+Literal Literal::fma(const Literal& left, const Literal& right) const {
+ switch (type.getBasic()) {
+ case Type::f32:
+ return Literal(::fmaf(left.getf32(), right.getf32(), getf32()));
+ break;
+ case Type::f64:
+ return Literal(::fma(left.getf64(), right.getf64(), getf64()));
+ break;
+ default:
+ WASM_UNREACHABLE("unexpected type");
+ }
+}
+
+Literal Literal::fms(const Literal& left, const Literal& right) const {
+ switch (type.getBasic()) {
+ case Type::f32:
+ return Literal(::fmaf(-left.getf32(), right.getf32(), getf32()));
+ break;
+ case Type::f64:
+ return Literal(::fma(-left.getf64(), right.getf64(), getf64()));
+ break;
+ default:
+ WASM_UNREACHABLE("unexpected type");
+ }
+}
+
template<typename LaneT, int Lanes>
static LaneArray<Lanes> getLanes(const Literal& val) {
assert(val.type == Type::v128);
@@ -2548,6 +2574,42 @@ Literal Literal::swizzleI8x16(const Literal& other) const {
return Literal(result);
}
+namespace {
+template<int Lanes,
+ LaneArray<Lanes> (Literal::*IntoLanes)() const,
+ Literal (Literal::*TernaryOp)(const Literal&, const Literal&) const>
+static Literal ternary(const Literal& a, const Literal& b, const Literal& c) {
+ LaneArray<Lanes> x = (a.*IntoLanes)();
+ LaneArray<Lanes> y = (b.*IntoLanes)();
+ LaneArray<Lanes> z = (c.*IntoLanes)();
+ LaneArray<Lanes> r;
+ for (size_t i = 0; i < Lanes; ++i) {
+ r[i] = (x[i].*TernaryOp)(y[i], z[i]);
+ }
+ return Literal(r);
+}
+} // namespace
+
+Literal Literal::relaxedFmaF32x4(const Literal& left,
+ const Literal& right) const {
+ return ternary<4, &Literal::getLanesF32x4, &Literal::fma>(*this, left, right);
+}
+
+Literal Literal::relaxedFmsF32x4(const Literal& left,
+ const Literal& right) const {
+ return ternary<4, &Literal::getLanesF32x4, &Literal::fms>(*this, left, right);
+}
+
+Literal Literal::relaxedFmaF64x2(const Literal& left,
+ const Literal& right) const {
+ return ternary<2, &Literal::getLanesF64x2, &Literal::fma>(*this, left, right);
+}
+
+Literal Literal::relaxedFmsF64x2(const Literal& left,
+ const Literal& right) const {
+ return ternary<2, &Literal::getLanesF64x2, &Literal::fms>(*this, left, right);
+}
+
bool Literal::isSubRtt(const Literal& other) const {
assert(type.isRtt() && other.type.isRtt());
// For this literal to be a sub-rtt of the other rtt, the supers must be a
diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp
index 6ce2c7979..0ccb9d6db 100644
--- a/src/wasm/wasm-binary.cpp
+++ b/src/wasm/wasm-binary.cpp
@@ -5524,6 +5524,26 @@ bool WasmBinaryBuilder::maybeVisitSIMDBinary(Expression*& out, uint32_t code) {
curr = allocator.alloc<Binary>();
curr->op = SwizzleVec8x16;
break;
+ case BinaryConsts::I8x16RelaxedSwizzle:
+ curr = allocator.alloc<Binary>();
+ curr->op = RelaxedSwizzleVec8x16;
+ break;
+ case BinaryConsts::F32x4RelaxedMin:
+ curr = allocator.alloc<Binary>();
+ curr->op = RelaxedMinVecF32x4;
+ break;
+ case BinaryConsts::F32x4RelaxedMax:
+ curr = allocator.alloc<Binary>();
+ curr->op = RelaxedMaxVecF32x4;
+ break;
+ case BinaryConsts::F64x2RelaxedMin:
+ curr = allocator.alloc<Binary>();
+ curr->op = RelaxedMinVecF64x2;
+ break;
+ case BinaryConsts::F64x2RelaxedMax:
+ curr = allocator.alloc<Binary>();
+ curr->op = RelaxedMaxVecF64x2;
+ break;
default:
return false;
}
@@ -5797,6 +5817,22 @@ bool WasmBinaryBuilder::maybeVisitSIMDUnary(Expression*& out, uint32_t code) {
curr = allocator.alloc<Unary>();
curr->op = PromoteLowVecF32x4ToVecF64x2;
break;
+ case BinaryConsts::I32x4RelaxedTruncF32x4S:
+ curr = allocator.alloc<Unary>();
+ curr->op = RelaxedTruncSVecF32x4ToVecI32x4;
+ break;
+ case BinaryConsts::I32x4RelaxedTruncF32x4U:
+ curr = allocator.alloc<Unary>();
+ curr->op = RelaxedTruncUVecF32x4ToVecI32x4;
+ break;
+ case BinaryConsts::I32x4RelaxedTruncF64x2SZero:
+ curr = allocator.alloc<Unary>();
+ curr->op = RelaxedTruncZeroSVecF64x2ToVecI32x4;
+ break;
+ case BinaryConsts::I32x4RelaxedTruncF64x2UZero:
+ curr = allocator.alloc<Unary>();
+ curr->op = RelaxedTruncZeroUVecF64x2ToVecI32x4;
+ break;
default:
return false;
}
@@ -5950,6 +5986,38 @@ bool WasmBinaryBuilder::maybeVisitSIMDTernary(Expression*& out, uint32_t code) {
curr = allocator.alloc<SIMDTernary>();
curr->op = Bitselect;
break;
+ case BinaryConsts::I8x16Laneselect:
+ curr = allocator.alloc<SIMDTernary>();
+ curr->op = LaneselectI8x16;
+ break;
+ case BinaryConsts::I16x8Laneselect:
+ curr = allocator.alloc<SIMDTernary>();
+ curr->op = LaneselectI16x8;
+ break;
+ case BinaryConsts::I32x4Laneselect:
+ curr = allocator.alloc<SIMDTernary>();
+ curr->op = LaneselectI32x4;
+ break;
+ case BinaryConsts::I64x2Laneselect:
+ curr = allocator.alloc<SIMDTernary>();
+ curr->op = LaneselectI64x2;
+ break;
+ case BinaryConsts::F32x4RelaxedFma:
+ curr = allocator.alloc<SIMDTernary>();
+ curr->op = RelaxedFmaVecF32x4;
+ break;
+ case BinaryConsts::F32x4RelaxedFms:
+ curr = allocator.alloc<SIMDTernary>();
+ curr->op = RelaxedFmsVecF32x4;
+ break;
+ case BinaryConsts::F64x2RelaxedFma:
+ curr = allocator.alloc<SIMDTernary>();
+ curr->op = RelaxedFmaVecF64x2;
+ break;
+ case BinaryConsts::F64x2RelaxedFms:
+ curr = allocator.alloc<SIMDTernary>();
+ curr->op = RelaxedFmsVecF64x2;
+ break;
default:
return false;
}
diff --git a/src/wasm/wasm-stack.cpp b/src/wasm/wasm-stack.cpp
index f5be5d2c5..59398839e 100644
--- a/src/wasm/wasm-stack.cpp
+++ b/src/wasm/wasm-stack.cpp
@@ -546,6 +546,30 @@ void BinaryInstWriter::visitSIMDTernary(SIMDTernary* curr) {
case Bitselect:
o << U32LEB(BinaryConsts::V128Bitselect);
break;
+ case LaneselectI8x16:
+ o << U32LEB(BinaryConsts::I8x16Laneselect);
+ break;
+ case LaneselectI16x8:
+ o << U32LEB(BinaryConsts::I16x8Laneselect);
+ break;
+ case LaneselectI32x4:
+ o << U32LEB(BinaryConsts::I32x4Laneselect);
+ break;
+ case LaneselectI64x2:
+ o << U32LEB(BinaryConsts::I64x2Laneselect);
+ break;
+ case RelaxedFmaVecF32x4:
+ o << U32LEB(BinaryConsts::F32x4RelaxedFma);
+ break;
+ case RelaxedFmsVecF32x4:
+ o << U32LEB(BinaryConsts::F32x4RelaxedFms);
+ break;
+ case RelaxedFmaVecF64x2:
+ o << U32LEB(BinaryConsts::F64x2RelaxedFma);
+ break;
+ case RelaxedFmsVecF64x2:
+ o << U32LEB(BinaryConsts::F64x2RelaxedFms);
+ break;
}
}
@@ -1153,6 +1177,22 @@ void BinaryInstWriter::visitUnary(Unary* curr) {
o << int8_t(BinaryConsts::SIMDPrefix)
<< U32LEB(BinaryConsts::F64x2PromoteLowF32x4);
break;
+ case RelaxedTruncSVecF32x4ToVecI32x4:
+ o << int8_t(BinaryConsts::SIMDPrefix)
+ << U32LEB(BinaryConsts::I32x4RelaxedTruncF32x4S);
+ break;
+ case RelaxedTruncUVecF32x4ToVecI32x4:
+ o << int8_t(BinaryConsts::SIMDPrefix)
+ << U32LEB(BinaryConsts::I32x4RelaxedTruncF32x4U);
+ break;
+ case RelaxedTruncZeroSVecF64x2ToVecI32x4:
+ o << int8_t(BinaryConsts::SIMDPrefix)
+ << U32LEB(BinaryConsts::I32x4RelaxedTruncF64x2SZero);
+ break;
+ case RelaxedTruncZeroUVecF64x2ToVecI32x4:
+ o << int8_t(BinaryConsts::SIMDPrefix)
+ << U32LEB(BinaryConsts::I32x4RelaxedTruncF64x2UZero);
+ break;
case InvalidUnary:
WASM_UNREACHABLE("invalid unary op");
}
@@ -1783,6 +1823,27 @@ void BinaryInstWriter::visitBinary(Binary* curr) {
<< U32LEB(BinaryConsts::I8x16Swizzle);
break;
+ case RelaxedSwizzleVec8x16:
+ o << int8_t(BinaryConsts::SIMDPrefix)
+ << U32LEB(BinaryConsts::I8x16RelaxedSwizzle);
+ break;
+ case RelaxedMinVecF32x4:
+ o << int8_t(BinaryConsts::SIMDPrefix)
+ << U32LEB(BinaryConsts::F32x4RelaxedMin);
+ break;
+ case RelaxedMaxVecF32x4:
+ o << int8_t(BinaryConsts::SIMDPrefix)
+ << U32LEB(BinaryConsts::F32x4RelaxedMax);
+ break;
+ case RelaxedMinVecF64x2:
+ o << int8_t(BinaryConsts::SIMDPrefix)
+ << U32LEB(BinaryConsts::F64x2RelaxedMin);
+ break;
+ case RelaxedMaxVecF64x2:
+ o << int8_t(BinaryConsts::SIMDPrefix)
+ << U32LEB(BinaryConsts::F64x2RelaxedMax);
+ break;
+
case InvalidBinary:
WASM_UNREACHABLE("invalid binary op");
}
diff --git a/src/wasm/wasm-validator.cpp b/src/wasm/wasm-validator.cpp
index 86b537bf5..696c50d8b 100644
--- a/src/wasm/wasm-validator.cpp
+++ b/src/wasm/wasm-validator.cpp
@@ -1613,6 +1613,8 @@ void FunctionValidator::visitBinary(Binary* curr) {
case MaxVecF32x4:
case PMinVecF32x4:
case PMaxVecF32x4:
+ case RelaxedMinVecF32x4:
+ case RelaxedMaxVecF32x4:
case AddVecF64x2:
case SubVecF64x2:
case MulVecF64x2:
@@ -1621,11 +1623,14 @@ void FunctionValidator::visitBinary(Binary* curr) {
case MaxVecF64x2:
case PMinVecF64x2:
case PMaxVecF64x2:
+ case RelaxedMinVecF64x2:
+ case RelaxedMaxVecF64x2:
case NarrowSVecI16x8ToVecI8x16:
case NarrowUVecI16x8ToVecI8x16:
case NarrowSVecI32x4ToVecI16x8:
case NarrowUVecI32x4ToVecI16x8:
- case SwizzleVec8x16: {
+ case SwizzleVec8x16:
+ case RelaxedSwizzleVec8x16: {
shouldBeEqualOrFirstIsUnreachable(
curr->left->type, Type(Type::v128), curr, "v128 op");
shouldBeEqualOrFirstIsUnreachable(
@@ -1898,6 +1903,10 @@ void FunctionValidator::visitUnary(Unary* curr) {
case TruncSatZeroUVecF64x2ToVecI32x4:
case DemoteZeroVecF64x2ToVecF32x4:
case PromoteLowVecF32x4ToVecF64x2:
+ case RelaxedTruncSVecF32x4ToVecI32x4:
+ case RelaxedTruncUVecF32x4ToVecI32x4:
+ case RelaxedTruncZeroSVecF64x2ToVecI32x4:
+ case RelaxedTruncZeroUVecF64x2ToVecI32x4:
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 015df26ac..fd3cec8d8 100644
--- a/src/wasm/wasm.cpp
+++ b/src/wasm/wasm.cpp
@@ -711,6 +711,10 @@ void Unary::finalize() {
case TruncSatZeroUVecF64x2ToVecI32x4:
case DemoteZeroVecF64x2ToVecF32x4:
case PromoteLowVecF32x4ToVecF64x2:
+ case RelaxedTruncSVecF32x4ToVecI32x4:
+ case RelaxedTruncUVecF32x4ToVecI32x4:
+ case RelaxedTruncZeroSVecF64x2ToVecI32x4:
+ case RelaxedTruncZeroUVecF64x2ToVecI32x4:
type = Type::v128;
break;
case AnyTrueVec128: