op=[PLUS, MINUS, IOR, XOR, ASHIFT, ASHIFTRT, LSHIFTRT, ROTATE, ROTATERT]

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

gcc/ChangeLog:

        * ifcvt.cc (noce_cond_zero_shift_op_supported): check if OP is shift 
like operation
        (noce_cond_zero_binary_op_supported): restructure & call 
noce_cond_zero_shift_op_supported
        (noce_bbs_ok_for_cond_zero_arith): add bin_exp_ptr interface
        (noce_try_cond_zero_arith): add support for x=c ? (y op const_int)

gcc/testsuite/ChangeLog:

        * gcc.target/riscv/zicond_ifcvt_opt.c: add TCs for x=c ? (y op 
const_int) : y
---
 gcc/ifcvt.cc                                  |  53 +-
 .../gcc.target/riscv/zicond_ifcvt_opt.c       | 675 +++++++++++++++++-
 2 files changed, 716 insertions(+), 12 deletions(-)

diff --git a/gcc/ifcvt.cc b/gcc/ifcvt.cc
index 8f6a0e7f5fe..4cc6a125ff0 100644
--- a/gcc/ifcvt.cc
+++ b/gcc/ifcvt.cc
@@ -2920,6 +2920,16 @@ noce_try_sign_mask (struct noce_if_info *if_info)
 
     OP is the operation to check.  */
 
+static bool
+noce_cond_zero_shift_op_supported (enum rtx_code op)
+{
+  if (op == ASHIFT || op == ASHIFTRT || op == LSHIFTRT || op == ROTATE
+      || op == ROTATERT)
+    return true;
+
+  return false;
+}
+
 static bool
 noce_cond_zero_binary_op_supported (rtx op)
 {
@@ -2930,8 +2940,7 @@ noce_cond_zero_binary_op_supported (rtx op)
     opcode = GET_CODE (XEXP (op, 0));
 
   if (opcode == PLUS || opcode == MINUS || opcode == IOR || opcode == XOR
-      || opcode == ASHIFT || opcode == ASHIFTRT || opcode == LSHIFTRT
-      || opcode == ROTATE || opcode == ROTATERT)
+      || noce_cond_zero_shift_op_supported (opcode))
     return true;
 
   return false;
@@ -2963,6 +2972,7 @@ get_base_reg (rtx exp)
 
 static bool
 noce_bbs_ok_for_cond_zero_arith (struct noce_if_info *if_info, rtx *common_ptr,
+                                rtx *bin_exp_ptr,
                                 enum rtx_code *czero_code_ptr, rtx *a_ptr,
                                 rtx **to_replace)
 {
@@ -3029,6 +3039,7 @@ noce_bbs_ok_for_cond_zero_arith (struct noce_if_info 
*if_info, rtx *common_ptr,
     return false;
 
   *common_ptr = common;
+  *bin_exp_ptr = bin_exp;
   *czero_code_ptr = czero_code;
   *a_ptr = a;
 
@@ -3047,20 +3058,28 @@ 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;
+  rtx bin_exp = NULL_RTX;
+  enum rtx_code bin_code = UNKNOWN;
+  rtx bin_op0 = NULL_RTX;
   rtx non_zero_op = NULL_RTX;
   rtx *to_replace = NULL;
 
-  if (!noce_bbs_ok_for_cond_zero_arith (if_info, &common, &czero_code, &a,
-                                       &to_replace))
+  if (!noce_bbs_ok_for_cond_zero_arith (if_info, &common, &bin_exp, 
&czero_code,
+                                       &a, &to_replace))
     return false;
 
-  /* Disallow CONST_INT currently for simplicity*/
-  if (to_replace == NULL || !REG_P (*to_replace))
-    return false;
+  start_sequence ();
 
-  non_zero_op = *to_replace;
+  bin_code = GET_CODE (bin_exp);
+  bin_op0 = XEXP (bin_exp, 0);
 
-  start_sequence ();
+  if (CONST_INT_P (*to_replace))
+    {
+      non_zero_op = gen_reg_rtx (mode);
+      noce_emit_move_insn (non_zero_op, *to_replace);
+    }
+  else
+    non_zero_op = *to_replace;
 
   /* If x is used in both input and out like x = c ? x + z : x,
      use a new reg to avoid modifying x  */
@@ -3076,7 +3095,21 @@ noce_try_cond_zero_arith (struct noce_if_info *if_info)
       return false;
     }
 
-  *to_replace = target;
+  if (CONST_INT_P (*to_replace))
+    {
+      if (noce_cond_zero_shift_op_supported (bin_code))
+       {
+         *to_replace = gen_rtx_SUBREG (E_QImode, target, 0);
+         if (GET_CODE (a) == ZERO_EXTEND && bin_code == LSHIFTRT)
+           PUT_CODE (a, SIGN_EXTEND);
+       }
+      else if (SUBREG_P (bin_op0))
+       *to_replace = gen_rtx_SUBREG (GET_MODE (bin_op0), target, 0);
+      else
+       *to_replace = target;
+    }
+  else
+    *to_replace = target;
   emit_insn (gen_rtx_SET (if_info->x, a));
 
   seq = end_ifcvt_sequence (if_info);
diff --git a/gcc/testsuite/gcc.target/riscv/zicond_ifcvt_opt.c 
b/gcc/testsuite/gcc.target/riscv/zicond_ifcvt_opt.c
index 9357f26d978..c6b0518968b 100644
--- a/gcc/testsuite/gcc.target/riscv/zicond_ifcvt_opt.c
+++ b/gcc/testsuite/gcc.target/riscv/zicond_ifcvt_opt.c
@@ -678,5 +678,676 @@ test_RotateR_eqz_int (unsigned int x, unsigned int y, 
unsigned int z,
   return x;
 }
 
-/* { dg-final { scan-assembler-times {czero\.eqz} 39 } } */
-/* { dg-final { scan-assembler-times {czero\.nez} 28 } } */
+long
+test_ADD_ceqz_imm (long x, long y, long c)
+{
+  if (c)
+    x = y + 11;
+  else
+    x = y;
+  return x;
+}
+
+long
+test_ADD_ceqz_x_imm (long x, long c)
+{
+  if (c)
+    x = x + 11;
+
+  return x;
+}
+
+long
+test_ADD_nez_imm (long x, long y, long c)
+{
+  if (c)
+    x = y;
+  else
+    x = y + 11;
+  return x;
+}
+
+long
+test_ADD_nez_x_imm (long x, long c)
+{
+  if (c)
+    {
+    }
+  else
+    x = x + 11;
+  return x;
+}
+
+long
+test_ADD_nez_2_imm (long x, long y, long c)
+{
+  if (!c)
+    x = y + 11;
+  else
+    x = y;
+  return x;
+}
+
+long
+test_ADD_nez_x_2_imm (long x, long c)
+{
+  if (!c)
+    x = x + 11;
+
+  return x;
+}
+
+long
+test_ADD_eqz_2_imm (long x, long y, long c)
+{
+  if (!c)
+    x = y;
+  else
+    x = y + 11;
+  return x;
+}
+
+long
+test_ADD_eqz_x_2_imm (long x, long c)
+{
+  if (!c)
+    {
+    }
+  else
+    x = x + 11;
+  return x;
+}
+
+long
+test_SUB_ceqz_imm (long x, long y, long c)
+{
+  if (c)
+    x = y - 11;
+  else
+    x = y;
+  return x;
+}
+
+long
+test_SUB_ceqz_x_imm (long x, long c)
+{
+  if (c)
+    x = x - 11;
+
+  return x;
+}
+
+long
+test_SUB_nez_imm (long x, long y, long c)
+{
+  if (c)
+    x = y;
+  else
+    x = y - 11;
+  return x;
+}
+
+long
+test_SUB_nez_x_imm (long x, long c)
+{
+  if (c)
+    {
+    }
+  else
+    x = x - 11;
+  return x;
+}
+
+long
+test_SUB_nez_2_imm (long x, long y, long c)
+{
+  if (!c)
+    x = y - 11;
+  else
+    x = y;
+  return x;
+}
+
+long
+test_SUB_nez_x_2_imm (long x, long c)
+{
+  if (!c)
+    x = x - 11;
+
+  return x;
+}
+
+long
+test_SUB_eqz_2_imm (long x, long y, long c)
+{
+  if (!c)
+    x = y;
+  else
+    x = y - 11;
+  return x;
+}
+
+long
+test_SUB_eqz_x_2_imm (long x, long c)
+{
+  if (!c)
+    {
+    }
+  else
+    x = x - 11;
+  return x;
+}
+
+long
+test_IOR_ceqz_imm (long x, long y, long c)
+{
+  if (c)
+    x = y | 11;
+  else
+    x = y;
+  return x;
+}
+
+long
+test_IOR_ceqz_x_imm (long x, long c)
+{
+  if (c)
+    x = x | 11;
+
+  return x;
+}
+
+long
+test_IOR_nez_imm (long x, long y, long c)
+{
+  if (c)
+    x = y;
+  else
+    x = y | 11;
+  return x;
+}
+
+long
+test_IOR_nez_x_imm (long x, long c)
+{
+  if (c)
+    {
+    }
+  else
+    x = x | 11;
+  return x;
+}
+
+long
+test_IOR_nez_2_imm (long x, long y, long c)
+{
+  if (!c)
+    x = y | 11;
+  else
+    x = y;
+  return x;
+}
+
+long
+test_IOR_nez_x_2_imm (long x, long c)
+{
+  if (!c)
+    x = x | 11;
+
+  return x;
+}
+
+long
+test_IOR_eqz_2_imm (long x, long y, long c)
+{
+  if (!c)
+    x = y;
+  else
+    x = y | 11;
+  return x;
+}
+
+long
+test_IOR_eqz_x_2_imm (long x, long c)
+{
+  if (!c)
+    {
+    }
+  else
+    x = x | 11;
+  return x;
+}
+
+long
+test_XOR_ceqz_imm (long x, long y, long c)
+{
+  if (c)
+    x = y ^ 11;
+  else
+    x = y;
+  return x;
+}
+
+long
+test_XOR_ceqz_x_imm (long x, long c)
+{
+  if (c)
+    x = x ^ 11;
+
+  return x;
+}
+
+long
+test_XOR_nez_imm (long x, long y, long c)
+{
+  if (c)
+    x = y;
+  else
+    x = y ^ 11;
+  return x;
+}
+
+long
+test_XOR_nez_x_imm (long x, long c)
+{
+  if (c)
+    {
+    }
+  else
+    x = x ^ 11;
+  return x;
+}
+
+long
+test_XOR_nez_2_imm (long x, long y, long c)
+{
+  if (!c)
+    x = y ^ 11;
+  else
+    x = y;
+  return x;
+}
+
+long
+test_XOR_nez_x_2_imm (long x, long c)
+{
+  if (!c)
+    x = x ^ 11;
+
+  return x;
+}
+
+long
+test_XOR_eqz_2_imm (long x, long y, long c)
+{
+  if (!c)
+    x = y;
+  else
+    x = y ^ 11;
+  return x;
+}
+
+long
+test_XOR_eqz_x_2_imm (long x, long c)
+{
+  if (!c)
+    {
+    }
+  else
+    x = x ^ 11;
+  return x;
+}
+
+long
+test_ADD_ceqz_imm_reverse_bin_oprands (long x, long y, long c)
+{
+  if (c)
+    x = 11 + y;
+  else
+    x = y;
+  return x;
+}
+
+long
+test_ADD_ceqz_x_imm_reverse_bin_oprands (long x, long c)
+{
+  if (c)
+    x = 11 + x;
+
+  return x;
+}
+
+long
+test_ADD_nez_imm_reverse_bin_oprands (long x, long y, long c)
+{
+  if (c)
+    x = y;
+  else
+    x = 11 + y;
+  return x;
+}
+
+long
+test_ADD_nez_x_imm_reverse_bin_oprands (long x, long c)
+{
+  if (c)
+    {
+    }
+  else
+    x = 11 + x;
+  return x;
+}
+
+long
+test_ADD_nez_2_imm_reverse_bin_oprands (long x, long y, long c)
+{
+  if (!c)
+    x = 11 + y;
+  else
+    x = y;
+  return x;
+}
+
+long
+test_ADD_nez_x_2_imm_reverse_bin_oprands (long x, long c)
+{
+  if (!c)
+    x = 11 + x;
+
+  return x;
+}
+
+long
+test_ADD_eqz_2_imm_reverse_bin_oprands (long x, long y, long c)
+{
+  if (!c)
+    x = y;
+  else
+    x = 11 + y;
+  return x;
+}
+
+long
+test_ADD_eqz_x_2_imm_reverse_bin_oprands (long x, long c)
+{
+  if (!c)
+    {
+    }
+  else
+    x = 11 + x;
+  return x;
+}
+
+long
+test_IOR_ceqz_imm_reverse_bin_oprands (long x, long y, long c)
+{
+  if (c)
+    x = 11 | y;
+  else
+    x = y;
+  return x;
+}
+
+long
+test_IOR_ceqz_x_imm_reverse_bin_oprands (long x, long c)
+{
+  if (c)
+    x = 11 | x;
+
+  return x;
+}
+
+long
+test_IOR_nez_imm_reverse_bin_oprands (long x, long y, long c)
+{
+  if (c)
+    x = y;
+  else
+    x = 11 | y;
+  return x;
+}
+
+long
+test_IOR_nez_x_imm_reverse_bin_oprands (long x, long c)
+{
+  if (c)
+    {
+    }
+  else
+    x = 11 | x;
+  return x;
+}
+
+long
+test_IOR_nez_2_imm_reverse_bin_oprands (long x, long y, long c)
+{
+  if (!c)
+    x = 11 | y;
+  else
+    x = y;
+  return x;
+}
+
+long
+test_IOR_nez_x_2_imm_reverse_bin_oprands (long x, long c)
+{
+  if (!c)
+    x = 11 | x;
+
+  return x;
+}
+
+long
+test_IOR_eqz_2_imm_reverse_bin_oprands (long x, long y, long c)
+{
+  if (!c)
+    x = y;
+  else
+    x = 11 | y;
+  return x;
+}
+
+long
+test_IOR_eqz_x_2_imm_reverse_bin_oprands (long x, long c)
+{
+  if (!c)
+    {
+    }
+  else
+    x = 11 | x;
+  return x;
+}
+
+long
+test_XOR_ceqz_imm_reverse_bin_oprands (long x, long y, long c)
+{
+  if (c)
+    x = 11 ^ y;
+  else
+    x = y;
+  return x;
+}
+
+long
+test_XOR_ceqz_x_imm_reverse_bin_oprands (long x, long c)
+{
+  if (c)
+    x = 11 ^ x;
+
+  return x;
+}
+
+long
+test_XOR_nez_imm_reverse_bin_oprands (long x, long y, long c)
+{
+  if (c)
+    x = y;
+  else
+    x = 11 ^ y;
+  return x;
+}
+
+long
+test_XOR_nez_x_imm_reverse_bin_oprands (long x, long c)
+{
+  if (c)
+    {
+    }
+  else
+    x = 11 ^ x;
+  return x;
+}
+
+long
+test_XOR_nez_2_imm_reverse_bin_oprands (long x, long y, long c)
+{
+  if (!c)
+    x = 11 ^ y;
+  else
+    x = y;
+  return x;
+}
+
+long
+test_XOR_nez_x_2_imm_reverse_bin_oprands (long x, long c)
+{
+  if (!c)
+    x = 11 ^ x;
+
+  return x;
+}
+
+long
+test_XOR_eqz_2_imm_reverse_bin_oprands (long x, long y, long c)
+{
+  if (!c)
+    x = y;
+  else
+    x = 11 ^ y;
+  return x;
+}
+
+long
+test_XOR_eqz_x_2_imm_reverse_bin_oprands (long x, long c)
+{
+  if (!c)
+    {
+    }
+  else
+    x = 11 ^ x;
+  return x;
+}
+
+long
+test_ShiftLeft_eqz_imm (long x, long y, long c)
+{
+  if (c)
+    x = y << 11;
+  else
+    x = y;
+  return x;
+}
+
+long
+test_ShiftR_eqz_imm (long x, long y, long c)
+{
+  if (c)
+    x = y >> 11;
+  else
+    x = y;
+  return x;
+}
+
+unsigned long
+test_ShiftR_logical_eqz_imm (unsigned long x, unsigned long y, unsigned long z,
+                            unsigned long c)
+{
+  if (c)
+    x = y >> 11;
+  else
+    x = y;
+  return x;
+}
+
+unsigned long
+test_RotateL_eqz_imm (unsigned long x, unsigned long y, unsigned long c)
+{
+  if (c)
+    x = (y << 11) | (y >> (64 - 11));
+  else
+    x = y;
+  return x;
+}
+
+unsigned long
+test_RotateR_eqz_imm (unsigned long x, unsigned long y, unsigned long c)
+{
+  if (c)
+    x = (y >> 11) | (y << (64 - 11));
+  else
+    x = y;
+  return x;
+}
+
+int
+test_ADD_ceqz_imm_int (int x, int y, int c)
+{
+  if (c)
+    x = y + 11;
+  else
+    x = y;
+  return x;
+}
+
+int
+test_ShiftLeft_eqz_imm_int (int x, int y, int c)
+{
+  if (c)
+    x = y << 11;
+  else
+    x = y;
+  return x;
+}
+
+int
+test_ShiftR_eqz_imm_int (int x, int y, int c)
+{
+  if (c)
+    x = y >> 11;
+  else
+    x = y;
+  return x;
+}
+
+unsigned int
+test_ShiftR_logical_eqz_imm_int (unsigned int x, unsigned int y, unsigned int 
c)
+{
+  if (c)
+    x = y >> 11;
+  else
+    x = y;
+  return x;
+}
+
+unsigned int
+test_RotateL_eqz_imm_int (unsigned int x, unsigned int y, unsigned int c)
+{
+  if (c)
+    x = (y << 11) | (y >> (32 - 11));
+  else
+    x = y;
+  return x;
+}
+
+unsigned int
+test_RotateR_eqz_imm_int (unsigned int x, unsigned int y, unsigned int c)
+{
+  if (c)
+    x = (y >> 11) | (y << (32 - 11));
+  else
+    x = y;
+  return x;
+}
+
+/* { dg-final { scan-assembler-times {czero\.eqz} 78 } } */
+/* { dg-final { scan-assembler-times {czero\.nez} 56 } } */
-- 
2.17.1

Reply via email to