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

multf3 has incorrect rounding on aarch64 linux #91840

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

multf3 has incorrect rounding on aarch64 linux #91840

tgross35 opened this issue May 11, 2024 · 1 comment

Comments

@tgross35
Copy link

tgross35 commented May 11, 2024

Testing with the following program:

#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;
}

Using the built-in version of Clang that links against system libraries gets the multf3 symbol from either /usr/lib/gcc/aarch64-linux-gnu/11/libgcc.a or /usr/lib/llvm-14/lib/clang/14.0.0/lib/linux/libclang_rt.builtins-aarch64.a. This is the output, which is correct:

$ clang f128_demo.c -o f128_demo
$ ./f128_demo
0x00007fffffffffffffffffffffffffff 0.000000
0x40007fffffffffffffffffffffffffff 3.000000
0x00017ffffffffffffffffffffffffffc 0.000000

However, building with the current multf3.c produces an incorrect value (note the ending b):

$ clang f128_demo.c llvm-project/compiler-rt/lib/builtins/multf3.c -o f128_demo_current_rt
$ ./f128_demo_current_rt
0x00007fffffffffffffffffffffffffff 0.000000
0x40007fffffffffffffffffffffffffff 3.000000
0x00017ffffffffffffffffffffffffffb 0.000000

This was just tested in a ubuntu docker container which has Clang 14.0.0 and GCC 11.4.0

@llvmbot
Copy link
Collaborator

llvmbot commented May 11, 2024

@llvm/issue-subscribers-backend-aarch64

Author: Trevor Gross (tgross35)

Testing with the following program:
#define __STDC_WANT_IEC_60559_TYPES_EXT__

#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;inttypes.h&gt;

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

typedef struct {
    uint64_t lower, upper;
} u128;


void f128_print(_Float128 val) {
    u128 ival = *((u128 *)(&amp;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 *)(&amp;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;
}

Using the builtin version of Clang that links against system libraries gets the multf3 symbol from either /usr/lib/gcc/aarch64-linux-gnu/11/libgcc.a or /usr/lib/llvm-14/lib/clang/14.0.0/lib/linux/libclang_rt.builtins-aarch64.a. This is the output, which is correct:

$ clang f128_demo.c -o f128_demo
$ ./f128_demo
0x00007fffffffffffffffffffffffffff 0.000000
0x40007fffffffffffffffffffffffffff 3.000000
0x00017ffffffffffffffffffffffffffc 0.000000

However, building with the current multf3.c produces an incorrect value (note the ending b):

$ clang f128_demo.c llvm-project/compiler-rt/lib/builtins/multf3.c -o f128_demo_current_rt
$ ./f128_demo_current_rt
0x00007fffffffffffffffffffffffffff 0.000000
0x40007fffffffffffffffffffffffffff 3.000000
0x00017ffffffffffffffffffffffffffb 0.000000

This was just tested in a ubuntu docker container which has clang 14.0.0 and gcc 11.4.0

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

3 participants