aarch64: Don't raise FE_INVALID for -__builtin_isgreater [PR93133]
authorRichard Sandiford <richard.sandiford@arm.com>
Thu, 16 Jan 2020 19:22:20 +0000 (19:22 +0000)
committerRichard Sandiford <richard.sandiford@arm.com>
Fri, 17 Jan 2020 12:17:11 +0000 (12:17 +0000)
commit865257c447cc50f5819e9b53da83145f3c36c305
tree6be457f73f1b89446cdc3e933c7073391d95a2f2
parent507de5ee23efdc8a16d6b0b6488e118055c711cd
aarch64: Don't raise FE_INVALID for -__builtin_isgreater [PR93133]

AIUI, the main purpose of REVERSE_CONDITION is to take advantage of
any integer vs. FP information encoded in the CC mode, particularly
when handling LT, LE, GE and GT.  For integer comparisons we can
safely map LT->GE, LE->GT, GE->LT and GT->LE, but for float comparisons
this would usually be invalid without -ffinite-math-only.

The aarch64 definition of REVERSE_CONDITION used
reverse_condition_maybe_unordered for FP comparisons, which had the
effect of converting an unordered-signalling LT, LE, GE or GT into a
quiet UNGE, UNGT, UNLT or UNLE.  And it would do the same in reverse:
convert a quiet UN* into an unordered-signalling comparison.

This would be safe in practice (although a little misleading) if we
always used a compare:CCFP or compare:CCFPE to do the comparison and
then used (gt (reg:CCFP/CCFPE CC_REGNUM) (const_int 0)) etc. to test
the result.  In that case any signal is raised by the compare and the
choice of quiet vs. signalling relations doesn't matter when testing
the result.  The problem is that we also want to use GT directly on
float registers, where any signal is raised by the comparison operation
itself and so must follow the normal rtl rules (GT signalling,
UNLE quiet).

I think the safest fix is to make REVERSIBLE_CC_MODE return false
for FP comparisons.  We can then use the default REVERSE_CONDITION
for integer comparisons and the usual conservatively-correct
reversed_comparison_code_parts behaviour for FP comparisons.
Unfortunately reversed_comparison_code_parts doesn't yet handle
-ffinite-math-only, but that's probably GCC 11 material.

A downside is that:

    int f (float x, float y) { return !(x < y); }

now generates:

        fcmpe   s0, s1
        cset    w0, mi
        eor     w0, w0, 1
        ret

without -ffinite-math-only.  Maybe for GCC 11 we should define rtx
codes for all IEEE comparisons, so that we don't have this kind of
representational gap.

Changing REVERSE_CONDITION itself is pretty easy.  However, the macro
was also used in the ccmp handling, which relied on being able to
reverse all comparisons.  The patch adds new reversed patterns for
cases in which the original condition needs to be kept.

The test is based on gcc.dg/torture/pr91323.c.  It might well fail
on other targets that have similar bugs; please XFAIL as appropriate
if you don't want to fix the target for GCC 10.

2020-01-17  Richard Sandiford  <richard.sandiford@arm.com>

gcc/
* config/aarch64/aarch64.h (REVERSIBLE_CC_MODE): Return false
for FP modes.
(REVERSE_CONDITION): Delete.
* config/aarch64/iterators.md (CC_ONLY): New mode iterator.
(CCFP_CCFPE): Likewise.
(e): New mode attribute.
* config/aarch64/aarch64.md (ccmp<GPI:mode>): Rename to...
(@ccmp<CC_ONLY:mode><GPI:mode>): ...this, using CC_ONLY instead of CC.
(fccmp<GPF:mode>, fccmpe<GPF:mode>): Merge into...
(@ccmp<CCFP_CCFPE:mode><GPF:mode>): ...this combined pattern.
(@ccmp<CC_ONLY:mode><GPI:mode>_rev): New pattern.
(@ccmp<CCFP_CCFPE:mode><GPF:mode>_rev): Likewise.
* config/aarch64/aarch64.c (aarch64_gen_compare_reg): Update
name of generator from gen_ccmpdi to gen_ccmpccdi.
(aarch64_gen_ccmp_next): Use code_for_ccmp.  If we want to reverse
the previous comparison but aren't able to, use the new ccmp_rev
patterns instead.
gcc/ChangeLog
gcc/config/aarch64/aarch64.c
gcc/config/aarch64/aarch64.h
gcc/config/aarch64/aarch64.md
gcc/config/aarch64/iterators.md
gcc/testsuite/gcc.dg/torture/pr93133.c [new file with mode: 0644]