On Tue, Aug 11, 2026 at 3:43 AM <[email protected]> wrote: > > From: Kyrylo Tkachov <[email protected]> > > 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. > > 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. > > Bootstrapped and tested on aarch64-none-linux-gnu. > Ok for trunk?
> Thanks, > Kyrill > > gcc/ > > * config/aarch64/aarch64.cc (aarch64_select_cc_mode): Use > CCFPmode when the FCMPE exception is not observable. > > 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 | 7 ++++--- > 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, 32 insertions(+), 11 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..e94b583d1bd 100644 > --- a/gcc/config/aarch64/aarch64.cc > +++ b/gcc/config/aarch64/aarch64.cc > @@ -12680,8 +12680,8 @@ 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. */ > + /* FCMP and FCMPE set the same flags, but FCMPE also raises Invalid for a > + quiet NaN. Use CCFPE only when that exception is observable. */ > if (GET_MODE_CLASS (mode_x) == MODE_FLOAT) > { > switch (code) > @@ -12702,7 +12702,8 @@ aarch64_select_cc_mode (RTX_CODE code, rtx x, rtx y) > case GT: > case GE: > case LTGT: > - return CCFPEmode; > + return HONOR_NANS (mode_x) && flag_trapping_math > + ? CCFPEmode : CCFPmode; It might be a good idea in the future, to pass down into this function if x and y could be a NaN. Otherwise Ok. > > default: > gcc_unreachable (); > 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) >
