public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH 1/5][V3][ifcvt] optimize x=c ? (y op z) : y by RISC-V Zicond like insns
@ 2023-12-05  8:12 Fei Gao
  2023-12-05  8:12 ` [PATCH 2/5] [ifcvt] optimize x=c ? (y shift_op z):y " Fei Gao
                   ` (4 more replies)
  0 siblings, 5 replies; 14+ messages in thread
From: Fei Gao @ 2023-12-05  8:12 UTC (permalink / raw)
  To: gcc-patches; +Cc: kito.cheng, palmer, jeffreyalaw, zengxiao, Fei Gao

op=[PLUS, MINUS, IOR, XOR]

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<zengxiao@eswincomputing.com>

gcc/ChangeLog:

	* ifcvt.cc (noce_try_cond_zero_arith):handler for condtional zero based ifcvt
        (noce_emit_czero): helper for noce_try_cond_zero_arith
        (noce_cond_zero_binary_op_supported): check supported OPs for condtional zero based ifcvt
        (get_base_reg): get the reg itself or NULL_RTX if not a reg
        (noce_bbs_ok_for_cond_zero_arith): check if BBs are OK for condtional zero based ifcvt
        (noce_process_if_block): add noce_try_cond_zero_arith

gcc/testsuite/ChangeLog:

	* gcc.target/riscv/zicond_ifcvt_opt.c: New test.
---
 gcc/ifcvt.cc                                  | 187 ++++++
 .../gcc.target/riscv/zicond_ifcvt_opt.c       | 566 ++++++++++++++++++
 2 files changed, 753 insertions(+)
 create mode 100644 gcc/testsuite/gcc.target/riscv/zicond_ifcvt_opt.c

diff --git a/gcc/ifcvt.cc b/gcc/ifcvt.cc
index a0af553b9ff..1f0f5414ea1 100644
--- a/gcc/ifcvt.cc
+++ b/gcc/ifcvt.cc
@@ -787,6 +787,7 @@ static rtx noce_get_alt_condition (struct noce_if_info *, rtx, rtx_insn **);
 static bool noce_try_minmax (struct noce_if_info *);
 static bool noce_try_abs (struct noce_if_info *);
 static bool noce_try_sign_mask (struct noce_if_info *);
+static int noce_try_cond_zero_arith (struct noce_if_info *);
 
 /* Return the comparison code for reversed condition for IF_INFO,
    or UNKNOWN if reversing the condition is not possible.  */
@@ -1831,6 +1832,35 @@ noce_emit_cmove (struct noce_if_info *if_info, rtx x, enum rtx_code code,
     return NULL_RTX;
 }
 
+/*  Emit a conditional zero, returning TARGET or NULL_RTX upon failure.
+    IF_INFO describes the if-conversion scenario under consideration.
+    CZERO_CODE selects the condition (EQ/NE).
+    NON_ZERO_OP is the nonzero operand of the conditional move
+    TARGET is the desired output register.  */
+
+static rtx
+noce_emit_czero (struct noce_if_info *if_info, enum rtx_code czero_code,
+		 rtx non_zero_op, rtx target)
+{
+  machine_mode mode = GET_MODE (target);
+  rtx cond_op0 = XEXP (if_info->cond, 0);
+  rtx czero_cond
+    = gen_rtx_fmt_ee (czero_code, GET_MODE (cond_op0), cond_op0, const0_rtx);
+  rtx if_then_else
+    = gen_rtx_IF_THEN_ELSE (mode, czero_cond, const0_rtx, non_zero_op);
+  rtx set = gen_rtx_SET (target, if_then_else);
+
+  rtx_insn *insn = make_insn_raw (set);
+
+  if (recog_memoized (insn) >= 0)
+    {
+      add_insn (insn);
+      return target;
+    }
+
+  return NULL_RTX;
+}
+
 /* Try only simple constants and registers here.  More complex cases
    are handled in noce_try_cmove_arith after noce_try_store_flag_arith
    has had a go at it.  */
@@ -2880,6 +2910,160 @@ noce_try_sign_mask (struct noce_if_info *if_info)
   return true;
 }
 
+/*  Check if OP is supported by conditional zero based if conversion,
+    returning TRUE if satisfied otherwise FALSE.
+
+    OP is the operation to check.  */
+
+static bool
+noce_cond_zero_binary_op_supported (rtx op)
+{
+  enum rtx_code opcode = GET_CODE (op);
+
+  if (opcode == PLUS || opcode == MINUS || opcode == IOR || opcode == XOR)
+    return true;
+
+  return false;
+}
+
+/*  Helper function to return REG itself,
+    otherwise NULL_RTX for other RTX_CODE.  */
+
+static rtx
+get_base_reg (rtx exp)
+{
+  if (REG_P (exp))
+    return exp;
+
+  return NULL_RTX;
+}
+
+/*  Check if IF-BB and THEN-BB satisfy the condition for conditional zero
+    based if conversion, returning TRUE if satisfied otherwise FALSE.
+
+    IF_INFO describes the if-conversion scenario under consideration.
+    COMMON_PTR points to the common REG of canonicalized IF_INFO->A and
+    IF_INFO->B.
+    CZERO_CODE_PTR points to the comparison code to use in czero RTX.
+    A_PTR points to the A expression of canonicalized IF_INFO->A.
+    TO_REPLACE points to the RTX to be replaced by czero RTX destnation.  */
+
+static bool
+noce_bbs_ok_for_cond_zero_arith (struct noce_if_info *if_info, rtx *common_ptr,
+				 enum rtx_code *czero_code_ptr, rtx *a_ptr,
+				 rtx **to_replace)
+{
+  rtx common = NULL_RTX;
+  rtx cond = if_info->cond;
+  rtx a = copy_rtx (if_info->a);
+  rtx b = copy_rtx (if_info->b);
+  rtx bin_op1 = NULL_RTX;
+  enum rtx_code czero_code = UNKNOWN;
+  bool reverse = false;
+  rtx op0, op1, bin_exp;
+
+  if (!noce_simple_bbs (if_info))
+    return false;
+
+  /* COND must be EQ or NE comparision of a reg and 0.  */
+  if (GET_CODE (cond) != NE && GET_CODE (cond) != EQ)
+    return false;
+  if (!REG_P (XEXP (cond, 0)) || !rtx_equal_p (XEXP (cond, 1), const0_rtx))
+    return false;
+
+  /* Canonicalize x = y : (y op z) to x = (y op z) : y.  */
+  if (REG_P (a) && noce_cond_zero_binary_op_supported (b))
+    {
+      std::swap (a, b);
+      reverse = !reverse;
+    }
+
+  /* Check if x = (y op z) : y is supported by czero based ifcvt.  */
+  if (!(noce_cond_zero_binary_op_supported (a) && REG_P (b)))
+    return false;
+
+  bin_exp = a;
+
+  /* Canonicalize x = (z op y) : y to x = (y op z) : y */
+  op1 = get_base_reg (XEXP (bin_exp, 1));
+  if (op1 && rtx_equal_p (op1, b) && COMMUTATIVE_ARITH_P (bin_exp))
+    std::swap (XEXP (bin_exp, 0), XEXP (bin_exp, 1));
+
+  op0 = get_base_reg (XEXP (bin_exp, 0));
+  if (op0 && rtx_equal_p (op0, b))
+    {
+      common = b;
+      bin_op1 = XEXP (bin_exp, 1);
+      czero_code = reverse
+		     ? noce_reversed_cond_code (if_info)
+		     : GET_CODE (cond);
+    }
+  else
+    return false;
+
+  if (czero_code == UNKNOWN)
+    return false;
+
+  if (REG_P (bin_op1))
+    *to_replace = &XEXP (bin_exp, 1);
+  else
+    return false;
+
+  *common_ptr = common;
+  *czero_code_ptr = czero_code;
+  *a_ptr = a;
+
+  return true;
+}
+
+/*  Try to covert if-then-else with conditional zero,
+    returning TURE on success or FALSE on failure.
+    IF_INFO describes the if-conversion scenario under consideration.  */
+
+static int
+noce_try_cond_zero_arith (struct noce_if_info *if_info)
+{
+  rtx target, a;
+  rtx_insn *seq;
+  machine_mode mode = GET_MODE (if_info->x);
+  rtx common = NULL_RTX;
+  enum rtx_code czero_code = UNKNOWN;
+  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))
+    return false;
+
+  non_zero_op = *to_replace;
+
+  start_sequence ();
+
+  /* If x is used in both input and out like x = c ? x + z : x,
+     use a new reg to avoid modifying x  */
+  if (common && rtx_equal_p (common, if_info->x))
+    target = gen_reg_rtx (mode);
+  else
+    target = if_info->x;
+
+  target = noce_emit_czero (if_info, czero_code, non_zero_op, target);
+  if (!target || !to_replace)
+    {
+      end_sequence ();
+      return false;
+    }
+
+  *to_replace = target;
+  noce_emit_move_insn (if_info->x, a);
+
+  seq = end_ifcvt_sequence (if_info);
+  if (!seq || !targetm.noce_conversion_profitable_p (seq, if_info))
+    return false;
+
+  emit_insn_before_setloc (seq, if_info->jump, INSN_LOCATION (if_info->insn_a));
+  if_info->transform_name = "noce_try_cond_zero_arith";
+  return true;
+}
 
 /* Optimize away "if (x & C) x |= C" and similar bit manipulation
    transformations.  */
@@ -3975,6 +4159,9 @@ noce_process_if_block (struct noce_if_info *if_info)
 	goto success;
       if (noce_try_store_flag_mask (if_info))
 	goto success;
+      if (HAVE_conditional_move
+          && noce_try_cond_zero_arith (if_info))
+	goto success;
       if (HAVE_conditional_move
 	  && noce_try_cmove_arith (if_info))
 	goto success;
diff --git a/gcc/testsuite/gcc.target/riscv/zicond_ifcvt_opt.c b/gcc/testsuite/gcc.target/riscv/zicond_ifcvt_opt.c
new file mode 100644
index 00000000000..dcb21c15d1a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/zicond_ifcvt_opt.c
@@ -0,0 +1,566 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gc_zbb_zicond -mabi=lp64d -O2 " } */
+/* { dg-skip-if "" { *-*-* } {"-O0" "-O1" "-Os" "-Og" "-O3" "-Oz" "-flto"} } */
+
+long
+test_ADD_ceqz (long x, long y, long z, long c)
+{
+  if (c)
+    x = y + z;
+  else
+    x = y;
+  return x;
+}
+
+long
+test_ADD_ceqz_x (long x, long z, long c)
+{
+  if (c)
+    x = x + z;
+
+  return x;
+}
+
+long
+test_ADD_nez (long x, long y, long z, long c)
+{
+  if (c)
+    x = y;
+  else
+    x = y + z;
+  return x;
+}
+
+long
+test_ADD_nez_x (long x, long z, long c)
+{
+  if (c)
+    {
+    }
+  else
+    x = x + z;
+  return x;
+}
+
+long
+test_ADD_nez_2 (long x, long y, long z, long c)
+{
+  if (!c)
+    x = y + z;
+  else
+    x = y;
+  return x;
+}
+
+long
+test_ADD_nez_x_2 (long x, long z, long c)
+{
+  if (!c)
+    x = x + z;
+
+  return x;
+}
+
+long
+test_ADD_eqz_2 (long x, long y, long z, long c)
+{
+  if (!c)
+    x = y;
+  else
+    x = y + z;
+  return x;
+}
+
+long
+test_ADD_eqz_x_2 (long x, long z, long c)
+{
+  if (!c)
+    {
+    }
+  else
+    x = x + z;
+  return x;
+}
+
+long
+test_SUB_ceqz (long x, long y, long z, long c)
+{
+  if (c)
+    x = y - z;
+  else
+    x = y;
+  return x;
+}
+
+long
+test_SUB_ceqz_x (long x, long z, long c)
+{
+  if (c)
+    x = x - z;
+
+  return x;
+}
+
+long
+test_SUB_nez (long x, long y, long z, long c)
+{
+  if (c)
+    x = y;
+  else
+    x = y - z;
+  return x;
+}
+
+long
+test_SUB_nez_x (long x, long z, long c)
+{
+  if (c)
+    {
+    }
+  else
+    x = x - z;
+  return x;
+}
+
+long
+test_SUB_nez_2 (long x, long y, long z, long c)
+{
+  if (!c)
+    x = y - z;
+  else
+    x = y;
+  return x;
+}
+
+long
+test_SUB_nez_x_2 (long x, long z, long c)
+{
+  if (!c)
+    x = x - z;
+
+  return x;
+}
+
+long
+test_SUB_eqz_2 (long x, long y, long z, long c)
+{
+  if (!c)
+    x = y;
+  else
+    x = y - z;
+  return x;
+}
+
+long
+test_SUB_eqz_x_2 (long x, long z, long c)
+{
+  if (!c)
+    {
+    }
+  else
+    x = x - z;
+  return x;
+}
+
+long
+test_IOR_ceqz (long x, long y, long z, long c)
+{
+  if (c)
+    x = y | z;
+  else
+    x = y;
+  return x;
+}
+
+long
+test_IOR_ceqz_x (long x, long z, long c)
+{
+  if (c)
+    x = x | z;
+
+  return x;
+}
+
+long
+test_IOR_nez (long x, long y, long z, long c)
+{
+  if (c)
+    x = y;
+  else
+    x = y | z;
+  return x;
+}
+
+long
+test_IOR_nez_x (long x, long z, long c)
+{
+  if (c)
+    {
+    }
+  else
+    x = x | z;
+  return x;
+}
+
+long
+test_IOR_nez_2 (long x, long y, long z, long c)
+{
+  if (!c)
+    x = y | z;
+  else
+    x = y;
+  return x;
+}
+
+long
+test_IOR_nez_x_2 (long x, long z, long c)
+{
+  if (!c)
+    x = x | z;
+
+  return x;
+}
+
+long
+test_IOR_eqz_2 (long x, long y, long z, long c)
+{
+  if (!c)
+    x = y;
+  else
+    x = y | z;
+  return x;
+}
+
+long
+test_IOR_eqz_x_2 (long x, long z, long c)
+{
+  if (!c)
+    {
+    }
+  else
+    x = x | z;
+  return x;
+}
+
+long
+test_XOR_ceqz (long x, long y, long z, long c)
+{
+  if (c)
+    x = y ^ z;
+  else
+    x = y;
+  return x;
+}
+
+long
+test_XOR_ceqz_x (long x, long z, long c)
+{
+  if (c)
+    x = x ^ z;
+
+  return x;
+}
+
+long
+test_XOR_nez (long x, long y, long z, long c)
+{
+  if (c)
+    x = y;
+  else
+    x = y ^ z;
+  return x;
+}
+
+long
+test_XOR_nez_x (long x, long z, long c)
+{
+  if (c)
+    {
+    }
+  else
+    x = x ^ z;
+  return x;
+}
+
+long
+test_XOR_nez_2 (long x, long y, long z, long c)
+{
+  if (!c)
+    x = y ^ z;
+  else
+    x = y;
+  return x;
+}
+
+long
+test_XOR_nez_x_2 (long x, long z, long c)
+{
+  if (!c)
+    x = x ^ z;
+
+  return x;
+}
+
+long
+test_XOR_eqz_2 (long x, long y, long z, long c)
+{
+  if (!c)
+    x = y;
+  else
+    x = y ^ z;
+  return x;
+}
+
+long
+test_XOR_eqz_x_2 (long x, long z, long c)
+{
+  if (!c)
+    {
+    }
+  else
+    x = x ^ z;
+  return x;
+}
+
+long
+test_ADD_ceqz_reverse_bin_oprands (long x, long y, long z, long c)
+{
+  if (c)
+    x = z + y;
+  else
+    x = y;
+  return x;
+}
+
+long
+test_ADD_ceqz_x_reverse_bin_oprands (long x, long z, long c)
+{
+  if (c)
+    x = z + x;
+
+  return x;
+}
+
+long
+test_ADD_nez_reverse_bin_oprands (long x, long y, long z, long c)
+{
+  if (c)
+    x = y;
+  else
+    x = z + y;
+  return x;
+}
+
+long
+test_ADD_nez_x_reverse_bin_oprands (long x, long z, long c)
+{
+  if (c)
+    {
+    }
+  else
+    x = z + x;
+  return x;
+}
+
+long
+test_ADD_nez_2_reverse_bin_oprands (long x, long y, long z, long c)
+{
+  if (!c)
+    x = z + y;
+  else
+    x = y;
+  return x;
+}
+
+long
+test_ADD_nez_x_2_reverse_bin_oprands (long x, long z, long c)
+{
+  if (!c)
+    x = z + x;
+
+  return x;
+}
+
+long
+test_ADD_eqz_2_reverse_bin_oprands (long x, long y, long z, long c)
+{
+  if (!c)
+    x = y;
+  else
+    x = z + y;
+  return x;
+}
+
+long
+test_ADD_eqz_x_2_reverse_bin_oprands (long x, long z, long c)
+{
+  if (!c)
+    {
+    }
+  else
+    x = z + x;
+  return x;
+}
+
+long
+test_IOR_ceqz_reverse_bin_oprands (long x, long y, long z, long c)
+{
+  if (c)
+    x = z | y;
+  else
+    x = y;
+  return x;
+}
+
+long
+test_IOR_ceqz_x_reverse_bin_oprands (long x, long z, long c)
+{
+  if (c)
+    x = z | x;
+
+  return x;
+}
+
+long
+test_IOR_nez_reverse_bin_oprands (long x, long y, long z, long c)
+{
+  if (c)
+    x = y;
+  else
+    x = z | y;
+  return x;
+}
+
+long
+test_IOR_nez_x_reverse_bin_oprands (long x, long z, long c)
+{
+  if (c)
+    {
+    }
+  else
+    x = z | x;
+  return x;
+}
+
+long
+test_IOR_nez_2_reverse_bin_oprands (long x, long y, long z, long c)
+{
+  if (!c)
+    x = z | y;
+  else
+    x = y;
+  return x;
+}
+
+long
+test_IOR_nez_x_2_reverse_bin_oprands (long x, long z, long c)
+{
+  if (!c)
+    x = z | x;
+
+  return x;
+}
+
+long
+test_IOR_eqz_2_reverse_bin_oprands (long x, long y, long z, long c)
+{
+  if (!c)
+    x = y;
+  else
+    x = z | y;
+  return x;
+}
+
+long
+test_IOR_eqz_x_2_reverse_bin_oprands (long x, long z, long c)
+{
+  if (!c)
+    {
+    }
+  else
+    x = z | x;
+  return x;
+}
+
+long
+test_XOR_ceqz_reverse_bin_oprands (long x, long y, long z, long c)
+{
+  if (c)
+    x = z ^ y;
+  else
+    x = y;
+  return x;
+}
+
+long
+test_XOR_ceqz_x_reverse_bin_oprands (long x, long z, long c)
+{
+  if (c)
+    x = z ^ x;
+
+  return x;
+}
+
+long
+test_XOR_nez_reverse_bin_oprands (long x, long y, long z, long c)
+{
+  if (c)
+    x = y;
+  else
+    x = z ^ y;
+  return x;
+}
+
+long
+test_XOR_nez_x_reverse_bin_oprands (long x, long z, long c)
+{
+  if (c)
+    {
+    }
+  else
+    x = z ^ x;
+  return x;
+}
+
+long
+test_XOR_nez_2_reverse_bin_oprands (long x, long y, long z, long c)
+{
+  if (!c)
+    x = z ^ y;
+  else
+    x = y;
+  return x;
+}
+
+long
+test_XOR_nez_x_2_reverse_bin_oprands (long x, long z, long c)
+{
+  if (!c)
+    x = z ^ x;
+
+  return x;
+}
+
+long
+test_XOR_eqz_2_reverse_bin_oprands (long x, long y, long z, long c)
+{
+  if (!c)
+    x = y;
+  else
+    x = z ^ y;
+  return x;
+}
+
+long
+test_XOR_eqz_x_2_reverse_bin_oprands (long x, long z, long c)
+{
+  if (!c)
+    {
+    }
+  else
+    x = z ^ x;
+  return x;
+}
+
+/* { dg-final { scan-assembler-times {czero\.eqz} 28 } } */
+/* { dg-final { scan-assembler-times {czero\.nez} 28 } } */
-- 
2.17.1


^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH 2/5] [ifcvt] optimize x=c ? (y shift_op z):y by RISC-V Zicond like insns
  2023-12-05  8:12 [PATCH 1/5][V3][ifcvt] optimize x=c ? (y op z) : y by RISC-V Zicond like insns Fei Gao
@ 2023-12-05  8:12 ` Fei Gao
  2023-12-10 20:43   ` Jeff Law
  2023-12-05  8:12 ` [PATCH 3/5] [ifcvt] optimize x=c ? (y AND z) : y " Fei Gao
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 14+ messages in thread
From: Fei Gao @ 2023-12-05  8:12 UTC (permalink / raw)
  To: gcc-patches; +Cc: kito.cheng, palmer, jeffreyalaw, zengxiao, Fei Gao

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<zengxiao@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


^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH 3/5] [ifcvt] optimize x=c ? (y AND z) : y by RISC-V Zicond like insns
  2023-12-05  8:12 [PATCH 1/5][V3][ifcvt] optimize x=c ? (y op z) : y by RISC-V Zicond like insns Fei Gao
  2023-12-05  8:12 ` [PATCH 2/5] [ifcvt] optimize x=c ? (y shift_op z):y " Fei Gao
@ 2023-12-05  8:12 ` Fei Gao
  2023-12-11  5:16   ` Jeff Law
  2023-12-05  8:12 ` [PATCH 4/5] [ifcvt] optimize x=c ? (y op const_int) " Fei Gao
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 14+ messages in thread
From: Fei Gao @ 2023-12-05  8:12 UTC (permalink / raw)
  To: gcc-patches; +Cc: kito.cheng, palmer, jeffreyalaw, zengxiao, Fei Gao

Take the following case for example.

CFLAGS: -march=rv64gc_zbb_zicond -mabi=lp64d -O2

long
test_AND_ceqz (long x, long y, long z, long c)
{
  if (c)
    x = y & z;
  else
    x = y;
  return x;
}

Before patch:

and	a2,a1,a2
czero.eqz	a0,a2,a3
czero.nez	a3,a1,a3
or	a0,a3,a0
ret

After patch:
and	a0,a1,a2
czero.nez	a1,a1,a3
or	a0,a1,a0
ret

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

gcc/ChangeLog:

	* ifcvt.cc (noce_cond_zero_binary_op_supported): Add support for AND.
        (noce_bbs_ok_for_cond_zero_arith): Likewise.
        (noce_try_cond_zero_arith): Likewise.

gcc/testsuite/ChangeLog:

	* gcc.target/riscv/zicond_ifcvt_opt.c: add TCs for AND.
---
 gcc/ifcvt.cc                                  |  69 ++++++--
 .../gcc.target/riscv/zicond_ifcvt_opt.c       | 163 +++++++++++++++++-
 2 files changed, 211 insertions(+), 21 deletions(-)

diff --git a/gcc/ifcvt.cc b/gcc/ifcvt.cc
index 2efae21ebfe..29f33f956eb 100644
--- a/gcc/ifcvt.cc
+++ b/gcc/ifcvt.cc
@@ -2922,7 +2922,7 @@ noce_cond_zero_binary_op_supported (rtx op)
 
   if (opcode == PLUS || opcode == MINUS || opcode == IOR || opcode == XOR
       || opcode == ASHIFT || opcode == ASHIFTRT || opcode == LSHIFTRT
-      || opcode == ROTATE || opcode == ROTATERT)
+      || opcode == ROTATE || opcode == ROTATERT || opcode == AND)
     return true;
 
   return false;
@@ -2954,6 +2954,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)
 {
@@ -2998,7 +2999,7 @@ noce_bbs_ok_for_cond_zero_arith (struct noce_if_info *if_info, rtx *common_ptr,
     {
       common = b;
       bin_op1 = XEXP (bin_exp, 1);
-      czero_code = reverse
+      czero_code = (reverse ^ (GET_CODE (bin_exp) == AND))
 		     ? noce_reversed_cond_code (if_info)
 		     : GET_CODE (cond);
     }
@@ -3016,6 +3017,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;
 
@@ -3029,38 +3031,67 @@ noce_bbs_ok_for_cond_zero_arith (struct noce_if_info *if_info, rtx *common_ptr,
 static int
 noce_try_cond_zero_arith (struct noce_if_info *if_info)
 {
-  rtx target, a;
+  rtx target, rtmp, a;
   rtx_insn *seq;
   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 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;
 
-  non_zero_op = *to_replace;
-
   start_sequence ();
 
-  /* If x is used in both input and out like x = c ? x + z : x,
-     use a new reg to avoid modifying x  */
-  if (common && rtx_equal_p (common, if_info->x))
-    target = gen_reg_rtx (mode);
-  else
-    target = if_info->x;
+  bin_code = GET_CODE (bin_exp);
 
-  target = noce_emit_czero (if_info, czero_code, non_zero_op, target);
-  if (!target || !to_replace)
+  if (bin_code == AND)
     {
-      end_sequence ();
-      return false;
+      rtmp = gen_reg_rtx (mode);
+      noce_emit_move_insn (rtmp, a);
+
+      target = noce_emit_czero (if_info, czero_code, common, if_info->x);
+      if (!target)
+	{
+	  end_sequence ();
+	  return false;
+	}
+
+      target = expand_simple_binop (mode, IOR, rtmp, target, if_info->x, 0,
+				    OPTAB_WIDEN);
+      if (!target)
+	{
+	  end_sequence ();
+	  return false;
+	}
+
+      if (target != if_info->x)
+	noce_emit_move_insn (if_info->x, target);
     }
+  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  */
+      if (common && rtx_equal_p (common, if_info->x))
+	target = gen_reg_rtx (mode);
+      else
+	target = if_info->x;
 
-  *to_replace = target;
-  noce_emit_move_insn (if_info->x, a);
+      target = noce_emit_czero (if_info, czero_code, non_zero_op, target);
+      if (!target || !to_replace)
+	{
+	  end_sequence ();
+	  return false;
+	}
+
+      *to_replace = target;
+      noce_emit_move_insn (if_info->x, a);
+    }
 
   seq = end_ifcvt_sequence (if_info);
   if (!seq || !targetm.noce_conversion_profitable_p (seq, 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 ab5a4909b61..d5310690539 100644
--- a/gcc/testsuite/gcc.target/riscv/zicond_ifcvt_opt.c
+++ b/gcc/testsuite/gcc.target/riscv/zicond_ifcvt_opt.c
@@ -615,5 +615,164 @@ test_RotateR_eqz (unsigned long x, unsigned long y, unsigned long z,
   return x;
 }
 
-/* { dg-final { scan-assembler-times {czero\.eqz} 33 } } */
-/* { dg-final { scan-assembler-times {czero\.nez} 28 } } */
+long
+test_AND_ceqz (long x, long y, long z, long c)
+{
+  if (c)
+    x = y & z;
+  else
+    x = y;
+  return x;
+}
+
+long
+test_AND_ceqz_x (long x, long z, long c)
+{
+  if (c)
+    x = x & z;
+
+  return x;
+}
+
+long
+test_AND_nez (long x, long y, long z, long c)
+{
+  if (c)
+    x = y;
+  else
+    x = y & z;
+  return x;
+}
+
+long
+test_AND_nez_x (long x, long z, long c)
+{
+  if (c)
+    {
+    }
+  else
+    x = x & z;
+  return x;
+}
+
+long
+test_AND_nez_2 (long x, long y, long z, long c)
+{
+  if (!c)
+    x = y & z;
+  else
+    x = y;
+  return x;
+}
+
+long
+test_AND_nez_x_2 (long x, long z, long c)
+{
+  if (!c)
+    x = x & z;
+
+  return x;
+}
+
+long
+test_AND_eqz_2 (long x, long y, long z, long c)
+{
+  if (!c)
+    x = y;
+  else
+    x = y & z;
+  return x;
+}
+
+long
+test_AND_eqz_x_2 (long x, long z, long c)
+{
+  if (!c)
+    {
+    }
+  else
+    x = x & z;
+  return x;
+}
+
+long
+test_AND_ceqz_reverse_bin_oprands (long x, long y, long z, long c)
+{
+  if (c)
+    x = z & y;
+  else
+    x = y;
+  return x;
+}
+
+long
+test_AND_ceqz_x_reverse_bin_oprands (long x, long z, long c)
+{
+  if (c)
+    x = z & x;
+
+  return x;
+}
+
+long
+test_AND_nez_reverse_bin_oprands (long x, long y, long z, long c)
+{
+  if (c)
+    x = y;
+  else
+    x = z & y;
+  return x;
+}
+
+long
+test_AND_nez_x_reverse_bin_oprands (long x, long z, long c)
+{
+  if (c)
+    {
+    }
+  else
+    x = z & x;
+  return x;
+}
+
+long
+test_AND_nez_2_reverse_bin_oprands (long x, long y, long z, long c)
+{
+  if (!c)
+    x = z & y;
+  else
+    x = y;
+  return x;
+}
+
+long
+test_AND_nez_x_2_reverse_bin_oprands (long x, long z, long c)
+{
+  if (!c)
+    x = z & x;
+
+  return x;
+}
+
+long
+test_AND_eqz_2_reverse_bin_oprands (long x, long y, long z, long c)
+{
+  if (!c)
+    x = y;
+  else
+    x = z & y;
+  return x;
+}
+
+long
+test_AND_eqz_x_2_reverse_bin_oprands (long x, long z, long c)
+{
+  if (!c)
+    {
+    }
+  else
+    x = z & x;
+  return x;
+}
+/* { dg-final { scan-assembler-times {czero\.eqz} 41 } } */
+/* { dg-final { scan-assembler-times {czero\.nez} 36 } } */
-- 
2.17.1


^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH 4/5] [ifcvt] optimize x=c ? (y op const_int) : y by RISC-V Zicond like insns
  2023-12-05  8:12 [PATCH 1/5][V3][ifcvt] optimize x=c ? (y op z) : y by RISC-V Zicond like insns Fei Gao
  2023-12-05  8:12 ` [PATCH 2/5] [ifcvt] optimize x=c ? (y shift_op z):y " Fei Gao
  2023-12-05  8:12 ` [PATCH 3/5] [ifcvt] optimize x=c ? (y AND z) : y " Fei Gao
@ 2023-12-05  8:12 ` Fei Gao
  2023-12-11  5:38   ` Jeff Law
  2023-12-05  8:12 ` [PATCH 5/5] [ifcvt] optimize extension for x=c ? (y op z) " Fei Gao
  2023-12-08  0:49 ` [PATCH 1/5][V3][ifcvt] optimize " Jeff Law
  4 siblings, 1 reply; 14+ messages in thread
From: Fei Gao @ 2023-12-05  8:12 UTC (permalink / raw)
  To: gcc-patches; +Cc: kito.cheng, palmer, jeffreyalaw, zengxiao, Fei Gao

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

Co-authored-by: Xiao Zeng<zengxiao@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 support for const_int
        (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                                  |  45 +-
 .../gcc.target/riscv/zicond_ifcvt_opt.c       | 774 +++++++++++++++++-
 2 files changed, 811 insertions(+), 8 deletions(-)

diff --git a/gcc/ifcvt.cc b/gcc/ifcvt.cc
index 29f33f956eb..b84be53ec5c 100644
--- a/gcc/ifcvt.cc
+++ b/gcc/ifcvt.cc
@@ -2910,6 +2910,20 @@ noce_try_sign_mask (struct noce_if_info *if_info)
   return true;
 }
 
+/*  Check if OP is shift-like operation supported by conditional zero
+    based if conversion, returning TRUE if satisfied otherwise FALSE.
+
+    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;
+}
+
 /*  Check if OP is supported by conditional zero based if conversion,
     returning TRUE if satisfied otherwise FALSE.
 
@@ -2921,8 +2935,7 @@ noce_cond_zero_binary_op_supported (rtx op)
   enum rtx_code opcode = GET_CODE (op);
 
   if (opcode == PLUS || opcode == MINUS || opcode == IOR || opcode == XOR
-      || opcode == ASHIFT || opcode == ASHIFTRT || opcode == LSHIFTRT
-      || opcode == ROTATE || opcode == ROTATERT || opcode == AND)
+      || opcode == AND || noce_cond_zero_shift_op_supported (opcode))
     return true;
 
   return false;
@@ -3009,7 +3022,7 @@ noce_bbs_ok_for_cond_zero_arith (struct noce_if_info *if_info, rtx *common_ptr,
   if (czero_code == UNKNOWN)
     return false;
 
-  if (REG_P (bin_op1))
+  if (CONST_INT_P (bin_op1) || REG_P (bin_op1))
     *to_replace = &XEXP (bin_exp, 1);
   else if (SUBREG_P (bin_op1))
     *to_replace = &SUBREG_REG (XEXP (bin_exp, 1));
@@ -3038,6 +3051,7 @@ noce_try_cond_zero_arith (struct noce_if_info *if_info)
   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;
 
@@ -3048,6 +3062,7 @@ noce_try_cond_zero_arith (struct noce_if_info *if_info)
   start_sequence ();
 
   bin_code = GET_CODE (bin_exp);
+  bin_op0 = XEXP (bin_exp, 0);
 
   if (bin_code == AND)
     {
@@ -3074,9 +3089,16 @@ noce_try_cond_zero_arith (struct noce_if_info *if_info)
     }
   else
     {
-      non_zero_op = *to_replace;
+      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  */
+	     use a new reg to avoid modifying x  */
       if (common && rtx_equal_p (common, if_info->x))
 	target = gen_reg_rtx (mode);
       else
@@ -3089,7 +3111,18 @@ 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);
+	  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;
+
       noce_emit_move_insn (if_info->x, a);
     }
 
diff --git a/gcc/testsuite/gcc.target/riscv/zicond_ifcvt_opt.c b/gcc/testsuite/gcc.target/riscv/zicond_ifcvt_opt.c
index d5310690539..85743e1734c 100644
--- a/gcc/testsuite/gcc.target/riscv/zicond_ifcvt_opt.c
+++ b/gcc/testsuite/gcc.target/riscv/zicond_ifcvt_opt.c
@@ -615,6 +615,616 @@ test_RotateR_eqz (unsigned long x, unsigned long y, unsigned long z,
   return x;
 }
 
+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;
+}
 long
 test_AND_ceqz (long x, long y, long z, long c)
 {
@@ -774,5 +1384,165 @@ test_AND_eqz_x_2_reverse_bin_oprands (long x, long z, long c)
     x = z & x;
   return x;
 }
-/* { dg-final { scan-assembler-times {czero\.eqz} 41 } } */
-/* { dg-final { scan-assembler-times {czero\.nez} 36 } } */
+
+long
+test_AND_ceqz_imm (long x, long y, long c)
+{
+  if (c)
+    x = y & 11;
+  else
+    x = y;
+  return x;
+}
+
+long
+test_AND_ceqz_x_imm (long x, long c)
+{
+  if (c)
+    x = x & 11;
+
+  return x;
+}
+
+long
+test_AND_nez_imm (long x, long y, long c)
+{
+  if (c)
+    x = y;
+  else
+    x = y & 11;
+  return x;
+}
+
+long
+test_AND_nez_x_imm (long x, long c)
+{
+  if (c)
+    {
+    }
+  else
+    x = x & 11;
+  return x;
+}
+
+long
+test_AND_nez_2_imm (long x, long y, long c)
+{
+  if (!c)
+    x = y & 11;
+  else
+    x = y;
+  return x;
+}
+
+long
+test_AND_nez_x_2_imm (long x, long c)
+{
+  if (!c)
+    x = x & 11;
+
+  return x;
+}
+
+long
+test_AND_eqz_2_imm (long x, long y, long c)
+{
+  if (!c)
+    x = y;
+  else
+    x = y & 11;
+  return x;
+}
+
+long
+test_AND_eqz_x_2_imm (long x, long c)
+{
+  if (!c)
+    {
+    }
+  else
+    x = x & 11;
+  return x;
+}
+
+long
+test_AND_ceqz_imm_reverse_bin_oprands (long x, long y, long c)
+{
+  if (c)
+    x = 11 & y;
+  else
+    x = y;
+  return x;
+}
+
+long
+test_AND_ceqz_x_imm_reverse_bin_oprands (long x, long c)
+{
+  if (c)
+    x = 11 & x;
+
+  return x;
+}
+
+long
+test_AND_nez_imm_reverse_bin_oprands (long x, long y, long c)
+{
+  if (c)
+    x = y;
+  else
+    x = 11 & y;
+  return x;
+}
+
+long
+test_AND_nez_x_imm_reverse_bin_oprands (long x, long c)
+{
+  if (c)
+    {
+    }
+  else
+    x = 11 & x;
+  return x;
+}
+
+long
+test_AND_nez_2_imm_reverse_bin_oprands (long x, long y, long c)
+{
+  if (!c)
+    x = 11 & y;
+  else
+    x = y;
+  return x;
+}
+
+long
+test_AND_nez_x_2_imm_reverse_bin_oprands (long x, long c)
+{
+  if (!c)
+    x = 11 & x;
+
+  return x;
+}
+
+long
+test_AND_eqz_2_imm_reverse_bin_oprands (long x, long y, long c)
+{
+  if (!c)
+    x = y;
+  else
+    x = 11 & y;
+  return x;
+}
+
+long
+test_AND_eqz_x_2_imm_reverse_bin_oprands (long x, long c)
+{
+  if (!c)
+    {
+    }
+  else
+    x = 11 & x;
+  return x;
+}
+/* { dg-final { scan-assembler-times {czero\.eqz} 82 } } */
+/* { dg-final { scan-assembler-times {czero\.nez} 72 } } */
-- 
2.17.1


^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH 5/5] [ifcvt] optimize extension for x=c ? (y op z) : y by RISC-V Zicond like insns
  2023-12-05  8:12 [PATCH 1/5][V3][ifcvt] optimize x=c ? (y op z) : y by RISC-V Zicond like insns Fei Gao
                   ` (2 preceding siblings ...)
  2023-12-05  8:12 ` [PATCH 4/5] [ifcvt] optimize x=c ? (y op const_int) " Fei Gao
@ 2023-12-05  8:12 ` Fei Gao
  2023-12-11  5:46   ` Jeff Law
  2023-12-08  0:49 ` [PATCH 1/5][V3][ifcvt] optimize " Jeff Law
  4 siblings, 1 reply; 14+ messages in thread
From: Fei Gao @ 2023-12-05  8:12 UTC (permalink / raw)
  To: gcc-patches; +Cc: kito.cheng, palmer, jeffreyalaw, zengxiao, Fei Gao

SIGN_EXTEND, ZERO_EXTEND and SUBREG has been considered
to support SImode in 64-bit machine.

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

gcc/ChangeLog:

	* ifcvt.cc (noce_cond_zero_binary_op_supported): add support for extension
        (noce_bbs_ok_for_cond_zero_arith): likewise
        (noce_try_cond_zero_arith): support extension of LSHIFTRT case

gcc/testsuite/ChangeLog:

	* gcc.target/riscv/zicond_ifcvt_opt.c: add TCs for extension
---
 gcc/ifcvt.cc                                  |  16 ++-
 .../gcc.target/riscv/zicond_ifcvt_opt.c       | 126 +++++++++++++++++-
 2 files changed, 139 insertions(+), 3 deletions(-)

diff --git a/gcc/ifcvt.cc b/gcc/ifcvt.cc
index b84be53ec5c..306497a8e37 100644
--- a/gcc/ifcvt.cc
+++ b/gcc/ifcvt.cc
@@ -2934,6 +2934,10 @@ noce_cond_zero_binary_op_supported (rtx op)
 {
   enum rtx_code opcode = GET_CODE (op);
 
+  /* Strip SIGN_EXTEND or ZERO_EXTEND if any.  */
+  if (opcode == SIGN_EXTEND || opcode == ZERO_EXTEND)
+    opcode = GET_CODE (XEXP (op, 0));
+
   if (opcode == PLUS || opcode == MINUS || opcode == IOR || opcode == XOR
       || opcode == AND || noce_cond_zero_shift_op_supported (opcode))
     return true;
@@ -3000,7 +3004,11 @@ noce_bbs_ok_for_cond_zero_arith (struct noce_if_info *if_info, rtx *common_ptr,
   if (!(noce_cond_zero_binary_op_supported (a) && REG_P (b)))
     return false;
 
-  bin_exp = a;
+  /* Strip sign_extend if any.  */
+  if (GET_CODE (a) == SIGN_EXTEND || GET_CODE (a) == ZERO_EXTEND)
+    bin_exp = XEXP (a, 0);
+  else
+    bin_exp = a;
 
   /* Canonicalize x = (z op y) : y to x = (y op z) : y */
   op1 = get_base_reg (XEXP (bin_exp, 1));
@@ -3114,7 +3122,11 @@ noce_try_cond_zero_arith (struct noce_if_info *if_info)
       if (CONST_INT_P (*to_replace))
 	{
 	  if (noce_cond_zero_shift_op_supported (bin_code))
-	    *to_replace = gen_rtx_SUBREG (E_QImode, target, 0);
+	    {
+	      *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
diff --git a/gcc/testsuite/gcc.target/riscv/zicond_ifcvt_opt.c b/gcc/testsuite/gcc.target/riscv/zicond_ifcvt_opt.c
index 85743e1734c..53206d76e9f 100644
--- a/gcc/testsuite/gcc.target/riscv/zicond_ifcvt_opt.c
+++ b/gcc/testsuite/gcc.target/riscv/zicond_ifcvt_opt.c
@@ -615,6 +615,69 @@ test_RotateR_eqz (unsigned long x, unsigned long y, unsigned long z,
   return x;
 }
 
+int
+test_ADD_ceqz_int (int x, int y, int z, int c)
+{
+  if (c)
+    x = y + z;
+  else
+    x = y;
+  return x;
+}
+
+int
+test_ShiftLeft_eqz_int (int x, int y, int z, int c)
+{
+  if (c)
+    x = y << z;
+  else
+    x = y;
+  return x;
+}
+
+int
+test_ShiftR_eqz_int (int x, int y, int z, int c)
+{
+  if (c)
+    x = y >> z;
+  else
+    x = y;
+  return x;
+}
+
+unsigned int
+test_ShiftR_logical_eqz_int (unsigned int x, unsigned int y, unsigned int z,
+			     unsigned int c)
+{
+  if (c)
+    x = y >> z;
+  else
+    x = y;
+  return x;
+}
+
+unsigned int
+test_RotateL_eqz_int (unsigned int x, unsigned int y, unsigned int z,
+		      unsigned int c)
+{
+  if (c)
+    x = (y << z) | (y >> (32 - z));
+  else
+    x = y;
+  return x;
+}
+
+unsigned int
+test_RotateR_eqz_int (unsigned int x, unsigned int y, unsigned int z,
+		      unsigned int c)
+{
+  if (c)
+    x = (y >> z) | (y << (32 - z));
+  else
+    x = y;
+  return x;
+}
+
 long
 test_ADD_ceqz_imm (long x, long y, long c)
 {
@@ -1225,6 +1288,67 @@ test_RotateR_eqz_imm (unsigned long x, unsigned long y, unsigned long c)
     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;
+}
+
 long
 test_AND_ceqz (long x, long y, long z, long c)
 {
@@ -1544,5 +1668,5 @@ test_AND_eqz_x_2_imm_reverse_bin_oprands (long x, long c)
     x = 11 & x;
   return x;
 }
-/* { dg-final { scan-assembler-times {czero\.eqz} 82 } } */
+/* { dg-final { scan-assembler-times {czero\.eqz} 94 } } */
 /* { dg-final { scan-assembler-times {czero\.nez} 72 } } */
-- 
2.17.1


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 1/5][V3][ifcvt] optimize x=c ? (y op z) : y by RISC-V Zicond like insns
  2023-12-05  8:12 [PATCH 1/5][V3][ifcvt] optimize x=c ? (y op z) : y by RISC-V Zicond like insns Fei Gao
                   ` (3 preceding siblings ...)
  2023-12-05  8:12 ` [PATCH 5/5] [ifcvt] optimize extension for x=c ? (y op z) " Fei Gao
@ 2023-12-08  0:49 ` Jeff Law
  4 siblings, 0 replies; 14+ messages in thread
From: Jeff Law @ 2023-12-08  0:49 UTC (permalink / raw)
  To: Fei Gao, gcc-patches; +Cc: kito.cheng, palmer, zengxiao



On 12/5/23 01:12, Fei Gao wrote:
> op=[PLUS, MINUS, IOR, XOR]
> 
> 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<zengxiao@eswincomputing.com>
> 
> gcc/ChangeLog:
> 
> 	* ifcvt.cc (noce_try_cond_zero_arith):handler for condtional zero based ifcvt
>          (noce_emit_czero): helper for noce_try_cond_zero_arith
>          (noce_cond_zero_binary_op_supported): check supported OPs for condtional zero based ifcvt
>          (get_base_reg): get the reg itself or NULL_RTX if not a reg
>          (noce_bbs_ok_for_cond_zero_arith): check if BBs are OK for condtional zero based ifcvt
>          (noce_process_if_block): add noce_try_cond_zero_arith
> 
> gcc/testsuite/ChangeLog:
> 
> 	* gcc.target/riscv/zicond_ifcvt_opt.c: New test.
Thanks.  In the future make sure to note testing you've done.  Given 
this is a change to target independent code it must be bootstrapped and 
regression tested on a primary platform.

FTR I've done the bootstrap and regression test on x86_64 in addition to 
regression testing on rv64gc.

I'll push this to the trunk momentarily.

jeff




^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 2/5] [ifcvt] optimize x=c ? (y shift_op z):y by RISC-V Zicond like insns
  2023-12-05  8:12 ` [PATCH 2/5] [ifcvt] optimize x=c ? (y shift_op z):y " Fei Gao
@ 2023-12-10 20:43   ` Jeff Law
  2023-12-11  4:01     ` Fei Gao
  0 siblings, 1 reply; 14+ messages in thread
From: Jeff Law @ 2023-12-10 20:43 UTC (permalink / raw)
  To: Fei Gao, gcc-patches; +Cc: kito.cheng, palmer, zengxiao



On 12/5/23 01:12, Fei Gao wrote:
> 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<zengxiao@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.
So I removed the SUBREG handling code which makes this patch merely an 
addition of the shift/rotate ops which trivally work just like PLUS, 
MINUS, IOR, XOR (by conditionally zero-ing the shift count) tested on 
x86 and pushed it to the trunk.

As I noted before while I think handling SUBREGs is important, now is 
not the time to be adding that support.

Thanks!

jeff

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: Re: [PATCH 2/5] [ifcvt] optimize x=c ? (y shift_op z):y by RISC-V Zicond like insns
  2023-12-10 20:43   ` Jeff Law
@ 2023-12-11  4:01     ` Fei Gao
  2023-12-11  6:15       ` Jeff Law
  0 siblings, 1 reply; 14+ messages in thread
From: Fei Gao @ 2023-12-11  4:01 UTC (permalink / raw)
  To: jeffreyalaw, gcc-patches; +Cc: Kito Cheng, Palmer Dabbelt, zengxiao

On 2023-12-11 04:43  Jeff Law <jeffreyalaw@gmail.com> wrote:
>
>
>
>On 12/5/23 01:12, Fei Gao wrote:
>> 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<zengxiao@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.
>So I removed the SUBREG handling code which makes this patch merely an
>addition of the shift/rotate ops which trivally work just like PLUS,
>MINUS, IOR, XOR (by conditionally zero-ing the shift count) tested on
>x86 and pushed it to the trunk.
>
>As I noted before while I think handling SUBREGs is important, now is
>not the time to be adding that support. 

Thanks for your review.
Got your point to defer support for SUBREGs.

Shift-like pattern:
(set (reg/v:DI 137 [ y ])
        (ashift:DI (reg/v:DI 137 [ y ])
            (subreg:QI (reg/v:DI 138 [ z ]) 0)))

No Zicond instructions are generated with the SUBREG handling code removed.
So I noticed your changes in testcases regarding the number of czero instruction number scanned.
Then this looks like a NFC patch.

BR, 
Fei


>
>Thanks!
>
>jeff

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 3/5] [ifcvt] optimize x=c ? (y AND z) : y by RISC-V Zicond like insns
  2023-12-05  8:12 ` [PATCH 3/5] [ifcvt] optimize x=c ? (y AND z) : y " Fei Gao
@ 2023-12-11  5:16   ` Jeff Law
  0 siblings, 0 replies; 14+ messages in thread
From: Jeff Law @ 2023-12-11  5:16 UTC (permalink / raw)
  To: Fei Gao, gcc-patches; +Cc: kito.cheng, palmer, zengxiao



On 12/5/23 01:12, Fei Gao wrote:
> Take the following case for example.
> 
> CFLAGS: -march=rv64gc_zbb_zicond -mabi=lp64d -O2
> 
> long
> test_AND_ceqz (long x, long y, long z, long c)
> {
>    if (c)
>      x = y & z;
>    else
>      x = y;
>    return x;
> }
> 
> Before patch:
> 
> and	a2,a1,a2
> czero.eqz	a0,a2,a3
> czero.nez	a3,a1,a3
> or	a0,a3,a0
> ret
> 
> After patch:
> and	a0,a1,a2
> czero.nez	a1,a1,a3
> or	a0,a1,a0
FWIW I was having a conversation with Andrew W. a little while ago and 
his preference was to change the IOR into an ADD.  We have a better 
chance of using a compressed variant as c.add allows the full set of 
registers while c.or only allows a subset of registers.  Given one of 
the two input registers in that IOR will always have the value zero, it 
should be equivalent.

Given this is target independent code we have to be careful, but I'm not 
immediately aware of a target where using ADD would be worse than IOR 
here.   Anyway, feel free to submit a patch for that minor change, it'll 
need to queue for gcc-15, but should be non-controversial at that time.

The same trick can be done in the conditional move expander within riscv.cc.




> 
> Co-authored-by: Xiao Zeng<zengxiao@eswincomputing.com>
> 
> gcc/ChangeLog:
> 
> 	* ifcvt.cc (noce_cond_zero_binary_op_supported): Add support for AND.
>          (noce_bbs_ok_for_cond_zero_arith): Likewise.
>          (noce_try_cond_zero_arith): Likewise.
> 
> gcc/testsuite/ChangeLog:
> 
> 	* gcc.target/riscv/zicond_ifcvt_opt.c: add TCs for AND.
This looks fine.  I'll need to adjust the matches in the test file 
because we're not supporting SUBREGs.  I can do that easy enough.

I 3-stage bootstrapped and regression tested this on x86_64 as well as 
regression tested it in rv64gc.

I'll push it to the trunk shortly.

jeff

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 4/5] [ifcvt] optimize x=c ? (y op const_int) : y by RISC-V Zicond like insns
  2023-12-05  8:12 ` [PATCH 4/5] [ifcvt] optimize x=c ? (y op const_int) " Fei Gao
@ 2023-12-11  5:38   ` Jeff Law
  2023-12-14  8:42     ` Fei Gao
  0 siblings, 1 reply; 14+ messages in thread
From: Jeff Law @ 2023-12-11  5:38 UTC (permalink / raw)
  To: Fei Gao, gcc-patches; +Cc: kito.cheng, palmer, zengxiao



On 12/5/23 01:12, Fei Gao wrote:
> op=[PLUS, MINUS, IOR, XOR, ASHIFT, ASHIFTRT, LSHIFTRT, ROTATE, ROTATERT, AND]
> 
> Co-authored-by: Xiao Zeng<zengxiao@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 support for const_int
>          (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                                  |  45 +-
>   .../gcc.target/riscv/zicond_ifcvt_opt.c       | 774 +++++++++++++++++-
>   2 files changed, 811 insertions(+), 8 deletions(-)
> 
> diff --git a/gcc/ifcvt.cc b/gcc/ifcvt.cc
> index 29f33f956eb..b84be53ec5c 100644
> --- a/gcc/ifcvt.cc
> +++ b/gcc/ifcvt.cc
> @@ -2910,6 +2910,20 @@ noce_try_sign_mask (struct noce_if_info *if_info)
>     return true;
>   }
>   
> +/*  Check if OP is shift-like operation supported by conditional zero
> +    based if conversion, returning TRUE if satisfied otherwise FALSE.
> +
> +    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;
Formatting nit.  Go ahead and bring down the || op = ROTATE test as 
well.  That leaves the two lines better balanced with all the shifts on 
one line and all the rotates on another.  It's minor, but we might as 
well keep it easy to read.

> @@ -3089,7 +3111,18 @@ 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);
> +	  else if (SUBREG_P (bin_op0))
> +	    *to_replace = gen_rtx_SUBREG (GET_MODE (bin_op0), target, 0);
> +	  else
> +	    *to_replace = target;
Not all targets use QImode for their shift counts, so you can't just 
force that argument to QImode.

The way this works in our internal tree is that we re-expand the binary 
operation rather than replacing bits of existing RTL.  That allows the 
expanders to do the right thing automatically for the target WRT 
handling of things like the mode of the shift count.  In fact, I don't 
see how you can ever do replacement of a constant with a register with 
the current scheme since the original constant will be modeless, so you 
never know what mode to use.



Jeff

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 5/5] [ifcvt] optimize extension for x=c ? (y op z) : y by RISC-V Zicond like insns
  2023-12-05  8:12 ` [PATCH 5/5] [ifcvt] optimize extension for x=c ? (y op z) " Fei Gao
@ 2023-12-11  5:46   ` Jeff Law
  2023-12-14  9:32     ` Fei Gao
  0 siblings, 1 reply; 14+ messages in thread
From: Jeff Law @ 2023-12-11  5:46 UTC (permalink / raw)
  To: Fei Gao, gcc-patches; +Cc: kito.cheng, palmer, zengxiao



On 12/5/23 01:12, Fei Gao wrote:
> SIGN_EXTEND, ZERO_EXTEND and SUBREG has been considered
> to support SImode in 64-bit machine.
> 
> Co-authored-by: Xiao Zeng<zengxiao@eswincomputing.com>
> 
> gcc/ChangeLog:
> 
> 	* ifcvt.cc (noce_cond_zero_binary_op_supported): add support for extension
>          (noce_bbs_ok_for_cond_zero_arith): likewise
>          (noce_try_cond_zero_arith): support extension of LSHIFTRT case
> 
> gcc/testsuite/ChangeLog:
> 
> 	* gcc.target/riscv/zicond_ifcvt_opt.c: add TCs for extension
So I think this needs to defer to gcc-15.  But even so I think getting 
some review on the effort is useful.


> ---
>   gcc/ifcvt.cc                                  |  16 ++-
>   .../gcc.target/riscv/zicond_ifcvt_opt.c       | 126 +++++++++++++++++-
>   2 files changed, 139 insertions(+), 3 deletions(-)
> 
> diff --git a/gcc/ifcvt.cc b/gcc/ifcvt.cc
> index b84be53ec5c..306497a8e37 100644
> --- a/gcc/ifcvt.cc
> +++ b/gcc/ifcvt.cc
> @@ -2934,6 +2934,10 @@ noce_cond_zero_binary_op_supported (rtx op)
>   {
>     enum rtx_code opcode = GET_CODE (op);
>   
> +  /* Strip SIGN_EXTEND or ZERO_EXTEND if any.  */
> +  if (opcode == SIGN_EXTEND || opcode == ZERO_EXTEND)
> +    opcode = GET_CODE (XEXP (op, 0));
So it seems to me like that you need to record what the extension was so 
that you can re-apply it to the result.

> @@ -3114,7 +3122,11 @@ noce_try_cond_zero_arith (struct noce_if_info *if_info)
>         if (CONST_INT_P (*to_replace))
>   	{
>   	  if (noce_cond_zero_shift_op_supported (bin_code))
> -	    *to_replace = gen_rtx_SUBREG (E_QImode, target, 0);
> +	    {
> +	      *to_replace = gen_rtx_SUBREG (E_QImode, target, 0);
> +	      if (GET_CODE (a) == ZERO_EXTEND && bin_code == LSHIFTRT)
> +		PUT_CODE (a, SIGN_EXTEND);
> +	    }
This doesn't look correct (ignoring the SUBREG issues with patch #4 in 
this series).

When we looked at this internally the conclusion was we needed to first 
strip the extension, recording what kind of extension it was, then 
reapply the same extension to the result of the now conditional 
operation.  And it's independent of SUBREG handling.


Jeff

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 2/5] [ifcvt] optimize x=c ? (y shift_op z):y by RISC-V Zicond like insns
  2023-12-11  4:01     ` Fei Gao
@ 2023-12-11  6:15       ` Jeff Law
  0 siblings, 0 replies; 14+ messages in thread
From: Jeff Law @ 2023-12-11  6:15 UTC (permalink / raw)
  To: Fei Gao, gcc-patches; +Cc: Kito Cheng, Palmer Dabbelt, zengxiao



On 12/10/23 21:01, Fei Gao wrote:
> On 2023-12-11 04:43  Jeff Law <jeffreyalaw@gmail.com> wrote:
>>
>>
>>
>> On 12/5/23 01:12, Fei Gao wrote:
>>> 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<zengxiao@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.
>> So I removed the SUBREG handling code which makes this patch merely an
>> addition of the shift/rotate ops which trivally work just like PLUS,
>> MINUS, IOR, XOR (by conditionally zero-ing the shift count) tested on
>> x86 and pushed it to the trunk.
>>
>> As I noted before while I think handling SUBREGs is important, now is
>> not the time to be adding that support.
> 
> Thanks for your review.
> Got your point to defer support for SUBREGs.
> 
> Shift-like pattern:
> (set (reg/v:DI 137 [ y ])
>          (ashift:DI (reg/v:DI 137 [ y ])
>              (subreg:QI (reg/v:DI 138 [ z ]) 0)))
> 
> No Zicond instructions are generated with the SUBREG handling code removed.
> So I noticed your changes in testcases regarding the number of czero instruction number scanned.
> Then this looks like a NFC patch.
Not on other targets -- not every target forces the shift count into a 
narrow mode.
jeff

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: Re: [PATCH 4/5] [ifcvt] optimize x=c ? (y op const_int) : y by RISC-V Zicond like insns
  2023-12-11  5:38   ` Jeff Law
@ 2023-12-14  8:42     ` Fei Gao
  0 siblings, 0 replies; 14+ messages in thread
From: Fei Gao @ 2023-12-14  8:42 UTC (permalink / raw)
  To: jeffreyalaw, gcc-patches; +Cc: Kito Cheng, Palmer Dabbelt, zengxiao

On 2023-12-11 13:38  Jeff Law <jeffreyalaw@gmail.com> wrote:
>
>
>
>On 12/5/23 01:12, Fei Gao wrote:
>> op=[PLUS, MINUS, IOR, XOR, ASHIFT, ASHIFTRT, LSHIFTRT, ROTATE, ROTATERT, AND]
>>
>> Co-authored-by: Xiao Zeng<zengxiao@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 support for const_int
>>          (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


>> @@ -3089,7 +3111,18 @@ 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);
>> +	  else if (SUBREG_P (bin_op0))
>> +	    *to_replace = gen_rtx_SUBREG (GET_MODE (bin_op0), target, 0);
>> +	  else
>> +	    *to_replace = target;
>Not all targets use QImode for their shift counts, so you can't just
>force that argument to QImode. 
Thanks for your info. I haven't understood the "complex" you mentioned
regarding subreg until now.

>
>The way this works in our internal tree is that we re-expand the binary
>operation rather than replacing bits of existing RTL.  That allows the
>expanders to do the right thing automatically for the target WRT
>handling of things like the mode of the shift count.  In fact, I don't
>see how you can ever do replacement of a constant with a register with
>the current scheme since the original constant will be modeless, so you
>never know what mode to use. 
Letting the expander to handle const_int case seems a target general solution.

BR, 
Fei

>
>
>
>Jeff

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: Re: [PATCH 5/5] [ifcvt] optimize extension for x=c ? (y op z) : y by RISC-V Zicond like insns
  2023-12-11  5:46   ` Jeff Law
@ 2023-12-14  9:32     ` Fei Gao
  0 siblings, 0 replies; 14+ messages in thread
From: Fei Gao @ 2023-12-14  9:32 UTC (permalink / raw)
  To: jeffreyalaw, gcc-patches; +Cc: Kito Cheng, Palmer Dabbelt, zengxiao

On 2023-12-11 13:46  Jeff Law <jeffreyalaw@gmail.com> wrote:
>
>
>
>On 12/5/23 01:12, Fei Gao wrote:
>> SIGN_EXTEND, ZERO_EXTEND and SUBREG has been considered
>> to support SImode in 64-bit machine.
>>
>> Co-authored-by: Xiao Zeng<zengxiao@eswincomputing.com>
>>
>> gcc/ChangeLog:
>>
>> * ifcvt.cc (noce_cond_zero_binary_op_supported): add support for extension
>>          (noce_bbs_ok_for_cond_zero_arith): likewise
>>          (noce_try_cond_zero_arith): support extension of LSHIFTRT case
>>
>> gcc/testsuite/ChangeLog:
>>
>> * gcc.target/riscv/zicond_ifcvt_opt.c: add TCs for extension
>So I think this needs to defer to gcc-15.  But even so I think getting
>some review on the effort is useful.
>
>
>> ---
>>   gcc/ifcvt.cc                                  |  16 ++-
>>   .../gcc.target/riscv/zicond_ifcvt_opt.c       | 126 +++++++++++++++++-
>>   2 files changed, 139 insertions(+), 3 deletions(-)
>>
>> diff --git a/gcc/ifcvt.cc b/gcc/ifcvt.cc
>> index b84be53ec5c..306497a8e37 100644
>> --- a/gcc/ifcvt.cc
>> +++ b/gcc/ifcvt.cc
>> @@ -2934,6 +2934,10 @@ noce_cond_zero_binary_op_supported (rtx op)
>>   {
>>     enum rtx_code opcode = GET_CODE (op);
>>  
>> +  /* Strip SIGN_EXTEND or ZERO_EXTEND if any.  */
>> +  if (opcode == SIGN_EXTEND || opcode == ZERO_EXTEND)
>> +    opcode = GET_CODE (XEXP (op, 0));
>So it seems to me like that you need to record what the extension was so
>that you can re-apply it to the result.
>
>> @@ -3114,7 +3122,11 @@ noce_try_cond_zero_arith (struct noce_if_info *if_info)
>>         if (CONST_INT_P (*to_replace))
>>   {
>>     if (noce_cond_zero_shift_op_supported (bin_code))
>> -	    *to_replace = gen_rtx_SUBREG (E_QImode, target, 0);
>> +	    {
>> +	      *to_replace = gen_rtx_SUBREG (E_QImode, target, 0);
>> +	      if (GET_CODE (a) == ZERO_EXTEND && bin_code == LSHIFTRT)
>> +	PUT_CODE (a, SIGN_EXTEND);
>> +	    }
>This doesn't look correct (ignoring the SUBREG issues with patch #4 in
>this series). 
Agree there's  issue here for const_int case as you mentioned in 
[PATCH 4/5] [ifcvt] optimize x=c ? (y op const_int) : y.

>
>When we looked at this internally the conclusion was we needed to first
>strip the extension, recording what kind of extension it was, then
>reapply the same extension to the result of the now conditional
>operation.  And it's independent of SUBREG handling. 
Ignoring the const_int case, we can reuse the RTL pattern and replace
the z(SUBREG pr REG) in INSN_A(x=y op z) without recording what kind
of extension it was. 

New patch will be sent to gcc15.

BR, 
Fei

>
>
>Jeff

^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2023-12-14  9:32 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-12-05  8:12 [PATCH 1/5][V3][ifcvt] optimize x=c ? (y op z) : y by RISC-V Zicond like insns Fei Gao
2023-12-05  8:12 ` [PATCH 2/5] [ifcvt] optimize x=c ? (y shift_op z):y " Fei Gao
2023-12-10 20:43   ` Jeff Law
2023-12-11  4:01     ` Fei Gao
2023-12-11  6:15       ` Jeff Law
2023-12-05  8:12 ` [PATCH 3/5] [ifcvt] optimize x=c ? (y AND z) : y " Fei Gao
2023-12-11  5:16   ` Jeff Law
2023-12-05  8:12 ` [PATCH 4/5] [ifcvt] optimize x=c ? (y op const_int) " Fei Gao
2023-12-11  5:38   ` Jeff Law
2023-12-14  8:42     ` Fei Gao
2023-12-05  8:12 ` [PATCH 5/5] [ifcvt] optimize extension for x=c ? (y op z) " Fei Gao
2023-12-11  5:46   ` Jeff Law
2023-12-14  9:32     ` Fei Gao
2023-12-08  0:49 ` [PATCH 1/5][V3][ifcvt] optimize " Jeff Law

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).