[PATCH 5/6] aarch64: Use one FP condition mode when exceptions are unobservable

<[email protected]>
Newsgroups gmane.comp.gcc.patches
Message-ID <[email protected]>
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;
 
 	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)
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.