123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137 |
- From 4c7b0ec59a1a3ab92d8b3221f4e3c23c29719a0a Mon Sep 17 00:00:00 2001
- From: Raphael Zinsly <rzinsly@ventanamicro.com>
- Date: Mon, 7 Aug 2023 10:26:24 -0400
- Subject: [PATCH 11/30] [committed] [RISC-V] Handle more cases in
- riscv_expand_conditional_move
- As I've mentioned in the main zicond thread, Ventana has had patches
- that support more cases by first emitting a suitable scc instruction
- essentially as a canonicalization step of the condition for zicond.
- For example if we have
- (set (target) (if_then_else (op (reg1) (reg2))
- (true_value)
- (false_value)))
- The two register comparison isn't handled by zicond directly. But we
- can generate something like this instead
- (set (temp) (op (reg1) (reg2)))
- (set (target) (if_then_else (op (temp) (const_int 0))
- (true_value)
- (false_value)
- Then let the remaining code from Xiao handle the true_value/false_value
- to make sure it's zicond compatible.
- This is primarily Raphael's work. My involvement has been mostly to
- move it from its original location (in the .md file) into the expander
- function and fix minor problems with the FP case.
- gcc/
- * config/riscv/riscv.cc (riscv_expand_int_scc): Add invert_ptr
- as an argument and pass it to riscv_emit_int_order_test.
- (riscv_expand_conditional_move): Handle cases where the condition
- is not EQ/NE or the second argument to the conditional is not
- (const_int 0).
- * config/riscv/riscv-protos.h (riscv_expand_int_scc): Update prototype.
- Co-authored-by: Jeff Law <jlaw@ventanamicro.com>
- ---
- gcc/config/riscv/riscv-protos.h | 2 +-
- gcc/config/riscv/riscv.cc | 44 ++++++++++++++++++++++++++++++---
- 2 files changed, 42 insertions(+), 4 deletions(-)
- diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h
- index 02b33e02020..8dd35f4262a 100644
- --- a/gcc/config/riscv/riscv-protos.h
- +++ b/gcc/config/riscv/riscv-protos.h
- @@ -56,7 +56,7 @@ extern const char *riscv_output_move (rtx, rtx);
- extern const char *riscv_output_return ();
-
- #ifdef RTX_CODE
- -extern void riscv_expand_int_scc (rtx, enum rtx_code, rtx, rtx);
- +extern void riscv_expand_int_scc (rtx, enum rtx_code, rtx, rtx, bool *invert_ptr = 0);
- extern void riscv_expand_float_scc (rtx, enum rtx_code, rtx, rtx);
- extern void riscv_expand_conditional_branch (rtx, enum rtx_code, rtx, rtx);
- #endif
- diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
- index f16fb17beb5..9b9fff496a3 100644
- --- a/gcc/config/riscv/riscv.cc
- +++ b/gcc/config/riscv/riscv.cc
- @@ -3335,7 +3335,7 @@ riscv_emit_float_compare (enum rtx_code *code, rtx *op0, rtx *op1)
- /* CODE-compare OP0 and OP1. Store the result in TARGET. */
-
- void
- -riscv_expand_int_scc (rtx target, enum rtx_code code, rtx op0, rtx op1)
- +riscv_expand_int_scc (rtx target, enum rtx_code code, rtx op0, rtx op1, bool *invert_ptr)
- {
- riscv_extend_comparands (code, &op0, &op1);
- op0 = force_reg (word_mode, op0);
- @@ -3346,7 +3346,7 @@ riscv_expand_int_scc (rtx target, enum rtx_code code, rtx op0, rtx op1)
- riscv_emit_binary (code, target, zie, const0_rtx);
- }
- else
- - riscv_emit_int_order_test (code, 0, target, op0, op1);
- + riscv_emit_int_order_test (code, invert_ptr, target, op0, op1);
- }
-
- /* Like riscv_expand_int_scc, but for floating-point comparisons. */
- @@ -3444,7 +3444,6 @@ riscv_expand_conditional_move (rtx dest, rtx op, rtx cons, rtx 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
- @@ -3454,6 +3453,45 @@ riscv_expand_conditional_move (rtx dest, rtx op, rtx cons, rtx alt)
- if (GET_MODE (op0) != word_mode || GET_MODE (op1) != word_mode)
- return false;
-
- + /* Canonicalize the comparison. It must be an equality comparison
- + against 0. If it isn't, then emit an SCC instruction so that
- + we can then use an equality comparison against zero. */
- + if (!equality_operator (op, VOIDmode) || op1 != CONST0_RTX (mode))
- + {
- + enum rtx_code new_code = NE;
- + bool *invert_ptr = 0;
- + bool invert = false;
- +
- + if (code == LE || code == GE)
- + invert_ptr = &invert;
- +
- + /* Emit an scc like instruction into a temporary
- + so that we can use an EQ/NE comparison. */
- + rtx tmp = gen_reg_rtx (mode);
- +
- + /* We can support both FP and integer conditional moves. */
- + if (INTEGRAL_MODE_P (GET_MODE (XEXP (op, 0))))
- + riscv_expand_int_scc (tmp, code, op0, op1, invert_ptr);
- + else if (FLOAT_MODE_P (GET_MODE (XEXP (op, 0)))
- + && fp_scc_comparison (op, GET_MODE (op)))
- + riscv_expand_float_scc (tmp, code, op0, op1);
- + else
- + return false;
- +
- + /* If riscv_expand_int_scc inverts the condition, then it will
- + flip the value of INVERT. We need to know where so that
- + we can adjust it for our needs. */
- + if (invert)
- + new_code = EQ;
- +
- + op = gen_rtx_fmt_ee (new_code, mode, tmp, const0_rtx);
- +
- + /* We've generated a new comparison. Update the local variables. */
- + code = GET_CODE (op);
- + op0 = XEXP (op, 0);
- + op1 = XEXP (op, 1);
- + }
- +
- /* 0, reg or 0, imm */
- if (cons == CONST0_RTX (mode)
- && (REG_P (alt)
- --
- 2.25.1
|