]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
Fix powerpc nearbyint wrongly clearing "inexact" and leaving traps disabled (bug...
authorJoseph Myers <joseph@codesourcery.com>
Wed, 11 Nov 2015 00:06:09 +0000 (00:06 +0000)
committerJoseph Myers <joseph@codesourcery.com>
Wed, 11 Nov 2015 00:06:09 +0000 (00:06 +0000)
Similar to bug 15491 recently fixed for x86_64 / x86, the powerpc
(both powerpc32 and powerpc64) hard-float implementations of
nearbyintf and nearbyint wrongly clear an "inexact" exception that was
raised before the function was called; this shows up as failure of the
test math/test-nearbyint-except added when that bug was fixed.  They
also wrongly leave traps on "inexact" disabled if they were enabled
before the function was called.

This patch fixes the bugs similar to how the x86 bug was fixed: saving
and restoring the whole floating-point state, both to restore the
original "inexact" flag state and to restore the original state of
whether traps on "inexact" were enabled.  Because there's a convenient
point in the powerpc implementations to save state after any sNaN
arguments will have raised "invalid" but before "inexact" traps need
to be disabled, no special handling for "invalid" is needed as in the
x86 version.

Tested for powerpc64 and powerpc32, where it fixes the
math/test-nearbyint-except failure as well as fixing the new test
math/test-nearbyint-except-2 added by this patch.  Also tested for
x86_64 and x86 that the new test passes.

If powerpc experts see a more efficient way of doing this
(e.g. instruction positioning that's better for pipelines on typical
processors) then of course followups optimizing the fix are welcome.

[BZ #19228]
* sysdeps/powerpc/powerpc32/fpu/s_nearbyint.S (__nearbyint): Save
and restore full floating-point state.
* sysdeps/powerpc/powerpc32/fpu/s_nearbyintf.S (__nearbyintf):
Likewise.
* sysdeps/powerpc/powerpc64/fpu/s_nearbyint.S (__nearbyint):
Likewise.
* sysdeps/powerpc/powerpc64/fpu/s_nearbyintf.S (__nearbyintf):
Likewise.
* math/test-nearbyint-except-2.c: New file.
* math/Makefile (tests): Add test-nearbyint-except-2.

ChangeLog
math/Makefile
math/test-nearbyint-except-2.c [new file with mode: 0644]
sysdeps/powerpc/powerpc32/fpu/s_nearbyint.S
sysdeps/powerpc/powerpc32/fpu/s_nearbyintf.S
sysdeps/powerpc/powerpc64/fpu/s_nearbyint.S
sysdeps/powerpc/powerpc64/fpu/s_nearbyintf.S

index 51faaed4c236f59acffd6a200b1f187f19e7b5b4..b23297b29bfe8e354fdf9e8f796cf393ed3dfd12 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,17 @@
+2015-11-10  Joseph Myers  <joseph@codesourcery.com>
+
+       [BZ #19228]
+       * sysdeps/powerpc/powerpc32/fpu/s_nearbyint.S (__nearbyint): Save
+       and restore full floating-point state.
+       * sysdeps/powerpc/powerpc32/fpu/s_nearbyintf.S (__nearbyintf):
+       Likewise.
+       * sysdeps/powerpc/powerpc64/fpu/s_nearbyint.S (__nearbyint):
+       Likewise.
+       * sysdeps/powerpc/powerpc64/fpu/s_nearbyintf.S (__nearbyintf):
+       Likewise.
+       * math/test-nearbyint-except-2.c: New file.
+       * math/Makefile (tests): Add test-nearbyint-except-2.
+
 2015-11-10  H.J. Lu  <hongjiu.lu@intel.com>
 
        [BZ #19178]
index ec9e6b29d1a2ccb1e4110f9e545105d16f174e7d..06412f3980664d85b919b1ee9832647081955145 100644 (file)
@@ -109,7 +109,8 @@ tests = test-matherr test-fenv atest-exp atest-sincos atest-exp2 basic-test \
        test-tgmath-int test-tgmath2 test-powl tst-CMPLX tst-CMPLX2 test-snan \
        test-fenv-tls test-fenv-preserve test-fenv-return test-fenvinline \
        test-nearbyint-except test-fenv-clear test-signgam-finite \
-       test-signgam-finite-c99 test-signgam-finite-c11 $(tests-static)
+       test-signgam-finite-c99 test-signgam-finite-c11 \
+       test-nearbyint-except-2 $(tests-static)
 tests-static = test-fpucw-static test-fpucw-ieee-static
 # We do the `long double' tests only if this data type is available and
 # distinct from `double'.
diff --git a/math/test-nearbyint-except-2.c b/math/test-nearbyint-except-2.c
new file mode 100644 (file)
index 0000000..04faac3
--- /dev/null
@@ -0,0 +1,72 @@
+/* Test nearbyint functions do not disable exception traps (bug 19228).
+   Copyright (C) 2015 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <fenv.h>
+#include <math.h>
+#include <stdio.h>
+
+#ifndef FE_INEXACT
+# define FE_INEXACT 0
+#endif
+
+#define TEST_FUNC(NAME, FLOAT, SUFFIX)                                 \
+static int                                                             \
+NAME (void)                                                            \
+{                                                                      \
+  int result = 0;                                                      \
+  volatile FLOAT a, b __attribute__ ((unused));                                \
+  a = 1.5;                                                             \
+  /* nearbyint must work when traps on "inexact" are enabled.  */      \
+  b = nearbyint ## SUFFIX (a);                                         \
+  /* And it must have left those traps enabled.  */                    \
+  if (fegetexcept () == FE_INEXACT)                                    \
+    puts ("PASS: " #FLOAT);                                            \
+  else                                                                 \
+    {                                                                  \
+      puts ("FAIL: " #FLOAT);                                          \
+      result = 1;                                                      \
+    }                                                                  \
+  return result;                                                       \
+}
+
+TEST_FUNC (float_test, float, f)
+TEST_FUNC (double_test, double, )
+#ifndef NO_LONG_DOUBLE
+TEST_FUNC (ldouble_test, long double, l)
+#endif
+
+static int
+do_test (void)
+{
+  if (feenableexcept (FE_INEXACT) == -1)
+    {
+      puts ("enabling FE_INEXACT traps failed, cannot test");
+      return 77;
+    }
+  int result = float_test ();
+  feenableexcept (FE_INEXACT);
+  result |= double_test ();
+#ifndef NO_LONG_DOUBLE
+  feenableexcept (FE_INEXACT);
+  result |= ldouble_test ();
+#endif
+  return result;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
index cee4c7b2396346aeac4c21fa56cabca2441392f2..27673b67e1a78d7ec4c923f61a7b107a9d1573ae 100644 (file)
@@ -52,19 +52,21 @@ ENTRY (__nearbyint)
        bgelr   cr7
        fcmpu   cr7,fp1,fp12    /* if (x > 0.0 */
        ble     cr7,L(lessthanzero)
+       mffs    fp11
        mtfsb0  4*cr7+lt        /* Disable FE_INEXACT exception */
        fadd    fp1,fp1,fp13    /* x += TWO52 */
        fsub    fp1,fp1,fp13    /* x -= TWO52 */
        fabs    fp1,fp1         /* if (x == 0.0 */
-       mtfsb0  4*cr1+eq        /* Clear any FE_INEXACT exception */
+       mtfsf   0xff,fp11       /* Restore FE_INEXACT state.  */
        blr
 L(lessthanzero):
        bgelr   cr7
+       mffs    fp11
        mtfsb0  4*cr7+lt        /* Disable FE_INEXACT exception */
        fsub    fp1,fp1,fp13    /* x -= TWO52 */
        fadd    fp1,fp1,fp13    /* x += TWO52 */
        fnabs   fp1,fp1         /* if (x == 0.0) */
-       mtfsb0  4*cr1+eq        /* Clear any FE_INEXACT exception */
+       mtfsf   0xff,fp11       /* Restore FE_INEXACT state.  */
        blr
 END (__nearbyint)
 
index 96a39c673dccc35314eb8976d1f68f0b93a2d405..a5084b26153abbf2af1f4f4ec0427fa81160a644 100644 (file)
@@ -51,19 +51,21 @@ ENTRY (__nearbyintf)
        bgelr   cr7
        fcmpu   cr7,fp1,fp12            /* if (x > 0.0 */
        ble     cr7,L(lessthanzero)
+       mffs    fp11
        mtfsb0  4*cr7+lt                /* Disable FE_INEXACT exception */
        fadds   fp1,fp1,fp13            /* x += TWO23 */
        fsubs   fp1,fp1,fp13            /* x -= TWO23 */
        fabs    fp1,fp1                 /* if (x == 0.0) */
-       mtfsb0  4*cr1+eq                /* Clear any FE_INEXACT exception */
+       mtfsf   0xff,fp11               /* Restore FE_INEXACT state.  */
        blr
 L(lessthanzero):
        bgelr   cr7
+       mffs    fp11
        mtfsb0  4*cr7+lt                /* Disable FE_INEXACT exception */
        fsubs   fp1,fp1,fp13            /* x -= TWO23 */
        fadds   fp1,fp1,fp13            /* x += TWO23 */
        fnabs   fp1,fp1                 /* if (x == 0.0) */
-       mtfsb0  4*cr1+eq                /* Clear any FE_INEXACT exception */
+       mtfsf   0xff,fp11               /* Restore FE_INEXACT state.  */
        blr
 END (__nearbyintf)
 
index 6654840f7fcd9c7bccdc70bb98a4e6b1e7026255..9c87596cc44ed49104bd0f0fae87fd37cb4028b3 100644 (file)
@@ -40,19 +40,21 @@ EALIGN (__nearbyint, 4, 0)
        fsub    fp12,fp13,fp13  /* generate 0.0 */
        fcmpu   cr7,fp1,fp12    /* if (x > 0.0) */
        ble     cr7, L(lessthanzero)
+       mffs    fp11
        mtfsb0  4*cr7+lt        /* Disable FE_INEXACT exception */
        fadd    fp1,fp1,fp13    /* x+= TWO52 */
        fsub    fp1,fp1,fp13    /* x-= TWO52 */
        fabs    fp1,fp1         /* if (x == 0.0) */
-       mtfsb0  4*cr1+eq        /* Clear any FE_INEXACT exception */
+       mtfsf   0xff,fp11       /* Restore FE_INEXACT state.  */
        blr                     /* x = 0.0; */
 L(lessthanzero):
        bgelr   cr7             /* if (x < 0.0) */
+       mffs    fp11
        mtfsb0  4*cr7+lt
        fsub    fp1,fp1,fp13    /* x -= TWO52 */
        fadd    fp1,fp1,fp13    /* x += TWO52 */
        fnabs   fp1,fp1         /* if (x == 0.0) */
-       mtfsb0  4*cr1+eq
+       mtfsf   0xff,fp11       /* Restore FE_INEXACT state.  */
        blr                     /* x = -0.0; */
 END (__nearbyint)
 
index 041dfeb46ea3c00302a80941919152ec081dbe8a..9dfbce6b9cd7ecd7bb95acffc6f2f7a238cb8ad9 100644 (file)
@@ -41,19 +41,21 @@ EALIGN (__nearbyintf, 4, 0)
        fsubs   fp12,fp13,fp13  /* generate 0.0 */
        fcmpu   cr7,fp1,fp12    /* if (x > 0.0)  */
        ble     cr7, L(lessthanzero)
+       mffs    fp11
        mtfsb0  4*cr7+lt        /* Disable FE_INEXACT exception */
        fadds   fp1,fp1,fp13    /* x += TWO23 */
        fsubs   fp1,fp1,fp13    /* x -= TWO23 */
        fabs    fp1,fp1         /* if (x == 0.0) */
-       mtfsb0  4*cr1+eq        /* Clear pending FE_INEXACT exception */
+       mtfsf   0xff,fp11       /* Restore FE_INEXACT state.  */
        blr                     /* x = 0.0; */
 L(lessthanzero):
        bgelr   cr7             /* if (x < 0.0) */
+       mffs    fp11
        mtfsb0  4*cr7+lt        /* Disable FE_INEXACT exception */
        fsubs   fp1,fp1,fp13    /* x -= TWO23 */
        fadds   fp1,fp1,fp13    /* x += TWO23 */
        fnabs   fp1,fp1         /* if (x == 0.0) */
-       mtfsb0  4*cr1+eq        /* Clear pending FE_INEXACT exception */
+       mtfsf   0xff,fp11       /* Restore FE_INEXACT state.  */
        blr                     /* x = -0.0; */
 END (__nearbyintf)