Re: [PATCH v3] [RISC-V] Generate Zicond instruction for select pattern with condition eq or neq to 0
On 8/1/23 19:38, Xiao Zeng wrote: This patch recognizes Zicond patterns when the select pattern with condition eq or neq to 0 (using eq as an example), namely: 1 rd = (rs2 == 0) ? non-imm : 0 2 rd = (rs2 == 0) ? non-imm : non-imm 3 rd = (rs2 == 0) ? reg : non-imm 4 rd = (rs2 == 0) ? reg : reg gcc/ChangeLog: * config/riscv/riscv.cc (riscv_expand_conditional_move): Recognize Zicond patterns * config/riscv/riscv.md: Recognize Zicond patterns through movcc gcc/testsuite/ChangeLog: * gcc.target/riscv/zicond-primitiveSemantics_return_0_imm.c: New test. * gcc.target/riscv/zicond-primitiveSemantics_return_imm_imm.c: New test. * gcc.target/riscv/zicond-primitiveSemantics_return_imm_reg.c: New test. * gcc.target/riscv/zicond-primitiveSemantics_return_reg_reg.c: New test. I've added -Oz and -Og to the skip list and pushed the tests up to the trunk. jeff
Re: Re: [PATCH v3] [RISC-V] Generate Zicond instruction for select pattern with condition eq or neq to 0
On Sat, Aug 05, 2023 at 05:31:00 AM Jeff Law wrote: > >On 8/1/23 19:38, Xiao Zeng wrote: >> This patch recognizes Zicond patterns when the select pattern >> with condition eq or neq to 0 (using eq as an example), namely: >> >> 1 rd = (rs2 == 0) ? non-imm : 0 >> 2 rd = (rs2 == 0) ? non-imm : non-imm >> 3 rd = (rs2 == 0) ? reg : non-imm >> 4 rd = (rs2 == 0) ? reg : reg >> >> gcc/ChangeLog: >> >> * config/riscv/riscv.cc (riscv_expand_conditional_move): Recognize >> Zicond patterns >> * config/riscv/riscv.md: Recognize Zicond patterns through >>movcc >So I've made minor adjustments to the remaining three cases. First we >need to check the code before optimizing the cases were one of the arms >of the conditional move matches op0. > >I slightly adjusted the case for out of range constants. Its better to >check SMALL_OPERAND rather than testing for specific constants. And >when that triggers, we can just force the value into a register and >continue as-is rather than recursing. > These changes make the code more concise and readable. Thumbs up! >The patch I'm committing fixes one comment typo (whitespace) and a bit >of accidentally duplicated code I added in a prior commit. > >Next up Raphael's patches to handle nontrival conditionals by emiting an >scc insn :-) It would be great to see other implementations for conditional execution. :-) > >Jeff > >ps. I'm deferrring the testsuite bits until we sort out the costing >problems. THey're definitely not forgotten and I still use them in my >local tree. Thank you Jeff, I look forward to a unified, complete and concise implementation method for cost calculation as soon as possible. Thanks Xiao Zeng
Re: [PATCH v3] [RISC-V] Generate Zicond instruction for select pattern with condition eq or neq to 0
On 8/1/23 19:38, Xiao Zeng wrote: This patch recognizes Zicond patterns when the select pattern with condition eq or neq to 0 (using eq as an example), namely: 1 rd = (rs2 == 0) ? non-imm : 0 2 rd = (rs2 == 0) ? non-imm : non-imm 3 rd = (rs2 == 0) ? reg : non-imm 4 rd = (rs2 == 0) ? reg : reg gcc/ChangeLog: * config/riscv/riscv.cc (riscv_expand_conditional_move): Recognize Zicond patterns * config/riscv/riscv.md: Recognize Zicond patterns through movcc So I've made minor adjustments to the remaining three cases. First we need to check the code before optimizing the cases were one of the arms of the conditional move matches op0. I slightly adjusted the case for out of range constants. Its better to check SMALL_OPERAND rather than testing for specific constants. And when that triggers, we can just force the value into a register and continue as-is rather than recursing. The patch I'm committing fixes one comment typo (whitespace) and a bit of accidentally duplicated code I added in a prior commit. Next up Raphael's patches to handle nontrival conditionals by emiting an scc insn :-) Jeff ps. I'm deferrring the testsuite bits until we sort out the costing problems. THey're definitely not forgotten and I still use them in my local tree. commit 4e87c953d16377457b31b65b6c3268d932e462ab Author: Xiao Zeng Date: Fri Aug 4 17:23:56 2023 -0400 [PATCH v3] [RISC-V] Generate Zicond instruction for select pattern with condition eq or neq to 0 This patch recognizes Zicond patterns when the select pattern with condition eq or neq to 0 (using eq as an example), namely: 1 rd = (rs2 == 0) ? non-imm : 0 2 rd = (rs2 == 0) ? non-imm : non-imm 3 rd = (rs2 == 0) ? reg : non-imm 4 rd = (rs2 == 0) ? reg : reg gcc/ChangeLog: * config/riscv/riscv.cc (riscv_expand_conditional_move): Recognize more Zicond patterns. Fix whitespace typo. (riscv_rtx_costs): Remove accidental code duplication. Co-authored-by: Jeff Law diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc index 8b725610815..7728cd34569 100644 --- a/gcc/config/riscv/riscv.cc +++ b/gcc/config/riscv/riscv.cc @@ -2522,20 +2522,6 @@ riscv_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno ATTRIBUTE_UN *total = COSTS_N_INSNS (1); return true; } - else if (TARGET_ZICOND - && outer_code == SET - && ((GET_CODE (XEXP (x, 1)) == REG - && XEXP (x, 2) == CONST0_RTX (GET_MODE (XEXP (x, 1 - || (GET_CODE (XEXP (x, 2)) == REG - && XEXP (x, 1) == CONST0_RTX (GET_MODE (XEXP (x, 2 - || (GET_CODE (XEXP (x, 1)) == REG - && rtx_equal_p (XEXP (x, 1), XEXP (XEXP (x, 0), 0))) - || (GET_CODE (XEXP (x, 1)) == REG - && rtx_equal_p (XEXP (x, 2), XEXP (XEXP (x, 0), 0) - { - *total = COSTS_N_INSNS (1); - return true; - } else if (LABEL_REF_P (XEXP (x, 1)) && XEXP (x, 2) == pc_rtx) { if (equality_operator (XEXP (x, 0), mode) @@ -3583,7 +3569,7 @@ riscv_expand_conditional_move (rtx dest, rtx op, rtx cons, rtx alt) /* The expander is a bit loose in its specification of the true arm of the conditional move. That allows us to support more cases for extensions which are more general than SFB. But - does mean we need to force CONS into a register at this point. */ +does mean we need to force CONS into a register at this point. */ cons = force_reg (GET_MODE (dest), cons); emit_insn (gen_rtx_SET (dest, gen_rtx_IF_THEN_ELSE (GET_MODE (dest), cond, cons, alt))); @@ -3628,6 +3614,40 @@ riscv_expand_conditional_move (rtx dest, rtx op, rtx cons, rtx alt) riscv_emit_binary (PLUS, dest, dest, cons); return true; } + /* imm, reg */ + else if (CONST_INT_P (cons) && cons != CONST0_RTX (mode) && REG_P (alt)) + { + /* Optimize for register value of 0. */ + if (code == NE && rtx_equal_p (op0, alt) && op1 == CONST0_RTX (mode)) + { + rtx cond = gen_rtx_fmt_ee (code, GET_MODE (op0), op0, op1); + cons = force_reg (mode, cons); + emit_insn (gen_rtx_SET (dest, + gen_rtx_IF_THEN_ELSE (mode, cond, + cons, alt))); + return true; + } + + riscv_emit_int_compare (, , , true); + rtx cond = gen_rtx_fmt_ee (code, GET_MODE (op0), op0, op1); + + rtx temp1 = gen_reg_rtx (mode); + rtx temp2 = gen_int_mode (-1 * INTVAL (cons), mode); + + /* TEMP2 might not fit into a signed 12 bit immediate suitable +for an addi
Re: [PATCH v3] [RISC-V] Generate Zicond instruction for select pattern with condition eq or neq to 0
On 8/1/23 19:38, Xiao Zeng wrote: This patch recognizes Zicond patterns when the select pattern with condition eq or neq to 0 (using eq as an example), namely: 1 rd = (rs2 == 0) ? non-imm : 0 2 rd = (rs2 == 0) ? non-imm : non-imm 3 rd = (rs2 == 0) ? reg : non-imm 4 rd = (rs2 == 0) ? reg : reg gcc/ChangeLog: * config/riscv/riscv.cc (riscv_expand_conditional_move): Recognize Zicond patterns * config/riscv/riscv.md: Recognize Zicond patterns through movcc gcc/testsuite/ChangeLog: * gcc.target/riscv/zicond-primitiveSemantics_return_0_imm.c: New test. * gcc.target/riscv/zicond-primitiveSemantics_return_imm_imm.c: New test. * gcc.target/riscv/zicond-primitiveSemantics_return_imm_reg.c: New test. * gcc.target/riscv/zicond-primitiveSemantics_return_reg_reg.c: New test. So I've done a partial commit of this patch. I'm still evaluating a few of the cases and haven't included them yet. The most notable change I've made is the 0, imm case and imm, 0 case can trivially handle 0, reg and reg, 0 as well. I also changed the imm, imm case to use gen_int_mode rather than GEN_INT. It may not be strictly necessary here, but it does future proof the code a bit if we were to support additional mode (and we may well want to do that). I'm hoping to get the rest of patch #3 in today, though I suspect the testing will push it into tomorrow. Then I want to layer on Raphael's code to handle missed cases using scc insns. Jeffcommit 9e3fd332959930efd3cabf222afbac910507d2f3 Author: Xiao Zeng Date: Thu Aug 3 16:09:46 2023 -0400 [PATCH 3/5] [RISC-V] Generate Zicond instruction for select pattern with condition eq or neq to 0 [ This is a partial commit. So not all the cases mentioned by Xiao are currently handled. ] This patch recognizes Zicond patterns when the select pattern with condition eq or neq to 0 (using eq as an example), namely: 1 rd = (rs2 == 0) ? non-imm : 0 2 rd = (rs2 == 0) ? non-imm : non-imm 3 rd = (rs2 == 0) ? reg : non-imm 4 rd = (rs2 == 0) ? reg : reg gcc/ChangeLog: * config/riscv/riscv.cc (riscv_expand_conditional_move): Recognize various Zicond patterns. * config/riscv/riscv.md (movcc): Allow TARGET_ZICOND. Use sfb_alu_operand for both arms of the conditional move. Co-authored-by: Jeff Law diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc index d8fab68dbb4..8b725610815 100644 --- a/gcc/config/riscv/riscv.cc +++ b/gcc/config/riscv/riscv.cc @@ -3580,15 +3580,67 @@ riscv_expand_conditional_move (rtx dest, rtx op, rtx cons, rtx alt) riscv_emit_int_compare (, , , need_eq_ne_p); rtx cond = gen_rtx_fmt_ee (code, GET_MODE (op0), op0, op1); - /* The expander allows (const_int 0) for CONS for the benefit of -TARGET_XTHEADCONDMOV, but that case isn't supported for -TARGET_SFB_ALU. So force that operand into a register if -necessary. */ + /* The expander is a bit loose in its specification of the true +arm of the conditional move. That allows us to support more +cases for extensions which are more general than SFB. But + does mean we need to force CONS into a register at this point. */ cons = force_reg (GET_MODE (dest), cons); emit_insn (gen_rtx_SET (dest, gen_rtx_IF_THEN_ELSE (GET_MODE (dest), cond, cons, alt))); return true; } + else if (TARGET_ZICOND + && (code == EQ || code == NE) + && GET_MODE_CLASS (mode) == MODE_INT) +{ + /* The comparison must be comparing WORD_MODE objects. We must +enforce that so that we don't strip away a sign_extension +thinking it is unnecessary. We might consider using +riscv_extend_operands if they are not already properly extended. */ + if (GET_MODE (op0) != word_mode || GET_MODE (op1) != word_mode) + return false; + + /* 0, reg or 0, imm */ + if (cons == CONST0_RTX (mode) + && (REG_P (alt) + || (CONST_INT_P (alt) && alt != CONST0_RTX (mode + { + riscv_emit_int_compare (, , , true); + rtx cond = gen_rtx_fmt_ee (code, GET_MODE (op0), op0, op1); + alt = force_reg (mode, alt); + emit_insn (gen_rtx_SET (dest, + gen_rtx_IF_THEN_ELSE (mode, cond, + cons, alt))); + return true; + } + /* imm, imm */ + else if (CONST_INT_P (cons) && cons != CONST0_RTX (mode) + && CONST_INT_P (alt) && alt != CONST0_RTX (mode)) + { + riscv_emit_int_compare (, , , true); + rtx cond = gen_rtx_fmt_ee (code, GET_MODE (op0), op0, op1); + HOST_WIDE_INT t = INTVAL (alt) - INTVAL (cons); + alt = force_reg (mode, gen_int_mode (t,
[PATCH v3] [RISC-V] Generate Zicond instruction for select pattern with condition eq or neq to 0
This patch recognizes Zicond patterns when the select pattern with condition eq or neq to 0 (using eq as an example), namely: 1 rd = (rs2 == 0) ? non-imm : 0 2 rd = (rs2 == 0) ? non-imm : non-imm 3 rd = (rs2 == 0) ? reg : non-imm 4 rd = (rs2 == 0) ? reg : reg gcc/ChangeLog: * config/riscv/riscv.cc (riscv_expand_conditional_move): Recognize Zicond patterns * config/riscv/riscv.md: Recognize Zicond patterns through movcc gcc/testsuite/ChangeLog: * gcc.target/riscv/zicond-primitiveSemantics_return_0_imm.c: New test. * gcc.target/riscv/zicond-primitiveSemantics_return_imm_imm.c: New test. * gcc.target/riscv/zicond-primitiveSemantics_return_imm_reg.c: New test. * gcc.target/riscv/zicond-primitiveSemantics_return_reg_reg.c: New test. --- gcc/config/riscv/riscv.cc | 137 ++ gcc/config/riscv/riscv.md | 4 +- .../zicond-primitiveSemantics_return_0_imm.c | 65 + ...zicond-primitiveSemantics_return_imm_imm.c | 73 ++ ...zicond-primitiveSemantics_return_imm_reg.c | 65 + ...zicond-primitiveSemantics_return_reg_reg.c | 65 + 6 files changed, 407 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/gcc.target/riscv/zicond-primitiveSemantics_return_0_imm.c create mode 100644 gcc/testsuite/gcc.target/riscv/zicond-primitiveSemantics_return_imm_imm.c create mode 100644 gcc/testsuite/gcc.target/riscv/zicond-primitiveSemantics_return_imm_reg.c create mode 100644 gcc/testsuite/gcc.target/riscv/zicond-primitiveSemantics_return_reg_reg.c diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc index b6a57d0306d..6353d08ba9d 100644 --- a/gcc/config/riscv/riscv.cc +++ b/gcc/config/riscv/riscv.cc @@ -3557,6 +3557,143 @@ riscv_expand_conditional_move (rtx dest, rtx op, rtx cons, rtx alt) cond, cons, alt))); return true; } + else if (TARGET_ZICOND + && (code == EQ || code == NE) + && GET_MODE_CLASS (mode) == MODE_INT) +{ + /* 0 + imm */ + if (CONST_INT_P (cons) && cons == CONST0_RTX (GET_MODE (cons)) + && CONST_INT_P (alt) && alt != CONST0_RTX (GET_MODE (alt))) +{ + riscv_emit_int_compare (, , , true); + rtx cond = gen_rtx_fmt_ee (code, GET_MODE (op0), op0, op1); + alt = force_reg (mode, alt); + emit_insn (gen_rtx_SET (dest, gen_rtx_IF_THEN_ELSE (mode, cond, + cons, alt))); + return true; +} + /* imm + imm */ + else if (CONST_INT_P (cons) && cons != CONST0_RTX (GET_MODE (cons)) + && CONST_INT_P (alt) && alt != CONST0_RTX (GET_MODE (alt))) +{ + riscv_emit_int_compare (, , , true); + rtx cond = gen_rtx_fmt_ee (code, GET_MODE (op0), op0, op1); + alt = force_reg (mode, GEN_INT (INTVAL (alt) - INTVAL (cons))); + emit_insn (gen_rtx_SET (dest, gen_rtx_IF_THEN_ELSE (mode, cond, + CONST0_RTX (mode), + alt))); + riscv_emit_binary (PLUS, dest, dest, cons); + return true; +} + /* imm + reg */ + else if (CONST_INT_P (cons) && cons != CONST0_RTX (GET_MODE (cons)) + && REG_P (alt)) +{ + if (op0 == alt && op1 == CONST0_RTX (GET_MODE (op1))) +{ + rtx cond = gen_rtx_fmt_ee (code, GET_MODE (op0), op0, op1); + cons = force_reg (mode, cons); + emit_insn (gen_rtx_SET (dest, gen_rtx_IF_THEN_ELSE (mode, cond, + cons, alt))); + return true; +} + /* Handle the special situation of: -2048 == INTVAL (alt) + to avoid failure due to an unrecognized insn. Let the costing + model determine if the conditional move sequence is better + than the branching sequence. */ + if (-2048 == INTVAL (cons)) +{ + rtx reg = gen_reg_rtx (mode); + emit_insn (gen_rtx_SET (reg, cons)); + return riscv_expand_conditional_move (dest, op, reg, alt); +} + riscv_emit_int_compare (, , , true); + rtx cond = gen_rtx_fmt_ee (code, GET_MODE (op0), op0, op1); + rtx temp = GEN_INT (-1 * INTVAL (cons)); + riscv_emit_binary (PLUS, alt, alt, temp); + emit_insn (gen_rtx_SET (dest, gen_rtx_IF_THEN_ELSE (mode, cond, + CONST0_RTX (mode), + alt))); + riscv_emit_binary (PLUS, dest, dest, cons); + return true; +} + /* imm + 0 */ + else if (CONST_INT_P (cons) && cons !=