diff options
| author | Adhemerval Zanella <adhemerval.zanella@linaro.org> | 2025-10-31 13:08:51 -0300 |
|---|---|---|
| committer | Adhemerval Zanella <adhemerval.zanella@linaro.org> | 2025-11-04 04:14:01 -0300 |
| commit | 0e1a1178ee22a25ff4568f51a2fec85451b17b04 (patch) | |
| tree | 4f500bd6e226c7621c2c557a585f85c8f5070663 /sysdeps/ieee754 | |
| parent | c4c6c79d70888702dcabfb208fbb664d9d9e6667 (diff) | |
math: Remove the SVID error handling from remainder
The optimized i386 version is faster than the generic one, and
gcc implements it through the builtin. This optimization enables
us to migrate the implementation to a C version. The performance
on a Zen3 chip is similar to the SVID one.
The m68k provided an optimized version through __m81_u(remainderf)
(mathimpl.h), and gcc does not implement it through a builtin
(different than i386).
Performance improves a bit on x86_64 (Zen3, gcc 15.2.1):
reciprocal-throughput input master NO-SVID improvement
x86_64 subnormals 18.8522 16.2506 13.80%
x86_64 normal 421.8260 403.9270 4.24%
x86_64 close-exponent 21.0579 18.7642 10.89%
i686 subnormals 21.3443 21.4229 -0.37%
i686 normal 525.8380 538.807 -2.47%
i686 close-exponent 21.6589 21.7983 -0.64%
Tested on x86_64-linux-gnu and i686-linux-gnu.
Reviewed-by: Wilco Dijkstra <Wilco.Dijkstra@arm.com>
Diffstat (limited to 'sysdeps/ieee754')
| -rw-r--r-- | sysdeps/ieee754/dbl-64/e_remainder.c | 30 | ||||
| -rw-r--r-- | sysdeps/ieee754/dbl-64/w_remainder.c | 1 | ||||
| -rw-r--r-- | sysdeps/ieee754/ldbl-opt/w_remainder_compat.c | 2 |
3 files changed, 21 insertions, 12 deletions
diff --git a/sysdeps/ieee754/dbl-64/e_remainder.c b/sysdeps/ieee754/dbl-64/e_remainder.c index dbae3aab81..99c6a754f0 100644 --- a/sysdeps/ieee754/dbl-64/e_remainder.c +++ b/sysdeps/ieee754/dbl-64/e_remainder.c @@ -18,10 +18,12 @@ #include <math.h> #include <libm-alias-finite.h> +#include <libm-alias-double.h> +#include <math-svid-compat.h> #include "math_config.h" double -__ieee754_remainder (double x, double y) +__remainder (double x, double y) { uint64_t hx = asuint64 (x); uint64_t hy = asuint64 (y); @@ -34,12 +36,8 @@ __ieee754_remainder (double x, double y) y = fabs (y); if (__glibc_likely (hy < UINT64_C (0x7fe0000000000000))) { - /* |x| not finite, |y| equal 0 is handled by fmod. */ - if (__glibc_unlikely (hx >= EXPONENT_MASK)) - return (x * y) / (x * y); - - x = fabs (__ieee754_fmod (x, y + y)); - if (x + x > y) + x = fabs (__fmod (x, y + y)); + if (isgreater (x + x, y)) { x -= y; if (x + x >= y) @@ -52,9 +50,9 @@ __ieee754_remainder (double x, double y) } else { - /* |x| not finite or |y| is NaN or 0 */ - if ((hx >= EXPONENT_MASK || (hy - 1) >= EXPONENT_MASK)) - return (x * y) / (x * y); + /* |x| not finite or |y| is NaN */ + if (__glibc_unlikely (hx >= EXPONENT_MASK || hy > EXPONENT_MASK)) + return __math_invalid (x * y); x = fabs (x); double y_half = y * 0.5; @@ -70,4 +68,14 @@ __ieee754_remainder (double x, double y) return sx ? -x : x; } -libm_alias_finite (__ieee754_remainder, __remainder) +libm_alias_finite (__remainder, __remainder) +#if LIBM_SVID_COMPAT +versioned_symbol (libm, __remainder, remainder, GLIBC_2_43); +libm_alias_double_other (__remainder, remainder) +#else +libm_alias_double (__remainder, remainder) +weak_alias (__remainder, drem) +# ifdef NO_LONG_DOUBLE +weak_alias (__remainder, dreml) +# endif +#endif diff --git a/sysdeps/ieee754/dbl-64/w_remainder.c b/sysdeps/ieee754/dbl-64/w_remainder.c new file mode 100644 index 0000000000..db3355f598 --- /dev/null +++ b/sysdeps/ieee754/dbl-64/w_remainder.c @@ -0,0 +1 @@ +/* Not needed */ diff --git a/sysdeps/ieee754/ldbl-opt/w_remainder_compat.c b/sysdeps/ieee754/ldbl-opt/w_remainder_compat.c index 8bdea32c02..ed87fbf7ec 100644 --- a/sysdeps/ieee754/ldbl-opt/w_remainder_compat.c +++ b/sysdeps/ieee754/ldbl-opt/w_remainder_compat.c @@ -1,6 +1,6 @@ #include <math_ldbl_opt.h> #include <math/w_remainder_compat.c> #if LONG_DOUBLE_COMPAT(libm, GLIBC_2_0) -strong_alias (__remainder, __drem) +strong_alias (__remainder_compat, __drem) compat_symbol (libm, __drem, dreml, GLIBC_2_0); #endif |
