Skip to content

Interpreter: Don't change NaN bits when dividing by 1 #2958

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 4 commits into from
Jul 15, 2020
Merged

Interpreter: Don't change NaN bits when dividing by 1 #2958

merged 4 commits into from
Jul 15, 2020

Conversation

kripken
Copy link
Member

@kripken kripken commented Jul 14, 2020

It's valid to change NaN bits in that case per the wasm spec, but
if we do so then fuzz testcases will fail on the optimization of

nan:foo / 1 => nan:foo

That is, it is ok to leave the bits as they are, and if we do that then
we are consistent with the simple and valid optimization of removing
a divide by 1.

Found by the fuzzer - looks like on x64 on some float32 NaNs,
the bits will actually change (see the testcase). I've seen this on
two machines consistently, so it's normal apparently.

@kripken
Copy link
Member Author

kripken commented Jul 14, 2020

Huh, this fails a spec test,

;; Test that x/1.0 is not folded to x.

(module
  (func (export "f32.no_fold_div_one") (param $x f32) (result f32)
    (f32.div (local.get $x) (f32.const 1.0)))
  (func (export "f64.no_fold_div_one") (param $x f64) (result f64)
    (f64.div (local.get $x) (f64.const 1.0)))
)

(assert_return (invoke "f32.no_fold_div_one" (f32.const nan:0x200000)) (f32.const nan:0x600000))
(assert_return (invoke "f64.no_fold_div_one" (f64.const nan:0x4000000000000)) (f64.const nan:0xc000000000000))

Does anyone understand what that test is doing? I'm puzzled by the nan bits change. It seems I'm missing something important here.

@kripken
Copy link
Member Author

kripken commented Jul 14, 2020

Ah, the spec test has been fixed in upstream, to

(assert_return (invoke "f32.no_fold_div_one" (f32.const nan:0x200000)) (f32.const nan:arithmetic))
(assert_return (invoke "f64.no_fold_div_one" (f64.const nan:0x4000000000000)) (f64.const nan:arithmetic))

We don't support that new test notation here, but anyhow I'll just remove that particular test, as the new test added here is even stricter.

@kripken kripken requested review from aheejin and tlively July 15, 2020 15:59
Co-authored-by: Thomas Lively <7121787+tlively@users.noreply.github.com>
@kripken kripken merged commit 1c75f7d into master Jul 15, 2020
@kripken kripken deleted the one branch July 15, 2020 18:49
kripken added a commit that referenced this pull request Sep 2, 2020
kripken added a commit that referenced this pull request Sep 9, 2020
Similar to #2958, but for multiplication. I thought this was limited
only to division (it doesn't happen for addition, for example), but the
fuzzer found that it does indeed happen for multiplication as well.

Overall these are kind of workarounds for the interpreter doing
normal f32/f64 multiplications using the host CPU, so we pick up
any oddness of its NaN behavior. Using soft float might be safer
(but much slower).
@kripken kripken mentioned this pull request Sep 21, 2020
kripken added a commit that referenced this pull request Sep 30, 2020
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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants