llvm / llvm-project

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
http://llvm.org
Other
27.91k stars 11.51k forks source link

[builtins] divtc3 accuracy issue #86871

Open vzakhari opened 5 months ago

vzakhari commented 5 months ago

I am getting quite incorrect result for _Complex __float128 division with clang 17.0.6. GCC 13.2.0 version returns closer result.

I used libquadmath for printing the results. Here is a reproducer:

#include <complex.h>
#include <quadmath.h>
#include <stdio.h>

#define complex128 _Complex __float128

int main() {
  char buffer[1000];
  complex128 z1 = {4.181214e+4931Q, -1.113838e+4932Q};
  complex128 z2 = {-1.113838e+4932Q, -4.181214e+4931Q};
  quadmath_snprintf(buffer, sizeof buffer, "%.6Qe", __real__ z1);
  printf("z1: %s ", buffer);
  quadmath_snprintf(buffer, sizeof buffer, "%.6Qe", __imag__ z1);
  printf("%s\n", buffer);
  quadmath_snprintf(buffer, sizeof buffer, "%.6Qe", __real__ z2);
  printf("z2: %s ", buffer);
  quadmath_snprintf(buffer, sizeof buffer, "%.6Qe", __imag__ z2);
  printf("%s\n", buffer);
  z1 /= z2;
  quadmath_snprintf(buffer, sizeof buffer, "%.6Qe", __real__ z1);
  printf("z1/z2: %s ", buffer);
  quadmath_snprintf(buffer, sizeof buffer, "%.6Qe", __imag__ z1);
  printf("%s\n", buffer);
  return 0;
}

Compilation with clang testdiv.c -I ${GCC_INSTALL}/lib/gcc/x86_64-pc-linux-gnu/13.2.0/include ${GCC_INSTALL}/lib64/libquadmath.a -lm --gcc-toolchain=${GCC_INSTALL}:

z1: 4.181214e+4931 -1.113838e+4932
z2: -1.113838e+4932 -4.181214e+4931
z1/z2: -0.000000e+00 1.000000e+00

This is close to the correct mathematical result: https://www.wolframalpha.com/input?i=%284.181214e%2B4931+-1.113838e%2B4932i%29%2F%28-1.113838e%2B4932+-4.181214e%2B4931i%29

When I link the builtins library with clang testdiv.c -I ${GCC_INSTALL}/lib/gcc/x86_64-pc-linux-gnu/13.2.0/include ${GCC_INSTALL}/lib64/libquadmath.a -lm ${CLANG_INSTALL}/lib/clang/17/lib/x86_64-unknown-linux-gnu/libclang_rt.builtins.a --gcc-toolchain=${GCC_INSTALL} I get this:

z1: 4.181214e+4931 -1.113838e+4932
z2: -1.113838e+4932 -4.181214e+4931
z1/z2: 1.680232e-4932 1.680232e-4932
tgross35 commented 3 months ago

Is this possibly the same issue as https://github.com/llvm/llvm-project/issues/93401?

vzakhari commented 3 months ago

I am not sure about this. The __divtc3 implementation does rely on FP division (i.e. __divtf3), but it is a bit more than just FP division. One will have to check if resolving https://github.com/llvm/llvm-project/issues/93401 resolves this issue as well.