From: Joseph Myers Date: Thu, 28 Sep 2017 01:59:02 +0000 (+0000) Subject: Fix nearbyint arithmetic moved before feholdexcept (bug 22225). X-Git-Tag: glibc-2.27~847 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f124cb381116b5809de198327690ad0bd8d1478e;p=thirdparty%2Fglibc.git Fix nearbyint arithmetic moved before feholdexcept (bug 22225). In I remarked on the possibility of arithmetic in various nearbyint implementations being scheduled before feholdexcept calls, resulting in spurious "inexact" exceptions. I'm now actually observing this occurring in glibc built for ARM with GCC 7 (in fact, both copies of the same addition/subtraction sequence being combined and moved out before the conditionals and feholdexcept/fesetenv pairs), resulting in test failures. This patch makes the nearbyint implementations with this particular feholdexcept / arithmetic / fesetenv pattern consistently use math_opt_barrier on the function argument when first used in arithmetic, and also consistently use math_force_eval before fesetenv (the latter was generally already done, but the dbl-64/wordsize-64 implementation used math_opt_barrier instead, and as math_opt_barrier's intended effect is through its output value being used, such a use that doesn't use the return value is suspect). Tested for x86_64 (--disable-multi-arch so more of these implementations get used), and for ARM in a configuration where I saw the problem scheduling. [BZ #22225] * sysdeps/ieee754/dbl-64/s_nearbyint.c (__nearbyint): Use math_opt_barrier on argument when doing arithmetic on it. * sysdeps/ieee754/dbl-64/wordsize-64/s_nearbyint.c (__nearbyint): Likewise. Use math_force_eval not math_opt_barrier after arithmetic. * sysdeps/ieee754/flt-32/s_nearbyintf.c (__nearbyintf): Use math_opt_barrier on argument when doing arithmetic on it. * sysdeps/ieee754/ldbl-128/s_nearbyintl.c (__nearbyintl): Likewise. --- diff --git a/ChangeLog b/ChangeLog index 2e29752af70..60c9521e6b6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,16 @@ +2017-09-28 Joseph Myers + + [BZ #22225] + * sysdeps/ieee754/dbl-64/s_nearbyint.c (__nearbyint): Use + math_opt_barrier on argument when doing arithmetic on it. + * sysdeps/ieee754/dbl-64/wordsize-64/s_nearbyint.c (__nearbyint): + Likewise. Use math_force_eval not math_opt_barrier after + arithmetic. + * sysdeps/ieee754/flt-32/s_nearbyintf.c (__nearbyintf): Use + math_opt_barrier on argument when doing arithmetic on it. + * sysdeps/ieee754/ldbl-128/s_nearbyintl.c (__nearbyintl): + Likewise. + 2017-09-27 H.J. Lu * sysdeps/unix/sysv/linux/ifaddrs.c (__getifaddrs): Add diff --git a/sysdeps/ieee754/dbl-64/s_nearbyint.c b/sysdeps/ieee754/dbl-64/s_nearbyint.c index dec0c5d6eef..6e3f8316b18 100644 --- a/sysdeps/ieee754/dbl-64/s_nearbyint.c +++ b/sysdeps/ieee754/dbl-64/s_nearbyint.c @@ -48,7 +48,7 @@ __nearbyint (double x) if (j0 < 0) { libc_feholdexcept (&env); - w = TWO52[sx] + x; + w = TWO52[sx] + math_opt_barrier (x); t = w - TWO52[sx]; math_force_eval (t); libc_fesetenv (&env); @@ -65,7 +65,7 @@ __nearbyint (double x) return x; /* x is integral */ } libc_feholdexcept (&env); - w = TWO52[sx] + x; + w = TWO52[sx] + math_opt_barrier (x); t = w - TWO52[sx]; math_force_eval (t); libc_fesetenv (&env); diff --git a/sysdeps/ieee754/dbl-64/wordsize-64/s_nearbyint.c b/sysdeps/ieee754/dbl-64/wordsize-64/s_nearbyint.c index 82938199817..7d135b54e4a 100644 --- a/sysdeps/ieee754/dbl-64/wordsize-64/s_nearbyint.c +++ b/sysdeps/ieee754/dbl-64/wordsize-64/s_nearbyint.c @@ -42,9 +42,9 @@ __nearbyint(double x) if(__builtin_expect(j0<52, 1)) { if(j0<0) { libc_feholdexcept (&env); - double w = TWO52[sx]+x; + double w = TWO52[sx] + math_opt_barrier (x); double t = w-TWO52[sx]; - math_opt_barrier(t); + math_force_eval (t); libc_fesetenv (&env); return __copysign (t, x); } @@ -53,9 +53,9 @@ __nearbyint(double x) else return x; /* x is integral */ } libc_feholdexcept (&env); - double w = TWO52[sx]+x; + double w = TWO52[sx] + math_opt_barrier (x); double t = w-TWO52[sx]; - math_opt_barrier (t); + math_force_eval (t); libc_fesetenv (&env); return t; } diff --git a/sysdeps/ieee754/flt-32/s_nearbyintf.c b/sysdeps/ieee754/flt-32/s_nearbyintf.c index afacdef67cf..a8af8948ec2 100644 --- a/sysdeps/ieee754/flt-32/s_nearbyintf.c +++ b/sysdeps/ieee754/flt-32/s_nearbyintf.c @@ -38,7 +38,7 @@ __nearbyintf(float x) if(j0<23) { if(j0<0) { libc_feholdexceptf (&env); - w = TWO23[sx]+x; + w = TWO23[sx] + math_opt_barrier (x); t = w-TWO23[sx]; math_force_eval (t); libc_fesetenvf (&env); @@ -51,7 +51,7 @@ __nearbyintf(float x) else return x; /* x is integral */ } libc_feholdexceptf (&env); - w = TWO23[sx]+x; + w = TWO23[sx] + math_opt_barrier (x); t = w-TWO23[sx]; math_force_eval (t); libc_fesetenvf (&env); diff --git a/sysdeps/ieee754/ldbl-128/s_nearbyintl.c b/sysdeps/ieee754/ldbl-128/s_nearbyintl.c index 631b0e0c714..c1ee68be638 100644 --- a/sysdeps/ieee754/ldbl-128/s_nearbyintl.c +++ b/sysdeps/ieee754/ldbl-128/s_nearbyintl.c @@ -45,7 +45,7 @@ _Float128 __nearbyintl(_Float128 x) if(j0<112) { if(j0<0) { feholdexcept (&env); - w = TWO112[sx]+x; + w = TWO112[sx] + math_opt_barrier (x); t = w-TWO112[sx]; math_force_eval (t); fesetenv (&env); @@ -58,7 +58,7 @@ _Float128 __nearbyintl(_Float128 x) else return x; /* x is integral */ } feholdexcept (&env); - w = TWO112[sx]+x; + w = TWO112[sx] + math_opt_barrier (x); t = w-TWO112[sx]; math_force_eval (t); fesetenv (&env);