public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
From: Fei Gao <gaofei@eswincomputing.com>
To: gcc-patches@gcc.gnu.org
Cc: kito.cheng@gmail.com, palmer@dabbelt.com, jeffreyalaw@gmail.com,
	zengxiao@eswincomputing.com, Fei Gao <gaofei@eswincomputing.com>
Subject: [PATCH 3/5] [ifcvt] optimize x=c ? (y AND z) : y by RISC-V Zicond like insns
Date: Tue,  5 Dec 2023 08:12:46 +0000	[thread overview]
Message-ID: <20231205081248.2106-3-gaofei@eswincomputing.com> (raw)
In-Reply-To: <20231205081248.2106-1-gaofei@eswincomputing.com>

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


  parent reply	other threads:[~2023-12-05  8:13 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-12-05  8:12 [PATCH 1/5][V3][ifcvt] optimize x=c ? (y op " 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 ` Fei Gao [this message]
2023-12-11  5:16   ` [PATCH 3/5] [ifcvt] optimize x=c ? (y AND z) : y " 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

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20231205081248.2106-3-gaofei@eswincomputing.com \
    --to=gaofei@eswincomputing.com \
    --cc=gcc-patches@gcc.gnu.org \
    --cc=jeffreyalaw@gmail.com \
    --cc=kito.cheng@gmail.com \
    --cc=palmer@dabbelt.com \
    --cc=zengxiao@eswincomputing.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).