aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoseph Myers <joseph@codesourcery.com>2014-02-12 18:27:12 +0000
committerJoseph Myers <joseph@codesourcery.com>2014-02-12 18:27:12 +0000
commitace614b8a5c03167cb92ff8ec652f788b8df6750 (patch)
treee26c9fe0bd823666d800ba8f4f444b34cb9521b8
parentfbfdf9cb039486f66994637081862c01bbd6a765 (diff)
downloadglibc-ace614b8a5c03167cb92ff8ec652f788b8df6750.tar
glibc-ace614b8a5c03167cb92ff8ec652f788b8df6750.tar.gz
glibc-ace614b8a5c03167cb92ff8ec652f788b8df6750.tar.bz2
glibc-ace614b8a5c03167cb92ff8ec652f788b8df6750.zip
soft-fp: support after-rounding tininess detection.
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.
-rw-r--r--ChangeLog33
-rw-r--r--soft-fp/op-common.h35
-rw-r--r--soft-fp/soft-fp.h3
-rw-r--r--sysdeps/aarch64/soft-fp/sfp-machine.h2
-rw-r--r--sysdeps/alpha/soft-fp/sfp-machine.h2
-rw-r--r--sysdeps/arm/soft-fp/sfp-machine.h2
-rw-r--r--sysdeps/mips/mips64/soft-fp/sfp-machine.h2
-rw-r--r--sysdeps/mips/soft-fp/sfp-machine.h2
-rw-r--r--sysdeps/powerpc/soft-fp/sfp-machine.h2
-rw-r--r--sysdeps/sh/soft-fp/sfp-machine.h2
-rw-r--r--sysdeps/sparc/sparc32/soft-fp/sfp-machine.h2
-rw-r--r--sysdeps/sparc/sparc64/soft-fp/sfp-machine.h2
-rw-r--r--sysdeps/tile/sfp-machine.h2
13 files changed, 87 insertions, 4 deletions
diff --git a/ChangeLog b/ChangeLog
index ffdb54696c..a7dc412492 100644
--- 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]
diff --git a/soft-fp/op-common.h b/soft-fp/op-common.h
index e901981b95..6f8c1f3cb0 100644
--- a/soft-fp/op-common.h
+++ b/soft-fp/op-common.h
@@ -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. */
@@ -191,8 +191,22 @@
#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)) \
@@ -279,6 +293,17 @@
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) \
{ \
@@ -296,8 +321,10 @@
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 \
diff --git a/soft-fp/soft-fp.h b/soft-fp/soft-fp.h
index c8a98948f8..8d0efa58e7 100644
--- a/soft-fp/soft-fp.h
+++ b/soft-fp/soft-fp.h
@@ -161,6 +161,9 @@
# 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) \
diff --git a/sysdeps/aarch64/soft-fp/sfp-machine.h b/sysdeps/aarch64/soft-fp/sfp-machine.h
index 9bb94e5ccc..3e969952fa 100644
--- a/sysdeps/aarch64/soft-fp/sfp-machine.h
+++ b/sysdeps/aarch64/soft-fp/sfp-machine.h
@@ -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); \
diff --git a/sysdeps/alpha/soft-fp/sfp-machine.h b/sysdeps/alpha/soft-fp/sfp-machine.h
index cceccafe26..e11a8dd7ca 100644
--- a/sysdeps/alpha/soft-fp/sfp-machine.h
+++ b/sysdeps/alpha/soft-fp/sfp-machine.h
@@ -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)) \
diff --git a/sysdeps/arm/soft-fp/sfp-machine.h b/sysdeps/arm/soft-fp/sfp-machine.h
index eba6e35ced..52a08b5298 100644
--- a/sysdeps/arm/soft-fp/sfp-machine.h
+++ b/sysdeps/arm/soft-fp/sfp-machine.h
@@ -47,3 +47,5 @@
} \
R##_c = FP_CLS_NAN; \
} while (0)
+
+#define _FP_TININESS_AFTER_ROUNDING 0
diff --git a/sysdeps/mips/mips64/soft-fp/sfp-machine.h b/sysdeps/mips/mips64/soft-fp/sfp-machine.h
index 5be50927d0..708afc783e 100644
--- a/sysdeps/mips/mips64/soft-fp/sfp-machine.h
+++ b/sysdeps/mips/mips64/soft-fp/sfp-machine.h
@@ -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 { \
diff --git a/sysdeps/mips/soft-fp/sfp-machine.h b/sysdeps/mips/soft-fp/sfp-machine.h
index fff3b3c613..4e23aa8b26 100644
--- a/sysdeps/mips/soft-fp/sfp-machine.h
+++ b/sysdeps/mips/soft-fp/sfp-machine.h
@@ -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
diff --git a/sysdeps/powerpc/soft-fp/sfp-machine.h b/sysdeps/powerpc/soft-fp/sfp-machine.h
index 35a38b0031..d92a90e3e2 100644
--- a/sysdeps/powerpc/soft-fp/sfp-machine.h
+++ b/sysdeps/powerpc/soft-fp/sfp-machine.h
@@ -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
diff --git a/sysdeps/sh/soft-fp/sfp-machine.h b/sysdeps/sh/soft-fp/sfp-machine.h
index 9b9074860f..81474e8a7c 100644
--- a/sysdeps/sh/soft-fp/sfp-machine.h
+++ b/sysdeps/sh/soft-fp/sfp-machine.h
@@ -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
diff --git a/sysdeps/sparc/sparc32/soft-fp/sfp-machine.h b/sysdeps/sparc/sparc32/soft-fp/sfp-machine.h
index 025b3ab196..b6baa8185f 100644
--- a/sysdeps/sparc/sparc32/soft-fp/sfp-machine.h
+++ b/sysdeps/sparc/sparc32/soft-fp/sfp-machine.h
@@ -185,6 +185,8 @@
#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)
diff --git a/sysdeps/sparc/sparc64/soft-fp/sfp-machine.h b/sysdeps/sparc/sparc64/soft-fp/sfp-machine.h
index 9a0384b1d8..80c1ac5d52 100644
--- a/sysdeps/sparc/sparc64/soft-fp/sfp-machine.h
+++ b/sysdeps/sparc/sparc64/soft-fp/sfp-machine.h
@@ -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)
diff --git a/sysdeps/tile/sfp-machine.h b/sysdeps/tile/sfp-machine.h
index ff8beeffa7..7a1993ea61 100644
--- a/sysdeps/tile/sfp-machine.h
+++ b/sysdeps/tile/sfp-machine.h
@@ -95,3 +95,5 @@
} \
R##_c = FP_CLS_NAN; \
} while (0)
+
+#define _FP_TININESS_AFTER_ROUNDING 0