Bug 52451 - gcc w/i387 float generates fucom rather than fcom for floating point comparsons
Summary: gcc w/i387 float generates fucom rather than fcom for floating point comparsons
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: target (show other bugs)
Version: unknown
: P3 normal
Target Milestone: 8.0
Assignee: Uroš Bizjak
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2012-03-01 15:25 UTC by Rich Felker
Modified: 2019-12-09 22:08 UTC (History)
2 users (show)

See Also:
Host:
Target: x86
Build:
Known to work:
Known to fail:
Last reconfirmed: 2012-03-01 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Rich Felker 2012-03-01 15:25:49 UTC
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.
Comment 1 Richard Biener 2012-03-01 15:55:37 UTC
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.
Comment 2 Rich Felker 2012-03-15 16:23:11 UTC
Try foo(NAN,NAN) and then check for the INVALID exception. It's not set.
Comment 3 Rich Felker 2012-04-23 09:37:45 UTC
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)...
Comment 4 Szabolcs Nagy 2014-09-11 16:11:20 UTC
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)

eg. with

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:

	http://goo.gl/awmRGP

-O2 -std=c99 -mno-ieee-fp on x86_64:

	http://goo.gl/9CHNjK
Comment 5 uros 2017-10-22 19:05:07 UTC
Author: uros
Date: Sun Oct 22 19:04:36 2017
New Revision: 253986

URL: https://gcc.gnu.org/viewcvs?rev=253986&root=gcc&view=rev
Log:
	PR target/52451
	* config/i386/i386.c (ix86_fp_compare_mode): Return CCFPmode
	for ordered inequality comparisons even with TARGET_IEEE_FP.

testsuite/ChangeLog:

	PR target/52451
	* gcc.dg/torture/pr52451.c: New test.


Added:
    trunk/gcc/testsuite/gcc.dg/torture/pr52451.c
Modified:
    trunk/gcc/ChangeLog
    trunk/gcc/config/i386/i386.c
    trunk/gcc/testsuite/ChangeLog
Comment 6 Uroš Bizjak 2017-10-22 19:07:07 UTC
Fixed on x86.

For reference, the testcase will fail on powerpc (PR 58684) and s390 (PR 77918).
Comment 7 seurer 2017-10-23 18:52:46 UTC
Shouldn't the new test case have been marked XFAIL for powerpc64 and s390?  It fails on powerpc64 for sure.
Comment 8 Uroš Bizjak 2017-10-23 19:09:42 UTC
(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.
Comment 9 John David Anglin 2017-12-17 22:13:01 UTC
Test fails on hppa*-*-hpux*.
Comment 10 jsm-csl@polyomino.org.uk 2017-12-19 00:03:17 UTC
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.
Comment 11 Vineet Gupta 2019-12-06 17:45:02 UTC
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.
Comment 12 Vineet Gupta 2019-12-06 17:47:07 UTC
oops the ARC bug is (PR 92846) not (PR 92845)
Comment 13 jsm-csl@polyomino.org.uk 2019-12-09 22:08:51 UTC
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.".