diff --git a/gcc/config/riscv/riscv-vsetvl.cc b/gcc/config/riscv/riscv-vsetvl.cc
index d91b0272d9f..78816cbee15 100644
--- a/gcc/config/riscv/riscv-vsetvl.cc
+++ b/gcc/config/riscv/riscv-vsetvl.cc
@@ -680,6 +680,30 @@ get_bb_index (unsigned expr_id, unsigned num_bb)
   return expr_id % num_bb;
 }

+/* Return true if the SET result is not used by any instructions.  */
+static bool
+has_no_uses (basic_block cfg_bb, rtx_insn *rinsn, int regno)
+{
+  if (bitmap_bit_p (df_get_live_out (cfg_bb), regno))
+    return false;
+
+  rtx_insn *iter;
+  for (iter = NEXT_INSN (rinsn); iter && iter != NEXT_INSN (BB_END (cfg_bb));
+       iter = NEXT_INSN (iter))
+    if (df_find_use (iter, regno_reg_rtx[regno]))
+      return false;
+
+  return true;
+}
+
+/* Change insn and Assert the change always happens.  */
+static void
+validate_change_or_fail (rtx object, rtx *loc, rtx new_rtx, bool in_group)
+{
+  bool change_p = validate_change (object, loc, new_rtx, in_group);
+  gcc_assert (change_p);
+}
+
 /* This flags indicates the minimum demand of the vl and vtype values by the
    RVV instruction. For example, DEMAND_RATIO_P indicates that this RVV
    instruction only needs the SEW/LMUL ratio to remain the same, and does not
@@ -1126,6 +1150,28 @@ public:
       }
   }

+  /* Returns the corresponding vsetvl rtx pat.  */
+  rtx get_vsetvl_pat (bool ignore_vl = false) const
+  {
+    rtx avl = get_avl ();
+    /* if optimization == 0 and the instruction is vmv.x.s/vfmv.f.s,
+       set the value of avl to (const_int 0) so that VSETVL PASS will
+       insert vsetvl correctly.*/
+    if (!get_avl ())
+      avl = GEN_INT (0);
+    rtx sew = gen_int_mode (get_sew (), Pmode);
+    rtx vlmul = gen_int_mode (get_vlmul (), Pmode);
+    rtx ta = gen_int_mode (get_ta (), Pmode);
+    rtx ma = gen_int_mode (get_ma (), Pmode);
+
+    if (change_vtype_only_p ())
+      return gen_vsetvl_vtype_change_only (sew, vlmul, ta, ma);
+    else if (has_reg_vl () && !ignore_vl)
+      return gen_vsetvl (Pmode, get_vl (), avl, sew, vlmul, ta, ma);
+    else
+      return gen_vsetvl_discard_result (Pmode, avl, sew, vlmul, ta, ma);
+  }
+
   bool operator== (const vsetvl_info &other) const
   {
     gcc_assert (!uninit_p () && !other.uninit_p ()
@@ -1938,199 +1984,6 @@ public:
   }
 };

-/* Emit vsetvl instruction.  */
-static rtx
-gen_vsetvl_pat (enum vsetvl_type insn_type, const vsetvl_info &info, rtx vl)
-{
-  rtx avl = info.get_avl ();
-  /* if optimization == 0 and the instruction is vmv.x.s/vfmv.f.s,
-     set the value of avl to (const_int 0) so that VSETVL PASS will
-     insert vsetvl correctly.*/
-  if (!info.get_avl ())
-    avl = GEN_INT (0);
-  rtx sew = gen_int_mode (info.get_sew (), Pmode);
-  rtx vlmul = gen_int_mode (info.get_vlmul (), Pmode);
-  rtx ta = gen_int_mode (info.get_ta (), Pmode);
-  rtx ma = gen_int_mode (info.get_ma (), Pmode);
-
-  if (insn_type == VSETVL_NORMAL)
-    {
-      gcc_assert (vl != NULL_RTX);
-      return gen_vsetvl (Pmode, vl, avl, sew, vlmul, ta, ma);
-    }
-  else if (insn_type == VSETVL_VTYPE_CHANGE_ONLY)
-    return gen_vsetvl_vtype_change_only (sew, vlmul, ta, ma);
-  else
-    return gen_vsetvl_discard_result (Pmode, avl, sew, vlmul, ta, ma);
-}
-
-static rtx
-gen_vsetvl_pat (rtx_insn *rinsn, const vsetvl_info &info, rtx vl = NULL_RTX)
-{
-  rtx new_pat;
-  vsetvl_info new_info = info;
-  /* For vmv.x.s, use 0 for avl.  */
-  if (!info.get_avl ())
-    {
-      new_info.set_avl (const0_rtx);
-      new_info.set_avl_def (nullptr);
-    }
-
-  if (vl)
-    new_pat = gen_vsetvl_pat (VSETVL_NORMAL, new_info, vl);
-  else
-    {
-      if (vsetvl_insn_p (rinsn) && !info.change_vtype_only_p ())
-	new_pat = gen_vsetvl_pat (VSETVL_NORMAL, new_info, get_vl (rinsn));
-      else if (info.change_vtype_only_p ()
-	       || INSN_CODE (rinsn) == CODE_FOR_vsetvl_vtype_change_only)
-	new_pat = gen_vsetvl_pat (VSETVL_VTYPE_CHANGE_ONLY, new_info, NULL_RTX);
-      else
-	new_pat = gen_vsetvl_pat (VSETVL_DISCARD_RESULT, new_info, NULL_RTX);
-    }
-  return new_pat;
-}
-
-static void
-emit_vsetvl_insn (enum vsetvl_type insn_type, enum emit_type emit_type,
-		  const vsetvl_info &info, rtx vl, rtx_insn *rinsn)
-{
-  rtx pat = gen_vsetvl_pat (insn_type, info, vl);
-
-  if (emit_type == EMIT_DIRECT)
-    {
-      emit_insn (pat);
-      if (dump_file)
-	{
-	  fprintf (dump_file, "  Insert vsetvl insn %d:\n",
-		   INSN_UID (get_last_insn ()));
-	  print_rtl_single (dump_file, get_last_insn ());
-	}
-    }
-  else if (emit_type == EMIT_BEFORE)
-    {
-      emit_insn_before (pat, rinsn);
-      if (dump_file)
-	{
-	  fprintf (dump_file, "  Insert vsetvl insn before insn %d:\n",
-		   INSN_UID (rinsn));
-	  print_rtl_single (dump_file, PREV_INSN (rinsn));
-	}
-    }
-  else
-    {
-      emit_insn_after (pat, rinsn);
-      if (dump_file)
-	{
-	  fprintf (dump_file, "  Insert vsetvl insn after insn %d:\n",
-		   INSN_UID (rinsn));
-	  print_rtl_single (dump_file, NEXT_INSN (rinsn));
-	}
-    }
-}
-
-static void
-eliminate_insn (rtx_insn *rinsn)
-{
-  if (dump_file)
-    {
-      fprintf (dump_file, "  Eliminate insn %d:\n", INSN_UID (rinsn));
-      print_rtl_single (dump_file, rinsn);
-    }
-  if (in_sequence_p ())
-    remove_insn (rinsn);
-  else
-    delete_insn (rinsn);
-}
-
-/* Change insn and Assert the change always happens.  */
-static void
-validate_change_or_fail (rtx object, rtx *loc, rtx new_rtx, bool in_group)
-{
-  bool change_p = validate_change (object, loc, new_rtx, in_group);
-  gcc_assert (change_p);
-}
-
-static void
-change_insn (rtx_insn *rinsn, rtx new_pat)
-{
-  /* We don't apply change on RTL_SSA here since it's possible a
-     new INSN we add in the PASS before which doesn't have RTL_SSA
-     info yet.*/
-  if (dump_file)
-    {
-      fprintf (dump_file, "  Change insn %d from:\n", INSN_UID (rinsn));
-      print_rtl_single (dump_file, rinsn);
-    }
-
-  validate_change_or_fail (rinsn, &PATTERN (rinsn), new_pat, false);
-
-  if (dump_file)
-    {
-      fprintf (dump_file, "\n  to:\n");
-      print_rtl_single (dump_file, rinsn);
-    }
-}
-
-static bool
-change_insn (function_info *ssa, insn_change change, insn_info *insn,
-	     rtx new_pat)
-{
-  rtx_insn *rinsn = insn->rtl ();
-  auto attempt = ssa->new_change_attempt ();
-  if (!restrict_movement (change))
-    return false;
-
-  if (dump_file)
-    {
-      fprintf (dump_file, "  Change insn %d from:\n", INSN_UID (rinsn));
-      print_rtl_single (dump_file, rinsn);
-    }
-
-  insn_change_watermark watermark;
-  validate_change_or_fail (rinsn, &PATTERN (rinsn), new_pat, true);
-
-  /* These routines report failures themselves.  */
-  if (!recog (attempt, change) || !change_is_worthwhile (change, false))
-    return false;
-
-  remove_reg_equal_equiv_notes (rinsn);
-  confirm_change_group ();
-  ssa->change_insn (change);
-
-  if (dump_file)
-    {
-      fprintf (dump_file, "\n  to:\n");
-      print_rtl_single (dump_file, rinsn);
-    }
-
-  return true;
-}
-
-static void
-change_vsetvl_insn (const insn_info *insn, const vsetvl_info &info)
-{
-  rtx_insn *rinsn = insn->rtl ();
-  rtx new_pat = gen_vsetvl_pat (rinsn, info);
-  change_insn (rinsn, new_pat);
-}
-
-/* Return true if the SET result is not used by any instructions.  */
-static bool
-has_no_uses (basic_block cfg_bb, rtx_insn *rinsn, int regno)
-{
-  if (bitmap_bit_p (df_get_live_out (cfg_bb), regno))
-    return false;
-
-  rtx_insn *iter;
-  for (iter = NEXT_INSN (rinsn); iter && iter != NEXT_INSN (BB_END (cfg_bb));
-       iter = NEXT_INSN (iter))
-    if (df_find_use (iter, regno_reg_rtx[regno]))
-      return false;
-
-  return true;
-}
-
 class pre_vsetvl
 {
 private:
@@ -2257,18 +2110,75 @@ private:
       }
   }

-  void insert_vsetvl (enum emit_type emit_type, rtx_insn *rinsn,
-		      const vsetvl_info &info)
+  void insert_vsetvl_insn (enum emit_type emit_type, const vsetvl_info &info)
   {
-    if (info.change_vtype_only_p ())
-      emit_vsetvl_insn (VSETVL_VTYPE_CHANGE_ONLY, emit_type, info, NULL_RTX,
-			rinsn);
+    rtx pat = info.get_vsetvl_pat ();
+    rtx_insn *rinsn = info.get_insn ()->rtl ();

-    else if (info.has_reg_vl ())
-      emit_vsetvl_insn (VSETVL_NORMAL, emit_type, info, info.get_vl (), rinsn);
+    if (emit_type == EMIT_DIRECT)
+      {
+	emit_insn (pat);
+	if (dump_file)
+	  {
+	    fprintf (dump_file, "  Insert vsetvl insn %d:\n",
+		     INSN_UID (get_last_insn ()));
+	    print_rtl_single (dump_file, get_last_insn ());
+	  }
+      }
+    else if (emit_type == EMIT_BEFORE)
+      {
+	emit_insn_before (pat, rinsn);
+	if (dump_file)
+	  {
+	    fprintf (dump_file, "  Insert vsetvl insn before insn %d:\n",
+		     INSN_UID (rinsn));
+	    print_rtl_single (dump_file, PREV_INSN (rinsn));
+	  }
+      }
     else
-      emit_vsetvl_insn (VSETVL_DISCARD_RESULT, emit_type, info, NULL_RTX,
-			rinsn);
+      {
+	emit_insn_after (pat, rinsn);
+	if (dump_file)
+	  {
+	    fprintf (dump_file, "  Insert vsetvl insn after insn %d:\n",
+		     INSN_UID (rinsn));
+	    print_rtl_single (dump_file, NEXT_INSN (rinsn));
+	  }
+      }
+  }
+
+  void change_vsetvl_insn (const vsetvl_info &info)
+  {
+    rtx_insn *rinsn = info.get_insn ()->rtl ();
+    rtx new_pat = info.get_vsetvl_pat ();
+
+    if (dump_file)
+      {
+	fprintf (dump_file, "  Change insn %d from:\n", INSN_UID (rinsn));
+	print_rtl_single (dump_file, rinsn);
+      }
+
+    validate_change_or_fail (rinsn, &PATTERN (rinsn), new_pat, false);
+
+    if (dump_file)
+      {
+	fprintf (dump_file, "\n  to:\n");
+	print_rtl_single (dump_file, rinsn);
+      }
+  }
+
+  void remove_vsetvl_insn (const vsetvl_info &info)
+  {
+    rtx_insn *rinsn = info.get_insn ()->rtl ();
+    if (dump_file)
+      {
+	fprintf (dump_file, "  Eliminate insn %d:\n", INSN_UID (rinsn));
+	print_rtl_single (dump_file, rinsn);
+      }
+    if (in_sequence_p ())
+      remove_insn (rinsn);
+    else
+      delete_insn (rinsn);
   }

   bool earliest_fusion_worthwhile_p (const basic_block cfg_bb) const
@@ -3297,7 +3207,7 @@ pre_vsetvl::emit_vsetvl ()
 	  if (curr_info.ignore_p ())
 	    {
 	      if (vsetvl_insn_p (insn->rtl ()))
-		eliminate_insn (insn->rtl ());
+		remove_vsetvl_insn (curr_info);
 	      continue;
 	    }
 	  else if (curr_info.valid_p ())
@@ -3314,7 +3224,7 @@ pre_vsetvl::emit_vsetvl ()
 			  fprintf (dump_file, "  to: ");
 			  curr_info.dump (dump_file, "    ");
 			}
-		      change_vsetvl_insn (insn, curr_info);
+		      change_vsetvl_insn (curr_info);
 		    }
 		}
 	      else
@@ -3326,7 +3236,7 @@ pre_vsetvl::emit_vsetvl ()
 			       insn->uid ());
 		      curr_info.dump (dump_file, "    ");
 		    }
-		  insert_vsetvl (EMIT_BEFORE, insn->rtl (), curr_info);
+		  insert_vsetvl_insn (EMIT_BEFORE, curr_info);
 		}
 	    }
 	}
@@ -3335,7 +3245,7 @@ pre_vsetvl::emit_vsetvl ()
   for (const vsetvl_info &item : delete_list)
     {
       gcc_assert (vsetvl_insn_p (item.get_insn ()->rtl ()));
-      eliminate_insn (item.get_insn ()->rtl ());
+      remove_vsetvl_insn (item);
     }

   /* Insert vsetvl as LCM suggest. */
@@ -3365,8 +3275,7 @@ pre_vsetvl::emit_vsetvl ()
       rtl_profile_for_edge (eg);
       start_sequence ();

-      insn_info *insn = info.get_insn ();
-      insert_vsetvl (EMIT_DIRECT, insn->rtl (), info);
+      insert_vsetvl_insn (EMIT_DIRECT, info);
       rtx_insn *rinsn = get_insns ();
       end_sequence ();
       default_rtl_profile ();
@@ -3385,7 +3294,6 @@ pre_vsetvl::emit_vsetvl ()
 	continue;

       const vsetvl_info &footer_info = block_info.get_footer_info ();
-      insn_info *insn = footer_info.get_insn ();

       if (footer_info.ignore_p ())
 	continue;
@@ -3404,7 +3312,7 @@ pre_vsetvl::emit_vsetvl ()
 	      footer_info.dump (dump_file, "    ");
 	    }
 	  start_sequence ();
-	  insert_vsetvl (EMIT_DIRECT, insn->rtl (), footer_info);
+	  insert_vsetvl_insn (EMIT_DIRECT, footer_info);
 	  rtx_insn *rinsn = get_insns ();
 	  end_sequence ();
 	  default_rtl_profile ();
@@ -3427,71 +3335,66 @@ pre_vsetvl::cleaup ()
 void
 pre_vsetvl::remove_avl_operand ()
 {
-  for (const bb_info *bb : crtl->ssa->bbs ())
-    for (insn_info *insn : bb->real_nondebug_insns ())
-      {
-	rtx_insn *rinsn = insn->rtl ();
-	/* Erase the AVL operand from the instruction.  */
-	if (!has_vl_op (rinsn) || !REG_P (get_vl (rinsn)))
-	  continue;
-	rtx avl = get_vl (rinsn);
-	if (count_regno_occurrences (rinsn, REGNO (avl)) == 1)
-	  {
-	    /* Get the list of uses for the new instruction.  */
-	    auto attempt = crtl->ssa->new_change_attempt ();
-	    insn_change change (insn);
-	    /* Remove the use of the substituted value.  */
-	    access_array_builder uses_builder (attempt);
-	    uses_builder.reserve (insn->num_uses () - 1);
-	    for (use_info *use : insn->uses ())
-	      if (use != find_access (insn->uses (), REGNO (avl)))
-		uses_builder.quick_push (use);
-	    use_array new_uses = use_array (uses_builder.finish ());
-	    change.new_uses = new_uses;
-	    change.move_range = insn->ebb ()->insn_range ();
-	    rtx pat;
-	    if (fault_first_load_p (rinsn))
-	      pat = simplify_replace_rtx (PATTERN (rinsn), avl, const0_rtx);
-	    else
-	      {
-		rtx set = single_set (rinsn);
-		rtx src = simplify_replace_rtx (SET_SRC (set), avl, const0_rtx);
-		pat = gen_rtx_SET (SET_DEST (set), src);
-	      }
-	    bool ok = change_insn (crtl->ssa, change, insn, pat);
-	    gcc_assert (ok);
-	  }
-      }
+  basic_block cfg_bb;
+  rtx_insn *rinsn;
+  FOR_ALL_BB_FN (cfg_bb, cfun)
+    FOR_BB_INSNS (cfg_bb, rinsn)
+      if (NONDEBUG_INSN_P (rinsn) && has_vl_op (rinsn)
+	  && REG_P (get_vl (rinsn)))
+	{
+	  rtx avl = get_vl (rinsn);
+	  if (count_regno_occurrences (rinsn, REGNO (avl)) == 1)
+	    {
+	      rtx new_pat;
+	      if (fault_first_load_p (rinsn))
+		new_pat
+		  = simplify_replace_rtx (PATTERN (rinsn), avl, const0_rtx);
+	      else
+		{
+		  rtx set = single_set (rinsn);
+		  rtx src
+		    = simplify_replace_rtx (SET_SRC (set), avl, const0_rtx);
+		  new_pat = gen_rtx_SET (SET_DEST (set), src);
+		}
+	      if (dump_file)
+		{
+		  fprintf (dump_file, "  Cleanup insn %u's avl operand:\n",
+			   INSN_UID (rinsn));
+		  print_rtl_single (dump_file, rinsn);
+		}
+	      validate_change_or_fail (rinsn, &PATTERN (rinsn), new_pat, false);
+	    }
+	}
 }

 void
 pre_vsetvl::remove_unused_dest_operand ()
 {
   df_analyze ();
-  hash_set<rtx_insn *> to_delete;
   basic_block cfg_bb;
   rtx_insn *rinsn;
   FOR_ALL_BB_FN (cfg_bb, cfun)
-    {
-      FOR_BB_INSNS (cfg_bb, rinsn)
+    FOR_BB_INSNS (cfg_bb, rinsn)
+      if (NONDEBUG_INSN_P (rinsn) && vsetvl_insn_p (rinsn))
 	{
-	  if (NONDEBUG_INSN_P (rinsn) && vsetvl_insn_p (rinsn))
-	    {
-	      rtx vl = get_vl (rinsn);
-	      vsetvl_info info = vsetvl_info (rinsn);
-	      if (has_no_uses (cfg_bb, rinsn, REGNO (vl)))
-		{
-		  if (!info.has_vlmax_avl ())
-		    {
-		      rtx new_pat = gen_vsetvl_pat (VSETVL_DISCARD_RESULT, info,
-						    NULL_RTX);
-		      validate_change_or_fail (rinsn, &PATTERN (rinsn), new_pat,
-					       false);
-		    }
-		}
-	    }
+	  rtx vl = get_vl (rinsn);
+	  vsetvl_info info = vsetvl_info (rinsn);
+	  if (has_no_uses (cfg_bb, rinsn, REGNO (vl)))
+	    if (!info.has_vlmax_avl ())
+	      {
+		rtx new_pat = info.get_vsetvl_pat (true);
+		if (dump_file)
+		  {
+		    fprintf (dump_file,
+			     "  Remove vsetvl insn %u's dest(vl) operand since "
+			     "it unused:\n",
+			     INSN_UID (rinsn));
+		    print_rtl_single (dump_file, rinsn);
+		  }
+		validate_change_or_fail (rinsn, &PATTERN (rinsn), new_pat,
+					 false);
+	      }
 	}
-    }
 }

 const pass_data pass_data_vsetvl = {
@@ -3536,9 +3439,15 @@ pass_vsetvl::simple_vsetvl ()
 	    continue;
 	  if (has_vtype_op (rinsn))
 	    {
-	      const auto info = vsetvl_info (rinsn);
-	      emit_vsetvl_insn (VSETVL_DISCARD_RESULT, EMIT_BEFORE, info,
-				NULL_RTX, rinsn);
+	      const auto &info = vsetvl_info (rinsn);
+	      rtx pat = info.get_vsetvl_pat ();
+	      emit_insn_before (pat, rinsn);
+	      if (dump_file)
+		{
+		  fprintf (dump_file, "  Insert vsetvl insn before insn %d:\n",
+			   INSN_UID (rinsn));
+		  print_rtl_single (dump_file, PREV_INSN (rinsn));
+		}
 	    }
 	}
     }
