-
Notifications
You must be signed in to change notification settings - Fork 15.5k
Description
After enabling experimental clang build support on glibc, the _Float128 powl support shows some regressions:
$ math/test-float128-pow
Failure: pow (-0x1.000002p+0, 0xf.ffffffffffff8p+1020): Exception "Underflow" set
Failure: pow (-0x1.000002p+0, 0xf.ffffffffffffbffffffffffffcp+1020): Exception "Underflow" set
Failure: pow (-0x1.000002p+0, 0xf.fffffffffffffffffffffffffff8p+16380): Exception "Underflow" set
Failure: pow (-0x1.000002p+0, 0xf.fffffffffffffffp+16380): Exception "Underflow" set
Failure: pow (-0x1.000002p+0, 0xf.fffffp+124): Exception "Underflow" set
Failure: pow (-0x1.00000ep+0, 0xf.ffffffffffff8p+1020): Exception "Underflow" set
Failure: pow (-0x1.00000ep+0, 0xf.ffffffffffffbffffffffffffcp+1020): Exception "Underflow" set
Failure: pow (-0x1.00000ep+0, 0xf.fffffffffffffffffffffffffff8p+16380): Exception "Underflow" set
Failure: pow (-0x1.00000ep+0, 0xf.fffffffffffffffp+16380): Exception "Underflow" set
Failure: pow (-0x1.00000ep+0, 0xf.fffffp+124): Exception "Underflow" set
[...]
Test suite completed:
Maximum error found of `2' ulp
4 max error test cases,
11912 input tests,
- with 47792 tests for exception flags,
- with 9350 tests for errno executed.
680 errors occurred.
The issues seems that clang is moving out the the multiplication used to raise overflow/underflow (hugehuge and tinytiny) before the check 'iy' check [1]:
/* |y| is huge.
2^-16495 = 1/2 of smallest representable value.
If (1 - 1/131072)^y underflows, y > 1.4986e9 */
if (iy > 0x401d654b)
{
/* if (1 - 2^-113)^y underflows, y > 1.1873e38 */
if (iy > 0x407d654b)
{
if (ix <= 0x3ffeffff)
return (hy < 0) ? huge * huge : tiny * tiny;
if (ix >= 0x3fff0000)
return (hy > 0) ? huge * huge : tiny * tiny;
}
/* over/underflow if x is not close to one */
if (ix < 0x3ffeffff)
return (hy < 0) ? sgn * huge * huge : sgn * tiny * tiny;
if (ix > 0x3fff0000)
return (hy > 0) ? sgn * huge * huge : sgn * tiny * tiny;
}
If I force the multiplication to be optimized away with the math_opt_barrier barrier, it works as expected.
To reproduce it build the commit be48ae12b10b0556895e356c3ae34b8ca229e61b or higher with clang-18 or higher. Currently only x86_64 and aarch64 is supported, but both exports the implementation (either by powl on aarch64 or powf128 on x86_64). Keep in mind that glibc explicit builds libm and all tests with -ftrapping-math.
I will try to come-up with a more contrieved example.