From: Fei Gao <gaofei@eswincomputing.com>
To: gcc-patches@gcc.gnu.org
Cc: kito.cheng@gmail.com, palmer@dabbelt.com, jeffreyalaw@gmail.com,
Fei Gao <gaofei@eswincomputing.com>
Subject: [PATCH 2/4] [ifcvt] if convert x=c ? y+z : y by RISC-V Zicond like insns
Date: Mon, 30 Oct 2023 07:25:21 +0000 [thread overview]
Message-ID: <20231030072523.26818-3-gaofei@eswincomputing.com> (raw)
In-Reply-To: <20231030072523.26818-1-gaofei@eswincomputing.com>
Conditional add, if zero
rd = (rc == 0) ? (rs1 + rs2) : rs1
-->
czero.nez rd, rs2, rc
add rd, rs1, rd
Conditional add, if non-zero
rd = (rc != 0) ? (rs1 + rs2) : rs1
-->
czero.eqz rd, rs2, rc
add rd, rs1, rd
Co-authored-by: Xiao Zeng<zengxiao@eswincomputing.com>
gcc/ChangeLog:
* ifcvt.cc (noce_emit_czero): helper for noce_try_cond_zero_arith
(noce_try_cond_zero_arith): handler for condtional zero op
(noce_process_if_block): add noce_try_cond_zero_arith with hook control
gcc/testsuite/ChangeLog:
* gcc.target/riscv/zicond_ifcvt_opt.c: New test.
---
gcc/ifcvt.cc | 112 +++++++++++++++
.../gcc.target/riscv/zicond_ifcvt_opt.c | 130 ++++++++++++++++++
2 files changed, 242 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..4f98c1c7bf9 100644
--- a/gcc/ifcvt.cc
+++ b/gcc/ifcvt.cc
@@ -781,12 +781,14 @@ static bool noce_try_store_flag_constants (struct noce_if_info *);
static bool noce_try_store_flag_mask (struct noce_if_info *);
static rtx noce_emit_cmove (struct noce_if_info *, rtx, enum rtx_code, rtx,
rtx, rtx, rtx, rtx = NULL, rtx = NULL);
+static rtx noce_emit_czero (struct noce_if_info *, enum rtx_code, rtx, rtx);
static bool noce_try_cmove (struct noce_if_info *);
static bool noce_try_cmove_arith (struct noce_if_info *);
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 bool 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 +1833,32 @@ noce_emit_cmove (struct noce_if_info *if_info, rtx x, enum rtx_code code,
return NULL_RTX;
}
+static rtx
+noce_emit_czero (struct noce_if_info *if_info, enum rtx_code czero_code, rtx z, 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, z);
+ rtx set = gen_rtx_SET (target, if_then_else);
+
+ start_sequence ();
+ rtx_insn *insn = emit_insn (set);
+
+ if (recog_memoized (insn) >= 0)
+ {
+ rtx_insn *seq = get_insns ();
+ end_sequence ();
+ emit_insn (seq);
+
+ return target;
+ }
+
+ end_sequence ();
+ 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 +2908,88 @@ noce_try_sign_mask (struct noce_if_info *if_info)
return true;
}
+/* Convert x = c ? y + z : y or x = c ? y : y + z. */
+
+static bool
+noce_try_cond_zero_arith (struct noce_if_info *if_info)
+{
+ rtx target;
+ rtx_insn *seq;
+ machine_mode mode = GET_MODE (if_info->x);
+ rtx common = NULL_RTX;
+ enum rtx_code czero_code = UNKNOWN;
+ rtx a = if_info->a;
+ rtx b = if_info->b;
+ rtx z = NULL_RTX;
+ rtx cond = if_info->cond;
+
+ if (!noce_simple_bbs (if_info))
+ return false;
+
+ /* cond must be EQ or NEQ 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;
+
+ /* check y + z:y*/
+ if (GET_CODE (a) == PLUS && REG_P (XEXP (a, 0)) && REG_P (XEXP (a, 1))
+ && REG_P (b) && rtx_equal_p (XEXP (a, 0), b))
+ {
+ common = b;
+ z = XEXP (a, 1);
+ /* x = c ? y+z : y, cond = !c --> x = cond ? y : y+z */
+ czero_code = GET_CODE (cond);
+ }
+ /* check y : y+z */
+ else if (GET_CODE (b) == PLUS && REG_P (XEXP (b, 0)) && REG_P (XEXP (b, 1))
+ && REG_P (a) && rtx_equal_p (a, XEXP (b, 0)))
+ {
+ common = a;
+ z = XEXP (b, 1);
+ /* x = c ? y : y+z, cond = !c --> x = !cond ? y : y+z */
+ czero_code = noce_reversed_cond_code (if_info);
+ }
+ else
+ return false;
+
+ if (czero_code == UNKNOWN)
+ return false;
+
+ start_sequence ();
+
+ /* If we have 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, z, target);
+ if (!target)
+ {
+ end_sequence ();
+ return false;
+ }
+
+ target = expand_simple_binop (mode, PLUS, common, target, if_info->x, 0,
+ OPTAB_DIRECT);
+ if (!target)
+ {
+ end_sequence ();
+ return false;
+ }
+
+ if (target != if_info->x)
+ noce_emit_move_insn (if_info->x, target);
+
+ 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 +4085,8 @@ noce_process_if_block (struct noce_if_info *if_info)
goto success;
if (noce_try_store_flag_mask (if_info))
goto success;
+ if (targetm.have_cond_zero () && 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..068c1443413
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/zicond_ifcvt_opt.c
@@ -0,0 +1,130 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gc_zicond -mabi=lp64d -O2" } */
+/* { dg-skip-if "" { *-*-* } {"-O0" "-O1" "-Os" "-Og" "-O3" "-Oz" "-flto"} } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+/*
+**test_ADD_ceqz:
+** czero\.eqz a3,a2,a3
+** add a0,a1,a3
+** ret
+*/
+// x = c ? y+z : y
+long test_ADD_ceqz(long x, long y, long z, long c)
+{
+ if (c)
+ x = y + z;
+ else
+ x = y;
+ return x;
+}
+
+/*
+**test_ADD_ceqz_x:
+** czero\.eqz a2,a1,a2
+** add a0,a0,a2
+** ret
+*/
+// x = c ? x+z : x
+long test_ADD_ceqz_x(long x, long z, long c)
+{
+ if (c)
+ x = x + z;
+
+ return x;
+}
+
+/*
+**test_ADD_nez:
+** czero\.nez a3,a2,a3
+** add a0,a1,a3
+** ret
+*/
+// x = c ? y : y+z
+long test_ADD_nez(long x, long y, long z, long c)
+{
+ if (c)
+ x = y;
+ else
+ x = y + z;
+ return x;
+}
+
+/*
+**test_ADD_nez_x:
+** czero\.nez a2,a1,a2
+** add a0,a0,a2
+** ret
+*/
+// x = c ? x : x+z
+long test_ADD_nez_x(long x, long z, long c)
+{
+ if (c)
+ {}
+ else
+ x = x + z;
+ return x;
+}
+
+/*
+**test_ADD_nez_2:
+** czero\.nez a3,a2,a3
+** add a0,a1,a3
+** ret
+*/
+// x = !c ? y+z : y
+long test_ADD_nez_2(long x, long y, long z, long c)
+{
+ if (!c)
+ x = y + z;
+ else
+ x = y;
+ return x;
+}
+
+/*
+**test_ADD_nez_x_2:
+** czero\.nez a2,a1,a2
+** add a0,a0,a2
+** ret
+*/
+// x = !c ? x+z : x
+long test_ADD_nez_x_2(long x, long z, long c)
+{
+ if (!c)
+ x = x + z;
+
+ return x;
+}
+
+/*
+**test_ADD_eqz_2:
+** czero\.eqz a3,a2,a3
+** add a0,a1,a3
+** ret
+*/
+// x = !c ? y : y+z
+long test_ADD_eqz_2(long x, long y, long z, long c)
+{
+ if (!c)
+ x = y;
+ else
+ x = y + z;
+ return x;
+}
+
+/*
+**test_ADD_eqz_x_2:
+** czero\.eqz a2,a1,a2
+** add a0,a0,a2
+** ret
+*/
+// x = !c ? x : x+z
+long test_ADD_eqz_x_2(long x, long z, long c)
+{
+ if (!c)
+ {}
+ else
+ x = x + z;
+ return x;
+}
--
2.17.1
next prev parent reply other threads:[~2023-10-30 7:25 UTC|newest]
Thread overview: 21+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-10-30 7:25 [PATCH 0/4] add support for conditional zero operation Fei Gao
2023-10-30 7:25 ` [PATCH 1/4] [RISC-V]add hook to control Zicond based ifcvt opt Fei Gao
2023-10-30 15:12 ` Jeff Law
2023-10-30 7:25 ` Fei Gao [this message]
2023-10-30 16:36 ` [PATCH 2/4] [ifcvt] if convert x=c ? y+z : y by RISC-V Zicond like insns Jeff Law
2023-10-31 2:53 ` Fei Gao
2023-10-30 18:41 ` Jeff Law
2023-10-30 19:16 ` Jeff Law
2023-10-31 3:35 ` Fei Gao
2023-11-20 6:46 ` Jeff Law
2023-11-28 2:46 ` Fei Gao
2023-11-28 5:05 ` Jeff Law
2023-11-20 6:59 ` Jeff Law
2023-11-28 2:57 ` Fei Gao
2023-11-29 4:46 ` Jeff Law
2023-10-30 7:25 ` [PATCH 3/4] [ifcvt] if convert x=c ? y op z " Fei Gao
2023-11-20 7:02 ` Jeff Law
2023-10-30 7:25 ` [PATCH 4/4] [ifcvt] if convert x=c ? y&z " Fei Gao
2023-10-30 18:46 ` Jeff Law
2023-11-20 7:10 ` Jeff Law
2023-11-28 3:04 ` Fei Gao
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=20231030072523.26818-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 \
/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).