soft-fp: Make extensions of subnormals from XFmode to TFmode signal underflow if traps enabled
diff mbox

Message ID Pine.LNX.4.64.1409172134470.17727@digraph.polyomino.org.uk
State New
Headers show

Commit Message

Joseph Myers Sept. 17, 2014, 9:35 p.m. UTC
This patch fixes a soft-fp corner case I previously noted in
<https://sourceware.org/ml/libc-alpha/2013-10/msg00349.html>: when
trapping on underflow is enabled, extensions of subnormals from XFmode
to TFmode need to signal underflow because the result is tiny (but
exact, so the underflow flag is not raised unless trapping is
enabled).

To avoid any excess initialization or tests for other cases of
floating-point extensions, a new FP_INIT_TRAPPING_EXCEPTIONS is added
that does the initialization required for this particular case (more
than FP_INIT_EXCEPTIONS, less than FP_INIT_ROUNDMODE, in general), and
FP_NO_EXACT_UNDERFLOW is added to stub out FP_TRAPPING_EXCEPTIONS
tests for those cases of extensions where the test would be dead code,
to avoid any uninitialized variable warnings.

As the relevant case only applies in libgcc, not to any use of soft-fp
in glibc, there is no bug report in Bugzilla and no non-default
definitions of FP_INIT_TRAPPING_EXCEPTIONS are added by the patch.  A
testcase will be added to GCC as part of an update of soft-fp in
libgcc once this patch is in libc.

Tested for powerpc-nofpu that the disassembly of installed shared
libraries is unchanged by this patch.  Bootstrapped GCC with updated
soft-fp (and an sfp-machine.h bug fix
<https://gcc.gnu.org/ml/gcc-patches/2014-09/msg01415.html> -
FP_TRAPPING_EXCEPTIONS was wrongly defined in libgcc for x86) with no
regressions on x86_64-unknown-linux-gnu and verified that a test of
the relevant case passes where it failed before.

2014-09-17  Joseph Myers  <joseph@codesourcery.com>

	* soft-fp/op-common.h (FP_EXTEND): When a subnormal input produces
	a subnormal result, set the underflow exception if trapping on
	underflow is enabled.
	* soft-fp/soft-fp.h (FP_INIT_TRAPPING_EXCEPTIONS): New macro.
	(FP_INIT_EXCEPTIONS): Default to FP_INIT_TRAPPING_EXCEPTIONS.
	[FP_NO_EXACT_UNDERFLOW] (FP_TRAPPING_EXCEPTIONS): Undefine and
	redefine to 0.
	* soft-fp/extenddftf2.c (FP_NO_EXACT_UNDERFLOW): Define.
	* soft-fp/extendsfdf2.c (FP_NO_EXACT_UNDERFLOW): Likewise.
	* soft-fp/extendsftf2.c (FP_NO_EXACT_UNDERFLOW): Likewise.
	* soft-fp/extendxftf2.c (__extendxftf2): Use
	FP_INIT_TRAPPING_EXCEPTIONS instead of FP_INIT_ROUNDMODE.

Comments

Joseph Myers Sept. 23, 2014, 12:56 p.m. UTC | #1
Ping.  This patch 
<https://sourceware.org/ml/libc-alpha/2014-09/msg00442.html> is pending 
review.
Joseph Myers Sept. 29, 2014, 2:52 p.m. UTC | #2
Ping^2.  This patch 
<https://sourceware.org/ml/libc-alpha/2014-09/msg00442.html> is still 
pending review.
Joseph Myers Oct. 6, 2014, 10:01 a.m. UTC | #3
Ping^3.  This patch 
<https://sourceware.org/ml/libc-alpha/2014-09/msg00442.html> is still 
pending review.
Carlos O'Donell Oct. 8, 2014, 11:50 p.m. UTC | #4
On 09/17/2014 05:35 PM, Joseph S. Myers wrote:
> This patch fixes a soft-fp corner case I previously noted in
> <https://sourceware.org/ml/libc-alpha/2013-10/msg00349.html>: when
> trapping on underflow is enabled, extensions of subnormals from XFmode
> to TFmode need to signal underflow because the result is tiny (but
> exact, so the underflow flag is not raised unless trapping is
> enabled).

Slightly unrelated, but why isn't everything using TFmode?
What benefit is there to XFmode?

> To avoid any excess initialization or tests for other cases of
> floating-point extensions, a new FP_INIT_TRAPPING_EXCEPTIONS is added
> that does the initialization required for this particular case (more
> than FP_INIT_EXCEPTIONS, less than FP_INIT_ROUNDMODE, in general), and
> FP_NO_EXACT_UNDERFLOW is added to stub out FP_TRAPPING_EXCEPTIONS
> tests for those cases of extensions where the test would be dead code,
> to avoid any uninitialized variable warnings.
> 
> As the relevant case only applies in libgcc, not to any use of soft-fp
> in glibc, there is no bug report in Bugzilla and no non-default
> definitions of FP_INIT_TRAPPING_EXCEPTIONS are added by the patch.  A
> testcase will be added to GCC as part of an update of soft-fp in
> libgcc once this patch is in libc.
> 
> Tested for powerpc-nofpu that the disassembly of installed shared
> libraries is unchanged by this patch.  Bootstrapped GCC with updated
> soft-fp (and an sfp-machine.h bug fix
> <https://gcc.gnu.org/ml/gcc-patches/2014-09/msg01415.html> -
> FP_TRAPPING_EXCEPTIONS was wrongly defined in libgcc for x86) with no
> regressions on x86_64-unknown-linux-gnu and verified that a test of
> the relevant case passes where it failed before.
> 
> 2014-09-17  Joseph Myers  <joseph@codesourcery.com>
> 
> 	* soft-fp/op-common.h (FP_EXTEND): When a subnormal input produces
> 	a subnormal result, set the underflow exception if trapping on
> 	underflow is enabled.
> 	* soft-fp/soft-fp.h (FP_INIT_TRAPPING_EXCEPTIONS): New macro.
> 	(FP_INIT_EXCEPTIONS): Default to FP_INIT_TRAPPING_EXCEPTIONS.
> 	[FP_NO_EXACT_UNDERFLOW] (FP_TRAPPING_EXCEPTIONS): Undefine and
> 	redefine to 0.
> 	* soft-fp/extenddftf2.c (FP_NO_EXACT_UNDERFLOW): Define.
> 	* soft-fp/extendsfdf2.c (FP_NO_EXACT_UNDERFLOW): Likewise.
> 	* soft-fp/extendsftf2.c (FP_NO_EXACT_UNDERFLOW): Likewise.
> 	* soft-fp/extendxftf2.c (__extendxftf2): Use
> 	FP_INIT_TRAPPING_EXCEPTIONS instead of FP_INIT_ROUNDMODE.

Looks good to me.

> diff --git a/soft-fp/extenddftf2.c b/soft-fp/extenddftf2.c
> index 6984b41..1765532 100644
> --- a/soft-fp/extenddftf2.c
> +++ b/soft-fp/extenddftf2.c
> @@ -28,6 +28,7 @@
>     License along with the GNU C Library; if not, see
>     <http://www.gnu.org/licenses/>.  */
>  
> +#define FP_NO_EXACT_UNDERFLOW

OK.

>  #include "soft-fp.h"
>  #include "double.h"
>  #include "quad.h"
> diff --git a/soft-fp/extendsfdf2.c b/soft-fp/extendsfdf2.c
> index a9b6bfb..6224195 100644
> --- a/soft-fp/extendsfdf2.c
> +++ b/soft-fp/extendsfdf2.c
> @@ -28,6 +28,7 @@
>     License along with the GNU C Library; if not, see
>     <http://www.gnu.org/licenses/>.  */
>  
> +#define FP_NO_EXACT_UNDERFLOW

OK.

>  #include "soft-fp.h"
>  #include "single.h"
>  #include "double.h"
> diff --git a/soft-fp/extendsftf2.c b/soft-fp/extendsftf2.c
> index 07fc367..f67d614 100644
> --- a/soft-fp/extendsftf2.c
> +++ b/soft-fp/extendsftf2.c
> @@ -28,6 +28,7 @@
>     License along with the GNU C Library; if not, see
>     <http://www.gnu.org/licenses/>.  */
>  
> +#define FP_NO_EXACT_UNDERFLOW

OK.

>  #include "soft-fp.h"
>  #include "single.h"
>  #include "quad.h"
> diff --git a/soft-fp/extendxftf2.c b/soft-fp/extendxftf2.c
> index 67b9095..a1386a6 100644
> --- a/soft-fp/extendxftf2.c
> +++ b/soft-fp/extendxftf2.c
> @@ -39,7 +39,7 @@ __extendxftf2 (XFtype a)
>    FP_DECL_Q (R);
>    TFtype r;
>  
> -  FP_INIT_ROUNDMODE;
> +  FP_INIT_TRAPPING_EXCEPTIONS;

OK.

>    FP_UNPACK_RAW_E (A, a);
>  #if (2 * _FP_W_TYPE_SIZE) < _FP_FRACBITS_Q
>    FP_EXTEND (Q, E, 4, 4, R, A);
> diff --git a/soft-fp/op-common.h b/soft-fp/op-common.h
> index 5f37a32..d55a1e5 100644
> --- a/soft-fp/op-common.h
> +++ b/soft-fp/op-common.h
> @@ -1538,6 +1538,8 @@
>  		  _FP_FRAC_SLL_##dwc (D, (_FP_FRACBITS_##dfs		\
>  					  - _FP_FRACBITS_##sfs));	\
>  		  D##_e = 0;						\
> +		  if (FP_TRAPPING_EXCEPTIONS & FP_EX_UNDERFLOW)		\
> +		    FP_SET_EXCEPTION (FP_EX_UNDERFLOW);			\

OK. Here we signal underflow if the trapping flag was set.

>  		}							\
>  	      else							\
>  		{							\
> diff --git a/soft-fp/soft-fp.h b/soft-fp/soft-fp.h
> index 8d0efa5..807f847 100644
> --- a/soft-fp/soft-fp.h
> +++ b/soft-fp/soft-fp.h
> @@ -108,9 +108,15 @@
>  #endif
>  
>  /* Initialize any machine-specific state used in
> +   FP_TRAPPING_EXCEPTIONS or FP_HANDLE_EXCEPTIONS.  */
> +#ifndef FP_INIT_TRAPPING_EXCEPTIONS
> +# define FP_INIT_TRAPPING_EXCEPTIONS FP_INIT_ROUNDMODE

OK. Default to what we did before.

> +#endif
> +
> +/* Initialize any machine-specific state used in
>     FP_HANDLE_EXCEPTIONS.  */
>  #ifndef FP_INIT_EXCEPTIONS
> -# define FP_INIT_EXCEPTIONS FP_INIT_ROUNDMODE
> +# define FP_INIT_EXCEPTIONS FP_INIT_TRAPPING_EXCEPTIONS

OK.

>  #endif
>  
>  #ifndef FP_HANDLE_EXCEPTIONS
> @@ -166,6 +172,16 @@
>  
>  #endif
>  
> +/* A file using soft-fp may define FP_NO_EXACT_UNDERFLOW before
> +   including soft-fp.h to indicate that, although a macro used there
> +   could allow for the case of exact underflow requiring the underflow
> +   exception to be raised if traps are enabled, for the particular
> +   arguments used in that file no exact underflow can occur.  */
> +#ifdef FP_NO_EXACT_UNDERFLOW
> +# undef FP_TRAPPING_EXCEPTIONS
> +# define FP_TRAPPING_EXCEPTIONS 0
> +#endif
> +

OK.

>  #define _FP_ROUND_NEAREST(wc, X)				\
>    do								\
>      {								\
> 

Cheers,
Carlos.
Joseph Myers Oct. 9, 2014, 12:18 a.m. UTC | #5
On Wed, 8 Oct 2014, Carlos O'Donell wrote:

> On 09/17/2014 05:35 PM, Joseph S. Myers wrote:
> > This patch fixes a soft-fp corner case I previously noted in
> > <https://sourceware.org/ml/libc-alpha/2013-10/msg00349.html>: when
> > trapping on underflow is enabled, extensions of subnormals from XFmode
> > to TFmode need to signal underflow because the result is tiny (but
> > exact, so the underflow flag is not raised unless trapping is
> > enabled).
> 
> Slightly unrelated, but why isn't everything using TFmode?
> What benefit is there to XFmode?

As a hardware floating-point format, I expect XFmode is a lot faster (even 
if x87 floating point is probably slower than SSE), though I don't have 
any benchmarks comparing long double and __float128 on x86.  (And the fact 
that it's long double - on x86 / x86_64 / ia64 - whereas TFmode is 
__float128 - no doubt also means it's much more widely used.  And so far 
getting libm functions and string conversions for __float128 requires you 
to use libquadmath shipped with GCC.  __float128 support in glibc was 
previously rejected in 
<https://sourceware.org/ml/libc-alpha/2004-03/msg00326.html> and 
<https://sourceware.org/ml/libc-alpha/2004-05/msg00055.html>, but now 
there are proposed standard C bindings for a _Float128 type with IEEE 
binary128 format - draft TS 18661-3 - so I think it makes sense to revisit 
the principle of adding such support to glibc now the standard bindings 
exist.)

Patch
diff mbox

diff --git a/soft-fp/extenddftf2.c b/soft-fp/extenddftf2.c
index 6984b41..1765532 100644
--- a/soft-fp/extenddftf2.c
+++ b/soft-fp/extenddftf2.c
@@ -28,6 +28,7 @@ 
    License along with the GNU C Library; if not, see
    <http://www.gnu.org/licenses/>.  */
 
+#define FP_NO_EXACT_UNDERFLOW
 #include "soft-fp.h"
 #include "double.h"
 #include "quad.h"
diff --git a/soft-fp/extendsfdf2.c b/soft-fp/extendsfdf2.c
index a9b6bfb..6224195 100644
--- a/soft-fp/extendsfdf2.c
+++ b/soft-fp/extendsfdf2.c
@@ -28,6 +28,7 @@ 
    License along with the GNU C Library; if not, see
    <http://www.gnu.org/licenses/>.  */
 
+#define FP_NO_EXACT_UNDERFLOW
 #include "soft-fp.h"
 #include "single.h"
 #include "double.h"
diff --git a/soft-fp/extendsftf2.c b/soft-fp/extendsftf2.c
index 07fc367..f67d614 100644
--- a/soft-fp/extendsftf2.c
+++ b/soft-fp/extendsftf2.c
@@ -28,6 +28,7 @@ 
    License along with the GNU C Library; if not, see
    <http://www.gnu.org/licenses/>.  */
 
+#define FP_NO_EXACT_UNDERFLOW
 #include "soft-fp.h"
 #include "single.h"
 #include "quad.h"
diff --git a/soft-fp/extendxftf2.c b/soft-fp/extendxftf2.c
index 67b9095..a1386a6 100644
--- a/soft-fp/extendxftf2.c
+++ b/soft-fp/extendxftf2.c
@@ -39,7 +39,7 @@  __extendxftf2 (XFtype a)
   FP_DECL_Q (R);
   TFtype r;
 
-  FP_INIT_ROUNDMODE;
+  FP_INIT_TRAPPING_EXCEPTIONS;
   FP_UNPACK_RAW_E (A, a);
 #if (2 * _FP_W_TYPE_SIZE) < _FP_FRACBITS_Q
   FP_EXTEND (Q, E, 4, 4, R, A);
diff --git a/soft-fp/op-common.h b/soft-fp/op-common.h
index 5f37a32..d55a1e5 100644
--- a/soft-fp/op-common.h
+++ b/soft-fp/op-common.h
@@ -1538,6 +1538,8 @@ 
 		  _FP_FRAC_SLL_##dwc (D, (_FP_FRACBITS_##dfs		\
 					  - _FP_FRACBITS_##sfs));	\
 		  D##_e = 0;						\
+		  if (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 8d0efa5..807f847 100644
--- a/soft-fp/soft-fp.h
+++ b/soft-fp/soft-fp.h
@@ -108,9 +108,15 @@ 
 #endif
 
 /* Initialize any machine-specific state used in
+   FP_TRAPPING_EXCEPTIONS or FP_HANDLE_EXCEPTIONS.  */
+#ifndef FP_INIT_TRAPPING_EXCEPTIONS
+# define FP_INIT_TRAPPING_EXCEPTIONS FP_INIT_ROUNDMODE
+#endif
+
+/* Initialize any machine-specific state used in
    FP_HANDLE_EXCEPTIONS.  */
 #ifndef FP_INIT_EXCEPTIONS
-# define FP_INIT_EXCEPTIONS FP_INIT_ROUNDMODE
+# define FP_INIT_EXCEPTIONS FP_INIT_TRAPPING_EXCEPTIONS
 #endif
 
 #ifndef FP_HANDLE_EXCEPTIONS
@@ -166,6 +172,16 @@ 
 
 #endif
 
+/* A file using soft-fp may define FP_NO_EXACT_UNDERFLOW before
+   including soft-fp.h to indicate that, although a macro used there
+   could allow for the case of exact underflow requiring the underflow
+   exception to be raised if traps are enabled, for the particular
+   arguments used in that file no exact underflow can occur.  */
+#ifdef FP_NO_EXACT_UNDERFLOW
+# undef FP_TRAPPING_EXCEPTIONS
+# define FP_TRAPPING_EXCEPTIONS 0
+#endif
+
 #define _FP_ROUND_NEAREST(wc, X)				\
   do								\
     {								\