> On 26 Aug 2026, at 07:16, Andrea Pinski <[email protected]> 
> wrote:
> 
> On Tue, Aug 11, 2026 at 11:33 PM <[email protected]> wrote:
>> 
>> From: Kyrylo Tkachov <[email protected]>
>> 
>> This is a rework of previously-approved 
>> https://gcc.gnu.org/pipermail/gcc-patches/2026-August/727208.html
>> with the FP CCmode logic factored into a helper to make it reusable in patch 
>> 3.
>> 
>> FCMP and FCMPE set NZCV identically.  FCMPE also raises Invalid for a quiet
>> NaN.  When NaNs are not honoured, or floating-point operations cannot trap,
>> this exception difference is not observable.
>> 
>> For example, with -O2 -ffinite-math-only:
>> 
>>  int
>>  f (double a, double b)
>>  {
>>    return (a < b) + (a == b);
>>  }
>> 
>> The ordered and equality comparisons used different condition modes, so
>> AArch64 emitted two comparisons:
>> 
>>        fcmpe   d0, d1
>>        cset    w0, mi
>>        fcmp    d0, d1
>>        cinc    w0, w0, eq
>> 
>> After this patch both operations use one comparison:
>> 
>>        fcmp    d0, d1
>>        cset    w0, eq
>>        cinc    w0, w0, mi
>> 
>> Use CCFPmode for ordered comparisons too when the exception is not 
>> observable.
>> Keep CCFPEmode when both NaNs and trapping operations are honoured.  Move the
>> rule into a helper that takes the comparison code and the operand mode, so
>> that a caller which has no operand rtx can use it.
>> 
>> Also anchor the existing FP assembly scans.  The old expressions could cross
>> line boundaries and incorrectly implied that FCCMP accepts a zero operand.
>> 
>> The tests cover finite-math and non-trapping instruction selection, 
>> comparison
>> reuse, and the default trapping behaviour.
>> 
>> gcc/
>> 
>>        * config/aarch64/aarch64.cc (aarch64_fp_cc_mode): New function.
>>        Use CCFPmode when the FCMPE exception is not observable.
>>        (aarch64_select_cc_mode): Use it.
>> 
>> gcc/testsuite/
>> 
>>        * gcc.target/aarch64/ccmp_1.c: Update and anchor the FP scans.
>>        * gcc.target/aarch64/fccmp_1.c: Update the expected mode.
>>        * gcc.target/aarch64/fccmp_3.c: New test.
>> 
>> Signed-off-by: Kyrylo Tkachov <[email protected]>
>> ---
>> gcc/config/aarch64/aarch64.cc              | 60 ++++++++++++----------
>> gcc/testsuite/gcc.target/aarch64/ccmp_1.c  | 10 ++--
>> gcc/testsuite/gcc.target/aarch64/fccmp_1.c |  8 +--
>> gcc/testsuite/gcc.target/aarch64/fccmp_3.c | 18 +++++++
>> 4 files changed, 61 insertions(+), 35 deletions(-)
>> create mode 100644 gcc/testsuite/gcc.target/aarch64/fccmp_3.c
>> 
>> diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
>> index 8e1eb2d7e33..0b73146b620 100644
>> --- a/gcc/config/aarch64/aarch64.cc
>> +++ b/gcc/config/aarch64/aarch64.cc
>> @@ -12674,40 +12674,46 @@ aarch64_emit_call_insn (rtx pat)
>>   return as_a<rtx_call_insn *> (insn);
>> }
>> 
>> +/* Return the condition code mode for comparison CODE of MODE floating-point
>> +   operands.  FCMP and FCMPE set the same flags, but FCMPE also raises 
>> Invalid
>> +   for a quiet NaN.  Use CCFPE only when that exception is observable.  */
>> +
>> +static machine_mode
>> +aarch64_fp_cc_mode (rtx_code code, machine_mode mode)
>> +{
>> +  switch (code)
>> +    {
>> +    case EQ:
>> +    case NE:
>> +    case UNORDERED:
>> +    case ORDERED:
>> +    case UNLT:
>> +    case UNLE:
>> +    case UNGT:
>> +    case UNGE:
>> +    case UNEQ:
>> +      return CCFPmode;
>> +
>> +    case LT:
>> +    case LE:
>> +    case GT:
>> +    case GE:
>> +    case LTGT:
>> +      return HONOR_NANS (mode) && flag_trapping_math ? CCFPEmode : CCFPmode;
> 
> I think this should be written as the following:
> if (!HONOR_NANS (mode) || !flag_trapping_math)
>  return CCFPmode;
> switch (code)
> ....
> 
> Just so it is easier to understand that for non trapping everything
> just uses CCFPmode and only trapping math we use CCFPEmode.
> 

Thanks, something like the attached?

> Now the question becomes for snans what should be done? Should
> CCFPEmode be used always then? Or something more complex? For now I
> think we can ignore that case but I suspect we might need to come up
> with a solution.

FCMP already raises Invalid for an sNaN, so sNaNs do not require CCFPE for 
every comparison. FCMPE differs by also raising Invalid for a qNaN.
But yeah, we’ll need to look into that separately.
Thanks,
Kyrill

> 
>> +
>> +    default:
>> +      gcc_unreachable ();
>> +    }
>> +}
>> +
>> machine_mode
>> aarch64_select_cc_mode (RTX_CODE code, rtx x, rtx y)
>> {
>>   machine_mode mode_x = GET_MODE (x);
>>   rtx_code code_x = GET_CODE (x);
>> 
>> -  /* All floating point compares return CCFP if it is an equality
>> -     comparison, and CCFPE otherwise.  */
>>   if (GET_MODE_CLASS (mode_x) == MODE_FLOAT)
>> -    {
>> -      switch (code)
>> -       {
>> -       case EQ:
>> -       case NE:
>> -       case UNORDERED:
>> -       case ORDERED:
>> -       case UNLT:
>> -       case UNLE:
>> -       case UNGT:
>> -       case UNGE:
>> -       case UNEQ:
>> -         return CCFPmode;
>> -
>> -       case LT:
>> -       case LE:
>> -       case GT:
>> -       case GE:
>> -       case LTGT:
>> -         return CCFPEmode;
>> -
>> -       default:
>> -         gcc_unreachable ();
>> -       }
>> -    }
>> +    return aarch64_fp_cc_mode (code, mode_x);
>> 
>>   /* Equality comparisons of short modes against zero can be performed
>>      using the TST instruction with the appropriate bitmask.  */
>> diff --git a/gcc/testsuite/gcc.target/aarch64/ccmp_1.c 
>> b/gcc/testsuite/gcc.target/aarch64/ccmp_1.c
>> index 9b68c070f9d..e1975c59ba1 100644
>> --- a/gcc/testsuite/gcc.target/aarch64/ccmp_1.c
>> +++ b/gcc/testsuite/gcc.target/aarch64/ccmp_1.c
>> @@ -86,10 +86,12 @@ f13 (int a, int b)
>> /* { dg-final { scan-assembler "cmp\t(.)+35" } } */
>> 
>> /* { dg-final { scan-assembler-times "\tcmp\tw\[0-9\]+, 0" 4 } } */
>> -/* { dg-final { scan-assembler-times "fcmpe\t(?:.)+0\\.0" 1 } } */
>> -/* { dg-final { scan-assembler-times "fcmp\t(?:.)+0\\.0" 1 } } */
>> +/* With -ffinite-math-only the signalling compares are not needed.  */
>> +/* { dg-final { scan-assembler-times {\tfcmp\t[sd][0-9]+, #0\.0} 4 } } */
>> +/* { dg-final { scan-assembler-not {\tfcmpe\t} } } */
>> 
>> /* { dg-final { scan-assembler "adds\t" } } */
>> /* { dg-final { scan-assembler-times "\tccmp\t" 11 } } */
>> -/* { dg-final { scan-assembler-times "fccmp\t.*0\\.0" 1 } } */
>> -/* { dg-final { scan-assembler-times "fccmpe\t.*0\\.0" 1 } } */
>> +/* FCCMP has no zero-immediate form, so both operands are registers.  */
>> +/* { dg-final { scan-assembler-times {\tfccmp\t[sd][0-9]+, [sd][0-9]+,} 2 } 
>> } */
>> +/* { dg-final { scan-assembler-not {\tfccmpe\t} } } */
>> diff --git a/gcc/testsuite/gcc.target/aarch64/fccmp_1.c 
>> b/gcc/testsuite/gcc.target/aarch64/fccmp_1.c
>> index 96d6f717136..934bb0e560b 100644
>> --- a/gcc/testsuite/gcc.target/aarch64/fccmp_1.c
>> +++ b/gcc/testsuite/gcc.target/aarch64/fccmp_1.c
>> @@ -7,8 +7,8 @@
>> 
>> /*
>> ** hf_lt:
>> -**     fcmpe   h0, h1
>> -**     fccmpe  h2, h3, 0, mi
>> +**     fcmp    h0, h1
>> +**     fccmp   h2, h3, 0, mi
>> **     cset    w0, mi
>> **     ret
>> */
>> @@ -35,8 +35,8 @@ hf_eq (_Float16 a, _Float16 b, _Float16 c, _Float16 d)
>> 
>> /*
>> ** hf_ior:
>> -**     fcmpe   h0, h1
>> -**     fccmpe  h2, h3, 8, pl
>> +**     fcmp    h0, h1
>> +**     fccmp   h2, h3, 8, pl
>> **     cset    w0, mi
>> **     ret
>> */
>> diff --git a/gcc/testsuite/gcc.target/aarch64/fccmp_3.c 
>> b/gcc/testsuite/gcc.target/aarch64/fccmp_3.c
>> new file mode 100644
>> index 00000000000..eb1505fc26f
>> --- /dev/null
>> +++ b/gcc/testsuite/gcc.target/aarch64/fccmp_3.c
>> @@ -0,0 +1,18 @@
>> +/* { dg-do compile } */
>> +/* { dg-options "-O2 -ffinite-math-only" } */
>> +/* { dg-final { check-function-bodies "**" "" } } */
>> +
>> +/* One condition code mode lets GCC reuse a compare of the same operands.  
>> */
>> +
>> +/*
>> +** cse:
>> +**     fcmp    d0, d1
>> +**     cset    w0, eq
>> +**     cinc    w0, w0, mi
>> +**     ret
>> +*/
>> +int
>> +cse (double a, double b)
>> +{
>> +  return (a < b) + (a == b);
>> +}
>> --
>> 2.50.1 (Apple Git-155)


Attachment: 0002-aarch64-Use-one-FP-condition-mode-when-exceptions-ar.patch
Description: 0002-aarch64-Use-one-FP-condition-mode-when-exceptions-ar.patch

Reply via email to