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

Rounding error in __mulsf3 #616

Closed
tgross35 opened this issue May 19, 2024 · 6 comments · Fixed by #637
Closed

Rounding error in __mulsf3 #616

tgross35 opened this issue May 19, 2024 · 6 comments · Fixed by #637

Comments

@tgross35
Copy link
Contributor

tgross35 commented May 19, 2024

This is a problem in Rust's compiler-builtins, but also the LLVM library (which is demonstrated here). The correct answer should be 0.0.

https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=54ee2169049eb22eb1b44d41c6f37e1e

extern "C" {
    fn __mulsf3(a: f32, b: f32) -> f32;
}

fn main() {
    let a = 7.83651e-39f32;
    let b = 2.7310085e-8f32;
    let res_asm = a * b ;
    let res_mulsf3 = unsafe { __mulsf3(a, b) };
    println!("asm {} {:#010x}", res_asm, res_asm.to_bits());
    println!("mulsf3 {} {:#010x}", res_mulsf3, res_mulsf3.to_bits());
}
asm 0 0x00000000
mulsf3 0.000000000000000000000000000000000000000000001 0x00000001
@tgross35
Copy link
Contributor Author

Hm, I can't reproduce this in C

@tgross35
Copy link
Contributor Author

Also a problem with f64: f64 mul(1.488018149503636e-307, -2.8933234101276373e-18): crate: -5e-324, asm: -0.0

@Amanieu
Copy link
Member

Amanieu commented May 19, 2024

res_asm doesn't actually use asm, it's const-evaluated by rustc. However inline assembly also produces a result of 0: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=89eb0e7d4c02667b77234004c5f313ec

It definitely seems like a library problem, IEEE734 should produce an exact result for multiply assuming round-to-nearest.

@tgross35
Copy link
Contributor Author

This is probably related to the rounding issue that I thought was limited to f128 llvm/llvm-project#91840

@tgross35
Copy link
Contributor Author

tgross35 commented May 20, 2024

multf3 too, on x86, I am surprised this didn't come up on fuzzing since it seems like the system functions do the right thing here.

#![feature(f128)]

use rustc_apfloat::ieee::Quad;
use rustc_apfloat::Float;

extern "C" {
    fn __multf3(a: f128, b: f128) -> f128;
}

#[test]
fn foo() {
    let a = f128::from_bits(0x03a00000000000000000000000005400);
    let b = f128::from_bits(0x3c2caaaaaaaaaa00000000002aa80002);
    let aq = Quad::from_bits(a.to_bits());
    let bq = Quad::from_bits(b.to_bits());
    let res_llvm = a * b;
    let res_crate = compiler_builtins::float::mul::__multf3(a, b);
    let res_sys = unsafe { __multf3(a, b) };
    println!("llvm {:?}", res_llvm);
    println!("crate {:?}", res_crate);
    println!("sys {:?}", res_sys);
    println!("ap {:#034x}", (aq * bq).value.to_bits());
    assert_eq!(res_llvm.to_bits(), res_crate.to_bits());
    assert_eq!(res_llvm.to_bits(), res_sys.to_bits());
}
llvm 0x00000000000000001aaaaaaaaaa00000
crate 0x00000000000000001aaaaaaaaaa00001
sys 0x00000000000000001aaaaaaaaaa00000
ap 0x00000000000000001aaaaaaaaaa00000
thread 'foo' panicked at testcrate/tests/break.rs:23:5:
assertion `left == right` failed
  left: 1921535841010712576
 right: 192153584101071257

@Amanieu
Copy link
Member

Amanieu commented May 20, 2024

Note that on -gnu targets, the system version of __mulsf3 and other builtins comes from libgcc, not LLVM's compiler-rt.

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