Open
Description
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.