Stream: git-wasmtime

Topic: wasmtime / issue #6961 wasmtime: `issue_3327_bnot_lowerin...


view this post on Zulip Wasmtime GitHub notifications bot (Sep 04 2023 at 16:39):

afonso360 opened issue #6961:

:wave: Hey,

This is the last remaining SIMD test that is disabled for RISC-V. I'm fairly sure that the RISC-V backend implements a spec compliant implementation of these instructions but I'd like to confirm it.

Test Case

The original test is the following:

;; from #3327
(module
  (func (result i32)
    v128.const i32x4 0xffffffff 0x80bfffff 0x80bf0a0a 0x80bf0a0a
    f64x2.promote_low_f32x4
    v128.not
    v128.not
    v128.not
    v128.not
    v128.not
    v128.not
    v128.not
    v128.const i32x4 0 0 0 0
    f64x2.gt
    v128.not
    i64x2.bitmask)
  (export "" (func 0)))
(assert_return (invoke "") (i32.const 0))

Steps to Reproduce

Expected Results

The test to pass

Actual Results

RISC-V fails.

Versions and Environment

Wasmtime version or commit: main

Operating system: Linux

Architecture: RISC-V

Extra Info

I've reduced the above input down to following clif test:

test interpret
test run
target riscv64gc has_v
target x86_64


function %a(i64) -> f64 fast {
    const0 = 0x80bf0a0a80bf0a0a80bfffffffffffff

block0(v1: i64):
    v3 = vconst.f32x4 const0
    v5 = fvpromote_low v3
    v6 = extractlane v5, 0
    return v6
}

;; X86_64 passes this
; run: %a(0) == -NaN:0x7ffffe0000000

;; RISCV64 passes this
; run: %a(0) == NaN

RISC-V returns a Positive Canonical NaN from fvpromote_low. While X86 keeps the NaN as negative (and preserves payload bits). In the original test case the NaNs are then compared to check if they are negative, this passes on x86, but not on RISC-V.

The docs on fvpromote_low don't specify what the correct behaviour here is. So I've looked at the NaN Propagation section of the WASM specification where it states:

When the result of a floating-point operator other than fneg, fabs, or fcopysing is a NaN, then its sign is non-deterministic and the payload is computed as follows:

In the original test case the part that makes the test fail is that RISC-V flips the sign of the NaN on promotion. I think this is allowed since the spec states its sign is non-deterministic. I think clearing the payload bits is also allowed, although it doesn't really matter here.

So, am I reading the above correctly? And if so should we just leave this test disabled for RISC-V, or try to rewrite it in a conformant way?

view this post on Zulip Wasmtime GitHub notifications bot (Sep 04 2023 at 16:39):

afonso360 added the bug label to Issue #6961.

view this post on Zulip Wasmtime GitHub notifications bot (Sep 04 2023 at 16:39):

afonso360 added the cranelift:area:riscv64 label to Issue #6961.

view this post on Zulip Wasmtime GitHub notifications bot (Sep 05 2023 at 18:43):

alexcrichton commented on issue #6961:

I believe you're correct in your conclusion here. I'll also link the documented semantics for promotion which explicitly agree with the NaN propagation section.

Given this I'd say it's ok to ignore the test on RISC-V. Ideally the test could be rewritten to accomodate platform differences but that seems difficult here as this is stressing a specific codegen bug. There's various s-expression matchers for "any nan" or "any arithmetic nan" which I think is ideally what's wanted here.

view this post on Zulip Wasmtime GitHub notifications bot (Sep 06 2023 at 20:30):

alexcrichton closed issue #6961:

:wave: Hey,

This is the last remaining SIMD test that is disabled for RISC-V. I'm fairly sure that the RISC-V backend implements a spec compliant implementation of these instructions but I'd like to confirm it.

Test Case

The original test is the following:

;; from #3327
(module
  (func (result i32)
    v128.const i32x4 0xffffffff 0x80bfffff 0x80bf0a0a 0x80bf0a0a
    f64x2.promote_low_f32x4
    v128.not
    v128.not
    v128.not
    v128.not
    v128.not
    v128.not
    v128.not
    v128.const i32x4 0 0 0 0
    f64x2.gt
    v128.not
    i64x2.bitmask)
  (export "" (func 0)))
(assert_return (invoke "") (i32.const 0))

Steps to Reproduce

Expected Results

The test to pass

Actual Results

RISC-V fails.

Versions and Environment

Wasmtime version or commit: main

Operating system: Linux

Architecture: RISC-V

Extra Info

I've reduced the above input down to following clif test:

test interpret
test run
target riscv64gc has_v
target x86_64


function %a(i64) -> f64 fast {
    const0 = 0x80bf0a0a80bf0a0a80bfffffffffffff

block0(v1: i64):
    v3 = vconst.f32x4 const0
    v5 = fvpromote_low v3
    v6 = extractlane v5, 0
    return v6
}

;; X86_64 passes this
; run: %a(0) == -NaN:0x7ffffe0000000

;; RISCV64 passes this
; run: %a(0) == NaN

RISC-V returns a Positive Canonical NaN from fvpromote_low. While X86 keeps the NaN as negative (and preserves payload bits). In the original test case the NaNs are then compared to check if they are negative, this passes on x86, but not on RISC-V.

The docs on fvpromote_low don't specify what the correct behaviour here is. So I've looked at the NaN Propagation section of the WASM specification where it states:

When the result of a floating-point operator other than fneg, fabs, or fcopysing is a NaN, then its sign is non-deterministic and the payload is computed as follows:

In the original test case the part that makes the test fail is that RISC-V flips the sign of the NaN on promotion. I think this is allowed since the spec states its sign is non-deterministic. I think clearing the payload bits is also allowed, although it doesn't really matter here.

So, am I reading the above correctly? And if so should we just leave this test disabled for RISC-V, or try to rewrite it in a conformant way?


Last updated: Dec 23 2024 at 12:05 UTC