diff mbox series

Change default to -fno-math-errno

Message ID DB6PR0801MB205326BE2D5879D558DD571C835A0@DB6PR0801MB2053.eurprd08.prod.outlook.com
State New
Headers show
Series Change default to -fno-math-errno | expand

Commit Message

Wilco Dijkstra Oct. 27, 2017, 3 p.m. UTC
GCC currently defaults to -fmath-errno.  This generates code assuming math
functions set errno and the application checks errno.  Very few applications
test errno and various systems and math libraries no longer set errno since it
is optional.  GCC generates much faster code for simple math functions with
-fno-math-errno such as sqrt and lround (avoiding a call and PLT redirection).
Therefore it seems reasonable to change the default to -fno-math-errno.

long f(float x) { return lroundf(x) + 1; }

by default:

f:
	str	x30, [sp, -16]!
	bl	lroundf
	add	x0, x0, 1
	ldr	x30, [sp], 16
	ret

lroundf in GLIBC doesn't set errno, so all the inefficiency was for nothing:

0000000000000000 <__lroundf>:
   0:	9e240000 	fcvtas	x0, s0
   4:	d65f03c0 	ret

With -fno-math-errno:

f:
	fcvtas	x0, s0
	add	x0, x0, 1
	ret

OK for commit?

2017-10-27  Wilco Dijkstra  <wdijkstr@arm.com>

	* common.opt (fmath-errno): Change default to 0.
	* opts.c (set_fast_math_flags): Force -fno-math-errno with -ffast-math.

doc/
	* invoke.texi (-fmath-errno) Update documentation.

--

Comments

Joseph Myers Oct. 27, 2017, 4:28 p.m. UTC | #1
No existing glibc version defines math_errhandling based on 
__NO_MATH_ERRNO__.  I'd expect such a change to come with a glibc patch, 
and indeed a GCC execution test of the value of math_errhandling to make 
sure the compiler's behavior isn't contradicting what's declared by the 
runtime libraries.  Also, the default should not be changed for pre-C99 C 
standard modes (or pre-C++11 C++, I suppose).
Richard Biener Oct. 30, 2017, 11:08 a.m. UTC | #2
On Fri, Oct 27, 2017 at 6:28 PM, Joseph Myers <joseph@codesourcery.com> wrote:
> No existing glibc version defines math_errhandling based on
> __NO_MATH_ERRNO__.  I'd expect such a change to come with a glibc patch,
> and indeed a GCC execution test of the value of math_errhandling to make
> sure the compiler's behavior isn't contradicting what's declared by the
> runtime libraries.  Also, the default should not be changed for pre-C99 C
> standard modes (or pre-C++11 C++, I suppose).

Should we also get the __ieee764_ entries used if the compiler sets
__NO_MATH_ERRNO__?  That is, if the librari advertises not setting errno
via math_errhandling is it still allowed to set/clobber errno anyways?

Richard.

> --
> Joseph S. Myers
> joseph@codesourcery.com
Joseph Myers Oct. 30, 2017, 12:27 p.m. UTC | #3
On Mon, 30 Oct 2017, Richard Biener wrote:

> On Fri, Oct 27, 2017 at 6:28 PM, Joseph Myers <joseph@codesourcery.com> wrote:
> > No existing glibc version defines math_errhandling based on
> > __NO_MATH_ERRNO__.  I'd expect such a change to come with a glibc patch,
> > and indeed a GCC execution test of the value of math_errhandling to make
> > sure the compiler's behavior isn't contradicting what's declared by the
> > runtime libraries.  Also, the default should not be changed for pre-C99 C
> > standard modes (or pre-C++11 C++, I suppose).
> 
> Should we also get the __ieee764_ entries used if the compiler sets
> __NO_MATH_ERRNO__?  That is, if the librari advertises not setting errno
> via math_errhandling is it still allowed to set/clobber errno anyways?

See C11 7.12.1p7.  "If a domain, pole, or range error occurs and the 
integer expression math_errhandling & MATH_ERRNO is zero, then errno shall 
either be set to the value corresponding to the error or left unmodified. 
If no such error occurs, errno shall be left unmodified regardless of the 
setting of math_errhandling.".  (And, for <complex.h> functions, "An 
implementation may set errno but is not required to.".)
Wilco Dijkstra Oct. 30, 2017, 3:06 p.m. UTC | #4
Richard Biener wrote:
> Should we also get the __ieee764_ entries used if the compiler sets
> __NO_MATH_ERRNO__?  That is, if the librari advertises not setting errno
> via math_errhandling is it still allowed to set/clobber errno anyways?

That's a good question! I checked and the math wrappers currently use
__FINITE_MATH_ONLY__ to decide whether to use the IEEE754 version
or the wrapper which sets errno. However that's actually incorrect given
that the only purpose of the wrappers is to set errno, not to add IEEE
handling (which is done in the math implementation).

Note -ffinite-math-only appears to imply -fno-math-errno, eventhough
this is not clear from the documentation - is that expected? In principle
these options are orthogonal, setting errno due to a range error is still
valid even if you don't use infinities or NaNs.

Wilco
Joseph Myers Oct. 30, 2017, 3:40 p.m. UTC | #5
On Mon, 30 Oct 2017, Wilco Dijkstra wrote:

> Richard Biener wrote:
> > Should we also get the __ieee764_ entries used if the compiler sets
> > __NO_MATH_ERRNO__?  That is, if the librari advertises not setting errno
> > via math_errhandling is it still allowed to set/clobber errno anyways?
> 
> That's a good question! I checked and the math wrappers currently use
> __FINITE_MATH_ONLY__ to decide whether to use the IEEE754 version
> or the wrapper which sets errno. However that's actually incorrect given
> that the only purpose of the wrappers is to set errno, not to add IEEE
> handling (which is done in the math implementation).

The semantics of __*_finite definitely include finite-math-only, as they 
aren't all just disabling the wrappers (e.g. sysdeps/i386/i686/fpu/e_log.S 
has __log_finite separate from __ieee754_log).

> Note -ffinite-math-only appears to imply -fno-math-errno, eventhough
> this is not clear from the documentation - is that expected? In principle
> these options are orthogonal, setting errno due to a range error is still
> valid even if you don't use infinities or NaNs.

Well, it's expected for glibc (as an empirical observation about what the 
__*_finite entry points do).  It may not necessarily be an implication for 
GCC.  And given appropriate documentation, it doesn't necessarily 
contradict math_errhandling & MATH_ERRNO being nonzero (in that errno 
setting on underflow is implementation-defined in that case - glibc 
documents semantics involving setting errno on underflow to 0 but not 
necessarily otherwise, but could document the effects of 
-ffinite-math-only potentially disabling the errno setting on underflow to 
0).
Wilco Dijkstra Nov. 7, 2017, 3:09 p.m. UTC | #6
Joseph Myers wrote:
On Mon, 30 Oct 2017, Wilco Dijkstra wrote:

> The semantics of __*_finite definitely include finite-math-only, as they 
> aren't all just disabling the wrappers (e.g. sysdeps/i386/i686/fpu/e_log.S 
> has __log_finite separate from __ieee754_log).

I only see a few cases where there are separate __ieee754 and finite
implementations - all seem to be x87 assembler. I don't think the existence
of a few special cases should block the simple optimization of avoiding the
wrappers when reasonable.

For example if removing/merging the x87 implementations is unacceptable,
the header could use -ffinite-math-only for x86/x64 but use -fno-math-errno 
on all other targets.

Wilco
Wilco Dijkstra Jan. 12, 2018, 3:44 p.m. UTC | #7
Joseph Myers wrote:
  
> No existing glibc version defines math_errhandling based on
> __NO_MATH_ERRNO__.  I'd expect such a change to come with a glibc patch, 
> and indeed a GCC execution test of the value of math_errhandling to make 
> sure the compiler's behavior isn't contradicting what's declared by the 
> runtime libraries.  Also, the default should not be changed for pre-C99 C 
> standard modes (or pre-C++11 C++, I suppose).

The math_errhandling change has been committed in GLIBC in a separate patch.
I've updated the patch to exclude pre-C99 C/C++/ObjC:

GCC currently defaults to -fmath-errno.  This generates code assuming math
functions set errno and the application checks errno.  Few applications
test errno and various systems and math libraries no longer set errno since it
is optional.  GCC generates much faster code for simple math functions with
-fno-math-errno such as sqrt and lround (avoiding a call and PLT redirection).
Therefore it is reasonable to change the default to -fno-math-errno.  Only change
the default for C99 and later (Fortan, Ada etc already force -fno-math-errno).

long f(float x) { return lroundf(x) + 1; }

Currently generates:

f:
	str	x30, [sp, -16]!
	bl	lroundf
	add	x0, x0, 1
	ldr	x30, [sp], 16
	ret

lroundf in GLIBC doesn't set errno, so all the inefficiency was for nothing:

0000000000000000 <__lroundf>:
   0:	9e240000 	fcvtas	x0, s0
   4:	d65f03c0 	ret

With -fno-math-errno:

f:
	fcvtas	x0, s0
	add	x0, x0, 1
	ret

OK for commit?

2018-01-12  Wilco Dijkstra  <wdijkstr@arm.com>


	* common.opt (fmath-errno): Change default to 0.
	* opts.c (set_fast_math_flags): Force -fno-math-errno with -ffast-math.
	* c-family/c-opts.c (c_common_init_options_struct): Set flag_errno_math
	to special value.
	(c_common_post_options): Set flag_errno_math default based on language.

doc/
	* invoke.texi (-fmath-errno) Update documentation.

--
diff --git a/gcc/c-family/c-opts.c b/gcc/c-family/c-opts.c
index f84ecf4539cb98b0d46a8d8e429f3860db1c79e8..62ae94b7016e3d5f7a7ff1f075c2667ff71975a4 100644
--- a/gcc/c-family/c-opts.c
+++ b/gcc/c-family/c-opts.c
@@ -207,6 +207,9 @@ c_common_init_options_struct (struct gcc_options *opts)
 
   /* By default, C99-like requirements for complex multiply and divide.  */
   opts->x_flag_complex_method = 2;
+
+  /* Use a special value so the default can be set after option parsing.  */
+  opts->x_flag_errno_math = 2;
 }
 
 /* Common initialization before calling option handlers.  */
@@ -828,6 +831,11 @@ c_common_post_options (const char **pfilename)
   else if (!flag_gnu89_inline && !flag_isoc99)
     error ("-fno-gnu89-inline is only supported in GNU99 or C99 mode");
 
+  /* If -fmath-errno isn't set (or implied by another math option),
+     set the default to -fno-math-errno for C99 and later.  */
+  if (flag_errno_math == 2)
+    flag_errno_math = !flag_isoc99 || c_dialect_objc ();
+
   /* Default to ObjC sjlj exception handling if NeXT runtime.  */
   if (flag_objc_sjlj_exceptions < 0)
     flag_objc_sjlj_exceptions = flag_next_runtime;
diff --git a/gcc/common.opt b/gcc/common.opt
index ac7e62620a407a1aedd1205c126d109f0b3577f8..dc183977471c332abc48c9b13a139b2f84a13acc 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -1846,7 +1846,7 @@ Common Report Var(flag_lto_report_wpa) Init(0)
 Report various link-time optimization statistics for WPA only.
 
 fmath-errno
-Common Report Var(flag_errno_math) Init(1) Optimization SetByCombined
+Common Report Var(flag_errno_math) Init(0) Optimization SetByCombined
 Set errno after built-in math functions.
 
 fmax-errors=
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 49fc5bf39ddbecbd735ffda9cc418908eb644786..442b4bfb6bc1067b4f8b0e3ceb9fdfc1fb6d8bbc 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -9531,24 +9531,16 @@ that depend on an exact implementation of IEEE or ISO rules/specifications
 for math functions. It may, however, yield faster code for programs
 that do not require the guarantees of these specifications.
 
-@item -fno-math-errno
-@opindex fno-math-errno
-Do not set @code{errno} after calling math functions that are executed
-with a single instruction, e.g., @code{sqrt}.  A program that relies on
-IEEE exceptions for math error handling may want to use this flag
-for speed while maintaining IEEE arithmetic compatibility.
+@item -fmath-errno
+@opindex fmath-errno
+Generate code that assumes math functions may set errno.  This disables
+inlining of simple math functions like @code{sqrt} and @code{lround}.
 
-This option is not turned on by any @option{-O} option since
-it can result in incorrect output for programs that depend on
-an exact implementation of IEEE or ISO rules/specifications for
-math functions. It may, however, yield faster code for programs
-that do not require the guarantees of these specifications.
-
-The default is @option{-fmath-errno}.
+A program which relies on math functions setting errno may need to
+use this flag.  However note various systems and math libraries never
+set errno.
 
-On Darwin systems, the math library never sets @code{errno}.  There is
-therefore no reason for the compiler to consider the possibility that
-it might, and @option{-fno-math-errno} is the default.
+The default is @option{-fno-math-errno} except in ISO C90 and C++98 modes.
 
 @item -funsafe-math-optimizations
 @opindex funsafe-math-optimizations
@@ -21564,8 +21556,8 @@ truncation towards zero.
 @item @samp{round}
 Conversion from single-precision floating point to signed integer,
 rounding to the nearest integer and ties away from zero.
-This corresponds to the @code{__builtin_lroundf} function when
-@option{-fno-math-errno} is used.
+This corresponds to the @code{__builtin_lroundf} function unless
+@option{-fmath-errno} is used.
 
 @item @samp{floatis}, @samp{floatus}, @samp{floatid}, @samp{floatud}
 Conversion from signed or unsigned integer types to floating-point types.
diff --git a/gcc/opts.c b/gcc/opts.c
index e9df6f6a6ae7a6c62b0ca1fdf6a57554916586b8..e3c806b38a1d98f9212375c4aa2062dc8df5edfb 100644
--- a/gcc/opts.c
+++ b/gcc/opts.c
@@ -2553,8 +2553,6 @@ set_fast_math_flags (struct gcc_options *opts, int set)
     }
   if (!opts->frontend_set_flag_finite_math_only)
     opts->x_flag_finite_math_only = set;
-  if (!opts->frontend_set_flag_errno_math)
-    opts->x_flag_errno_math = !set;
   if (set)
     {
       if (opts->frontend_set_flag_excess_precision_cmdline
@@ -2567,6 +2565,8 @@ set_fast_math_flags (struct gcc_options *opts, int set)
 	opts->x_flag_rounding_math = 0;
       if (!opts->frontend_set_flag_cx_limited_range)
 	opts->x_flag_cx_limited_range = 1;
+      if (!opts->frontend_set_flag_errno_math)
+	opts->x_flag_errno_math = 0;
     }
 }
Joseph Myers Jan. 12, 2018, 6:05 p.m. UTC | #8
On Fri, 12 Jan 2018, Wilco Dijkstra wrote:

> I've updated the patch to exclude pre-C99 C/C++/ObjC:

Another question to consider: what about configurations (mostly 
soft-float) where floating-point exceptions are not supported?  (glibc 
wrongly defines math_errhandling to include MATH_ERREXCEPT there, but the 
only option actually permitted by C99 in that case would be to define it 
to MATH_ERRNO.)

If we wish to distinguish that case, the 
targetm.float_exceptions_rounding_supported_p hook is the one to use (in 
the absence of anyone identifying a target that supports exceptions but 
not rounding modes) - possibly together with flag_iso.

> lroundf in GLIBC doesn't set errno, so all the inefficiency was for nothing:

(glibc bug 6797.)
Wilco Dijkstra Jan. 16, 2018, 3:35 p.m. UTC | #9
Joseph Myers wrote:

> Another question to consider: what about configurations (mostly 
> soft-float) where floating-point exceptions are not supported?  (glibc 
> wrongly defines math_errhandling to include MATH_ERREXCEPT there, but the 
> only option actually permitted by C99 in that case would be to define it 
> to MATH_ERRNO.)
> 
> If we wish to distinguish that case, the 
> targetm.float_exceptions_rounding_supported_p hook is the one to use (in 
> the absence of anyone identifying a target that supports exceptions but 
> not rounding modes) - possibly together with flag_iso.

I looked into this and the issue is that calling targetm functions is not possible until
the backend is fully initialized (whether the pattern exists or not is not sufficient,
the pattern condition must be valid to evaluate as well), and that happens after
option parsing.

In general soft-float is used on tiny targets which don't use errno at all (as in
remove all the code dealing with it, including the errno variable itself!), so I
believe it's best to let people explicitly enable -fmath-errno in the rare case
when they really want to.

>> lroundf in GLIBC doesn't set errno, so all the inefficiency was for nothing:
>
> (glibc bug 6797.)

I see, that explains it! A decade old bug - it shows the popularity of errno...

Wilco
diff mbox series

Patch

diff --git a/gcc/common.opt b/gcc/common.opt
index 836f05b95a219d17614f35e8dad61b22fef7d748..1bb87353f760d7c60c39de8b9de4311c1ec3d892 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -1842,7 +1842,7 @@  Common Report Var(flag_lto_report_wpa) Init(0)
 Report various link-time optimization statistics for WPA only.
 
 fmath-errno
-Common Report Var(flag_errno_math) Init(1) Optimization SetByCombined
+Common Report Var(flag_errno_math) Init(0) Optimization SetByCombined
 Set errno after built-in math functions.
 
 fmax-errors=
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 71b2445f70fd5b832c68c08e69e71d8ecad37a4a..3328a3b5fafa6a98007eff52d2a26af520de9128 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -9397,24 +9397,16 @@  that depend on an exact implementation of IEEE or ISO rules/specifications
 for math functions. It may, however, yield faster code for programs
 that do not require the guarantees of these specifications.
 
-@item -fno-math-errno
-@opindex fno-math-errno
-Do not set @code{errno} after calling math functions that are executed
-with a single instruction, e.g., @code{sqrt}.  A program that relies on
-IEEE exceptions for math error handling may want to use this flag
-for speed while maintaining IEEE arithmetic compatibility.
+@item -fmath-errno
+@opindex fmath-errno
+Generate code that assumes math functions may set errno.  This disables
+inlining of simple math functions like @code{sqrt} and @code{lround}.
 
-This option is not turned on by any @option{-O} option since
-it can result in incorrect output for programs that depend on
-an exact implementation of IEEE or ISO rules/specifications for
-math functions. It may, however, yield faster code for programs
-that do not require the guarantees of these specifications.
-
-The default is @option{-fmath-errno}.
+A program which relies on math functions setting errno may need to
+use this flag.  However note various systems and math libraries never
+set errno.
 
-On Darwin systems, the math library never sets @code{errno}.  There is
-therefore no reason for the compiler to consider the possibility that
-it might, and @option{-fno-math-errno} is the default.
+The default is @option{-fno-math-errno}.
 
 @item -funsafe-math-optimizations
 @opindex funsafe-math-optimizations
@@ -21315,8 +21307,8 @@  truncation towards zero.
 @item @samp{round}
 Conversion from single-precision floating point to signed integer,
 rounding to the nearest integer and ties away from zero.
-This corresponds to the @code{__builtin_lroundf} function when
-@option{-fno-math-errno} is used.
+This corresponds to the @code{__builtin_lroundf} function unless
+@option{-fmath-errno} is used.
 
 @item @samp{floatis}, @samp{floatus}, @samp{floatid}, @samp{floatud}
 Conversion from signed or unsigned integer types to floating-point types.
diff --git a/gcc/opts.c b/gcc/opts.c
index 6600a5afd488e89262e6327f7370057c7ae234ba..dfad955e220870a3250198640f3790c804b191e0 100644
--- a/gcc/opts.c
+++ b/gcc/opts.c
@@ -2530,8 +2530,6 @@  set_fast_math_flags (struct gcc_options *opts, int set)
     }
   if (!opts->frontend_set_flag_finite_math_only)
     opts->x_flag_finite_math_only = set;
-  if (!opts->frontend_set_flag_errno_math)
-    opts->x_flag_errno_math = !set;
   if (set)
     {
       if (opts->frontend_set_flag_excess_precision_cmdline
@@ -2544,6 +2542,8 @@  set_fast_math_flags (struct gcc_options *opts, int set)
 	opts->x_flag_rounding_math = 0;
       if (!opts->frontend_set_flag_cx_limited_range)
 	opts->x_flag_cx_limited_range = 1;
+      if (!opts->frontend_set_flag_errno_math)
+	opts->x_flag_errno_math = 0;
     }
 }