summaryrefslogtreecommitdiff
path: root/src/wasm/literal.cpp
diff options
context:
space:
mode:
authorNg Zhi An <zhin@chromium.org>2021-11-15 13:43:43 -0800
committerGitHub <noreply@github.com>2021-11-15 13:43:43 -0800
commit3549e3040340c706349b1ee9ab3e994279805afc (patch)
tree4764d49a6c0ec600102dd07ec677c6755b6da338 /src/wasm/literal.cpp
parented1f0d8427f330a18b2ca98adeadcb1be56d59bc (diff)
downloadbinaryen-3549e3040340c706349b1ee9ab3e994279805afc.tar.gz
binaryen-3549e3040340c706349b1ee9ab3e994279805afc.tar.bz2
binaryen-3549e3040340c706349b1ee9ab3e994279805afc.zip
Add support for relaxed-simd instructions (#4320)
This adds relaxed-simd instructions based on the current status of the proposal https://github.com/WebAssembly/relaxed-simd/blob/main/proposals/relaxed-simd/Overview.md. Binary opcodes are based on what is listed in https://github.com/WebAssembly/relaxed-simd/blob/main/proposals/relaxed-simd/Overview.md#binary-format. Text names are not fixed yet, and some sort sort of names that maps to the non-relaxed versions are chosen for this prototype. Support for these instructions have been added to LLVM via builtins, adding support here will allow Emscripten to successfully compile files that use those builtins. Interpreter support has also been added, and they delegate to the non-relaxed versions of the instructions. Most instructions are implemented in the interpreter the same way as the non-relaxed simd128 instructions, except for fma/fms, which is always fused.
Diffstat (limited to 'src/wasm/literal.cpp')
-rw-r--r--src/wasm/literal.cpp62
1 files changed, 62 insertions, 0 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