diff mbox series

[v3] Change default to -fno-math-errno

Message ID DB5PR08MB10304297CC6EF69350F0ACD683710@DB5PR08MB1030.eurprd08.prod.outlook.com
State New
Headers show
Series [v3] Change default to -fno-math-errno | expand

Commit Message

Wilco Dijkstra June 18, 2018, 2:01 p.m. UTC
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.  This is
already the case for non-C languages.  Only change the default for C99 and
later.

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

With -fno-math-errno:

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

Passes regress on AArch64. OK for commit?

ChangeLog:
2018-06-18  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.

testsuite/

	* gcc.dg/errno-1.c: Add -fmath-errno.
	* gcc.dg/torture/pr68264.c: Likewise.
	* gcc.dg/tree-ssa/ssa-dse-15.c: Likewise.
	* gcc.target/aarch64/no-inline-lrint_1.c: Likewise.
--

Comments

Jeff Law June 18, 2018, 4:17 p.m. UTC | #1
On 06/18/2018 08:01 AM, Wilco Dijkstra wrote:
> 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.  This is
> already the case for non-C languages.  Only change the default for C99 and
> later.
> 
> 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
> 
> With -fno-math-errno:
> 
> f:
> 	fcvtas	x0, s0
> 	add	x0, x0, 1
> 	ret
> 
> Passes regress on AArch64. OK for commit?
> 
> ChangeLog:
> 2018-06-18  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.
> 
> testsuite/
> 
> 	* gcc.dg/errno-1.c: Add -fmath-errno.
> 	* gcc.dg/torture/pr68264.c: Likewise.
> 	* gcc.dg/tree-ssa/ssa-dse-15.c: Likewise.
> 	* gcc.target/aarch64/no-inline-lrint_1.c: Likewise.
So do we need to set or check math_errhandling & MATH_ERRNO at all?  Or
are those really meant for the user to test?  (which I think just
indicates we need to make sure they're set correctly).

WRT library behavior, I thought it was only complex arithmetic that had
the option of setting errno.  I thought float/double math functions had
a requirement to set errno?

While I would love to see us drop the need to ensure errno is set as it
allows us to exploit processor capabilities, I want to make sure that we
stay conformant with the relevant standards.

jeff

>
Joseph Myers June 18, 2018, 4:46 p.m. UTC | #2
On Mon, 18 Jun 2018, Jeff Law wrote:

> So do we need to set or check math_errhandling & MATH_ERRNO at all?  Or

That's a matter for libc (glibc currently sets it based on __FAST_MATH__ / 
__NO_MATH_ERRNO__, but fails to avoid including MATH_ERREXCEPT in the 
definition for configurations not supporting exceptions).

> WRT library behavior, I thought it was only complex arithmetic that had
> the option of setting errno.  I thought float/double math functions had
> a requirement to set errno?

For complex.h functions it's always optional.  For math.h functions at 
least one of errno and exceptions must be set, as indicated in the 
definition of math_errhandling (and if math_errhandling is defined to just 
one of MATH_ERRNO and MATH_ERREXCEPT, functions then may or may not also 
indicate errors in the other way).  Hence the question of whether a 
-fno-math-errno default should be different for (mainly soft-float) 
configurations not supporting floating-point exceptions, for which errno 
is the only way they have available to indicate errors.
Richard Biener June 19, 2018, 8:29 a.m. UTC | #3
On Mon, Jun 18, 2018 at 4:01 PM Wilco Dijkstra <Wilco.Dijkstra@arm.com> wrote:
>
> 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.  This is
> already the case for non-C languages.  Only change the default for C99 and
> later.
>
> 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
>
> With -fno-math-errno:
>
> f:
>         fcvtas  x0, s0
>         add     x0, x0, 1
>         ret
>
> Passes regress on AArch64. OK for commit?

There are a number of regression tests that check for errno handling
(I added some to avoid aliasing for example).  Please make sure to
add explicit -fmath-errno to those that do not already have it set
(I guess such patch would be obvious and independent of this one).

A grep -r errno testsuite/ is only 159 lines but it might not
catch all cases - the one I'm refering to above matches because
of a comment only:

testsuite/gcc.dg/tree-ssa/ssa-dse-15.c:  /* We should be able to DSE this store
(p may point to errno).  */

Following Josephs comment it may be reasonable to have the default
depend on the targets C library and thus make it a target macro (IIRC
the BSD libc never set errno for any math function for example).

Josephs comment indicates conformance issues with a
-fno-math-errno -fno-trapping-math combination (-ftrapping-math
is default).

Thanks,
Richard.

> ChangeLog:
> 2018-06-18  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.
>
> testsuite/
>
>         * gcc.dg/errno-1.c: Add -fmath-errno.
>         * gcc.dg/torture/pr68264.c: Likewise.
>         * gcc.dg/tree-ssa/ssa-dse-15.c: Likewise.
>         * gcc.target/aarch64/no-inline-lrint_1.c: Likewise.
> --
>
> diff --git a/gcc/c-family/c-opts.c b/gcc/c-family/c-opts.c
> index bbcb1bb1a9c606a262a1aa362471388987629d06..b13fc122f8baf6aae0b47010be92ffd961b0147a 100644
> --- a/gcc/c-family/c-opts.c
> +++ b/gcc/c-family/c-opts.c
> @@ -208,6 +208,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.  */
> @@ -831,6 +834,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 d54e8e5601698c73d2c2bc8f354b55f3889a9186..e6fe11d1dcdbb39016242299dd3d76233e2bd976 100644
> --- a/gcc/common.opt
> +++ b/gcc/common.opt
> @@ -1855,7 +1855,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 42832c5a50013d776dff47c6d347f5bc4dbef2d8..aeda219ba0dbe169d9fb2b4358950f2ba32b5c78 100644
> --- a/gcc/doc/invoke.texi
> +++ b/gcc/doc/invoke.texi
> @@ -9783,24 +9783,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
> @@ -21827,8 +21819,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 33efcc0d6e7db73ba60cab62ef146e976e75ca21..a6f228a53e1baa505a477a273fad3d00364f6893 100644
> --- a/gcc/opts.c
> +++ b/gcc/opts.c
> @@ -2581,8 +2581,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
> @@ -2595,6 +2593,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;
>      }
>  }
>
> diff --git a/gcc/testsuite/gcc.dg/errno-1.c b/gcc/testsuite/gcc.dg/errno-1.c
> index 0dfb00087dee04cd5ff1e916149c0c13c9b87b20..25739e4a862ca9a9c05157d3abc87216eb27ea7d 100644
> --- a/gcc/testsuite/gcc.dg/errno-1.c
> +++ b/gcc/testsuite/gcc.dg/errno-1.c
> @@ -1,5 +1,5 @@
>  /* { dg-do compile } */
> -/* { dg-options "-O2" } */
> +/* { dg-options "-O2 -fmath-errno" } */
>
>  #include <errno.h>
>  #include <stdlib.h>
> diff --git a/gcc/testsuite/gcc.dg/torture/pr68264.c b/gcc/testsuite/gcc.dg/torture/pr68264.c
> index 9294d5aedb79de1b91b3074e34b089b100031d54..56d7bf7bc64545566d7127a329f244045a0f2afc 100644
> --- a/gcc/testsuite/gcc.dg/torture/pr68264.c
> +++ b/gcc/testsuite/gcc.dg/torture/pr68264.c
> @@ -1,5 +1,6 @@
>  /* { dg-do run } */
>  /* { dg-add-options ieee } */
> +/* { dg-additional-options "-fmath-errno" } */
>  /* { dg-require-effective-target fenv_exceptions } */
>
>  #include <fenv.h>
> diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-15.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-15.c
> index 43a41c8eb38db1c930923f1bb0fd9d1689fac826..134febf96d38128a0f5ebf7175f137c7aefc90bc 100644
> --- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-15.c
> +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-15.c
> @@ -1,5 +1,5 @@
>  /* { dg-do compile } */
> -/* { dg-options "-O2 -fdump-tree-dse1-details" } */
> +/* { dg-options "-O2 -fdump-tree-dse1-details -fmath-errno" } */
>
>  void *foo (int *p)
>  {
> diff --git a/gcc/testsuite/gcc.target/aarch64/no-inline-lrint_1.c b/gcc/testsuite/gcc.target/aarch64/no-inline-lrint_1.c
> index d5e9200562c166ace4d8e72d9a9f560e35846b29..229b456576a81d99427625a3e3f6cc63e937eb5a 100644
> --- a/gcc/testsuite/gcc.target/aarch64/no-inline-lrint_1.c
> +++ b/gcc/testsuite/gcc.target/aarch64/no-inline-lrint_1.c
> @@ -1,6 +1,6 @@
>  /* { dg-do compile } */
>  /* { dg-require-effective-target lp64 } */
> -/* { dg-options "-O3" } */
> +/* { dg-options "-O3 -fmath-errno" } */
>
>  #include "lrint-matherr.h"
>
Wilco Dijkstra June 19, 2018, 10:38 a.m. UTC | #4
Richard Biener wrote:

> There are a number of regression tests that check for errno handling
> (I added some to avoid aliasing for example).  Please make sure to
> add explicit -fmath-errno to those that do not already have it set
> (I guess such patch would be obvious and independent of this one).

All the tests apart from the ones I fixed are already correct, explicitly
setting -f(no-)math-errno if necessary, or they are unrelated to math
functions (eg. testing errno after strtol or mprotect).

> A grep -r errno testsuite/ is only 159 lines but it might not
> catch all cases - the one I'm refering to above matches because
> of a comment only:
>
> testsuite/gcc.dg/tree-ssa/ssa-dse-15.c:  /* We should be able to DSE this store
> (p may point to errno).  */

That one has after my patch:
/* { dg-options "-O2 -fdump-tree-dse1-details -fmath-errno" } */

> Following Josephs comment it may be reasonable to have the default
> depend on the targets C library and thus make it a target macro (IIRC
> the BSD libc never set errno for any math function for example).

Targets can override the math-errno default using the existing option
infrastructure if required. However even with softfloat one can test the
return value for Infinity/NaN, so even in that case errno is only required
if the application relies on it and the C library supports it.

> Josephs comment indicates conformance issues with a
> -fno-math-errno -fno-trapping-math combination (-ftrapping-math
> is default).

Maybe, it depends on what exactly -ftrapping-math implies, and that
is still unclear to me.

Wilco
Jeff Law June 21, 2018, 10:44 p.m. UTC | #5
On 06/19/2018 02:29 AM, Richard Biener wrote:
> On Mon, Jun 18, 2018 at 4:01 PM Wilco Dijkstra <Wilco.Dijkstra@arm.com> wrote:
>>
>> 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.  This is
>> already the case for non-C languages.  Only change the default for C99 and
>> later.
>>
>> 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
>>
>> With -fno-math-errno:
>>
>> f:
>>         fcvtas  x0, s0
>>         add     x0, x0, 1
>>         ret
>>
>> Passes regress on AArch64. OK for commit?
> 
> There are a number of regression tests that check for errno handling
> (I added some to avoid aliasing for example).  Please make sure to
> add explicit -fmath-errno to those that do not already have it set
> (I guess such patch would be obvious and independent of this one).
> 
> A grep -r errno testsuite/ is only 159 lines but it might not
> catch all cases - the one I'm refering to above matches because
> of a comment only:
> 
> testsuite/gcc.dg/tree-ssa/ssa-dse-15.c:  /* We should be able to DSE this store
> (p may point to errno).  */
We're concerned about errno as potentially set by malloc here.  It's
unrelated to the math-errno work.


Jeff
Jeff Law June 21, 2018, 10:53 p.m. UTC | #6
On 06/18/2018 10:46 AM, Joseph Myers wrote:
> On Mon, 18 Jun 2018, Jeff Law wrote:
> 
>> So do we need to set or check math_errhandling & MATH_ERRNO at all?  Or
> 
> That's a matter for libc (glibc currently sets it based on __FAST_MATH__ / 
> __NO_MATH_ERRNO__, but fails to avoid including MATH_ERREXCEPT in the 
> definition for configurations not supporting exceptions).
> 
>> WRT library behavior, I thought it was only complex arithmetic that had
>> the option of setting errno.  I thought float/double math functions had
>> a requirement to set errno?
> 
> For complex.h functions it's always optional.  For math.h functions at 
> least one of errno and exceptions must be set, as indicated in the 
> definition of math_errhandling (and if math_errhandling is defined to just 
> one of MATH_ERRNO and MATH_ERREXCEPT, functions then may or may not also 
> indicate errors in the other way).  Hence the question of whether a 
> -fno-math-errno default should be different for (mainly soft-float) 
> configurations not supporting floating-point exceptions, for which errno 
> is the only way they have available to indicate errors.
> 
Ah.  THanks for explaining things.

I think all this implies that the setting of -fno-math-errno by default
really depends on the math library in use since it's the library that
has to arrange for either errno to get set or for an exception to be raised.

I don't know enough about the various math runtimes to even hazard a
guess about the behavior of each.  glibc, musl, ulibc, newlib... THen
there's the alterate libraries from Intel & AMD and the proprietary Unix
math runtimes.  Ugh.

With that in mind ISTM that we may be best off keeping the default
as-is, but overriding it for libraries which we know are going to throw
exceptions rather than set errno.

Thoughts?

jeff
Joseph Myers June 22, 2018, 5:01 p.m. UTC | #7
On Thu, 21 Jun 2018, Jeff Law wrote:

> I think all this implies that the setting of -fno-math-errno by default
> really depends on the math library in use since it's the library that
> has to arrange for either errno to get set or for an exception to be raised.

If the library does not set errno, clearly -fno-math-errno by default is 
appropriate (and is the default on Darwin).

If the library does set errno, but the user doesn't care about the errno 
setting, -fno-math-errno is useful to that user; the question here is 
whether it's also an appropriate default to assume the user doesn't care 
about errno setting and so require them to pass -fmath-errno if they do.  
There are separate cases here for if the library does or does not set 
exceptions (the latter including most soft-float cases).

Then there are various built-in functions in GCC that use 
ATTR_MATHFN_FPROUNDING when they should use ATTR_MATHFN_FPROUNDING_ERRNO - 
because there are legitimate error cases for those functions for which 
errno setting is appropriate.  sin, cos, tan (domain errors for infinite 
arguments) are obvious examples.  (We have bug 64101 for erf, which is a 
case where the glibc model of when to set errno for underflow does *not* 
ever involve setting errno for this function, but some other 
implementations might have other models for when setting errno is 
appropriate.)
Wilco Dijkstra June 26, 2018, 1:52 p.m. UTC | #8
Joseph Myers wrote:
> On Thu, 21 Jun 2018, Jeff Law wrote:
>
> > I think all this implies that the setting of -fno-math-errno by default
> > really depends on the math library in use since it's the library that
> > has to arrange for either errno to get set or for an exception to be raised.
>
> If the library does not set errno, clearly -fno-math-errno by default is 
> appropriate (and is the default on Darwin).

Various librarys no longer set errno nowadays, for example BSD, MUSL, Bionic
etc. For GLIBC 3.0 I'd propose to drop setting of errno as well since very few
applications check errno after math functions that may set it (C89 support
could be added using wrappers that set errno if required).

> If the library does set errno, but the user doesn't care about the errno 
> setting, -fno-math-errno is useful to that user; the question here is 
> whether it's also an appropriate default to assume the user doesn't care 
> about errno setting and so require them to pass -fmath-errno if they do.  
> There are separate cases here for if the library does or does not set 
> exceptions (the latter including most soft-float cases).

For C99 and higher an application could check math_errhandling and report
an error if the libary does not support the required error handling. However
error checks are feasible even if the floating point runtime does not to set
exceptions since the return value will be NaN or Inf (of course in the case
of non-IEEE754 FP all bets are off).

Note errno is not guaranteed to not be set even if there is no error, so you
need to check the return value first before checking errno.

> Then there are various built-in functions in GCC that use 
> ATTR_MATHFN_FPROUNDING when they should use ATTR_MATHFN_FPROUNDING_ERRNO - 
> because there are legitimate error cases for those functions for which 
> errno setting is appropriate.  sin, cos, tan (domain errors for infinite 
> arguments) are obvious examples.  (We have bug 64101 for erf, which is a 
> case where the glibc model of when to set errno for underflow does *not* 
> ever involve setting errno for this function, but some other 
> implementations might have other models for when setting errno is 
> appropriate.)

That looks incorrect indeed but that's mostly a problem with -fmath-errno as it
would result in GCC assuming the function is const/pure when in fact it isn't.
Does ATTR_MATHFN_FPROUNDING imply that errno is dead after the call?

Wilco
Joseph Myers June 27, 2018, 8:03 p.m. UTC | #9
On Tue, 26 Jun 2018, Wilco Dijkstra wrote:

> > If the library does not set errno, clearly -fno-math-errno by default is 
> > appropriate (and is the default on Darwin).
> 
> Various librarys no longer set errno nowadays, for example BSD, MUSL, Bionic
> etc. For GLIBC 3.0 I'd propose to drop setting of errno as well since very few
> applications check errno after math functions that may set it (C89 support
> could be added using wrappers that set errno if required).

I think that's clearly something that would require new symbol versions 
for all affected symbols, or a new SONAME.

> That looks incorrect indeed but that's mostly a problem with -fmath-errno as it
> would result in GCC assuming the function is const/pure when in fact it isn't.
> Does ATTR_MATHFN_FPROUNDING imply that errno is dead after the call?

No, it implies a pure function, so the previous errno value is still live 
after the call.
Wilco Dijkstra June 27, 2018, 10:04 p.m. UTC | #10
Joseph Myers wrote:
> On Tue, 26 Jun 2018, Wilco Dijkstra wrote:

> > That looks incorrect indeed but that's mostly a problem with -fmath-errno as it
> > would result in GCC assuming the function is const/pure when in fact it isn't.
> > Does ATTR_MATHFN_FPROUNDING imply that errno is dead after the call?
>
> No, it implies a pure function, so the previous errno value is still live 
> after the call.

OK, so given GLIBC math functions may set errno anyway (irrespectively of the
math-errno setting used), those 2 settings are not sufficient. Ideally you'd need
to model GLIBC style errno as may or may not be set (still pure since it doesn't
affect global state but not assuming errno is live afterwards). But perhaps it
doesn't matter since this has been incorrect for years now...

Wilco
Joseph Myers June 27, 2018, 11:14 p.m. UTC | #11
On Wed, 27 Jun 2018, Wilco Dijkstra wrote:

> Joseph Myers wrote:
> > On Tue, 26 Jun 2018, Wilco Dijkstra wrote:
> 
> > > That looks incorrect indeed but that's mostly a problem with -fmath-errno as it
> > > would result in GCC assuming the function is const/pure when in fact it isn't.
> > > Does ATTR_MATHFN_FPROUNDING imply that errno is dead after the call?
> >
> > No, it implies a pure function, so the previous errno value is still live 
> > after the call.
> 
> OK, so given GLIBC math functions may set errno anyway (irrespectively of the
> math-errno setting used), those 2 settings are not sufficient. Ideally you'd need
> to model GLIBC style errno as may or may not be set (still pure since it doesn't
> affect global state but not assuming errno is live afterwards). But perhaps it
> doesn't matter since this has been incorrect for years now...

Well, in some cases I think it can be treated as pure with 
-fno-math-errno, because that option implies functions may or may not set 
errno.  So (in the absence of spurious errno settings from libm functions 
not encountering errors), if the compiler reuses an errno value from 
before a libm function call because the function was marked as pure, 
that's equivalent to the function call not in fact setting errno.  The 
trouble is that (a) generating a read of errno after the call when the 
actual access in the abstract machine was before the call would be bad if 
that call in fact sets errno, and (b) each execution of a call in the 
abstract machine should either execute as if it set errno, or execute as 
if it did not set errno, and optimizations might not preserve that 
property.
Wilco Dijkstra Sept. 4, 2018, 3:27 p.m. UTC | #12
ping




From: Wilco Dijkstra
Sent: 18 June 2018 15:01
To: GCC Patches
Cc: nd; Joseph Myers
Subject: [PATCH v3] Change default to -fno-math-errno
  

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.  This is
already the case for non-C languages.  Only change the default for C99 and
later.

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

With -fno-math-errno:

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

Passes regress on AArch64. OK for commit?

ChangeLog:
2018-06-18  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.

testsuite/

        * gcc.dg/errno-1.c: Add -fmath-errno.
        * gcc.dg/torture/pr68264.c: Likewise.
        * gcc.dg/tree-ssa/ssa-dse-15.c: Likewise.
        * gcc.target/aarch64/no-inline-lrint_1.c: Likewise.
--

diff --git a/gcc/c-family/c-opts.c b/gcc/c-family/c-opts.c
index bbcb1bb1a9c606a262a1aa362471388987629d06..b13fc122f8baf6aae0b47010be92ffd961b0147a 100644
--- a/gcc/c-family/c-opts.c
+++ b/gcc/c-family/c-opts.c
@@ -208,6 +208,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.  */
@@ -831,6 +834,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 d54e8e5601698c73d2c2bc8f354b55f3889a9186..e6fe11d1dcdbb39016242299dd3d76233e2bd976 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -1855,7 +1855,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 42832c5a50013d776dff47c6d347f5bc4dbef2d8..aeda219ba0dbe169d9fb2b4358950f2ba32b5c78 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -9783,24 +9783,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
@@ -21827,8 +21819,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 33efcc0d6e7db73ba60cab62ef146e976e75ca21..a6f228a53e1baa505a477a273fad3d00364f6893 100644
--- a/gcc/opts.c
+++ b/gcc/opts.c
@@ -2581,8 +2581,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
@@ -2595,6 +2593,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;
     }
 }
 
diff --git a/gcc/testsuite/gcc.dg/errno-1.c b/gcc/testsuite/gcc.dg/errno-1.c
index 0dfb00087dee04cd5ff1e916149c0c13c9b87b20..25739e4a862ca9a9c05157d3abc87216eb27ea7d 100644
--- a/gcc/testsuite/gcc.dg/errno-1.c
+++ b/gcc/testsuite/gcc.dg/errno-1.c
@@ -1,5 +1,5 @@
 /* { dg-do compile } */
-/* { dg-options "-O2" } */
+/* { dg-options "-O2 -fmath-errno" } */
 
 #include <errno.h>
 #include <stdlib.h>
diff --git a/gcc/testsuite/gcc.dg/torture/pr68264.c b/gcc/testsuite/gcc.dg/torture/pr68264.c
index 9294d5aedb79de1b91b3074e34b089b100031d54..56d7bf7bc64545566d7127a329f244045a0f2afc 100644
--- a/gcc/testsuite/gcc.dg/torture/pr68264.c
+++ b/gcc/testsuite/gcc.dg/torture/pr68264.c
@@ -1,5 +1,6 @@
 /* { dg-do run } */
 /* { dg-add-options ieee } */
+/* { dg-additional-options "-fmath-errno" } */
 /* { dg-require-effective-target fenv_exceptions } */
 
 #include <fenv.h>
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-15.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-15.c
index 43a41c8eb38db1c930923f1bb0fd9d1689fac826..134febf96d38128a0f5ebf7175f137c7aefc90bc 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-15.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-15.c
@@ -1,5 +1,5 @@
 /* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-dse1-details" } */
+/* { dg-options "-O2 -fdump-tree-dse1-details -fmath-errno" } */
 
 void *foo (int *p)
 {
diff --git a/gcc/testsuite/gcc.target/aarch64/no-inline-lrint_1.c b/gcc/testsuite/gcc.target/aarch64/no-inline-lrint_1.c
index d5e9200562c166ace4d8e72d9a9f560e35846b29..229b456576a81d99427625a3e3f6cc63e937eb5a 100644
--- a/gcc/testsuite/gcc.target/aarch64/no-inline-lrint_1.c
+++ b/gcc/testsuite/gcc.target/aarch64/no-inline-lrint_1.c
@@ -1,6 +1,6 @@
 /* { dg-do compile } */
 /* { dg-require-effective-target lp64 } */
-/* { dg-options "-O3" } */
+/* { dg-options "-O3 -fmath-errno" } */
 
 #include "lrint-matherr.h"
Jeff Law Oct. 3, 2018, 11:09 p.m. UTC | #13
On 9/4/18 9:27 AM, Wilco Dijkstra wrote:
> 
> ping
> 
> 
> 
> 
> From: Wilco Dijkstra
> Sent: 18 June 2018 15:01
> To: GCC Patches
> Cc: nd; Joseph Myers
> Subject: [PATCH v3] Change default to -fno-math-errno
>   
> 
> 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.  This is
> already the case for non-C languages.  Only change the default for C99 and
> later.
> 
> 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
> 
> With -fno-math-errno:
> 
> f:
>         fcvtas  x0, s0
>         add     x0, x0, 1
>         ret
> 
> Passes regress on AArch64. OK for commit?
> 
> ChangeLog:
> 2018-06-18  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.
> 
> testsuite/
> 
>         * gcc.dg/errno-1.c: Add -fmath-errno.
>         * gcc.dg/torture/pr68264.c: Likewise.
>         * gcc.dg/tree-ssa/ssa-dse-15.c: Likewise.
>         * gcc.target/aarch64/no-inline-lrint_1.c: Likewise.
So I went back and reviewed all the discussion around this.  I'm still
having trouble getting comfortable with flipping the default -- unless
we know ahead of time that the target runtime doesn't set errno on any
of the math routines.  That implies a target hook to describe the
runtime's handling off errno in math functions.  It also introduces
target dependencies early in the GIMPLE pipeline which is generally
counter to design goals around GIMPLE.

Essentially if we flip the default, we run the risk that user code which
does check this stuff will silently break.  That's not a good position
to take IMHO.

One could also argue that if we're using -fno-math-errno and we see
errno read after a math call without it being set/clobbered by some
other non-math call then we should be warning the user.  That'd be some
kind of propagation engine in gimple.  That would make flipping the
default more reasonable -- we'd have a reasonable chance of warning the
user that their code is potentially buggy and may need adjustment.

That led me to wonder if we could prove that for the majority of FP
intensive codes that even if the library set errno that nobody could
possibly be reading it, then we could in large part treat those builtin
calls as -fno-math-errno (we'd mark them somehow and check the mark at
GIMPLE->RTL expansion time (and possibly other points) to allow us to
generate machine instructions rather than library calls).  That would
get most of the benefit without the possibility to breaking user code.

I'm willing to go with Joseph's recommendation here, but I'm not really
comfortable acking the patch as-is on my own.

jeff
Richard Biener Oct. 4, 2018, 8:15 a.m. UTC | #14
On Thu, Oct 4, 2018 at 1:10 AM Jeff Law <law@redhat.com> wrote:
>
> On 9/4/18 9:27 AM, Wilco Dijkstra wrote:
> >
> > ping
> >
> >
> >
> >
> > From: Wilco Dijkstra
> > Sent: 18 June 2018 15:01
> > To: GCC Patches
> > Cc: nd; Joseph Myers
> > Subject: [PATCH v3] Change default to -fno-math-errno
> >
> >
> > 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.  This is
> > already the case for non-C languages.  Only change the default for C99 and
> > later.
> >
> > 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
> >
> > With -fno-math-errno:
> >
> > f:
> >         fcvtas  x0, s0
> >         add     x0, x0, 1
> >         ret
> >
> > Passes regress on AArch64. OK for commit?
> >
> > ChangeLog:
> > 2018-06-18  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.
> >
> > testsuite/
> >
> >         * gcc.dg/errno-1.c: Add -fmath-errno.
> >         * gcc.dg/torture/pr68264.c: Likewise.
> >         * gcc.dg/tree-ssa/ssa-dse-15.c: Likewise.
> >         * gcc.target/aarch64/no-inline-lrint_1.c: Likewise.
> So I went back and reviewed all the discussion around this.  I'm still
> having trouble getting comfortable with flipping the default -- unless
> we know ahead of time that the target runtime doesn't set errno on any
> of the math routines.  That implies a target hook to describe the
> runtime's handling off errno in math functions.  It also introduces
> target dependencies early in the GIMPLE pipeline which is generally
> counter to design goals around GIMPLE.
>
> Essentially if we flip the default, we run the risk that user code which
> does check this stuff will silently break.  That's not a good position
> to take IMHO.
>
> One could also argue that if we're using -fno-math-errno and we see
> errno read after a math call without it being set/clobbered by some
> other non-math call then we should be warning the user.  That'd be some
> kind of propagation engine in gimple.  That would make flipping the
> default more reasonable -- we'd have a reasonable chance of warning the
> user that their code is potentially buggy and may need adjustment.
>
> That led me to wonder if we could prove that for the majority of FP
> intensive codes that even if the library set errno that nobody could
> possibly be reading it, then we could in large part treat those builtin
> calls as -fno-math-errno (we'd mark them somehow and check the mark at
> GIMPLE->RTL expansion time (and possibly other points) to allow us to
> generate machine instructions rather than library calls).  That would
> get most of the benefit without the possibility to breaking user code.

One major issue here is that there's no way for GCC to know what
access constitutes an access to errno.  We already have "hacks" in place
that even though things like pow() techincally clobber memory we only
consider (with TBAA) clobbers of 'int' typed memory.

glibc currently calls __errno_location to get at a pointer to errno, so
theoretically we could add a __attribute__((returns_errno_location))
and a __attribute__((errno)) for implementations that have a global
(TLS?) variable __errno.  Then points-to analysis could track this,
but that also means this tracking would be weak.

The other issue is that we're treating -fno-math-errno as disabling
errno handling in general (not only for math functions).  That would
have to be fixed when we switch the default (or even now...  though
nobody uses errno set from malloc & friends which is where we abuse
the flag).

Richard.

> I'm willing to go with Joseph's recommendation here, but I'm not really
> comfortable acking the patch as-is on my own.
>
> jeff
Joseph Myers Oct. 4, 2018, 12:06 p.m. UTC | #15
On Thu, 4 Oct 2018, Richard Biener wrote:

> The other issue is that we're treating -fno-math-errno as disabling
> errno handling in general (not only for math functions).  That would

Also, is it treated as meaning the math functions *do not set errno* (so a 
load of errno (or of anything that might be errno) before a math function 
call could be moved after the call)?  Because the proper meaning is simply 
*may not set errno* (so you shouldn't be able to move an errno load across 
a call like that, since the call might still happen to clobber it - of 
course if it happens to be a call that GCC inlines and eliminates any 
possibility of errno setting that way, e.g. sqrt on many platforms, or a 
platform where libm never sets errno at all, then such a move is safe).
Richard Biener Oct. 4, 2018, 12:37 p.m. UTC | #16
On Thu, Oct 4, 2018 at 2:06 PM Joseph Myers <joseph@codesourcery.com> wrote:
>
> On Thu, 4 Oct 2018, Richard Biener wrote:
>
> > The other issue is that we're treating -fno-math-errno as disabling
> > errno handling in general (not only for math functions).  That would
>
> Also, is it treated as meaning the math functions *do not set errno* (so a
> load of errno (or of anything that might be errno) before a math function
> call could be moved after the call)?

Yes.  That's implicit in math functions becoming CONST.

>  Because the proper meaning is simply
> *may not set errno* (so you shouldn't be able to move an errno load across
> a call like that, since the call might still happen to clobber it - of
> course if it happens to be a call that GCC inlines and eliminates any
> possibility of errno setting that way, e.g. sqrt on many platforms, or a
> platform where libm never sets errno at all, then such a move is safe).

So it means that GCC may elide errno setting (by inlining a function
for example)
but otherwise assume nothing else?  That makes it quite useless to optimizers.
For example the vectorizer would need to know pow() doesn't clobber
random memory
and thus causes dependency issues.  It's of course also inconsistent with
the fact that we make those math functions CONST with -fno-math-errno.

I see that the user documentation suggests what you say but I'll note that
implementation-wise we've done what I explained for a long time now.

Richard.

> --
> Joseph S. Myers
> joseph@codesourcery.com
Joseph Myers Oct. 4, 2018, 1:20 p.m. UTC | #17
On Thu, 4 Oct 2018, Richard Biener wrote:

> So it means that GCC may elide errno setting (by inlining a function for 
> example) but otherwise assume nothing else?

Yes, on systems where libm functions do in fact set errno (but it can also 
assume that only the actual errno variable is clobbered, not e.g. some 
random int in the middle of your array).  (It would be possible to have 
libm function variants that explicitly guarantee not to set errno, if 
there are particular functions for which having such variants is useful to 
e.g. the vectorizer, but it would of course be a property of the libm 
implementation whether such variants are available and for what 
functions.)

There could be a variant option that does mean "libm functions are not 
called with arguments that make them set errno", and -ffast-math could 
imply that (-ffinite-math-only doesn't, because e.g. underflow is 
consistent with -ffinite-math-only but can result in errno setting).

Or you could say -fno-math-errno is that variant option, but the thing 
enabled by default is the weaker option meaning "may or may not set errno" 
(but if Darwin libm indeed never sets errno, the stronger version should 
be enabled by default there).
Jeff Law Oct. 4, 2018, 1:25 p.m. UTC | #18
On 10/4/18 6:37 AM, Richard Biener wrote:
> On Thu, Oct 4, 2018 at 2:06 PM Joseph Myers <joseph@codesourcery.com> wrote:
>>
>> On Thu, 4 Oct 2018, Richard Biener wrote:
>>
>>> The other issue is that we're treating -fno-math-errno as disabling
>>> errno handling in general (not only for math functions).  That would
>>
>> Also, is it treated as meaning the math functions *do not set errno* (so a
>> load of errno (or of anything that might be errno) before a math function
>> call could be moved after the call)?
> 
> Yes.  That's implicit in math functions becoming CONST.
Right.  But I think this highlights the other issue here.  Namely that
if the user's code does read errno, we don't know if the intent was to
read errno from some other call before the math bits or the most recent
math call.

So again, as much as I'd like to move to a world where we don't have to
worry about errno for math functions, I'm not comfortable making that
change, though I won't object if someone  with a stronger standards
background says "just do it".

jeff
Szabolcs Nagy Oct. 4, 2018, 1:53 p.m. UTC | #19
On 04/10/18 14:25, Jeff Law wrote:
> On 10/4/18 6:37 AM, Richard Biener wrote:
>> On Thu, Oct 4, 2018 at 2:06 PM Joseph Myers <joseph@codesourcery.com> wrote:
>>>
>>> On Thu, 4 Oct 2018, Richard Biener wrote:
>>>
>>>> The other issue is that we're treating -fno-math-errno as disabling
>>>> errno handling in general (not only for math functions).  That would
>>>
>>> Also, is it treated as meaning the math functions *do not set errno* (so a
>>> load of errno (or of anything that might be errno) before a math function
>>> call could be moved after the call)?
>>
>> Yes.  That's implicit in math functions becoming CONST.
> Right.  But I think this highlights the other issue here.  Namely that
> if the user's code does read errno, we don't know if the intent was to
> read errno from some other call before the math bits or the most recent
> math call.
> 

if (math_errhandling & MATH_ERRNO) == 0 a math
function may still set errno.

it can only set it if there was an error though,
not arbitrarily clobber it, but this means that

(1) reordering errno access around math calls is
invalid even with -fno-math-errno.

(2) user code reading errno after a math call can
assume it to be unmodified in exactly the same
cases with -fmath-errno and -fno-math-errno.

> So again, as much as I'd like to move to a world where we don't have to
> worry about errno for math functions, I'm not comfortable making that
> change, though I won't object if someone  with a stronger standards
> background says "just do it".
> 
> jeff
>
Joseph Myers Oct. 4, 2018, 5:29 p.m. UTC | #20
On Wed, 3 Oct 2018, Jeff Law wrote:

> That led me to wonder if we could prove that for the majority of FP
> intensive codes that even if the library set errno that nobody could
> possibly be reading it, then we could in large part treat those builtin
> calls as -fno-math-errno (we'd mark them somehow and check the mark at
> GIMPLE->RTL expansion time (and possibly other points) to allow us to
> generate machine instructions rather than library calls).  That would
> get most of the benefit without the possibility to breaking user code.

I doubt you could prove that without LTO of the whole program because an 
errno value set by a libm function call could always be checked in the 
caller of whatever function is being compiled.

I think it's reasonable to have a default (outside C90 mode) of not 
requiring libm functions to set errno - but as discussed that's different 
from the present effects of -fno-math-errno.  There seem to be three 
reasonable modes here:

(a) Assume errno setting from libm functions in error cases may be 
required by the user; avoid inlining them in ways that would lose such 
errno setting.  This is -fmath-errno.

(b) Assume libm functions may set errno in error cases but this is not 
required by the user, so such functions may be inlined in ways that lose 
errno setting.  This might be the new default outside C90 mode.  
Furthermore, for complex.h functions this can be the default even with 
-fmath-errno; complex.h functions are never required to set errno, 
regardless of the value of math_errhandling.

(c) Optimize on the basis that libm functions do not set errno and thus it 
is OK to move what might be loads and stores of errno across calls to libm 
functions.  Maybe -fno-math-errno does this in fact, but it's not the 
documented semantics, and it breaks valid C code in some cases.  This is 
OK as the default on platforms where libm functions never set errno 
(Darwin?).

(None of these modes should have anything to do with whether other 
standard library functions such as malloc set errno; if optimizations for 
that are useful, they should be controlled by an option whose name does 
not involve "math".)

If we distinguish (b) and (c) in order to change the default, we also need 
a new option name for whichever of them doesn't get the name 
-fno-math-errno.  Both options should result in __NO_MATH_ERRNO__ being 
defined.


In general, libm functions are "const/pure with exceptions".  Maybe there 
should be attributes to describe such a function property - of course, 
none of this is needed to change the math-errno default, it's simply a way 
in which more precise optimization in this area might be allowed.  If so, 
it's critical that no warnings (like those for declaring a function with 
both const and pure) should result from libraries declaring a function 
with properties stricter than those required by the standard, but still 
permitted by the standard semantics, when the built-in function is 
declared only with the properties required by the standard.  That is, it 
must be OK for the built-in function to declare that it may set errno but 
is otherwise pure, and for the library, based on headers seeing 
__NO_MATH_ERRNO__ defined, to select a variant that it declares never sets 
errno.

Here are some of the ways in which a function can be const/pure with 
exceptions (which may be converted by the compiler into being entirely 
const or pure based on command-line options).

* Function depends, or does not depend, on the rounding mode (but does not 
read other global state).  What this means in terms of being const versus 
pure depends on -frounding-math (which has no corresponding preprocessor 
macro, so it's not possible for library headers to choose a different 
attribute depending on -frounding-math).

* Function may set exceptions for no inputs (e.g. fabs, copysign), only 
for signaling NaNs (e.g. trunc) or for inputs other than signaling NaNs.  
There's no preprocessor macro for -f(no-)trapping-math.

* Function may set errno in error cases, or is guaranteed not to do so.

Apart from lgamma functions setting signgam, I think all math.h / 
complex.h functions without pointer arguments should be const apart from 
rounding mode, exceptions and errno.  (For this purpose I'm ignoring other 
error-handling mechanisms like SVID matherr / _LIB_VERSION that involve 
other global state - obsoleted in glibc 2.27 so that with glibc you can no 
longer link a new program or library to use that mechanism.  I think if 
you're using such mechanisms it's reasonable to require you to use 
-fno-builtin-* to avoid problematic optimizations, similar to if you're 
using printf hooks or interposed malloc that access global state visible 
in the caller - all of these things are going well outside the standard.)
Jeff Law Oct. 4, 2018, 6:35 p.m. UTC | #21
On 10/4/18 11:29 AM, Joseph Myers wrote:
> On Wed, 3 Oct 2018, Jeff Law wrote:
> 
>> That led me to wonder if we could prove that for the majority of FP
>> intensive codes that even if the library set errno that nobody could
>> possibly be reading it, then we could in large part treat those builtin
>> calls as -fno-math-errno (we'd mark them somehow and check the mark at
>> GIMPLE->RTL expansion time (and possibly other points) to allow us to
>> generate machine instructions rather than library calls).  That would
>> get most of the benefit without the possibility to breaking user code.
> 
> I doubt you could prove that without LTO of the whole program because an 
> errno value set by a libm function call could always be checked in the 
> caller of whatever function is being compiled.
Right, but if you have a series of calls like


  t1 = sqrt (x);
  t2 = sqrt (y);
  t3 = sqrt (z);
  return t1 + t2 + t3;

You know that errno from the first two isn't examined and you could emit
the hardware insn for sqrt in those cases.  You couldn't do so for the
3rd because you don't necessarily have the caller context.

But as Richi reminded us it can be exceedingly painful to find reads of
errno because of the way it's defined by glibc (presumably for thread
safety).  So this may be academic in practice.
Jeff
Joseph Myers Oct. 4, 2018, 7:43 p.m. UTC | #22
On Thu, 4 Oct 2018, Jeff Law wrote:

> > I doubt you could prove that without LTO of the whole program because an 
> > errno value set by a libm function call could always be checked in the 
> > caller of whatever function is being compiled.
> Right, but if you have a series of calls like
> 
> 
>   t1 = sqrt (x);
>   t2 = sqrt (y);
>   t3 = sqrt (z);
>   return t1 + t2 + t3;
> 
> You know that errno from the first two isn't examined and you could emit
> the hardware insn for sqrt in those cases.  You couldn't do so for the
> 3rd because you don't necessarily have the caller context.

No, you don't know that error from the first two isn't examined.  sqrt 
doesn't set errno on success.  A caller could set errno to 0 before that 
code, then check for errno == EDOM afterwards, meaning that any of the 
sqrt arguments were negative.  (The caller could also check whether the 
result is a NaN and so not need errno, of course.)
Richard Biener Oct. 8, 2018, 10:11 a.m. UTC | #23
On Thu, Oct 4, 2018 at 9:43 PM Joseph Myers <joseph@codesourcery.com> wrote:
>
> On Thu, 4 Oct 2018, Jeff Law wrote:
>
> > > I doubt you could prove that without LTO of the whole program because an
> > > errno value set by a libm function call could always be checked in the
> > > caller of whatever function is being compiled.
> > Right, but if you have a series of calls like
> >
> >
> >   t1 = sqrt (x);
> >   t2 = sqrt (y);
> >   t3 = sqrt (z);
> >   return t1 + t2 + t3;
> >
> > You know that errno from the first two isn't examined and you could emit
> > the hardware insn for sqrt in those cases.  You couldn't do so for the
> > 3rd because you don't necessarily have the caller context.
>
> No, you don't know that error from the first two isn't examined.  sqrt
> doesn't set errno on success.  A caller could set errno to 0 before that
> code, then check for errno == EDOM afterwards, meaning that any of the
> sqrt arguments were negative.  (The caller could also check whether the
> result is a NaN and so not need errno, of course.)

So I think it would be fine if we'd have -fno-math-errno as documented
and then the C library would annotate their math functions according
to whether they will ever set errno or not.  Once a math function is
const or pure it cannot ever set errno so -fno-math-errno shouldn't have
any effect.

Then a C library could say that if a user says -D_I_NEED_NO_ERRNO_FROM_MATH
then it could redirect to appropriate functions?

Just assuming that the latter is easier for the library itself than
from the compiler.

glibc has the ieee entry points but I'm not sure if it has any way
to use those by default.

Richard.

> --
> Joseph S. Myers
> joseph@codesourcery.com
Joseph Myers Oct. 8, 2018, 11:47 a.m. UTC | #24
On Mon, 8 Oct 2018, Richard Biener wrote:

> So I think it would be fine if we'd have -fno-math-errno as documented
> and then the C library would annotate their math functions according
> to whether they will ever set errno or not.  Once a math function is
> const or pure it cannot ever set errno so -fno-math-errno shouldn't have
> any effect.

Note that "will ever set errno" includes possibly setting it in the 
future, since code may be built with one libm version and used with 
another.  So it wouldn't be correct to have a "never sets errno" attribute 
on glibc logb / lround / llround / lrint / llrint / fma / remquo (missing 
errno setting is a known bug).  It also wouldn't be correct to have it on 
many complex.h functions, because while a requirement to set errno is 
never part of their interface, they may call real functions which may set 
errno (and may sometimes move from not setting it to setting it; e.g., 
they call the internal exp, sincos etc. functions, which for 
implementations using a wrapper do not set errno, but for implementations 
without a wrapper have errno setting integrated; whether this results in 
errno set by complex functions depends on details of exactly how they 
handle overflow etc. cases).

(Also, directly setting const/pure on most libm functions runs into issues 
of what exactly that means regarding floating-point exceptions and 
rounding modes - and the need to avoid libm specifying a stricter 
attribute than the built-in function if that results in diagnostics from 
GCC.  glibc specifies const on a few functions that don't raise exceptions 
or depend on the rounding mode, and even some of those are questionable if 
raising "invalid" for signaling NaNs is an issue.)

> glibc has the ieee entry points but I'm not sure if it has any way
> to use those by default.

__ieee754_* have never been exported from shared libm.

The old -lieee mechanism, no longer supported, involved libm function 
wrappers reading a writable global variable _LIB_VERSION to determine how 
to handle errors; depending on writable global data like that was itself 
obviously problematic.
Jeff Law Oct. 8, 2018, 2:47 p.m. UTC | #25
On 10/4/18 1:43 PM, Joseph Myers wrote:
> On Thu, 4 Oct 2018, Jeff Law wrote:
> 
>>> I doubt you could prove that without LTO of the whole program because an 
>>> errno value set by a libm function call could always be checked in the 
>>> caller of whatever function is being compiled.
>> Right, but if you have a series of calls like
>>
>>
>>   t1 = sqrt (x);
>>   t2 = sqrt (y);
>>   t3 = sqrt (z);
>>   return t1 + t2 + t3;
>>
>> You know that errno from the first two isn't examined and you could emit
>> the hardware insn for sqrt in those cases.  You couldn't do so for the
>> 3rd because you don't necessarily have the caller context.
> 
> No, you don't know that error from the first two isn't examined.  sqrt 
> doesn't set errno on success.  A caller could set errno to 0 before that 
> code, then check for errno == EDOM afterwards, meaning that any of the 
> sqrt arguments were negative.  (The caller could also check whether the 
> result is a NaN and so not need errno, of course.)
You're right of course.

Jeff
Wilco Dijkstra Oct. 11, 2018, 1:09 p.m. UTC | #26
Hi Jeff,

> So I went back and reviewed all the discussion around this.  I'm still
> having trouble getting comfortable with flipping the default -- unless
> we know ahead of time that the target runtime doesn't set errno on any
> of the math routines.  That implies a target hook to describe the
> runtime's handling off errno in math functions.  It also introduces
> target dependencies early in the GIMPLE pipeline which is generally
> counter to design goals around GIMPLE.

The goal of my patch was to inline single-instruction functions, so for
these cases you can be 100% sure errno will never be set. No target
hooks are required for this, and it works exactly as documented.

It turns out -fmath-errno is already quite broken since GCC treats
many math functions as never setting errno when in fact GLIBC does 
set errno in almost all math functions.

> Essentially if we flip the default, we run the risk that user code which
> does check this stuff will silently break.  That's not a good position
> to take IMHO.

-fmath-errno is already broken today for many math functions. That's a
much more serious issue than setting errno when we don't care about
errno anyway.

> That led me to wonder if we could prove that for the majority of FP
> intensive codes that even if the library set errno that nobody could
> possibly be reading it, then we could in large part treat those builtin
> calls as -fno-math-errno (we'd mark them somehow and check the mark at
> GIMPLE->RTL expansion time (and possibly other points) to allow us to
> generate machine instructions rather than library calls).  That would
> get most of the benefit without the possibility to breaking user code.

I don't believe any of this is worth the effort. Errno for math functions has
been dead for several decades. A user who really cares about errno can find
the correct option, like one needs for similar rare cases (eg. -frounding-math
which is not the default).

Wilco
Wilco Dijkstra Oct. 11, 2018, 1:43 p.m. UTC | #27
Joseph Myers wrote:
> On Mon, 8 Oct 2018, Richard Biener wrote:

>> So I think it would be fine if we'd have -fno-math-errno as documented
>> and then the C library would annotate their math functions according
>> to whether they will ever set errno or not.  Once a math function is
>> const or pure it cannot ever set errno so -fno-math-errno shouldn't have
>> any effect.
>
> Note that "will ever set errno" includes possibly setting it in the 
> future, since code may be built with one libm version and used with 
> another.  So it wouldn't be correct to have a "never sets errno" attribute 
> on glibc logb / lround / llround / lrint / llrint / fma / remquo (missing 
> errno setting is a known bug).  

Math functions don't require errno to be set if math_errhandling doesn't
specify MATH_ERRNO. So it's certainly feasible to guarantee errno
won't ever be set. It would even be feasible to decide per application
whether GLIBC sets errno or not.

My feeling is that errno from math functions has been dead for long enough
that removing support for it from libraries is very reasonable - and many
libraries have already done so. Have there been any reports of this breaking
large numbers of applications?

> It also wouldn't be correct to have it on 
> many complex.h functions, because while a requirement to set errno is 
> never part of their interface, they may call real functions which may set 
> errno (and may sometimes move from not setting it to setting it; e.g., 
> they call the internal exp, sincos etc. functions, which for 
> implementations using a wrapper do not set errno, but for implementations 
> without a wrapper have errno setting integrated; whether this results in 
> errno set by complex functions depends on details of exactly how they 
> handle overflow etc. cases).

Math functions (with or without a wrapper) can conditionally set errno if required.
You could save/restore errno in really complicated math functions, as is done for
rounding modes and exception flags.

For the new math functions all errno handling is already done in a single function
so you could do something like: if (want_errno) set_errno (error).

>> glibc has the ieee entry points but I'm not sure if it has any way
>> to use those by default.

Adding more entry points is a bad idea, the __finite entry points and slow
wrappers are bad enough as it is. The new optimized math functions use a
much more efficient and maintainable approach.

Wilco
Wilco Dijkstra Oct. 11, 2018, 2:39 p.m. UTC | #28
Hi,

> Note that "will ever set errno" includes possibly setting it in the 
> future, since code may be built with one libm version and used with 
> another.  So it wouldn't be correct to have a "never sets errno" attribute 
> on glibc logb / lround / llround / lrint / llrint / fma / remquo (missing 
> errno setting is a known bug).  

If these functions should set errno, there are many issues both in GCC and
GLIBC. GCC treats fma and remquo always as const/pure, so inlines fma
always even with -fmath-errno. GLIBC targets which support fma as a
single instruction always inline it as a single instruction, as expected.

GCC incorrectly treats many other math functions as const/pure, for 
example GCC "knows" that the C89 sin function will never set errno with
-fmath-errno:

#include <math.h>
#include <errno.h>
int res;
double f(double x)
{
  errno = 0;
  double y = sin (x);
  res = errno;
  return y;
}

So if anything this is good evidence that nobody is using errno in actual
applications, otherwise these bugs would have been found many years ago.

Wilco
Wilco Dijkstra Oct. 11, 2018, 3:29 p.m. UTC | #29
Hi,
  
> if (math_errhandling & MATH_ERRNO) == 0 a math
> function may still set errno.
>
> it can only set it if there was an error though,
> not arbitrarily clobber it, but this means that
>
> (1) reordering errno access around math calls is
> invalid even with -fno-math-errno.

It's typically the math calls themselves which are optimized, moved, CSEd etc.
However if a compiler has to optimize based on the assumuption that math
calls may still set errno then no optimizations are feasible.

> (2) user code reading errno after a math call can
> assume it to be unmodified in exactly the same
> cases with -fmath-errno and -fno-math-errno.

Again, that would mean there cannot be any difference in code generation
(which blocks all optimization).

To optimize math calls you really need to assume they are const and don't
write errno. This can be done by ensuring the library never sets errno for math
functions or simply ignore the low probability that an optimized math call might
corrupt a non-math use of errno (like GCC already does today for many math
functions, even with -fmath-errno).

Wilco
Joseph Myers Oct. 11, 2018, 5:43 p.m. UTC | #30
On Thu, 11 Oct 2018, Wilco Dijkstra wrote:

> For the new math functions all errno handling is already done in a 
> single function so you could do something like: if (want_errno) 
> set_errno (error).

want_errno being a global (or TLS) variable gets into the same problems as 
_LIB_VERSION; you want something that's a property of the particular call 
to the function, based on the options used to compile that call (which 
gets you into either wrappers, or building selected functions twice to 
provide no-errno-setting entry point, if you want to be able to optimize 
on the basis that a call cannot change errno).

Saving and restoring seems a plausible approach if you want to e.g. 
provide a guarantee in future glibc versions that complex.h functions will 
not set errno (they'd need review to see if at present they can actually 
call any error cases of other functions that might set errno, or if there 
isn't a problem anyway).
Joseph Myers Oct. 11, 2018, 5:51 p.m. UTC | #31
On Thu, 11 Oct 2018, Wilco Dijkstra wrote:

> Hi,
> 
> > Note that "will ever set errno" includes possibly setting it in the 
> > future, since code may be built with one libm version and used with 
> > another.  So it wouldn't be correct to have a "never sets errno" attribute 
> > on glibc logb / lround / llround / lrint / llrint / fma / remquo (missing 
> > errno setting is a known bug).  
> 
> If these functions should set errno, there are many issues both in GCC and
> GLIBC. GCC treats fma and remquo always as const/pure, so inlines fma
> always even with -fmath-errno. GLIBC targets which support fma as a
> single instruction always inline it as a single instruction, as expected.
> 
> GCC incorrectly treats many other math functions as const/pure, for 
> example GCC "knows" that the C89 sin function will never set errno with
> -fmath-errno:

That (for sin) is bug 80042.  (While bug 37073 is enabling for FreeBSD the 
same optimizations as on Darwin and bug 64101 deals with a case where 
glibc's rules for errno setting on underflow do not require errno to be 
set, ISO C leaving that as implementation-defined, but some 
implementations, including the one used by the bug reporter, follow 
different rules that do involve setting errno.)

I suspect the current settings in GCC are based on someone's observations 
of what one particular implementation did around 2003; they aren't based 
on the standard.

> So if anything this is good evidence that nobody is using errno in actual
> applications, otherwise these bugs would have been found many years ago.

People *did* find such bugs, referenced above (but many uses likely would 
be such that the code movement in question does not occur and so the errno 
tests work anyway).

I think it would be reasonable to move to a -fno-math-errno default that 
actually matches the standard semantics (various functions may set errno 
but aren't required to, so replacing with single instructions is OK - 
without requiring a fix for the existing functions wrongly marked as never 
setting errno).  A stronger default (assume the functions never set errno) 
is appropriate on Darwin and FreeBSD (and potentially for some functions 
on some other platforms, if those platforms define no-errno-setting 
semantics for those functions rather than simply not setting errno by 
accident for them), and an explicit option could be used to enable such a 
stronger version on other platforms, and we could provide a way for libm 
implementations to declare that a function variant will never set errno.
diff mbox series

Patch

diff --git a/gcc/c-family/c-opts.c b/gcc/c-family/c-opts.c
index bbcb1bb1a9c606a262a1aa362471388987629d06..b13fc122f8baf6aae0b47010be92ffd961b0147a 100644
--- a/gcc/c-family/c-opts.c
+++ b/gcc/c-family/c-opts.c
@@ -208,6 +208,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.  */
@@ -831,6 +834,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 d54e8e5601698c73d2c2bc8f354b55f3889a9186..e6fe11d1dcdbb39016242299dd3d76233e2bd976 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -1855,7 +1855,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 42832c5a50013d776dff47c6d347f5bc4dbef2d8..aeda219ba0dbe169d9fb2b4358950f2ba32b5c78 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -9783,24 +9783,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
@@ -21827,8 +21819,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 33efcc0d6e7db73ba60cab62ef146e976e75ca21..a6f228a53e1baa505a477a273fad3d00364f6893 100644
--- a/gcc/opts.c
+++ b/gcc/opts.c
@@ -2581,8 +2581,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
@@ -2595,6 +2593,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;
     }
 }
 
diff --git a/gcc/testsuite/gcc.dg/errno-1.c b/gcc/testsuite/gcc.dg/errno-1.c
index 0dfb00087dee04cd5ff1e916149c0c13c9b87b20..25739e4a862ca9a9c05157d3abc87216eb27ea7d 100644
--- a/gcc/testsuite/gcc.dg/errno-1.c
+++ b/gcc/testsuite/gcc.dg/errno-1.c
@@ -1,5 +1,5 @@ 
 /* { dg-do compile } */
-/* { dg-options "-O2" } */
+/* { dg-options "-O2 -fmath-errno" } */
 
 #include <errno.h>
 #include <stdlib.h>
diff --git a/gcc/testsuite/gcc.dg/torture/pr68264.c b/gcc/testsuite/gcc.dg/torture/pr68264.c
index 9294d5aedb79de1b91b3074e34b089b100031d54..56d7bf7bc64545566d7127a329f244045a0f2afc 100644
--- a/gcc/testsuite/gcc.dg/torture/pr68264.c
+++ b/gcc/testsuite/gcc.dg/torture/pr68264.c
@@ -1,5 +1,6 @@ 
 /* { dg-do run } */
 /* { dg-add-options ieee } */
+/* { dg-additional-options "-fmath-errno" } */
 /* { dg-require-effective-target fenv_exceptions } */
 
 #include <fenv.h>
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-15.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-15.c
index 43a41c8eb38db1c930923f1bb0fd9d1689fac826..134febf96d38128a0f5ebf7175f137c7aefc90bc 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-15.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-15.c
@@ -1,5 +1,5 @@ 
 /* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-dse1-details" } */
+/* { dg-options "-O2 -fdump-tree-dse1-details -fmath-errno" } */
 
 void *foo (int *p)
 {
diff --git a/gcc/testsuite/gcc.target/aarch64/no-inline-lrint_1.c b/gcc/testsuite/gcc.target/aarch64/no-inline-lrint_1.c
index d5e9200562c166ace4d8e72d9a9f560e35846b29..229b456576a81d99427625a3e3f6cc63e937eb5a 100644
--- a/gcc/testsuite/gcc.target/aarch64/no-inline-lrint_1.c
+++ b/gcc/testsuite/gcc.target/aarch64/no-inline-lrint_1.c
@@ -1,6 +1,6 @@ 
 /* { dg-do compile } */
 /* { dg-require-effective-target lp64 } */
-/* { dg-options "-O3" } */
+/* { dg-options "-O3 -fmath-errno" } */
 
 #include "lrint-matherr.h"