Bug 104865 - Wrong code for conditional expression on VAX or with -ffast-math
Summary: Wrong code for conditional expression on VAX or with -ffast-math
Status: NEW
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 12.0
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: wrong-code
Depends on:
Blocks:
 
Reported: 2022-03-10 14:11 UTC by Jonathan Wakely
Modified: 2022-04-02 16:37 UTC (History)
3 users (show)

See Also:
Host:
Target: vax-dec-netbsdelf
Build:
Known to work:
Known to fail:
Last reconfirmed: 2022-03-10 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Jonathan Wakely 2022-03-10 14:11:34 UTC
This fails the second static assert on vax-dec-netbsdelf:


template<typename T>
constexpr int
cmp1(T x) noexcept
{
    int ix = (bool) __builtin_isnan(x);
    return ix;
}

template<typename T>
constexpr int
cmp2(T x) noexcept
{
    int ix = __builtin_isnan(x) ? 1 : 0;
    return ix;
}   
   
constexpr double nan = __builtin_nan("");

static_assert( cmp1(nan) ); 
static_assert( cmp2(nan) ); 

extern const auto c1 = cmp1(nan);
extern const auto c2 = cmp2(nan);     


$ gcc/cc1plus  -quiet ~/tmp/ord.C
/home/jwakely/tmp/ord.C:20:20: error: static assertion failed
   20 | static_assert( cmp2(nan) );
      |                ~~~~^~~~~





If the failing static assert is commented out, the assembly code is:

#NO_APP
        .file   "ord.C"
        .text
        .section        .rodata
        .align 2
        .type   _ZL3nan, @object
        .size   _ZL3nan, 8
_ZL3nan:
        .long   -32769
        .long   -1
.globl c1
        .align 2
        .type   c1, @object
        .size   c1, 4
c1:
        .long   1
.globl c2
        .align 2
        .type   c2, @object
        .size   c2, 4
c2:
        .zero   4
        .ident  "GCC: (GNU) 12.0.1 20220308 (experimental)"




For some reason the cmp2 function returns zero.



I'm using binutils configured with --target=vax-dec-netbsdelf and gcc configured with:

/home/jwakely/src/gcc/configure --target vax-dec-netbsdelf --without-headers --with-newlib --disable-bootstrap --disable-nls --without-lto --without-isl --disable-libcc1 --disable-libsanitizer --disable-libitm --disable-libvtv --disable-libgomp --disable-libssp --enable-languages=c++,c --disable-libstdcxx-pch --disable-hosted-libstdcxx --prefix=/home/jwakely/gcc/vax

I only did 'make all-gcc' and am running cc1plus from the build tree, as I don't have a sysroot for the target.
Comment 1 Marek Polacek 2022-03-10 15:13:57 UTC
Confirmed with --target vax-dec-netbsdelf:

$ ./cc1plus -quiet 104865.C
104865.C:20:20: error: static assertion failed
   20 | static_assert( cmp2(nan) );
      |                ~~~~^~~~~
Comment 2 Andrew Pinski 2022-03-11 00:48:02 UTC
/* Accessor macros for format properties.  */
#define MODE_HAS_NANS(MODE) \
  (FLOAT_MODE_P (MODE) && FLOAT_MODE_FORMAT (MODE)->has_nans)

.....
vax_f_format
...
false,

Hmm,
 -ffast-math has the same result (that is the assert happening) on any other target really.
Comment 3 Maciej W. Rozycki 2022-04-02 13:57:31 UTC
Should `__builtin_nan' even compile on non-IEEE-754 FP targets?
Comment 4 Jonathan Wakely 2022-04-02 14:51:48 UTC
They can still have NaNs.
Comment 5 Maciej W. Rozycki 2022-04-02 16:00:50 UTC
Wrong question then.  Should `__builtin_nan' even compile on non-IEEE-754
FP targets that don't have a qNaN?  And I'll reply to myself.

According to our manual:

"-- Built-in Function: double __builtin_nan (const char *str)
     This is an implementation of the ISO C99 function 'nan'."

and then according to ISO C99:

"The nan functions return a quiet NaN, if available, with content
indicated through tagp.  If the implementation does not support quiet
NaNs, the functions return zero."

so firstly __builtin_isnan(__builtin_nan("")) is supposed to return 0
with the VAX target (because obviously 0.0 is not a NaN), and secondly
the compiled program is wrong as `_ZL3nan' is supposed to be set to
all-zeros (which is the representation of 0.0 datum with the VAX
floating-point format), and then `c1' and `c2' must likewise be both 0.

Both asserts are supposed to fail with the VAX target then (and similarly
PDP-11, which has a similar FP format).
Comment 6 Jonathan Wakely 2022-04-02 16:07:54 UTC
OK, maybe I should not have used __builtin_nan in the test. The bug is in the rest of the code though, isn't it? Replace the __builtin_nan with a function returning the same sNaN, does the test still fail? (I can't check myself right now).
Comment 7 Maciej W. Rozycki 2022-04-02 16:37:51 UTC
Well, it's not clear to me whether the reserved operand as defined by the
VAX floating-point architecture ought be considered an sNaN given that
there is no qNaN.

Also a reserved operand causes a fault with any FP instruction, even data
moves (though one can move a reserved operand bit pattern with an integer
move of the right width, observing that there is a single register file
for both integer and FP arithmetic, and that of course FP operations can
be directly performed on memory as well).

In any case there's probably more than one bug here.