The C comparison operators (as opposed to the isgreater, etc. macros) are specified to correspond to the IEEE "unordered-signaling predicates" which raise the INVALID exception on comparisons involving a NaN (quiet or signaling). However, gcc on x86 is generating the FUCOM opcode rather than FCOM, which does not raise any exception unless it encounters a signaling NaN.
Apparently this is a regression since ancient versions of gcc, which correctly generated FCOM.
This bug report is i387-specific; I have no idea if the same issue applies with SSE math or non-x86-family cpu archs.
Please provide a testcase and specify the GCC version you are using.
Works for me with
int foo (double x, double y)
return x < y;
and GCC 4.6.2.
Try foo(NAN,NAN) and then check for the INVALID exception. It's not set.
Compiling with the -mno-ieee-fp option fixes this bug. It seems like the behavior of this option is reversed from the documentation; -mno-ieee-fp gives IEEE conformant comparisons (raising exception on unordered) and -mieee-fp gives non-conformant comparisons (silent on unordered)...
this bug is still present in gcc-4.9 on i386 and x86_64 targets
and possibly others (clang is broken too but that's another story)
the ieee-754 and thus iso c99/c11 + annex f, requires that
==, != are quiet (never raise any exception)
<, >, <=, >= are signaling (raise invalid if an operand is nan)
int f(float x, float y)
return x < y;
int g(float x, float y)
return x == y;
on x87 (i386):
fcom* should be used for f (signaling)
fucom* should be used for g (quiet)
with sse2 (x86_64):
comis* should be used for f (signaling)
ucomis* should be used for g (quiet)
(on arm it is vcmpe.f32 vs vcmp.f32)
it is easy to check that gcc always emits quiet comparisions
and with -mno-ieee-fp it always emits signaling ones
(both of them are wrong)
-O2 -std=c99 on x86_64:
-O2 -std=c99 -mno-ieee-fp on x86_64:
Date: Sun Oct 22 19:04:36 2017
New Revision: 253986
* config/i386/i386.c (ix86_fp_compare_mode): Return CCFPmode
for ordered inequality comparisons even with TARGET_IEEE_FP.
* gcc.dg/torture/pr52451.c: New test.
Fixed on x86.
For reference, the testcase will fail on powerpc (PR 58684) and s390 (PR 77918).
Shouldn't the new test case have been marked XFAIL for powerpc64 and s390? It fails on powerpc64 for sure.
(In reply to seurer from comment #7)
> Shouldn't the new test case have been marked XFAIL for powerpc64 and s390?
> It fails on powerpc64 for sure.
This is up to target maintainer. XFAIL will get the problem off the radar for the next 10 years or so ...
OTOH, the fix should be the same as for x86 - relatively straightforward introduction of CCFPU mode with a helper function that selects between CCFP and CCFPU mode depending on comparison code.