diff options
author | Xiao Zeng <zengxiao@eswincomputing.com> | 2023-08-03 16:09:46 -0400 |
---|---|---|
committer | Jeff Law <jeffreyalaw@gmail.com> | 2023-08-03 16:14:02 -0400 |
commit | 9e3fd332959930efd3cabf222afbac910507d2f3 (patch) | |
tree | 5841e3a314c2b782c654499ae87338ffc5c8d2c8 /gcc | |
parent | c2a447d840476dbd99720f72809304a74abcf040 (diff) | |
download | gcc-9e3fd332959930efd3cabf222afbac910507d2f3.zip gcc-9e3fd332959930efd3cabf222afbac910507d2f3.tar.gz gcc-9e3fd332959930efd3cabf222afbac910507d2f3.tar.bz2 |
[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 (mov<mode>cc): Allow TARGET_ZICOND. Use
sfb_alu_operand for both arms of the conditional move.
Co-authored-by: Jeff Law <jlaw@ventanamicro.com>
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/config/riscv/riscv.cc | 60 | ||||
-rw-r--r-- | gcc/config/riscv/riscv.md | 4 |
2 files changed, 58 insertions, 6 deletions
diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc index d8fab68..8b72561 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 (&code, &op0, &op1, 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 (&code, &op0, &op1, 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 (&code, &op0, &op1, 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, mode)); + 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; + } + /* reg, 0 or imm, 0 */ + else if ((REG_P (cons) + || (CONST_INT_P (cons) && cons != CONST0_RTX (mode))) + && alt == CONST0_RTX (mode)) + { + riscv_emit_int_compare (&code, &op0, &op1, true); + 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; + } + } return false; } diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md index 24819cc..688fd69 100644 --- a/gcc/config/riscv/riscv.md +++ b/gcc/config/riscv/riscv.md @@ -2492,9 +2492,9 @@ (define_expand "mov<mode>cc" [(set (match_operand:GPR 0 "register_operand") (if_then_else:GPR (match_operand 1 "comparison_operator") - (match_operand:GPR 2 "reg_or_0_operand") + (match_operand:GPR 2 "sfb_alu_operand") (match_operand:GPR 3 "sfb_alu_operand")))] - "TARGET_SFB_ALU || TARGET_XTHEADCONDMOV" + "TARGET_SFB_ALU || TARGET_XTHEADCONDMOV || TARGET_ZICOND" { if (riscv_expand_conditional_move (operands[0], operands[1], operands[2], operands[3])) |