Skip to content

Add support for relaxed-simd instructions #4320

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Nov 15, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
9 changes: 9 additions & 0 deletions src/literal.h
Original file line number Diff line number Diff line change
Expand Up @@ -425,6 +425,11 @@ class Literal {
Literal pmax(const Literal& other) const;
Literal copysign(const Literal& other) const;

// Fused multiply add and subtract.
// Computes this + (left * right) to infinite precision then round once.
Literal fma(const Literal& left, const Literal& right) const;
Literal fms(const Literal& left, const Literal& right) const;

std::array<Literal, 16> getLanesSI8x16() const;
std::array<Literal, 16> getLanesUI8x16() const;
std::array<Literal, 8> getLanesSI16x8() const;
Expand Down Expand Up @@ -647,6 +652,10 @@ class Literal {
Literal demoteZeroToF32x4() const;
Literal promoteLowToF64x2() const;
Literal swizzleI8x16(const Literal& other) const;
Literal relaxedFmaF32x4(const Literal& left, const Literal& right) const;
Literal relaxedFmsF32x4(const Literal& left, const Literal& right) const;
Literal relaxedFmaF64x2(const Literal& left, const Literal& right) const;
Literal relaxedFmsF64x2(const Literal& left, const Literal& right) const;

// Checks if an RTT value is a sub-rtt of another, that is, whether GC data
// with this object's RTT can be successfuly cast using the other RTT
Expand Down
59 changes: 59 additions & 0 deletions src/wasm/literal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1610,6 +1610,33 @@ 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(fmaf(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(fmaf(-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);
Expand Down Expand Up @@ -2548,6 +2575,38 @@ 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
Expand Down