[3/4,ifcvt] if convert x=c ? y op z : y by RISC-V Zicond like insns

Message ID 20231030072523.26818-4-gaofei@eswincomputing.com
State Unresolved
Headers
Series add support for conditional zero operation |

Checks

Context Check Description
snail/gcc-patch-check warning Git am fail log

Commit Message

Fei Gao Oct. 30, 2023, 7:25 a.m. UTC
  op=[-, |, ^]
opcode=[sub, or, xor]

Conditional op, if zero
rd = (rc == 0) ? (rs1 op rs2) : rs1
-->
czero.nez rd, rs2, rc
opcode rd, rs1, rd

Conditional op, if non-zero
rd = (rc != 0) ? (rs1 op rs2) : rs1
-->
czero.eqz rd, rs2, rc
opcode rd, rs1, rd

Co-authored-by: Xiao Zeng<zengxiao@eswincomputing.com>

gcc/ChangeLog:

        * ifcvt.cc (noce_cond_zero_binary_op_supported): add more op=[-, |, ^]
        (noce_try_cond_zero_arith): adapt for newly added op

gcc/testsuite/ChangeLog:

        * gcc.target/riscv/zicond_ifcvt_opt.c: add TCs for op=[-, |, ^]
---
 gcc/ifcvt.cc                                  |  23 +-
 .../gcc.target/riscv/zicond_ifcvt_opt.c       | 378 ++++++++++++++++++
 2 files changed, 396 insertions(+), 5 deletions(-)
  

Patch

diff --git a/gcc/ifcvt.cc b/gcc/ifcvt.cc
index 4f98c1c7bf9..6e341fc4d4b 100644
--- a/gcc/ifcvt.cc
+++ b/gcc/ifcvt.cc
@@ -2908,6 +2908,15 @@  noce_try_sign_mask (struct noce_if_info *if_info)
   return true;
 }
 
+static bool
+noce_cond_zero_binary_op_supported (enum rtx_code op)
+{
+  if (op == PLUS || op == MINUS || op == IOR || op == XOR)
+    return true;
+
+  return false;
+}
+
 /* Convert x = c ? y + z : y or x = c ? y : y + z. */
 
 static bool
@@ -2918,6 +2927,7 @@  noce_try_cond_zero_arith (struct noce_if_info *if_info)
   machine_mode mode = GET_MODE (if_info->x);
   rtx common = NULL_RTX;
   enum rtx_code czero_code = UNKNOWN;
+  enum rtx_code opcode = UNKNOWN;
   rtx a = if_info->a;
   rtx b = if_info->b;
   rtx z = NULL_RTX;
@@ -2933,18 +2943,21 @@  noce_try_cond_zero_arith (struct noce_if_info *if_info)
     return false;
 
   /* check y + z:y*/
-  if (GET_CODE (a) == PLUS && REG_P (XEXP (a, 0)) && REG_P (XEXP (a, 1))
-      && REG_P (b) && rtx_equal_p (XEXP (a, 0), b))
+  if (noce_cond_zero_binary_op_supported (GET_CODE (a)) && REG_P (XEXP (a, 0))
+      && REG_P (XEXP (a, 1)) && REG_P (b) && rtx_equal_p (XEXP (a, 0), b))
     {
+      opcode = GET_CODE (a);
       common = b;
       z = XEXP (a, 1);
       /* x = c ? y+z : y, cond = !c --> x = cond ? y : y+z  */
       czero_code = GET_CODE (cond);
     }
   /* check y : y+z  */
-  else if (GET_CODE (b) == PLUS && REG_P (XEXP (b, 0)) && REG_P (XEXP (b, 1))
-	   && REG_P (a) && rtx_equal_p (a, XEXP (b, 0)))
+  else if (noce_cond_zero_binary_op_supported (GET_CODE (b))
+	   && REG_P (XEXP (b, 0)) && REG_P (XEXP (b, 1)) && REG_P (a)
+	   && rtx_equal_p (a, XEXP (b, 0)))
     {
+      opcode = GET_CODE (b);
       common = a;
       z = XEXP (b, 1);
       /* x = c ? y : y+z, cond = !c --> x = !cond ? y : y+z  */
@@ -2971,7 +2984,7 @@  noce_try_cond_zero_arith (struct noce_if_info *if_info)
       return false;
     }
 
-  target = expand_simple_binop (mode, PLUS, common, target, if_info->x, 0,
+  target = expand_simple_binop (mode, opcode, common, target, if_info->x, 0,
 				OPTAB_DIRECT);
   if (!target)
     {
diff --git a/gcc/testsuite/gcc.target/riscv/zicond_ifcvt_opt.c b/gcc/testsuite/gcc.target/riscv/zicond_ifcvt_opt.c
index 068c1443413..3ec01dcb135 100644
--- a/gcc/testsuite/gcc.target/riscv/zicond_ifcvt_opt.c
+++ b/gcc/testsuite/gcc.target/riscv/zicond_ifcvt_opt.c
@@ -128,3 +128,381 @@  long test_ADD_eqz_x_2(long x, long z, long c)
     x = x + z;
   return x;
 }
+
+/*
+**test_SUB_ceqz:
+**	czero\.eqz	a3,a2,a3
+**	sub	a0,a1,a3
+**	ret
+*/
+// x = c ? y-z : y
+long test_SUB_ceqz(long x, long y, long z, long c)
+{
+  if (c)
+    x = y - z;
+  else
+    x = y;
+  return x;
+}
+
+/*
+**test_SUB_ceqz_x:
+**	czero\.eqz	a2,a1,a2
+**	sub	a0,a0,a2
+**	ret
+*/
+// x = c ? x-z : x
+long test_SUB_ceqz_x(long x, long z, long c)
+{
+  if (c)
+    x = x - z;
+
+  return x;
+}
+
+/*
+**test_SUB_nez:
+**	czero\.nez	a3,a2,a3
+**	sub	a0,a1,a3
+**	ret
+*/
+// x = c ? y : y-z
+long test_SUB_nez(long x, long y, long z, long c)
+{
+  if (c)
+    x = y;
+  else
+    x = y - z;
+  return x;
+}
+
+/*
+**test_SUB_nez_x:
+**	czero\.nez	a2,a1,a2
+**	sub	a0,a0,a2
+**	ret
+*/
+// x = c ? x : x-z
+long test_SUB_nez_x(long x, long z, long c)
+{
+  if (c)
+  {}
+  else
+    x = x - z;
+  return x;
+}
+
+/*
+**test_SUB_nez_2:
+**	czero\.nez	a3,a2,a3
+**	sub	a0,a1,a3
+**	ret
+*/
+// x = !c ? y-z : y
+long test_SUB_nez_2(long x, long y, long z, long c)
+{
+  if (!c)
+    x = y - z;
+  else
+    x = y;
+  return x;
+}
+
+/*
+**test_SUB_nez_x_2:
+**	czero\.nez	a2,a1,a2
+**	sub	a0,a0,a2
+**	ret
+*/
+// x = !c ? x-z : x
+long test_SUB_nez_x_2(long x, long z, long c)
+{
+  if (!c)
+    x = x - z;
+
+  return x;
+}
+
+/*
+**test_SUB_eqz_2:
+**	czero\.eqz	a3,a2,a3
+**	sub	a0,a1,a3
+**	ret
+*/
+// x = !c ? y : y-z
+long test_SUB_eqz_2(long x, long y, long z, long c)
+{
+  if (!c)
+    x = y;
+  else
+    x = y - z;
+  return x;
+}
+
+/*
+**test_SUB_eqz_x_2:
+**	czero\.eqz	a2,a1,a2
+**	sub	a0,a0,a2
+**	ret
+*/
+// x = !c ? x : x-z
+long test_SUB_eqz_x_2(long x, long z, long c)
+{
+  if (!c)
+  {}
+  else
+    x = x - z;
+  return x;
+}
+
+/*
+**test_IOR_ceqz:
+**	czero\.eqz	a3,a2,a3
+**	or	a0,a1,a3
+**	ret
+*/
+// x = c ? y|z : y
+long test_IOR_ceqz(long x, long y, long z, long c)
+{
+  if (c)
+    x = y | z;
+  else
+    x = y;
+  return x;
+}
+
+/*
+**test_IOR_ceqz_x:
+**	czero\.eqz	a2,a1,a2
+**	or	a0,a0,a2
+**	ret
+*/
+// x = c ? x|z : x
+long test_IOR_ceqz_x(long x, long z, long c)
+{
+  if (c)
+    x = x | z;
+
+  return x;
+}
+
+/*
+**test_IOR_nez:
+**	czero\.nez	a3,a2,a3
+**	or	a0,a1,a3
+**	ret
+*/
+// x = c ? y : y|z
+long test_IOR_nez(long x, long y, long z, long c)
+{
+  if (c)
+    x = y;
+  else
+    x = y | z;
+  return x;
+}
+
+/*
+**test_IOR_nez_x:
+**	czero\.nez	a2,a1,a2
+**	or	a0,a0,a2
+**	ret
+*/
+// x = c ? x : x|z
+long test_IOR_nez_x(long x, long z, long c)
+{
+  if (c)
+  {}
+  else
+    x = x | z;
+  return x;
+}
+
+/*
+**test_IOR_nez_2:
+**	czero\.nez	a3,a2,a3
+**	or	a0,a1,a3
+**	ret
+*/
+// x = !c ? y|z : y
+long test_IOR_nez_2(long x, long y, long z, long c)
+{
+  if (!c)
+    x = y | z;
+  else
+    x = y;
+  return x;
+}
+
+/*
+**test_IOR_nez_x_2:
+**	czero\.nez	a2,a1,a2
+**	or	a0,a0,a2
+**	ret
+*/
+// x = !c ? x|z : x
+long test_IOR_nez_x_2(long x, long z, long c)
+{
+  if (!c)
+    x = x | z;
+
+  return x;
+}
+
+/*
+**test_IOR_eqz_2:
+**	czero\.eqz	a3,a2,a3
+**	or	a0,a1,a3
+**	ret
+*/
+// x = !c ? y : y|z
+long test_IOR_eqz_2(long x, long y, long z, long c)
+{
+  if (!c)
+    x = y;
+  else
+    x = y | z;
+  return x;
+}
+
+/*
+**test_IOR_eqz_x_2:
+**	czero\.eqz	a2,a1,a2
+**	or	a0,a0,a2
+**	ret
+*/
+// x = !c ? x : x|z
+long test_IOR_eqz_x_2(long x, long z, long c)
+{
+  if (!c)
+  {}
+  else
+    x = x | z;
+  return x;
+}
+
+/*
+**test_XOR_ceqz:
+**	czero\.eqz	a3,a2,a3
+**	xor	a0,a1,a3
+**	ret
+*/
+// x = c ? y^z : y
+long test_XOR_ceqz(long x, long y, long z, long c)
+{
+  if (c)
+    x = y ^ z;
+  else
+    x = y;
+  return x;
+}
+
+/*
+**test_XOR_ceqz_x:
+**	czero\.eqz	a2,a1,a2
+**	xor	a0,a0,a2
+**	ret
+*/
+// x = c ? x^z : x
+long test_XOR_ceqz_x(long x, long z, long c)
+{
+  if (c)
+    x = x ^ z;
+
+  return x;
+}
+
+/*
+**test_XOR_nez:
+**	czero\.nez	a3,a2,a3
+**	xor	a0,a1,a3
+**	ret
+*/
+// x = c ? y : y^z
+long test_XOR_nez(long x, long y, long z, long c)
+{
+  if (c)
+    x = y;
+  else
+    x = y ^ z;
+  return x;
+}
+
+/*
+**test_XOR_nez_x:
+**	czero\.nez	a2,a1,a2
+**	xor	a0,a0,a2
+**	ret
+*/
+// x = c ? x : x^z
+long test_XOR_nez_x(long x, long z, long c)
+{
+  if (c)
+  {}
+  else
+    x = x ^ z;
+  return x;
+}
+
+/*
+**test_XOR_nez_2:
+**	czero\.nez	a3,a2,a3
+**	xor	a0,a1,a3
+**	ret
+*/
+// x = !c ? y^z : y
+long test_XOR_nez_2(long x, long y, long z, long c)
+{
+  if (!c)
+    x = y ^ z;
+  else
+    x = y;
+  return x;
+}
+
+/*
+**test_XOR_nez_x_2:
+**	czero\.nez	a2,a1,a2
+**	xor	a0,a0,a2
+**	ret
+*/
+// x = !c ? x^z : x
+long test_XOR_nez_x_2(long x, long z, long c)
+{
+  if (!c)
+    x = x ^ z;
+
+  return x;
+}
+
+/*
+**test_XOR_eqz_2:
+**	czero\.eqz	a3,a2,a3
+**	xor	a0,a1,a3
+**	ret
+*/
+// x = !c ? y : y^z
+long test_XOR_eqz_2(long x, long y, long z, long c)
+{
+  if (!c)
+    x = y;
+  else
+    x = y ^ z;
+  return x;
+}
+
+/*
+**test_XOR_eqz_x_2:
+**	czero\.eqz	a2,a1,a2
+**	xor	a0,a0,a2
+**	ret
+*/
+// x = !c ? x : x^z
+long test_XOR_eqz_x_2(long x, long z, long c)
+{
+  if (!c)
+  {}
+  else
+    x = x ^ z;
+  return x;
+}