public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [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

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).