]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
Fix nearbyint arithmetic moved before feholdexcept (bug 22225).
authorJoseph Myers <joseph@codesourcery.com>
Thu, 28 Sep 2017 01:59:02 +0000 (01:59 +0000)
committerJoseph Myers <joseph@codesourcery.com>
Thu, 28 Sep 2017 02:03:21 +0000 (02:03 +0000)
In <https://sourceware.org/ml/libc-alpha/2013-05/msg00722.html> 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.

(cherry picked from commit f124cb381116b5809de198327690ad0bd8d1478e)

ChangeLog
sysdeps/ieee754/dbl-64/s_nearbyint.c
sysdeps/ieee754/dbl-64/wordsize-64/s_nearbyint.c
sysdeps/ieee754/flt-32/s_nearbyintf.c
sysdeps/ieee754/ldbl-128/s_nearbyintl.c

index 382674d5a3306685f5bb0766d80b5e0b7ffe567a..992722acdb133553807cb47bab28d8834090bb0e 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+2017-09-28  Joseph Myers  <joseph@codesourcery.com>
+
+       [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-22  Gabriel F. T. Gomes  <gabriel@inconstante.eti.br>
 
        [BZ #22146]
index dec0c5d6eefa9a9ce2084691be9b7c9887428044..6e3f8316b18d88a98032d16c43cd028145861aba 100644 (file)
@@ -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);
index 82938199817c454c7050ca28302450d0874fa8f4..7d135b54e4ae920d2668f3bf4238465f964dbef8 100644 (file)
@@ -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;
 }
index 5aebefafcfb38c1e581bc6beb50a2d946e24d966..b06df6b3c83f6455ee2aafee1db401ddbb3e8ecb 100644 (file)
@@ -37,7 +37,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);
@@ -50,7 +50,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);
index 1565a8183f1a933d7318d7adba45f68aa47fc3fb..98a33d24a78c681c2aa69a7d71283d88282e20ba 100644 (file)
@@ -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);