[PATCH-4,rs6000] Optimize single cc bit reverse implementation

Message ID ee561ab2-57dc-4d25-b901-9210e97e3e71@linux.ibm.com
State New
Headers
Series [PATCH-4,rs6000] Optimize single cc bit reverse implementation |

Checks

Context Check Description
linaro-tcwg-bot/tcwg_gcc_build--master-arm fail Patch failed to apply
linaro-tcwg-bot/tcwg_gcc_build--master-aarch64 fail Patch failed to apply

Commit Message

HAO CHEN GUI April 30, 2024, 7:20 a.m. UTC
  Hi,
  It's the forth patch of a series of patches optimizing CC modes on
rs6000.

  The single CC bit reverse can be implemented by setbcr on Power10 or
isel on Power9 or mfcr on Power8 and below. Originally CCFP is not
supported for isel and setbcr as bcd insns use CCFP and its bit reverse
is not the same as normal CCFP mode. Previous patches add new CC modes
according to the usage of CC bits. So now single CC bit reverse can be
supported on all CC modes with a uniform pattern.

  This patch removes unordered and ordered from codes list of CCFP with
finite_math_only set. These two are no needed as bcd insns use a separate
CC mode now. reverse_condition is replaced with rs6000_reverse_condition
as all CC modes can be reversed. A new isel version single CC bit reverse
pattern is added. fp and bcd CC reverse pattern are removed and a uniform
single CC bit reverse pattern is added, which is mfcr version.

  The new test cases illustrate the different implementation of single cc
bit reverse test.

  Bootstrapped and tested on powerpc64-linux BE and LE with no
regressions. Is it OK for the trunk?

Thanks
Gui Haochen

ChangeLog
rs6000: Optimize single cc bit reverse implementation

This patch implements single cc bit reverse by mfcr (on Power8 and below)
or isel (on Power9) or setbcr (on Power10) with all CC modes.

gcc/
	* config/rs6000/predicates.md (branch_comparison_operator): Remove
	unordered and ordered from CCFP with finite_math_only.
	(scc_comparison_operator): Add unle and unge.
	* config/rs6000/rs6000.md (CCANY): Add CCFP, CCBCD, CCLTEQ and CCEQ.
	(*isel_reversed_<CCANY:mode>_<GPR:mode>): Replace reverse_condition
	with rs6000_reverse_condition.
	(*set<GPR:mode><CCANY:mode>_rev): New insn_and_split pattern for
	single cc bit reverse P9 version.
	(fp_rev, ccbcd_rev): Remove.
	(*<code><mode>_cc): Remove the pattern for CCFP and CCBCD.  Merge
	them to...
	(*set<GPR:mode><CCANY:mode>_rev): ...this, the new insn_and_split
	pattern for single cc bit reverse P8 and below version.

gcc/testsuite/
	* gcc.target/powerpc/cc_rev.h: New.
	* gcc.target/powerpc/cc_rev_1.c: New.
	* gcc.target/powerpc/cc_rev_2.c: New.
	* gcc.target/powerpc/cc_rev_3.c: New.

patch.diff
  

Patch

diff --git a/gcc/config/rs6000/predicates.md b/gcc/config/rs6000/predicates.md
index 322e7639fd4..ddb46799bff 100644
--- a/gcc/config/rs6000/predicates.md
+++ b/gcc/config/rs6000/predicates.md
@@ -1348,7 +1348,7 @@  (define_predicate "branch_comparison_operator"
 	(match_test "GET_MODE_CLASS (GET_MODE (XEXP (op, 0))) == MODE_CC")
 	(if_then_else (match_test "GET_MODE (XEXP (op, 0)) == CCFPmode")
 	  (if_then_else (match_test "flag_finite_math_only")
-	    (match_code "lt,le,gt,ge,eq,ne,unordered,ordered")
+	    (match_code "lt,le,gt,ge,eq,ne")
 	    (match_code "lt,gt,eq,unordered,unge,unle,ne,ordered"))
 	  (if_then_else (match_test "GET_MODE (XEXP (op, 0)) == CCBCDmode")
 	    (match_code "lt,le,gt,ge,eq,ne,unordered,ordered")
@@ -1397,7 +1397,7 @@  (define_predicate "scc_comparison_operator"
 ;; an SCC insn.
 (define_predicate "scc_rev_comparison_operator"
   (and (match_operand 0 "branch_comparison_operator")
-       (match_code "ne,le,ge,leu,geu,ordered")))
+       (match_code "ne,le,ge,leu,geu,ordered,unle,unge")))

 ;; Return 1 if OP is a comparison operator suitable for floating point
 ;; vector/scalar comparisons that generate a -1/0 mask.
diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index 2c6255395d1..ccf392b6409 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -5509,7 +5509,7 @@  (define_expand "mov<mode>cc"
 ;; leave out the mode in operand 4 and use one pattern, but reload can
 ;; change the mode underneath our feet and then gets confused trying
 ;; to reload the value.
-(define_mode_iterator CCANY [CC CCUNS])
+(define_mode_iterator CCANY [CC CCUNS CCFP CCBCD CCLTEQ CCEQ])
 (define_insn "isel_<CCANY:mode>_<GPR:mode>"
   [(set (match_operand:GPR 0 "gpc_reg_operand" "=r,r")
 	(if_then_else:GPR
@@ -5536,7 +5536,8 @@  (define_insn "*isel_reversed_<CCANY:mode>_<GPR:mode>"
 	 (match_operand:GPR 3 "reg_or_zero_operand" "O,b")))]
   "TARGET_ISEL"
 {
-  PUT_CODE (operands[1], reverse_condition (GET_CODE (operands[1])));
+  PUT_CODE (operands[1], rs6000_reverse_condition (<CCANY:MODE>mode,
+						   GET_CODE (operands[1])));
   return "isel %0,%3,%2,%j1";
 }
   [(set_attr "type" "isel")])
@@ -12764,6 +12765,27 @@  (define_insn "set<mode>_cc"
 	(const_string "mfcr")))
    (set_attr "length" "8")])

+(define_insn_and_split "*set<GPR:mode><CCANY:mode>_rev"
+  [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
+	(match_operator:GPR 1 "scc_rev_comparison_operator"
+			[(match_operand:CCANY 2 "cc_reg_operand" "y")
+			 (const_int 0)]))]
+  "TARGET_ISEL
+   && !TARGET_POWER10"
+  "#"
+  "&& 1"
+  [(set (match_dup 2)
+	(const_int 1))
+   (set (match_dup 0)
+	(if_then_else:GPR
+	  (match_dup 1)
+	  (match_dup 2)
+	  (const_int 0)))]
+{
+  operands[2] = can_create_pseudo_p ()
+		? operands[0] : gen_reg_rtx (<GPR:MODE>mode);
+}
+  [(set_attr "type" "isel")])

 (define_code_iterator cmp [eq ne lt ltu gt gtu le leu ge geu])
 (define_code_attr UNS [(eq "CC")
@@ -13243,42 +13265,25 @@  (define_insn_and_split "*nesi3_ext<mode>"
 		      (const_string "16")))])


-(define_code_iterator fp_rev [ordered ne unle unge])
 (define_code_iterator fp_two [ltgt le ge unlt ungt uneq])
-(define_code_iterator ccbcd_rev [ordered ne le ge])

-(define_insn_and_split "*<code><mode>_cc"
+(define_insn_and_split "*set<GPR:mode><CCANY:mode>_rev"
   [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
-	(fp_rev:GPR (match_operand:CCFP 1 "cc_reg_operand" "y")
-		    (const_int 0)))]
-  "!flag_finite_math_only"
-  "#"
-  "&& 1"
-  [(pc)]
-{
-  rtx_code revcode = reverse_condition_maybe_unordered (<CODE>);
-  rtx eq = gen_rtx_fmt_ee (revcode, <MODE>mode, operands[1], const0_rtx);
-  rtx tmp = gen_reg_rtx (<MODE>mode);
-  emit_move_insn (tmp, eq);
-  emit_insn (gen_xor<mode>3 (operands[0], tmp, const1_rtx));
-  DONE;
-}
-  [(set_attr "length" "12")])
-
-(define_insn_and_split "*<code><mode>_cc"
-  [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
-	(ccbcd_rev:GPR (match_operand:CCBCD 1 "cc_reg_operand" "y")
-		    (const_int 0)))]
-  ""
+	(match_operator:GPR 1 "scc_rev_comparison_operator"
+			[(match_operand:CCANY 2 "cc_reg_operand" "y")
+			 (const_int 0)]))]
+  "!TARGET_ISEL
+   && !TARGET_POWER10"
   "#"
   "&& 1"
   [(pc)]
 {
-  rtx_code revcode = reverse_condition (<CODE>);
-  rtx eq = gen_rtx_fmt_ee (revcode, <MODE>mode, operands[1], const0_rtx);
-  rtx tmp = gen_reg_rtx (<MODE>mode);
+  rtx_code revcode = rs6000_reverse_condition (<CCANY:MODE>mode,
+					       GET_CODE (operands[1]));
+  rtx eq = gen_rtx_fmt_ee (revcode, <GPR:MODE>mode, operands[2], const0_rtx);
+  rtx tmp = gen_reg_rtx (<GPR:MODE>mode);
   emit_move_insn (tmp, eq);
-  emit_insn (gen_xor<mode>3 (operands[0], tmp, const1_rtx));
+  emit_insn (gen_xor<GPR:mode>3 (operands[0], tmp, const1_rtx));
   DONE;
 }
   [(set_attr "length" "12")])
diff --git a/gcc/testsuite/gcc.target/powerpc/cc_rev.h b/gcc/testsuite/gcc.target/powerpc/cc_rev.h
new file mode 100644
index 00000000000..777718a8546
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/cc_rev.h
@@ -0,0 +1,11 @@ 
+#include <altivec.h>
+
+int test1 (vector unsigned char a, vector unsigned char b)
+{
+  return __builtin_bcdcmpge (a, b);
+}
+
+int test2 (vector unsigned char a, vector unsigned char b)
+{
+  return __builtin_bcdcmple (a, b);
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/cc_rev_1.c b/gcc/testsuite/gcc.target/powerpc/cc_rev_1.c
new file mode 100644
index 00000000000..b1125531e9d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/cc_rev_1.c
@@ -0,0 +1,7 @@ 
+/* { dg-do compile } */
+/* { dg-require-effective-target powerpc_vsx_ok } */
+/* { dg-options "-mdejagnu-cpu=power8 -O2" } */
+/* { dg-final { scan-assembler-times {\mmfcr\M} 2 } } */
+/* { dg-final { scan-assembler-times {\mxori\M} 2 } } */
+
+#include "cc_rev.h"
diff --git a/gcc/testsuite/gcc.target/powerpc/cc_rev_2.c b/gcc/testsuite/gcc.target/powerpc/cc_rev_2.c
new file mode 100644
index 00000000000..5938cedf230
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/cc_rev_2.c
@@ -0,0 +1,6 @@ 
+/* { dg-do compile } */
+/* { dg-require-effective-target powerpc_vsx_ok } */
+/* { dg-options "-mdejagnu-cpu=power9 -O2" } */
+/* { dg-final { scan-assembler-times {\misel\M} 2 } } */
+
+#include "cc_rev.h"
diff --git a/gcc/testsuite/gcc.target/powerpc/cc_rev_3.c b/gcc/testsuite/gcc.target/powerpc/cc_rev_3.c
new file mode 100644
index 00000000000..954ecf0586f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/cc_rev_3.c
@@ -0,0 +1,6 @@ 
+/* { dg-do compile } */
+/* { dg-require-effective-target powerpc_vsx_ok } */
+/* { dg-options "-mdejagnu-cpu=power10 -O2" } */
+/* { dg-final { scan-assembler-times {\msetbcr\M} 2 } } */
+
+#include "cc_rev.h"