]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
soft-fp: support after-rounding tininess detection.
authorJoseph Myers <joseph@codesourcery.com>
Wed, 12 Feb 2014 18:27:12 +0000 (18:27 +0000)
committerJoseph Myers <joseph@codesourcery.com>
Wed, 12 Feb 2014 18:27:12 +0000 (18:27 +0000)
IEEE 754-2008 defines two ways in which tiny results can be detected,
"before rounding" (based on the infinite-precision result) and "after
rounding" (based on the result when rounded to normal precision as if
the exponent range were unbounded).  All binary operations on an
architecture must use the same choice of how tininess is detected.

soft-fp has so far implemented only before-rounding tininess
detection.  This patch adds support for after-rounding tininess
detection.  A new macro _FP_TININESS_AFTER_ROUNDING is added that
sfp-machine.h must define (soft-fp is meant to be self-contained so
the existing tininess.h files aren't used here, though the information
going in sfp-machine.h has been taken from them).  The soft-fp macros
dealing with raising underflow exceptions then handle the cases where
the choice matters specially, rounding a copy of the input to the
appropriate precision to see if a value that's tiny before rounding
isn't tiny after rounding.

Tested for mips64 using GCC trunk (which now uses soft-fp on MIPS, so
supporting exceptions and rounding modes for long double where not
previously supported - this is the immediate motivation for doing this
patch now) together with (a) a patch to sysdeps/mips/math-tests.h to
enable exceptions / rounding modes tests for long double for GCC 4.9
and later, and (b) corresponding changes applied to libgcc's soft-fp
and sfp-machine.h files.  In the libgcc context this is also tested on
x86_64 (also an after-rounding architecture) with testcases for
__float128 that I intend to add to the GCC testsuite when updating
soft-fp there.

(To be clear: this patch does not fix any glibc bugs that were
user-visible in past releases, since after-rounding architectures
didn't use soft-fp in any affected case with support for
floating-point exceptions - so there is no corresponding Bugzilla bug.
Rather, it works together with the GCC changes to use soft-fp on MIPS
to allow previously absent long double functionality to work properly,
and allows soft-fp to be used in glibc on after-rounding architectures
in cases where it couldn't previously be used.)

* soft-fp/op-common.h (_FP_DECL): Mark exponent as possibly
unused.
(_FP_PACK_SEMIRAW): Determine tininess based on rounding shifted
value if _FP_TININESS_AFTER_ROUNDING and unrounded value is in
subnormal range.
(_FP_PACK_CANONICAL): Determine tininess based on rounding to
normal precision if _FP_TININESS_AFTER_ROUNDING and unrounded
value has largest subnormal exponent.
* soft-fp/soft-fp.h [FP_NO_EXCEPTIONS]
(_FP_TININESS_AFTER_ROUNDING): Undefine and redefine to 0.
* sysdeps/aarch64/soft-fp/sfp-machine.h
(_FP_TININESS_AFTER_ROUNDING): New macro.
* sysdeps/alpha/soft-fp/sfp-machine.h
(_FP_TININESS_AFTER_ROUNDING): Likewise.
* sysdeps/arm/soft-fp/sfp-machine.h (_FP_TININESS_AFTER_ROUNDING):
Likewise.
* sysdeps/mips/mips64/soft-fp/sfp-machine.h
(_FP_TININESS_AFTER_ROUNDING): Likewise.
* sysdeps/mips/soft-fp/sfp-machine.h
(_FP_TININESS_AFTER_ROUNDING): Likewise.
* sysdeps/powerpc/soft-fp/sfp-machine.h
(_FP_TININESS_AFTER_ROUNDING): Likewise.
* sysdeps/sh/soft-fp/sfp-machine.h (_FP_TININESS_AFTER_ROUNDING):
Likewise.
* sysdeps/sparc/sparc32/soft-fp/sfp-machine.h
(_FP_TININESS_AFTER_ROUNDING): Likewise.
* sysdeps/sparc/sparc64/soft-fp/sfp-machine.h
(_FP_TININESS_AFTER_ROUNDING): Likewise.
* sysdeps/tile/sfp-machine.h (_FP_TININESS_AFTER_ROUNDING):
Likewise.

13 files changed:
ChangeLog
soft-fp/op-common.h
soft-fp/soft-fp.h
sysdeps/aarch64/soft-fp/sfp-machine.h
sysdeps/alpha/soft-fp/sfp-machine.h
sysdeps/arm/soft-fp/sfp-machine.h
sysdeps/mips/mips64/soft-fp/sfp-machine.h
sysdeps/mips/soft-fp/sfp-machine.h
sysdeps/powerpc/soft-fp/sfp-machine.h
sysdeps/sh/soft-fp/sfp-machine.h
sysdeps/sparc/sparc32/soft-fp/sfp-machine.h
sysdeps/sparc/sparc64/soft-fp/sfp-machine.h
sysdeps/tile/sfp-machine.h

index ffdb54696cfb059efb31f43ce2d58b73cb7675fa..a7dc4124925a668675b56c055af471cc774d6afe 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,36 @@
+2014-02-12  Joseph Myers  <joseph@codesourcery.com>
+
+       * soft-fp/op-common.h (_FP_DECL): Mark exponent as possibly
+       unused.
+       (_FP_PACK_SEMIRAW): Determine tininess based on rounding shifted
+       value if _FP_TININESS_AFTER_ROUNDING and unrounded value is in
+       subnormal range.
+       (_FP_PACK_CANONICAL): Determine tininess based on rounding to
+       normal precision if _FP_TININESS_AFTER_ROUNDING and unrounded
+       value has largest subnormal exponent.
+       * soft-fp/soft-fp.h [FP_NO_EXCEPTIONS]
+       (_FP_TININESS_AFTER_ROUNDING): Undefine and redefine to 0.
+       * sysdeps/aarch64/soft-fp/sfp-machine.h
+       (_FP_TININESS_AFTER_ROUNDING): New macro.
+       * sysdeps/alpha/soft-fp/sfp-machine.h
+       (_FP_TININESS_AFTER_ROUNDING): Likewise.
+       * sysdeps/arm/soft-fp/sfp-machine.h (_FP_TININESS_AFTER_ROUNDING):
+       Likewise.
+       * sysdeps/mips/mips64/soft-fp/sfp-machine.h
+       (_FP_TININESS_AFTER_ROUNDING): Likewise.
+       * sysdeps/mips/soft-fp/sfp-machine.h
+       (_FP_TININESS_AFTER_ROUNDING): Likewise.
+       * sysdeps/powerpc/soft-fp/sfp-machine.h
+       (_FP_TININESS_AFTER_ROUNDING): Likewise.
+       * sysdeps/sh/soft-fp/sfp-machine.h (_FP_TININESS_AFTER_ROUNDING):
+       Likewise.
+       * sysdeps/sparc/sparc32/soft-fp/sfp-machine.h
+       (_FP_TININESS_AFTER_ROUNDING): Likewise.
+       * sysdeps/sparc/sparc64/soft-fp/sfp-machine.h
+       (_FP_TININESS_AFTER_ROUNDING): Likewise.
+       * sysdeps/tile/sfp-machine.h (_FP_TININESS_AFTER_ROUNDING):
+       Likewise.
+
 2014-02-12  Dylan Alex Simon  <dylan@dylex.net>
 
        [BZ #16545]
index e901981b95ee49f72671d7e98eb79137c9283567..6f8c1f3cb04c1300a37be433b528c44d5d464103 100644 (file)
@@ -32,7 +32,7 @@
 #define _FP_DECL(wc, X)                                \
   _FP_I_TYPE X##_c __attribute__ ((unused));   \
   _FP_I_TYPE X##_s __attribute__ ((unused));   \
-  _FP_I_TYPE X##_e;                            \
+  _FP_I_TYPE X##_e __attribute__ ((unused));   \
   _FP_FRAC_DECL_##wc (X)
 
 /* Test whether the qNaN bit denotes a signaling NaN.  */
 #define _FP_PACK_SEMIRAW(fs, wc, X)                            \
   do                                                           \
     {                                                          \
+      int _FP_PACK_SEMIRAW_is_tiny                             \
+       = X##_e == 0 && !_FP_FRAC_ZEROP_##wc (X);               \
+      if (_FP_TININESS_AFTER_ROUNDING                          \
+         && _FP_PACK_SEMIRAW_is_tiny)                          \
+       {                                                       \
+         FP_DECL_##fs (_FP_PACK_SEMIRAW_T);                    \
+         _FP_FRAC_COPY_##wc (_FP_PACK_SEMIRAW_T, X);           \
+         _FP_PACK_SEMIRAW_T##_s = X##_s;                       \
+         _FP_PACK_SEMIRAW_T##_e = X##_e;                       \
+         _FP_FRAC_SLL_##wc (_FP_PACK_SEMIRAW_T, 1);            \
+         _FP_ROUND (wc, _FP_PACK_SEMIRAW_T);                   \
+         if (_FP_FRAC_OVERP_##wc (fs, _FP_PACK_SEMIRAW_T))     \
+           _FP_PACK_SEMIRAW_is_tiny = 0;                       \
+       }                                                       \
       _FP_ROUND (wc, X);                                       \
-      if (X##_e == 0 && !_FP_FRAC_ZEROP_##wc (X))              \
+      if (_FP_PACK_SEMIRAW_is_tiny)                            \
        {                                                       \
          if ((FP_CUR_EXCEPTIONS & FP_EX_INEXACT)               \
              || (FP_TRAPPING_EXCEPTIONS & FP_EX_UNDERFLOW))    \
          else                                                          \
            {                                                           \
              /* we've got a denormalized number */                     \
+             int _FP_PACK_CANONICAL_is_tiny = 1;                       \
+             if (_FP_TININESS_AFTER_ROUNDING && X##_e == 0)            \
+               {                                                       \
+                 FP_DECL_##fs (_FP_PACK_CANONICAL_T);                  \
+                 _FP_FRAC_COPY_##wc (_FP_PACK_CANONICAL_T, X);         \
+                 _FP_PACK_CANONICAL_T##_s = X##_s;                     \
+                 _FP_PACK_CANONICAL_T##_e = X##_e;                     \
+                 _FP_ROUND (wc, _FP_PACK_CANONICAL_T);                 \
+                 if (_FP_FRAC_OVERP_##wc (fs, _FP_PACK_CANONICAL_T))   \
+                   _FP_PACK_CANONICAL_is_tiny = 0;                     \
+               }                                                       \
              X##_e = -X##_e + 1;                                       \
              if (X##_e <= _FP_WFRACBITS_##fs)                          \
                {                                                       \
                      X##_e = 0;                                        \
                      _FP_FRAC_SRL_##wc (X, _FP_WORKBITS);              \
                    }                                                   \
-                 if ((FP_CUR_EXCEPTIONS & FP_EX_INEXACT)               \
-                     || (FP_TRAPPING_EXCEPTIONS & FP_EX_UNDERFLOW))    \
+                 if (_FP_PACK_CANONICAL_is_tiny                        \
+                     && ((FP_CUR_EXCEPTIONS & FP_EX_INEXACT)           \
+                         || (FP_TRAPPING_EXCEPTIONS                    \
+                             & FP_EX_UNDERFLOW)))                      \
                    FP_SET_EXCEPTION (FP_EX_UNDERFLOW);                 \
                }                                                       \
              else                                                      \
index c8a98948f8a17a955210e8e333f56d29ccc47c74..8d0efa58e74614d60beb8f9c267ca0c0d758973e 100644 (file)
 # undef FP_ROUNDMODE
 # define FP_ROUNDMODE FP_RND_ZERO
 
+# undef _FP_TININESS_AFTER_ROUNDING
+# define _FP_TININESS_AFTER_ROUNDING 0
+
 #endif
 
 #define _FP_ROUND_NEAREST(wc, X)                               \
index 9bb94e5ccc76895087fe17c22f5e0b2aaf012e0c..3e969952facadaca79d1a86c93b09cf5236c7f1c 100644 (file)
@@ -60,6 +60,8 @@
 #define FP_EX_DIVZERO          FE_DIVBYZERO
 #define FP_EX_INEXACT          FE_INEXACT
 
+#define _FP_TININESS_AFTER_ROUNDING 0
+
 #define FP_INIT_ROUNDMODE                      \
 do {                                           \
   _FPU_GETCW (_fcw);                           \
index cceccafe269ba629348afe3aa874cd83e02c3141..e11a8dd7ca8e37d523cad1b26c7d60c3dbfa7787 100644 (file)
@@ -74,6 +74,8 @@
 #define FP_EX_DIVZERO          FE_DIVBYZERO
 #define FP_EX_INEXACT          FE_INEXACT
 
+#define _FP_TININESS_AFTER_ROUNDING 1
+
 #define FP_INIT_ROUNDMODE                                      \
 do {                                                           \
   if (__builtin_expect (_round == 4, 0))                       \
index eba6e35cedde7aff44410d57fcda212c864066af..52a08b529824402e2a259a58bc0110307b420ad0 100644 (file)
@@ -47,3 +47,5 @@
       }                                                                \
     R##_c = FP_CLS_NAN;                                                \
   } while (0)
+
+#define _FP_TININESS_AFTER_ROUNDING 0
index 5be50927d0698d5b92c05b4e4bb575ccff7d05d9..708afc783e97dd3da55559d324ba7ca15999642b 100644 (file)
@@ -77,6 +77,8 @@
 #define FP_EX_DIVZERO          FE_DIVBYZERO
 #define FP_EX_INEXACT          FE_INEXACT
 
+#define _FP_TININESS_AFTER_ROUNDING 1
+
 #ifdef __mips_hard_float
 #define FP_INIT_ROUNDMODE                      \
 do {                                           \
index fff3b3c613882e94d263678f3f320254a5ae6a28..4e23aa8b2622df0019eea113302be3d883aea53a 100644 (file)
@@ -64,3 +64,5 @@
 #define FP_EX_OVERFLOW          (1 << 2)
 #define FP_EX_UNDERFLOW         (1 << 1)
 #define FP_EX_INEXACT           (1 << 0)
+
+#define _FP_TININESS_AFTER_ROUNDING 1
index 35a38b0031efc5ed355ce0818e67aa1da72b02b8..d92a90e3e206d5b1dbf3d5fd0d319114a7297dc4 100644 (file)
@@ -41,6 +41,8 @@
     R##_c = FP_CLS_NAN;                                                \
   } while (0)
 
+#define _FP_TININESS_AFTER_ROUNDING 0
+
 #if defined __NO_FPRS__ && !defined _SOFT_FLOAT
 
 /* Exception flags.  We use the bit positions of the appropriate bits
index 9b9074860f5065dab761fe49dd5b282d0a2a4857..81474e8a7cc07d66b8709f07da1c4cb641cbfa0b 100644 (file)
@@ -53,3 +53,5 @@
 #define FP_EX_OVERFLOW          (1 << 4)
 #define FP_EX_UNDERFLOW         (1 << 3)
 #define FP_EX_INEXACT           (1 << 2)
+
+#define _FP_TININESS_AFTER_ROUNDING 1
index 025b3ab196d91b23c092a4e7c1ced74a3635783e..b6baa8185f5a236896c384c367bc11ad8ec30e0a 100644 (file)
 #define FP_EX_DIVZERO          (1 << 1)
 #define FP_EX_INEXACT          (1 << 0)
 
+#define _FP_TININESS_AFTER_ROUNDING 0
+
 #define _FP_DECL_EX \
   fpu_control_t _fcw __attribute__ ((unused)) = (FP_RND_NEAREST << 30)
 
index 9a0384b1d89abadd0968d9806f10fd4a915913fc..80c1ac5d52f90e89d16a280a0cbc592635531ba7 100644 (file)
@@ -93,6 +93,8 @@ do {                                                          \
 #define FP_EX_DIVZERO          (1 << 1)
 #define FP_EX_INEXACT          (1 << 0)
 
+#define _FP_TININESS_AFTER_ROUNDING 0
+
 #define _FP_DECL_EX \
   fpu_control_t _fcw __attribute__ ((unused)) = (FP_RND_NEAREST << 30)
 
index ff8beeffa716299160a4a7e18ba1120eba2930c6..7a1993ea610ffd8a0220302306be14b754f6bdc7 100644 (file)
@@ -95,3 +95,5 @@
       }                                                                \
     R##_c = FP_CLS_NAN;                                                \
   } while (0)
+
+#define _FP_TININESS_AFTER_ROUNDING 0