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: 2017-10-23 19:09 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.