Ping.
https://gcc.gnu.org/pipermail/gcc-patches/2026-August/727263.html
Thanks,
Kyrill

> On 12 Aug 2026, at 08:32, Kyrylo Tkachov <[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;
> +
> +    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)
> 

Reply via email to