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.
Test fails on hppa*-*-hpux*.
Please file a separate bug for hppa, just as we have separate bugs for the
powerpc and s390 back end issues. Assuming hppa-hpux has working fenv.h,
failure on hppa is probably a back-end issue.
ARC gcc backend suffers from this and I've created https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92845 and also a tentative fix which passes gcc.dg/torture/pr52451.c
However I'm curious that the test uses qNaN. What is the expected behavior for sNaN. If you tweak the testcase slightly as follows:
diff --git a/gcc/testsuite/gcc.dg/torture/pr52451.c b/gcc/testsuite/gcc.dg/torture/pr52451.c
- volatile TYPE nan##S = __builtin_nan##S (""); \
+ volatile TYPE nan##S = __builtin_nans##S (""); \
With that even on ARM (RPI3) it now fails for the "quite" C operations "==" and "!=" and isless(),isgreater(),islessequal(),isgreaterequal().
Is that expected, OK ? I guess there's no easy to fix this unless hardware supports the 3 varaints or glibc code has a way to clear exception in certain cases.
oops the ARC bug is (PR 92846) not (PR 92845)
On Fri, 6 Dec 2019, vgupta at synopsys dot com wrote:
> However I'm curious that the test uses qNaN. What is the expected behavior for
> sNaN. If you tweak the testcase slightly as follows:
All the comparison operations raise exceptions for sNaN. See IEEE 754.
"Invalid operation is the only exception that a comparison predicate can
signal. All predicates signal the invalid operation exception on signaling
NaN operands. The predicates named Quiet shall not signal any exception,
unless an operand is a signaling NaN. The predicates named Signaling shall
signal the invalid operation exception on quiet NaN operands.".