public inbox for gcc@gcc.gnu.org
 help / color / mirror / Atom feed
* Weird behaviour (bug?) of __builtin_nans()
@ 2021-12-31 16:13 FX
  2021-12-31 17:05 ` Joseph Myers
  0 siblings, 1 reply; 3+ messages in thread
From: FX @ 2021-12-31 16:13 UTC (permalink / raw)
  To: GCC Mailing List; +Cc: Joseph Myers

Hi,

I think I’ve found a bug in the handling of __builtin_nans() in GCC, but I am aware that this is a tricky area, so before claiming so I would like to check with the experts. Consider the following code:

$ cat v.c 
#include <stdint.h>
#include <stdio.h>

#if 1
typedef double GFC_REAL_8;
#else
#define GFC_REAL_8 double
#endif

GFC_REAL_8 foo (void)
{
  return __builtin_nans("");
}

int main (void) {
  double x;

  x = __builtin_nans ("");
  printf("==> %lX\n", *(uint64_t *) &x);
  x = foo ();
  printf("==> %lX\n", *(uint64_t *) &x);
}
$ gcc v.c -W -Wall && ./a.out
==> 7FF4000000000000
==> 7FF8000000000000


My expectation is: the x variable should be assigned a signalling NaN, both times, and therefore the code should output the same value twice. But as you can see, the second time the NaN is converted to quiet.

What is even more troubling: this behavior only happens if GFC_REAL_8 is typedef’ed to double. If we use the double type directly (change #if 1 to #if 0) then the output is as expected:

==> 7FF4000000000000
==> 7FF4000000000000


What is even more worrying is that, if you keep the typedef, but change the function to go through a variable, then the signalling nan is returned correctly:

typedef double GFC_REAL_8;
GFC_REAL_8 foo (void)
{
  GFC_REAL_8 x = __builtin_nans("");
  return x;
}


---------

The reason I ended up in this rabbit hole is that I am implementing some handling of signalling NaNs in libgfortran. Could someone either confirm that the behavior observed above is a bug, or if not, kindly explain to me why it happens?


Thanks,
FX

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

* Re: Weird behaviour (bug?) of __builtin_nans()
  2021-12-31 16:13 Weird behaviour (bug?) of __builtin_nans() FX
@ 2021-12-31 17:05 ` Joseph Myers
  2021-12-31 19:14   ` FX
  0 siblings, 1 reply; 3+ messages in thread
From: Joseph Myers @ 2021-12-31 17:05 UTC (permalink / raw)
  To: FX; +Cc: GCC Mailing List

On Fri, 31 Dec 2021, FX via Gcc wrote:

> The reason I ended up in this rabbit hole is that I am implementing some 
> handling of signalling NaNs in libgfortran. Could someone either confirm 
> that the behavior observed above is a bug, or if not, kindly explain to 
> me why it happens?

1. You should use -fsignaling-nans if you want signaling NaNs to work 
correctly.

2. I suspect this has the same, or similar, underlying cause to bug 86367 
(whatever that cause is): something is interpreting conversions between 
types with the same floating-point format (in this case, the same type but 
using a typedef name on one side of the conversion) as being a 
convertFormat operation - but apparently only without -fsignaling-nans.

3. There is probably a reasonable case for interpreting such conversions 
(including casts) as copy operations instead, including in the absence of 
-fsignaling-nans; C23 Annex F leaves that implementation-defined, and 
handling such conversions as copy operations is likely to be more 
predictable and more useful.

4. Note however that in some cases the ABI may mean the conversion has to 
be treated as convertFormat (returning float or double on 32-bit x86, in 
particular, because that return uses an x87 register).

5. In other cases on 32-bit x86, the failure of GCC to model excess 
precision explicitly by default (instead pretending the machine has SFmode 
and DFmode loads and stores) makes it hard to avoid spurious conversions 
(even in some cases where there is no floating-point operation or 
lvalue-to-rvalue conversion at all in the abstract machine and so 
-fsignaling-nans shouldn't be needed at all, see bugs 58416, 71460, 
93934).

-- 
Joseph S. Myers
joseph@codesourcery.com

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

* Re: Weird behaviour (bug?) of __builtin_nans()
  2021-12-31 17:05 ` Joseph Myers
@ 2021-12-31 19:14   ` FX
  0 siblings, 0 replies; 3+ messages in thread
From: FX @ 2021-12-31 19:14 UTC (permalink / raw)
  To: Joseph Myers; +Cc: GCC Mailing List

Hi Joseph,

> 1. You should use -fsignaling-nans if you want signaling NaNs to work 
> correctly.

Thanks, we’ll compile the libgfortran parts that are IEEE-related with that from now on. Sounds like a good idea, anyway.


> 3. There is probably a reasonable case for interpreting such conversions 
> (including casts) as copy operations instead, including in the absence of 
> -fsignaling-nans; C23 Annex F leaves that implementation-defined, and 
> handling such conversions as copy operations is likely to be more 
> predictable and more useful.

I agree that while there may be no guarantee, it sounds like a reasonable expectation in the case I posted. I’ve filed a PR: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=103883


Thanks,
FX

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

end of thread, other threads:[~2021-12-31 19:14 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-12-31 16:13 Weird behaviour (bug?) of __builtin_nans() FX
2021-12-31 17:05 ` Joseph Myers
2021-12-31 19:14   ` FX

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).