hi Jeff and Kito Please be noted this patch is based on https://www.mail-archive.com/gcc-patches@gcc.gnu.org/msg327149.html [PATCH 3/4] [ifcvt] optimize x=c ? (y op const_int) : y by RISC-V Zicond like insns
Thanks & BR, Fei On 2023-11-28 18:10 Fei Gao <gao...@eswincomputing.com> 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 > ret > >Co-authored-by: Xiao Zeng<zengx...@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 | 86 +++-- > .../gcc.target/riscv/zicond_ifcvt_opt.c | 323 +++++++++++++++++- > 2 files changed, 377 insertions(+), 32 deletions(-) > >diff --git a/gcc/ifcvt.cc b/gcc/ifcvt.cc >index 4cc6a125ff0..a1af762b5aa 100644 >--- a/gcc/ifcvt.cc >+++ b/gcc/ifcvt.cc >@@ -2940,7 +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 >- || noce_cond_zero_shift_op_supported (opcode)) >+ || opcode == AND || noce_cond_zero_shift_op_supported (opcode)) > return true; > > return false; >@@ -3021,7 +3021,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); > } >@@ -3053,7 +3053,7 @@ 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; >@@ -3073,44 +3073,70 @@ noce_try_cond_zero_arith (struct noce_if_info *if_info) > bin_code = GET_CODE (bin_exp); > bin_op0 = XEXP (bin_exp, 0); > >- if (CONST_INT_P (*to_replace)) >+ if (bin_code == AND) > { >- non_zero_op = gen_reg_rtx (mode); >- noce_emit_move_insn (non_zero_op, *to_replace); >+ rtmp = gen_reg_rtx (mode); >+ emit_insn (gen_rtx_SET (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 (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 */ >- if (common && rtx_equal_p (common, if_info->x)) >- target = gen_reg_rtx (mode); >- else >- target = if_info->x; >+ /* 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; >- } >+ target = noce_emit_czero (if_info, czero_code, non_zero_op, target); >+ if (!target || !to_replace) >+ { >+ end_sequence (); >+ return false; >+ } > >- if (CONST_INT_P (*to_replace)) >- { >- if (noce_cond_zero_shift_op_supported (bin_code)) >+ if (CONST_INT_P (*to_replace)) > { >- *to_replace = gen_rtx_SUBREG (E_QImode, target, 0); >- if (GET_CODE (a) == ZERO_EXTEND && bin_code == LSHIFTRT) >- PUT_CODE (a, SIGN_EXTEND); >+ 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 if (SUBREG_P (bin_op0)) >- *to_replace = gen_rtx_SUBREG (GET_MODE (bin_op0), target, 0); > else > *to_replace = target; >+ emit_insn (gen_rtx_SET (if_info->x, a)); > } >- else >- *to_replace = target; >- emit_insn (gen_rtx_SET (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 c6b0518968b..53206d76e9f 100644 >--- a/gcc/testsuite/gcc.target/riscv/zicond_ifcvt_opt.c >+++ b/gcc/testsuite/gcc.target/riscv/zicond_ifcvt_opt.c >@@ -1349,5 +1349,324 @@ test_RotateR_eqz_imm_int (unsigned int x, unsigned int >y, unsigned int c) > return x; > } > >-/* { dg-final { scan-assembler-times {czero\.eqz} 78 } } */ >-/* { dg-final { scan-assembler-times {czero\.nez} 56 } } */ >+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; >+} >+ >+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} 94 } } */ >+/* { dg-final { scan-assembler-times {czero\.nez} 72 } } */ >-- >2.17.1