Skip to content

aarch64-linux multf3 symbol has incorrect rounding #607

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

Closed
tgross35 opened this issue May 11, 2024 · 1 comment
Closed

aarch64-linux multf3 symbol has incorrect rounding #607

tgross35 opened this issue May 11, 2024 · 1 comment

Comments

@tgross35
Copy link
Contributor

tgross35 commented May 11, 2024

Still getting to the root of this, discussion started at https://rust-lang.zulipchat.com/#narrow/stream/122651-general/topic/f128.20system.20libraries.20noncompliant.20platforms

Comparing this Rust code:

#![feature(f128)]

#[no_mangle]
fn mul_entry(a: f128, b: f128) -> f128 {
    a * b
}

fn main() {
    let a = f128::from_bits(0x00007fffffffffffffffffffffffffff);
    let b = f128::from_bits(0x40007fffffffffffffffffffffffffff);
    let c = mul_entry(a, b);
    dbg!(c);
}

Against this C version:

#define __STDC_WANT_IEC_60559_TYPES_EXT__

#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>

#if defined(__clang__) && (defined(__i386) || defined(__x86_64))
#define _Float128 __float128
#endif

typedef struct {
    uint64_t lower, upper;
} u128;


void f128_print(_Float128 val) {
    u128 ival = *((u128 *)(&val));

    #ifndef __clang__
    char buf[1024];
    strfromf128(buf, sizeof(buf), "%.32g", val);
    printf("%#018" PRIx64 "%016" PRIx64 " %s\n", ival.upper, ival.lower, buf);
    #else
    printf("%#018" PRIx64 "%016" PRIx64 " %lf\n", ival.upper, ival.lower, (double)val);
    #endif
}

_Float128 new_f128(uint64_t upper, uint64_t lower) {
    u128 val;
    val.lower = lower;
    val.upper = upper;
    return *((_Float128 *)(&val));
}

int main() {
    _Float128 a = new_f128(0x00007fffffffffff, 0xffffffffffffffff);
    _Float128 b = new_f128(0x40007fffffffffff, 0xffffffffffffffff);
    f128_print(a);
    f128_print(b);
    _Float128 c = a * b;
    f128_print(c);

    return 0;
}

With gcc:

0x00007fffffffffffffffffffffffffff 1.6810515715560467531313389086609e-4932
0x40007fffffffffffffffffffffffffff 3
0x00017ffffffffffffffffffffffffffc 5.0431547146681402593940167259826e-4932

Clang:

0x00007fffffffffffffffffffffffffff 0.000000
0x40007fffffffffffffffffffffffffff 3.000000
0x00017ffffffffffffffffffffffffffc 0.000000

Both of those are correct. However, the Rust version is not:

[f128_demo.rs:12:5] c = 0x00017ffffffffffffffffffffffffffb

Reproduction with C:

/usr/lib/llvm-14/bin/clang -cc1 -triple aarch64-unknown-linux-gnu -emit-obj \
-mrelax-all --mrelax-relocations -disable-free -clear-ast-before-backend \
-disable-llvm-verifier -discard-value-names \
-main-file-name f128_demo.c \
-mrelocation-model pic -pic-level 2 -pic-is-pie \
-mframe-pointer=non-leaf \
-fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 \
-target-cpu generic -target-feature +neon -target-feature +v8a -target-abi aapcs \
-fallow-half-arguments-and-returns -mllvm \
-treat-scalable-fixed-error-as-warning -debugger-tuning=gdb -v \
-fcoverage-compilation-dir=/root -resource-dir /usr/lib/llvm-14/lib/clang/14.0.0 \
-internal-isystem /usr/lib/llvm-14/lib/clang/14.0.0/include -internal-isystem /usr/local/include \
-internal-isystem /usr/bin/../lib/gcc/aarch64-linux-gnu/11/../../../../aarch64-linux-gnu/include \
-internal-externc-isystem /usr/include/aarch64-linux-gnu -internal-externc-isystem /include \
-internal-externc-isystem /usr/include -fdebug-compilation-dir=/root \
-ferror-limit 19 -fno-signed-char -fgnuc-version=4.2.1 -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 \
-o f128_demo_clang.o -x c f128_demo.c

Linking:

/usr/bin/ld -pie -EL -z relro --hash-style=gnu --build-id --eh-frame-hdr -m aarch64linux \
-dynamic-linker /lib/ld-linux-aarch64.so.1 \
-o f128_demo_clang.out \
/lib/aarch64-linux-gnu/Scrt1.o /lib/aarch64-linux-gnu/crti.o /usr/bin/../lib/gcc/aarch64-linux-gnu/11/crtbeginS.o \
-L/usr/bin/../lib/gcc/aarch64-linux-gnu/11 -L/lib/aarch64-linux-gnu -L/usr/lib/aarch64-linux-gnu \
-L/usr/lib/llvm-14/bin/../lib -L/lib -L/usr/lib \
f128_demo_clang.o \
-lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed \
/usr/bin/../lib/gcc/aarch64-linux-gnu/11/crtendS.o /lib/aarch64-linux-gnu/crtn.o

This produces the same correct output as above (ending in c). However, changing the command to link the rust library

clang f128_demo.c \
.rustup/toolchains/nightly-aarch64-unknown-linux-gnu/lib/rustlib/aarch64-unknown-linux-gnu/lib/libcompiler_builtins-8750659c02157b46.rlib \
-o f128_demo_clang_with_rustlibs.out

Produces the same output as Rust, incorrect:

./f128_demo_clang_with_rustlibs.out
0x00007fffffffffffffffffffffffffff 0.000000
0x40007fffffffffffffffffffffffffff 3.000000
0x00017ffffffffffffffffffffffffffb 0.000000

rustc 1.80.0-nightly (6e1d94708 2024-05-10)

@tgross35
Copy link
Contributor Author

I think it is a LLVM problem llvm/llvm-project#91840

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

No branches or pull requests

1 participant