llvm / llvm-project

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

cbrt(2.0) computed differently by llvm and gcc #46253

Open BalaRishi-AMD opened 4 years ago

BalaRishi-AMD commented 4 years ago
Bugzilla Link 46909
Version trunk
OS Linux
CC @efriedma-quic,@RKSimon,@rotateright

Extended Description

$ cat foo.c

include

include

include

include

int main() { double d; d = 2.0; printf("pow((2.0), 1.0/3.0) = % .16e\n", pow((2.0), 1.0/3.0)); printf("cbrt(2.0) = % .16e\n", cbrt(2.0)); }

$ gcc foo.c -o foo -lm $ ./foo pow((2.0), 1.0/3.0) = 1.2599210498948732e+00 cbrt(2.0) = 1.2599210498948732e+00

$ clang foo.c -o foo -lm $ ./foo pow((2.0), 1.0/3.0) = 1.2599210498948732e+00 cbrt(2.0) = 1.2599210498948734e+00 // <====

efriedma-quic commented 4 years ago

This is potentially a counter-point to bug 46376, comment 15. We are relying on the system, but still getting blamed for an FP accuracy bug.

The way these functions are defined is fundamentally weird: for almost every other library function, the result is precisely predictable. But the math functions can return whatever they want.

Does this mean that gcc has its own implementation of cbrt() that is more accurate than the system's?

gcc uses MPFR for compile-time constant folding, which always produces correctly rounded results.

rotateright commented 4 years ago

Assuming again that host == target, I think we would see the same result independent of whether we constant fold the call or not.

So even though our cbrt() handling is not consistent with most libm calls, I don't see how this is a compiler bug rather than a bug for the system's (some version of Linux?) math library.

This is potentially a counter-point to bug 46376, comment 15. We are relying on the system, but still getting blamed for an FP accuracy bug.

Does this mean that gcc has its own implementation of cbrt() that is more accurate than the system's?

efriedma-quic commented 4 years ago

It looks like host and target are the same from the description, but would it be more accurate to say clang is using the target's libm in this case?

Ie, unlike most mathlib calls, we are not constant folding calls to cbrt() even when compiling with optimization:

Somehow got confused here. Yes, you're right, we're not folding it at all.

rotateright commented 4 years ago

clang is using the host's libm to compute cbrt. Apparently the error of that implementation is greater than 1 ulp.

It looks like host and target are the same from the description, but would it be more accurate to say clang is using the target's libm in this case?

Ie, unlike most mathlib calls, we are not constant folding calls to cbrt() even when compiling with optimization:

$ clang cbrt.c -w -O2 -S -o - | grep cbrt callq _cbrt

efriedma-quic commented 4 years ago

clang is using the host's libm to compute cbrt. Apparently the error of that implementation is greater than 1 ulp.