* [PATCH] riscv: Clarify vlmax and length handling.
@ 2023-05-10 15:24 Robin Dapp
2023-05-10 18:32 ` Palmer Dabbelt
2023-05-11 2:30 ` [PATCH] riscv: " juzhe.zhong
0 siblings, 2 replies; 9+ messages in thread
From: Robin Dapp @ 2023-05-10 15:24 UTC (permalink / raw)
To: gcc-patches, juzhe.zhong, Kito Cheng, Michael Collison, palmer,
jeffreyalaw
Cc: rdapp.gcc
Hi,
this patch tries to improve the wrappers that emit either vlmax or
non-vlmax operations. Now, emit_len_op can be used to
emit a regular operation. Depending on whether a length != NULL
is passed either no VLMAX flags are set or we emit a vsetvli and
set VLMAX flags. The patch also adds some comments that describes
some of the rationale of the current handling of vlmax/nonvlmax
operations.
Bootstrapped and regtested.
Regards
Robin
--
gcc/ChangeLog:
* config/riscv/autovec.md: Use renamed functions.
* config/riscv/riscv-protos.h (emit_vlmax_op): Rename.
(emit_vlmax_reg_op): To this.
(emit_nonvlmax_op): Rename.
(emit_len_op): To this.
(emit_nonvlmax_binop): Rename.
(emit_len_binop): To this.
* config/riscv/riscv-v.cc (emit_pred_op): Add default parameter.
(emit_pred_binop): Remove vlmax_p.
(emit_vlmax_op): Rename.
(emit_vlmax_reg_op): To this.
(emit_nonvlmax_op): Rename.
(emit_len_op): To this.
(emit_nonvlmax_binop): Rename.
(emit_len_binop): To this.
(sew64_scalar_helper): Use renamed functions.
(expand_tuple_move): Use renamed functions.
* config/riscv/riscv.cc (vector_zero_call_used_regs): Use
renamed functions.
* config/riscv/vector.md: Use renamed functions.
---
gcc/config/riscv/autovec.md | 24 +++++-----
gcc/config/riscv/riscv-protos.h | 8 ++--
gcc/config/riscv/riscv-v.cc | 82 ++++++++++++++++++++-------------
gcc/config/riscv/riscv.cc | 4 +-
gcc/config/riscv/vector.md | 12 +++--
5 files changed, 75 insertions(+), 55 deletions(-)
diff --git a/gcc/config/riscv/autovec.md b/gcc/config/riscv/autovec.md
index 15f8d007e07..8347e42bb9c 100644
--- a/gcc/config/riscv/autovec.md
+++ b/gcc/config/riscv/autovec.md
@@ -31,8 +31,8 @@ (define_expand "len_load_<mode>"
(match_operand 3 "const_0_operand")]
"TARGET_VECTOR"
{
- riscv_vector::emit_nonvlmax_op (code_for_pred_mov (<MODE>mode), operands[0],
- operands[1], operands[2], <VM>mode);
+ riscv_vector::emit_len_op (code_for_pred_mov (<MODE>mode), operands[0],
+ operands[1], operands[2], <VM>mode);
DONE;
})
@@ -43,8 +43,8 @@ (define_expand "len_store_<mode>"
(match_operand 3 "const_0_operand")]
"TARGET_VECTOR"
{
- riscv_vector::emit_nonvlmax_op (code_for_pred_mov (<MODE>mode), operands[0],
- operands[1], operands[2], <VM>mode);
+ riscv_vector::emit_len_op (code_for_pred_mov (<MODE>mode), operands[0],
+ operands[1], operands[2], <VM>mode);
DONE;
})
@@ -79,15 +79,15 @@ (define_expand "<optab><mode>3"
if (inner == E_QImode || inner == E_HImode || inner == E_SImode)
op2mode = inner;
- riscv_vector::emit_nonvlmax_binop (code_for_pred_scalar
- (<BINOP_TO_UPPERCASE>, <MODE>mode),
- operands[0], operands[1], cst,
- NULL_RTX, <VM>mode, op2mode);
+ riscv_vector::emit_len_binop (code_for_pred_scalar
+ (<BINOP_TO_UPPERCASE>, <MODE>mode),
+ operands[0], operands[1], cst,
+ NULL_RTX, <VM>mode, op2mode);
}
else
- riscv_vector::emit_nonvlmax_binop (code_for_pred
- (<BINOP_TO_UPPERCASE>, <MODE>mode),
- operands[0], operands[1], operands[2],
- NULL_RTX, <VM>mode);
+ riscv_vector::emit_len_binop (code_for_pred
+ (<BINOP_TO_UPPERCASE>, <MODE>mode),
+ operands[0], operands[1], operands[2],
+ NULL_RTX, <VM>mode);
DONE;
})
diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h
index 75cdb90b9c9..bfdf09b17ee 100644
--- a/gcc/config/riscv/riscv-protos.h
+++ b/gcc/config/riscv/riscv-protos.h
@@ -167,10 +167,10 @@ bool legitimize_move (rtx, rtx, machine_mode);
void emit_vlmax_vsetvl (machine_mode, rtx);
void emit_hard_vlmax_vsetvl (machine_mode, rtx);
void emit_vlmax_op (unsigned, rtx, rtx, machine_mode);
-void emit_vlmax_op (unsigned, rtx, rtx, rtx, machine_mode);
-void emit_nonvlmax_op (unsigned, rtx, rtx, rtx, machine_mode);
-void emit_nonvlmax_binop (unsigned, rtx, rtx, rtx, rtx, machine_mode,
- machine_mode = VOIDmode);
+void emit_vlmax_reg_op (unsigned, rtx, rtx, rtx, machine_mode);
+void emit_len_op (unsigned, rtx, rtx, rtx, machine_mode);
+void emit_len_binop (unsigned, rtx, rtx, rtx, rtx, machine_mode, machine_mode =
+ VOIDmode);
enum vlmul_type get_vlmul (machine_mode);
unsigned int get_ratio (machine_mode);
unsigned int get_nf (machine_mode);
diff --git a/gcc/config/riscv/riscv-v.cc b/gcc/config/riscv/riscv-v.cc
index 3c43dfc5eea..07b7783282f 100644
--- a/gcc/config/riscv/riscv-v.cc
+++ b/gcc/config/riscv/riscv-v.cc
@@ -99,27 +99,24 @@ public:
add_vundef_operand (dest_mode);
}
- void set_len_and_policy (rtx len, bool vlmax_p)
+ void set_len_and_policy (rtx len, bool force_vlmax = false)
{
+ bool vlmax_p = force_vlmax;
gcc_assert (has_dest);
- gcc_assert (len || vlmax_p);
- if (len)
- add_input_operand (len, Pmode);
- else
+ if (!len)
{
- rtx vlmax = gen_reg_rtx (Pmode);
- emit_vlmax_vsetvl (dest_mode, vlmax);
- add_input_operand (vlmax, Pmode);
+ vlmax_p = true;
+ len = gen_reg_rtx (Pmode);
+ emit_vlmax_vsetvl (dest_mode, len);
}
+ add_input_operand (len, Pmode);
+
if (GET_MODE_CLASS (dest_mode) != MODE_VECTOR_BOOL)
add_policy_operand (get_prefer_tail_policy (), get_prefer_mask_policy ());
- if (vlmax_p)
- add_avl_type_operand (avl_type::VLMAX);
- else
- add_avl_type_operand (avl_type::NONVLMAX);
+ add_avl_type_operand (vlmax_p ? avl_type::VLMAX : avl_type::NONVLMAX);
}
void expand (enum insn_code icode, bool temporary_volatile_p = false)
@@ -251,14 +248,14 @@ set_expander_dest_and_mask (insn_expander<MAX_OPERANDS> &e, rtx mask, rtx dest,
/* Emit an RVV unmask && vl mov from SRC to DEST. */
static void
emit_pred_op (unsigned icode, rtx mask, rtx dest, rtx src, rtx len,
- machine_mode mask_mode, bool vlmax_p)
+ machine_mode mask_mode, bool force_vlmax = false)
{
insn_expander<8> e;
e.set_dest_and_mask (mask, dest, mask_mode);
e.add_input_operand (src, GET_MODE (src));
- e.set_len_and_policy (len, vlmax_p);
+ e.set_len_and_policy (len, force_vlmax);
e.expand ((enum insn_code) icode, MEM_P (dest) || MEM_P (src));
}
@@ -266,8 +263,7 @@ emit_pred_op (unsigned icode, rtx mask, rtx dest, rtx src, rtx len,
/* Emit an RVV unmask && vl mov from SRC to DEST. */
static void
emit_pred_binop (unsigned icode, rtx mask, rtx dest, rtx src1, rtx src2,
- rtx len, machine_mode mask_mode, machine_mode op2mode,
- bool vlmax_p)
+ rtx len, machine_mode mask_mode, machine_mode op2mode)
{
insn_expander<9> e;
e.set_dest_and_mask (mask, dest, mask_mode);
@@ -275,37 +271,59 @@ emit_pred_binop (unsigned icode, rtx mask, rtx dest, rtx src1, rtx src2,
e.add_input_operand (src1, GET_MODE (src1));
e.add_input_operand (src2, op2mode == VOIDmode ? GET_MODE (src2) : op2mode);
- e.set_len_and_policy (len, vlmax_p);
+ e.set_len_and_policy (len);
e.expand ((enum insn_code) icode, MEM_P (dest) || MEM_P (src1) || MEM_P (src2));
}
+/* The RISC-V vsetvli pass uses vlmax operation for optimization. Whether or
+ not an instruction actually is a vlmax operation is not recognizable from
+ the length operand alone but the avl_type operand is used instead.
+ In general, there are two cases:
+
+ - Emit a vlmax operation by passing a NULL length. Here we emit
+ a vsetvli with vlmax configuration and set the avl_type to VLMAX.
+ - Emit an operation that uses the existing (last-set) length and
+ set the avl_type to NONVLMAX.
+
+ Sometimes we also need to set the VLMAX avl_type to an operation that
+ already uses a given length register. This can happen during or after
+ register allocation when we are not allowed to create a new register.
+ For that case we also allow to set the avl_type to VLMAX.
+*/
+
+/* This function emits a VLMAX vsetvli followed by the actual operation. */
void
emit_vlmax_op (unsigned icode, rtx dest, rtx src, machine_mode mask_mode)
{
- emit_pred_op (icode, NULL_RTX, dest, src, NULL_RTX, mask_mode, true);
+ emit_pred_op (icode, NULL_RTX, dest, src, NULL_RTX, mask_mode);
}
+/* This function emits an operation with a given LEN that is determined
+ by a previously emitted VLMAX vsetvli. */
void
-emit_vlmax_op (unsigned icode, rtx dest, rtx src, rtx len,
- machine_mode mask_mode)
+emit_len_op (unsigned icode, rtx dest, rtx src, rtx len,
+ machine_mode mask_mode)
{
- emit_pred_op (icode, NULL_RTX, dest, src, len, mask_mode, true);
+ emit_pred_op (icode, NULL_RTX, dest, src, len, mask_mode);
}
+/* This function emits an operation with a given LEN that is known to be
+ a preceding VLMAX. It also sets the VLMAX flag which allows further
+ optimization in the vsetvli pass. */
void
-emit_nonvlmax_op (unsigned icode, rtx dest, rtx src, rtx len,
- machine_mode mask_mode)
+emit_vlmax_reg_op (unsigned icode, rtx dest, rtx src, rtx len,
+ machine_mode mask_mode)
{
- emit_pred_op (icode, NULL_RTX, dest, src, len, mask_mode, false);
+ emit_pred_op (icode, NULL_RTX, dest, src, len, mask_mode,
+ /* Force VLMAX */ true);
}
void
-emit_nonvlmax_binop (unsigned icode, rtx dest, rtx src1, rtx src2, rtx len,
- machine_mode mask_mode, machine_mode op2mode)
+emit_len_binop (unsigned icode, rtx dest, rtx src1, rtx src2, rtx len,
+ machine_mode mask_mode, machine_mode op2mode)
{
- emit_pred_binop (icode, NULL_RTX, dest, src1, src2, len, mask_mode, op2mode,
- false);
+ emit_pred_binop (icode, NULL_RTX, dest, src1, src2, len, mask_mode, op2mode);
}
static void
@@ -667,8 +685,8 @@ sew64_scalar_helper (rtx *operands, rtx *scalar_op, rtx vl,
*scalar_op = force_reg (scalar_mode, *scalar_op);
rtx tmp = gen_reg_rtx (vector_mode);
- riscv_vector::emit_nonvlmax_op (code_for_pred_broadcast (vector_mode), tmp,
- *scalar_op, vl, mask_mode);
+ riscv_vector::emit_len_op (code_for_pred_broadcast (vector_mode), tmp,
+ *scalar_op, vl, mask_mode);
emit_vector_func (operands, tmp);
return true;
@@ -974,7 +992,7 @@ expand_tuple_move (machine_mode mask_mode, rtx *ops)
rtx mem = gen_rtx_MEM (subpart_mode, ops[3]);
if (fractional_p)
- emit_vlmax_op (code_for_pred_mov (subpart_mode), subreg, mem,
+ emit_vlmax_reg_op (code_for_pred_mov (subpart_mode), subreg, mem,
ops[4], mask_mode);
else
emit_move_insn (subreg, mem);
@@ -996,7 +1014,7 @@ expand_tuple_move (machine_mode mask_mode, rtx *ops)
rtx mem = gen_rtx_MEM (subpart_mode, ops[3]);
if (fractional_p)
- emit_vlmax_op (code_for_pred_mov (subpart_mode), mem, subreg,
+ emit_vlmax_reg_op (code_for_pred_mov (subpart_mode), mem, subreg,
ops[4], mask_mode);
else
emit_move_insn (mem, subreg);
diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 9e08a1bfe35..9a493295a38 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -7373,8 +7373,8 @@ vector_zero_call_used_regs (HARD_REG_SET need_zeroed_hardregs)
emitted_vlmax_vsetvl = true;
}
- riscv_vector::emit_vlmax_op (code_for_pred_mov (mode), target,
- CONST0_RTX (mode), vl, mask_mode);
+ riscv_vector::emit_vlmax_reg_op (code_for_pred_mov (mode), target,
+ CONST0_RTX (mode), vl, mask_mode);
SET_HARD_REG_BIT (zeroed_hardregs, regno);
}
diff --git a/gcc/config/riscv/vector.md b/gcc/config/riscv/vector.md
index 9ccc0d6a513..75479f27bcd 100644
--- a/gcc/config/riscv/vector.md
+++ b/gcc/config/riscv/vector.md
@@ -721,8 +721,9 @@ (define_insn_and_split "*mov<V_FRACT:mode><P:mode>_lra"
else
{
riscv_vector::emit_vlmax_vsetvl (<V_FRACT:MODE>mode, operands[2]);
- riscv_vector::emit_vlmax_op (code_for_pred_mov (<V_FRACT:MODE>mode),
- operands[0], operands[1], operands[2], <VM>mode);
+ riscv_vector::emit_vlmax_reg_op (code_for_pred_mov (<V_FRACT:MODE>mode),
+ operands[0], operands[1], operands[2],
+ <VM>mode);
}
DONE;
})
@@ -741,8 +742,9 @@ (define_insn_and_split "*mov<VB:mode><P:mode>_lra"
else
{
riscv_vector::emit_vlmax_vsetvl (<VB:MODE>mode, operands[2]);
- riscv_vector::emit_vlmax_op (code_for_pred_mov (<VB:MODE>mode),
- operands[0], operands[1], operands[2], <VB:MODE>mode);
+ riscv_vector::emit_vlmax_reg_op (code_for_pred_mov (<VB:MODE>mode),
+ operands[0], operands[1], operands[2],
+ <VB:MODE>mode);
}
DONE;
})
@@ -806,7 +808,7 @@ (define_expand "vec_duplicate<mode>"
"TARGET_VECTOR"
{
riscv_vector::emit_vlmax_op (code_for_pred_broadcast (<MODE>mode),
- operands[0], operands[1], <VM>mode);
+ operands[0], operands[1], <VM>mode);
DONE;
}
)
--
2.40.0
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH] riscv: Clarify vlmax and length handling.
2023-05-10 15:24 [PATCH] riscv: Clarify vlmax and length handling Robin Dapp
@ 2023-05-10 18:32 ` Palmer Dabbelt
2023-05-10 18:50 ` Robin Dapp
2023-05-11 2:30 ` [PATCH] riscv: " juzhe.zhong
1 sibling, 1 reply; 9+ messages in thread
From: Palmer Dabbelt @ 2023-05-10 18:32 UTC (permalink / raw)
To: rdapp.gcc
Cc: gcc-patches, juzhe.zhong, Kito Cheng, collison, jeffreyalaw, rdapp.gcc
On Wed, 10 May 2023 08:24:40 PDT (-0700), rdapp.gcc@gmail.com wrote:
> Hi,
>
> this patch tries to improve the wrappers that emit either vlmax or
> non-vlmax operations. Now, emit_len_op can be used to
> emit a regular operation. Depending on whether a length != NULL
> is passed either no VLMAX flags are set or we emit a vsetvli and
> set VLMAX flags. The patch also adds some comments that describes
> some of the rationale of the current handling of vlmax/nonvlmax
> operations.
>
> Bootstrapped and regtested.
>
> Regards
> Robin
It's somewhat common for mail clients to treat "--" as a signature
deliminator, it's "---" that git uses as a comment deliminator.
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH] riscv: Clarify vlmax and length handling.
2023-05-10 18:32 ` Palmer Dabbelt
@ 2023-05-10 18:50 ` Robin Dapp
2023-05-10 18:53 ` Palmer Dabbelt
0 siblings, 1 reply; 9+ messages in thread
From: Robin Dapp @ 2023-05-10 18:50 UTC (permalink / raw)
To: Palmer Dabbelt
Cc: gcc-patches, juzhe.zhong, Kito Cheng, collison, jeffreyalaw
> It's somewhat common for mail clients to treat "--" as a signature
> deliminator, it's "---" that git uses as a comment deliminator.
It's in my muscle memory somehow. Always did it that way because I
didn't want the same delimiter as in the git part of the message. Time
to change that habit I suppose :) (or automate more of the process).
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH] riscv: Clarify vlmax and length handling.
2023-05-10 18:50 ` Robin Dapp
@ 2023-05-10 18:53 ` Palmer Dabbelt
2023-05-11 2:26 ` Kito Cheng
0 siblings, 1 reply; 9+ messages in thread
From: Palmer Dabbelt @ 2023-05-10 18:53 UTC (permalink / raw)
To: rdapp.gcc; +Cc: gcc-patches, juzhe.zhong, Kito Cheng, collison, jeffreyalaw
On Wed, 10 May 2023 11:50:32 PDT (-0700), rdapp.gcc@gmail.com wrote:
>> It's somewhat common for mail clients to treat "--" as a signature
>> deliminator, it's "---" that git uses as a comment deliminator.
>
> It's in my muscle memory somehow. Always did it that way because I
> didn't want the same delimiter as in the git part of the message. Time
> to change that habit I suppose :) (or automate more of the process).
I guess if you're committing your own code it doesn't matter, but mixing
them will trip up git-am and such.
The patch LGTM, but it's mostly Juzhe's code so it's probably best to at
least give him a chance to see it when he's awake.
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH] riscv: Clarify vlmax and length handling.
2023-05-10 18:53 ` Palmer Dabbelt
@ 2023-05-11 2:26 ` Kito Cheng
2023-05-11 10:29 ` [PATCH v2] RISC-V: " Robin Dapp
0 siblings, 1 reply; 9+ messages in thread
From: Kito Cheng @ 2023-05-11 2:26 UTC (permalink / raw)
To: Palmer Dabbelt; +Cc: rdapp.gcc, gcc-patches, juzhe.zhong, collison, jeffreyalaw
LGTM, and just one nit, use RISC-V in the title would be better since
Palmer's patchwork filter is set to "RISC-V", so using "riscv:" might
be missed during patchwork review meeting :P
On Thu, May 11, 2023 at 2:54 AM Palmer Dabbelt <palmer@dabbelt.com> wrote:
>
> On Wed, 10 May 2023 11:50:32 PDT (-0700), rdapp.gcc@gmail.com wrote:
> >> It's somewhat common for mail clients to treat "--" as a signature
> >> deliminator, it's "---" that git uses as a comment deliminator.
> >
> > It's in my muscle memory somehow. Always did it that way because I
> > didn't want the same delimiter as in the git part of the message. Time
> > to change that habit I suppose :) (or automate more of the process).
>
> I guess if you're committing your own code it doesn't matter, but mixing
> them will trip up git-am and such.
>
> The patch LGTM, but it's mostly Juzhe's code so it's probably best to at
> least give him a chance to see it when he's awake.
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH] riscv: Clarify vlmax and length handling.
2023-05-10 15:24 [PATCH] riscv: Clarify vlmax and length handling Robin Dapp
2023-05-10 18:32 ` Palmer Dabbelt
@ 2023-05-11 2:30 ` juzhe.zhong
1 sibling, 0 replies; 9+ messages in thread
From: juzhe.zhong @ 2023-05-11 2:30 UTC (permalink / raw)
To: Robin Dapp, gcc-patches, kito.cheng, collison, palmer, jeffreyalaw
Cc: Robin Dapp
[-- Attachment #1: Type: text/plain, Size: 13040 bytes --]
This part LGTM.
juzhe.zhong@rivai.ai
From: Robin Dapp
Date: 2023-05-10 23:24
To: gcc-patches; juzhe.zhong@rivai.ai; Kito Cheng; Michael Collison; palmer; jeffreyalaw
CC: rdapp.gcc
Subject: [PATCH] riscv: Clarify vlmax and length handling.
Hi,
this patch tries to improve the wrappers that emit either vlmax or
non-vlmax operations. Now, emit_len_op can be used to
emit a regular operation. Depending on whether a length != NULL
is passed either no VLMAX flags are set or we emit a vsetvli and
set VLMAX flags. The patch also adds some comments that describes
some of the rationale of the current handling of vlmax/nonvlmax
operations.
Bootstrapped and regtested.
Regards
Robin
--
gcc/ChangeLog:
* config/riscv/autovec.md: Use renamed functions.
* config/riscv/riscv-protos.h (emit_vlmax_op): Rename.
(emit_vlmax_reg_op): To this.
(emit_nonvlmax_op): Rename.
(emit_len_op): To this.
(emit_nonvlmax_binop): Rename.
(emit_len_binop): To this.
* config/riscv/riscv-v.cc (emit_pred_op): Add default parameter.
(emit_pred_binop): Remove vlmax_p.
(emit_vlmax_op): Rename.
(emit_vlmax_reg_op): To this.
(emit_nonvlmax_op): Rename.
(emit_len_op): To this.
(emit_nonvlmax_binop): Rename.
(emit_len_binop): To this.
(sew64_scalar_helper): Use renamed functions.
(expand_tuple_move): Use renamed functions.
* config/riscv/riscv.cc (vector_zero_call_used_regs): Use
renamed functions.
* config/riscv/vector.md: Use renamed functions.
---
gcc/config/riscv/autovec.md | 24 +++++-----
gcc/config/riscv/riscv-protos.h | 8 ++--
gcc/config/riscv/riscv-v.cc | 82 ++++++++++++++++++++-------------
gcc/config/riscv/riscv.cc | 4 +-
gcc/config/riscv/vector.md | 12 +++--
5 files changed, 75 insertions(+), 55 deletions(-)
diff --git a/gcc/config/riscv/autovec.md b/gcc/config/riscv/autovec.md
index 15f8d007e07..8347e42bb9c 100644
--- a/gcc/config/riscv/autovec.md
+++ b/gcc/config/riscv/autovec.md
@@ -31,8 +31,8 @@ (define_expand "len_load_<mode>"
(match_operand 3 "const_0_operand")]
"TARGET_VECTOR"
{
- riscv_vector::emit_nonvlmax_op (code_for_pred_mov (<MODE>mode), operands[0],
- operands[1], operands[2], <VM>mode);
+ riscv_vector::emit_len_op (code_for_pred_mov (<MODE>mode), operands[0],
+ operands[1], operands[2], <VM>mode);
DONE;
})
@@ -43,8 +43,8 @@ (define_expand "len_store_<mode>"
(match_operand 3 "const_0_operand")]
"TARGET_VECTOR"
{
- riscv_vector::emit_nonvlmax_op (code_for_pred_mov (<MODE>mode), operands[0],
- operands[1], operands[2], <VM>mode);
+ riscv_vector::emit_len_op (code_for_pred_mov (<MODE>mode), operands[0],
+ operands[1], operands[2], <VM>mode);
DONE;
})
@@ -79,15 +79,15 @@ (define_expand "<optab><mode>3"
if (inner == E_QImode || inner == E_HImode || inner == E_SImode)
op2mode = inner;
- riscv_vector::emit_nonvlmax_binop (code_for_pred_scalar
- (<BINOP_TO_UPPERCASE>, <MODE>mode),
- operands[0], operands[1], cst,
- NULL_RTX, <VM>mode, op2mode);
+ riscv_vector::emit_len_binop (code_for_pred_scalar
+ (<BINOP_TO_UPPERCASE>, <MODE>mode),
+ operands[0], operands[1], cst,
+ NULL_RTX, <VM>mode, op2mode);
}
else
- riscv_vector::emit_nonvlmax_binop (code_for_pred
- (<BINOP_TO_UPPERCASE>, <MODE>mode),
- operands[0], operands[1], operands[2],
- NULL_RTX, <VM>mode);
+ riscv_vector::emit_len_binop (code_for_pred
+ (<BINOP_TO_UPPERCASE>, <MODE>mode),
+ operands[0], operands[1], operands[2],
+ NULL_RTX, <VM>mode);
DONE;
})
diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h
index 75cdb90b9c9..bfdf09b17ee 100644
--- a/gcc/config/riscv/riscv-protos.h
+++ b/gcc/config/riscv/riscv-protos.h
@@ -167,10 +167,10 @@ bool legitimize_move (rtx, rtx, machine_mode);
void emit_vlmax_vsetvl (machine_mode, rtx);
void emit_hard_vlmax_vsetvl (machine_mode, rtx);
void emit_vlmax_op (unsigned, rtx, rtx, machine_mode);
-void emit_vlmax_op (unsigned, rtx, rtx, rtx, machine_mode);
-void emit_nonvlmax_op (unsigned, rtx, rtx, rtx, machine_mode);
-void emit_nonvlmax_binop (unsigned, rtx, rtx, rtx, rtx, machine_mode,
- machine_mode = VOIDmode);
+void emit_vlmax_reg_op (unsigned, rtx, rtx, rtx, machine_mode);
+void emit_len_op (unsigned, rtx, rtx, rtx, machine_mode);
+void emit_len_binop (unsigned, rtx, rtx, rtx, rtx, machine_mode, machine_mode =
+ VOIDmode);
enum vlmul_type get_vlmul (machine_mode);
unsigned int get_ratio (machine_mode);
unsigned int get_nf (machine_mode);
diff --git a/gcc/config/riscv/riscv-v.cc b/gcc/config/riscv/riscv-v.cc
index 3c43dfc5eea..07b7783282f 100644
--- a/gcc/config/riscv/riscv-v.cc
+++ b/gcc/config/riscv/riscv-v.cc
@@ -99,27 +99,24 @@ public:
add_vundef_operand (dest_mode);
}
- void set_len_and_policy (rtx len, bool vlmax_p)
+ void set_len_and_policy (rtx len, bool force_vlmax = false)
{
+ bool vlmax_p = force_vlmax;
gcc_assert (has_dest);
- gcc_assert (len || vlmax_p);
- if (len)
- add_input_operand (len, Pmode);
- else
+ if (!len)
{
- rtx vlmax = gen_reg_rtx (Pmode);
- emit_vlmax_vsetvl (dest_mode, vlmax);
- add_input_operand (vlmax, Pmode);
+ vlmax_p = true;
+ len = gen_reg_rtx (Pmode);
+ emit_vlmax_vsetvl (dest_mode, len);
}
+ add_input_operand (len, Pmode);
+
if (GET_MODE_CLASS (dest_mode) != MODE_VECTOR_BOOL)
add_policy_operand (get_prefer_tail_policy (), get_prefer_mask_policy ());
- if (vlmax_p)
- add_avl_type_operand (avl_type::VLMAX);
- else
- add_avl_type_operand (avl_type::NONVLMAX);
+ add_avl_type_operand (vlmax_p ? avl_type::VLMAX : avl_type::NONVLMAX);
}
void expand (enum insn_code icode, bool temporary_volatile_p = false)
@@ -251,14 +248,14 @@ set_expander_dest_and_mask (insn_expander<MAX_OPERANDS> &e, rtx mask, rtx dest,
/* Emit an RVV unmask && vl mov from SRC to DEST. */
static void
emit_pred_op (unsigned icode, rtx mask, rtx dest, rtx src, rtx len,
- machine_mode mask_mode, bool vlmax_p)
+ machine_mode mask_mode, bool force_vlmax = false)
{
insn_expander<8> e;
e.set_dest_and_mask (mask, dest, mask_mode);
e.add_input_operand (src, GET_MODE (src));
- e.set_len_and_policy (len, vlmax_p);
+ e.set_len_and_policy (len, force_vlmax);
e.expand ((enum insn_code) icode, MEM_P (dest) || MEM_P (src));
}
@@ -266,8 +263,7 @@ emit_pred_op (unsigned icode, rtx mask, rtx dest, rtx src, rtx len,
/* Emit an RVV unmask && vl mov from SRC to DEST. */
static void
emit_pred_binop (unsigned icode, rtx mask, rtx dest, rtx src1, rtx src2,
- rtx len, machine_mode mask_mode, machine_mode op2mode,
- bool vlmax_p)
+ rtx len, machine_mode mask_mode, machine_mode op2mode)
{
insn_expander<9> e;
e.set_dest_and_mask (mask, dest, mask_mode);
@@ -275,37 +271,59 @@ emit_pred_binop (unsigned icode, rtx mask, rtx dest, rtx src1, rtx src2,
e.add_input_operand (src1, GET_MODE (src1));
e.add_input_operand (src2, op2mode == VOIDmode ? GET_MODE (src2) : op2mode);
- e.set_len_and_policy (len, vlmax_p);
+ e.set_len_and_policy (len);
e.expand ((enum insn_code) icode, MEM_P (dest) || MEM_P (src1) || MEM_P (src2));
}
+/* The RISC-V vsetvli pass uses vlmax operation for optimization. Whether or
+ not an instruction actually is a vlmax operation is not recognizable from
+ the length operand alone but the avl_type operand is used instead.
+ In general, there are two cases:
+
+ - Emit a vlmax operation by passing a NULL length. Here we emit
+ a vsetvli with vlmax configuration and set the avl_type to VLMAX.
+ - Emit an operation that uses the existing (last-set) length and
+ set the avl_type to NONVLMAX.
+
+ Sometimes we also need to set the VLMAX avl_type to an operation that
+ already uses a given length register. This can happen during or after
+ register allocation when we are not allowed to create a new register.
+ For that case we also allow to set the avl_type to VLMAX.
+*/
+
+/* This function emits a VLMAX vsetvli followed by the actual operation. */
void
emit_vlmax_op (unsigned icode, rtx dest, rtx src, machine_mode mask_mode)
{
- emit_pred_op (icode, NULL_RTX, dest, src, NULL_RTX, mask_mode, true);
+ emit_pred_op (icode, NULL_RTX, dest, src, NULL_RTX, mask_mode);
}
+/* This function emits an operation with a given LEN that is determined
+ by a previously emitted VLMAX vsetvli. */
void
-emit_vlmax_op (unsigned icode, rtx dest, rtx src, rtx len,
- machine_mode mask_mode)
+emit_len_op (unsigned icode, rtx dest, rtx src, rtx len,
+ machine_mode mask_mode)
{
- emit_pred_op (icode, NULL_RTX, dest, src, len, mask_mode, true);
+ emit_pred_op (icode, NULL_RTX, dest, src, len, mask_mode);
}
+/* This function emits an operation with a given LEN that is known to be
+ a preceding VLMAX. It also sets the VLMAX flag which allows further
+ optimization in the vsetvli pass. */
void
-emit_nonvlmax_op (unsigned icode, rtx dest, rtx src, rtx len,
- machine_mode mask_mode)
+emit_vlmax_reg_op (unsigned icode, rtx dest, rtx src, rtx len,
+ machine_mode mask_mode)
{
- emit_pred_op (icode, NULL_RTX, dest, src, len, mask_mode, false);
+ emit_pred_op (icode, NULL_RTX, dest, src, len, mask_mode,
+ /* Force VLMAX */ true);
}
void
-emit_nonvlmax_binop (unsigned icode, rtx dest, rtx src1, rtx src2, rtx len,
- machine_mode mask_mode, machine_mode op2mode)
+emit_len_binop (unsigned icode, rtx dest, rtx src1, rtx src2, rtx len,
+ machine_mode mask_mode, machine_mode op2mode)
{
- emit_pred_binop (icode, NULL_RTX, dest, src1, src2, len, mask_mode, op2mode,
- false);
+ emit_pred_binop (icode, NULL_RTX, dest, src1, src2, len, mask_mode, op2mode);
}
static void
@@ -667,8 +685,8 @@ sew64_scalar_helper (rtx *operands, rtx *scalar_op, rtx vl,
*scalar_op = force_reg (scalar_mode, *scalar_op);
rtx tmp = gen_reg_rtx (vector_mode);
- riscv_vector::emit_nonvlmax_op (code_for_pred_broadcast (vector_mode), tmp,
- *scalar_op, vl, mask_mode);
+ riscv_vector::emit_len_op (code_for_pred_broadcast (vector_mode), tmp,
+ *scalar_op, vl, mask_mode);
emit_vector_func (operands, tmp);
return true;
@@ -974,7 +992,7 @@ expand_tuple_move (machine_mode mask_mode, rtx *ops)
rtx mem = gen_rtx_MEM (subpart_mode, ops[3]);
if (fractional_p)
- emit_vlmax_op (code_for_pred_mov (subpart_mode), subreg, mem,
+ emit_vlmax_reg_op (code_for_pred_mov (subpart_mode), subreg, mem,
ops[4], mask_mode);
else
emit_move_insn (subreg, mem);
@@ -996,7 +1014,7 @@ expand_tuple_move (machine_mode mask_mode, rtx *ops)
rtx mem = gen_rtx_MEM (subpart_mode, ops[3]);
if (fractional_p)
- emit_vlmax_op (code_for_pred_mov (subpart_mode), mem, subreg,
+ emit_vlmax_reg_op (code_for_pred_mov (subpart_mode), mem, subreg,
ops[4], mask_mode);
else
emit_move_insn (mem, subreg);
diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 9e08a1bfe35..9a493295a38 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -7373,8 +7373,8 @@ vector_zero_call_used_regs (HARD_REG_SET need_zeroed_hardregs)
emitted_vlmax_vsetvl = true;
}
- riscv_vector::emit_vlmax_op (code_for_pred_mov (mode), target,
- CONST0_RTX (mode), vl, mask_mode);
+ riscv_vector::emit_vlmax_reg_op (code_for_pred_mov (mode), target,
+ CONST0_RTX (mode), vl, mask_mode);
SET_HARD_REG_BIT (zeroed_hardregs, regno);
}
diff --git a/gcc/config/riscv/vector.md b/gcc/config/riscv/vector.md
index 9ccc0d6a513..75479f27bcd 100644
--- a/gcc/config/riscv/vector.md
+++ b/gcc/config/riscv/vector.md
@@ -721,8 +721,9 @@ (define_insn_and_split "*mov<V_FRACT:mode><P:mode>_lra"
else
{
riscv_vector::emit_vlmax_vsetvl (<V_FRACT:MODE>mode, operands[2]);
- riscv_vector::emit_vlmax_op (code_for_pred_mov (<V_FRACT:MODE>mode),
- operands[0], operands[1], operands[2], <VM>mode);
+ riscv_vector::emit_vlmax_reg_op (code_for_pred_mov (<V_FRACT:MODE>mode),
+ operands[0], operands[1], operands[2],
+ <VM>mode);
}
DONE;
})
@@ -741,8 +742,9 @@ (define_insn_and_split "*mov<VB:mode><P:mode>_lra"
else
{
riscv_vector::emit_vlmax_vsetvl (<VB:MODE>mode, operands[2]);
- riscv_vector::emit_vlmax_op (code_for_pred_mov (<VB:MODE>mode),
- operands[0], operands[1], operands[2], <VB:MODE>mode);
+ riscv_vector::emit_vlmax_reg_op (code_for_pred_mov (<VB:MODE>mode),
+ operands[0], operands[1], operands[2],
+ <VB:MODE>mode);
}
DONE;
})
@@ -806,7 +808,7 @@ (define_expand "vec_duplicate<mode>"
"TARGET_VECTOR"
{
riscv_vector::emit_vlmax_op (code_for_pred_broadcast (<MODE>mode),
- operands[0], operands[1], <VM>mode);
+ operands[0], operands[1], <VM>mode);
DONE;
}
)
--
2.40.0
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH v2] RISC-V: Clarify vlmax and length handling.
2023-05-11 2:26 ` Kito Cheng
@ 2023-05-11 10:29 ` Robin Dapp
2023-05-11 10:35 ` juzhe.zhong
0 siblings, 1 reply; 9+ messages in thread
From: Robin Dapp @ 2023-05-11 10:29 UTC (permalink / raw)
To: Kito Cheng, Palmer Dabbelt
Cc: gcc-patches, juzhe.zhong, collison, jeffreyalaw
Changes from v1:
- Change subject to RISC-V ;)
- Minor comment updates and rebasing.
This patch tries to improve the wrappers that emit either vlmax or
non-vlmax operations. Now, emit_len_op can be used to
emit a regular operation. Depending on whether a length != NULL
is passed either no VLMAX flags are set or we emit a vsetvli and
set VLMAX flags. The patch also adds some comments that describes
some of the rationale of the current handling of vlmax/nonvlmax
operations.
gcc/ChangeLog:
* config/riscv/autovec.md: Use renamed functions.
* config/riscv/riscv-protos.h (emit_vlmax_op): Rename.
(emit_vlmax_reg_op): To this.
(emit_nonvlmax_op): Rename.
(emit_len_op): To this.
(emit_nonvlmax_binop): Rename.
(emit_len_binop): To this.
* config/riscv/riscv-v.cc (emit_pred_op): Add default parameter.
(emit_pred_binop): Remove vlmax_p.
(emit_vlmax_op): Rename.
(emit_vlmax_reg_op): To this.
(emit_nonvlmax_op): Rename.
(emit_len_op): To this.
(emit_nonvlmax_binop): Rename.
(emit_len_binop): To this.
(sew64_scalar_helper): Use renamed functions.
(expand_tuple_move): Use renamed functions.
* config/riscv/riscv.cc (vector_zero_call_used_regs): Use
renamed functions.
* config/riscv/vector.md: Use renamed functions.
---
gcc/config/riscv/autovec.md | 26 ++++-----
gcc/config/riscv/riscv-protos.h | 8 +--
gcc/config/riscv/riscv-v.cc | 94 ++++++++++++++++++++-------------
gcc/config/riscv/riscv.cc | 4 +-
gcc/config/riscv/vector.md | 12 +++--
5 files changed, 83 insertions(+), 61 deletions(-)
diff --git a/gcc/config/riscv/autovec.md b/gcc/config/riscv/autovec.md
index e249f4be704..58926ed3e67 100644
--- a/gcc/config/riscv/autovec.md
+++ b/gcc/config/riscv/autovec.md
@@ -31,8 +31,8 @@ (define_expand "len_load_<mode>"
(match_operand 3 "const_0_operand")]
"TARGET_VECTOR"
{
- riscv_vector::emit_nonvlmax_op (code_for_pred_mov (<MODE>mode), operands[0],
- operands[1], operands[2], <VM>mode);
+ riscv_vector::emit_len_op (code_for_pred_mov (<MODE>mode), operands[0],
+ operands[1], operands[2], <VM>mode);
DONE;
})
@@ -43,8 +43,8 @@ (define_expand "len_store_<mode>"
(match_operand 3 "const_0_operand")]
"TARGET_VECTOR"
{
- riscv_vector::emit_nonvlmax_op (code_for_pred_mov (<MODE>mode), operands[0],
- operands[1], operands[2], <VM>mode);
+ riscv_vector::emit_len_op (code_for_pred_mov (<MODE>mode), operands[0],
+ operands[1], operands[2], <VM>mode);
DONE;
})
@@ -106,16 +106,16 @@ (define_expand "<optab><mode>3"
{
rtx cst;
gcc_assert (const_vec_duplicate_p(operands[2], &cst));
- riscv_vector::emit_nonvlmax_binop (code_for_pred_scalar
- (<CODE>, <MODE>mode),
- operands[0], operands[1], cst,
- NULL, <VM>mode,
- <VEL>mode);
+ riscv_vector::emit_len_binop (code_for_pred_scalar
+ (<CODE>, <MODE>mode),
+ operands[0], operands[1], cst,
+ NULL, <VM>mode,
+ <VEL>mode);
}
else
- riscv_vector::emit_nonvlmax_binop (code_for_pred
- (<CODE>, <MODE>mode),
- operands[0], operands[1], operands[2],
- NULL, <VM>mode);
+ riscv_vector::emit_len_binop (code_for_pred
+ (<CODE>, <MODE>mode),
+ operands[0], operands[1], operands[2],
+ NULL, <VM>mode);
DONE;
})
diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h
index 4d0589e502c..55a43d6270e 100644
--- a/gcc/config/riscv/riscv-protos.h
+++ b/gcc/config/riscv/riscv-protos.h
@@ -167,10 +167,10 @@ bool legitimize_move (rtx, rtx, machine_mode);
void emit_vlmax_vsetvl (machine_mode, rtx);
void emit_hard_vlmax_vsetvl (machine_mode, rtx);
void emit_vlmax_op (unsigned, rtx, rtx, machine_mode);
-void emit_vlmax_op (unsigned, rtx, rtx, rtx, machine_mode);
-void emit_nonvlmax_op (unsigned, rtx, rtx, rtx, machine_mode);
-void emit_nonvlmax_binop (unsigned, rtx, rtx, rtx, rtx, machine_mode,
- machine_mode = VOIDmode);
+void emit_vlmax_reg_op (unsigned, rtx, rtx, rtx, machine_mode);
+void emit_len_op (unsigned, rtx, rtx, rtx, machine_mode);
+void emit_len_binop (unsigned, rtx, rtx, rtx, rtx, machine_mode,
+ machine_mode = VOIDmode);
enum vlmul_type get_vlmul (machine_mode);
unsigned int get_ratio (machine_mode);
unsigned int get_nf (machine_mode);
diff --git a/gcc/config/riscv/riscv-v.cc b/gcc/config/riscv/riscv-v.cc
index 8f46226d571..7cf5ec9f3ba 100644
--- a/gcc/config/riscv/riscv-v.cc
+++ b/gcc/config/riscv/riscv-v.cc
@@ -99,27 +99,24 @@ public:
add_vundef_operand (dest_mode);
}
- void set_len_and_policy (rtx len, bool vlmax_p)
+ void set_len_and_policy (rtx len, bool force_vlmax = false)
{
+ bool vlmax_p = force_vlmax;
gcc_assert (has_dest);
- gcc_assert (len || vlmax_p);
- if (len)
- add_input_operand (len, Pmode);
- else
+ if (!len)
{
- rtx vlmax = gen_reg_rtx (Pmode);
- emit_vlmax_vsetvl (dest_mode, vlmax);
- add_input_operand (vlmax, Pmode);
+ vlmax_p = true;
+ len = gen_reg_rtx (Pmode);
+ emit_vlmax_vsetvl (dest_mode, len);
}
+ add_input_operand (len, Pmode);
+
if (GET_MODE_CLASS (dest_mode) != MODE_VECTOR_BOOL)
add_policy_operand (get_prefer_tail_policy (), get_prefer_mask_policy ());
- if (vlmax_p)
- add_avl_type_operand (avl_type::VLMAX);
- else
- add_avl_type_operand (avl_type::NONVLMAX);
+ add_avl_type_operand (vlmax_p ? avl_type::VLMAX : avl_type::NONVLMAX);
}
void expand (enum insn_code icode, bool temporary_volatile_p = false)
@@ -232,14 +229,14 @@ autovec_use_vlmax_p (void)
/* Emit an RVV unmask && vl mov from SRC to DEST. */
static void
emit_pred_op (unsigned icode, rtx mask, rtx dest, rtx src, rtx len,
- machine_mode mask_mode, bool vlmax_p)
+ machine_mode mask_mode, bool force_vlmax = false)
{
insn_expander<8> e;
e.set_dest_and_mask (mask, dest, mask_mode);
e.add_input_operand (src, GET_MODE (src));
- e.set_len_and_policy (len, vlmax_p);
+ e.set_len_and_policy (len, force_vlmax);
e.expand ((enum insn_code) icode, MEM_P (dest) || MEM_P (src));
}
@@ -248,8 +245,8 @@ emit_pred_op (unsigned icode, rtx mask, rtx dest, rtx src, rtx len,
specified using SCALAR_MODE. */
static void
emit_pred_binop (unsigned icode, rtx mask, rtx dest, rtx src1, rtx src2,
- rtx len, machine_mode mask_mode, machine_mode scalar_mode,
- bool vlmax_p)
+ rtx len, machine_mode mask_mode,
+ machine_mode scalar_mode = VOIDmode)
{
insn_expander<9> e;
e.set_dest_and_mask (mask, dest, mask_mode);
@@ -267,37 +264,60 @@ emit_pred_binop (unsigned icode, rtx mask, rtx dest, rtx src1, rtx src2,
else
e.add_input_operand (src2, scalar_mode);
- e.set_len_and_policy (len, vlmax_p);
+ e.set_len_and_policy (len);
e.expand ((enum insn_code) icode, MEM_P (dest) || MEM_P (src1) || MEM_P (src2));
}
+/* The RISC-V vsetvli pass uses "known vlmax" operations for optimization.
+ Whether or not an instruction actually is a vlmax operation is not
+ recognizable from the length operand alone but the avl_type operand
+ is used instead. In general, there are two cases:
+
+ - Emit a vlmax operation by passing a NULL length. Here we emit
+ a vsetvli with vlmax configuration and set the avl_type to VLMAX.
+ - Emit an operation that uses the existing (last-set) length and
+ set the avl_type to NONVLMAX.
+
+ Sometimes we also need to set the VLMAX avl_type to an operation that
+ already uses a given length register. This can happen during or after
+ register allocation when we are not allowed to create a new register.
+ For that case we also allow to set the avl_type to VLMAX.
+*/
+
+/* This function emits a VLMAX vsetvli followed by the actual operation. */
void
emit_vlmax_op (unsigned icode, rtx dest, rtx src, machine_mode mask_mode)
{
- emit_pred_op (icode, NULL_RTX, dest, src, NULL_RTX, mask_mode, true);
+ emit_pred_op (icode, NULL_RTX, dest, src, NULL_RTX, mask_mode);
}
+/* This function emits an operation with a given LEN that is determined
+ by a previously emitted VLMAX vsetvli. */
void
-emit_vlmax_op (unsigned icode, rtx dest, rtx src, rtx len,
- machine_mode mask_mode)
+emit_len_op (unsigned icode, rtx dest, rtx src, rtx len,
+ machine_mode mask_mode)
{
- emit_pred_op (icode, NULL_RTX, dest, src, len, mask_mode, true);
+ emit_pred_op (icode, NULL_RTX, dest, src, len, mask_mode);
}
+/* This function emits an operation with a given LEN that is known to be
+ a preceding VLMAX. It also sets the VLMAX flag which allows further
+ optimization in the vsetvli pass. */
void
-emit_nonvlmax_op (unsigned icode, rtx dest, rtx src, rtx len,
- machine_mode mask_mode)
+emit_vlmax_reg_op (unsigned icode, rtx dest, rtx src, rtx len,
+ machine_mode mask_mode)
{
- emit_pred_op (icode, NULL_RTX, dest, src, len, mask_mode, false);
+ emit_pred_op (icode, NULL_RTX, dest, src, len, mask_mode,
+ /* Force VLMAX */ true);
}
void
-emit_nonvlmax_binop (unsigned icode, rtx dest, rtx src1, rtx src2, rtx len,
- machine_mode mask_mode, machine_mode scalar_mode)
+emit_len_binop (unsigned icode, rtx dest, rtx src1, rtx src2, rtx len,
+ machine_mode mask_mode, machine_mode scalar_mode)
{
- emit_pred_binop (icode, NULL_RTX, dest, src1, src2, len, mask_mode,
- scalar_mode, len ? false : true);
+ emit_pred_binop (icode, NULL_RTX, dest, src1, src2, len,
+ mask_mode, scalar_mode);
}
/* Emit vid.v instruction. */
@@ -345,14 +365,14 @@ expand_vec_series (rtx dest, rtx base, rtx step)
int shift = exact_log2 (INTVAL (step));
rtx shift_amount = gen_int_mode (shift, Pmode);
insn_code icode = code_for_pred_scalar (ASHIFT, mode);
- emit_nonvlmax_binop (icode, step_adj, vid, shift_amount,
- NULL, mask_mode, Pmode);
+ emit_len_binop (icode, step_adj, vid, shift_amount,
+ NULL, mask_mode, Pmode);
}
else
{
insn_code icode = code_for_pred_scalar (MULT, mode);
- emit_nonvlmax_binop (icode, step_adj, vid, step,
- NULL, mask_mode, inner_mode);
+ emit_len_binop (icode, step_adj, vid, step,
+ NULL, mask_mode, inner_mode);
}
}
@@ -367,7 +387,7 @@ expand_vec_series (rtx dest, rtx base, rtx step)
{
rtx result = gen_reg_rtx (mode);
insn_code icode = code_for_pred_scalar (PLUS, mode);
- emit_nonvlmax_binop (icode, result, step_adj, base,
+ emit_len_binop (icode, result, step_adj, base,
NULL, mask_mode, inner_mode);
emit_move_insn (dest, result);
}
@@ -739,8 +759,8 @@ sew64_scalar_helper (rtx *operands, rtx *scalar_op, rtx vl,
*scalar_op = force_reg (scalar_mode, *scalar_op);
rtx tmp = gen_reg_rtx (vector_mode);
- riscv_vector::emit_nonvlmax_op (code_for_pred_broadcast (vector_mode), tmp,
- *scalar_op, vl, mask_mode);
+ riscv_vector::emit_len_op (code_for_pred_broadcast (vector_mode), tmp,
+ *scalar_op, vl, mask_mode);
emit_vector_func (operands, tmp);
return true;
@@ -1046,7 +1066,7 @@ expand_tuple_move (machine_mode mask_mode, rtx *ops)
rtx mem = gen_rtx_MEM (subpart_mode, ops[3]);
if (fractional_p)
- emit_vlmax_op (code_for_pred_mov (subpart_mode), subreg, mem,
+ emit_vlmax_reg_op (code_for_pred_mov (subpart_mode), subreg, mem,
ops[4], mask_mode);
else
emit_move_insn (subreg, mem);
@@ -1068,7 +1088,7 @@ expand_tuple_move (machine_mode mask_mode, rtx *ops)
rtx mem = gen_rtx_MEM (subpart_mode, ops[3]);
if (fractional_p)
- emit_vlmax_op (code_for_pred_mov (subpart_mode), mem, subreg,
+ emit_vlmax_reg_op (code_for_pred_mov (subpart_mode), mem, subreg,
ops[4], mask_mode);
else
emit_move_insn (mem, subreg);
diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 02d581589ac..cecb4d49092 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -7391,8 +7391,8 @@ vector_zero_call_used_regs (HARD_REG_SET need_zeroed_hardregs)
emitted_vlmax_vsetvl = true;
}
- riscv_vector::emit_vlmax_op (code_for_pred_mov (mode), target,
- CONST0_RTX (mode), vl, mask_mode);
+ riscv_vector::emit_vlmax_reg_op (code_for_pred_mov (mode), target,
+ CONST0_RTX (mode), vl, mask_mode);
SET_HARD_REG_BIT (zeroed_hardregs, regno);
}
diff --git a/gcc/config/riscv/vector.md b/gcc/config/riscv/vector.md
index 9ccc0d6a513..75479f27bcd 100644
--- a/gcc/config/riscv/vector.md
+++ b/gcc/config/riscv/vector.md
@@ -721,8 +721,9 @@ (define_insn_and_split "*mov<V_FRACT:mode><P:mode>_lra"
else
{
riscv_vector::emit_vlmax_vsetvl (<V_FRACT:MODE>mode, operands[2]);
- riscv_vector::emit_vlmax_op (code_for_pred_mov (<V_FRACT:MODE>mode),
- operands[0], operands[1], operands[2], <VM>mode);
+ riscv_vector::emit_vlmax_reg_op (code_for_pred_mov (<V_FRACT:MODE>mode),
+ operands[0], operands[1], operands[2],
+ <VM>mode);
}
DONE;
})
@@ -741,8 +742,9 @@ (define_insn_and_split "*mov<VB:mode><P:mode>_lra"
else
{
riscv_vector::emit_vlmax_vsetvl (<VB:MODE>mode, operands[2]);
- riscv_vector::emit_vlmax_op (code_for_pred_mov (<VB:MODE>mode),
- operands[0], operands[1], operands[2], <VB:MODE>mode);
+ riscv_vector::emit_vlmax_reg_op (code_for_pred_mov (<VB:MODE>mode),
+ operands[0], operands[1], operands[2],
+ <VB:MODE>mode);
}
DONE;
})
@@ -806,7 +808,7 @@ (define_expand "vec_duplicate<mode>"
"TARGET_VECTOR"
{
riscv_vector::emit_vlmax_op (code_for_pred_broadcast (<MODE>mode),
- operands[0], operands[1], <VM>mode);
+ operands[0], operands[1], <VM>mode);
DONE;
}
)
--
2.40.0
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v2] RISC-V: Clarify vlmax and length handling.
2023-05-11 10:29 ` [PATCH v2] RISC-V: " Robin Dapp
@ 2023-05-11 10:35 ` juzhe.zhong
2023-05-11 11:09 ` Kito Cheng
0 siblings, 1 reply; 9+ messages in thread
From: juzhe.zhong @ 2023-05-11 10:35 UTC (permalink / raw)
To: Robin Dapp, kito.cheng, palmer; +Cc: gcc-patches, collison, jeffreyalaw
[-- Attachment #1: Type: text/plain, Size: 14027 bytes --]
LGTM. Plz commit it now. Then I can rebase vec_init patch.
juzhe.zhong@rivai.ai
From: Robin Dapp
Date: 2023-05-11 18:29
To: Kito Cheng; Palmer Dabbelt
CC: gcc-patches; juzhe.zhong; collison; jeffreyalaw
Subject: [PATCH v2] RISC-V: Clarify vlmax and length handling.
Changes from v1:
- Change subject to RISC-V ;)
- Minor comment updates and rebasing.
This patch tries to improve the wrappers that emit either vlmax or
non-vlmax operations. Now, emit_len_op can be used to
emit a regular operation. Depending on whether a length != NULL
is passed either no VLMAX flags are set or we emit a vsetvli and
set VLMAX flags. The patch also adds some comments that describes
some of the rationale of the current handling of vlmax/nonvlmax
operations.
gcc/ChangeLog:
* config/riscv/autovec.md: Use renamed functions.
* config/riscv/riscv-protos.h (emit_vlmax_op): Rename.
(emit_vlmax_reg_op): To this.
(emit_nonvlmax_op): Rename.
(emit_len_op): To this.
(emit_nonvlmax_binop): Rename.
(emit_len_binop): To this.
* config/riscv/riscv-v.cc (emit_pred_op): Add default parameter.
(emit_pred_binop): Remove vlmax_p.
(emit_vlmax_op): Rename.
(emit_vlmax_reg_op): To this.
(emit_nonvlmax_op): Rename.
(emit_len_op): To this.
(emit_nonvlmax_binop): Rename.
(emit_len_binop): To this.
(sew64_scalar_helper): Use renamed functions.
(expand_tuple_move): Use renamed functions.
* config/riscv/riscv.cc (vector_zero_call_used_regs): Use
renamed functions.
* config/riscv/vector.md: Use renamed functions.
---
gcc/config/riscv/autovec.md | 26 ++++-----
gcc/config/riscv/riscv-protos.h | 8 +--
gcc/config/riscv/riscv-v.cc | 94 ++++++++++++++++++++-------------
gcc/config/riscv/riscv.cc | 4 +-
gcc/config/riscv/vector.md | 12 +++--
5 files changed, 83 insertions(+), 61 deletions(-)
diff --git a/gcc/config/riscv/autovec.md b/gcc/config/riscv/autovec.md
index e249f4be704..58926ed3e67 100644
--- a/gcc/config/riscv/autovec.md
+++ b/gcc/config/riscv/autovec.md
@@ -31,8 +31,8 @@ (define_expand "len_load_<mode>"
(match_operand 3 "const_0_operand")]
"TARGET_VECTOR"
{
- riscv_vector::emit_nonvlmax_op (code_for_pred_mov (<MODE>mode), operands[0],
- operands[1], operands[2], <VM>mode);
+ riscv_vector::emit_len_op (code_for_pred_mov (<MODE>mode), operands[0],
+ operands[1], operands[2], <VM>mode);
DONE;
})
@@ -43,8 +43,8 @@ (define_expand "len_store_<mode>"
(match_operand 3 "const_0_operand")]
"TARGET_VECTOR"
{
- riscv_vector::emit_nonvlmax_op (code_for_pred_mov (<MODE>mode), operands[0],
- operands[1], operands[2], <VM>mode);
+ riscv_vector::emit_len_op (code_for_pred_mov (<MODE>mode), operands[0],
+ operands[1], operands[2], <VM>mode);
DONE;
})
@@ -106,16 +106,16 @@ (define_expand "<optab><mode>3"
{
rtx cst;
gcc_assert (const_vec_duplicate_p(operands[2], &cst));
- riscv_vector::emit_nonvlmax_binop (code_for_pred_scalar
- (<CODE>, <MODE>mode),
- operands[0], operands[1], cst,
- NULL, <VM>mode,
- <VEL>mode);
+ riscv_vector::emit_len_binop (code_for_pred_scalar
+ (<CODE>, <MODE>mode),
+ operands[0], operands[1], cst,
+ NULL, <VM>mode,
+ <VEL>mode);
}
else
- riscv_vector::emit_nonvlmax_binop (code_for_pred
- (<CODE>, <MODE>mode),
- operands[0], operands[1], operands[2],
- NULL, <VM>mode);
+ riscv_vector::emit_len_binop (code_for_pred
+ (<CODE>, <MODE>mode),
+ operands[0], operands[1], operands[2],
+ NULL, <VM>mode);
DONE;
})
diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h
index 4d0589e502c..55a43d6270e 100644
--- a/gcc/config/riscv/riscv-protos.h
+++ b/gcc/config/riscv/riscv-protos.h
@@ -167,10 +167,10 @@ bool legitimize_move (rtx, rtx, machine_mode);
void emit_vlmax_vsetvl (machine_mode, rtx);
void emit_hard_vlmax_vsetvl (machine_mode, rtx);
void emit_vlmax_op (unsigned, rtx, rtx, machine_mode);
-void emit_vlmax_op (unsigned, rtx, rtx, rtx, machine_mode);
-void emit_nonvlmax_op (unsigned, rtx, rtx, rtx, machine_mode);
-void emit_nonvlmax_binop (unsigned, rtx, rtx, rtx, rtx, machine_mode,
- machine_mode = VOIDmode);
+void emit_vlmax_reg_op (unsigned, rtx, rtx, rtx, machine_mode);
+void emit_len_op (unsigned, rtx, rtx, rtx, machine_mode);
+void emit_len_binop (unsigned, rtx, rtx, rtx, rtx, machine_mode,
+ machine_mode = VOIDmode);
enum vlmul_type get_vlmul (machine_mode);
unsigned int get_ratio (machine_mode);
unsigned int get_nf (machine_mode);
diff --git a/gcc/config/riscv/riscv-v.cc b/gcc/config/riscv/riscv-v.cc
index 8f46226d571..7cf5ec9f3ba 100644
--- a/gcc/config/riscv/riscv-v.cc
+++ b/gcc/config/riscv/riscv-v.cc
@@ -99,27 +99,24 @@ public:
add_vundef_operand (dest_mode);
}
- void set_len_and_policy (rtx len, bool vlmax_p)
+ void set_len_and_policy (rtx len, bool force_vlmax = false)
{
+ bool vlmax_p = force_vlmax;
gcc_assert (has_dest);
- gcc_assert (len || vlmax_p);
- if (len)
- add_input_operand (len, Pmode);
- else
+ if (!len)
{
- rtx vlmax = gen_reg_rtx (Pmode);
- emit_vlmax_vsetvl (dest_mode, vlmax);
- add_input_operand (vlmax, Pmode);
+ vlmax_p = true;
+ len = gen_reg_rtx (Pmode);
+ emit_vlmax_vsetvl (dest_mode, len);
}
+ add_input_operand (len, Pmode);
+
if (GET_MODE_CLASS (dest_mode) != MODE_VECTOR_BOOL)
add_policy_operand (get_prefer_tail_policy (), get_prefer_mask_policy ());
- if (vlmax_p)
- add_avl_type_operand (avl_type::VLMAX);
- else
- add_avl_type_operand (avl_type::NONVLMAX);
+ add_avl_type_operand (vlmax_p ? avl_type::VLMAX : avl_type::NONVLMAX);
}
void expand (enum insn_code icode, bool temporary_volatile_p = false)
@@ -232,14 +229,14 @@ autovec_use_vlmax_p (void)
/* Emit an RVV unmask && vl mov from SRC to DEST. */
static void
emit_pred_op (unsigned icode, rtx mask, rtx dest, rtx src, rtx len,
- machine_mode mask_mode, bool vlmax_p)
+ machine_mode mask_mode, bool force_vlmax = false)
{
insn_expander<8> e;
e.set_dest_and_mask (mask, dest, mask_mode);
e.add_input_operand (src, GET_MODE (src));
- e.set_len_and_policy (len, vlmax_p);
+ e.set_len_and_policy (len, force_vlmax);
e.expand ((enum insn_code) icode, MEM_P (dest) || MEM_P (src));
}
@@ -248,8 +245,8 @@ emit_pred_op (unsigned icode, rtx mask, rtx dest, rtx src, rtx len,
specified using SCALAR_MODE. */
static void
emit_pred_binop (unsigned icode, rtx mask, rtx dest, rtx src1, rtx src2,
- rtx len, machine_mode mask_mode, machine_mode scalar_mode,
- bool vlmax_p)
+ rtx len, machine_mode mask_mode,
+ machine_mode scalar_mode = VOIDmode)
{
insn_expander<9> e;
e.set_dest_and_mask (mask, dest, mask_mode);
@@ -267,37 +264,60 @@ emit_pred_binop (unsigned icode, rtx mask, rtx dest, rtx src1, rtx src2,
else
e.add_input_operand (src2, scalar_mode);
- e.set_len_and_policy (len, vlmax_p);
+ e.set_len_and_policy (len);
e.expand ((enum insn_code) icode, MEM_P (dest) || MEM_P (src1) || MEM_P (src2));
}
+/* The RISC-V vsetvli pass uses "known vlmax" operations for optimization.
+ Whether or not an instruction actually is a vlmax operation is not
+ recognizable from the length operand alone but the avl_type operand
+ is used instead. In general, there are two cases:
+
+ - Emit a vlmax operation by passing a NULL length. Here we emit
+ a vsetvli with vlmax configuration and set the avl_type to VLMAX.
+ - Emit an operation that uses the existing (last-set) length and
+ set the avl_type to NONVLMAX.
+
+ Sometimes we also need to set the VLMAX avl_type to an operation that
+ already uses a given length register. This can happen during or after
+ register allocation when we are not allowed to create a new register.
+ For that case we also allow to set the avl_type to VLMAX.
+*/
+
+/* This function emits a VLMAX vsetvli followed by the actual operation. */
void
emit_vlmax_op (unsigned icode, rtx dest, rtx src, machine_mode mask_mode)
{
- emit_pred_op (icode, NULL_RTX, dest, src, NULL_RTX, mask_mode, true);
+ emit_pred_op (icode, NULL_RTX, dest, src, NULL_RTX, mask_mode);
}
+/* This function emits an operation with a given LEN that is determined
+ by a previously emitted VLMAX vsetvli. */
void
-emit_vlmax_op (unsigned icode, rtx dest, rtx src, rtx len,
- machine_mode mask_mode)
+emit_len_op (unsigned icode, rtx dest, rtx src, rtx len,
+ machine_mode mask_mode)
{
- emit_pred_op (icode, NULL_RTX, dest, src, len, mask_mode, true);
+ emit_pred_op (icode, NULL_RTX, dest, src, len, mask_mode);
}
+/* This function emits an operation with a given LEN that is known to be
+ a preceding VLMAX. It also sets the VLMAX flag which allows further
+ optimization in the vsetvli pass. */
void
-emit_nonvlmax_op (unsigned icode, rtx dest, rtx src, rtx len,
- machine_mode mask_mode)
+emit_vlmax_reg_op (unsigned icode, rtx dest, rtx src, rtx len,
+ machine_mode mask_mode)
{
- emit_pred_op (icode, NULL_RTX, dest, src, len, mask_mode, false);
+ emit_pred_op (icode, NULL_RTX, dest, src, len, mask_mode,
+ /* Force VLMAX */ true);
}
void
-emit_nonvlmax_binop (unsigned icode, rtx dest, rtx src1, rtx src2, rtx len,
- machine_mode mask_mode, machine_mode scalar_mode)
+emit_len_binop (unsigned icode, rtx dest, rtx src1, rtx src2, rtx len,
+ machine_mode mask_mode, machine_mode scalar_mode)
{
- emit_pred_binop (icode, NULL_RTX, dest, src1, src2, len, mask_mode,
- scalar_mode, len ? false : true);
+ emit_pred_binop (icode, NULL_RTX, dest, src1, src2, len,
+ mask_mode, scalar_mode);
}
/* Emit vid.v instruction. */
@@ -345,14 +365,14 @@ expand_vec_series (rtx dest, rtx base, rtx step)
int shift = exact_log2 (INTVAL (step));
rtx shift_amount = gen_int_mode (shift, Pmode);
insn_code icode = code_for_pred_scalar (ASHIFT, mode);
- emit_nonvlmax_binop (icode, step_adj, vid, shift_amount,
- NULL, mask_mode, Pmode);
+ emit_len_binop (icode, step_adj, vid, shift_amount,
+ NULL, mask_mode, Pmode);
}
else
{
insn_code icode = code_for_pred_scalar (MULT, mode);
- emit_nonvlmax_binop (icode, step_adj, vid, step,
- NULL, mask_mode, inner_mode);
+ emit_len_binop (icode, step_adj, vid, step,
+ NULL, mask_mode, inner_mode);
}
}
@@ -367,7 +387,7 @@ expand_vec_series (rtx dest, rtx base, rtx step)
{
rtx result = gen_reg_rtx (mode);
insn_code icode = code_for_pred_scalar (PLUS, mode);
- emit_nonvlmax_binop (icode, result, step_adj, base,
+ emit_len_binop (icode, result, step_adj, base,
NULL, mask_mode, inner_mode);
emit_move_insn (dest, result);
}
@@ -739,8 +759,8 @@ sew64_scalar_helper (rtx *operands, rtx *scalar_op, rtx vl,
*scalar_op = force_reg (scalar_mode, *scalar_op);
rtx tmp = gen_reg_rtx (vector_mode);
- riscv_vector::emit_nonvlmax_op (code_for_pred_broadcast (vector_mode), tmp,
- *scalar_op, vl, mask_mode);
+ riscv_vector::emit_len_op (code_for_pred_broadcast (vector_mode), tmp,
+ *scalar_op, vl, mask_mode);
emit_vector_func (operands, tmp);
return true;
@@ -1046,7 +1066,7 @@ expand_tuple_move (machine_mode mask_mode, rtx *ops)
rtx mem = gen_rtx_MEM (subpart_mode, ops[3]);
if (fractional_p)
- emit_vlmax_op (code_for_pred_mov (subpart_mode), subreg, mem,
+ emit_vlmax_reg_op (code_for_pred_mov (subpart_mode), subreg, mem,
ops[4], mask_mode);
else
emit_move_insn (subreg, mem);
@@ -1068,7 +1088,7 @@ expand_tuple_move (machine_mode mask_mode, rtx *ops)
rtx mem = gen_rtx_MEM (subpart_mode, ops[3]);
if (fractional_p)
- emit_vlmax_op (code_for_pred_mov (subpart_mode), mem, subreg,
+ emit_vlmax_reg_op (code_for_pred_mov (subpart_mode), mem, subreg,
ops[4], mask_mode);
else
emit_move_insn (mem, subreg);
diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 02d581589ac..cecb4d49092 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -7391,8 +7391,8 @@ vector_zero_call_used_regs (HARD_REG_SET need_zeroed_hardregs)
emitted_vlmax_vsetvl = true;
}
- riscv_vector::emit_vlmax_op (code_for_pred_mov (mode), target,
- CONST0_RTX (mode), vl, mask_mode);
+ riscv_vector::emit_vlmax_reg_op (code_for_pred_mov (mode), target,
+ CONST0_RTX (mode), vl, mask_mode);
SET_HARD_REG_BIT (zeroed_hardregs, regno);
}
diff --git a/gcc/config/riscv/vector.md b/gcc/config/riscv/vector.md
index 9ccc0d6a513..75479f27bcd 100644
--- a/gcc/config/riscv/vector.md
+++ b/gcc/config/riscv/vector.md
@@ -721,8 +721,9 @@ (define_insn_and_split "*mov<V_FRACT:mode><P:mode>_lra"
else
{
riscv_vector::emit_vlmax_vsetvl (<V_FRACT:MODE>mode, operands[2]);
- riscv_vector::emit_vlmax_op (code_for_pred_mov (<V_FRACT:MODE>mode),
- operands[0], operands[1], operands[2], <VM>mode);
+ riscv_vector::emit_vlmax_reg_op (code_for_pred_mov (<V_FRACT:MODE>mode),
+ operands[0], operands[1], operands[2],
+ <VM>mode);
}
DONE;
})
@@ -741,8 +742,9 @@ (define_insn_and_split "*mov<VB:mode><P:mode>_lra"
else
{
riscv_vector::emit_vlmax_vsetvl (<VB:MODE>mode, operands[2]);
- riscv_vector::emit_vlmax_op (code_for_pred_mov (<VB:MODE>mode),
- operands[0], operands[1], operands[2], <VB:MODE>mode);
+ riscv_vector::emit_vlmax_reg_op (code_for_pred_mov (<VB:MODE>mode),
+ operands[0], operands[1], operands[2],
+ <VB:MODE>mode);
}
DONE;
})
@@ -806,7 +808,7 @@ (define_expand "vec_duplicate<mode>"
"TARGET_VECTOR"
{
riscv_vector::emit_vlmax_op (code_for_pred_broadcast (<MODE>mode),
- operands[0], operands[1], <VM>mode);
+ operands[0], operands[1], <VM>mode);
DONE;
}
)
--
2.40.0
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v2] RISC-V: Clarify vlmax and length handling.
2023-05-11 10:35 ` juzhe.zhong
@ 2023-05-11 11:09 ` Kito Cheng
0 siblings, 0 replies; 9+ messages in thread
From: Kito Cheng @ 2023-05-11 11:09 UTC (permalink / raw)
To: 钟居哲
Cc: Robin Dapp, palmer, gcc-patches, collison, jeffreyalaw
[-- Attachment #1: Type: text/plain, Size: 14859 bytes --]
LGTM
juzhe.zhong@rivai.ai <juzhe.zhong@rivai.ai> 於 2023年5月11日 週四 18:36 寫道:
> LGTM. Plz commit it now. Then I can rebase vec_init patch.
>
>
>
> juzhe.zhong@rivai.ai
>
> From: Robin Dapp
> Date: 2023-05-11 18:29
> To: Kito Cheng; Palmer Dabbelt
> CC: gcc-patches; juzhe.zhong; collison; jeffreyalaw
> Subject: [PATCH v2] RISC-V: Clarify vlmax and length handling.
> Changes from v1:
> - Change subject to RISC-V ;)
> - Minor comment updates and rebasing.
>
> This patch tries to improve the wrappers that emit either vlmax or
> non-vlmax operations. Now, emit_len_op can be used to
> emit a regular operation. Depending on whether a length != NULL
> is passed either no VLMAX flags are set or we emit a vsetvli and
> set VLMAX flags. The patch also adds some comments that describes
> some of the rationale of the current handling of vlmax/nonvlmax
> operations.
>
> gcc/ChangeLog:
>
> * config/riscv/autovec.md: Use renamed functions.
> * config/riscv/riscv-protos.h (emit_vlmax_op): Rename.
> (emit_vlmax_reg_op): To this.
> (emit_nonvlmax_op): Rename.
> (emit_len_op): To this.
> (emit_nonvlmax_binop): Rename.
> (emit_len_binop): To this.
> * config/riscv/riscv-v.cc (emit_pred_op): Add default parameter.
> (emit_pred_binop): Remove vlmax_p.
> (emit_vlmax_op): Rename.
> (emit_vlmax_reg_op): To this.
> (emit_nonvlmax_op): Rename.
> (emit_len_op): To this.
> (emit_nonvlmax_binop): Rename.
> (emit_len_binop): To this.
> (sew64_scalar_helper): Use renamed functions.
> (expand_tuple_move): Use renamed functions.
> * config/riscv/riscv.cc (vector_zero_call_used_regs): Use
> renamed functions.
> * config/riscv/vector.md: Use renamed functions.
> ---
> gcc/config/riscv/autovec.md | 26 ++++-----
> gcc/config/riscv/riscv-protos.h | 8 +--
> gcc/config/riscv/riscv-v.cc | 94 ++++++++++++++++++++-------------
> gcc/config/riscv/riscv.cc | 4 +-
> gcc/config/riscv/vector.md | 12 +++--
> 5 files changed, 83 insertions(+), 61 deletions(-)
>
> diff --git a/gcc/config/riscv/autovec.md b/gcc/config/riscv/autovec.md
> index e249f4be704..58926ed3e67 100644
> --- a/gcc/config/riscv/autovec.md
> +++ b/gcc/config/riscv/autovec.md
> @@ -31,8 +31,8 @@ (define_expand "len_load_<mode>"
> (match_operand 3 "const_0_operand")]
> "TARGET_VECTOR"
> {
> - riscv_vector::emit_nonvlmax_op (code_for_pred_mov (<MODE>mode),
> operands[0],
> - operands[1], operands[2], <VM>mode);
> + riscv_vector::emit_len_op (code_for_pred_mov (<MODE>mode), operands[0],
> + operands[1], operands[2], <VM>mode);
> DONE;
> })
> @@ -43,8 +43,8 @@ (define_expand "len_store_<mode>"
> (match_operand 3 "const_0_operand")]
> "TARGET_VECTOR"
> {
> - riscv_vector::emit_nonvlmax_op (code_for_pred_mov (<MODE>mode),
> operands[0],
> - operands[1], operands[2], <VM>mode);
> + riscv_vector::emit_len_op (code_for_pred_mov (<MODE>mode), operands[0],
> + operands[1], operands[2], <VM>mode);
> DONE;
> })
> @@ -106,16 +106,16 @@ (define_expand "<optab><mode>3"
> {
> rtx cst;
> gcc_assert (const_vec_duplicate_p(operands[2], &cst));
> - riscv_vector::emit_nonvlmax_binop (code_for_pred_scalar
> - (<CODE>, <MODE>mode),
> - operands[0], operands[1], cst,
> - NULL, <VM>mode,
> - <VEL>mode);
> + riscv_vector::emit_len_binop (code_for_pred_scalar
> + (<CODE>, <MODE>mode),
> + operands[0], operands[1], cst,
> + NULL, <VM>mode,
> + <VEL>mode);
> }
> else
> - riscv_vector::emit_nonvlmax_binop (code_for_pred
> - (<CODE>, <MODE>mode),
> - operands[0], operands[1], operands[2],
> - NULL, <VM>mode);
> + riscv_vector::emit_len_binop (code_for_pred
> + (<CODE>, <MODE>mode),
> + operands[0], operands[1], operands[2],
> + NULL, <VM>mode);
> DONE;
> })
> diff --git a/gcc/config/riscv/riscv-protos.h
> b/gcc/config/riscv/riscv-protos.h
> index 4d0589e502c..55a43d6270e 100644
> --- a/gcc/config/riscv/riscv-protos.h
> +++ b/gcc/config/riscv/riscv-protos.h
> @@ -167,10 +167,10 @@ bool legitimize_move (rtx, rtx, machine_mode);
> void emit_vlmax_vsetvl (machine_mode, rtx);
> void emit_hard_vlmax_vsetvl (machine_mode, rtx);
> void emit_vlmax_op (unsigned, rtx, rtx, machine_mode);
> -void emit_vlmax_op (unsigned, rtx, rtx, rtx, machine_mode);
> -void emit_nonvlmax_op (unsigned, rtx, rtx, rtx, machine_mode);
> -void emit_nonvlmax_binop (unsigned, rtx, rtx, rtx, rtx, machine_mode,
> - machine_mode = VOIDmode);
> +void emit_vlmax_reg_op (unsigned, rtx, rtx, rtx, machine_mode);
> +void emit_len_op (unsigned, rtx, rtx, rtx, machine_mode);
> +void emit_len_binop (unsigned, rtx, rtx, rtx, rtx, machine_mode,
> + machine_mode = VOIDmode);
> enum vlmul_type get_vlmul (machine_mode);
> unsigned int get_ratio (machine_mode);
> unsigned int get_nf (machine_mode);
> diff --git a/gcc/config/riscv/riscv-v.cc b/gcc/config/riscv/riscv-v.cc
> index 8f46226d571..7cf5ec9f3ba 100644
> --- a/gcc/config/riscv/riscv-v.cc
> +++ b/gcc/config/riscv/riscv-v.cc
> @@ -99,27 +99,24 @@ public:
> add_vundef_operand (dest_mode);
> }
> - void set_len_and_policy (rtx len, bool vlmax_p)
> + void set_len_and_policy (rtx len, bool force_vlmax = false)
> {
> + bool vlmax_p = force_vlmax;
> gcc_assert (has_dest);
> - gcc_assert (len || vlmax_p);
> - if (len)
> - add_input_operand (len, Pmode);
> - else
> + if (!len)
> {
> - rtx vlmax = gen_reg_rtx (Pmode);
> - emit_vlmax_vsetvl (dest_mode, vlmax);
> - add_input_operand (vlmax, Pmode);
> + vlmax_p = true;
> + len = gen_reg_rtx (Pmode);
> + emit_vlmax_vsetvl (dest_mode, len);
> }
> + add_input_operand (len, Pmode);
> +
> if (GET_MODE_CLASS (dest_mode) != MODE_VECTOR_BOOL)
> add_policy_operand (get_prefer_tail_policy (), get_prefer_mask_policy ());
> - if (vlmax_p)
> - add_avl_type_operand (avl_type::VLMAX);
> - else
> - add_avl_type_operand (avl_type::NONVLMAX);
> + add_avl_type_operand (vlmax_p ? avl_type::VLMAX :
> avl_type::NONVLMAX);
> }
> void expand (enum insn_code icode, bool temporary_volatile_p = false)
> @@ -232,14 +229,14 @@ autovec_use_vlmax_p (void)
> /* Emit an RVV unmask && vl mov from SRC to DEST. */
> static void
> emit_pred_op (unsigned icode, rtx mask, rtx dest, rtx src, rtx len,
> - machine_mode mask_mode, bool vlmax_p)
> + machine_mode mask_mode, bool force_vlmax = false)
> {
> insn_expander<8> e;
> e.set_dest_and_mask (mask, dest, mask_mode);
> e.add_input_operand (src, GET_MODE (src));
> - e.set_len_and_policy (len, vlmax_p);
> + e.set_len_and_policy (len, force_vlmax);
> e.expand ((enum insn_code) icode, MEM_P (dest) || MEM_P (src));
> }
> @@ -248,8 +245,8 @@ emit_pred_op (unsigned icode, rtx mask, rtx dest, rtx
> src, rtx len,
> specified using SCALAR_MODE. */
> static void
> emit_pred_binop (unsigned icode, rtx mask, rtx dest, rtx src1, rtx src2,
> - rtx len, machine_mode mask_mode, machine_mode scalar_mode,
> - bool vlmax_p)
> + rtx len, machine_mode mask_mode,
> + machine_mode scalar_mode = VOIDmode)
> {
> insn_expander<9> e;
> e.set_dest_and_mask (mask, dest, mask_mode);
> @@ -267,37 +264,60 @@ emit_pred_binop (unsigned icode, rtx mask, rtx dest,
> rtx src1, rtx src2,
> else
> e.add_input_operand (src2, scalar_mode);
> - e.set_len_and_policy (len, vlmax_p);
> + e.set_len_and_policy (len);
> e.expand ((enum insn_code) icode, MEM_P (dest) || MEM_P (src1) || MEM_P
> (src2));
> }
> +/* The RISC-V vsetvli pass uses "known vlmax" operations for optimization.
> + Whether or not an instruction actually is a vlmax operation is not
> + recognizable from the length operand alone but the avl_type operand
> + is used instead. In general, there are two cases:
> +
> + - Emit a vlmax operation by passing a NULL length. Here we emit
> + a vsetvli with vlmax configuration and set the avl_type to VLMAX.
> + - Emit an operation that uses the existing (last-set) length and
> + set the avl_type to NONVLMAX.
> +
> + Sometimes we also need to set the VLMAX avl_type to an operation that
> + already uses a given length register. This can happen during or after
> + register allocation when we are not allowed to create a new register.
> + For that case we also allow to set the avl_type to VLMAX.
> +*/
> +
> +/* This function emits a VLMAX vsetvli followed by the actual operation.
> */
> void
> emit_vlmax_op (unsigned icode, rtx dest, rtx src, machine_mode mask_mode)
> {
> - emit_pred_op (icode, NULL_RTX, dest, src, NULL_RTX, mask_mode, true);
> + emit_pred_op (icode, NULL_RTX, dest, src, NULL_RTX, mask_mode);
> }
> +/* This function emits an operation with a given LEN that is determined
> + by a previously emitted VLMAX vsetvli. */
> void
> -emit_vlmax_op (unsigned icode, rtx dest, rtx src, rtx len,
> - machine_mode mask_mode)
> +emit_len_op (unsigned icode, rtx dest, rtx src, rtx len,
> + machine_mode mask_mode)
> {
> - emit_pred_op (icode, NULL_RTX, dest, src, len, mask_mode, true);
> + emit_pred_op (icode, NULL_RTX, dest, src, len, mask_mode);
> }
> +/* This function emits an operation with a given LEN that is known to be
> + a preceding VLMAX. It also sets the VLMAX flag which allows further
> + optimization in the vsetvli pass. */
> void
> -emit_nonvlmax_op (unsigned icode, rtx dest, rtx src, rtx len,
> - machine_mode mask_mode)
> +emit_vlmax_reg_op (unsigned icode, rtx dest, rtx src, rtx len,
> + machine_mode mask_mode)
> {
> - emit_pred_op (icode, NULL_RTX, dest, src, len, mask_mode, false);
> + emit_pred_op (icode, NULL_RTX, dest, src, len, mask_mode,
> + /* Force VLMAX */ true);
> }
> void
> -emit_nonvlmax_binop (unsigned icode, rtx dest, rtx src1, rtx src2, rtx
> len,
> - machine_mode mask_mode, machine_mode scalar_mode)
> +emit_len_binop (unsigned icode, rtx dest, rtx src1, rtx src2, rtx len,
> + machine_mode mask_mode, machine_mode scalar_mode)
> {
> - emit_pred_binop (icode, NULL_RTX, dest, src1, src2, len, mask_mode,
> - scalar_mode, len ? false : true);
> + emit_pred_binop (icode, NULL_RTX, dest, src1, src2, len,
> + mask_mode, scalar_mode);
> }
> /* Emit vid.v instruction. */
> @@ -345,14 +365,14 @@ expand_vec_series (rtx dest, rtx base, rtx step)
> int shift = exact_log2 (INTVAL (step));
> rtx shift_amount = gen_int_mode (shift, Pmode);
> insn_code icode = code_for_pred_scalar (ASHIFT, mode);
> - emit_nonvlmax_binop (icode, step_adj, vid, shift_amount,
> - NULL, mask_mode, Pmode);
> + emit_len_binop (icode, step_adj, vid, shift_amount,
> + NULL, mask_mode, Pmode);
> }
> else
> {
> insn_code icode = code_for_pred_scalar (MULT, mode);
> - emit_nonvlmax_binop (icode, step_adj, vid, step,
> - NULL, mask_mode, inner_mode);
> + emit_len_binop (icode, step_adj, vid, step,
> + NULL, mask_mode, inner_mode);
> }
> }
> @@ -367,7 +387,7 @@ expand_vec_series (rtx dest, rtx base, rtx step)
> {
> rtx result = gen_reg_rtx (mode);
> insn_code icode = code_for_pred_scalar (PLUS, mode);
> - emit_nonvlmax_binop (icode, result, step_adj, base,
> + emit_len_binop (icode, result, step_adj, base,
> NULL, mask_mode, inner_mode);
> emit_move_insn (dest, result);
> }
> @@ -739,8 +759,8 @@ sew64_scalar_helper (rtx *operands, rtx *scalar_op,
> rtx vl,
> *scalar_op = force_reg (scalar_mode, *scalar_op);
> rtx tmp = gen_reg_rtx (vector_mode);
> - riscv_vector::emit_nonvlmax_op (code_for_pred_broadcast (vector_mode),
> tmp,
> - *scalar_op, vl, mask_mode);
> + riscv_vector::emit_len_op (code_for_pred_broadcast (vector_mode), tmp,
> + *scalar_op, vl, mask_mode);
> emit_vector_func (operands, tmp);
> return true;
> @@ -1046,7 +1066,7 @@ expand_tuple_move (machine_mode mask_mode, rtx *ops)
> rtx mem = gen_rtx_MEM (subpart_mode, ops[3]);
> if (fractional_p)
> - emit_vlmax_op (code_for_pred_mov (subpart_mode), subreg, mem,
> + emit_vlmax_reg_op (code_for_pred_mov (subpart_mode), subreg, mem,
> ops[4], mask_mode);
> else
> emit_move_insn (subreg, mem);
> @@ -1068,7 +1088,7 @@ expand_tuple_move (machine_mode mask_mode, rtx *ops)
> rtx mem = gen_rtx_MEM (subpart_mode, ops[3]);
> if (fractional_p)
> - emit_vlmax_op (code_for_pred_mov (subpart_mode), mem, subreg,
> + emit_vlmax_reg_op (code_for_pred_mov (subpart_mode), mem, subreg,
> ops[4], mask_mode);
> else
> emit_move_insn (mem, subreg);
> diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
> index 02d581589ac..cecb4d49092 100644
> --- a/gcc/config/riscv/riscv.cc
> +++ b/gcc/config/riscv/riscv.cc
> @@ -7391,8 +7391,8 @@ vector_zero_call_used_regs (HARD_REG_SET
> need_zeroed_hardregs)
> emitted_vlmax_vsetvl = true;
> }
> - riscv_vector::emit_vlmax_op (code_for_pred_mov (mode), target,
> - CONST0_RTX (mode), vl, mask_mode);
> + riscv_vector::emit_vlmax_reg_op (code_for_pred_mov (mode), target,
> + CONST0_RTX (mode), vl, mask_mode);
> SET_HARD_REG_BIT (zeroed_hardregs, regno);
> }
> diff --git a/gcc/config/riscv/vector.md b/gcc/config/riscv/vector.md
> index 9ccc0d6a513..75479f27bcd 100644
> --- a/gcc/config/riscv/vector.md
> +++ b/gcc/config/riscv/vector.md
> @@ -721,8 +721,9 @@ (define_insn_and_split "*mov<V_FRACT:mode><P:mode>_lra"
> else
> {
> riscv_vector::emit_vlmax_vsetvl (<V_FRACT:MODE>mode, operands[2]);
> - riscv_vector::emit_vlmax_op (code_for_pred_mov (<V_FRACT:MODE>mode),
> - operands[0], operands[1], operands[2], <VM>mode);
> + riscv_vector::emit_vlmax_reg_op (code_for_pred_mov
> (<V_FRACT:MODE>mode),
> + operands[0], operands[1], operands[2],
> + <VM>mode);
> }
> DONE;
> })
> @@ -741,8 +742,9 @@ (define_insn_and_split "*mov<VB:mode><P:mode>_lra"
> else
> {
> riscv_vector::emit_vlmax_vsetvl (<VB:MODE>mode, operands[2]);
> - riscv_vector::emit_vlmax_op (code_for_pred_mov (<VB:MODE>mode),
> - operands[0], operands[1], operands[2], <VB:MODE>mode);
> + riscv_vector::emit_vlmax_reg_op (code_for_pred_mov (<VB:MODE>mode),
> + operands[0], operands[1], operands[2],
> + <VB:MODE>mode);
> }
> DONE;
> })
> @@ -806,7 +808,7 @@ (define_expand "vec_duplicate<mode>"
> "TARGET_VECTOR"
> {
> riscv_vector::emit_vlmax_op (code_for_pred_broadcast (<MODE>mode),
> - operands[0], operands[1], <VM>mode);
> + operands[0], operands[1], <VM>mode);
> DONE;
> }
> )
> --
> 2.40.0
>
>
>
>
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2023-05-11 11:09 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-05-10 15:24 [PATCH] riscv: Clarify vlmax and length handling Robin Dapp
2023-05-10 18:32 ` Palmer Dabbelt
2023-05-10 18:50 ` Robin Dapp
2023-05-10 18:53 ` Palmer Dabbelt
2023-05-11 2:26 ` Kito Cheng
2023-05-11 10:29 ` [PATCH v2] RISC-V: " Robin Dapp
2023-05-11 10:35 ` juzhe.zhong
2023-05-11 11:09 ` Kito Cheng
2023-05-11 2:30 ` [PATCH] riscv: " juzhe.zhong
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).