Skip to content
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

On wasm32, half operation results aren't correctly rounded between each operation #96437

Open
beetrees opened this issue Jun 23, 2024 · 2 comments

Comments

@beetrees
Copy link
Contributor

The following IR (compiler explorer):

target triple = "wasm32-unknown-wasi"

define half @f(half %x) {
start:
  %y = fmul half %x, 0xH4000 ; 0xH4000 == 2.0
  %z = fdiv half %y, 0xH4000 ; 0xH4000 == 2.0
  ret half %z
}

define half @callf() {
    %res = call half @f(half 0xH7BFF)  ; 0xH7BFF = maximum finite `f16`
    ret half %res
}

Is compiled into the following WASM:

f:                                      # @f
        local.get       0
        call    __truncsfhf2
        call    __extendhfsf2
        local.tee       0
        local.get       0
        f32.add 
        f32.const       0x1p-1
        f32.mul 
        end_function
callf:                                  # @callf
        f32.const       0x1.ffcp15
        call    f
        end_function

callf should return positive infinity (0xH7C00), but on WASM it will return 0xH7BFF due to the extra range of the f32 used to store the intermediate result.

This Rust program, when compiled with rustc 1.81.0-nightly (3cb521a43 2024-06-22) with rustc --target wasm32-wasip1 code.rs and run with wasmtime, demonstrates the issue.

#![feature(f16)]

fn f(x: f16) -> f16 {
	x * 2.0 / 2.0
}

fn main() {
	assert_eq!(f(f16::MAX), 1.0 / 0.0);
}

The assertion should succeed, but on WASM it fails.

@llvmbot
Copy link
Collaborator

llvmbot commented Jun 23, 2024

@llvm/issue-subscribers-backend-webassembly

Author: None (beetrees)

The following IR ([compiler explorer](https://godbolt.org/z/TbKnj8n4e)):
target triple = "wasm32-unknown-wasi"

define half @<!-- -->f(half %x) {
start:
  %y = fmul half %x, 0xH4000 ; 0xH4000 == 2.0
  %z = fdiv half %y, 0xH4000 ; 0xH4000 == 2.0
  ret half %z
}

define half @<!-- -->callf() {
    %res = call half @<!-- -->f(half 0xH7BFF)  ; 0xH7BFF = maximum finite `f16`
    ret half %res
}

Is compiled into the following WASM:

f:                                      # @<!-- -->f
        local.get       0
        call    __truncsfhf2
        call    __extendhfsf2
        local.tee       0
        local.get       0
        f32.add 
        f32.const       0x1p-1
        f32.mul 
        end_function
callf:                                  # @<!-- -->callf
        f32.const       0x1.ffcp15
        call    f
        end_function

callf should return positive infinity (0xH7C00), but on WASM it will return 0xH7BFF due to the extra range of the f32 used to store the intermediate result.

This Rust program, when compiled with rustc 1.81.0-nightly (3cb521a43 2024-06-22) with rustc --target wasm32-wasip1 code.rs and run with wasmtime, demonstrates the issue.

#![feature(f16)]

fn f(x: f16) -&gt; f16 {
	x * 2.0 / 2.0
}

fn main() {
	assert_eq!(f(f16::MAX), 1.0 / 0.0);
}

The assertion should succeed, but on WASM it fails.

@tlively
Copy link
Collaborator

tlively commented Jun 27, 2024

cc @brendandahl, this seems potentially related to your recent fp16 work.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants