op=[ASHIFT, ASHIFTRT, LSHIFTRT, ROTATE, ROTATERT]

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

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

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

gcc/ChangeLog:

        * ifcvt.cc (noce_cond_zero_binary_op_supported): add support for shift 
like op.
        (get_base_reg): add support for subreg to handle shift amount operand.
        (noce_bbs_ok_for_cond_zero_arith): to replace shift amount operand.

gcc/testsuite/ChangeLog:

        * gcc.target/riscv/zicond_ifcvt_opt.c: add TCs for shift like op.
---
 gcc/ifcvt.cc                                  |  8 ++-
 .../gcc.target/riscv/zicond_ifcvt_opt.c       | 55 ++++++++++++++++++-
 2 files changed, 61 insertions(+), 2 deletions(-)

diff --git a/gcc/ifcvt.cc b/gcc/ifcvt.cc
index 1f0f5414ea1..2efae21ebfe 100644
--- a/gcc/ifcvt.cc
+++ b/gcc/ifcvt.cc
@@ -2920,7 +2920,9 @@ noce_cond_zero_binary_op_supported (rtx op)
 {
   enum rtx_code opcode = GET_CODE (op);
 
-  if (opcode == PLUS || opcode == MINUS || opcode == IOR || opcode == XOR)
+  if (opcode == PLUS || opcode == MINUS || opcode == IOR || opcode == XOR
+      || opcode == ASHIFT || opcode == ASHIFTRT || opcode == LSHIFTRT
+      || opcode == ROTATE || opcode == ROTATERT)
     return true;
 
   return false;
@@ -2934,6 +2936,8 @@ get_base_reg (rtx exp)
 {
   if (REG_P (exp))
     return exp;
+  else if (SUBREG_P (exp))
+    return SUBREG_REG (exp);
 
   return NULL_RTX;
 }
@@ -3006,6 +3010,8 @@ noce_bbs_ok_for_cond_zero_arith (struct noce_if_info 
*if_info, rtx *common_ptr,
 
   if (REG_P (bin_op1))
     *to_replace = &XEXP (bin_exp, 1);
+  else if (SUBREG_P (bin_op1))
+    *to_replace = &SUBREG_REG (XEXP (bin_exp, 1));
   else
     return false;
 
diff --git a/gcc/testsuite/gcc.target/riscv/zicond_ifcvt_opt.c 
b/gcc/testsuite/gcc.target/riscv/zicond_ifcvt_opt.c
index dcb21c15d1a..ab5a4909b61 100644
--- a/gcc/testsuite/gcc.target/riscv/zicond_ifcvt_opt.c
+++ b/gcc/testsuite/gcc.target/riscv/zicond_ifcvt_opt.c
@@ -562,5 +562,58 @@ test_XOR_eqz_x_2_reverse_bin_oprands (long x, long z, long 
c)
   return x;
 }
 
-/* { dg-final { scan-assembler-times {czero\.eqz} 28 } } */
+long
+test_ShiftLeft_eqz (long x, long y, long z, long c)
+{
+  if (c)
+    x = y << z;
+  else
+    x = y;
+  return x;
+}
+
+long
+test_ShiftR_eqz (long x, long y, long z, long c)
+{
+  if (c)
+    x = y >> z;
+  else
+    x = y;
+  return x;
+}
+
+unsigned long
+test_ShiftR_logical_eqz (unsigned long x, unsigned long y, unsigned long z,
+                        unsigned long c)
+{
+  if (c)
+    x = y >> z;
+  else
+    x = y;
+  return x;
+}
+
+unsigned long
+test_RotateL_eqz (unsigned long x, unsigned long y, unsigned long z,
+                 unsigned long c)
+{
+  if (c)
+    x = (y << z) | (y >> (64 - z));
+  else
+    x = y;
+  return x;
+}
+
+unsigned long
+test_RotateR_eqz (unsigned long x, unsigned long y, unsigned long z,
+                 unsigned long c)
+{
+  if (c)
+    x = (y >> z) | (y << (64 - z));
+  else
+    x = y;
+  return x;
+}
+
+/* { dg-final { scan-assembler-times {czero\.eqz} 33 } } */
 /* { dg-final { scan-assembler-times {czero\.nez} 28 } } */
-- 
2.17.1

Reply via email to