public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
* [Bug c/112449] New: Arithmetic operations can produce signaling NaNs
@ 2023-11-08 21:03 post+gcc at ralfj dot de
  2023-11-08 21:11 ` [Bug c/112449] " pinskia at gcc dot gnu.org
                   ` (12 more replies)
  0 siblings, 13 replies; 14+ messages in thread
From: post+gcc at ralfj dot de @ 2023-11-08 21:03 UTC (permalink / raw)
  To: gcc-bugs

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

            Bug ID: 112449
           Summary: Arithmetic operations can produce signaling NaNs
           Product: gcc
           Version: 13.2.1
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c
          Assignee: unassigned at gcc dot gnu.org
          Reporter: post+gcc at ralfj dot de
  Target Milestone: ---

According to the IEEE 754 specification, the output of an arithmetic operation
can never be a signaling NaN. However, GCC performs optimizations that turn `x
* 1.0` into just `x`, and if `x` is a signaling NaN, that means that the
multiplication will now (seem to) return a signaling NaN. (proof of GCC
performing that transformation: https://godbolt.org/z/scPhn1d8s)

It is very common for C compilers to violate this IEEE 754 requirement, but it
does open the door to a great many questions. Since GCC evidently does not seem
to implement the original IEEE 754 semantics, it would be great to have some
documentation on what exactly GCC *does* implement, and in particular under
which conditions operations are allowed to return a signaling NaN.

So currently, GCC is either buggy because it violates the IEEE 754 spec, or
there's a documentation bug in that the actual floating point spec GCC intends
to implement is not documented. At least, all I was able to find is
https://gcc.gnu.org/wiki/FloatingPointMath, which just says "does not care
about signalling NaNs". (I hope this does not mean that any arithmetic
operation may arbitrarily produce signaling NaNs. That would be an issue for
operations which are sensitive to the difference between quiet NaN and
signaling NaN, such as `pow`.)

As a point of comparison, LLVM recently added this to their documentation to
answer these kinds of questions:
https://llvm.org/docs/LangRef.html#behavior-of-floating-point-nan-values. (That
PR was authored by me but received input from a lot of people.) LLVM goes
further than to just document signaling vs quiet NaN there, since in practice
there's some critical code that would break if arithmetic operations returned
NaNs with arbitrary bits in their payload (specifically, that would break NaN
boxing as performing by some JavaScript engines, or at least make it a lot less
efficient since engines would have to re-normalize NaNs after every single
operation -- which to my knowledge, they don't actually do in practice).

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

* [Bug c/112449] Arithmetic operations can produce signaling NaNs
  2023-11-08 21:03 [Bug c/112449] New: Arithmetic operations can produce signaling NaNs post+gcc at ralfj dot de
@ 2023-11-08 21:11 ` pinskia at gcc dot gnu.org
  2023-11-08 21:18 ` pinskia at gcc dot gnu.org
                   ` (11 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: pinskia at gcc dot gnu.org @ 2023-11-08 21:11 UTC (permalink / raw)
  To: gcc-bugs

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

--- Comment #1 from Andrew Pinski <pinskia at gcc dot gnu.org> ---
See
https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html#index-fsignaling-nans

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

* [Bug c/112449] Arithmetic operations can produce signaling NaNs
  2023-11-08 21:03 [Bug c/112449] New: Arithmetic operations can produce signaling NaNs post+gcc at ralfj dot de
  2023-11-08 21:11 ` [Bug c/112449] " pinskia at gcc dot gnu.org
@ 2023-11-08 21:18 ` pinskia at gcc dot gnu.org
  2023-11-08 21:40 ` pinskia at gcc dot gnu.org
                   ` (10 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: pinskia at gcc dot gnu.org @ 2023-11-08 21:18 UTC (permalink / raw)
  To: gcc-bugs

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

--- Comment #2 from Andrew Pinski <pinskia at gcc dot gnu.org> ---
Note mips and sh and a few other targets have the quiet bit meaning the
opposite.

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

* [Bug c/112449] Arithmetic operations can produce signaling NaNs
  2023-11-08 21:03 [Bug c/112449] New: Arithmetic operations can produce signaling NaNs post+gcc at ralfj dot de
  2023-11-08 21:11 ` [Bug c/112449] " pinskia at gcc dot gnu.org
  2023-11-08 21:18 ` pinskia at gcc dot gnu.org
@ 2023-11-08 21:40 ` pinskia at gcc dot gnu.org
  2023-11-08 21:43 ` pinskia at gcc dot gnu.org
                   ` (9 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: pinskia at gcc dot gnu.org @ 2023-11-08 21:40 UTC (permalink / raw)
  To: gcc-bugs

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

--- Comment #3 from Andrew Pinski <pinskia at gcc dot gnu.org> ---
GCC does document some of this on
https://gcc.gnu.org/onlinedocs/gcc-13.2.0/gcc/Floating-point-implementation.html
but not the signaling nan part.

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

* [Bug c/112449] Arithmetic operations can produce signaling NaNs
  2023-11-08 21:03 [Bug c/112449] New: Arithmetic operations can produce signaling NaNs post+gcc at ralfj dot de
                   ` (2 preceding siblings ...)
  2023-11-08 21:40 ` pinskia at gcc dot gnu.org
@ 2023-11-08 21:43 ` pinskia at gcc dot gnu.org
  2023-11-09  6:40 ` post+gcc at ralfj dot de
                   ` (8 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: pinskia at gcc dot gnu.org @ 2023-11-08 21:43 UTC (permalink / raw)
  To: gcc-bugs

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

--- Comment #4 from Andrew Pinski <pinskia at gcc dot gnu.org> ---
And documented other parts here:
https://gcc.gnu.org/onlinedocs/gcc-13.2.0/cpp/Common-Predefined-Macros.html


specifically:
It does not indicate whether optimizations respect signaling NaN semantics (the
macro for that is __SUPPORT_SNAN__).

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

* [Bug c/112449] Arithmetic operations can produce signaling NaNs
  2023-11-08 21:03 [Bug c/112449] New: Arithmetic operations can produce signaling NaNs post+gcc at ralfj dot de
                   ` (3 preceding siblings ...)
  2023-11-08 21:43 ` pinskia at gcc dot gnu.org
@ 2023-11-09  6:40 ` post+gcc at ralfj dot de
  2023-11-09  6:46 ` post+gcc at ralfj dot de
                   ` (7 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: post+gcc at ralfj dot de @ 2023-11-09  6:40 UTC (permalink / raw)
  To: gcc-bugs

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

--- Comment #5 from post+gcc at ralfj dot de ---
> See https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html#index-fsignaling-nans

That's unrelated. That's about whether operation on signaling NaNs can trap. I
am asking when operations can output a signaling NaN.

So, for code like

float x = y <op> z;
return is_signaling_nan(x);

when can that code return `true`? Normal IEEE semantics would say "never". And
yet if "z" is the constant 1, <op> is `*`, and "y" is a signaling NaN, then
this evidently can output a signaling NaN.

I would hope the answer is "this can output a signaling NaN only if one of the
inputs is a signaling NaN", but is that documented anywhere?

> Note mips and sh and a few other targets have the quiet bit meaning the opposite.

I know. LLVM is currently buggy on those targets.

> GCC does document some of this on https://gcc.gnu.org/onlinedocs/gcc-13.2.0/gcc/Floating-point-implementation.html but not the signaling nan part.

This seems to list a bunch of implementation-defined aspects of C? To my
knowledge, my question is not implementation defined. C (with the annex for
floating-point arithmetic) requires the above operations to always return
"false". GCC violates the C spec here (since it defines __STDC_IEC_559__,
declaring support for the annex), and it'd be good to know how far it is going
in that violation.

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

* [Bug c/112449] Arithmetic operations can produce signaling NaNs
  2023-11-08 21:03 [Bug c/112449] New: Arithmetic operations can produce signaling NaNs post+gcc at ralfj dot de
                   ` (4 preceding siblings ...)
  2023-11-09  6:40 ` post+gcc at ralfj dot de
@ 2023-11-09  6:46 ` post+gcc at ralfj dot de
  2023-11-09  6:56 ` post+gcc at ralfj dot de
                   ` (6 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: post+gcc at ralfj dot de @ 2023-11-09  6:46 UTC (permalink / raw)
  To: gcc-bugs

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

--- Comment #6 from post+gcc at ralfj dot de ---
Hm, OTOH the C standard says

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

So, it seems like when they say "The + ,- , * , and / operators provide the IEC
60559 add, subtract, multiply, and divide operations.", they don't quite mean
that.

This seems internally inconsistent in the C standard, since C also permits
`pow(1, sNaN)` to behave different from `pow(1, qNaN)` -- and in fact they do
behave different in GNU's libm. So on the one hand `pow(1, x * y)` must always
be `1` but on the other hand it can return a NaN when `x` is an sNaN and `y` is
`1`?

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

* [Bug c/112449] Arithmetic operations can produce signaling NaNs
  2023-11-08 21:03 [Bug c/112449] New: Arithmetic operations can produce signaling NaNs post+gcc at ralfj dot de
                   ` (5 preceding siblings ...)
  2023-11-09  6:46 ` post+gcc at ralfj dot de
@ 2023-11-09  6:56 ` post+gcc at ralfj dot de
  2023-11-09  7:57 ` rguenth at gcc dot gnu.org
                   ` (5 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: post+gcc at ralfj dot de @ 2023-11-09  6:56 UTC (permalink / raw)
  To: gcc-bugs

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

--- Comment #7 from post+gcc at ralfj dot de ---
I guess the idea is that by passing a signaling NaN to a float operation, I am
already entering unspecified behavior, so it's okay for that float operation to
violate its usual contract and return a signaling NaN?

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

* [Bug c/112449] Arithmetic operations can produce signaling NaNs
  2023-11-08 21:03 [Bug c/112449] New: Arithmetic operations can produce signaling NaNs post+gcc at ralfj dot de
                   ` (6 preceding siblings ...)
  2023-11-09  6:56 ` post+gcc at ralfj dot de
@ 2023-11-09  7:57 ` rguenth at gcc dot gnu.org
  2023-11-09 17:53 ` joseph at codesourcery dot com
                   ` (4 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: rguenth at gcc dot gnu.org @ 2023-11-09  7:57 UTC (permalink / raw)
  To: gcc-bugs

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

Richard Biener <rguenth at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |jsm28 at gcc dot gnu.org,
                   |                            |rguenth at gcc dot gnu.org

--- Comment #8 from Richard Biener <rguenth at gcc dot gnu.org> ---
I think if you can reproduce the issue with -fsignaling-nans (which defaults to
off) then I would consider this to be an implementation issue.  The GCC
middle-end shouldn't clang to contradicting wording in the C standard here.

In particular we say

@opindex fsignaling-nans
@item -fsignaling-nans
Compile code assuming that IEEE signaling NaNs may generate user-visible
traps during floating-point operations.  Setting this option disables
optimizations that may change the number of exceptions visible with
signaling NaNs.  This option implies @option{-ftrapping-math}.

Changing tem = x * 1.0 to tem = x would possibly change the number of observed
traps if tem is used more than once.

OTOH below we also say

This option is experimental and does not currently guarantee to
disable all GCC optimizations that affect signaling NaN behavior.

so bugs in this area are expected (but they are still bugs IMHO).

CCing Joseph for clarification.

Note a quick check with

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

and -O2 -fsignaling-nans shows the multiplication is preserved (on x86_64),
so is your example in godbolt where you fail to specify -fsignaling-nans.

I agree the documentation is maybe not entirely clear about the effect.

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

* [Bug c/112449] Arithmetic operations can produce signaling NaNs
  2023-11-08 21:03 [Bug c/112449] New: Arithmetic operations can produce signaling NaNs post+gcc at ralfj dot de
                   ` (7 preceding siblings ...)
  2023-11-09  7:57 ` rguenth at gcc dot gnu.org
@ 2023-11-09 17:53 ` joseph at codesourcery dot com
  2023-11-09 20:33 ` post+gcc at ralfj dot de
                   ` (3 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: joseph at codesourcery dot com @ 2023-11-09 17:53 UTC (permalink / raw)
  To: gcc-bugs

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

--- Comment #9 from joseph at codesourcery dot com <joseph at codesourcery dot com> ---
To quote the C23 DIS, "This annex does not require the full support for 
signaling NaNs specified in IEC 60559. This annex uses the term NaN, 
unless explicitly qualified, to denote quiet NaNs.".

Support for signaling NaNs is indicated by FE_SNANS_ALWAYS_SIGNAL in 
<fenv.h>, which glibc makes sure to define only if __SUPPORT_SNAN__ (which 
is defined by GCC if -fsignaling-nans).

If -fsignaling-nans is not used, you should not expect consistency in 
whether a signaling NaN is handled differently from a quiet NaN (including 
whether optimizations might be applied that result in a signaling NaN 
result from an operation that can't produce such a result with IEEE 
signaling NaN semantics).

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

* [Bug c/112449] Arithmetic operations can produce signaling NaNs
  2023-11-08 21:03 [Bug c/112449] New: Arithmetic operations can produce signaling NaNs post+gcc at ralfj dot de
                   ` (8 preceding siblings ...)
  2023-11-09 17:53 ` joseph at codesourcery dot com
@ 2023-11-09 20:33 ` post+gcc at ralfj dot de
  2023-11-10  8:15 ` rguenth at gcc dot gnu.org
                   ` (2 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: post+gcc at ralfj dot de @ 2023-11-09 20:33 UTC (permalink / raw)
  To: gcc-bugs

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

--- Comment #10 from post+gcc at ralfj dot de ---
The standard says

> This annex does not require the full support for signaling NaNs specified in IEC 60559. This
annex uses the term NaN, unless explicitly qualified, to denote quiet NaNs.
Where specification of
signaling NaNs is not provided, the behavior of signaling NaNs is
implementation-defined (either
treated as an IEC 60559 quiet NaN or treated as an IEC 60559 signaling NaN).

I have no idea how that allows a situation where the *output* of an operation
becomes signaling -- that can't usually happen no matter whether the inputs are
signaling or quiet.

But that seems to be the common interpretation.

Still, it seems important that `pow(1.0, 0.0/0.0)` returns `1.0` and not a NaN.
That's what the `pow` docs say. So for this there must be a guarantee that
`0.0/0.0` is a quiet NaN.

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

* [Bug c/112449] Arithmetic operations can produce signaling NaNs
  2023-11-08 21:03 [Bug c/112449] New: Arithmetic operations can produce signaling NaNs post+gcc at ralfj dot de
                   ` (9 preceding siblings ...)
  2023-11-09 20:33 ` post+gcc at ralfj dot de
@ 2023-11-10  8:15 ` rguenth at gcc dot gnu.org
  2023-11-10 10:27 ` post+gcc at ralfj dot de
  2023-11-13 22:46 ` joseph at codesourcery dot com
  12 siblings, 0 replies; 14+ messages in thread
From: rguenth at gcc dot gnu.org @ 2023-11-10  8:15 UTC (permalink / raw)
  To: gcc-bugs

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

--- Comment #11 from Richard Biener <rguenth at gcc dot gnu.org> ---
(In reply to post+gcc from comment #10)
> The standard says
> 
> > This annex does not require the full support for signaling NaNs specified in IEC 60559. This
> annex uses the term NaN, unless explicitly qualified, to denote quiet NaNs.
> Where specification of
> signaling NaNs is not provided, the behavior of signaling NaNs is
> implementation-defined (either
> treated as an IEC 60559 quiet NaN or treated as an IEC 60559 signaling NaN).

I don't see implement-c.texi saying anything about this.  Joseph, can you
improve documentation here?

> I have no idea how that allows a situation where the *output* of an
> operation becomes signaling -- that can't usually happen no matter whether
> the inputs are signaling or quiet.
> 
> But that seems to be the common interpretation.
> 
> Still, it seems important that `pow(1.0, 0.0/0.0)` returns `1.0` and not a
> NaN. That's what the `pow` docs say. So for this there must be a guarantee
> that `0.0/0.0` is a quiet NaN.

GCC will not create an sNaN out of nowhere.  But unless you enable
-fsignaling-nans it is unspecified whether and when an sNaN will become
a quiet NaN as GCC - as you observed - will happily elide x * 1.0 even
when 'x' might be a sNaN (basically with -fno-signaling-nans GCC assumes that
inputs are _never_ sNaN).

The -fsignaling-nans might also need clarification to make it more obvious
what omitting it means.

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

* [Bug c/112449] Arithmetic operations can produce signaling NaNs
  2023-11-08 21:03 [Bug c/112449] New: Arithmetic operations can produce signaling NaNs post+gcc at ralfj dot de
                   ` (10 preceding siblings ...)
  2023-11-10  8:15 ` rguenth at gcc dot gnu.org
@ 2023-11-10 10:27 ` post+gcc at ralfj dot de
  2023-11-13 22:46 ` joseph at codesourcery dot com
  12 siblings, 0 replies; 14+ messages in thread
From: post+gcc at ralfj dot de @ 2023-11-10 10:27 UTC (permalink / raw)
  To: gcc-bugs

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

--- Comment #12 from post+gcc at ralfj dot de ---
> GCC will not create an sNaN out of nowhere.

That's the part I was hoping for. :)  I just don't think it obviously follows
from any docs (the C standard or GCC docs).

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

* [Bug c/112449] Arithmetic operations can produce signaling NaNs
  2023-11-08 21:03 [Bug c/112449] New: Arithmetic operations can produce signaling NaNs post+gcc at ralfj dot de
                   ` (11 preceding siblings ...)
  2023-11-10 10:27 ` post+gcc at ralfj dot de
@ 2023-11-13 22:46 ` joseph at codesourcery dot com
  12 siblings, 0 replies; 14+ messages in thread
From: joseph at codesourcery dot com @ 2023-11-13 22:46 UTC (permalink / raw)
  To: gcc-bugs

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

--- Comment #13 from joseph at codesourcery dot com <joseph at codesourcery dot com> ---
On Fri, 10 Nov 2023, rguenth at gcc dot gnu.org via Gcc-bugs wrote:

> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=112449
> 
> --- Comment #11 from Richard Biener <rguenth at gcc dot gnu.org> ---
> (In reply to post+gcc from comment #10)
> > The standard says
> > 
> > > This annex does not require the full support for signaling NaNs specified in IEC 60559. This
> > annex uses the term NaN, unless explicitly qualified, to denote quiet NaNs.
> > Where specification of
> > signaling NaNs is not provided, the behavior of signaling NaNs is
> > implementation-defined (either
> > treated as an IEC 60559 quiet NaN or treated as an IEC 60559 signaling NaN).
> 
> I don't see implement-c.texi saying anything about this.  Joseph, can you
> improve documentation here?

Updating implement-c.texi for C23 is on my list for after C23 is out and 
so we have final subclause references (but the list of 
implementation-defined behavior in J.3 doesn't seem to have that point 
from Annex F at present).

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

end of thread, other threads:[~2023-11-13 22:46 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-11-08 21:03 [Bug c/112449] New: Arithmetic operations can produce signaling NaNs post+gcc at ralfj dot de
2023-11-08 21:11 ` [Bug c/112449] " pinskia at gcc dot gnu.org
2023-11-08 21:18 ` pinskia at gcc dot gnu.org
2023-11-08 21:40 ` pinskia at gcc dot gnu.org
2023-11-08 21:43 ` pinskia at gcc dot gnu.org
2023-11-09  6:40 ` post+gcc at ralfj dot de
2023-11-09  6:46 ` post+gcc at ralfj dot de
2023-11-09  6:56 ` post+gcc at ralfj dot de
2023-11-09  7:57 ` rguenth at gcc dot gnu.org
2023-11-09 17:53 ` joseph at codesourcery dot com
2023-11-09 20:33 ` post+gcc at ralfj dot de
2023-11-10  8:15 ` rguenth at gcc dot gnu.org
2023-11-10 10:27 ` post+gcc at ralfj dot de
2023-11-13 22:46 ` 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).