public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
* [Bug middle-end/102126] New: Wrong optimization of multiplication by 1 and -1 with -ftrapping-math when an underflow is possible
@ 2021-08-30  9:11 vincent-gcc at vinc17 dot net
  2021-08-30  9:22 ` [Bug middle-end/102126] Wrong optimization of FP multiplication and division " vincent-gcc at vinc17 dot net
                   ` (7 more replies)
  0 siblings, 8 replies; 9+ messages in thread
From: vincent-gcc at vinc17 dot net @ 2021-08-30  9:11 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102126

            Bug ID: 102126
           Summary: Wrong optimization of multiplication by 1 and -1 with
                    -ftrapping-math when an underflow is possible
           Product: gcc
           Version: 11.2.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: middle-end
          Assignee: unassigned at gcc dot gnu.org
          Reporter: vincent-gcc at vinc17 dot net
  Target Milestone: ---

Without -fsignaling-nans, GCC optimizes the floating-point multiplication by 1
as a no-op, even when it may generate a trap due to underflow. This is wrong.

Testcase:

#define _GNU_SOURCE
#include <stdio.h>
#include <float.h>
#include <fenv.h>
#pragma STDC FENV_ACCESS ON

double f (double x)
{
  return x * 1.0;
}

double g (double x)
{
  volatile double one = 1.0;
  return x * one;
}

int main (void)
{
  volatile double x = DBL_MIN / 2, y;

  feenableexcept (FE_UNDERFLOW);
  y = f(x);
  printf ("f: %d\n", y != 0);
  y = g(x);
  printf ("g: %d\n", y != 0);

  return 0;
}

Here, x is a subnormal, so that its multiplication by 1 signals an underflow.
Note that since the result is exact, the underflow flag is not raised under the
default exception handling, so that without -ftrapping-math and
-fsignaling-nans, f() may be optimized to no-op. With -fsignaling-nans, GCC
disables the optimization as expected. But with -ftrapping-math, it doesn't
(the optimization is done at any optimization level, even -O0); this can be
seen in the generated asm code, with -S.

When executing the code (with -O3 -ftrapping-math -lm):

f: 1
Floating point exception (core dumped)

showing that f() was incorrectly optimized, and that g(), which is not
optimized due to volatile, gives a floating-point exception as expected.

Similar issue with the multiplication by -1 (at least on x86_64), where GCC
just negates the value.

Bug reproducible from at least GCC 4.6 to GCC 11.2.0.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [Bug middle-end/102126] Wrong optimization of FP multiplication and division by 1 and -1 with -ftrapping-math when an underflow is possible
  2021-08-30  9:11 [Bug middle-end/102126] New: Wrong optimization of multiplication by 1 and -1 with -ftrapping-math when an underflow is possible vincent-gcc at vinc17 dot net
@ 2021-08-30  9:22 ` vincent-gcc at vinc17 dot net
  2021-08-30  9:37 ` vincent-gcc at vinc17 dot net
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: vincent-gcc at vinc17 dot net @ 2021-08-30  9:22 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102126

--- Comment #1 from Vincent Lefèvre <vincent-gcc at vinc17 dot net> ---
Division by 1 and -1 is affected too (as being equivalent to multiplication).

Note that F.9.2 "Expression transformations" in ISO C17 says:

  1 × x and x/1 → x     The expressions 1 × x, x/1, and x are equivalent
                        (on IEC 60559 machines, among others).374)

   374) Strict support for signaling NaNs — not required by this
   specification — would invalidate these and other transformations
   that remove arithmetic operators.

and the current C2x draft (N2596) has something similar. But this is incorrect
as it misses the underflow case with enabled trap (allowed by F.8).

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [Bug middle-end/102126] Wrong optimization of FP multiplication and division by 1 and -1 with -ftrapping-math when an underflow is possible
  2021-08-30  9:11 [Bug middle-end/102126] New: Wrong optimization of multiplication by 1 and -1 with -ftrapping-math when an underflow is possible vincent-gcc at vinc17 dot net
  2021-08-30  9:22 ` [Bug middle-end/102126] Wrong optimization of FP multiplication and division " vincent-gcc at vinc17 dot net
@ 2021-08-30  9:37 ` vincent-gcc at vinc17 dot net
  2021-08-30 11:28 ` rguenth at gcc dot gnu.org
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: vincent-gcc at vinc17 dot net @ 2021-08-30  9:37 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102126

--- Comment #2 from Vincent Lefèvre <vincent-gcc at vinc17 dot net> ---
In the testcase, I forgot

#pragma STDC FP_CONTRACT OFF

Anyway, it is currently ignored by GCC.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [Bug middle-end/102126] Wrong optimization of FP multiplication and division by 1 and -1 with -ftrapping-math when an underflow is possible
  2021-08-30  9:11 [Bug middle-end/102126] New: Wrong optimization of multiplication by 1 and -1 with -ftrapping-math when an underflow is possible vincent-gcc at vinc17 dot net
  2021-08-30  9:22 ` [Bug middle-end/102126] Wrong optimization of FP multiplication and division " vincent-gcc at vinc17 dot net
  2021-08-30  9:37 ` vincent-gcc at vinc17 dot net
@ 2021-08-30 11:28 ` rguenth at gcc dot gnu.org
  2021-08-30 13:17 ` vincent-gcc at vinc17 dot net
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: rguenth at gcc dot gnu.org @ 2021-08-30 11:28 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102126

--- Comment #3 from Richard Biener <rguenth at gcc dot gnu.org> ---
(In reply to Vincent Lefèvre from comment #2)
> In the testcase, I forgot
> 
> #pragma STDC FP_CONTRACT OFF
> 
> Anyway, it is currently ignored by GCC.

You can use -ffp-contract=off but I don't think these transforms are affected.

Note FENV_ACCESS is also ignored but then -ftrapping-math should indeed make
your testcase valid.  Are denormals standardized or left towards the
implementation?  One could argue the underflow exception with * 1 on a denormal
isn't covered?

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [Bug middle-end/102126] Wrong optimization of FP multiplication and division by 1 and -1 with -ftrapping-math when an underflow is possible
  2021-08-30  9:11 [Bug middle-end/102126] New: Wrong optimization of multiplication by 1 and -1 with -ftrapping-math when an underflow is possible vincent-gcc at vinc17 dot net
                   ` (2 preceding siblings ...)
  2021-08-30 11:28 ` rguenth at gcc dot gnu.org
@ 2021-08-30 13:17 ` vincent-gcc at vinc17 dot net
  2021-08-30 19:38 ` joseph at codesourcery dot com
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: vincent-gcc at vinc17 dot net @ 2021-08-30 13:17 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102126

--- Comment #4 from Vincent Lefèvre <vincent-gcc at vinc17 dot net> ---
(In reply to Richard Biener from comment #3)
> You can use -ffp-contract=off but I don't think these transforms are
> affected.

I confirm that the test behaves in the same way with -ffp-contract=off too.
BTW, -ftrapping-math is documented to be the default.

> Note FENV_ACCESS is also ignored but then -ftrapping-math should indeed make
> your testcase valid.  Are denormals standardized or left towards the
> implementation?  One could argue the underflow exception with * 1 on a
> denormal isn't covered?

Subnormals are actually even standardized in the main C specification, but are
required only for float and double if __STDC_IEC_559__ is defined (Annex F):
float and double match IEC 60559 (= IEEE 754) single and double formats
respectively, and all IEEE 754 formats have subnormals.

But what is important here is more the specification of underflow.

In C17, F.10:

  The “underflow” floating-point exception is raised whenever a result is tiny
  (essentially subnormal or zero) and suffers loss of accuracy.377)

  377) IEC 60559 allows different definitions of underflow. They all result in
  the same values, but differ on when the floating-point exception is raised.

However, IMHO, if the processor has some definition of underflow (typically
conforming to the IEEE 754 one), optimization should not yield a different one.

IEEE 754-2019 (which has a simpler definition than 754-1985, by eliminating
choices that have never been used in practice, according to discussions in the
stds-754 list) says: "The underflow exception shall be signaled when a tiny
non-zero result is detected." It still allows differences about tininess
detection (i.e. either after rounding or before rounding, the difference being
for exact values close to the minimum normal number in magnitude), but this
does not matter on my example.

It also says: "In addition, under default exception handling for underflow, if
the rounded result is inexact — that is, it differs from what would have been
computed were both exponent range and precision unbounded — the underflow flag
shall be raised and the inexact (see 7.6) exception shall be signaled. If the
rounded result is exact, no flag is raised and no inexact exception is
signaled. This is the only case in this standard of an exception signal
receiving default handling that does not raise the corresponding flag. Such an
underflow signal has no observable effect under default handling."

When the underflow trap is enabled, this is not the default exception handling
for underflow. Thus, whether the result is exact or not, the exception is
expected to be signaled in the same way, here with a trap.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [Bug middle-end/102126] Wrong optimization of FP multiplication and division by 1 and -1 with -ftrapping-math when an underflow is possible
  2021-08-30  9:11 [Bug middle-end/102126] New: Wrong optimization of multiplication by 1 and -1 with -ftrapping-math when an underflow is possible vincent-gcc at vinc17 dot net
                   ` (3 preceding siblings ...)
  2021-08-30 13:17 ` vincent-gcc at vinc17 dot net
@ 2021-08-30 19:38 ` joseph at codesourcery dot com
  2021-08-30 19:55 ` joseph at codesourcery dot com
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: joseph at codesourcery dot com @ 2021-08-30 19:38 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102126

--- Comment #5 from joseph at codesourcery dot com <joseph at codesourcery dot com> ---
Exception traps (and thus exact underflow) are outside the scope of ISO C.  
(Some forms of alternate exception handling are described in TS 18661-5, 
which is *not* being integrated into C2x, but none of them are like 
feenableexcept; they involve lexically scoped, not dynamically scoped, 
alternate exception handling.)  Note "This specification does not require 
support for trap handlers that maintain information about the order or 
count of floating-point exceptions.", concerning a different case where 
trap handlers could observe transformations that are not otherwise 
visible.

Maybe we should split -ftrapping-math into the on-by-default flag 
concerned with the raising of exception flags, and an off-by-default flag 
concerned with actual changed-flow-of-control traps.  (That's apart from 
the question of splitting -ftrapping-math into the part concerned with 
local transformations keeping the correct set of exception flags raised by 
expressions whose results are used, and the part (largely not implemented, 
but see Marc Glisse's -ffenv-access patches from August 2020) concerned 
with treating flag raising as an actual side effect and preventing code 
movement or removal that would be valid if flag raising weren't handled as 
a side effect.)

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [Bug middle-end/102126] Wrong optimization of FP multiplication and division by 1 and -1 with -ftrapping-math when an underflow is possible
  2021-08-30  9:11 [Bug middle-end/102126] New: Wrong optimization of multiplication by 1 and -1 with -ftrapping-math when an underflow is possible vincent-gcc at vinc17 dot net
                   ` (4 preceding siblings ...)
  2021-08-30 19:38 ` joseph at codesourcery dot com
@ 2021-08-30 19:55 ` joseph at codesourcery dot com
  2021-08-31  0:51 ` vincent-gcc at vinc17 dot net
  2021-08-31 17:58 ` joseph at codesourcery dot com
  7 siblings, 0 replies; 9+ messages in thread
From: joseph at codesourcery dot com @ 2021-08-30 19:55 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102126

--- Comment #6 from joseph at codesourcery dot com <joseph at codesourcery dot com> ---
Issues relating to traps being enabled are still bugs (unlike e.g. any 
issues with changing x87 rounding precision, which are definitely "don't 
do that" when it invalidates assumptions made by the compiler) - e.g. we 
have tests in the testsuite for exact underflow being handled 
appropriately by soft-fp for __float128 - but correct semantics when traps 
are enabled can't usefully be read from ISO C or any part of TS 18661, 
since trap enablement is out of scope there.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [Bug middle-end/102126] Wrong optimization of FP multiplication and division by 1 and -1 with -ftrapping-math when an underflow is possible
  2021-08-30  9:11 [Bug middle-end/102126] New: Wrong optimization of multiplication by 1 and -1 with -ftrapping-math when an underflow is possible vincent-gcc at vinc17 dot net
                   ` (5 preceding siblings ...)
  2021-08-30 19:55 ` joseph at codesourcery dot com
@ 2021-08-31  0:51 ` vincent-gcc at vinc17 dot net
  2021-08-31 17:58 ` joseph at codesourcery dot com
  7 siblings, 0 replies; 9+ messages in thread
From: vincent-gcc at vinc17 dot net @ 2021-08-31  0:51 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102126

--- Comment #7 from Vincent Lefèvre <vincent-gcc at vinc17 dot net> ---
According to the current documentation, -f(no-)trapping-math is only about
traps, not flags.

And Glibc provides functions feenableexcept and fedisableexcept to enable and
disable traps, so that their possible existence needs to be supported.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [Bug middle-end/102126] Wrong optimization of FP multiplication and division by 1 and -1 with -ftrapping-math when an underflow is possible
  2021-08-30  9:11 [Bug middle-end/102126] New: Wrong optimization of multiplication by 1 and -1 with -ftrapping-math when an underflow is possible vincent-gcc at vinc17 dot net
                   ` (6 preceding siblings ...)
  2021-08-31  0:51 ` vincent-gcc at vinc17 dot net
@ 2021-08-31 17:58 ` joseph at codesourcery dot com
  7 siblings, 0 replies; 9+ messages in thread
From: joseph at codesourcery dot com @ 2021-08-31 17:58 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102126

--- Comment #8 from joseph at codesourcery dot com <joseph at codesourcery dot com> ---
I think that documentation should be changed to say it's primarily about 
flags, not traps, with trapping being considered much more of a legacy 
feature rather than something it's normally a good idea to use (although 
the option should generally cover the case of traps as well, while still 
allowing variations in the nonzero number of times an exception is raised 
or the order in which different exceptions are raised).

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2021-08-31 17:58 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-08-30  9:11 [Bug middle-end/102126] New: Wrong optimization of multiplication by 1 and -1 with -ftrapping-math when an underflow is possible vincent-gcc at vinc17 dot net
2021-08-30  9:22 ` [Bug middle-end/102126] Wrong optimization of FP multiplication and division " vincent-gcc at vinc17 dot net
2021-08-30  9:37 ` vincent-gcc at vinc17 dot net
2021-08-30 11:28 ` rguenth at gcc dot gnu.org
2021-08-30 13:17 ` vincent-gcc at vinc17 dot net
2021-08-30 19:38 ` joseph at codesourcery dot com
2021-08-30 19:55 ` joseph at codesourcery dot com
2021-08-31  0:51 ` vincent-gcc at vinc17 dot net
2021-08-31 17:58 ` joseph at codesourcery dot com

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).