summaryrefslogtreecommitdiff
path: root/src/wasm/literal.cpp
diff options
context:
space:
mode:
authorAlon Zakai <azakai@google.com>2020-09-30 12:39:05 -0700
committerGitHub <noreply@github.com>2020-09-30 12:39:05 -0700
commit07047103a26e1c17ee995ef3e1358ddb26d8e8c8 (patch)
treeedaf22d19ab7c22c3cff58f9e02d8f41abcb5b3e /src/wasm/literal.cpp
parent11de8894505d37b7b970a2103bc5b1cfd094b115 (diff)
downloadbinaryen-07047103a26e1c17ee995ef3e1358ddb26d8e8c8.tar.gz
binaryen-07047103a26e1c17ee995ef3e1358ddb26d8e8c8.tar.bz2
binaryen-07047103a26e1c17ee995ef3e1358ddb26d8e8c8.zip
Add --fast-math mode (#3155)
Similar to clang and gcc, --fast-math makes us ignore corner cases of floating-point math like NaN changes and (not done yet) lack of associativity and so forth. In the future we may want to have separate fast math flags for each specific thing, like gcc and clang do. This undoes some changes (#2958 and #3096) where we assumed it was ok to not change NaN bits, but @binji corrected us. We can only do such things in fast math mode. This puts those optimizations behind that flag, adds tests for it, and restores the interpreter to the simpler code from before with no special cases.
Diffstat (limited to 'src/wasm/literal.cpp')
-rw-r--r--src/wasm/literal.cpp41
1 files changed, 4 insertions, 37 deletions
diff --git a/src/wasm/literal.cpp b/src/wasm/literal.cpp
index d309be308..54453b356 100644
--- a/src/wasm/literal.cpp
+++ b/src/wasm/literal.cpp
@@ -934,35 +934,10 @@ Literal Literal::mul(const Literal& other) const {
return Literal(uint32_t(i32) * uint32_t(other.i32));
case Type::i64:
return Literal(uint64_t(i64) * uint64_t(other.i64));
- case Type::f32: {
- // Special-case multiplication by 1. nan * 1 can change nan bits per the
- // wasm spec, but it is ok to just return that original nan, and we
- // do that here so that we are consistent with the optimization of
- // removing the * 1 and leaving just the nan. That is, if we just
- // do a normal multiply and the CPU decides to change the bits, we'd
- // give a different result on optimized code, which would look like
- // it was a bad optimization. So out of all the valid results to
- // return here, return the simplest one that is consistent with
- // our optimization for the case of 1.
- float lhs = getf32(), rhs = other.getf32();
- if (rhs == 1) {
- return Literal(lhs);
- }
- if (lhs == 1) {
- return Literal(rhs);
- }
- return Literal(lhs * rhs);
- }
- case Type::f64: {
- double lhs = getf64(), rhs = other.getf64();
- if (rhs == 1) {
- return Literal(lhs);
- }
- if (lhs == 1) {
- return Literal(rhs);
- }
- return Literal(lhs * rhs);
- }
+ case Type::f32:
+ return Literal(getf32() * other.getf32());
+ case Type::f64:
+ return Literal(getf64() * other.getf64());
case Type::v128:
case Type::funcref:
case Type::externref:
@@ -1002,10 +977,6 @@ Literal Literal::div(const Literal& other) const {
case FP_INFINITE: // fallthrough
case FP_NORMAL: // fallthrough
case FP_SUBNORMAL:
- // Special-case division by 1, similar to multiply from earlier.
- if (rhs == 1) {
- return Literal(lhs);
- }
return Literal(lhs / rhs);
default:
WASM_UNREACHABLE("invalid fp classification");
@@ -1034,10 +1005,6 @@ Literal Literal::div(const Literal& other) const {
case FP_INFINITE: // fallthrough
case FP_NORMAL: // fallthrough
case FP_SUBNORMAL:
- // See above comment on f32.
- if (rhs == 1) {
- return Literal(lhs);
- }
return Literal(lhs / rhs);
default:
WASM_UNREACHABLE("invalid fp classification");