public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] RISC-V: Refactor and clean emit_{vlmax,nonvlmax}_xxx functions
@ 2023-08-30 11:53 Lehua Ding
  2023-08-31  7:51 ` [PATCH] RISC-V: Refactor and clean emit_{vlmax, nonvlmax}_xxx functions Kito Cheng
  2023-08-31  9:16 ` [PATCH] RISC-V: Refactor and clean emit_{vlmax,nonvlmax}_xxx functions Robin Dapp
  0 siblings, 2 replies; 5+ messages in thread
From: Lehua Ding @ 2023-08-30 11:53 UTC (permalink / raw)
  To: gcc-patches, rdapp.gcc; +Cc: juzhe.zhong, kito.cheng, palmer, jeffreyalaw

Hi,

This patch refactor the code of emit_{vlmax,nonvlmax}_xxx functions.
These functions are used to generate RVV insn. There are currently 31
such functions and a few duplicates. The reason so many functions are
needed is because there are more types of RVV instructions. There are
patterns that don't have mask operand, patterns that don't have merge
operand, and patterns that don't need a tail policy operand, etc.

Previously there was the insn_type enum, but it's value was just used
to indicate how many operands were passed in by caller. The rest of
the operands information is scattered throughout these functions.
For example, emit_vlmax_fp_insn indicates that a rounding mode operand
of FRM_DYN should also be passed, emit_vlmax_merge_insn means that
there is no mask operand or mask policy operand.

I introduced a new enum insn_flags to indicate some properties of these
RVV patterns. These insn_flags are then used to define insn_type enum.
For example for the defintion of WIDEN_TERNARY_OP:

  WIDEN_TERNARY_OP = HAS_DEST_P | HAS_MASK_P | USE_ALL_TRUES_MASK_P
                       | TDEFAULT_POLICY_P | MDEFAULT_POLICY_P | TERNARY_OP_P,

This flags mean the RVV pattern has no merge operand. This flags only apply
to vwmacc instructions. After defining the desired insn_type, all the
emit_{vlmax,nonvlmax}_xxx functions are unified into three functions:

  emit_vlmax_insn (icode, insn_flags, ops);
  emit_nonvlmax_insn (icode, insn_flags, ops, vl);
  emit_vlmax_insn_lra (icode, insn_flags, ops, vl);

Then user can select the appropriate insn_type and the appropriate emit_xxx
function for RVV patterns generation as needed.

Best,
Lehua

gcc/ChangeLog:

	* config/riscv/autovec-opt.md: Adjust.
	* config/riscv/autovec-vls.md: Ditto.
	* config/riscv/autovec.md: Ditto.
	* config/riscv/riscv-protos.h (enum insn_type): Add insn_type.
	(enum insn_flags): Add insn flags.
	(emit_vlmax_insn): Adjust.
	(emit_vlmax_fp_insn): Delete.
	(emit_vlmax_ternary_insn): Delete.
	(emit_vlmax_fp_ternary_insn): Delete.
	(emit_nonvlmax_insn): Adjust.
	(emit_vlmax_slide_insn): Delete.
	(emit_nonvlmax_slide_tu_insn): Delete.
	(emit_vlmax_merge_insn): Delete.
	(emit_vlmax_cmp_insn): Delete.
	(emit_vlmax_cmp_mu_insn): Delete.
	(emit_vlmax_masked_mu_insn): Delete.
	(emit_scalar_move_insn): Delete.
	(emit_nonvlmax_integer_move_insn): Delete.
	(emit_vlmax_insn_lra): Add.
	* config/riscv/riscv-v.cc (get_mask_mode_from_insn_flags): New.
	(emit_vlmax_insn): Adjust.
	(emit_nonvlmax_insn): Adjust.
	(emit_vlmax_insn_lra): Add.
	(emit_vlmax_fp_insn): Delete.
	(emit_vlmax_ternary_insn): Delete.
	(emit_vlmax_fp_ternary_insn): Delete.
	(emit_vlmax_slide_insn): Delete.
	(emit_nonvlmax_slide_tu_insn): Delete.
	(emit_nonvlmax_slide_insn): Delete.
	(emit_vlmax_merge_insn): Delete.
	(emit_vlmax_cmp_insn): Delete.
	(emit_vlmax_cmp_mu_insn): Delete.
	(emit_vlmax_masked_insn): Delete.
	(emit_nonvlmax_masked_insn): Delete.
	(emit_vlmax_masked_store_insn): Delete.
	(emit_nonvlmax_masked_store_insn): Delete.
	(emit_vlmax_masked_mu_insn): Delete.
	(emit_vlmax_masked_fp_mu_insn): Delete.
	(emit_nonvlmax_tu_insn): Delete.
	(emit_nonvlmax_fp_tu_insn): Delete.
	(emit_nonvlmax_tumu_insn): Delete.
	(emit_nonvlmax_fp_tumu_insn): Delete.
	(emit_scalar_move_insn): Delete.
	(emit_cpop_insn): Delete.
	(emit_vlmax_integer_move_insn): Delete.
	(emit_nonvlmax_integer_move_insn): Delete.
	(emit_vlmax_gather_insn): Delete.
	(emit_vlmax_masked_gather_mu_insn): Delete.
	(emit_vlmax_compress_insn): Delete.
	(emit_nonvlmax_compress_insn): Delete.
	(emit_vlmax_reduction_insn): Delete.
	(emit_vlmax_fp_reduction_insn): Delete.
	(emit_nonvlmax_fp_reduction_insn): Delete.
	(expand_vec_series): Adjust.
	(expand_const_vector): Adjust.
	(legitimize_move): Adjust.
	(sew64_scalar_helper): Adjust.
	(expand_tuple_move): Adjust.
	(expand_vector_init_insert_elems): Adjust.
	(expand_vector_init_merge_repeating_sequence): Adjust.
	(expand_vec_cmp): Adjust.
	(expand_vec_cmp_float): Adjust.
	(expand_vec_perm): Adjust.
	(shuffle_merge_patterns): Adjust.
	(shuffle_compress_patterns): Adjust.
	(shuffle_decompress_patterns): Adjust.
	(expand_load_store): Adjust.
	(expand_cond_len_op): Adjust.
	(expand_cond_len_unop): Adjust.
	(expand_cond_len_binop): Adjust.
	(expand_gather_scatter): Adjust.
	(expand_cond_len_ternop): Adjust.
	(expand_reduction): Adjust.
	(expand_lanes_load_store): Adjust.
	(expand_fold_extract_last): Adjust.
	* config/riscv/riscv.cc (vector_zero_call_used_regs): Adjust.
	* config/riscv/vector.md: Adjust.
---
 gcc/config/riscv/autovec-opt.md |   52 +-
 gcc/config/riscv/autovec-vls.md |   10 +-
 gcc/config/riscv/autovec.md     |  145 ++--
 gcc/config/riscv/riscv-protos.h |  195 +++++-
 gcc/config/riscv/riscv-v.cc     | 1131 +++++++++----------------------
 gcc/config/riscv/riscv.cc       |    4 +-
 gcc/config/riscv/vector.md      |   10 +-
 7 files changed, 594 insertions(+), 953 deletions(-)

diff --git a/gcc/config/riscv/autovec-opt.md b/gcc/config/riscv/autovec-opt.md
index 8247eb87ddb..899e44b63b5 100644
--- a/gcc/config/riscv/autovec-opt.md
+++ b/gcc/config/riscv/autovec-opt.md
@@ -45,7 +45,7 @@
     insn_code icode = code_for_pred_vf2 (<CODE>, <MODE>mode);
     rtx tmp = gen_reg_rtx (<MODE>mode);
     rtx ops[] = {tmp, operands[4]};
-    riscv_vector::emit_vlmax_insn (icode, riscv_vector::RVV_UNOP, ops);
+    riscv_vector::emit_vlmax_insn (icode, riscv_vector::UNARY_OP, ops);
 
     emit_insn (gen_pred (MULT, <MODE>mode, operands[0], operands[1], operands[2],
 			 operands[3], tmp, operands[5], operands[6],
@@ -138,7 +138,7 @@
   [(const_int 0)]
   {
     insn_code icode = code_for_pred_not (<CODE>, <MODE>mode);
-    riscv_vector::emit_vlmax_insn (icode, riscv_vector::RVV_BINOP, operands);
+    riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_MASK_OP, operands);
     DONE;
   }
   [(set_attr "type" "vmalu")
@@ -165,7 +165,7 @@
   [(const_int 0)]
   {
     insn_code icode = code_for_pred_n (<CODE>, <MODE>mode);
-    riscv_vector::emit_vlmax_insn (icode, riscv_vector::RVV_BINOP, operands);
+    riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_MASK_OP, operands);
     DONE;
   }
   [(set_attr "type" "vmalu")
@@ -202,8 +202,8 @@
   "&& 1"
   [(const_int 0)]
   {
-    riscv_vector::emit_vlmax_ternary_insn (code_for_pred_widen_mul_plus (<CODE>, <MODE>mode),
-					   riscv_vector::RVV_WIDEN_TERNOP, operands);
+    riscv_vector::emit_vlmax_insn (code_for_pred_widen_mul_plus (<CODE>, <MODE>mode),
+				    riscv_vector::WIDEN_TERNARY_OP, operands);
     DONE;
   }
   [(set_attr "type" "viwmuladd")
@@ -226,7 +226,7 @@
     insn_code icode = code_for_pred_vf2 (<CODE>, <MODE>mode);
     rtx tmp = gen_reg_rtx (<MODE>mode);
     rtx ext_ops[] = {tmp, operands[2]};
-    riscv_vector::emit_vlmax_insn (icode, riscv_vector::RVV_UNOP, ext_ops);
+    riscv_vector::emit_vlmax_insn (icode, riscv_vector::UNARY_OP, ext_ops);
 
     rtx dst = expand_ternary_op (<MODE>mode, fma_optab, tmp, operands[3],
 				 operands[1], operands[0], 0);
@@ -301,8 +301,8 @@
   "&& 1"
   [(const_int 0)]
   {
-    riscv_vector::emit_vlmax_ternary_insn (code_for_pred_widen_mul_plussu (<MODE>mode),
-					   riscv_vector::RVV_WIDEN_TERNOP, operands);
+    riscv_vector::emit_vlmax_insn (code_for_pred_widen_mul_plussu (<MODE>mode),
+				    riscv_vector::WIDEN_TERNARY_OP, operands);
     DONE;
   }
   [(set_attr "type" "viwmuladd")
@@ -324,8 +324,8 @@
   [(const_int 0)]
   {
     rtx ops[] = {operands[0], operands[1], operands[3], operands[2]};
-    riscv_vector::emit_vlmax_ternary_insn (code_for_pred_widen_mul_plussu (<MODE>mode),
-					   riscv_vector::RVV_WIDEN_TERNOP, ops);
+    riscv_vector::emit_vlmax_insn (code_for_pred_widen_mul_plussu (<MODE>mode),
+				    riscv_vector::WIDEN_TERNARY_OP, ops);
     DONE;
   }
   [(set_attr "type" "viwmuladd")
@@ -352,7 +352,7 @@
   [(const_int 0)]
 {
   insn_code icode = code_for_pred_narrow (<any_shiftrt:CODE>, <MODE>mode);
-  riscv_vector::emit_vlmax_insn (icode, riscv_vector::RVV_BINOP, operands);
+  riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP, operands);
   DONE;
 }
  [(set_attr "type" "vnshift")
@@ -371,7 +371,7 @@
 {
   operands[2] = gen_lowpart (Pmode, operands[2]);
   insn_code icode = code_for_pred_narrow_scalar (<any_shiftrt:CODE>, <MODE>mode);
-  riscv_vector::emit_vlmax_insn (icode, riscv_vector::RVV_BINOP, operands);
+  riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP, operands);
   DONE;
 }
  [(set_attr "type" "vnshift")
@@ -435,7 +435,7 @@
     insn_code icode = code_for_pred_extend (<MODE>mode);
     rtx tmp = gen_reg_rtx (<MODE>mode);
     rtx ops[] = {tmp, operands[4]};
-    riscv_vector::emit_vlmax_insn (icode, riscv_vector::RVV_UNOP, ops);
+    riscv_vector::emit_vlmax_insn (icode, riscv_vector::UNARY_OP, ops);
 
     emit_insn (gen_pred (MULT, <MODE>mode, operands[0], operands[1], operands[2],
                         operands[3], tmp, operands[5], operands[6],
@@ -470,8 +470,8 @@
   "&& 1"
   [(const_int 0)]
   {
-    riscv_vector::emit_vlmax_fp_ternary_insn (code_for_pred_widen_mul (PLUS, <MODE>mode),
-					      riscv_vector::RVV_WIDEN_TERNOP, operands);
+    riscv_vector::emit_vlmax_insn (code_for_pred_widen_mul (PLUS, <MODE>mode),
+				    riscv_vector::WIDEN_TERNARY_OP_FRM_DYN, operands);
     DONE;
   }
   [(set_attr "type" "vfwmuladd")
@@ -493,7 +493,7 @@
     insn_code icode = code_for_pred_extend (<MODE>mode);
     rtx tmp = gen_reg_rtx (<MODE>mode);
     rtx ext_ops[] = {tmp, operands[2]};
-    riscv_vector::emit_vlmax_insn (icode, riscv_vector::RVV_UNOP, ext_ops);
+    riscv_vector::emit_vlmax_insn (icode, riscv_vector::UNARY_OP, ext_ops);
 
     rtx dst = expand_ternary_op (<MODE>mode, fma_optab, tmp, operands[3],
 				 operands[1], operands[0], 0);
@@ -529,8 +529,8 @@
   "&& 1"
   [(const_int 0)]
   {
-    riscv_vector::emit_vlmax_fp_ternary_insn (code_for_pred_widen_mul_neg (PLUS, <MODE>mode),
-					      riscv_vector::RVV_WIDEN_TERNOP, operands);
+    riscv_vector::emit_vlmax_insn (code_for_pred_widen_mul_neg (PLUS, <MODE>mode),
+				    riscv_vector::WIDEN_TERNARY_OP_FRM_DYN, operands);
     DONE;
   }
   [(set_attr "type" "vfwmuladd")
@@ -553,7 +553,7 @@
     insn_code icode = code_for_pred_extend (<MODE>mode);
     rtx tmp = gen_reg_rtx (<MODE>mode);
     rtx ext_ops[] = {tmp, operands[2]};
-    riscv_vector::emit_vlmax_insn (icode, riscv_vector::RVV_UNOP, ext_ops);
+    riscv_vector::emit_vlmax_insn (icode, riscv_vector::UNARY_OP, ext_ops);
 
     rtx dst = expand_ternary_op (<MODE>mode, fnma_optab, tmp, operands[3],
 				 operands[1], operands[0], 0);
@@ -589,8 +589,8 @@
   "&& 1"
   [(const_int 0)]
   {
-    riscv_vector::emit_vlmax_fp_ternary_insn (code_for_pred_widen_mul (MINUS, <MODE>mode),
-					      riscv_vector::RVV_WIDEN_TERNOP, operands);
+    riscv_vector::emit_vlmax_insn (code_for_pred_widen_mul (MINUS, <MODE>mode),
+				    riscv_vector::WIDEN_TERNARY_OP_FRM_DYN, operands);
     DONE;
   }
   [(set_attr "type" "vfwmuladd")
@@ -613,7 +613,7 @@
     insn_code icode = code_for_pred_extend (<MODE>mode);
     rtx tmp = gen_reg_rtx (<MODE>mode);
     rtx ext_ops[] = {tmp, operands[2]};
-    riscv_vector::emit_vlmax_insn (icode, riscv_vector::RVV_UNOP, ext_ops);
+    riscv_vector::emit_vlmax_insn (icode, riscv_vector::UNARY_OP, ext_ops);
 
     rtx dst = expand_ternary_op (<MODE>mode, fms_optab, tmp, operands[3],
 				 operands[1], operands[0], 0);
@@ -650,8 +650,8 @@
   "&& 1"
   [(const_int 0)]
   {
-    riscv_vector::emit_vlmax_fp_ternary_insn (code_for_pred_widen_mul_neg (MINUS, <MODE>mode),
-					      riscv_vector::RVV_WIDEN_TERNOP, operands);
+    riscv_vector::emit_vlmax_insn (code_for_pred_widen_mul_neg (MINUS, <MODE>mode),
+				    riscv_vector::WIDEN_TERNARY_OP_FRM_DYN, operands);
     DONE;
   }
   [(set_attr "type" "vfwmuladd")
@@ -675,7 +675,7 @@
     insn_code icode = code_for_pred_extend (<MODE>mode);
     rtx tmp = gen_reg_rtx (<MODE>mode);
     rtx ext_ops[] = {tmp, operands[2]};
-    riscv_vector::emit_vlmax_insn (icode, riscv_vector::RVV_UNOP, ext_ops);
+    riscv_vector::emit_vlmax_insn (icode, riscv_vector::UNARY_OP, ext_ops);
 
     rtx dst = expand_ternary_op (<MODE>mode, fnms_optab, tmp, operands[3],
 				 operands[1], operands[0], 0);
@@ -720,6 +720,6 @@
   [(const_int 0)]
 {
   riscv_vector::emit_vlmax_insn (code_for_pred_ncopysign (<MODE>mode),
-                                 riscv_vector::RVV_BINOP, operands);
+                                  riscv_vector::BINARY_OP, operands);
   DONE;
 })
diff --git a/gcc/config/riscv/autovec-vls.md b/gcc/config/riscv/autovec-vls.md
index 0e4701a96df..503ad691b9a 100644
--- a/gcc/config/riscv/autovec-vls.md
+++ b/gcc/config/riscv/autovec-vls.md
@@ -129,7 +129,7 @@
       emit_move_insn (operands[2], gen_int_mode (GET_MODE_NUNITS (<VLS_AVL_REG:MODE>mode),
 						 Pmode));
       riscv_vector::emit_nonvlmax_insn (code_for_pred_mov (<VLS_AVL_REG:MODE>mode),
-					riscv_vector::RVV_UNOP, operands, operands[2]);
+					 riscv_vector::UNARY_OP, operands, operands[2]);
     }
   DONE;
 }
@@ -158,7 +158,7 @@
     operands[1] = gen_lowpart (mode, operands[1]);
     if (MEM_P (operands[0]) && !register_operand (operands[1], mode))
       operands[1] = force_reg (mode, operands[1]);
-    riscv_vector::emit_vlmax_insn (code_for_pred_mov (mode), riscv_vector::RVV_UNOP, operands);
+    riscv_vector::emit_vlmax_insn (code_for_pred_mov (mode), riscv_vector::UNARY_OP, operands);
     DONE;
   }
 )
@@ -177,7 +177,7 @@
   [(const_int 0)]
   {
     riscv_vector::emit_vlmax_insn (code_for_pred_broadcast (<MODE>mode),
-                                   riscv_vector::RVV_UNOP, operands);
+                                   riscv_vector::UNARY_OP, operands);
     DONE;
   }
   [(set_attr "type" "vector")]
@@ -202,7 +202,7 @@
   [(const_int 0)]
 {
   riscv_vector::emit_vlmax_insn (code_for_pred (<CODE>, <MODE>mode),
-				 riscv_vector::RVV_BINOP, operands);
+				  riscv_vector::BINARY_OP, operands);
   DONE;
 }
 [(set_attr "type" "vector")]
@@ -225,7 +225,7 @@
   [(const_int 0)]
 {
   insn_code icode = code_for_pred (<CODE>, <MODE>mode);
-  riscv_vector::emit_vlmax_insn (icode, riscv_vector::RVV_UNOP, operands);
+  riscv_vector::emit_vlmax_insn (icode, riscv_vector::UNARY_OP, operands);
   DONE;
 }
 [(set_attr "type" "vector")]
diff --git a/gcc/config/riscv/autovec.md b/gcc/config/riscv/autovec.md
index 6cfdd7fc9f4..3e0a1da3651 100644
--- a/gcc/config/riscv/autovec.md
+++ b/gcc/config/riscv/autovec.md
@@ -390,8 +390,8 @@
   "TARGET_VECTOR"
 {
   insn_code icode = code_for_pred_slide (UNSPEC_VSLIDE1UP, <MODE>mode);
-  rtx ops[] = {operands[0], RVV_VUNDEF (<MODE>mode), operands[1], operands[2]};
-  riscv_vector::emit_vlmax_slide_insn (icode, ops);
+  rtx ops[] = {operands[0], operands[1], operands[2]};
+  riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP, ops);
   DONE;
 })
 
@@ -402,8 +402,8 @@
   "TARGET_VECTOR"
 {
   insn_code icode = code_for_pred_slide (UNSPEC_VFSLIDE1UP, <MODE>mode);
-  rtx ops[] = {operands[0], RVV_VUNDEF (<MODE>mode), operands[1], operands[2]};
-  riscv_vector::emit_vlmax_slide_insn (icode, ops);
+  rtx ops[] = {operands[0], operands[1], operands[2]};
+  riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP, ops);
   DONE;
 })
 
@@ -427,7 +427,7 @@
   "TARGET_VECTOR"
 {
   riscv_vector::emit_vlmax_insn (code_for_pred (<CODE>, <MODE>mode),
-				 riscv_vector::RVV_BINOP, operands);
+				 riscv_vector::BINARY_OP, operands);
   DONE;
 })
 
@@ -451,7 +451,7 @@
 {
   operands[2] = gen_lowpart (Pmode, operands[2]);
   riscv_vector::emit_vlmax_insn (code_for_pred_scalar (<CODE>, <MODE>mode),
-				 riscv_vector::RVV_BINOP, operands);
+				 riscv_vector::BINARY_OP, operands);
   DONE;
 }
  [(set_attr "type" "vshift")
@@ -475,7 +475,7 @@
   [(const_int 0)]
 {
   riscv_vector::emit_vlmax_insn (code_for_pred (<CODE>, <MODE>mode),
-				 riscv_vector::RVV_BINOP, operands);
+				 riscv_vector::BINARY_OP, operands);
   DONE;
 }
  [(set_attr "type" "vshift")
@@ -500,7 +500,7 @@
   [(const_int 0)]
   {
     insn_code icode = code_for_pred (<CODE>, <MODE>mode);
-    riscv_vector::emit_vlmax_insn (icode, riscv_vector::RVV_BINOP, operands);
+    riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_MASK_OP, operands);
     DONE;
   }
   [(set_attr "type" "vmalu")
@@ -522,7 +522,7 @@
   [(const_int 0)]
   {
     insn_code icode = code_for_pred_not (<MODE>mode);
-    riscv_vector::emit_vlmax_insn (icode, riscv_vector::RVV_UNOP, operands);
+    riscv_vector::emit_vlmax_insn (icode, riscv_vector::UNARY_MASK_OP, operands);
     DONE;
   }
   [(set_attr "type" "vmalu")
@@ -554,8 +554,8 @@
   {
     /* The order of vcond_mask is opposite to pred_merge.  */
     std::swap (operands[1], operands[2]);
-    riscv_vector::emit_vlmax_merge_insn (code_for_pred_merge (<MODE>mode),
-    			riscv_vector::RVV_MERGE_OP, operands);
+    riscv_vector::emit_vlmax_insn (code_for_pred_merge (<MODE>mode),
+                                   riscv_vector::MERGE_OP, operands);
     DONE;
   }
 )
@@ -627,7 +627,7 @@
   [(const_int 0)]
 {
   insn_code icode = code_for_pred_vf2 (<CODE>, <MODE>mode);
-  riscv_vector::emit_vlmax_insn (icode, riscv_vector::RVV_UNOP, operands);
+  riscv_vector::emit_vlmax_insn (icode, riscv_vector::UNARY_OP, operands);
   DONE;
 }
   [(set_attr "type" "vext")
@@ -640,7 +640,7 @@
   "TARGET_VECTOR"
 {
   insn_code icode = code_for_pred_vf4 (<CODE>, <MODE>mode);
-  riscv_vector::emit_vlmax_insn (icode, riscv_vector::RVV_UNOP, operands);
+  riscv_vector::emit_vlmax_insn (icode, riscv_vector::UNARY_OP, operands);
   DONE;
 })
 
@@ -651,7 +651,7 @@
   "TARGET_VECTOR"
 {
   insn_code icode = code_for_pred_vf8 (<CODE>, <MODE>mode);
-  riscv_vector::emit_vlmax_insn (icode, riscv_vector::RVV_UNOP, operands);
+  riscv_vector::emit_vlmax_insn (icode, riscv_vector::UNARY_OP, operands);
   DONE;
 })
 
@@ -670,7 +670,7 @@
   [(const_int 0)]
 {
   insn_code icode = code_for_pred_trunc (<MODE>mode);
-  riscv_vector::emit_vlmax_insn (icode, riscv_vector::RVV_UNOP, operands);
+  riscv_vector::emit_vlmax_insn (icode, riscv_vector::UNARY_OP, operands);
   DONE;
 }
   [(set_attr "type" "vshift")
@@ -689,11 +689,11 @@
   rtx half = gen_reg_rtx (<V_DOUBLE_TRUNC>mode);
   rtx opshalf[] = {half, operands[1]};
   insn_code icode = code_for_pred_trunc (<MODE>mode);
-  riscv_vector::emit_vlmax_insn (icode, riscv_vector::RVV_UNOP, opshalf);
+  riscv_vector::emit_vlmax_insn (icode, riscv_vector::UNARY_OP, opshalf);
 
   rtx ops[] = {operands[0], half};
   icode = code_for_pred_trunc (<V_DOUBLE_TRUNC>mode);
-  riscv_vector::emit_vlmax_insn (icode, riscv_vector::RVV_UNOP, ops);
+  riscv_vector::emit_vlmax_insn (icode, riscv_vector::UNARY_OP, ops);
   DONE;
 })
 
@@ -710,16 +710,16 @@
   rtx half = gen_reg_rtx (<V_DOUBLE_TRUNC>mode);
   rtx opshalf[] = {half, operands[1]};
   insn_code icode = code_for_pred_trunc (<MODE>mode);
-  riscv_vector::emit_vlmax_insn (icode, riscv_vector::RVV_UNOP, opshalf);
+  riscv_vector::emit_vlmax_insn (icode, riscv_vector::UNARY_OP, opshalf);
 
   rtx quarter = gen_reg_rtx (<V_QUAD_TRUNC>mode);
   rtx opsquarter[] = {quarter, half};
   icode = code_for_pred_trunc (<V_DOUBLE_TRUNC>mode);
-  riscv_vector::emit_vlmax_insn (icode, riscv_vector::RVV_UNOP, opsquarter);
+  riscv_vector::emit_vlmax_insn (icode, riscv_vector::UNARY_OP, opsquarter);
 
   rtx ops[] = {operands[0], quarter};
   icode = code_for_pred_trunc (<V_QUAD_TRUNC>mode);
-  riscv_vector::emit_vlmax_insn (icode, riscv_vector::RVV_UNOP, ops);
+  riscv_vector::emit_vlmax_insn (icode, riscv_vector::UNARY_OP, ops);
   DONE;
 })
 
@@ -738,7 +738,7 @@
   [(const_int 0)]
 {
   insn_code icode = code_for_pred_extend (<MODE>mode);
-  riscv_vector::emit_vlmax_insn (icode, riscv_vector::RVV_UNOP, operands);
+  riscv_vector::emit_vlmax_insn (icode, riscv_vector::UNARY_OP, operands);
   DONE;
 }
   [(set_attr "type" "vfwcvtftof")
@@ -753,11 +753,11 @@
   rtx dblw = gen_reg_rtx (<V_DOUBLE_TRUNC>mode);
   insn_code icode = code_for_pred_extend (<V_DOUBLE_TRUNC>mode);
   rtx ops1[] = {dblw, operands[1]};
-  riscv_vector::emit_vlmax_insn (icode, riscv_vector::RVV_UNOP, ops1);
+  riscv_vector::emit_vlmax_insn (icode, riscv_vector::UNARY_OP, ops1);
 
   icode = code_for_pred_extend (<MODE>mode);
   rtx ops2[] = {operands[0], dblw};
-  riscv_vector::emit_vlmax_insn (icode, riscv_vector::RVV_UNOP, ops2);
+  riscv_vector::emit_vlmax_insn (icode, riscv_vector::UNARY_OP, ops2);
   DONE;
 })
 
@@ -776,7 +776,7 @@
   [(const_int 0)]
 {
   insn_code icode = code_for_pred_trunc (<MODE>mode);
-  riscv_vector::emit_vlmax_fp_insn (icode, riscv_vector::RVV_UNOP, operands);
+  riscv_vector::emit_vlmax_insn (icode, riscv_vector::UNARY_OP_FRM_DYN, operands);
   DONE;
 }
   [(set_attr "type" "vfncvtftof")
@@ -798,11 +798,11 @@
   /* According to the RISC-V V Spec 13.19. we need to use
      vfncvt.rod.f.f.w for all steps but the last.  */
   insn_code icode = code_for_pred_rod_trunc (<MODE>mode);
-  riscv_vector::emit_vlmax_insn (icode, riscv_vector::RVV_UNOP, opshalf);
+  riscv_vector::emit_vlmax_insn (icode, riscv_vector::UNARY_OP, opshalf);
 
   rtx ops[] = {operands[0], half};
   icode = code_for_pred_trunc (<V_DOUBLE_TRUNC>mode);
-  riscv_vector::emit_vlmax_fp_insn (icode, riscv_vector::RVV_UNOP, ops);
+  riscv_vector::emit_vlmax_insn (icode, riscv_vector::UNARY_OP_FRM_DYN, ops);
   DONE;
 })
 
@@ -826,7 +826,7 @@
   "TARGET_VECTOR"
 {
   insn_code icode = code_for_pred (<CODE>, <MODE>mode);
-  riscv_vector::emit_vlmax_insn (icode, riscv_vector::RVV_UNOP, operands);
+  riscv_vector::emit_vlmax_insn (icode, riscv_vector::UNARY_OP, operands);
   DONE;
 })
 
@@ -845,7 +845,7 @@
   "TARGET_VECTOR"
 {
   insn_code icode = code_for_pred (<CODE>, <MODE>mode);
-  riscv_vector::emit_vlmax_fp_insn (icode, riscv_vector::RVV_UNOP, operands);
+  riscv_vector::emit_vlmax_insn (icode, riscv_vector::UNARY_OP_FRM_DYN, operands);
   DONE;
 })
 
@@ -867,7 +867,7 @@
   "TARGET_VECTOR"
 {
   insn_code icode = code_for_pred_widen (<CODE>, <MODE>mode);
-  riscv_vector::emit_vlmax_insn (icode, riscv_vector::RVV_UNOP, operands);
+  riscv_vector::emit_vlmax_insn (icode, riscv_vector::UNARY_OP, operands);
   DONE;
 })
 
@@ -885,7 +885,7 @@
   "TARGET_VECTOR"
 {
   insn_code icode = code_for_pred_widen (<CODE>, <MODE>mode);
-  riscv_vector::emit_vlmax_insn (icode, riscv_vector::RVV_UNOP, operands);
+  riscv_vector::emit_vlmax_insn (icode, riscv_vector::UNARY_OP, operands);
   DONE;
 })
 
@@ -903,7 +903,7 @@
   "TARGET_VECTOR"
 {
   insn_code icode = code_for_pred_narrow (<CODE>, <MODE>mode);
-  riscv_vector::emit_vlmax_insn (icode, riscv_vector::RVV_UNOP, operands);
+  riscv_vector::emit_vlmax_insn (icode, riscv_vector::UNARY_OP, operands);
   DONE;
 })
 
@@ -921,7 +921,7 @@
   "TARGET_VECTOR"
 {
   insn_code icode = code_for_pred_narrow (<CODE>, <MODE>mode);
-  riscv_vector::emit_vlmax_fp_insn (icode, riscv_vector::RVV_UNOP, operands);
+  riscv_vector::emit_vlmax_insn (icode, riscv_vector::UNARY_OP_FRM_DYN, operands);
   DONE;
 })
 
@@ -942,7 +942,7 @@
   "TARGET_VECTOR"
 {
   insn_code icode = code_for_pred (<CODE>, <MODE>mode);
-  riscv_vector::emit_vlmax_insn (icode, riscv_vector::RVV_UNOP, operands);
+  riscv_vector::emit_vlmax_insn (icode, riscv_vector::UNARY_OP, operands);
   DONE;
 })
 
@@ -960,9 +960,9 @@
   rtx mask = gen_reg_rtx (mask_mode);
   riscv_vector::expand_vec_cmp (mask, LT, operands[1], zero);
 
-  rtx ops[] = {operands[0], mask, operands[1], operands[1],
-               riscv_vector::get_vlmax_rtx (<MODE>mode)};
-  riscv_vector::expand_cond_len_unop (NEG, ops);
+  rtx ops[] = {operands[0], mask, operands[1], operands[1]};
+  riscv_vector::emit_vlmax_insn (code_for_pred (NEG, <MODE>mode),
+                                  riscv_vector::UNARY_OP_TAMU, ops);
   DONE;
 })
 
@@ -982,7 +982,7 @@
   [(const_int 0)]
 {
   insn_code icode = code_for_pred (<CODE>, <MODE>mode);
-  riscv_vector::emit_vlmax_insn (icode, riscv_vector::RVV_UNOP, operands);
+  riscv_vector::emit_vlmax_insn (icode, riscv_vector::UNARY_OP, operands);
   DONE;
 })
 
@@ -999,7 +999,7 @@
   "TARGET_VECTOR"
 {
   insn_code icode = code_for_pred (<CODE>, <MODE>mode);
-  riscv_vector::emit_vlmax_fp_insn (icode, riscv_vector::RVV_UNOP, operands);
+  riscv_vector::emit_vlmax_insn (icode, riscv_vector::UNARY_OP_FRM_DYN, operands);
   DONE;
 })
 
@@ -1060,8 +1060,8 @@
   {
     riscv_vector::emit_vlmax_vsetvl (<VI:MODE>mode, operands[4]);
     rtx ops[] = {operands[0], operands[1], operands[2], operands[3], operands[0]};
-    riscv_vector::emit_vlmax_ternary_insn (code_for_pred_mul_plus (<VI:MODE>mode),
-					   riscv_vector::RVV_TERNOP, ops, operands[4]);
+    riscv_vector::emit_vlmax_insn_lra (code_for_pred_mul_plus (<VI:MODE>mode),
+					riscv_vector::TERNARY_OP, ops, operands[4]);
     DONE;
   }
   [(set_attr "type" "vimuladd")
@@ -1104,8 +1104,8 @@
   {
     riscv_vector::emit_vlmax_vsetvl (<VI:MODE>mode, operands[4]);
     rtx ops[] = {operands[0], operands[1], operands[2], operands[3], operands[0]};
-    riscv_vector::emit_vlmax_ternary_insn (code_for_pred_minus_mul (<VI:MODE>mode),
-    					   riscv_vector::RVV_TERNOP, ops, operands[4]);
+    riscv_vector::emit_vlmax_insn_lra (code_for_pred_minus_mul (<VI:MODE>mode),
+                                       riscv_vector::TERNARY_OP, ops, operands[4]);
     DONE;
   }
   [(set_attr "type" "vimuladd")
@@ -1146,8 +1146,8 @@
   {
     riscv_vector::emit_vlmax_vsetvl (<VF:MODE>mode, operands[4]);
     rtx ops[] = {operands[0], operands[1], operands[2], operands[3], operands[0]};
-    riscv_vector::emit_vlmax_fp_ternary_insn (code_for_pred_mul (PLUS, <VF:MODE>mode),
-					      riscv_vector::RVV_TERNOP, ops, operands[4]);
+    riscv_vector::emit_vlmax_insn_lra (code_for_pred_mul (PLUS, <VF:MODE>mode),
+					riscv_vector::TERNARY_OP_FRM_DYN, ops, operands[4]);
     DONE;
   }
   [(set_attr "type" "vfmuladd")
@@ -1190,8 +1190,8 @@
   {
     riscv_vector::emit_vlmax_vsetvl (<VF:MODE>mode, operands[4]);
     rtx ops[] = {operands[0], operands[1], operands[2], operands[3], operands[0]};
-    riscv_vector::emit_vlmax_fp_ternary_insn (code_for_pred_mul_neg (PLUS, <VF:MODE>mode),
-					      riscv_vector::RVV_TERNOP, ops, operands[4]);
+    riscv_vector::emit_vlmax_insn_lra (code_for_pred_mul_neg (PLUS, <VF:MODE>mode),
+					riscv_vector::TERNARY_OP_FRM_DYN, ops, operands[4]);
     DONE;
   }
   [(set_attr "type" "vfmuladd")
@@ -1234,8 +1234,8 @@
   {
     riscv_vector::emit_vlmax_vsetvl (<VF:MODE>mode, operands[4]);
     rtx ops[] = {operands[0], operands[1], operands[2], operands[3], operands[0]};
-    riscv_vector::emit_vlmax_fp_ternary_insn (code_for_pred_mul (MINUS, <VF:MODE>mode),
-					      riscv_vector::RVV_TERNOP, ops, operands[4]);
+    riscv_vector::emit_vlmax_insn_lra (code_for_pred_mul (MINUS, <VF:MODE>mode),
+					riscv_vector::TERNARY_OP_FRM_DYN, ops, operands[4]);
     DONE;
   }
   [(set_attr "type" "vfmuladd")
@@ -1280,8 +1280,8 @@
   {
     riscv_vector::emit_vlmax_vsetvl (<VF:MODE>mode, operands[4]);
     rtx ops[] = {operands[0], operands[1], operands[2], operands[3], operands[0]};
-    riscv_vector::emit_vlmax_fp_ternary_insn (code_for_pred_mul_neg (MINUS, <VF:MODE>mode),
-					      riscv_vector::RVV_TERNOP, ops, operands[4]);
+    riscv_vector::emit_vlmax_insn_lra (code_for_pred_mul_neg (MINUS, <VF:MODE>mode),
+					riscv_vector::TERNARY_OP_FRM_DYN, ops, operands[4]);
     DONE;
   }
   [(set_attr "type" "vfmuladd")
@@ -1314,10 +1314,9 @@
   /* If we set the first element, emit an v(f)mv.s.[xf].  */
   if (operands[2] == const0_rtx)
     {
-      rtx ops[] = {operands[0], riscv_vector::gen_scalar_move_mask (<VM>mode),
-		   RVV_VUNDEF (<MODE>mode), operands[1]};
-      riscv_vector::emit_scalar_move_insn
-	  (code_for_pred_broadcast (<MODE>mode), ops);
+      rtx ops[] = {operands[0], operands[1]};
+      riscv_vector::emit_nonvlmax_insn (code_for_pred_broadcast (<MODE>mode),
+                                         riscv_vector::SCALAR_MOVE_OP, ops, CONST1_RTX (Pmode));
     }
   else
     {
@@ -1341,14 +1340,14 @@
 	 VL we need for the slide.  */
       rtx tmp = gen_reg_rtx (<MODE>mode);
       rtx ops1[] = {tmp, operands[1]};
-      riscv_vector::emit_nonvlmax_integer_move_insn
-	(code_for_pred_broadcast (<MODE>mode), ops1, length);
+      emit_nonvlmax_insn (code_for_pred_broadcast (<MODE>mode),
+                           riscv_vector::UNARY_OP, ops1, length);
 
       /* Slide exactly one element up leaving the tail elements
 	 unchanged.  */
       rtx ops2[] = {operands[0], operands[0], tmp, operands[2]};
-      riscv_vector::emit_nonvlmax_slide_tu_insn
-	(code_for_pred_slide (UNSPEC_VSLIDEUP, <MODE>mode), ops2, length);
+      riscv_vector::emit_nonvlmax_insn
+	(code_for_pred_slide (UNSPEC_VSLIDEUP, <MODE>mode), riscv_vector::BINARY_OP_TUMA, ops2, length);
     }
   DONE;
 })
@@ -1375,9 +1374,9 @@
       /* Emit the slide down to index 0 in a new vector.  */
       tmp = gen_reg_rtx (<MODE>mode);
       operands[2] = gen_lowpart (Pmode, operands[2]);
-      rtx ops[] = {tmp, RVV_VUNDEF (<MODE>mode), operands[1], operands[2]};
-      riscv_vector::emit_vlmax_slide_insn
-	(code_for_pred_slide (UNSPEC_VSLIDEDOWN, <MODE>mode), ops);
+      rtx ops[] = {tmp, operands[1], operands[2]};
+      riscv_vector::emit_vlmax_insn
+	(code_for_pred_slide (UNSPEC_VSLIDEDOWN, <MODE>mode), riscv_vector::BINARY_OP, ops);
     }
 
   /* Emit v(f)mv.[xf].s.  */
@@ -1400,8 +1399,8 @@
     (match_operand:VF 2 "register_operand"))]
   "TARGET_VECTOR"
 {
-  riscv_vector::emit_vlmax_fp_insn (code_for_pred (<CODE>, <MODE>mode),
-				    riscv_vector::RVV_BINOP, operands);
+  riscv_vector::emit_vlmax_insn (code_for_pred (<CODE>, <MODE>mode),
+				    riscv_vector::BINARY_OP_FRM_DYN, operands);
   DONE;
 })
 
@@ -1418,7 +1417,7 @@
   "TARGET_VECTOR"
 {
   riscv_vector::emit_vlmax_insn (code_for_pred (<CODE>, <MODE>mode),
-				 riscv_vector::RVV_BINOP, operands);
+				  riscv_vector::BINARY_OP, operands);
   DONE;
 })
 
@@ -1443,7 +1442,7 @@
   [(const_int 0)]
 {
   riscv_vector::emit_vlmax_insn (code_for_pred (UNSPEC_VCOPYSIGN, <MODE>mode),
-				 riscv_vector::RVV_BINOP, operands);
+				  riscv_vector::BINARY_OP, operands);
   DONE;
 }
   [(set_attr "type" "vfsgnj")
@@ -1461,7 +1460,7 @@
   "TARGET_VECTOR"
 {
   riscv_vector::emit_vlmax_insn (code_for_pred (UNSPEC_VXORSIGN, <MODE>mode),
-				 riscv_vector::RVV_BINOP, operands);
+				  riscv_vector::BINARY_OP, operands);
   DONE;
 })
 
@@ -1480,7 +1479,7 @@
   "TARGET_VECTOR"
 {
   insn_code icode = code_for_pred_mulh (UNSPEC_VMULHS, <MODE>mode);
-  riscv_vector::emit_vlmax_insn (icode, riscv_vector::RVV_BINOP, operands);
+  riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP, operands);
   DONE;
 })
 
@@ -1491,7 +1490,7 @@
   "TARGET_VECTOR"
 {
   insn_code icode = code_for_pred_mulh (UNSPEC_VMULHU, <MODE>mode);
-  riscv_vector::emit_vlmax_insn (icode, riscv_vector::RVV_BINOP, operands);
+  riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP, operands);
   DONE;
 })
 
@@ -2164,12 +2163,12 @@
   rtx tmp1 = gen_reg_rtx (<MODE>mode);
   rtx ops1[] = {tmp1, operands[1], operands[2]};
   insn_code icode = code_for_pred_dual_widen (PLUS, <CODE>, <MODE>mode);
-  riscv_vector::emit_vlmax_insn (icode, riscv_vector::RVV_BINOP, ops1);
+  riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP, ops1);
 
   /* Then a narrowing shift.  */
   rtx ops2[] = {operands[0], tmp1, const1_rtx};
   icode = code_for_pred_narrow_scalar (<EXT_TO_RSHIFT>, <MODE>mode);
-  riscv_vector::emit_vlmax_insn (icode, riscv_vector::RVV_BINOP, ops2);
+  riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP, ops2);
   DONE;
 })
 
@@ -2190,17 +2189,17 @@
   rtx tmp1 = gen_reg_rtx (<MODE>mode);
   rtx ops1[] = {tmp1, operands[1], operands[2]};
   insn_code icode = code_for_pred_dual_widen (PLUS, <CODE>, <MODE>mode);
-  riscv_vector::emit_vlmax_insn (icode, riscv_vector::RVV_BINOP, ops1);
+  riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP, ops1);
 
   /* Then add 1.  */
   rtx tmp2 = gen_reg_rtx (<MODE>mode);
   rtx ops2[] = {tmp2, tmp1, const1_rtx};
   icode = code_for_pred_scalar (PLUS, <MODE>mode);
-  riscv_vector::emit_vlmax_insn (icode, riscv_vector::RVV_BINOP, ops2);
+  riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP, ops2);
 
   /* Finally, a narrowing shift.  */
   rtx ops3[] = {operands[0], tmp2, const1_rtx};
   icode = code_for_pred_narrow_scalar (<EXT_TO_RSHIFT>, <MODE>mode);
-  riscv_vector::emit_vlmax_insn (icode, riscv_vector::RVV_BINOP, ops3);
+  riscv_vector::emit_vlmax_insn (icode, riscv_vector::BINARY_OP, ops3);
   DONE;
 })
diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h
index 65d20cebd9e..92e30a10f3c 100644
--- a/gcc/config/riscv/riscv-protos.h
+++ b/gcc/config/riscv/riscv-protos.h
@@ -184,29 +184,166 @@ namespace riscv_vector {
   gen_rtx_UNSPEC (MODE, gen_rtvec (1, gen_rtx_REG (SImode, X0_REGNUM)),        \
 		  UNSPEC_VUNDEF)
 
-/* The value means the number of operands for insn_expander.  */
-enum insn_type
+/* These flags describe how to pass the operands to a rvv insn pattern.
+   e.g.:
+     If a insn has this flags:
+       HAS_DEST_P | HAS_MASK_P | USE_VUNDEF_MERGE_P
+	 | TU_POLICY_P | BINARY_OP_P | FRM_DYN_P
+     that means:
+       operands[0] is the dest operand
+       operands[1] is the mask operand
+       operands[2] is the merge operand
+       operands[3] and operands[4] is the two operand to do the operation.
+       operands[5] is the vl operand
+       operands[6] is the tail policy operand
+       operands[7] is the mask policy operands
+       operands[8] is the rounding mode operands
+
+     Then you can call `emit_vlmax_insn (flags, icode, ops)` to emit a insn.
+     and ops[0] is the dest operand (operands[0]), ops[1] is the mask
+     operand (operands[1]), ops[2] and ops[3] is the two
+     operands (operands[3], operands[4]) to do the operation. Other operands
+     will be created by emit_vlmax_insn according to the flags information.
+*/
+enum insn_flags : unsigned int
 {
-  RVV_MISC_OP = 1,
-  RVV_UNOP = 2,
-  RVV_UNOP_MASK = RVV_UNOP + 2,
-  RVV_BINOP = 3,
-  RVV_BINOP_MASK = RVV_BINOP + 2,
-  RVV_MERGE_OP = 4,
-  RVV_CMP_OP = 4,
-  RVV_CMP_MU_OP = RVV_CMP_OP + 2, /* +2 means mask and maskoff operand.  */
-  RVV_TERNOP = 5,
-  RVV_TERNOP_MASK = RVV_TERNOP + 1,
-  RVV_WIDEN_TERNOP = 4,
-  RVV_SCALAR_MOV_OP = 4, /* +1 for VUNDEF according to vector.md.  */
-  RVV_SLIDE_OP = 4,      /* Dest, VUNDEF, source and offset.  */
-  RVV_COMPRESS_OP = 4,
-  RVV_GATHER_M_OP = 5,
-  RVV_SCATTER_M_OP = 4,
-  RVV_REDUCTION_OP = 3,
-  RVV_REDUCTION_TU_OP = RVV_REDUCTION_OP + 2,
-  RVV_CPOP = 2,
+  /* flags for dest, mask, merge operands.  */
+  /* Means INSN has dest operand. False for STORE insn.  */
+  HAS_DEST_P = 1 << 0,
+  /* Means INSN has mask operand.  */
+  HAS_MASK_P = 1 << 1,
+  /* Means using ALL_TRUES for mask operand.  */
+  USE_ALL_TRUES_MASK_P = 1 << 2,
+  /* Means using ONE_TRUE for mask operand.  */
+  USE_ONE_TRUE_MASK_P = 1 << 3,
+  /* Means INSN has merge operand.  */
+  HAS_MERGE_P = 1 << 4,
+  /* Means using VUNDEF for merge operand.  */
+  USE_VUNDEF_MERGE_P = 1 << 5,
+
+  /* flags for tail policy and mask plicy operands.  */
+  /* Means the tail policy is TAIL_UNDISTURBED.  */
+  TU_POLICY_P = 1 << 6,
+  /* Means the tail policy is default (return by get_prefer_tail_policy).  */
+  TDEFAULT_POLICY_P = 1 << 7,
+  /* Means the mask policy is MASK_UNDISTURBED.  */
+  MU_POLICY_P = 1 << 8,
+  /* Means the mask policy is default (return by get_prefer_mask_policy).  */
+  MDEFAULT_POLICY_P = 1 << 9,
+
+  /* flags for the number operands to do the operation.  */
+  /* Means INSN need zero operand to do the operation. e.g. vid.v */
+  NULLARY_OP_P = 1 << 10,
+  /* Means INSN need one operand to do the operation.  */
+  UNARY_OP_P = 1 << 11,
+  /* Means INSN need two operands to do the operation.  */
+  BINARY_OP_P = 1 << 12,
+  /* Means INSN need two operands to do the operation.  */
+  TERNARY_OP_P = 1 << 13,
+
+  /* flags for get mask mode from the index number. default from dest operand.  */
+  MASK_MODE_FROM_OP1_P = 1 << 14,
+
+  /* flags for the floating-point rounding mode.  */
+  /* Means INSN has FRM operand and the value is FRM_DYN.  */
+  FRM_DYN_P = 1 << 15,
 };
+
+enum insn_type : unsigned int
+{
+  /* some flags macros.  */
+  /* For non-mask insn with tama.  */
+  __NORMAL_OP = HAS_DEST_P | HAS_MASK_P | USE_ALL_TRUES_MASK_P | HAS_MERGE_P
+		| USE_VUNDEF_MERGE_P | TDEFAULT_POLICY_P | MDEFAULT_POLICY_P,
+  /* For non-mask insn with ta, without mask policy operand.  */
+  __NORMAL_OP_TA = HAS_DEST_P | HAS_MASK_P | USE_ALL_TRUES_MASK_P | HAS_MERGE_P
+		   | USE_VUNDEF_MERGE_P | TDEFAULT_POLICY_P,
+  /* For non-mask insn with ta, without mask operand and mask policy operand. */
+  __NORMAL_OP_TA2
+  = HAS_DEST_P | HAS_MERGE_P | USE_VUNDEF_MERGE_P | TDEFAULT_POLICY_P,
+  /* For non-mask insn with ma, without tail policy operand.  */
+  __NORMAL_OP_MA = HAS_DEST_P | HAS_MASK_P | USE_ALL_TRUES_MASK_P | HAS_MERGE_P
+		   | USE_VUNDEF_MERGE_P | MDEFAULT_POLICY_P,
+  /* For mask insn with tama.  */
+  __MASK_OP_TAMA = HAS_DEST_P | HAS_MASK_P | HAS_MERGE_P | USE_VUNDEF_MERGE_P
+		   | TDEFAULT_POLICY_P | MDEFAULT_POLICY_P,
+  /* For mask insn with tamu.  */
+  __MASK_OP_TAMU
+  = HAS_DEST_P | HAS_MASK_P | HAS_MERGE_P | TDEFAULT_POLICY_P | MU_POLICY_P,
+  /* For mask insn with tuma.  */
+  __MASK_OP_TUMA = HAS_DEST_P | HAS_MASK_P | USE_ALL_TRUES_MASK_P | HAS_MERGE_P
+		   | TU_POLICY_P | MDEFAULT_POLICY_P,
+  /* For mask insn with mu.  */
+  __MASK_OP_MU = HAS_DEST_P | HAS_MASK_P | HAS_MERGE_P | MU_POLICY_P,
+  /* For mask insn with ta, without mask policy operand.  */
+  __MASK_OP_TA = HAS_DEST_P | HAS_MASK_P | HAS_MERGE_P | USE_VUNDEF_MERGE_P
+		 | TDEFAULT_POLICY_P,
+
+  /* Nullary operator. e.g. vid.v  */
+  NULLARY_OP = __NORMAL_OP | NULLARY_OP_P,
+
+  /* Unary operator.  */
+  UNARY_OP = __NORMAL_OP | UNARY_OP_P,
+  UNARY_OP_TAMA = __MASK_OP_TAMA | UNARY_OP_P,
+  UNARY_OP_TAMU = __MASK_OP_TAMU | UNARY_OP_P,
+  UNARY_OP_FRM_DYN = UNARY_OP | FRM_DYN_P,
+
+  /* Binary operator.  */
+  BINARY_OP = __NORMAL_OP | BINARY_OP_P,
+  BINARY_OP_TAMA = __MASK_OP_TAMA | BINARY_OP_P,
+  BINARY_OP_TAMU = __MASK_OP_TAMU | BINARY_OP_P,
+  BINARY_OP_TUMA = __MASK_OP_TUMA | BINARY_OP_P,
+  BINARY_OP_FRM_DYN = BINARY_OP | FRM_DYN_P,
+
+  /* Ternary operator. Always have real merge operand.  */
+  TERNARY_OP = HAS_DEST_P | HAS_MASK_P | USE_ALL_TRUES_MASK_P | HAS_MERGE_P
+	       | TDEFAULT_POLICY_P | MDEFAULT_POLICY_P | TERNARY_OP_P,
+  TERNARY_OP_FRM_DYN = TERNARY_OP | FRM_DYN_P,
+
+  /* For vwmacc, no merge operand.  */
+  WIDEN_TERNARY_OP = HAS_DEST_P | HAS_MASK_P | USE_ALL_TRUES_MASK_P
+		     | TDEFAULT_POLICY_P | MDEFAULT_POLICY_P | TERNARY_OP_P,
+  WIDEN_TERNARY_OP_FRM_DYN = WIDEN_TERNARY_OP | FRM_DYN_P,
+
+  /* For vmerge, no mask operand, no mask policy operand.  */
+  MERGE_OP = __NORMAL_OP_TA2 | TERNARY_OP_P,
+
+  /* For vm<compare>, no tail policy operand.  */
+  COMPARE_OP = __NORMAL_OP_MA | TERNARY_OP_P,
+  COMPARE_OP_MU = __MASK_OP_MU | TERNARY_OP_P,
+
+  /* For scatter insn: no dest operand, no merge operand, no tail and mask
+     policy operands.  */
+  SCATTER_OP_M = HAS_MASK_P | TERNARY_OP_P,
+
+  /* For vcpop.m, no merge operand, no tail and mask policy operands.  */
+  CPOP_OP = HAS_DEST_P | HAS_MASK_P | USE_ALL_TRUES_MASK_P | UNARY_OP_P
+	    | MASK_MODE_FROM_OP1_P,
+
+  /* For mask instrunctions, no tail and mask policy operands.  */
+  UNARY_MASK_OP = HAS_DEST_P | HAS_MASK_P | USE_ALL_TRUES_MASK_P | HAS_MERGE_P
+		  | USE_VUNDEF_MERGE_P | UNARY_OP_P,
+  BINARY_MASK_OP = HAS_DEST_P | HAS_MASK_P | USE_ALL_TRUES_MASK_P | HAS_MERGE_P
+		   | USE_VUNDEF_MERGE_P | BINARY_OP_P,
+
+  /* For vcompress.vm */
+  COMPRESS_OP = __NORMAL_OP_TA2 | BINARY_OP_P,
+  /* has merge operand but use ta.  */
+  COMPRESS_OP_MERGE
+  = HAS_DEST_P | HAS_MERGE_P | TDEFAULT_POLICY_P | BINARY_OP_P,
+
+  /* For vreduce, no mask policy operand. */
+  REDUCE_OP = __NORMAL_OP_TA | BINARY_OP_P | MASK_MODE_FROM_OP1_P,
+  REDUCE_OP_FRM_DYN = REDUCE_OP | FRM_DYN_P | MASK_MODE_FROM_OP1_P,
+  REDUCE_OP_M_FRM_DYN
+  = __MASK_OP_TA | BINARY_OP_P | FRM_DYN_P | MASK_MODE_FROM_OP1_P,
+
+  /* For vmv.s.x/vfmv.s.f.  */
+  SCALAR_MOVE_OP = HAS_DEST_P | HAS_MASK_P | USE_ONE_TRUE_MASK_P | HAS_MERGE_P
+		   | USE_VUNDEF_MERGE_P | TDEFAULT_POLICY_P | MDEFAULT_POLICY_P
+		   | UNARY_OP_P,
+};
+
 enum vlmul_type
 {
   LMUL_1 = 0,
@@ -243,19 +380,9 @@ bool const_vec_all_same_in_range_p (rtx, HOST_WIDE_INT, HOST_WIDE_INT);
 bool legitimize_move (rtx, rtx);
 void emit_vlmax_vsetvl (machine_mode, rtx);
 void emit_hard_vlmax_vsetvl (machine_mode, rtx);
-void emit_vlmax_insn (unsigned, int, rtx *, rtx = 0);
-void emit_vlmax_fp_insn (unsigned, int, rtx *, rtx = 0);
-void emit_vlmax_ternary_insn (unsigned, int, rtx *, rtx = 0);
-void emit_vlmax_fp_ternary_insn (unsigned, int, rtx *, rtx = 0);
-void emit_nonvlmax_insn (unsigned, int, rtx *, rtx);
-void emit_vlmax_slide_insn (unsigned, rtx *);
-void emit_nonvlmax_slide_tu_insn (unsigned, rtx *, rtx);
-void emit_vlmax_merge_insn (unsigned, int, rtx *);
-void emit_vlmax_cmp_insn (unsigned, rtx *);
-void emit_vlmax_cmp_mu_insn (unsigned, rtx *);
-void emit_vlmax_masked_mu_insn (unsigned, int, rtx *);
-void emit_scalar_move_insn (unsigned, rtx *, rtx = 0);
-void emit_nonvlmax_integer_move_insn (unsigned, rtx *, rtx);
+void emit_vlmax_insn (unsigned, unsigned, rtx *);
+void emit_nonvlmax_insn (unsigned, unsigned, rtx *, rtx);
+void emit_vlmax_insn_lra (unsigned, unsigned, rtx *, rtx);
 enum vlmul_type get_vlmul (machine_mode);
 rtx get_vlmax_rtx (machine_mode);
 unsigned int get_ratio (machine_mode);
diff --git a/gcc/config/riscv/riscv-v.cc b/gcc/config/riscv/riscv-v.cc
index bf247788659..3e7caf48742 100644
--- a/gcc/config/riscv/riscv-v.cc
+++ b/gcc/config/riscv/riscv-v.cc
@@ -70,51 +70,64 @@ const_vlmax_p (machine_mode mode)
 template <int MAX_OPERANDS> class insn_expander
 {
 public:
-  insn_expander ()
-    : m_opno (0), m_op_num (0), m_has_dest_p (false),
-      m_fully_unmasked_p (false), m_use_real_merge_p (false),
-      m_needs_avl_p (false), m_vlmax_p (false), m_has_tail_policy_p (false),
-      m_has_mask_policy_p (false), m_has_fp_rounding_mode_p (false),
-      m_tail_policy (TAIL_ANY), m_mask_policy (MASK_ANY),
-      m_fp_rounding_mode (FRM_DYN),
-      m_dest_mode (VOIDmode), m_mask_mode (VOIDmode),
-      m_vl_op (NULL_RTX)
-  {}
-
-  /* Initializer for various configurations.  */
-  insn_expander (int op_num, bool has_dest_p, bool use_all_trues_mask_p,
-		 bool use_real_merge_p, bool needs_avl_p, bool vlmax_p,
-		 machine_mode dest_mode, machine_mode mask_mode)
-    : m_opno (0), m_op_num (op_num), m_has_dest_p (has_dest_p),
-      m_fully_unmasked_p (use_all_trues_mask_p),
-      m_use_real_merge_p (use_real_merge_p), m_needs_avl_p (needs_avl_p),
-      m_vlmax_p (vlmax_p), m_has_tail_policy_p (false),
-      m_has_mask_policy_p (false), m_has_fp_rounding_mode_p (false),
-      m_tail_policy (TAIL_ANY), m_mask_policy (MASK_ANY),
-      m_fp_rounding_mode (FRM_DYN),
-      m_dest_mode (dest_mode),
-      m_mask_mode (mask_mode), m_vl_op (NULL_RTX)
-  {}
-
-  void set_policy (enum tail_policy ta)
-  {
-    m_has_tail_policy_p = true;
-    m_tail_policy = ta;
-  }
-  void set_policy (enum mask_policy ma)
+  insn_expander () = delete;
+
+  insn_expander (unsigned insn_flags, bool vlmax_p, machine_mode dest_mode,
+		  machine_mode mask_mode)
+    : m_insn_flags (insn_flags), m_opno (0), m_vlmax_p (vlmax_p),
+      m_dest_mode (dest_mode), m_mask_mode (mask_mode), m_vl_op (NULL_RTX)
   {
-    m_has_mask_policy_p = true;
-    m_mask_policy = ma;
+    check_insn_flags ();
   }
-  void set_vl (rtx vl) { m_vl_op = vl; }
 
-  void set_rounding_mode (enum floating_point_rounding_mode mode)
+  void check_insn_flags ()
   {
-    m_has_fp_rounding_mode_p = true;
-    m_fp_rounding_mode = mode;
-    gcc_assert (mode <= FRM_DYN);
+    if (m_insn_flags & USE_ONE_TRUE_MASK_P)
+      /* USE_ONE_TRUE_MASK_P is dependent on HAS_MASK_P.  */
+      gcc_assert ((m_insn_flags & HAS_MASK_P));
+
+    if (m_insn_flags & USE_ALL_TRUES_MASK_P)
+      /* USE_ALL_TRUES_MASK_P is dependent on HAS_MASK_P.  */
+      gcc_assert ((m_insn_flags & HAS_MASK_P));
+
+    /* USE_ONE_TRUE_MASK_P and USE_ALL_TRUES_MASK_P are mutually exclusive.  */
+    gcc_assert (!((m_insn_flags & USE_ONE_TRUE_MASK_P)
+		  && (m_insn_flags & USE_ALL_TRUES_MASK_P)));
+
+    if (m_insn_flags & USE_VUNDEF_MERGE_P)
+      /* USE_VUNDEF_MERGE_P is dependent on HAS_MERGE_P.  */
+      gcc_assert ((m_insn_flags & HAS_MERGE_P));
+
+    /* TU_POLICY_P and TDEFAULT_POLICY_P are mutually exclusive.  */
+    gcc_assert (
+      !((m_insn_flags & TU_POLICY_P) && (m_insn_flags & TDEFAULT_POLICY_P)));
+
+    /* MU_POLICY_P and MDEFAULT_POLICY_P are mutually exclusive.  */
+    gcc_assert (
+      !((m_insn_flags & MU_POLICY_P) && (m_insn_flags & MDEFAULT_POLICY_P)));
+
+    /* NULLARY_OP_P, UNARY_OP_P, BINARY_OP_P, TERNARY_OP_P are mutually
+       exclusive.  */
+    gcc_assert (
+      !((m_insn_flags & NULLARY_OP_P)
+	&& ((m_insn_flags & UNARY_OP_P) || (m_insn_flags & BINARY_OP_P)
+	    || (m_insn_flags & TERNARY_OP_P))));
+    gcc_assert (
+      !((m_insn_flags & UNARY_OP_P)
+	&& ((m_insn_flags & NULLARY_OP_P) || (m_insn_flags & BINARY_OP_P)
+	    || (m_insn_flags & TERNARY_OP_P))));
+    gcc_assert (
+      !((m_insn_flags & BINARY_OP_P)
+	&& ((m_insn_flags & NULLARY_OP_P) || (m_insn_flags & UNARY_OP_P)
+	    || (m_insn_flags & TERNARY_OP_P))));
+    gcc_assert (
+      !((m_insn_flags & TERNARY_OP_P)
+	&& ((m_insn_flags & NULLARY_OP_P) || (m_insn_flags & UNARY_OP_P)
+	    || (m_insn_flags & BINARY_OP_P))));
   }
 
+  void set_vl (rtx vl) { m_vl_op = vl; }
+
   void add_output_operand (rtx x, machine_mode mode)
   {
     create_output_operand (&m_ops[m_opno++], x, mode);
@@ -135,14 +148,25 @@ public:
   }
   void add_policy_operand ()
   {
-    if (m_has_tail_policy_p)
+    if (m_insn_flags & TU_POLICY_P)
       {
-	rtx tail_policy_rtx = gen_int_mode (m_tail_policy, Pmode);
+	rtx tail_policy_rtx = gen_int_mode (TAIL_UNDISTURBED, Pmode);
 	add_input_operand (tail_policy_rtx, Pmode);
       }
-    if (m_has_mask_policy_p)
+    else if (m_insn_flags & TDEFAULT_POLICY_P)
       {
-	rtx mask_policy_rtx = gen_int_mode (m_mask_policy, Pmode);
+	rtx tail_policy_rtx = gen_int_mode (get_prefer_tail_policy (), Pmode);
+	add_input_operand (tail_policy_rtx, Pmode);
+      }
+
+    if (m_insn_flags & MU_POLICY_P)
+      {
+	rtx mask_policy_rtx = gen_int_mode (MASK_UNDISTURBED, Pmode);
+	add_input_operand (mask_policy_rtx, Pmode);
+      }
+    else if (m_insn_flags & MDEFAULT_POLICY_P)
+      {
+	rtx mask_policy_rtx = gen_int_mode (get_prefer_mask_policy (), Pmode);
 	add_input_operand (mask_policy_rtx, Pmode);
       }
   }
@@ -151,39 +175,72 @@ public:
     add_input_operand (gen_int_mode (type, Pmode), Pmode);
   }
 
-  void add_rounding_mode_operand ()
+  void
+  add_rounding_mode_operand (enum floating_point_rounding_mode rounding_mode)
   {
-    if (m_has_fp_rounding_mode_p)
-      {
-	rtx frm_rtx = gen_int_mode (m_fp_rounding_mode, Pmode);
-	add_input_operand (frm_rtx, Pmode);
-      }
+    rtx frm_rtx = gen_int_mode (rounding_mode, Pmode);
+    add_input_operand (frm_rtx, Pmode);
+  }
+
+  void add_oprand (rtx *ops, int opno)
+  {
+
   }
 
   void emit_insn (enum insn_code icode, rtx *ops)
   {
     int opno = 0;
+    int num_ops = 0;
     /* It's true if any operand is memory operand.  */
     bool any_mem_p = false;
-    /* It's true if all operands are mask operand.  */
-    bool all_mask_p = true;
-    if (m_has_dest_p)
+
+    /* Add dest operand.  */
+    if (m_insn_flags & HAS_DEST_P)
       {
 	any_mem_p |= MEM_P (ops[opno]);
-	all_mask_p &= GET_MODE_CLASS (GET_MODE (ops[opno])) == MODE_VECTOR_BOOL;
 	add_output_operand (ops[opno++], m_dest_mode);
+	num_ops += 1;
       }
 
-    if (m_fully_unmasked_p)
+    /* Add mask operand.  */
+    if (m_insn_flags & USE_ONE_TRUE_MASK_P)
+      add_input_operand (gen_scalar_move_mask (m_mask_mode), m_mask_mode);
+    else if (m_insn_flags & USE_ALL_TRUES_MASK_P)
       add_all_one_mask_operand ();
+    else if (m_insn_flags & HAS_MASK_P)
+      {
+	machine_mode mode = insn_data[(int) icode].operand[m_opno].mode;
+	gcc_assert (mode != VOIDmode);
+	add_input_operand (ops[opno++], mode);
+	num_ops += 1;
+      }
 
-    if (!m_use_real_merge_p)
+    /* Add merge operand.  */
+    if (m_insn_flags & USE_VUNDEF_MERGE_P)
       add_vundef_operand ();
+    else if (m_insn_flags & HAS_MERGE_P)
+      {
+	machine_mode mode = insn_data[(int) icode].operand[m_opno].mode;
+	gcc_assert (mode != VOIDmode);
+	add_input_operand (ops[opno++], mode);
+	num_ops += 1;
+      }
+
+    if (m_insn_flags & NULLARY_OP_P)
+      num_ops += 0;
+    else if (m_insn_flags & UNARY_OP_P)
+      num_ops += 1;
+    else if (m_insn_flags & BINARY_OP_P)
+      num_ops += 2;
+    else if (m_insn_flags & TERNARY_OP_P)
+      num_ops += 3;
+    else
+      gcc_unreachable ();
 
-    for (; opno < m_op_num; opno++)
+    /* Add the remain operands.  */
+    for (; opno < num_ops; opno++)
       {
 	any_mem_p |= MEM_P (ops[opno]);
-	all_mask_p &= GET_MODE_CLASS (GET_MODE (ops[opno])) == MODE_VECTOR_BOOL;
 	machine_mode mode = insn_data[(int) icode].operand[m_opno].mode;
 	/* 'create_input_operand doesn't allow VOIDmode.
 	   According to vector.md, we may have some patterns that do not have
@@ -194,46 +251,51 @@ public:
 	add_input_operand (ops[opno], mode);
       }
 
-    if (m_needs_avl_p)
+    /* Add vl operand.  */
+    rtx len = m_vl_op;
+    machine_mode mode = VECTOR_MODE_P (m_dest_mode) ? m_dest_mode : m_mask_mode;
+    if (m_vlmax_p)
       {
-	rtx len = m_vl_op;
-	machine_mode mode
-	  = VECTOR_MODE_P (m_dest_mode) ? m_dest_mode : m_mask_mode;
-	if (m_vlmax_p)
+	if (riscv_v_ext_vls_mode_p (mode))
+	  {
+	    /* VLS modes always set VSETVL by
+	       "vsetvl zero, rs1/imm".  */
+	    poly_uint64 nunits = GET_MODE_NUNITS (mode);
+	    len = gen_int_mode (nunits, Pmode);
+	    if (!satisfies_constraint_K (len))
+	      len = force_reg (Pmode, len);
+	    m_vlmax_p = false;
+	  }
+	else if (const_vlmax_p (mode))
+	  {
+	    /* Optimize VLS-VLMAX code gen, we can use vsetivli instead of
+	       the vsetvli to obtain the value of vlmax.  */
+	    poly_uint64 nunits = GET_MODE_NUNITS (mode);
+	    len = gen_int_mode (nunits, Pmode);
+	    m_vlmax_p = false;
+	  }
+	else if (can_create_pseudo_p ())
 	  {
-	    if (riscv_v_ext_vls_mode_p (mode))
-	      {
-		/* VLS modes always set VSETVL by
-		   "vsetvl zero, rs1/imm".  */
-		poly_uint64 nunits = GET_MODE_NUNITS (mode);
-		len = gen_int_mode (nunits, Pmode);
-		if (!satisfies_constraint_K (len))
-		  len = force_reg (Pmode, len);
-		m_vlmax_p = false; /* It has became NONVLMAX now.  */
-	      }
-	    else if (const_vlmax_p (mode))
-	      {
-		/* Optimize VLS-VLMAX code gen, we can use vsetivli instead of
-		   the vsetvli to obtain the value of vlmax.  */
-		poly_uint64 nunits = GET_MODE_NUNITS (mode);
-		len = gen_int_mode (nunits, Pmode);
-		m_vlmax_p = false; /* It has became NONVLMAX now.  */
-	      }
-	    else if (can_create_pseudo_p ())
-	      {
-		len = gen_reg_rtx (Pmode);
-		emit_vlmax_vsetvl (mode, len);
-	      }
+	    len = gen_reg_rtx (Pmode);
+	    emit_vlmax_vsetvl (mode, len);
 	  }
-	add_input_operand (len, Pmode);
+	else
+	  gcc_assert (len != NULL_RTX);
       }
+    else
+      /* Must specify vl when not vlmax.  */
+      gcc_assert (len != NULL_RTX);
+    add_input_operand (len, Pmode);
+
+    /* Add tail and mask policy operands.  */
+    add_policy_operand ();
 
-    if (!all_mask_p)
-      add_policy_operand ();
-    if (m_needs_avl_p)
-      add_avl_type_operand (m_vlmax_p ? avl_type::VLMAX : avl_type::NONVLMAX);
+    /* Add avl_type operand.  */
+    add_avl_type_operand (m_vlmax_p ? avl_type::VLMAX : avl_type::NONVLMAX);
 
-    add_rounding_mode_operand ();
+    /* Add rounding mode operand.  */
+    if (m_insn_flags & FRM_DYN_P)
+      add_rounding_mode_operand (FRM_DYN);
 
     expand (icode, any_mem_p);
   }
@@ -250,32 +312,67 @@ public:
   }
 
 private:
+  int m_insn_flags;
   int m_opno;
-  int m_op_num;
-  /* It't true when the pattern has a dest operand. Most of the patterns have
-     dest operand wheras some patterns like STOREs does not have dest operand.
-     For example, according to vector.md. We can see indexed loads/stores do
-     not have dest operand.
-  */
-  bool m_has_dest_p;
-  /* It't true if the pattern uses all trues mask operand.  */
-  bool m_fully_unmasked_p;
-  /* It's true if the pattern uses real merge operand.  */
-  bool m_use_real_merge_p;
-  bool m_needs_avl_p;
   bool m_vlmax_p;
-  bool m_has_tail_policy_p;
-  bool m_has_mask_policy_p;
-  bool m_has_fp_rounding_mode_p;
-  enum tail_policy m_tail_policy;
-  enum mask_policy m_mask_policy;
-  enum floating_point_rounding_mode m_fp_rounding_mode;
   machine_mode m_dest_mode;
   machine_mode m_mask_mode;
   rtx m_vl_op;
   expand_operand m_ops[MAX_OPERANDS];
 };
 
+/* Return the mask mode based on insn_flags */
+static machine_mode
+get_mask_mode_from_insn_flags (unsigned insn_flags, rtx *ops)
+{
+  machine_mode mask_mode;
+  if (insn_flags & MASK_MODE_FROM_OP1_P)
+    mask_mode = get_mask_mode (GET_MODE (ops[1]));
+  else
+    mask_mode = get_mask_mode (GET_MODE (ops[0]));
+  return mask_mode;
+}
+
+/* Emit RVV insn which vl is VLMAX.
+   This function can only be used before LRA pass or
+   for VLS_AVL_IMM modes.  */
+void
+emit_vlmax_insn (unsigned icode, unsigned insn_flags, rtx *ops)
+{
+  machine_mode dest_mode = GET_MODE (ops[0]);
+  machine_mode mask_mode = get_mask_mode_from_insn_flags (insn_flags, ops);
+
+  insn_expander<RVV_INSN_OPERANDS_MAX> e (insn_flags, true, dest_mode,
+					   mask_mode);
+  e.emit_insn ((enum insn_code) icode, ops);
+}
+
+/* Emit RVV insn which vl is VL.  */
+void
+emit_nonvlmax_insn (unsigned icode, unsigned insn_flags, rtx *ops, rtx vl)
+{
+  machine_mode dest_mode = GET_MODE (ops[0]);
+  machine_mode mask_mode = get_mask_mode_from_insn_flags (insn_flags, ops);
+  insn_expander<RVV_INSN_OPERANDS_MAX> e (insn_flags, false, dest_mode,
+					   mask_mode);
+  e.set_vl (vl);
+  e.emit_insn ((enum insn_code) icode, ops);
+}
+
+/* Emit RVV insn which vl is VL but the AVL_TYPE insn attr is VLMAX.
+   This function used after LRA pass that cann't create pseudo register.  */
+void
+emit_vlmax_insn_lra (unsigned icode, unsigned insn_flags, rtx *ops, rtx vl)
+{
+  gcc_assert (!can_create_pseudo_p ());
+
+  machine_mode dest_mode = GET_MODE (ops[0]);
+  machine_mode mask_mode = get_mask_mode_from_insn_flags (insn_flags, ops);
+  insn_expander<RVV_INSN_OPERANDS_MAX> e (insn_flags, true, dest_mode,
+					   mask_mode);
+  e.set_vl (vl);
+  e.emit_insn ((enum insn_code) icode, ops);
+}
 
 class rvv_builder : public rtx_vector_builder
 {
@@ -673,481 +770,6 @@ autovec_use_vlmax_p (void)
     For that case we also allow to set the avl_type to VLMAX.
 */
 
-/* This function emits a {VLMAX, TAIL_ANY, MASK_ANY} vsetvli followed by the
- * actual operation.  */
-void
-emit_vlmax_insn (unsigned icode, int op_num, rtx *ops, rtx vl)
-{
-  machine_mode dest_mode = GET_MODE (ops[0]);
-  machine_mode mask_mode = get_mask_mode (dest_mode);
-  insn_expander<RVV_INSN_OPERANDS_MAX> e (op_num,
-					  /* HAS_DEST_P */ true,
-					  /* FULLY_UNMASKED_P */ true,
-					  /* USE_REAL_MERGE_P */ false,
-					  /* HAS_AVL_P */ true,
-					  /* VLMAX_P */ true,
-					  dest_mode,
-					  mask_mode);
-
-  e.set_policy (TAIL_ANY);
-  e.set_policy (MASK_ANY);
-  /* According to LRA mov pattern in vector.md, we have a clobber operand
-     to be used ad VL operand.  */
-  e.set_vl (vl);
-  e.emit_insn ((enum insn_code) icode, ops);
-}
-
-void
-emit_vlmax_fp_insn (unsigned icode, int op_num, rtx *ops, rtx vl)
-{
-  machine_mode dest_mode = GET_MODE (ops[0]);
-  machine_mode mask_mode = get_mask_mode (dest_mode);
-  insn_expander<RVV_INSN_OPERANDS_MAX> e (op_num,
-					  /* HAS_DEST_P */ true,
-					  /* FULLY_UNMASKED_P */ true,
-					  /* USE_REAL_MERGE_P */ false,
-					  /* HAS_AVL_P */ true,
-					  /* VLMAX_P */ true,
-					  dest_mode,
-					  mask_mode);
-
-  e.set_policy (TAIL_ANY);
-  e.set_policy (MASK_ANY);
-  e.set_rounding_mode (FRM_DYN);
-  e.set_vl (vl);
-  e.emit_insn ((enum insn_code) icode, ops);
-}
-
-/* This function emits a {VLMAX, TAIL_ANY, MASK_ANY} vsetvli followed by the
- * ternary operation which always has a real merge operand.  */
-void
-emit_vlmax_ternary_insn (unsigned icode, int op_num, rtx *ops, rtx vl)
-{
-  machine_mode dest_mode = GET_MODE (ops[0]);
-  machine_mode mask_mode = get_mask_mode (dest_mode);
-  insn_expander<RVV_INSN_OPERANDS_MAX> e (/*OP_NUM*/ op_num,
-					  /*HAS_DEST_P*/ true,
-					  /*FULLY_UNMASKED_P*/ true,
-					  /*USE_REAL_MERGE_P*/ true,
-					  /*HAS_AVL_P*/ true,
-					  /*VLMAX_P*/ true,
-					  /*DEST_MODE*/ dest_mode,
-					  /*MASK_MODE*/ mask_mode);
-  e.set_policy (TAIL_ANY);
-  e.set_policy (MASK_ANY);
-  e.set_vl (vl);
-  e.emit_insn ((enum insn_code) icode, ops);
-}
-
-/* This function emits a {VLMAX, TAIL_ANY, MASK_ANY} vsetvli followed by the
- * ternary operation which always has a real merge operand.  */
-void
-emit_vlmax_fp_ternary_insn (unsigned icode, int op_num, rtx *ops, rtx vl)
-{
-  machine_mode dest_mode = GET_MODE (ops[0]);
-  machine_mode mask_mode = get_mask_mode (dest_mode);
-  insn_expander<RVV_INSN_OPERANDS_MAX> e (/*OP_NUM*/ op_num,
-					  /*HAS_DEST_P*/ true,
-					  /*FULLY_UNMASKED_P*/ true,
-					  /*USE_REAL_MERGE_P*/ true,
-					  /*HAS_AVL_P*/ true,
-					  /*VLMAX_P*/ true,
-					  /*DEST_MODE*/ dest_mode,
-					  /*MASK_MODE*/ mask_mode);
-  e.set_policy (TAIL_ANY);
-  e.set_policy (MASK_ANY);
-  e.set_rounding_mode (FRM_DYN);
-  e.set_vl (vl);
-  e.emit_insn ((enum insn_code) icode, ops);
-}
-
-/* This function emits a {NONVLMAX, TAIL_ANY, MASK_ANY} vsetvli followed by the
- * actual operation.  */
-void
-emit_nonvlmax_insn (unsigned icode, int op_num, rtx *ops, rtx avl)
-{
-  machine_mode dest_mode = GET_MODE (ops[0]);
-  machine_mode mask_mode = get_mask_mode (dest_mode);
-  insn_expander<RVV_INSN_OPERANDS_MAX> e (op_num,
-					  /* HAS_DEST_P */ true,
-					  /* FULLY_UNMASKED_P */ true,
-					  /* USE_REAL_MERGE_P */ false,
-					  /* HAS_AVL_P */ true,
-					  /* VLMAX_P */ false,
-					  dest_mode,
-					  mask_mode);
-
-  e.set_policy (TAIL_ANY);
-  e.set_policy (MASK_ANY);
-  e.set_vl (avl);
-  e.emit_insn ((enum insn_code) icode, ops);
-}
-
-/* This function emits a {NONVLMAX, TAIL_UNDISTURBED, MASK_ANY} vsetvli
-   followed by a vslide insn (with real merge operand).  */
-void
-emit_vlmax_slide_insn (unsigned icode, rtx *ops)
-{
-  machine_mode dest_mode = GET_MODE (ops[0]);
-  machine_mode mask_mode = get_mask_mode (dest_mode);
-  insn_expander<RVV_INSN_OPERANDS_MAX> e (RVV_SLIDE_OP,
-					  /* HAS_DEST_P */ true,
-					  /* FULLY_UNMASKED_P */ true,
-					  /* USE_REAL_MERGE_P */ true,
-					  /* HAS_AVL_P */ true,
-					  /* VLMAX_P */ true,
-					  dest_mode,
-					  mask_mode);
-
-  e.set_policy (TAIL_ANY);
-  e.set_policy (MASK_ANY);
-
-  e.emit_insn ((enum insn_code) icode, ops);
-}
-
-/* This function emits a {NONVLMAX, TAIL_UNDISTURBED, MASK_ANY} vsetvli
-   followed by a vslide insn (with real merge operand).  */
-void
-emit_nonvlmax_slide_tu_insn (unsigned icode, rtx *ops, rtx avl)
-{
-  machine_mode dest_mode = GET_MODE (ops[0]);
-  machine_mode mask_mode = get_mask_mode (dest_mode);
-  insn_expander<RVV_INSN_OPERANDS_MAX> e (RVV_SLIDE_OP,
-					  /* HAS_DEST_P */ true,
-					  /* FULLY_UNMASKED_P */ true,
-					  /* USE_REAL_MERGE_P */ true,
-					  /* HAS_AVL_P */ true,
-					  /* VLMAX_P */ false,
-					  dest_mode,
-					  mask_mode);
-
-  e.set_policy (TAIL_UNDISTURBED);
-  e.set_policy (MASK_ANY);
-  e.set_vl (avl);
-
-  e.emit_insn ((enum insn_code) icode, ops);
-}
-
-/* This function emits a {NONVLMAX, TAIL_ANY, MASK_ANY} vsetvli
-   followed by a vslide insn (with real merge operand).  */
-void
-emit_nonvlmax_slide_insn (unsigned icode, rtx *ops, rtx avl)
-{
-  machine_mode dest_mode = GET_MODE (ops[0]);
-  machine_mode mask_mode = get_mask_mode (dest_mode);
-  insn_expander<RVV_INSN_OPERANDS_MAX> e (RVV_SLIDE_OP,
-					  /* HAS_DEST_P */ true,
-					  /* FULLY_UNMASKED_P */ true,
-					  /* USE_REAL_MERGE_P */ true,
-					  /* HAS_AVL_P */ true,
-					  /* VLMAX_P */ true,
-					  dest_mode,
-					  mask_mode);
-
-  e.set_policy (TAIL_ANY);
-  e.set_policy (MASK_ANY);
-  e.set_vl (avl);
-
-  e.emit_insn ((enum insn_code) icode, ops);
-}
-
-/* This function emits merge instruction.  */
-void
-emit_vlmax_merge_insn (unsigned icode, int op_num, rtx *ops)
-{
-  machine_mode dest_mode = GET_MODE (ops[0]);
-  machine_mode mask_mode = get_mask_mode (dest_mode);
-  insn_expander<RVV_INSN_OPERANDS_MAX> e (op_num,
-					  /* HAS_DEST_P */ true,
-					  /* FULLY_UNMASKED_P */ false,
-					  /* USE_REAL_MERGE_P */ false,
-					  /* HAS_AVL_P */ true,
-					  /* VLMAX_P */ true,
-					  dest_mode,
-					  mask_mode);
-
-  e.set_policy (TAIL_ANY);
-  e.emit_insn ((enum insn_code) icode, ops);
-}
-
-/* This function emits cmp instruction.  */
-void
-emit_vlmax_cmp_insn (unsigned icode, rtx *ops)
-{
-  machine_mode mode = GET_MODE (ops[0]);
-  insn_expander<RVV_INSN_OPERANDS_MAX> e (RVV_CMP_OP,
-					  /* HAS_DEST_P */ true,
-					  /* FULLY_UNMASKED_P */ true,
-					  /* USE_REAL_MERGE_P */ false,
-					  /* HAS_AVL_P */ true,
-					  /* VLMAX_P */ true,
-					  mode,
-					  mode);
-
-  e.set_policy (MASK_ANY);
-  e.emit_insn ((enum insn_code) icode, ops);
-}
-
-/* This function emits cmp with MU instruction.  */
-void
-emit_vlmax_cmp_mu_insn (unsigned icode, rtx *ops)
-{
-  machine_mode mode = GET_MODE (ops[0]);
-  insn_expander<RVV_INSN_OPERANDS_MAX> e (RVV_CMP_MU_OP,
-					  /* HAS_DEST_P */ true,
-					  /* FULLY_UNMASKED_P */ false,
-					  /* USE_REAL_MERGE_P */ true,
-					  /* HAS_AVL_P */ true,
-					  /* VLMAX_P */ true,
-					  mode,
-					  mode);
-
-  e.set_policy (MASK_UNDISTURBED);
-  e.emit_insn ((enum insn_code) icode, ops);
-}
-
-/* This function emits a masked instruction.  */
-static void
-emit_vlmax_masked_insn (unsigned icode, int op_num, rtx *ops)
-{
-  machine_mode dest_mode = GET_MODE (ops[0]);
-  machine_mode mask_mode = get_mask_mode (dest_mode);
-  insn_expander<RVV_INSN_OPERANDS_MAX> e (/*OP_NUM*/ op_num,
-					  /*HAS_DEST_P*/ true,
-					  /*FULLY_UNMASKED_P*/ false,
-					  /*USE_REAL_MERGE_P*/ true,
-					  /*HAS_AVL_P*/ true,
-					  /*VLMAX_P*/ true, dest_mode,
-					  mask_mode);
-  e.set_policy (TAIL_ANY);
-  e.set_policy (MASK_ANY);
-  e.emit_insn ((enum insn_code) icode, ops);
-}
-
-/* This function emits a masked instruction.  */
-static void
-emit_nonvlmax_masked_insn (unsigned icode, int op_num, rtx *ops, rtx avl)
-{
-  machine_mode dest_mode = GET_MODE (ops[0]);
-  machine_mode mask_mode = get_mask_mode (dest_mode);
-  insn_expander<RVV_INSN_OPERANDS_MAX> e (/*OP_NUM*/ op_num,
-					  /*HAS_DEST_P*/ true,
-					  /*FULLY_UNMASKED_P*/ false,
-					  /*USE_REAL_MERGE_P*/ true,
-					  /*HAS_AVL_P*/ true,
-					  /*VLMAX_P*/ false, dest_mode,
-					  mask_mode);
-  e.set_policy (TAIL_ANY);
-  e.set_policy (MASK_ANY);
-  e.set_vl (avl);
-  e.emit_insn ((enum insn_code) icode, ops);
-}
-
-/* This function emits a VLMAX masked store instruction.  */
-static void
-emit_vlmax_masked_store_insn (unsigned icode, int op_num, rtx *ops)
-{
-  machine_mode dest_mode = GET_MODE (ops[0]);
-  machine_mode mask_mode = get_mask_mode (dest_mode);
-  insn_expander<RVV_INSN_OPERANDS_MAX> e (/*OP_NUM*/ op_num,
-					  /*HAS_DEST_P*/ false,
-					  /*FULLY_UNMASKED_P*/ false,
-					  /*USE_REAL_MERGE_P*/ true,
-					  /*HAS_AVL_P*/ true,
-					  /*VLMAX_P*/ true, dest_mode,
-					  mask_mode);
-  e.emit_insn ((enum insn_code) icode, ops);
-}
-
-/* This function emits a non-VLMAX masked store instruction.  */
-static void
-emit_nonvlmax_masked_store_insn (unsigned icode, int op_num, rtx *ops, rtx avl)
-{
-  machine_mode dest_mode = GET_MODE (ops[0]);
-  machine_mode mask_mode = get_mask_mode (dest_mode);
-  insn_expander<RVV_INSN_OPERANDS_MAX> e (/*OP_NUM*/ op_num,
-					  /*HAS_DEST_P*/ false,
-					  /*FULLY_UNMASKED_P*/ false,
-					  /*USE_REAL_MERGE_P*/ true,
-					  /*HAS_AVL_P*/ true,
-					  /*VLMAX_P*/ false, dest_mode,
-					  mask_mode);
-  e.set_vl (avl);
-  e.emit_insn ((enum insn_code) icode, ops);
-}
-
-/* This function emits a masked instruction.  */
-void
-emit_vlmax_masked_mu_insn (unsigned icode, int op_num, rtx *ops)
-{
-  machine_mode dest_mode = GET_MODE (ops[0]);
-  machine_mode mask_mode = get_mask_mode (dest_mode);
-  insn_expander<RVV_INSN_OPERANDS_MAX> e (/*OP_NUM*/ op_num,
-					  /*HAS_DEST_P*/ true,
-					  /*FULLY_UNMASKED_P*/ false,
-					  /*USE_REAL_MERGE_P*/ true,
-					  /*HAS_AVL_P*/ true,
-					  /*VLMAX_P*/ true, dest_mode,
-					  mask_mode);
-  e.set_policy (TAIL_ANY);
-  e.set_policy (MASK_UNDISTURBED);
-  e.emit_insn ((enum insn_code) icode, ops);
-}
-
-/* This function emits a masked instruction.  */
-static void
-emit_vlmax_masked_fp_mu_insn (unsigned icode, int op_num, rtx *ops)
-{
-  machine_mode dest_mode = GET_MODE (ops[0]);
-  machine_mode mask_mode = get_mask_mode (dest_mode);
-  insn_expander<RVV_INSN_OPERANDS_MAX> e (/*OP_NUM*/ op_num,
-					  /*HAS_DEST_P*/ true,
-					  /*FULLY_UNMASKED_P*/ false,
-					  /*USE_REAL_MERGE_P*/ true,
-					  /*HAS_AVL_P*/ true,
-					  /*VLMAX_P*/ true, dest_mode,
-					  mask_mode);
-  e.set_policy (TAIL_ANY);
-  e.set_policy (MASK_UNDISTURBED);
-  e.set_rounding_mode (FRM_DYN);
-  e.emit_insn ((enum insn_code) icode, ops);
-}
-
-/* This function emits a TU instruction.  */
-static void
-emit_nonvlmax_tu_insn (unsigned icode, int op_num, rtx *ops, rtx avl)
-{
-  machine_mode dest_mode = GET_MODE (ops[0]);
-  machine_mode mask_mode = get_mask_mode (dest_mode);
-  insn_expander<RVV_INSN_OPERANDS_MAX> e (/*OP_NUM*/ op_num,
-					  /*HAS_DEST_P*/ true,
-					  /*FULLY_UNMASKED_P*/ false,
-					  /*USE_REAL_MERGE_P*/ true,
-					  /*HAS_AVL_P*/ true,
-					  /*VLMAX_P*/ false, dest_mode,
-					  mask_mode);
-  e.set_policy (TAIL_UNDISTURBED);
-  e.set_policy (MASK_ANY);
-  e.set_vl (avl);
-  e.emit_insn ((enum insn_code) icode, ops);
-}
-
-/* This function emits a TU instruction.  */
-static void
-emit_nonvlmax_fp_tu_insn (unsigned icode, int op_num, rtx *ops, rtx avl)
-{
-  machine_mode dest_mode = GET_MODE (ops[0]);
-  machine_mode mask_mode = get_mask_mode (dest_mode);
-  insn_expander<RVV_INSN_OPERANDS_MAX> e (/*OP_NUM*/ op_num,
-					  /*HAS_DEST_P*/ true,
-					  /*FULLY_UNMASKED_P*/ false,
-					  /*USE_REAL_MERGE_P*/ true,
-					  /*HAS_AVL_P*/ true,
-					  /*VLMAX_P*/ false, dest_mode,
-					  mask_mode);
-  e.set_policy (TAIL_UNDISTURBED);
-  e.set_policy (MASK_ANY);
-  e.set_rounding_mode (FRM_DYN);
-  e.set_vl (avl);
-  e.emit_insn ((enum insn_code) icode, ops);
-}
-
-/* This function emits a TUMU instruction.  */
-static void
-emit_nonvlmax_tumu_insn (unsigned icode, int op_num, rtx *ops, rtx avl)
-{
-  machine_mode dest_mode = GET_MODE (ops[0]);
-  machine_mode mask_mode = get_mask_mode (dest_mode);
-  insn_expander<RVV_INSN_OPERANDS_MAX> e (/*OP_NUM*/ op_num,
-					  /*HAS_DEST_P*/ true,
-					  /*FULLY_UNMASKED_P*/ false,
-					  /*USE_REAL_MERGE_P*/ true,
-					  /*HAS_AVL_P*/ true,
-					  /*VLMAX_P*/ false, dest_mode,
-					  mask_mode);
-  e.set_policy (TAIL_UNDISTURBED);
-  e.set_policy (MASK_UNDISTURBED);
-  e.set_vl (avl);
-  e.emit_insn ((enum insn_code) icode, ops);
-}
-
-/* This function emits a TUMU instruction.  */
-static void
-emit_nonvlmax_fp_tumu_insn (unsigned icode, int op_num, rtx *ops, rtx avl)
-{
-  machine_mode dest_mode = GET_MODE (ops[0]);
-  machine_mode mask_mode = get_mask_mode (dest_mode);
-  insn_expander<RVV_INSN_OPERANDS_MAX> e (/*OP_NUM*/ op_num,
-					  /*HAS_DEST_P*/ true,
-					  /*FULLY_UNMASKED_P*/ false,
-					  /*USE_REAL_MERGE_P*/ true,
-					  /*HAS_AVL_P*/ true,
-					  /*VLMAX_P*/ false, dest_mode,
-					  mask_mode);
-  e.set_policy (TAIL_UNDISTURBED);
-  e.set_policy (MASK_UNDISTURBED);
-  e.set_rounding_mode (FRM_DYN);
-  e.set_vl (avl);
-  e.emit_insn ((enum insn_code) icode, ops);
-}
-
-/* Emit vmv.s.x instruction.  */
-
-void
-emit_scalar_move_insn (unsigned icode, rtx *ops, rtx len)
-{
-  machine_mode dest_mode = GET_MODE (ops[0]);
-  machine_mode mask_mode = get_mask_mode (dest_mode);
-  insn_expander<RVV_INSN_OPERANDS_MAX> e (RVV_SCALAR_MOV_OP,
-					  /* HAS_DEST_P */ true,
-					  /* FULLY_UNMASKED_P */ false,
-					  /* USE_REAL_MERGE_P */ true,
-					  /* HAS_AVL_P */ true,
-					  /* VLMAX_P */ false,
-					  dest_mode,
-					  mask_mode);
-
-  e.set_policy (TAIL_ANY);
-  e.set_policy (MASK_ANY);
-  e.set_vl (len ? len : CONST1_RTX (Pmode));
-  e.emit_insn ((enum insn_code) icode, ops);
-}
-
-/* Emit vcpop.m instruction.  */
-
-static void
-emit_cpop_insn (unsigned icode, rtx *ops, rtx len)
-{
-  machine_mode dest_mode = GET_MODE (ops[0]);
-  machine_mode mask_mode = GET_MODE (ops[1]);
-  insn_expander<RVV_INSN_OPERANDS_MAX> e (RVV_CPOP,
-					  /* HAS_DEST_P */ true,
-					  /* FULLY_UNMASKED_P */ true,
-					  /* USE_REAL_MERGE_P */ true,
-					  /* HAS_AVL_P */ true,
-					  /* VLMAX_P */ len ? false : true,
-					  dest_mode, mask_mode);
-
-  e.set_vl (len);
-  e.emit_insn ((enum insn_code) icode, ops);
-}
-
-/* Emit vmv.v.x instruction with vlmax.  */
-
-static void
-emit_vlmax_integer_move_insn (unsigned icode, rtx *ops, rtx vl)
-{
-  emit_vlmax_insn (icode, riscv_vector::RVV_UNOP, ops, vl);
-}
-
-/* Emit vmv.v.x instruction with nonvlmax.  */
-
-void
-emit_nonvlmax_integer_move_insn (unsigned icode, rtx *ops, rtx avl)
-{
-  emit_nonvlmax_insn (icode, riscv_vector::RVV_UNOP, ops, avl);
-}
-
 /* This function emits VLMAX vrgather instruction. Emit vrgather.vx/vi when sel
    is a const duplicate vector. Otherwise, emit vrgather.vv.  */
 static void
@@ -1167,7 +789,7 @@ emit_vlmax_gather_insn (rtx target, rtx op, rtx sel)
   else
     icode = code_for_pred_gather (data_mode);
   rtx ops[] = {target, op, sel};
-  emit_vlmax_insn (icode, RVV_BINOP, ops);
+  emit_vlmax_insn (icode, BINARY_OP, ops);
 }
 
 static void
@@ -1186,8 +808,8 @@ emit_vlmax_masked_gather_mu_insn (rtx target, rtx op, rtx sel, rtx mask)
     }
   else
     icode = code_for_pred_gather (data_mode);
-  rtx ops[RVV_BINOP_MASK] = {target, mask, target, op, sel};
-  emit_vlmax_masked_mu_insn (icode, RVV_BINOP_MASK, ops);
+  rtx ops[] = {target, mask, target, op, sel};
+  emit_vlmax_insn (icode, BINARY_OP_TAMU, ops);
 }
 
 /* According to RVV ISA spec (16.5.1. Synthesizing vdecompress):
@@ -1212,7 +834,7 @@ emit_vlmax_masked_gather_mu_insn (rtx target, rtx op, rtx sel, rtx mask)
      p q r s t u v w  # v11 destination register
 	   e d c b a  # v1 source vector
      1 0 0 1 1 1 0 1  # v0 mask vector
-
+make
      4 4 4 3 2 1 1 0  # v10 result of viota.m
      e q r d c b v a  # v11 destination after vrgather using viota.m under mask
 */
@@ -1226,105 +848,11 @@ emit_vlmax_decompress_insn (rtx target, rtx op0, rtx op1, rtx mask)
 
   rtx sel = gen_reg_rtx (sel_mode);
   rtx iota_ops[] = {sel, mask};
-  emit_vlmax_insn (code_for_pred_iota (sel_mode), RVV_UNOP, iota_ops);
+  emit_vlmax_insn (code_for_pred_iota (sel_mode), UNARY_OP, iota_ops);
   emit_vlmax_gather_insn (target, op0, sel);
   emit_vlmax_masked_gather_mu_insn (target, op1, sel, mask);
 }
 
-/* Emit compress instruction.  */
-static void
-emit_vlmax_compress_insn (unsigned icode, rtx *ops)
-{
-  machine_mode dest_mode = GET_MODE (ops[0]);
-  machine_mode mask_mode = get_mask_mode (dest_mode);
-  insn_expander<RVV_INSN_OPERANDS_MAX> e (RVV_COMPRESS_OP,
-					  /* HAS_DEST_P */ true,
-					  /* FULLY_UNMASKED_P */ false,
-					  /* USE_REAL_MERGE_P */ true,
-					  /* HAS_AVL_P */ true,
-					  /* VLMAX_P */ true, dest_mode,
-					  mask_mode);
-
-  e.set_policy (TAIL_ANY);
-  e.emit_insn ((enum insn_code) icode, ops);
-}
-
-/* Emit compress instruction.  */
-static void
-emit_nonvlmax_compress_insn (unsigned icode, rtx *ops, rtx avl)
-{
-  machine_mode dest_mode = GET_MODE (ops[0]);
-  machine_mode mask_mode = get_mask_mode (dest_mode);
-  insn_expander<RVV_INSN_OPERANDS_MAX> e (RVV_COMPRESS_OP,
-					  /* HAS_DEST_P */ true,
-					  /* FULLY_UNMASKED_P */ false,
-					  /* USE_REAL_MERGE_P */ true,
-					  /* HAS_AVL_P */ true,
-					  /* VLMAX_P */ true, dest_mode,
-					  mask_mode);
-
-  e.set_policy (TAIL_ANY);
-  e.set_vl (avl);
-  e.emit_insn ((enum insn_code) icode, ops);
-}
-
-/* Emit reduction instruction.  */
-static void
-emit_vlmax_reduction_insn (unsigned icode, int op_num, rtx *ops)
-{
-  machine_mode dest_mode = GET_MODE (ops[0]);
-  machine_mode mask_mode = get_mask_mode (GET_MODE (ops[1]));
-  insn_expander<RVV_INSN_OPERANDS_MAX> e (op_num,
-					  /* HAS_DEST_P */ true,
-					  /* FULLY_UNMASKED_P */ true,
-					  /* USE_REAL_MERGE_P */ false,
-					  /* HAS_AVL_P */ true,
-					  /* VLMAX_P */ true, dest_mode,
-					  mask_mode);
-
-  e.set_policy (TAIL_ANY);
-  e.emit_insn ((enum insn_code) icode, ops);
-}
-
-/* Emit reduction instruction.  */
-static void
-emit_vlmax_fp_reduction_insn (unsigned icode, int op_num, rtx *ops)
-{
-  machine_mode dest_mode = GET_MODE (ops[0]);
-  machine_mode mask_mode = get_mask_mode (GET_MODE (ops[1]));
-  insn_expander<RVV_INSN_OPERANDS_MAX> e (op_num,
-					  /* HAS_DEST_P */ true,
-					  /* FULLY_UNMASKED_P */ true,
-					  /* USE_REAL_MERGE_P */ false,
-					  /* HAS_AVL_P */ true,
-					  /* VLMAX_P */ true, dest_mode,
-					  mask_mode);
-
-  e.set_policy (TAIL_ANY);
-  e.set_rounding_mode (FRM_DYN);
-  e.emit_insn ((enum insn_code) icode, ops);
-}
-
-/* Emit reduction instruction.  */
-static void
-emit_nonvlmax_fp_reduction_insn (unsigned icode, int op_num, rtx *ops, rtx vl)
-{
-  machine_mode dest_mode = GET_MODE (ops[0]);
-  machine_mode mask_mode = get_mask_mode (GET_MODE (ops[1]));
-  insn_expander<RVV_INSN_OPERANDS_MAX> e (op_num,
-					  /* HAS_DEST_P */ true,
-					  /* FULLY_UNMASKED_P */ false,
-					  /* USE_REAL_MERGE_P */ true,
-					  /* HAS_AVL_P */ true,
-					  /* VLMAX_P */ false, dest_mode,
-					  mask_mode);
-
-  e.set_policy (TAIL_ANY);
-  e.set_rounding_mode (FRM_DYN);
-  e.set_vl (vl);
-  e.emit_insn ((enum insn_code) icode, ops);
-}
-
 /* Emit merge instruction.  */
 
 static machine_mode
@@ -1356,7 +884,7 @@ expand_vec_series (rtx dest, rtx base, rtx step)
   /* Step 1: Generate I = { 0, 1, 2, ... } by vid.v.  */
   rtx vid = gen_reg_rtx (mode);
   rtx op[] = {vid};
-  emit_vlmax_insn (code_for_pred_series (mode), RVV_MISC_OP, op);
+  emit_vlmax_insn (code_for_pred_series (mode), NULLARY_OP, op);
 
   rtx step_adj;
   if (rtx_equal_p (step, constm1_rtx)
@@ -1373,7 +901,7 @@ expand_vec_series (rtx dest, rtx base, rtx step)
       rtx ops[]
 	= {result, vid, gen_int_mode (nunits_m1, GET_MODE_INNER (mode))};
       insn_code icode = code_for_pred_sub_reverse_scalar (mode);
-      emit_vlmax_insn (icode, RVV_BINOP, ops);
+      emit_vlmax_insn (icode, BINARY_OP, ops);
     }
   else
     {
@@ -1393,13 +921,13 @@ expand_vec_series (rtx dest, rtx base, rtx step)
 	      rtx shift_amount = gen_int_mode (shift, Pmode);
 	      insn_code icode = code_for_pred_scalar (ASHIFT, mode);
 	      rtx ops[] = {step_adj, vid, shift_amount};
-	      emit_vlmax_insn (icode, RVV_BINOP, ops);
+	      emit_vlmax_insn (icode, BINARY_OP, ops);
 	    }
 	  else
 	    {
 	      insn_code icode = code_for_pred_scalar (MULT, mode);
 	      rtx ops[] = {step_adj, vid, step};
-	      emit_vlmax_insn (icode, RVV_BINOP, ops);
+	      emit_vlmax_insn (icode, BINARY_OP, ops);
 	    }
 	}
 
@@ -1412,7 +940,7 @@ expand_vec_series (rtx dest, rtx base, rtx step)
 	{
 	  insn_code icode = code_for_pred_scalar (PLUS, mode);
 	  rtx ops[] = {result, step_adj, base};
-	  emit_vlmax_insn (icode, RVV_BINOP, ops);
+	  emit_vlmax_insn (icode, BINARY_OP, ops);
 	}
     }
 
@@ -1431,7 +959,7 @@ expand_const_vector (rtx target, rtx src)
 	const_vec_duplicate_p (src, &elt)
 	&& (rtx_equal_p (elt, const0_rtx) || rtx_equal_p (elt, const1_rtx)));
       rtx ops[] = {target, src};
-      emit_vlmax_insn (code_for_pred_mov (mode), RVV_UNOP, ops);
+      emit_vlmax_insn (code_for_pred_mov (mode), UNARY_MASK_OP, ops);
       return;
     }
 
@@ -1444,12 +972,12 @@ expand_const_vector (rtx target, rtx src)
       if (satisfies_constraint_vi (src) || satisfies_constraint_Wc0 (src))
 	{
 	  rtx ops[] = {tmp, src};
-	  emit_vlmax_insn (code_for_pred_mov (mode), RVV_UNOP, ops);
+	  emit_vlmax_insn (code_for_pred_mov (mode), UNARY_OP, ops);
 	}
       else
 	{
 	  rtx ops[] = {tmp, elt};
-	  emit_vlmax_insn (code_for_pred_broadcast (mode), RVV_UNOP, ops);
+	  emit_vlmax_insn (code_for_pred_broadcast (mode), UNARY_OP, ops);
 	}
 
       if (tmp != target)
@@ -1514,19 +1042,19 @@ expand_const_vector (rtx target, rtx src)
 	  rtx vid = gen_reg_rtx (builder.int_mode ());
 	  rtx op[] = {vid};
 	  emit_vlmax_insn (code_for_pred_series (builder.int_mode ()),
-			   RVV_MISC_OP, op);
+			    NULLARY_OP, op);
 
 	  /* Generate vid_repeat = { 0, 1, ... nbits, ... }  */
 	  rtx vid_repeat = gen_reg_rtx (builder.int_mode ());
 	  rtx and_ops[] = {vid_repeat, vid,
 			   gen_int_mode (nbits, builder.inner_int_mode ())};
 	  emit_vlmax_insn (code_for_pred_scalar (AND, builder.int_mode ()),
-			   RVV_BINOP, and_ops);
+			    BINARY_OP, and_ops);
 
 	  rtx tmp = gen_reg_rtx (builder.mode ());
 	  rtx dup_ops[] = {tmp, builder.elt (0)};
-	  emit_vlmax_insn (code_for_pred_broadcast (builder.mode ()), RVV_UNOP,
-			   dup_ops);
+	  emit_vlmax_insn (code_for_pred_broadcast (builder.mode ()), UNARY_OP,
+			    dup_ops);
 	  for (unsigned int i = 1; i < builder.npatterns (); i++)
 	    {
 	      /* Generate mask according to i.  */
@@ -1538,7 +1066,7 @@ expand_const_vector (rtx target, rtx src)
 	      rtx tmp2 = gen_reg_rtx (builder.mode ());
 	      rtx merge_ops[] = {tmp2, tmp, builder.elt (i), mask};
 	      insn_code icode = code_for_pred_merge_scalar (builder.mode ());
-	      emit_vlmax_merge_insn (icode, RVV_MERGE_OP, merge_ops);
+	      emit_vlmax_insn (icode, MERGE_OP, merge_ops);
 	      tmp = tmp2;
 	    }
 	  emit_move_insn (target, tmp);
@@ -1556,7 +1084,7 @@ expand_const_vector (rtx target, rtx src)
 	  rtx vid = gen_reg_rtx (builder.mode ());
 	  rtx vid_ops[] = {vid};
 	  icode = code_for_pred_series (builder.mode ());
-	  emit_vlmax_insn (icode, RVV_MISC_OP, vid_ops);
+	  emit_vlmax_insn (icode, NULLARY_OP, vid_ops);
 
 	  if (builder.npatterns_all_equal_p ())
 	    {
@@ -1574,7 +1102,7 @@ expand_const_vector (rtx target, rtx src)
 	      rtx tmp = gen_reg_rtx (builder.mode ());
 	      rtx and_ops[] = {tmp, vid, imm};
 	      icode = code_for_pred_scalar (AND, builder.mode ());
-	      emit_vlmax_insn (icode, RVV_BINOP, and_ops);
+	      emit_vlmax_insn (icode, BINARY_OP, and_ops);
 	      HOST_WIDE_INT init_val = INTVAL (builder.elt (0));
 	      if (init_val == 0)
 		emit_move_insn (target, tmp);
@@ -1583,7 +1111,7 @@ expand_const_vector (rtx target, rtx src)
 		  rtx dup = gen_const_vector_dup (builder.mode (), init_val);
 		  rtx add_ops[] = {target, tmp, dup};
 		  icode = code_for_pred (PLUS, builder.mode ());
-		  emit_vlmax_insn (icode, RVV_BINOP, add_ops);
+		  emit_vlmax_insn (icode, BINARY_OP, add_ops);
 		}
 	    }
 	  else
@@ -1604,8 +1132,8 @@ expand_const_vector (rtx target, rtx src)
 	      /* Step 2: Generate result = VID + diff.  */
 	      rtx vec = v.build ();
 	      rtx add_ops[] = {target, vid, vec};
-	      emit_vlmax_insn (code_for_pred (PLUS, builder.mode ()), RVV_BINOP,
-			       add_ops);
+	      emit_vlmax_insn (code_for_pred (PLUS, builder.mode ()),
+				BINARY_OP, add_ops);
 	    }
 	}
       else if (npatterns == 1 && nelts_per_pattern == 3)
@@ -1728,13 +1256,15 @@ legitimize_move (rtx dest, rtx src)
       return true;
     }
 
+  unsigned insn_flags
+    = GET_MODE_CLASS (mode) == MODE_VECTOR_BOOL ? UNARY_MASK_OP : UNARY_OP;
   if (!register_operand (src, mode) && !register_operand (dest, mode))
     {
       rtx tmp = gen_reg_rtx (mode);
       if (MEM_P (src))
 	{
 	  rtx ops[] = {tmp, src};
-	  emit_vlmax_insn (code_for_pred_mov (mode), RVV_UNOP, ops);
+	  emit_vlmax_insn (code_for_pred_mov (mode), insn_flags, ops);
 	}
       else
 	emit_move_insn (tmp, src);
@@ -1745,7 +1275,7 @@ legitimize_move (rtx dest, rtx src)
     return false;
 
   rtx ops[] = {dest, src};
-  emit_vlmax_insn (code_for_pred_mov (mode), RVV_UNOP, ops);
+  emit_vlmax_insn (code_for_pred_mov (mode), insn_flags, ops);
   return true;
 }
 
@@ -2090,8 +1620,7 @@ sew64_scalar_helper (rtx *operands, rtx *scalar_op, rtx vl,
 
   rtx tmp = gen_reg_rtx (vector_mode);
   rtx ops[] = {tmp, *scalar_op};
-  riscv_vector::emit_nonvlmax_insn (code_for_pred_broadcast (vector_mode),
-				    riscv_vector::RVV_UNOP, ops, vl);
+  emit_nonvlmax_insn (code_for_pred_broadcast (vector_mode), UNARY_OP, ops, vl);
   emit_vector_func (operands, tmp);
 
   return true;
@@ -2398,8 +1927,8 @@ expand_tuple_move (rtx *ops)
 	      if (fractional_p)
 		{
 		  rtx operands[] = {subreg, mem};
-		  emit_vlmax_insn (code_for_pred_mov (subpart_mode), RVV_UNOP,
-				   operands, ops[4]);
+		  emit_vlmax_insn_lra (code_for_pred_mov (subpart_mode),
+					UNARY_OP, operands, ops[4]);
 		}
 	      else
 		emit_move_insn (subreg, mem);
@@ -2423,8 +1952,8 @@ expand_tuple_move (rtx *ops)
 	      if (fractional_p)
 		{
 		  rtx operands[] = {mem, subreg};
-		  emit_vlmax_insn (code_for_pred_mov (subpart_mode), RVV_UNOP,
-				   operands, ops[4]);
+		  emit_vlmax_insn_lra (code_for_pred_mov (subpart_mode),
+					UNARY_OP, operands, ops[4]);
 		}
 	      else
 		emit_move_insn (mem, subreg);
@@ -2488,7 +2017,7 @@ expand_vector_init_insert_elems (rtx target, const rvv_builder &builder,
 	= FLOAT_MODE_P (mode) ? UNSPEC_VFSLIDE1DOWN : UNSPEC_VSLIDE1DOWN;
       insn_code icode = code_for_pred_slide (unspec, mode);
       rtx ops[] = {target, target, builder.elt (i)};
-      emit_vlmax_insn (icode, RVV_BINOP, ops);
+      emit_vlmax_insn (icode, BINARY_OP, ops);
     }
 }
 
@@ -2504,15 +2033,13 @@ expand_vector_init_merge_repeating_sequence (rtx target,
 					     const rvv_builder &builder)
 {
   machine_mode dup_mode = get_repeating_sequence_dup_machine_mode (builder);
-  machine_mode dup_mask_mode = get_mask_mode (dup_mode);
   machine_mode mask_mode = get_mask_mode (builder.mode ());
   uint64_t full_nelts = builder.full_nelts ().to_constant ();
 
   /* Step 1: Broadcast the first pattern.  */
   rtx ops[] = {target, force_reg (GET_MODE_INNER (dup_mode), builder.elt (0))};
-  emit_vlmax_integer_move_insn (code_for_pred_broadcast (builder.mode ()),
-				ops, NULL_RTX);
-
+  emit_vlmax_insn (code_for_pred_broadcast (builder.mode ()),
+		    UNARY_OP, ops);
   /* Step 2: Merge the rest iteration of pattern.  */
   for (unsigned int i = 1; i < builder.npatterns (); i++)
     {
@@ -2523,26 +2050,25 @@ expand_vector_init_merge_repeating_sequence (rtx target,
 
       if (full_nelts <= builder.inner_bits_size ()) /* vmv.s.x.  */
 	{
-	  rtx ops[] = {dup, gen_scalar_move_mask (dup_mask_mode),
-	    RVV_VUNDEF (dup_mode), merge_mask};
-	  emit_scalar_move_insn (code_for_pred_broadcast (GET_MODE (dup)),
-				 ops);
+	  rtx ops[] = {dup, merge_mask};
+	  emit_nonvlmax_insn (code_for_pred_broadcast (GET_MODE (dup)),
+			       SCALAR_MOVE_OP, ops, CONST1_RTX (Pmode));
 	}
       else /* vmv.v.x.  */
 	{
 	  rtx ops[] = {dup, force_reg (GET_MODE_INNER (dup_mode), merge_mask)};
 	  rtx vl = gen_int_mode (CEIL (full_nelts, builder.inner_bits_size ()),
 				 Pmode);
-	  emit_nonvlmax_integer_move_insn (code_for_pred_broadcast (dup_mode),
-					   ops, vl);
+	  emit_nonvlmax_insn (code_for_pred_broadcast (dup_mode), UNARY_OP,
+			       ops, vl);
 	}
 
       emit_move_insn (mask, gen_lowpart (mask_mode, dup));
 
       /* Step 2-2: Merge pattern according to the mask.  */
       rtx ops[] = {target, target, builder.elt (i), mask};
-      emit_vlmax_merge_insn (code_for_pred_merge_scalar (GET_MODE (target)),
-			     riscv_vector::RVV_MERGE_OP, ops);
+      emit_vlmax_insn (code_for_pred_merge_scalar (GET_MODE (target)),
+			MERGE_OP, ops);
     }
 }
 
@@ -2739,13 +2265,13 @@ expand_vec_cmp (rtx target, rtx_code code, rtx op0, rtx op1)
       expand_vec_cmp (gt, GT, op0, op1);
       icode = code_for_pred (IOR, mask_mode);
       rtx ops[] = {target, lt, gt};
-      emit_vlmax_insn (icode, riscv_vector::RVV_BINOP, ops);
+      emit_vlmax_insn (icode, BINARY_MASK_OP, ops);
       return;
     }
 
   rtx cmp = gen_rtx_fmt_ee (code, mask_mode, op0, op1);
   rtx ops[] = {target, cmp, op0, op1};
-  emit_vlmax_cmp_insn (icode, ops);
+  emit_vlmax_insn (icode, COMPARE_OP, ops);
 }
 
 void
@@ -2764,13 +2290,13 @@ expand_vec_cmp (rtx target, rtx_code code, rtx mask, rtx maskoff, rtx op0,
       expand_vec_cmp (gt, GT, mask, maskoff, op0, op1);
       icode = code_for_pred (IOR, mask_mode);
       rtx ops[] = {target, lt, gt};
-      emit_vlmax_insn (icode, RVV_BINOP, ops);
+      emit_vlmax_insn (icode, BINARY_MASK_OP, ops);
       return;
     }
 
   rtx cmp = gen_rtx_fmt_ee (code, mask_mode, op0, op1);
   rtx ops[] = {target, mask, maskoff, cmp, op0, op1};
-  emit_vlmax_cmp_mu_insn (icode, ops);
+  emit_vlmax_insn (icode, COMPARE_OP_MU, ops);
 }
 
 /* Expand an RVV floating-point comparison:
@@ -2843,7 +2369,7 @@ expand_vec_cmp_float (rtx target, rtx_code code, rtx op0, rtx op1,
 	  expand_vec_cmp (eq1, EQ, op1, op1);
 	  insn_code icode = code_for_pred (AND, mask_mode);
 	  rtx ops[] = {eq0, eq0, eq1};
-	  emit_vlmax_insn (icode, riscv_vector::RVV_BINOP, ops);
+	  emit_vlmax_insn (icode, BINARY_MASK_OP, ops);
 	}
       else
 	{
@@ -2972,7 +2498,7 @@ expand_vec_perm (rtx target, rtx op0, rtx op1, rtx sel)
 	    [0, max_of_mode - nunits].  */
   rtx tmp = gen_reg_rtx (sel_mode);
   rtx ops[] = {tmp, sel_mod, max_sel};
-  emit_vlmax_insn (code_for_pred (MINUS, sel_mode), RVV_BINOP, ops);
+  emit_vlmax_insn (code_for_pred (MINUS, sel_mode), BINARY_OP, ops);
 
   /* Step4: gather those into the previously masked-out elements
 	    of target.  */
@@ -3037,12 +2563,12 @@ shuffle_merge_patterns (struct expand_vec_perm_d *d)
   insn_code icode = code_for_pred_cmp_scalar (sel_mode);
   rtx cmp = gen_rtx_fmt_ee (LTU, mask_mode, sel, x);
   rtx ops[] = {mask, cmp, sel, x};
-  emit_vlmax_cmp_insn (icode, ops);
+  emit_vlmax_insn (icode, COMPARE_OP, ops);
 
   /* TARGET = MASK ? OP0 : OP1.  */
   /* swap op0 and op1 since the order is opposite to pred_merge.  */
   rtx ops2[] = {d->target, d->op1, d->op0, mask};
-  emit_vlmax_merge_insn (code_for_pred_merge (vmode), riscv_vector::RVV_MERGE_OP, ops2);
+  emit_vlmax_insn (code_for_pred_merge (vmode), MERGE_OP, ops2);
   return true;
 }
 
@@ -3173,16 +2699,15 @@ shuffle_compress_patterns (struct expand_vec_perm_d *d)
   if (need_slideup_p)
     {
       int slideup_cnt = vlen - (d->perm[vlen - 1].to_constant () % vlen) - 1;
-      rtx ops[] = {d->target, RVV_VUNDEF (vmode), d->op1,
-		   gen_int_mode (slideup_cnt, Pmode)};
+      rtx ops[] = {d->target, d->op1, gen_int_mode (slideup_cnt, Pmode)};
       insn_code icode = code_for_pred_slide (UNSPEC_VSLIDEUP, vmode);
-      emit_vlmax_slide_insn (icode, ops);
+      emit_vlmax_insn (icode, BINARY_OP, ops);
       merge = d->target;
     }
 
   insn_code icode = code_for_pred_compress (vmode);
   rtx ops[] = {d->target, merge, d->op0, mask};
-  emit_vlmax_compress_insn (icode, ops);
+  emit_vlmax_insn (icode, COMPRESS_OP_MERGE, ops);
   return true;
 }
 
@@ -3238,15 +2763,15 @@ shuffle_decompress_patterns (struct expand_vec_perm_d *d)
       insn_code icode = code_for_pred_slide (UNSPEC_VSLIDEDOWN, d->vmode);
       rtx ops0[] = {op0, d->op0, gen_int_mode (first, Pmode)};
       rtx ops1[] = {op1, d->op1, gen_int_mode (first, Pmode)};
-      emit_vlmax_insn (icode, RVV_BINOP, ops0);
-      emit_vlmax_insn (icode, RVV_BINOP, ops1);
+      emit_vlmax_insn (icode, BINARY_OP, ops0);
+      emit_vlmax_insn (icode, BINARY_OP, ops1);
     }
   /* Generate { 0, 1, .... } mask.  */
   rtx vid = gen_reg_rtx (sel_mode);
   rtx vid_repeat = gen_reg_rtx (sel_mode);
   emit_insn (gen_vec_series (sel_mode, vid, const0_rtx, const1_rtx));
   rtx and_ops[] = {vid_repeat, vid, const1_rtx};
-  emit_vlmax_insn (code_for_pred_scalar (AND, sel_mode), RVV_BINOP, and_ops);
+  emit_vlmax_insn (code_for_pred_scalar (AND, sel_mode), BINARY_OP, and_ops);
   rtx const_vec = gen_const_vector_dup (sel_mode, 1);
   rtx mask = gen_reg_rtx (mask_mode);
   expand_vec_cmp (mask, EQ, vid_repeat, const_vec);
@@ -3400,8 +2925,8 @@ expand_load_store (rtx *ops, bool is_load)
       /* If the length operand is equal to VF, it is VLMAX load/store.  */
       if (is_load)
 	{
-	  rtx m_ops[] = {ops[0], mask, RVV_VUNDEF (mode), ops[1]};
-	  emit_vlmax_masked_insn (code_for_pred_mov (mode), RVV_UNOP_MASK, m_ops);
+	  rtx m_ops[] = {ops[0], mask, ops[1]};
+	  emit_vlmax_insn (code_for_pred_mov (mode), UNARY_OP_TAMA, m_ops);
 	}
       else
 	{
@@ -3417,9 +2942,9 @@ expand_load_store (rtx *ops, bool is_load)
 	len = force_reg (Pmode, len);
       if (is_load)
 	{
-	  rtx m_ops[] = {ops[0], mask, RVV_VUNDEF (mode), ops[1]};
-	  emit_nonvlmax_masked_insn (code_for_pred_mov (mode), RVV_UNOP_MASK,
-				     m_ops, len);
+	  rtx m_ops[] = {ops[0], mask, ops[1]};
+	  emit_nonvlmax_insn (code_for_pred_mov (mode), UNARY_OP_TAMA, m_ops,
+			       len);
 	}
       else
 	emit_insn (gen_pred_store (mode, ops[0], mask, ops[1], len,
@@ -3439,7 +2964,7 @@ needs_fp_rounding (rtx_code code, machine_mode mode)
 
 /* Subroutine to expand COND_LEN_* patterns.  */
 static void
-expand_cond_len_op (rtx_code code, unsigned icode, int num_ops, rtx *ops,
+expand_cond_len_op (rtx_code code, unsigned icode, insn_flags op_type, rtx *ops,
 		    rtx len)
 {
   rtx dest = ops[0];
@@ -3450,33 +2975,22 @@ expand_cond_len_op (rtx_code code, unsigned icode, int num_ops, rtx *ops,
   bool is_dummy_mask = rtx_equal_p (mask, CONSTM1_RTX (mask_mode));
   bool is_vlmax_len
     = poly_int_rtx_p (len, &value) && known_eq (value, GET_MODE_NUNITS (mode));
+
+  unsigned insn_flags = HAS_DEST_P | HAS_MASK_P | HAS_MERGE_P | op_type;
   if (is_dummy_mask)
-    {
-      /* Use TU, MASK ANY policy.  */
-      if (needs_fp_rounding (code, mode))
-	emit_nonvlmax_fp_tu_insn (icode, num_ops, ops, len);
-      else
-	emit_nonvlmax_tu_insn (icode, num_ops, ops, len);
-    }
+    insn_flags |= TU_POLICY_P | MDEFAULT_POLICY_P;
+  else if (is_vlmax_len)
+    insn_flags |= TDEFAULT_POLICY_P | MU_POLICY_P;
   else
-    {
-      if (is_vlmax_len)
-	{
-	  /* Use TAIL ANY, MU policy.  */
-	  if (needs_fp_rounding (code, mode))
-	    emit_vlmax_masked_fp_mu_insn (icode, num_ops, ops);
-	  else
-	    emit_vlmax_masked_mu_insn (icode, num_ops, ops);
-	}
-      else
-	{
-	  /* Use TU, MU policy.  */
-	  if (needs_fp_rounding (code, mode))
-	    emit_nonvlmax_fp_tumu_insn (icode, num_ops, ops, len);
-	  else
-	    emit_nonvlmax_tumu_insn (icode, num_ops, ops, len);
-	}
-    }
+    insn_flags |= TU_POLICY_P | MU_POLICY_P;
+
+  if (needs_fp_rounding (code, mode))
+    insn_flags |= FRM_DYN_P;
+
+  if (is_vlmax_len)
+    emit_vlmax_insn (icode, insn_flags, ops);
+  else
+    emit_nonvlmax_insn (icode, insn_flags, ops, len);
 }
 
 /* Expand unary ops COND_LEN_*.  */
@@ -3491,8 +3005,8 @@ expand_cond_len_unop (rtx_code code, rtx *ops)
 
   machine_mode mode = GET_MODE (dest);
   insn_code icode = code_for_pred (code, mode);
-  rtx cond_ops[RVV_UNOP_MASK] = {dest, mask, merge, src};
-  expand_cond_len_op (code, icode, RVV_UNOP_MASK, cond_ops, len);
+  rtx cond_ops[] = {dest, mask, merge, src};
+  expand_cond_len_op (code, icode, UNARY_OP_P, cond_ops, len);
 }
 
 /* Expand binary ops COND_LEN_*.  */
@@ -3508,8 +3022,8 @@ expand_cond_len_binop (rtx_code code, rtx *ops)
 
   machine_mode mode = GET_MODE (dest);
   insn_code icode = code_for_pred (code, mode);
-  rtx cond_ops[RVV_BINOP_MASK] = {dest, mask, merge, src1, src2};
-  expand_cond_len_op (code, icode, RVV_BINOP_MASK, cond_ops, len);
+  rtx cond_ops[] = {dest, mask, merge, src1, src2};
+  expand_cond_len_op (code, icode, BINARY_OP_P, cond_ops, len);
 }
 
 /* Prepare insn_code for gather_load/scatter_store according to
@@ -3643,13 +3157,13 @@ expand_gather_scatter (rtx *ops, bool is_load)
       if (is_load)
 	{
 	  rtx load_ops[]
-	    = {vec_reg, mask, RVV_VUNDEF (vec_mode), ptr, vec_offset};
-	  emit_vlmax_masked_insn (icode, RVV_GATHER_M_OP, load_ops);
+	    = {vec_reg, mask, ptr, vec_offset};
+	  emit_vlmax_insn (icode, BINARY_OP_TAMA, load_ops);
 	}
       else
 	{
 	  rtx store_ops[] = {mask, ptr, vec_offset, vec_reg};
-	  emit_vlmax_masked_store_insn (icode, RVV_SCATTER_M_OP, store_ops);
+	  emit_vlmax_insn (icode, SCATTER_OP_M, store_ops);
 	}
     }
   else
@@ -3657,14 +3171,13 @@ expand_gather_scatter (rtx *ops, bool is_load)
       if (is_load)
 	{
 	  rtx load_ops[]
-	    = {vec_reg, mask, RVV_VUNDEF (vec_mode), ptr, vec_offset};
-	  emit_nonvlmax_masked_insn (icode, RVV_GATHER_M_OP, load_ops, len);
+	    = {vec_reg, mask, ptr, vec_offset};
+	  emit_nonvlmax_insn (icode, BINARY_OP_TAMA, load_ops, len);
 	}
       else
 	{
 	  rtx store_ops[] = {mask, ptr, vec_offset, vec_reg};
-	  emit_nonvlmax_masked_store_insn (icode, RVV_SCATTER_M_OP, store_ops,
-					   len);
+	  emit_nonvlmax_insn (icode, SCATTER_OP_M, store_ops, len);
 	}
     }
 }
@@ -3681,8 +3194,8 @@ expand_cond_len_ternop (unsigned icode, rtx *ops)
   rtx merge = ops[5];
   rtx len = ops[6];
 
-  rtx cond_ops[RVV_TERNOP_MASK] = {dest, mask, src1, src2, src3, merge};
-  expand_cond_len_op (UNSPEC, icode, RVV_TERNOP_MASK, cond_ops, len);
+  rtx cond_ops[] = {dest, mask, src1, src2, src3, merge};
+  expand_cond_len_op (UNSPEC, icode, TERNARY_OP_P, cond_ops, len);
 }
 
 /* Expand reduction operations.  */
@@ -3692,16 +3205,14 @@ expand_reduction (rtx_code code, rtx *ops, rtx init, reduction_type type)
   rtx vector = type == reduction_type::UNORDERED ? ops[1] : ops[2];
   machine_mode vmode = GET_MODE (vector);
   machine_mode m1_mode = get_m1_mode (vmode).require ();
-  machine_mode m1_mmode = get_mask_mode (m1_mode);
 
   rtx m1_tmp = gen_reg_rtx (m1_mode);
-  rtx m1_mask = gen_scalar_move_mask (m1_mmode);
-  rtx m1_undef = RVV_VUNDEF (m1_mode);
-  rtx scalar_move_ops[] = {m1_tmp, m1_mask, m1_undef, init};
-  rtx len = type == reduction_type::MASK_LEN_FOLD_LEFT ? ops[4] : NULL_RTX;
-  emit_scalar_move_insn (code_for_pred_broadcast (m1_mode), scalar_move_ops,
-			 len);
-
+  rtx scalar_move_ops[] = {m1_tmp, init};
+  emit_nonvlmax_insn (code_for_pred_broadcast (m1_mode), SCALAR_MOVE_OP,
+		       scalar_move_ops,
+		       type == reduction_type::MASK_LEN_FOLD_LEFT
+			 ? ops[4]
+			 : CONST1_RTX (Pmode));
   rtx m1_tmp2 = gen_reg_rtx (m1_mode);
   rtx reduc_ops[] = {m1_tmp2, vector, m1_tmp};
 
@@ -3715,18 +3226,17 @@ expand_reduction (rtx_code code, rtx *ops, rtx init, reduction_type type)
       if (type == reduction_type::MASK_LEN_FOLD_LEFT)
 	{
 	  rtx mask = ops[3];
-	  rtx mask_len_reduc_ops[]
-	    = {m1_tmp2, mask, RVV_VUNDEF (m1_mode), vector, m1_tmp};
-	  emit_nonvlmax_fp_reduction_insn (icode, RVV_REDUCTION_TU_OP,
-					   mask_len_reduc_ops, len);
+	  rtx mask_len_reduc_ops[] = {m1_tmp2, mask, vector, m1_tmp};
+	  emit_nonvlmax_insn (icode, REDUCE_OP_M_FRM_DYN, mask_len_reduc_ops,
+			       ops[4]);
 	}
       else
-	emit_vlmax_fp_reduction_insn (icode, RVV_REDUCTION_OP, reduc_ops);
+	emit_vlmax_insn (icode, REDUCE_OP_FRM_DYN, reduc_ops);
     }
   else
     {
       insn_code icode = code_for_pred_reduc (code, vmode, m1_mode);
-      emit_vlmax_reduction_insn (icode, RVV_REDUCTION_OP, reduc_ops);
+      emit_vlmax_insn (icode, REDUCE_OP, reduc_ops);
     }
 
   emit_insn (gen_pred_extract_first (m1_mode, ops[0], m1_tmp2));
@@ -3786,9 +3296,9 @@ expand_lanes_load_store (rtx *ops, bool is_load)
       /* If the length operand is equal to VF, it is VLMAX load/store.  */
       if (is_load)
 	{
-	  rtx m_ops[] = {reg, mask, RVV_VUNDEF (mode), addr};
-	  emit_vlmax_masked_insn (code_for_pred_unit_strided_load (mode),
-				  RVV_UNOP_MASK, m_ops);
+	  rtx m_ops[] = {reg, mask, addr};
+	  emit_vlmax_insn (code_for_pred_unit_strided_load (mode), UNARY_OP_TAMA,
+			    m_ops);
 	}
       else
 	{
@@ -3804,9 +3314,9 @@ expand_lanes_load_store (rtx *ops, bool is_load)
 	len = force_reg (Pmode, len);
       if (is_load)
 	{
-	  rtx m_ops[] = {reg, mask, RVV_VUNDEF (mode), addr};
-	  emit_nonvlmax_masked_insn (code_for_pred_unit_strided_load (mode),
-				     RVV_UNOP_MASK, m_ops, len);
+	  rtx m_ops[] = {reg, mask, addr};
+	  emit_nonvlmax_insn (code_for_pred_unit_strided_load (mode),
+			       UNARY_OP_TAMA, m_ops, len);
 	}
       else
 	emit_insn (gen_pred_unit_strided_store (mode, mask, addr, reg, len,
@@ -3839,24 +3349,29 @@ expand_fold_extract_last (rtx *ops)
 
   /* Calculate the number of 1-bit in mask. */
   rtx cpop_ops[] = {anchor, mask};
-  emit_cpop_insn (code_for_pred_popcount (mask_mode, Pmode), cpop_ops, len);
+  if (len)
+    emit_nonvlmax_insn (code_for_pred_popcount (mask_mode, Pmode), CPOP_OP,
+			 cpop_ops, len);
+  else
+    emit_vlmax_insn (code_for_pred_popcount (mask_mode, Pmode), CPOP_OP,
+		      cpop_ops);
 
   riscv_expand_conditional_branch (else_label, EQ, anchor, const0_rtx);
   emit_insn (gen_rtx_SET (index, gen_rtx_PLUS (Pmode, anchor, constm1_rtx)));
   /* Compress the vector.  */
   icode = code_for_pred_compress (mode);
-  rtx compress_ops[] = {compress_vect, RVV_VUNDEF (mode), vect, mask};
+  rtx compress_ops[] = {compress_vect, vect, mask};
   if (len)
-    emit_nonvlmax_compress_insn (icode, compress_ops, len);
+    emit_nonvlmax_insn (icode, COMPRESS_OP, compress_ops, len);
   else
-    emit_vlmax_compress_insn (icode, compress_ops);
+    emit_vlmax_insn (icode, COMPRESS_OP, compress_ops);
   /* Emit the slide down to index 0 in a new vector.  */
-  rtx slide_ops[] = {slide_vect, RVV_VUNDEF (mode), compress_vect, index};
+  rtx slide_ops[] = {slide_vect, compress_vect, index};
   icode = code_for_pred_slide (UNSPEC_VSLIDEDOWN, mode);
   if (len)
-    emit_nonvlmax_slide_insn (icode, slide_ops, len);
+    emit_nonvlmax_insn (icode, BINARY_OP, slide_ops, len);
   else
-    emit_vlmax_slide_insn (icode, slide_ops);
+    emit_vlmax_insn (icode, BINARY_OP, slide_ops);
   /* Emit v(f)mv.[xf].s.  */
   emit_insn (gen_pred_extract_first (mode, dst, slide_vect));
 
diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 5dc303f89c7..d84fa2311fa 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -8581,8 +8581,8 @@ vector_zero_call_used_regs (HARD_REG_SET need_zeroed_hardregs)
 	    }
 
 	  rtx ops[] = {target, CONST0_RTX (mode)};
-	  riscv_vector::emit_vlmax_insn (code_for_pred_mov (mode),
-					 riscv_vector::RVV_UNOP, ops, vl);
+	  riscv_vector::emit_vlmax_insn_lra (code_for_pred_mov (mode),
+					      riscv_vector::UNARY_OP, ops, vl);
 
 	  SET_HARD_REG_BIT (zeroed_hardregs, regno);
 	}
diff --git a/gcc/config/riscv/vector.md b/gcc/config/riscv/vector.md
index 27901c4692c..451138a1b45 100644
--- a/gcc/config/riscv/vector.md
+++ b/gcc/config/riscv/vector.md
@@ -1134,8 +1134,8 @@
   else
     {
       riscv_vector::emit_vlmax_vsetvl (<V_FRACT:MODE>mode, operands[2]);
-      riscv_vector::emit_vlmax_insn (code_for_pred_mov (<V_FRACT:MODE>mode),
-				     riscv_vector::RVV_UNOP, operands, operands[2]);
+      riscv_vector::emit_vlmax_insn_lra (code_for_pred_mov (<V_FRACT:MODE>mode),
+				          riscv_vector::UNARY_OP, operands, operands[2]);
     }
   DONE;
 }
@@ -1156,8 +1156,8 @@
   else
     {
       riscv_vector::emit_vlmax_vsetvl (<VB:MODE>mode, operands[2]);
-      riscv_vector::emit_vlmax_insn (code_for_pred_mov (<VB:MODE>mode),
-				     riscv_vector::RVV_UNOP, operands, operands[2]);
+      riscv_vector::emit_vlmax_insn_lra (code_for_pred_mov (<VB:MODE>mode),
+				          riscv_vector::UNARY_MASK_OP, operands, operands[2]);
     }
   DONE;
 }
@@ -1223,7 +1223,7 @@
   "TARGET_VECTOR"
   {
     riscv_vector::emit_vlmax_insn (code_for_pred_broadcast (<MODE>mode),
-				   riscv_vector::RVV_UNOP, operands);
+				    riscv_vector::UNARY_OP, operands);
     DONE;
   }
 )
-- 
2.36.3


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] RISC-V: Refactor and clean emit_{vlmax, nonvlmax}_xxx functions
  2023-08-30 11:53 [PATCH] RISC-V: Refactor and clean emit_{vlmax,nonvlmax}_xxx functions Lehua Ding
@ 2023-08-31  7:51 ` Kito Cheng
  2023-08-31  8:59   ` Lehua Ding
  2023-08-31  9:16 ` [PATCH] RISC-V: Refactor and clean emit_{vlmax,nonvlmax}_xxx functions Robin Dapp
  1 sibling, 1 reply; 5+ messages in thread
From: Kito Cheng @ 2023-08-31  7:51 UTC (permalink / raw)
  To: Lehua Ding; +Cc: gcc-patches, rdapp.gcc, juzhe.zhong

Thanks for the cleanup, the new interface is really much simpler than before!

Only few minor comment, you can go ahead to commit that after address
those comment.

(OK, I don't want to review whole patch again, it's really huge change :P

>
> -  void set_rounding_mode (enum floating_point_rounding_mode mode)
> +  void check_insn_flags ()

void check_insn_flags () const

>    void emit_insn (enum insn_code icode, rtx *ops)
>    {
>      int opno = 0;
> +    int num_ops = 0;
>      /* It's true if any operand is memory operand.  */
>      bool any_mem_p = false;
> -    /* It's true if all operands are mask operand.  */
> -    bool all_mask_p = true;
> -    if (m_has_dest_p)
> +
> +    /* Add dest operand.  */
> +    if (m_insn_flags & HAS_DEST_P)
>        {
>         any_mem_p |= MEM_P (ops[opno]);
> -       all_mask_p &= GET_MODE_CLASS (GET_MODE (ops[opno])) == MODE_VECTOR_BOOL;
>         add_output_operand (ops[opno++], m_dest_mode);
> +       num_ops += 1;

Drop this

>        }
>
> -    if (m_fully_unmasked_p)
> +    /* Add mask operand.  */
> +    if (m_insn_flags & USE_ONE_TRUE_MASK_P)
> +      add_input_operand (gen_scalar_move_mask (m_mask_mode), m_mask_mode);
> +    else if (m_insn_flags & USE_ALL_TRUES_MASK_P)
>        add_all_one_mask_operand ();
> +    else if (m_insn_flags & HAS_MASK_P)
> +      {
> +       machine_mode mode = insn_data[(int) icode].operand[m_opno].mode;
> +       gcc_assert (mode != VOIDmode);
> +       add_input_operand (ops[opno++], mode);
> +       num_ops += 1;
> +      }

Drop this

> -    if (!m_use_real_merge_p)
> +    /* Add merge operand.  */
> +    if (m_insn_flags & USE_VUNDEF_MERGE_P)
>        add_vundef_operand ();
> +    else if (m_insn_flags & HAS_MERGE_P)
> +      {
> +       machine_mode mode = insn_data[(int) icode].operand[m_opno].mode;
> +       gcc_assert (mode != VOIDmode);
> +       add_input_operand (ops[opno++], mode);
> +       num_ops += 1;
> +      }
> +
> +    if (m_insn_flags & NULLARY_OP_P)
> +      num_ops += 0;
> +    else if (m_insn_flags & UNARY_OP_P)
> +      num_ops += 1;
> +    else if (m_insn_flags & BINARY_OP_P)
> +      num_ops += 2;
> +    else if (m_insn_flags & TERNARY_OP_P)
> +      num_ops += 3;

num_ops = rather than += here.

> +    else
> +      gcc_unreachable ();
>
> -    for (; opno < m_op_num; opno++)
> +    /* Add the remain operands.  */
> +    for (; opno < num_ops; opno++)

for (;num_ops;num_ops--, opno++)

>        {
>         any_mem_p |= MEM_P (ops[opno]);
> -       all_mask_p &= GET_MODE_CLASS (GET_MODE (ops[opno])) == MODE_VECTOR_BOOL;
>         machine_mode mode = insn_data[(int) icode].operand[m_opno].mode;
>         /* 'create_input_operand doesn't allow VOIDmode.
>            According to vector.md, we may have some patterns that do not have
> @@ -194,46 +251,51 @@ public:
>         add_input_operand (ops[opno], mode);
>        }
>
> -    if (m_needs_avl_p)
> +    /* Add vl operand.  */
> +    rtx len = m_vl_op;
> +    machine_mode mode = VECTOR_MODE_P (m_dest_mode) ? m_dest_mode : m_mask_mode;
> +    if (m_vlmax_p)
>        {
> -       rtx len = m_vl_op;
> -       machine_mode mode
> -         = VECTOR_MODE_P (m_dest_mode) ? m_dest_mode : m_mask_mode;
> -       if (m_vlmax_p)
> +       if (riscv_v_ext_vls_mode_p (mode))
> +         {
> +           /* VLS modes always set VSETVL by
> +              "vsetvl zero, rs1/imm".  */
> +           poly_uint64 nunits = GET_MODE_NUNITS (mode);
> +           len = gen_int_mode (nunits, Pmode);
> +           if (!satisfies_constraint_K (len))
> +             len = force_reg (Pmode, len);
> +           m_vlmax_p = false;
> +         }
> +       else if (const_vlmax_p (mode))
> +         {
> +           /* Optimize VLS-VLMAX code gen, we can use vsetivli instead of
> +              the vsetvli to obtain the value of vlmax.  */
> +           poly_uint64 nunits = GET_MODE_NUNITS (mode);
> +           len = gen_int_mode (nunits, Pmode);
> +           m_vlmax_p = false;
> +         }
> +       else if (can_create_pseudo_p ())
>           {
> -           if (riscv_v_ext_vls_mode_p (mode))
> -             {
> -               /* VLS modes always set VSETVL by
> -                  "vsetvl zero, rs1/imm".  */
> -               poly_uint64 nunits = GET_MODE_NUNITS (mode);
> -               len = gen_int_mode (nunits, Pmode);
> -               if (!satisfies_constraint_K (len))
> -                 len = force_reg (Pmode, len);
> -               m_vlmax_p = false; /* It has became NONVLMAX now.  */
> -             }
> -           else if (const_vlmax_p (mode))
> -             {
> -               /* Optimize VLS-VLMAX code gen, we can use vsetivli instead of
> -                  the vsetvli to obtain the value of vlmax.  */
> -               poly_uint64 nunits = GET_MODE_NUNITS (mode);
> -               len = gen_int_mode (nunits, Pmode);
> -               m_vlmax_p = false; /* It has became NONVLMAX now.  */
> -             }
> -           else if (can_create_pseudo_p ())
> -             {
> -               len = gen_reg_rtx (Pmode);
> -               emit_vlmax_vsetvl (mode, len);
> -             }
> +           len = gen_reg_rtx (Pmode);
> +           emit_vlmax_vsetvl (mode, len);
>           }
> -       add_input_operand (len, Pmode);
> +       else
> +         gcc_assert (len != NULL_RTX);

I don't see the gcc_assert here before, and seems like that should
move to another place

>        }
> +    else
> +      /* Must specify vl when not vlmax.  */
> +      gcc_assert (len != NULL_RTX);

Like here and drop the else since we need this assert no matter
m_vlmax_p true or false


diff --git a/gcc/config/riscv/riscv-v.cc b/gcc/config/riscv/riscv-v.cc
index 3e7caf48742..64e22177e81 100644
--- a/gcc/config/riscv/riscv-v.cc
+++ b/gcc/config/riscv/riscv-v.cc
@@ -279,12 +279,8 @@ public:
            len = gen_reg_rtx (Pmode);
            emit_vlmax_vsetvl (mode, len);
          }
-       else
-         gcc_assert (len != NULL_RTX);
       }
-    else
-      /* Must specify vl when not vlmax.  */
-      gcc_assert (len != NULL_RTX);
+    gcc_assert (len != NULL_RTX);
     add_input_operand (len, Pmode);

     /* Add tail and mask policy operands.  */


> @@ -1212,7 +834,7 @@ emit_vlmax_masked_gather_mu_insn (rtx target, rtx op, rtx sel, rtx mask)
>       p q r s t u v w  # v11 destination register
>            e d c b a  # v1 source vector
>       1 0 0 1 1 1 0 1  # v0 mask vector
> -
> +make

Ha, this must be a mistake, right? :P

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] RISC-V: Refactor and clean emit_{vlmax, nonvlmax}_xxx functions
  2023-08-31  7:51 ` [PATCH] RISC-V: Refactor and clean emit_{vlmax, nonvlmax}_xxx functions Kito Cheng
@ 2023-08-31  8:59   ` Lehua Ding
  0 siblings, 0 replies; 5+ messages in thread
From: Lehua Ding @ 2023-08-31  8:59 UTC (permalink / raw)
  To: Kito Cheng; +Cc: gcc-patches, rdapp.gcc, juzhe.zhong

Committed after addressing these comments.
Many thanks to Kito for taking the time to review such a large patch :)

On 2023/8/31 15:51, Kito Cheng wrote:
> Thanks for the cleanup, the new interface is really much simpler than before!
> 
> Only few minor comment, you can go ahead to commit that after address
> those comment.
> 
> (OK, I don't want to review whole patch again, it's really huge change :P
> 
>>
>> -  void set_rounding_mode (enum floating_point_rounding_mode mode)
>> +  void check_insn_flags ()
> 
> void check_insn_flags () const
> 
>>     void emit_insn (enum insn_code icode, rtx *ops)
>>     {
>>       int opno = 0;
>> +    int num_ops = 0;
>>       /* It's true if any operand is memory operand.  */
>>       bool any_mem_p = false;
>> -    /* It's true if all operands are mask operand.  */
>> -    bool all_mask_p = true;
>> -    if (m_has_dest_p)
>> +
>> +    /* Add dest operand.  */
>> +    if (m_insn_flags & HAS_DEST_P)
>>         {
>>          any_mem_p |= MEM_P (ops[opno]);
>> -       all_mask_p &= GET_MODE_CLASS (GET_MODE (ops[opno])) == MODE_VECTOR_BOOL;
>>          add_output_operand (ops[opno++], m_dest_mode);
>> +       num_ops += 1;
> 
> Drop this
> 
>>         }
>>
>> -    if (m_fully_unmasked_p)
>> +    /* Add mask operand.  */
>> +    if (m_insn_flags & USE_ONE_TRUE_MASK_P)
>> +      add_input_operand (gen_scalar_move_mask (m_mask_mode), m_mask_mode);
>> +    else if (m_insn_flags & USE_ALL_TRUES_MASK_P)
>>         add_all_one_mask_operand ();
>> +    else if (m_insn_flags & HAS_MASK_P)
>> +      {
>> +       machine_mode mode = insn_data[(int) icode].operand[m_opno].mode;
>> +       gcc_assert (mode != VOIDmode);
>> +       add_input_operand (ops[opno++], mode);
>> +       num_ops += 1;
>> +      }
> 
> Drop this
> 
>> -    if (!m_use_real_merge_p)
>> +    /* Add merge operand.  */
>> +    if (m_insn_flags & USE_VUNDEF_MERGE_P)
>>         add_vundef_operand ();
>> +    else if (m_insn_flags & HAS_MERGE_P)
>> +      {
>> +       machine_mode mode = insn_data[(int) icode].operand[m_opno].mode;
>> +       gcc_assert (mode != VOIDmode);
>> +       add_input_operand (ops[opno++], mode);
>> +       num_ops += 1;
>> +      }
>> +
>> +    if (m_insn_flags & NULLARY_OP_P)
>> +      num_ops += 0;
>> +    else if (m_insn_flags & UNARY_OP_P)
>> +      num_ops += 1;
>> +    else if (m_insn_flags & BINARY_OP_P)
>> +      num_ops += 2;
>> +    else if (m_insn_flags & TERNARY_OP_P)
>> +      num_ops += 3;
> 
> num_ops = rather than += here.
> 
>> +    else
>> +      gcc_unreachable ();
>>
>> -    for (; opno < m_op_num; opno++)
>> +    /* Add the remain operands.  */
>> +    for (; opno < num_ops; opno++)
> 
> for (;num_ops;num_ops--, opno++)
> 
>>         {
>>          any_mem_p |= MEM_P (ops[opno]);
>> -       all_mask_p &= GET_MODE_CLASS (GET_MODE (ops[opno])) == MODE_VECTOR_BOOL;
>>          machine_mode mode = insn_data[(int) icode].operand[m_opno].mode;
>>          /* 'create_input_operand doesn't allow VOIDmode.
>>             According to vector.md, we may have some patterns that do not have
>> @@ -194,46 +251,51 @@ public:
>>          add_input_operand (ops[opno], mode);
>>         }
>>
>> -    if (m_needs_avl_p)
>> +    /* Add vl operand.  */
>> +    rtx len = m_vl_op;
>> +    machine_mode mode = VECTOR_MODE_P (m_dest_mode) ? m_dest_mode : m_mask_mode;
>> +    if (m_vlmax_p)
>>         {
>> -       rtx len = m_vl_op;
>> -       machine_mode mode
>> -         = VECTOR_MODE_P (m_dest_mode) ? m_dest_mode : m_mask_mode;
>> -       if (m_vlmax_p)
>> +       if (riscv_v_ext_vls_mode_p (mode))
>> +         {
>> +           /* VLS modes always set VSETVL by
>> +              "vsetvl zero, rs1/imm".  */
>> +           poly_uint64 nunits = GET_MODE_NUNITS (mode);
>> +           len = gen_int_mode (nunits, Pmode);
>> +           if (!satisfies_constraint_K (len))
>> +             len = force_reg (Pmode, len);
>> +           m_vlmax_p = false;
>> +         }
>> +       else if (const_vlmax_p (mode))
>> +         {
>> +           /* Optimize VLS-VLMAX code gen, we can use vsetivli instead of
>> +              the vsetvli to obtain the value of vlmax.  */
>> +           poly_uint64 nunits = GET_MODE_NUNITS (mode);
>> +           len = gen_int_mode (nunits, Pmode);
>> +           m_vlmax_p = false;
>> +         }
>> +       else if (can_create_pseudo_p ())
>>            {
>> -           if (riscv_v_ext_vls_mode_p (mode))
>> -             {
>> -               /* VLS modes always set VSETVL by
>> -                  "vsetvl zero, rs1/imm".  */
>> -               poly_uint64 nunits = GET_MODE_NUNITS (mode);
>> -               len = gen_int_mode (nunits, Pmode);
>> -               if (!satisfies_constraint_K (len))
>> -                 len = force_reg (Pmode, len);
>> -               m_vlmax_p = false; /* It has became NONVLMAX now.  */
>> -             }
>> -           else if (const_vlmax_p (mode))
>> -             {
>> -               /* Optimize VLS-VLMAX code gen, we can use vsetivli instead of
>> -                  the vsetvli to obtain the value of vlmax.  */
>> -               poly_uint64 nunits = GET_MODE_NUNITS (mode);
>> -               len = gen_int_mode (nunits, Pmode);
>> -               m_vlmax_p = false; /* It has became NONVLMAX now.  */
>> -             }
>> -           else if (can_create_pseudo_p ())
>> -             {
>> -               len = gen_reg_rtx (Pmode);
>> -               emit_vlmax_vsetvl (mode, len);
>> -             }
>> +           len = gen_reg_rtx (Pmode);
>> +           emit_vlmax_vsetvl (mode, len);
>>            }
>> -       add_input_operand (len, Pmode);
>> +       else
>> +         gcc_assert (len != NULL_RTX);
> 
> I don't see the gcc_assert here before, and seems like that should
> move to another place
> 
>>         }
>> +    else
>> +      /* Must specify vl when not vlmax.  */
>> +      gcc_assert (len != NULL_RTX);
> 
> Like here and drop the else since we need this assert no matter
> m_vlmax_p true or false
> 
> 
> diff --git a/gcc/config/riscv/riscv-v.cc b/gcc/config/riscv/riscv-v.cc
> index 3e7caf48742..64e22177e81 100644
> --- a/gcc/config/riscv/riscv-v.cc
> +++ b/gcc/config/riscv/riscv-v.cc
> @@ -279,12 +279,8 @@ public:
>              len = gen_reg_rtx (Pmode);
>              emit_vlmax_vsetvl (mode, len);
>            }
> -       else
> -         gcc_assert (len != NULL_RTX);
>         }
> -    else
> -      /* Must specify vl when not vlmax.  */
> -      gcc_assert (len != NULL_RTX);
> +    gcc_assert (len != NULL_RTX);
>       add_input_operand (len, Pmode);
> 
>       /* Add tail and mask policy operands.  */
> 
> 
>> @@ -1212,7 +834,7 @@ emit_vlmax_masked_gather_mu_insn (rtx target, rtx op, rtx sel, rtx mask)
>>        p q r s t u v w  # v11 destination register
>>             e d c b a  # v1 source vector
>>        1 0 0 1 1 1 0 1  # v0 mask vector
>> -
>> +make
> 
> Ha, this must be a mistake, right? :P
> 

-- 
Best,
Lehua


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] RISC-V: Refactor and clean emit_{vlmax,nonvlmax}_xxx functions
  2023-08-30 11:53 [PATCH] RISC-V: Refactor and clean emit_{vlmax,nonvlmax}_xxx functions Lehua Ding
  2023-08-31  7:51 ` [PATCH] RISC-V: Refactor and clean emit_{vlmax, nonvlmax}_xxx functions Kito Cheng
@ 2023-08-31  9:16 ` Robin Dapp
  2023-08-31  9:59   ` Lehua Ding
  1 sibling, 1 reply; 5+ messages in thread
From: Robin Dapp @ 2023-08-31  9:16 UTC (permalink / raw)
  To: Lehua Ding, gcc-patches
  Cc: rdapp.gcc, juzhe.zhong, kito.cheng, palmer, jeffreyalaw

Hi Lehua,

thanks, this definitely goes into the direction of what I had in mind and
simplifies a lot of the reduntant emit_... so it's good to have it.

I was too slow for a detailed response :)  So just some high-level comments.

One thing I noticed is the overloading of "MASK_OP",  we use it as
"operation on masks" i.e. an insn as well as "mask policy".  IMHO we could
get rid of UNARY_MASK_OP and BINARY_MASK_OP and just decide whether to
add a mask policy depending on if all operands are masks (the same way we
did before).

Related, and seeing that the MASK in UNARY_MASK_OP is somewhat redundant,
I feel we still mix concerns a bit.  For example it is not obvious, from
the name at least, why a WIDEN_TERNARY_OP does not have a merge operand
and the decision making seems very "enum centered" now :D

In general we use the NULLARY, UNARY, BINARY, TERNARY prefixes just
to determine the number of sources which doesn't seem really necessary
because a user of e.g. NEG will already know that there only is one
source - he already specified it and currently needs to, redundantly,
say UNARY again.
 
If we split off the destination and sources from mask, merge and the rest
we could ditch them altogether.

What about
 emit_(non)vlmax_insn (icode, *operands (just dest and sources),
		       mask, merge, tail/mask policy, frm)

with mask defaulting to NULL and merge defaulting to VUNDEF?  So ideally,
and in the easy case, the call would just degenerate to
 emit_..._insn (icode, operands).
 
I realize this will cause some complications on the "other side" but with
the enum in place it should still be doable?

No need to address this right away though, just sharing some ideas again.

Regards
 Robin


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] RISC-V: Refactor and clean emit_{vlmax,nonvlmax}_xxx functions
  2023-08-31  9:16 ` [PATCH] RISC-V: Refactor and clean emit_{vlmax,nonvlmax}_xxx functions Robin Dapp
@ 2023-08-31  9:59   ` Lehua Ding
  0 siblings, 0 replies; 5+ messages in thread
From: Lehua Ding @ 2023-08-31  9:59 UTC (permalink / raw)
  To: Robin Dapp, gcc-patches; +Cc: juzhe.zhong, kito.cheng, palmer, jeffreyalaw

Hi Robin,

Thanks for these comments.

On 2023/8/31 17:16, Robin Dapp wrote:
> Hi Lehua,
> 
> thanks, this definitely goes into the direction of what I had in mind and
> simplifies a lot of the reduntant emit_... so it's good to have it.
> 
> I was too slow for a detailed response :)  So just some high-level comments.
> 
> One thing I noticed is the overloading of "MASK_OP",  we use it as
> "operation on masks" i.e. an insn as well as "mask policy".  IMHO we could
> get rid of UNARY_MASK_OP and BINARY_MASK_OP and just decide whether to
> add a mask policy depending on if all operands are masks (the same way we
> did before).

I think I should change the marco name here form __MASK_OP to 
__NORMAL_OP_MASK. MASK_OP means this is a insn operate on mask operands. 
I lift up it here because I want to simplify the emit_insn method.

> Related, and seeing that the MASK in UNARY_MASK_OP is somewhat redundant,
> I feel we still mix concerns a bit.  For example it is not obvious, from
> the name at least, why a WIDEN_TERNARY_OP does not have a merge operand
> and the decision making seems very "enum centered" now :D

As the above says, UNARY_MASK_OP means it is an operator of mask 
operands and itself don't have mask operand. If the operation depends on 
a mask, then the name should be UNARY_MASK_OP_TAMA.

For the WIDEN_TERNARY_OP, This is because of the design problem of 
vwmacc pattern (as bellow), maybe it can be unified with wmacc and then 
WIDEN_TERNARY_OP is not needed.

(define_insn "@pred_widen_mul_plus<su><mode>"
   [(set (match_operand:VWEXTI 0 "register_operand")
	(if_then_else:VWEXTI
	  (unspec:<VM>
	    [(match_operand:<VM> 1 "vector_mask_operand")
	     (match_operand 5 "vector_length_operand")
	     (match_operand 6 "const_int_operand")
	     (match_operand 7 "const_int_operand")
	     (match_operand 8 "const_int_operand")
	     (reg:SI VL_REGNUM)
	     (reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE)
	  (plus:VWEXTI
	    (mult:VWEXTI
	      (any_extend:VWEXTI
	        (match_operand:<V_DOUBLE_TRUNC> 3 "register_operand"))
	      (any_extend:VWEXTI
	        (match_operand:<V_DOUBLE_TRUNC> 4 "register_operand")))
	    (match_operand:VWEXTI 2 "register_operand"))
	  (match_dup 2)))]
   "TARGET_VECTOR"
   "vwmacc<u>.vv\t%0,%3,%4%p1"
   [(set_attr "type" "viwmuladd")
    (set_attr "mode" "<V_DOUBLE_TRUNC>")])


> In general we use the NULLARY, UNARY, BINARY, TERNARY prefixes just
> to determine the number of sources which doesn't seem really necessary
> because a user of e.g. NEG will already know that there only is one
> source - he already specified it and currently needs to, redundantly,
> say UNARY again.

 From the caller's point of view, he does know how many sources, but the 
emit_insn method needs to use this flag(NULLARY_OP_P, UNARY_OP_P) to 
determine how many sources to add.

Oh, you mean we can get oerands number from insn_data[icode].n_operands? 
In this case, we don't really need to distinguish between NULLARY, UNARY 
and ect.

> If we split off the destination and sources from mask, merge and the rest
> we could ditch them altogether.
> 
> What about
>   emit_(non)vlmax_insn (icode, *operands (just dest and sources),
> 		       mask, merge, tail/mask policy, frm)
> 
> with mask defaulting to NULL and merge defaulting to VUNDEF?  So ideally,
> and in the easy case, the call would just degenerate to
>   emit_..._insn (icode, operands).
>   
> I realize this will cause some complications on the "other side" but with
> the enum in place it should still be doable?

That is to say, when the user needs to emit a COND_NEG, do you need to 
call it like this?:
   emit_vlmax_insn (pred_neg, ops, mask, vundef(), ta, ma)

Is there too much focus on operands that don't need to be passed in? 
Like merge, tail and mask policy operands.

Maybe I don't understand enough here, can you explain it in some more 
detail?

-- 
Best,
Lehua


^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2023-08-31 10:00 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-08-30 11:53 [PATCH] RISC-V: Refactor and clean emit_{vlmax,nonvlmax}_xxx functions Lehua Ding
2023-08-31  7:51 ` [PATCH] RISC-V: Refactor and clean emit_{vlmax, nonvlmax}_xxx functions Kito Cheng
2023-08-31  8:59   ` Lehua Ding
2023-08-31  9:16 ` [PATCH] RISC-V: Refactor and clean emit_{vlmax,nonvlmax}_xxx functions Robin Dapp
2023-08-31  9:59   ` Lehua Ding

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