RISC-V: RVV: add toggle to control vsetvl pass behavior

Message ID 20231222194513.294048-1-vineetg@rivosinc.com
State Unresolved
Headers
Series RISC-V: RVV: add toggle to control vsetvl pass behavior |

Checks

Context Check Description
snail/gcc-patch-check warning Git am fail log

Commit Message

Vineet Gupta Dec. 22, 2023, 7:45 p.m. UTC
  RVV requires VSET?VL? instructions to dynamically configure VLEN at
runtime. There's a custom pass to do that which has a simple mode
which generates a VSETVL for each V insn and a lazy/optimal mode which
uses LCM dataflow to move VSETVL around, identify/delete the redundant
ones.

Currently simple mode is default for !optimize invocations while lazy
mode being the default.

This patch allows simple mode to be forced via a toggle independent of
the optimization level. A lot of gcc developers are currently doing this
in some form in their local setups, as in the initial phase of autovec
development issues are expected. It makes sense to provide this facility
upstream. It could potentially also be used by distro builder for any
quick workarounds in autovec bugs of future.

gcc/ChangeLog:
	* config/riscv/riscv.opt: New -param=vsetvl-strategy.
	* config/riscv/riscv-opts.h: New enum vsetvl_strategy_enum.
	* config/riscv/riscv-vsetvl.cc
	(pre_vsetvl::pre_global_vsetvl_info): Use vsetvl_strategy.
	(pass_vsetvl::execute): Use vsetvl_strategy.

Signed-off-by: Vineet Gupta <vineetg@rivosinc.com>
---
 gcc/config/riscv/riscv-opts.h    | 11 +++++++
 gcc/config/riscv/riscv-vsetvl.cc | 49 +++++++++++++++++---------------
 gcc/config/riscv/riscv.opt       | 17 +++++++++++
 3 files changed, 54 insertions(+), 23 deletions(-)
  

Comments

Jeff Law Jan. 2, 2024, 5:21 p.m. UTC | #1
On 12/22/23 12:45, Vineet Gupta wrote:
> RVV requires VSET?VL? instructions to dynamically configure VLEN at
> runtime. There's a custom pass to do that which has a simple mode
> which generates a VSETVL for each V insn and a lazy/optimal mode which
> uses LCM dataflow to move VSETVL around, identify/delete the redundant
> ones.
> 
> Currently simple mode is default for !optimize invocations while lazy
> mode being the default.
> 
> This patch allows simple mode to be forced via a toggle independent of
> the optimization level. A lot of gcc developers are currently doing this
> in some form in their local setups, as in the initial phase of autovec
> development issues are expected. It makes sense to provide this facility
> upstream. It could potentially also be used by distro builder for any
> quick workarounds in autovec bugs of future.
> 
> gcc/ChangeLog:
> 	* config/riscv/riscv.opt: New -param=vsetvl-strategy.
> 	* config/riscv/riscv-opts.h: New enum vsetvl_strategy_enum.
> 	* config/riscv/riscv-vsetvl.cc
> 	(pre_vsetvl::pre_global_vsetvl_info): Use vsetvl_strategy.
> 	(pass_vsetvl::execute): Use vsetvl_strategy.
OK if we mark them as undocumented since I would expect these are really 
just for developers to use during bring-up/debugging and ideally the 
param will disappear by gcc-15.


While I realize there are differing ideas on the set of knobs we may 
want to turn during the debugging phases, we can fault the different 
sets of knobs in as we need them.

jeff
  

Patch

diff --git a/gcc/config/riscv/riscv-opts.h b/gcc/config/riscv/riscv-opts.h
index dbf213926572..ad21ca63fb59 100644
--- a/gcc/config/riscv/riscv-opts.h
+++ b/gcc/config/riscv/riscv-opts.h
@@ -116,6 +116,17 @@  enum stringop_strategy_enum {
   STRATEGY_AUTO = STRATEGY_SCALAR | STRATEGY_VECTOR
 };
 
+/* Behavior of VSETVL Pass.  */
+enum vsetvl_strategy_enum {
+  /* Simple: Insert a vsetvl* instruction for each Vector instruction.  */
+  VSETVL_SIMPLE = 1,
+  /* Optimal but with a caveat : Run LCM dataflow analysis which could
+     lead to redundant vsetvl* instructions, which are retained.  */
+  VSETVL_OPT_NO_DEL = 2,
+  /* Optimal: Same as optimal with any redundant vsetvl* removed.  */
+  VSETVL_OPT = 4
+};
+
 #define TARGET_ZICOND_LIKE (TARGET_ZICOND || (TARGET_XVENTANACONDOPS && TARGET_64BIT))
 
 /* Bit of riscv_zvl_flags will set contintuly, N-1 bit will set if N-bit is
diff --git a/gcc/config/riscv/riscv-vsetvl.cc b/gcc/config/riscv/riscv-vsetvl.cc
index eabaef80f898..e4f1372bce3f 100644
--- a/gcc/config/riscv/riscv-vsetvl.cc
+++ b/gcc/config/riscv/riscv-vsetvl.cc
@@ -3244,31 +3244,34 @@  pre_vsetvl::pre_global_vsetvl_info ()
 	}
     }
 
-  /* Remove vsetvl infos as LCM suggest */
-  for (const bb_info *bb : crtl->ssa->bbs ())
+  if (!(vsetvl_strategy & VSETVL_OPT_NO_DEL))
     {
-      sbitmap d = m_del[bb->index ()];
-      if (bitmap_count_bits (d) == 0)
-	continue;
-      gcc_assert (bitmap_count_bits (d) == 1);
-      unsigned expr_index = bitmap_first_set_bit (d);
-      vsetvl_info &info = *m_exprs[expr_index];
-      gcc_assert (info.valid_p ());
-      gcc_assert (info.get_bb () == bb);
-      const vsetvl_block_info &block_info = get_block_info (info.get_bb ());
-      gcc_assert (block_info.get_entry_info () == info);
-      info.set_delete ();
-    }
+      /* Remove vsetvl infos as LCM suggest.  */
+      for (const bb_info *bb : crtl->ssa->bbs ())
+	{
+	  sbitmap d = m_del[bb->index ()];
+	  if (bitmap_count_bits (d) == 0)
+	    continue;
+	  gcc_assert (bitmap_count_bits (d) == 1);
+	  unsigned expr_index = bitmap_first_set_bit (d);
+	  vsetvl_info &info = *m_exprs[expr_index];
+	  gcc_assert (info.valid_p ());
+	  gcc_assert (info.get_bb () == bb);
+	  const vsetvl_block_info &block_info = get_block_info (info.get_bb ());
+	  gcc_assert (block_info.get_entry_info () == info);
+	  info.set_delete ();
+	}
 
-  /* Remove vsetvl infos if all precessors are available to the block.  */
-  for (const bb_info *bb : crtl->ssa->bbs ())
-    {
-      vsetvl_block_info &block_info = get_block_info (bb);
-      if (block_info.empty_p () || !block_info.full_available)
-	continue;
+      /* Remove vsetvl infos if all precessors are available to the block.  */
+      for (const bb_info *bb : crtl->ssa->bbs ())
+	{
+	  vsetvl_block_info &block_info = get_block_info (bb);
+	  if (block_info.empty_p () || !block_info.full_available)
+	    continue;
 
-      vsetvl_info &info = block_info.get_entry_info ();
-      info.set_delete ();
+	  vsetvl_info &info = block_info.get_entry_info ();
+	  info.set_delete ();
+	}
     }
 
   for (const bb_info *bb : crtl->ssa->bbs ())
@@ -3627,7 +3630,7 @@  pass_vsetvl::execute (function *)
   if (!has_vector_insn (cfun))
     return 0;
 
-  if (!optimize)
+  if (!optimize || vsetvl_strategy & VSETVL_SIMPLE)
     simple_vsetvl ();
   else
     lazy_vsetvl ();
diff --git a/gcc/config/riscv/riscv.opt b/gcc/config/riscv/riscv.opt
index 2bc1273fe284..5f824e2ddb3d 100644
--- a/gcc/config/riscv/riscv.opt
+++ b/gcc/config/riscv/riscv.opt
@@ -553,6 +553,23 @@  Target Undocumented Bool Var(riscv_vector_abi) Init(0)
 Enable the use of vector registers for function arguments and return value.
 This is an experimental switch and may be subject to change in the future.
 
+Enum
+Name(vsetvl_strategy) Type(enum vsetvl_strategy_enum)
+Valid arguments to -param=vsetvl-strategy=:
+
+EnumValue
+Enum(vsetvl_strategy) String(simple) Value(VSETVL_SIMPLE)
+
+EnumValue
+Enum(vsetvl_strategy) String(optim-no-del) Value(VSETVL_OPT_NO_DEL)
+
+EnumValue
+Enum(vsetvl_strategy) String(optim) Value(VSETVL_OPT)
+
+-param=vsetvl-strategy=
+Target RejectNegative Joined Enum(vsetvl_strategy) Var(vsetvl_strategy) Init(VSETVL_OPT)
+-param=vsetvl-strategy=<string>	Set the optimization level of VSETVL insert pass.
+
 Enum
 Name(stringop_strategy) Type(enum stringop_strategy_enum)
 Valid arguments to -mstringop-strategy=: