public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH v1] RISC-V: Bugfix for vls integer mode calling convention
@ 2024-01-24  3:16 pan2.li
  2024-01-24  3:18 ` juzhe.zhong
                   ` (2 more replies)
  0 siblings, 3 replies; 10+ messages in thread
From: pan2.li @ 2024-01-24  3:16 UTC (permalink / raw)
  To: gcc-patches; +Cc: juzhe.zhong, pan2.li, yanzhang.wang, kito.cheng

From: Pan Li <pan2.li@intel.com>

According to the issue as below.

https://hub.fgit.cf/riscv-non-isa/riscv-elf-psabi-doc/pull/416

When the mode size of vls integer mode is less than 2 * XLEN, we will
take the gpr/fpr for both the args and the return values. Instead of
the reference. For example the below code:

typedef short v8hi __attribute__ ((vector_size (16)));

v8hi __attribute__((noinline))
add (v8hi a, v8hi b)
{
  v8hi r = a + b;
  return r;
}

Before this patch:
add:
  vsetivli zero,8,e16,m1,ta,ma
  vle16.v  v1,0(a1) <== arg by reference
  vle16.v  v2,0(a2) <== arg by reference
  vadd.vv  v1,v1,v2
  vse16.v  v1,0(a0) <== return by reference
  ret

After this patch:
add:
  addi     sp,sp,-32
  sd       a0,0(sp)  <== arg by register a0 - a3
  sd       a1,8(sp)
  sd       a2,16(sp)
  sd       a3,24(sp)
  addi     a5,sp,16
  vsetivli zero,8,e16,m1,ta,ma
  vle16.v  v2,0(sp)
  vle16.v  v1,0(a5)
  vadd.vv  v1,v1,v2
  vse16.v  v1,0(sp)
  ld       a0,0(sp)  <== return by a0 - a1.
  ld       a1,8(sp)
  addi     sp,sp,32
  jr       ra

For vls floating point, the things get more complicated.  We follow
the below rules.

1. Vls element count <= 2 and vls size <= 2 * xlen, go fpr.
2. Vls size <= 2 * xlen, go gpr.
3. Vls size > 2 * xlen, go reference.

One exceptions is V2DF mode, we treat vls mode as aggregated and we will
have TFmode here.  Unforturnately, the emit_move_multi_word cannot take
care of TFmode elegantly and we go to gpr for V2DF mode.

The riscv regression passed for this patch.

gcc/ChangeLog:

	* config/riscv/riscv.cc (riscv_v_ext_vector_or_tuple_mode_p):
	New predicate function for vector or tuple vector.
	(riscv_v_vls_mode_aggregate_reg_count): New function to
	calculate the gpr/fpr count required by vls mode.
	(riscv_gpr_unit_size): New function to get gpr in bytes.
	(riscv_fpr_unit_size): New function to get fpr in bytes.
	(riscv_v_vls_to_gpr_mode): New function convert vls mode to gpr mode.
	(riscv_v_vls_to_fpr_mode): New function convert vls mode to fpr mode.
	(riscv_pass_vls_aggregate_in_gpr_or_fpr): New function to return
	the rtx of gpr/fpr for vls mode.
	(riscv_mode_pass_by_reference_p): New predicate function to
	indicate the mode will be passed by reference or not.
	(riscv_get_arg_info): Add vls mode handling.
	(riscv_pass_by_reference): Return false if arg info has no zero
	gpr count.

gcc/testsuite/ChangeLog:

	* gcc.target/riscv/rvv/autovec/vls/def.h: Add helper marcos.
	* gcc.target/riscv/rvv/autovec/vls/calling-convention-1.c: New test.
	* gcc.target/riscv/rvv/autovec/vls/calling-convention-10.c: New test.
	* gcc.target/riscv/rvv/autovec/vls/calling-convention-2.c: New test.
	* gcc.target/riscv/rvv/autovec/vls/calling-convention-3.c: New test.
	* gcc.target/riscv/rvv/autovec/vls/calling-convention-4.c: New test.
	* gcc.target/riscv/rvv/autovec/vls/calling-convention-5.c: New test.
	* gcc.target/riscv/rvv/autovec/vls/calling-convention-6.c: New test.
	* gcc.target/riscv/rvv/autovec/vls/calling-convention-7.c: New test.
	* gcc.target/riscv/rvv/autovec/vls/calling-convention-8.c: New test.
	* gcc.target/riscv/rvv/autovec/vls/calling-convention-9.c: New test.
	* gcc.target/riscv/rvv/autovec/vls/calling-convention-run-1.c: New test.
	* gcc.target/riscv/rvv/autovec/vls/calling-convention-run-2.c: New test.
	* gcc.target/riscv/rvv/autovec/vls/calling-convention-run-3.c: New test.
	* gcc.target/riscv/rvv/autovec/vls/calling-convention-run-4.c: New test.
	* gcc.target/riscv/rvv/autovec/vls/calling-convention-run-5.c: New test.
	* gcc.target/riscv/rvv/autovec/vls/calling-convention-run-6.c: New test.

Signed-off-by: Pan Li <pan2.li@intel.com>
---
 gcc/config/riscv/riscv.cc                     | 185 +++++++++++++++++-
 .../rvv/autovec/vls/calling-convention-1.c    | 154 +++++++++++++++
 .../rvv/autovec/vls/calling-convention-10.c   |  51 +++++
 .../rvv/autovec/vls/calling-convention-2.c    | 142 ++++++++++++++
 .../rvv/autovec/vls/calling-convention-3.c    | 130 ++++++++++++
 .../rvv/autovec/vls/calling-convention-4.c    | 118 +++++++++++
 .../rvv/autovec/vls/calling-convention-5.c    | 141 +++++++++++++
 .../rvv/autovec/vls/calling-convention-6.c    | 129 ++++++++++++
 .../rvv/autovec/vls/calling-convention-7.c    | 120 ++++++++++++
 .../rvv/autovec/vls/calling-convention-8.c    |  43 ++++
 .../rvv/autovec/vls/calling-convention-9.c    |  51 +++++
 .../autovec/vls/calling-convention-run-1.c    |  55 ++++++
 .../autovec/vls/calling-convention-run-2.c    |  55 ++++++
 .../autovec/vls/calling-convention-run-3.c    |  55 ++++++
 .../autovec/vls/calling-convention-run-4.c    |  55 ++++++
 .../autovec/vls/calling-convention-run-5.c    |  55 ++++++
 .../autovec/vls/calling-convention-run-6.c    |  55 ++++++
 .../gcc.target/riscv/rvv/autovec/vls/def.h    |  74 +++++++
 18 files changed, 1665 insertions(+), 3 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-1.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-10.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-2.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-3.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-4.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-5.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-6.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-7.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-8.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-9.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-run-1.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-run-2.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-run-3.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-run-4.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-run-5.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-run-6.c

diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 3ba45ffaa74..fb79a475bbe 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -1382,6 +1382,106 @@ riscv_v_ext_mode_p (machine_mode mode)
 	 || riscv_v_ext_vls_mode_p (mode);
 }
 
+/* Return true if it is either of below modes.
+   1. RVV vector mode.
+   2. RVV tuple mode.  */
+
+static bool
+riscv_v_ext_vector_or_tuple_mode_p (machine_mode mode)
+{
+  return riscv_v_ext_vector_mode_p (mode) || riscv_v_ext_tuple_mode_p (mode);
+}
+
+static unsigned
+riscv_v_vls_mode_aggregate_reg_count (unsigned vls_unit_size,
+				      unsigned scalar_unit_size)
+{
+  gcc_assert (vls_unit_size != 0 && scalar_unit_size != 0);
+
+  if (vls_unit_size < scalar_unit_size)
+    return 1;
+
+  return vls_unit_size / scalar_unit_size;
+}
+
+static unsigned short
+riscv_gpr_unit_size ()
+{
+  return GET_MODE_SIZE (Xmode);
+}
+
+static unsigned short
+riscv_fpr_unit_size ()
+{
+  unsigned fpr_size = 0;
+
+  if (TARGET_HARD_FLOAT && !TARGET_DOUBLE_FLOAT)
+    {
+      switch (riscv_abi)
+	{
+	  case ABI_LP64F:
+	  case ABI_ILP32F:
+	    fpr_size = GET_MODE_SIZE (SFmode);
+	    break;
+	}
+    }
+
+  if (TARGET_DOUBLE_FLOAT)
+    {
+      switch (riscv_abi)
+	{
+	  case ABI_LP64F:
+	  case ABI_ILP32F:
+	    fpr_size = GET_MODE_SIZE (SFmode);
+	    break;
+	  case ABI_LP64D:
+	  case ABI_ILP32D:
+	    fpr_size = GET_MODE_SIZE (DFmode);
+	    break;
+	}
+    }
+
+  return fpr_size;
+}
+
+static machine_mode
+riscv_v_vls_to_gpr_mode (unsigned vls_mode_size)
+{
+  switch (vls_mode_size)
+    {
+      case 16:
+	return TImode;
+      case 8:
+	return DImode;
+      case 4:
+	return SImode;
+      case 2:
+	return HImode;
+      case 1:
+	return QImode;
+      default:
+	gcc_unreachable ();
+    }
+}
+
+static machine_mode
+riscv_v_vls_to_fpr_mode (unsigned vls_mode_size)
+{
+  switch (vls_mode_size)
+    {
+      case 16:
+	return TFmode;
+      case 8:
+	return DFmode;
+      case 4:
+	return SFmode;
+      case 2:
+	return HFmode;
+      default:
+	gcc_unreachable ();
+    }
+}
+
 /* Call from ADJUST_NUNITS in riscv-modes.def. Return the correct
    NUNITS size for corresponding machine_mode.  */
 
@@ -4868,6 +4968,63 @@ riscv_pass_fpr_pair (machine_mode mode, unsigned regno1,
 				   GEN_INT (offset2))));
 }
 
+static rtx
+riscv_pass_vls_aggregate_in_gpr_or_fpr (struct riscv_arg_info *info,
+					machine_mode mode, unsigned gpr_base,
+					unsigned fpr_base)
+{
+  gcc_assert (riscv_v_ext_vls_mode_p (mode));
+
+  unsigned vls_size = GET_MODE_SIZE (mode).to_constant ();
+  unsigned gpr_size = riscv_gpr_unit_size ();
+  unsigned fpr_size = riscv_fpr_unit_size ();
+  unsigned regnum = 0, count = 0;
+  unsigned vls_elem_count = vls_size / GET_MODE_SIZE (GET_MODE_INNER (mode));
+  machine_mode smode = VOIDmode;
+
+  /* For vls floating point >= 16 bytes, it cannot be well token care of when
+     emit_move_multi_word.  For example vls size == 16 bytes when move multi
+     word.  We will hit assert similar to gcc_assert (xpart && ypart).
+     x=(reg:TF 42 fa0)
+     y=(subreg:TF (reg:TI 136) 0)
+
+     Thus, we will go with gpr for vls size >= 16.
+  */
+  if (vls_elem_count <= 2 && FLOAT_MODE_P (mode) && fpr_size && vls_size < 16
+    && IN_RANGE (vls_size, 0, fpr_size * 2))
+    {
+      count = riscv_v_vls_mode_aggregate_reg_count (vls_size, fpr_size);
+
+      if (count + info->fpr_offset <= MAX_ARGS_IN_REGISTERS)
+	{
+	  regnum = fpr_base + info->fpr_offset;
+	  info->num_fprs = count;
+	  smode = riscv_v_vls_to_fpr_mode (vls_size);
+	}
+    }
+  else if (IN_RANGE (vls_size, 0, gpr_size * 2))
+    {
+      count = riscv_v_vls_mode_aggregate_reg_count (vls_size, gpr_size);
+
+      if (count + info->gpr_offset <= MAX_ARGS_IN_REGISTERS)
+	{
+	  regnum = gpr_base + info->gpr_offset;
+	  info->num_gprs = count;
+	  smode = riscv_v_vls_to_gpr_mode (vls_size);
+	}
+    }
+
+  if (!regnum)
+    return NULL_RTX; /* Return NULL_RTX if we cannot find a suitable reg.  */
+
+  gcc_assert (smode != VOIDmode);
+
+  rtx reg = gen_rtx_REG (smode, regnum);
+  rtx x = gen_rtx_EXPR_LIST (VOIDmode, reg, CONST0_RTX (smode));
+
+  return gen_rtx_PARALLEL (mode, gen_rtvec (1, x));
+}
+
 /* Initialize a variable CUM of type CUMULATIVE_ARGS
    for a call to a function whose data type is FNTYPE.
    For a library call, FNTYPE is 0.  */
@@ -4975,6 +5132,22 @@ riscv_get_vector_arg (struct riscv_arg_info *info, const CUMULATIVE_ARGS *cum,
   return NULL_RTX;
 }
 
+/* Return true if the argument mode is passed by reference. Aka:
+   1. Scalable vector argument is anonymous.
+   2. The vector abi is disabled for vector or tuple mode.
+   Else return false.  */
+static bool
+riscv_mode_pass_by_reference_p (machine_mode mode, bool named)
+{
+  if (riscv_v_ext_mode_p (mode) && !named)
+    return true;
+
+  if (riscv_v_ext_vector_or_tuple_mode_p (mode) && !riscv_vector_abi)
+    return true;
+
+  return false;
+}
+
 /* Fill INFO with information about a single argument, and return an RTL
    pattern to pass or return the argument. Return NULL_RTX if argument cannot
    pass or return in registers, then the argument may be passed by reference or
@@ -4997,9 +5170,7 @@ riscv_get_arg_info (struct riscv_arg_info *info, const CUMULATIVE_ARGS *cum,
   info->gpr_offset = cum->num_gprs;
   info->fpr_offset = cum->num_fprs;
 
-  /* When disable vector_abi or scalable vector argument is anonymous, this
-     argument is passed by reference.  */
-  if (riscv_v_ext_mode_p (mode) && (!riscv_vector_abi || !named))
+  if (riscv_mode_pass_by_reference_p (mode, named))
     return NULL_RTX;
 
   if (named)
@@ -5064,6 +5235,10 @@ riscv_get_arg_info (struct riscv_arg_info *info, const CUMULATIVE_ARGS *cum,
 				      fields[1].offset);
 	}
 
+      if (riscv_v_ext_vls_mode_p (mode))
+	return riscv_pass_vls_aggregate_in_gpr_or_fpr (info, mode, gpr_base,
+						       fpr_base);
+
       /* For scalable vector argument.  */
       if (riscv_vector_type_p (type) && riscv_v_ext_mode_p (mode))
 	return riscv_get_vector_arg (info, cum, mode, return_p);
@@ -5196,6 +5371,10 @@ riscv_pass_by_reference (cumulative_args_t cum_v, const function_arg_info &arg)
       if (info.num_fprs)
 	return false;
 
+      /* Don't pass by reference if we can use general register(s) for vls.  */
+      if (info.num_gprs && riscv_v_ext_vls_mode_p (arg.mode))
+	return false;
+
       /* Don't pass by reference if we can use vector register groups.  */
       if (info.num_vrs > 0 || info.num_mrs > 0)
 	return false;
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-1.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-1.c
new file mode 100644
index 00000000000..41e31c258f8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-1.c
@@ -0,0 +1,154 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv_zvl4096b --param riscv-autovec-preference=scalable -mabi=lp64d -O3" } */
+
+#include "def.h"
+
+DEF_RET1_ARG0 (v1qi)
+DEF_RET1_ARG0 (v2qi)
+DEF_RET1_ARG0 (v4qi)
+DEF_RET1_ARG0 (v8qi)
+DEF_RET1_ARG0 (v16qi)
+DEF_RET1_ARG0 (v32qi)
+DEF_RET1_ARG0 (v64qi)
+DEF_RET1_ARG0 (v128qi)
+DEF_RET1_ARG0 (v256qi)
+DEF_RET1_ARG0 (v512qi)
+DEF_RET1_ARG0 (v1024qi)
+DEF_RET1_ARG0 (v2048qi)
+DEF_RET1_ARG0 (v4096qi)
+
+DEF_RET1_ARG1 (v1qi)
+DEF_RET1_ARG1 (v2qi)
+DEF_RET1_ARG1 (v4qi)
+DEF_RET1_ARG1 (v8qi)
+DEF_RET1_ARG1 (v16qi)
+DEF_RET1_ARG1 (v32qi)
+DEF_RET1_ARG1 (v64qi)
+DEF_RET1_ARG1 (v128qi)
+DEF_RET1_ARG1 (v256qi)
+DEF_RET1_ARG1 (v512qi)
+DEF_RET1_ARG1 (v1024qi)
+DEF_RET1_ARG1 (v2048qi)
+DEF_RET1_ARG1 (v4096qi)
+
+DEF_RET1_ARG2 (v1qi)
+DEF_RET1_ARG2 (v2qi)
+DEF_RET1_ARG2 (v4qi)
+DEF_RET1_ARG2 (v8qi)
+DEF_RET1_ARG2 (v16qi)
+DEF_RET1_ARG2 (v32qi)
+DEF_RET1_ARG2 (v64qi)
+DEF_RET1_ARG2 (v128qi)
+DEF_RET1_ARG2 (v256qi)
+DEF_RET1_ARG2 (v512qi)
+DEF_RET1_ARG2 (v1024qi)
+DEF_RET1_ARG2 (v2048qi)
+DEF_RET1_ARG2 (v4096qi)
+
+DEF_RET1_ARG3 (v1qi)
+DEF_RET1_ARG3 (v2qi)
+DEF_RET1_ARG3 (v4qi)
+DEF_RET1_ARG3 (v8qi)
+DEF_RET1_ARG3 (v16qi)
+DEF_RET1_ARG3 (v32qi)
+DEF_RET1_ARG3 (v64qi)
+DEF_RET1_ARG3 (v128qi)
+DEF_RET1_ARG3 (v256qi)
+DEF_RET1_ARG3 (v512qi)
+DEF_RET1_ARG3 (v1024qi)
+DEF_RET1_ARG3 (v2048qi)
+DEF_RET1_ARG3 (v4096qi)
+
+DEF_RET1_ARG4 (v1qi)
+DEF_RET1_ARG4 (v2qi)
+DEF_RET1_ARG4 (v4qi)
+DEF_RET1_ARG4 (v8qi)
+DEF_RET1_ARG4 (v16qi)
+DEF_RET1_ARG4 (v32qi)
+DEF_RET1_ARG4 (v64qi)
+DEF_RET1_ARG4 (v128qi)
+DEF_RET1_ARG4 (v256qi)
+DEF_RET1_ARG4 (v512qi)
+DEF_RET1_ARG4 (v1024qi)
+DEF_RET1_ARG4 (v2048qi)
+DEF_RET1_ARG4 (v4096qi)
+
+DEF_RET1_ARG5 (v1qi)
+DEF_RET1_ARG5 (v2qi)
+DEF_RET1_ARG5 (v4qi)
+DEF_RET1_ARG5 (v8qi)
+DEF_RET1_ARG5 (v16qi)
+DEF_RET1_ARG5 (v32qi)
+DEF_RET1_ARG5 (v64qi)
+DEF_RET1_ARG5 (v128qi)
+DEF_RET1_ARG5 (v256qi)
+DEF_RET1_ARG5 (v512qi)
+DEF_RET1_ARG5 (v1024qi)
+DEF_RET1_ARG5 (v2048qi)
+DEF_RET1_ARG5 (v4096qi)
+
+DEF_RET1_ARG6 (v1qi)
+DEF_RET1_ARG6 (v2qi)
+DEF_RET1_ARG6 (v4qi)
+DEF_RET1_ARG6 (v8qi)
+DEF_RET1_ARG6 (v16qi)
+DEF_RET1_ARG6 (v32qi)
+DEF_RET1_ARG6 (v64qi)
+DEF_RET1_ARG6 (v128qi)
+DEF_RET1_ARG6 (v256qi)
+DEF_RET1_ARG6 (v512qi)
+DEF_RET1_ARG6 (v1024qi)
+DEF_RET1_ARG6 (v2048qi)
+DEF_RET1_ARG6 (v4096qi)
+
+DEF_RET1_ARG7 (v1qi)
+DEF_RET1_ARG7 (v2qi)
+DEF_RET1_ARG7 (v4qi)
+DEF_RET1_ARG7 (v8qi)
+DEF_RET1_ARG7 (v16qi)
+DEF_RET1_ARG7 (v32qi)
+DEF_RET1_ARG7 (v64qi)
+DEF_RET1_ARG7 (v128qi)
+DEF_RET1_ARG7 (v256qi)
+DEF_RET1_ARG7 (v512qi)
+DEF_RET1_ARG7 (v1024qi)
+DEF_RET1_ARG7 (v2048qi)
+DEF_RET1_ARG7 (v4096qi)
+
+DEF_RET1_ARG8 (v1qi)
+DEF_RET1_ARG8 (v2qi)
+DEF_RET1_ARG8 (v4qi)
+DEF_RET1_ARG8 (v8qi)
+DEF_RET1_ARG8 (v16qi)
+DEF_RET1_ARG8 (v32qi)
+DEF_RET1_ARG8 (v64qi)
+DEF_RET1_ARG8 (v128qi)
+DEF_RET1_ARG8 (v256qi)
+DEF_RET1_ARG8 (v512qi)
+DEF_RET1_ARG8 (v1024qi)
+DEF_RET1_ARG8 (v2048qi)
+DEF_RET1_ARG8 (v4096qi)
+
+DEF_RET1_ARG9 (v1qi)
+DEF_RET1_ARG9 (v2qi)
+DEF_RET1_ARG9 (v4qi)
+DEF_RET1_ARG9 (v8qi)
+DEF_RET1_ARG9 (v16qi)
+DEF_RET1_ARG9 (v32qi)
+DEF_RET1_ARG9 (v64qi)
+DEF_RET1_ARG9 (v128qi)
+DEF_RET1_ARG9 (v256qi)
+DEF_RET1_ARG9 (v512qi)
+DEF_RET1_ARG9 (v1024qi)
+DEF_RET1_ARG9 (v2048qi)
+DEF_RET1_ARG9 (v4096qi)
+
+/* { dg-final { scan-assembler-times {li\s+a[0-1],\s*0} 9 } } */
+/* { dg-final { scan-assembler-times {lbu\s+a0,\s*[0-9]+\(sp\)} 8 } } */
+/* { dg-final { scan-assembler-times {lhu\s+a0,\s*[0-9]+\(sp\)} 8 } } */
+/* { dg-final { scan-assembler-times {lw\s+a0,\s*[0-9]+\(sp\)} 8 } } */
+/* { dg-final { scan-assembler-times {ld\s+a[0-1],\s*[0-9]+\(sp\)} 35 } } */
+/* { dg-final { scan-assembler-times {sb\s+a[0-7],\s*[0-9]+\(sp\)} 43 } } */
+/* { dg-final { scan-assembler-times {sh\s+a[0-7],\s*[0-9]+\(sp\)} 43 } } */
+/* { dg-final { scan-assembler-times {sw\s+a[0-7],\s*[0-9]+\(sp\)} 43 } } */
+/* { dg-final { scan-assembler-times {sd\s+a[0-7],\s*[0-9]+\(sp\)} 103 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-10.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-10.c
new file mode 100644
index 00000000000..0abc6cf0146
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-10.c
@@ -0,0 +1,51 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv_zvfh_zvl4096b -mabi=lp64 --param riscv-autovec-preference=scalable -O3 -fno-schedule-insns -fno-schedule-insns2" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include "def.h"
+
+/*
+** v4hf_RET1_ARG1:
+** ret
+*/
+DEF_RET1_ARG1 (v4hf)
+
+/*
+** v2sf_RET1_ARG2:
+** addi\s+sp,\s*sp,\s*-16
+** sd\s+a0,\s*0\(sp\)
+** sd\s+a1,\s*8\(sp\)
+** ...
+** ld\s+a0,\s*0\(sp\)
+** addi\s+sp,\s*sp,\s*16
+** jr\s+ra
+*/
+DEF_RET1_ARG2 (v2sf)
+
+/*
+** v4sf_RET1_ARG2:
+** addi\s+sp,\s*sp,\s*-32
+** sd\s+a0,\s*0\(sp\)
+** sd\s+a1,\s*8\(sp\)
+** sd\s+a2,\s*16\(sp\)
+** sd\s+a3,\s*24\(sp\)
+** ...
+** ld\s+a0,\s*0\(sp\)
+** ld\s+a1,\s*8\(sp\)
+** addi\s+sp,\s*sp,\s*32
+** jr\s+ra
+*/
+DEF_RET1_ARG2 (v4sf)
+
+/*
+** v1df_RET1_ARG3:
+** addi\s+sp,\s*sp,\s*-32
+** sd\s+a0,\s*8\(sp\)
+** sd\s+a1,\s*16\(sp\)
+** sd\s+a2,\s*24\(sp\)
+** ...
+** ld\s+a0,\s*8\(sp\)
+** addi\s+sp,\s*sp,\s*32
+** jr\s+ra
+*/
+DEF_RET1_ARG3 (v1df)
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-2.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-2.c
new file mode 100644
index 00000000000..8544f160e93
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-2.c
@@ -0,0 +1,142 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv_zvl4096b --param riscv-autovec-preference=scalable -mabi=lp64d -O3" } */
+
+#include "def.h"
+
+DEF_RET1_ARG0 (v1hi)
+DEF_RET1_ARG0 (v2hi)
+DEF_RET1_ARG0 (v4hi)
+DEF_RET1_ARG0 (v8hi)
+DEF_RET1_ARG0 (v16hi)
+DEF_RET1_ARG0 (v32hi)
+DEF_RET1_ARG0 (v64hi)
+DEF_RET1_ARG0 (v128hi)
+DEF_RET1_ARG0 (v256hi)
+DEF_RET1_ARG0 (v512hi)
+DEF_RET1_ARG0 (v1024hi)
+DEF_RET1_ARG0 (v2048hi)
+
+DEF_RET1_ARG1 (v1hi)
+DEF_RET1_ARG1 (v2hi)
+DEF_RET1_ARG1 (v4hi)
+DEF_RET1_ARG1 (v8hi)
+DEF_RET1_ARG1 (v16hi)
+DEF_RET1_ARG1 (v32hi)
+DEF_RET1_ARG1 (v64hi)
+DEF_RET1_ARG1 (v128hi)
+DEF_RET1_ARG1 (v256hi)
+DEF_RET1_ARG1 (v512hi)
+DEF_RET1_ARG1 (v1024hi)
+DEF_RET1_ARG1 (v2048hi)
+
+DEF_RET1_ARG2 (v1hi)
+DEF_RET1_ARG2 (v2hi)
+DEF_RET1_ARG2 (v4hi)
+DEF_RET1_ARG2 (v8hi)
+DEF_RET1_ARG2 (v16hi)
+DEF_RET1_ARG2 (v32hi)
+DEF_RET1_ARG2 (v64hi)
+DEF_RET1_ARG2 (v128hi)
+DEF_RET1_ARG2 (v256hi)
+DEF_RET1_ARG2 (v512hi)
+DEF_RET1_ARG2 (v1024hi)
+DEF_RET1_ARG2 (v2048hi)
+
+DEF_RET1_ARG3 (v1hi)
+DEF_RET1_ARG3 (v2hi)
+DEF_RET1_ARG3 (v4hi)
+DEF_RET1_ARG3 (v8hi)
+DEF_RET1_ARG3 (v16hi)
+DEF_RET1_ARG3 (v32hi)
+DEF_RET1_ARG3 (v64hi)
+DEF_RET1_ARG3 (v128hi)
+DEF_RET1_ARG3 (v256hi)
+DEF_RET1_ARG3 (v512hi)
+DEF_RET1_ARG3 (v1024hi)
+DEF_RET1_ARG3 (v2048hi)
+
+DEF_RET1_ARG4 (v1hi)
+DEF_RET1_ARG4 (v2hi)
+DEF_RET1_ARG4 (v4hi)
+DEF_RET1_ARG4 (v8hi)
+DEF_RET1_ARG4 (v16hi)
+DEF_RET1_ARG4 (v32hi)
+DEF_RET1_ARG4 (v64hi)
+DEF_RET1_ARG4 (v128hi)
+DEF_RET1_ARG4 (v256hi)
+DEF_RET1_ARG4 (v512hi)
+DEF_RET1_ARG4 (v1024hi)
+DEF_RET1_ARG4 (v2048hi)
+
+DEF_RET1_ARG5 (v1hi)
+DEF_RET1_ARG5 (v2hi)
+DEF_RET1_ARG5 (v4hi)
+DEF_RET1_ARG5 (v8hi)
+DEF_RET1_ARG5 (v16hi)
+DEF_RET1_ARG5 (v32hi)
+DEF_RET1_ARG5 (v64hi)
+DEF_RET1_ARG5 (v128hi)
+DEF_RET1_ARG5 (v256hi)
+DEF_RET1_ARG5 (v512hi)
+DEF_RET1_ARG5 (v1024hi)
+DEF_RET1_ARG5 (v2048hi)
+
+DEF_RET1_ARG6 (v1hi)
+DEF_RET1_ARG6 (v2hi)
+DEF_RET1_ARG6 (v4hi)
+DEF_RET1_ARG6 (v8hi)
+DEF_RET1_ARG6 (v16hi)
+DEF_RET1_ARG6 (v32hi)
+DEF_RET1_ARG6 (v64hi)
+DEF_RET1_ARG6 (v128hi)
+DEF_RET1_ARG6 (v256hi)
+DEF_RET1_ARG6 (v512hi)
+DEF_RET1_ARG6 (v1024hi)
+DEF_RET1_ARG6 (v2048hi)
+
+DEF_RET1_ARG7 (v1hi)
+DEF_RET1_ARG7 (v2hi)
+DEF_RET1_ARG7 (v4hi)
+DEF_RET1_ARG7 (v8hi)
+DEF_RET1_ARG7 (v16hi)
+DEF_RET1_ARG7 (v32hi)
+DEF_RET1_ARG7 (v64hi)
+DEF_RET1_ARG7 (v128hi)
+DEF_RET1_ARG7 (v256hi)
+DEF_RET1_ARG7 (v512hi)
+DEF_RET1_ARG7 (v1024hi)
+DEF_RET1_ARG7 (v2048hi)
+
+DEF_RET1_ARG8 (v1hi)
+DEF_RET1_ARG8 (v2hi)
+DEF_RET1_ARG8 (v4hi)
+DEF_RET1_ARG8 (v8hi)
+DEF_RET1_ARG8 (v16hi)
+DEF_RET1_ARG8 (v32hi)
+DEF_RET1_ARG8 (v64hi)
+DEF_RET1_ARG8 (v128hi)
+DEF_RET1_ARG8 (v256hi)
+DEF_RET1_ARG8 (v512hi)
+DEF_RET1_ARG8 (v1024hi)
+DEF_RET1_ARG8 (v2048hi)
+
+DEF_RET1_ARG9 (v1hi)
+DEF_RET1_ARG9 (v2hi)
+DEF_RET1_ARG9 (v4hi)
+DEF_RET1_ARG9 (v8hi)
+DEF_RET1_ARG9 (v16hi)
+DEF_RET1_ARG9 (v32hi)
+DEF_RET1_ARG9 (v64hi)
+DEF_RET1_ARG9 (v128hi)
+DEF_RET1_ARG9 (v256hi)
+DEF_RET1_ARG9 (v512hi)
+DEF_RET1_ARG9 (v1024hi)
+DEF_RET1_ARG9 (v2048hi)
+
+/* { dg-final { scan-assembler-times {li\s+a[0-1],\s*0} 8 } } */
+/* { dg-final { scan-assembler-times {lhu\s+a0,\s*[0-9]+\(sp\)} 8 } } */
+/* { dg-final { scan-assembler-times {lw\s+a0,\s*[0-9]+\(sp\)} 8 } } */
+/* { dg-final { scan-assembler-times {ld\s+a[0-1],\s*[0-9]+\(sp\)} 33 } } */
+/* { dg-final { scan-assembler-times {sh\s+a[0-7],\s*[0-9]+\(sp\)} 43 } } */
+/* { dg-final { scan-assembler-times {sw\s+a[0-7],\s*[0-9]+\(sp\)} 43 } } */
+/* { dg-final { scan-assembler-times {sd\s+a[0-7],\s*[0-9]+\(sp\)} 103 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-3.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-3.c
new file mode 100644
index 00000000000..17b06933c72
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-3.c
@@ -0,0 +1,130 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv_zvl4096b --param riscv-autovec-preference=scalable -mabi=lp64d -O3" } */
+
+#include "def.h"
+
+DEF_RET1_ARG0 (v1si)
+DEF_RET1_ARG0 (v2si)
+DEF_RET1_ARG0 (v4si)
+DEF_RET1_ARG0 (v8si)
+DEF_RET1_ARG0 (v16si)
+DEF_RET1_ARG0 (v32si)
+DEF_RET1_ARG0 (v64si)
+DEF_RET1_ARG0 (v128si)
+DEF_RET1_ARG0 (v256si)
+DEF_RET1_ARG0 (v512si)
+DEF_RET1_ARG0 (v1024si)
+
+DEF_RET1_ARG1 (v1si)
+DEF_RET1_ARG1 (v2si)
+DEF_RET1_ARG1 (v4si)
+DEF_RET1_ARG1 (v8si)
+DEF_RET1_ARG1 (v16si)
+DEF_RET1_ARG1 (v32si)
+DEF_RET1_ARG1 (v64si)
+DEF_RET1_ARG1 (v128si)
+DEF_RET1_ARG1 (v256si)
+DEF_RET1_ARG1 (v512si)
+DEF_RET1_ARG1 (v1024si)
+
+DEF_RET1_ARG2 (v1si)
+DEF_RET1_ARG2 (v2si)
+DEF_RET1_ARG2 (v4si)
+DEF_RET1_ARG2 (v8si)
+DEF_RET1_ARG2 (v16si)
+DEF_RET1_ARG2 (v32si)
+DEF_RET1_ARG2 (v64si)
+DEF_RET1_ARG2 (v128si)
+DEF_RET1_ARG2 (v256si)
+DEF_RET1_ARG2 (v512si)
+DEF_RET1_ARG2 (v1024si)
+
+DEF_RET1_ARG3 (v1si)
+DEF_RET1_ARG3 (v2si)
+DEF_RET1_ARG3 (v4si)
+DEF_RET1_ARG3 (v8si)
+DEF_RET1_ARG3 (v16si)
+DEF_RET1_ARG3 (v32si)
+DEF_RET1_ARG3 (v64si)
+DEF_RET1_ARG3 (v128si)
+DEF_RET1_ARG3 (v256si)
+DEF_RET1_ARG3 (v512si)
+DEF_RET1_ARG3 (v1024si)
+
+DEF_RET1_ARG4 (v1si)
+DEF_RET1_ARG4 (v2si)
+DEF_RET1_ARG4 (v4si)
+DEF_RET1_ARG4 (v8si)
+DEF_RET1_ARG4 (v16si)
+DEF_RET1_ARG4 (v32si)
+DEF_RET1_ARG4 (v64si)
+DEF_RET1_ARG4 (v128si)
+DEF_RET1_ARG4 (v256si)
+DEF_RET1_ARG4 (v512si)
+DEF_RET1_ARG4 (v1024si)
+
+DEF_RET1_ARG5 (v1si)
+DEF_RET1_ARG5 (v2si)
+DEF_RET1_ARG5 (v4si)
+DEF_RET1_ARG5 (v8si)
+DEF_RET1_ARG5 (v16si)
+DEF_RET1_ARG5 (v32si)
+DEF_RET1_ARG5 (v64si)
+DEF_RET1_ARG5 (v128si)
+DEF_RET1_ARG5 (v256si)
+DEF_RET1_ARG5 (v512si)
+DEF_RET1_ARG5 (v1024si)
+
+DEF_RET1_ARG6 (v1si)
+DEF_RET1_ARG6 (v2si)
+DEF_RET1_ARG6 (v4si)
+DEF_RET1_ARG6 (v8si)
+DEF_RET1_ARG6 (v16si)
+DEF_RET1_ARG6 (v32si)
+DEF_RET1_ARG6 (v64si)
+DEF_RET1_ARG6 (v128si)
+DEF_RET1_ARG6 (v256si)
+DEF_RET1_ARG6 (v512si)
+DEF_RET1_ARG6 (v1024si)
+
+DEF_RET1_ARG7 (v1si)
+DEF_RET1_ARG7 (v2si)
+DEF_RET1_ARG7 (v4si)
+DEF_RET1_ARG7 (v8si)
+DEF_RET1_ARG7 (v16si)
+DEF_RET1_ARG7 (v32si)
+DEF_RET1_ARG7 (v64si)
+DEF_RET1_ARG7 (v128si)
+DEF_RET1_ARG7 (v256si)
+DEF_RET1_ARG7 (v512si)
+DEF_RET1_ARG7 (v1024si)
+
+DEF_RET1_ARG8 (v1si)
+DEF_RET1_ARG8 (v2si)
+DEF_RET1_ARG8 (v4si)
+DEF_RET1_ARG8 (v8si)
+DEF_RET1_ARG8 (v16si)
+DEF_RET1_ARG8 (v32si)
+DEF_RET1_ARG8 (v64si)
+DEF_RET1_ARG8 (v128si)
+DEF_RET1_ARG8 (v256si)
+DEF_RET1_ARG8 (v512si)
+DEF_RET1_ARG8 (v1024si)
+
+DEF_RET1_ARG9 (v1si)
+DEF_RET1_ARG9 (v2si)
+DEF_RET1_ARG9 (v4si)
+DEF_RET1_ARG9 (v8si)
+DEF_RET1_ARG9 (v16si)
+DEF_RET1_ARG9 (v32si)
+DEF_RET1_ARG9 (v64si)
+DEF_RET1_ARG9 (v128si)
+DEF_RET1_ARG9 (v256si)
+DEF_RET1_ARG9 (v512si)
+DEF_RET1_ARG9 (v1024si)
+
+/* { dg-final { scan-assembler-times {li\s+a[0-1],\s*0} 7 } } */
+/* { dg-final { scan-assembler-times {lw\s+a0,\s*[0-9]+\(sp\)} 8 } } */
+/* { dg-final { scan-assembler-times {ld\s+a[0-1],\s*[0-9]+\(sp\)} 31 } } */
+/* { dg-final { scan-assembler-times {sw\s+a[0-7],\s*[0-9]+\(sp\)} 43 } } */
+/* { dg-final { scan-assembler-times {sd\s+a[0-7],\s*[0-9]+\(sp\)} 103 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-4.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-4.c
new file mode 100644
index 00000000000..8c3f6ba98e3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-4.c
@@ -0,0 +1,118 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv_zvl4096b --param riscv-autovec-preference=scalable -mabi=lp64d -O3" } */
+
+#include "def.h"
+
+DEF_RET1_ARG0 (v1di)
+DEF_RET1_ARG0 (v2di)
+DEF_RET1_ARG0 (v4di)
+DEF_RET1_ARG0 (v8di)
+DEF_RET1_ARG0 (v16di)
+DEF_RET1_ARG0 (v32di)
+DEF_RET1_ARG0 (v64di)
+DEF_RET1_ARG0 (v128di)
+DEF_RET1_ARG0 (v256di)
+DEF_RET1_ARG0 (v512di)
+
+DEF_RET1_ARG1 (v1di)
+DEF_RET1_ARG1 (v2di)
+DEF_RET1_ARG1 (v4di)
+DEF_RET1_ARG1 (v8di)
+DEF_RET1_ARG1 (v16di)
+DEF_RET1_ARG1 (v32di)
+DEF_RET1_ARG1 (v64di)
+DEF_RET1_ARG1 (v128di)
+DEF_RET1_ARG1 (v256di)
+DEF_RET1_ARG1 (v512di)
+
+DEF_RET1_ARG2 (v1di)
+DEF_RET1_ARG2 (v2di)
+DEF_RET1_ARG2 (v4di)
+DEF_RET1_ARG2 (v8di)
+DEF_RET1_ARG2 (v16di)
+DEF_RET1_ARG2 (v32di)
+DEF_RET1_ARG2 (v64di)
+DEF_RET1_ARG2 (v128di)
+DEF_RET1_ARG2 (v256di)
+DEF_RET1_ARG2 (v512di)
+
+DEF_RET1_ARG3 (v1di)
+DEF_RET1_ARG3 (v2di)
+DEF_RET1_ARG3 (v4di)
+DEF_RET1_ARG3 (v8di)
+DEF_RET1_ARG3 (v16di)
+DEF_RET1_ARG3 (v32di)
+DEF_RET1_ARG3 (v64di)
+DEF_RET1_ARG3 (v128di)
+DEF_RET1_ARG3 (v256di)
+DEF_RET1_ARG3 (v512di)
+
+DEF_RET1_ARG4 (v1di)
+DEF_RET1_ARG4 (v2di)
+DEF_RET1_ARG4 (v4di)
+DEF_RET1_ARG4 (v8di)
+DEF_RET1_ARG4 (v16di)
+DEF_RET1_ARG4 (v32di)
+DEF_RET1_ARG4 (v64di)
+DEF_RET1_ARG4 (v128di)
+DEF_RET1_ARG4 (v256di)
+DEF_RET1_ARG4 (v512di)
+
+DEF_RET1_ARG5 (v1di)
+DEF_RET1_ARG5 (v2di)
+DEF_RET1_ARG5 (v4di)
+DEF_RET1_ARG5 (v8di)
+DEF_RET1_ARG5 (v16di)
+DEF_RET1_ARG5 (v32di)
+DEF_RET1_ARG5 (v64di)
+DEF_RET1_ARG5 (v128di)
+DEF_RET1_ARG5 (v256di)
+DEF_RET1_ARG5 (v512di)
+
+DEF_RET1_ARG6 (v1di)
+DEF_RET1_ARG6 (v2di)
+DEF_RET1_ARG6 (v4di)
+DEF_RET1_ARG6 (v8di)
+DEF_RET1_ARG6 (v16di)
+DEF_RET1_ARG6 (v32di)
+DEF_RET1_ARG6 (v64di)
+DEF_RET1_ARG6 (v128di)
+DEF_RET1_ARG6 (v256di)
+DEF_RET1_ARG6 (v512di)
+
+DEF_RET1_ARG7 (v1di)
+DEF_RET1_ARG7 (v2di)
+DEF_RET1_ARG7 (v4di)
+DEF_RET1_ARG7 (v8di)
+DEF_RET1_ARG7 (v16di)
+DEF_RET1_ARG7 (v32di)
+DEF_RET1_ARG7 (v64di)
+DEF_RET1_ARG7 (v128di)
+DEF_RET1_ARG7 (v256di)
+DEF_RET1_ARG7 (v512di)
+
+DEF_RET1_ARG8 (v1di)
+DEF_RET1_ARG8 (v2di)
+DEF_RET1_ARG8 (v4di)
+DEF_RET1_ARG8 (v8di)
+DEF_RET1_ARG8 (v16di)
+DEF_RET1_ARG8 (v32di)
+DEF_RET1_ARG8 (v64di)
+DEF_RET1_ARG8 (v128di)
+DEF_RET1_ARG8 (v256di)
+DEF_RET1_ARG8 (v512di)
+
+DEF_RET1_ARG9 (v1di)
+DEF_RET1_ARG9 (v2di)
+DEF_RET1_ARG9 (v4di)
+DEF_RET1_ARG9 (v8di)
+DEF_RET1_ARG9 (v16di)
+DEF_RET1_ARG9 (v32di)
+DEF_RET1_ARG9 (v64di)
+DEF_RET1_ARG9 (v128di)
+DEF_RET1_ARG9 (v256di)
+DEF_RET1_ARG9 (v512di)
+
+/* { dg-final { scan-assembler-times {li\s+a[0-1],\s*0} 6 } } */
+/* { dg-final { scan-assembler-times {ld\s+a[0-1],\s*[0-9]+\(sp\)} 29 } } */
+/* { dg-final { scan-assembler-times {sd\s+a[0-7],\s*[0-9]+\(sp\)} 103 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-5.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-5.c
new file mode 100644
index 00000000000..cfa4f5db372
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-5.c
@@ -0,0 +1,141 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv_zvfh_zvl4096b --param riscv-autovec-preference=scalable -mabi=lp64d -O3" } */
+
+#include "def.h"
+
+DEF_RET1_ARG0 (v1hf)
+DEF_RET1_ARG0 (v2hf)
+DEF_RET1_ARG0 (v4hf)
+DEF_RET1_ARG0 (v8hf)
+DEF_RET1_ARG0 (v16hf)
+DEF_RET1_ARG0 (v32hf)
+DEF_RET1_ARG0 (v64hf)
+DEF_RET1_ARG0 (v128hf)
+DEF_RET1_ARG0 (v256hf)
+DEF_RET1_ARG0 (v512hf)
+DEF_RET1_ARG0 (v1024hf)
+DEF_RET1_ARG0 (v2048hf)
+
+DEF_RET1_ARG1 (v1hf)
+DEF_RET1_ARG1 (v2hf)
+DEF_RET1_ARG1 (v4hf)
+DEF_RET1_ARG1 (v8hf)
+DEF_RET1_ARG1 (v16hf)
+DEF_RET1_ARG1 (v32hf)
+DEF_RET1_ARG1 (v64hf)
+DEF_RET1_ARG1 (v128hf)
+DEF_RET1_ARG1 (v256hf)
+DEF_RET1_ARG1 (v512hf)
+DEF_RET1_ARG1 (v1024hf)
+DEF_RET1_ARG1 (v2048hf)
+
+DEF_RET1_ARG2 (v1hf)
+DEF_RET1_ARG2 (v2hf)
+DEF_RET1_ARG2 (v4hf)
+DEF_RET1_ARG2 (v8hf)
+DEF_RET1_ARG2 (v16hf)
+DEF_RET1_ARG2 (v32hf)
+DEF_RET1_ARG2 (v64hf)
+DEF_RET1_ARG2 (v128hf)
+DEF_RET1_ARG2 (v256hf)
+DEF_RET1_ARG2 (v512hf)
+DEF_RET1_ARG2 (v1024hf)
+DEF_RET1_ARG2 (v2048hf)
+
+DEF_RET1_ARG3 (v1hf)
+DEF_RET1_ARG3 (v2hf)
+DEF_RET1_ARG3 (v4hf)
+DEF_RET1_ARG3 (v8hf)
+DEF_RET1_ARG3 (v16hf)
+DEF_RET1_ARG3 (v32hf)
+DEF_RET1_ARG3 (v64hf)
+DEF_RET1_ARG3 (v128hf)
+DEF_RET1_ARG3 (v256hf)
+DEF_RET1_ARG3 (v512hf)
+DEF_RET1_ARG3 (v1024hf)
+DEF_RET1_ARG3 (v2048hf)
+
+DEF_RET1_ARG4 (v1hf)
+DEF_RET1_ARG4 (v2hf)
+DEF_RET1_ARG4 (v4hf)
+DEF_RET1_ARG4 (v8hf)
+DEF_RET1_ARG4 (v16hf)
+DEF_RET1_ARG4 (v32hf)
+DEF_RET1_ARG4 (v64hf)
+DEF_RET1_ARG4 (v128hf)
+DEF_RET1_ARG4 (v256hf)
+DEF_RET1_ARG4 (v512hf)
+DEF_RET1_ARG4 (v1024hf)
+DEF_RET1_ARG4 (v2048hf)
+
+DEF_RET1_ARG5 (v1hf)
+DEF_RET1_ARG5 (v2hf)
+DEF_RET1_ARG5 (v4hf)
+DEF_RET1_ARG5 (v8hf)
+DEF_RET1_ARG5 (v16hf)
+DEF_RET1_ARG5 (v32hf)
+DEF_RET1_ARG5 (v64hf)
+DEF_RET1_ARG5 (v128hf)
+DEF_RET1_ARG5 (v256hf)
+DEF_RET1_ARG5 (v512hf)
+DEF_RET1_ARG5 (v1024hf)
+DEF_RET1_ARG5 (v2048hf)
+
+DEF_RET1_ARG6 (v1hf)
+DEF_RET1_ARG6 (v2hf)
+DEF_RET1_ARG6 (v4hf)
+DEF_RET1_ARG6 (v8hf)
+DEF_RET1_ARG6 (v16hf)
+DEF_RET1_ARG6 (v32hf)
+DEF_RET1_ARG6 (v64hf)
+DEF_RET1_ARG6 (v128hf)
+DEF_RET1_ARG6 (v256hf)
+DEF_RET1_ARG6 (v512hf)
+DEF_RET1_ARG6 (v1024hf)
+DEF_RET1_ARG6 (v2048hf)
+
+DEF_RET1_ARG7 (v1hf)
+DEF_RET1_ARG7 (v2hf)
+DEF_RET1_ARG7 (v4hf)
+DEF_RET1_ARG7 (v8hf)
+DEF_RET1_ARG7 (v16hf)
+DEF_RET1_ARG7 (v32hf)
+DEF_RET1_ARG7 (v64hf)
+DEF_RET1_ARG7 (v128hf)
+DEF_RET1_ARG7 (v256hf)
+DEF_RET1_ARG7 (v512hf)
+DEF_RET1_ARG7 (v1024hf)
+DEF_RET1_ARG7 (v2048hf)
+
+DEF_RET1_ARG8 (v1hf)
+DEF_RET1_ARG8 (v2hf)
+DEF_RET1_ARG8 (v4hf)
+DEF_RET1_ARG8 (v8hf)
+DEF_RET1_ARG8 (v16hf)
+DEF_RET1_ARG8 (v32hf)
+DEF_RET1_ARG8 (v64hf)
+DEF_RET1_ARG8 (v128hf)
+DEF_RET1_ARG8 (v256hf)
+DEF_RET1_ARG8 (v512hf)
+DEF_RET1_ARG8 (v1024hf)
+DEF_RET1_ARG8 (v2048hf)
+
+DEF_RET1_ARG9 (v1hf)
+DEF_RET1_ARG9 (v2hf)
+DEF_RET1_ARG9 (v4hf)
+DEF_RET1_ARG9 (v8hf)
+DEF_RET1_ARG9 (v16hf)
+DEF_RET1_ARG9 (v32hf)
+DEF_RET1_ARG9 (v64hf)
+DEF_RET1_ARG9 (v128hf)
+DEF_RET1_ARG9 (v256hf)
+DEF_RET1_ARG9 (v512hf)
+DEF_RET1_ARG9 (v1024hf)
+DEF_RET1_ARG9 (v2048hf)
+
+/* { dg-final { scan-assembler-times {li\s+a[0-1],\s*0} 6 } } */
+/* { dg-final { scan-assembler-times {flh\s+fa[0-1],\s*[0-9]+\(sp\)} 9 } } */
+/* { dg-final { scan-assembler-times {flw\s+fa[0-1],\s*[0-9]+\(sp\)} 9 } } */
+/* { dg-final { scan-assembler-times {fsh\s+fa[0-7],\s*[0-9]+\(sp\)} 43 } } */
+/* { dg-final { scan-assembler-times {fsw\s+fa[0-7],\s*[0-9]+\(sp\)} 43 } } */
+/* { dg-final { scan-assembler-times {sd\s+a[0-7],\s*[0-9]+\(sp\)} 103 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-6.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-6.c
new file mode 100644
index 00000000000..45a9e2debe8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-6.c
@@ -0,0 +1,129 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv_zvl4096b --param riscv-autovec-preference=scalable -mabi=lp64d -O3" } */
+
+#include "def.h"
+
+DEF_RET1_ARG0 (v1sf)
+DEF_RET1_ARG0 (v2sf)
+DEF_RET1_ARG0 (v4sf)
+DEF_RET1_ARG0 (v8sf)
+DEF_RET1_ARG0 (v16sf)
+DEF_RET1_ARG0 (v32sf)
+DEF_RET1_ARG0 (v64sf)
+DEF_RET1_ARG0 (v128sf)
+DEF_RET1_ARG0 (v256sf)
+DEF_RET1_ARG0 (v512sf)
+DEF_RET1_ARG0 (v1024sf)
+
+DEF_RET1_ARG1 (v1sf)
+DEF_RET1_ARG1 (v2sf)
+DEF_RET1_ARG1 (v4sf)
+DEF_RET1_ARG1 (v8sf)
+DEF_RET1_ARG1 (v16sf)
+DEF_RET1_ARG1 (v32sf)
+DEF_RET1_ARG1 (v64sf)
+DEF_RET1_ARG1 (v128sf)
+DEF_RET1_ARG1 (v256sf)
+DEF_RET1_ARG1 (v512sf)
+DEF_RET1_ARG1 (v1024sf)
+
+DEF_RET1_ARG2 (v1sf)
+DEF_RET1_ARG2 (v2sf)
+DEF_RET1_ARG2 (v4sf)
+DEF_RET1_ARG2 (v8sf)
+DEF_RET1_ARG2 (v16sf)
+DEF_RET1_ARG2 (v32sf)
+DEF_RET1_ARG2 (v64sf)
+DEF_RET1_ARG2 (v128sf)
+DEF_RET1_ARG2 (v256sf)
+DEF_RET1_ARG2 (v512sf)
+DEF_RET1_ARG2 (v1024sf)
+
+DEF_RET1_ARG3 (v1sf)
+DEF_RET1_ARG3 (v2sf)
+DEF_RET1_ARG3 (v4sf)
+DEF_RET1_ARG3 (v8sf)
+DEF_RET1_ARG3 (v16sf)
+DEF_RET1_ARG3 (v32sf)
+DEF_RET1_ARG3 (v64sf)
+DEF_RET1_ARG3 (v128sf)
+DEF_RET1_ARG3 (v256sf)
+DEF_RET1_ARG3 (v512sf)
+DEF_RET1_ARG3 (v1024sf)
+
+DEF_RET1_ARG4 (v1sf)
+DEF_RET1_ARG4 (v2sf)
+DEF_RET1_ARG4 (v4sf)
+DEF_RET1_ARG4 (v8sf)
+DEF_RET1_ARG4 (v16sf)
+DEF_RET1_ARG4 (v32sf)
+DEF_RET1_ARG4 (v64sf)
+DEF_RET1_ARG4 (v128sf)
+DEF_RET1_ARG4 (v256sf)
+DEF_RET1_ARG4 (v512sf)
+DEF_RET1_ARG4 (v1024sf)
+
+DEF_RET1_ARG5 (v1sf)
+DEF_RET1_ARG5 (v2sf)
+DEF_RET1_ARG5 (v4sf)
+DEF_RET1_ARG5 (v8sf)
+DEF_RET1_ARG5 (v16sf)
+DEF_RET1_ARG5 (v32sf)
+DEF_RET1_ARG5 (v64sf)
+DEF_RET1_ARG5 (v128sf)
+DEF_RET1_ARG5 (v256sf)
+DEF_RET1_ARG5 (v512sf)
+DEF_RET1_ARG5 (v1024sf)
+
+DEF_RET1_ARG6 (v1sf)
+DEF_RET1_ARG6 (v2sf)
+DEF_RET1_ARG6 (v4sf)
+DEF_RET1_ARG6 (v8sf)
+DEF_RET1_ARG6 (v16sf)
+DEF_RET1_ARG6 (v32sf)
+DEF_RET1_ARG6 (v64sf)
+DEF_RET1_ARG6 (v128sf)
+DEF_RET1_ARG6 (v256sf)
+DEF_RET1_ARG6 (v512sf)
+DEF_RET1_ARG6 (v1024sf)
+
+DEF_RET1_ARG7 (v1sf)
+DEF_RET1_ARG7 (v2sf)
+DEF_RET1_ARG7 (v4sf)
+DEF_RET1_ARG7 (v8sf)
+DEF_RET1_ARG7 (v16sf)
+DEF_RET1_ARG7 (v32sf)
+DEF_RET1_ARG7 (v64sf)
+DEF_RET1_ARG7 (v128sf)
+DEF_RET1_ARG7 (v256sf)
+DEF_RET1_ARG7 (v512sf)
+DEF_RET1_ARG7 (v1024sf)
+
+DEF_RET1_ARG8 (v1sf)
+DEF_RET1_ARG8 (v2sf)
+DEF_RET1_ARG8 (v4sf)
+DEF_RET1_ARG8 (v8sf)
+DEF_RET1_ARG8 (v16sf)
+DEF_RET1_ARG8 (v32sf)
+DEF_RET1_ARG8 (v64sf)
+DEF_RET1_ARG8 (v128sf)
+DEF_RET1_ARG8 (v256sf)
+DEF_RET1_ARG8 (v512sf)
+DEF_RET1_ARG8 (v1024sf)
+
+DEF_RET1_ARG9 (v1sf)
+DEF_RET1_ARG9 (v2sf)
+DEF_RET1_ARG9 (v4sf)
+DEF_RET1_ARG9 (v8sf)
+DEF_RET1_ARG9 (v16sf)
+DEF_RET1_ARG9 (v32sf)
+DEF_RET1_ARG9 (v64sf)
+DEF_RET1_ARG9 (v128sf)
+DEF_RET1_ARG9 (v256sf)
+DEF_RET1_ARG9 (v512sf)
+DEF_RET1_ARG9 (v1024sf)
+
+/* { dg-final { scan-assembler-times {li\s+a[0-1],\s*0} 5 } } */
+/* { dg-final { scan-assembler-times {flw\s+fa[0-1],\s*[0-9]+\(sp\)} 9 } } */
+/* { dg-final { scan-assembler-times {fsw\s+fa[0-7],\s*[0-9]+\(sp\)} 43 } } */
+/* { dg-final { scan-assembler-times {sd\s+a[0-7],\s*[0-9]+\(sp\)} 60 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-7.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-7.c
new file mode 100644
index 00000000000..a607786afea
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-7.c
@@ -0,0 +1,120 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv_zvl4096b --param riscv-autovec-preference=scalable -mabi=lp64d -O3" } */
+
+#include "def.h"
+
+DEF_RET1_ARG0 (v1df)
+DEF_RET1_ARG0 (v2df)
+DEF_RET1_ARG0 (v4df)
+DEF_RET1_ARG0 (v8df)
+DEF_RET1_ARG0 (v16df)
+DEF_RET1_ARG0 (v32df)
+DEF_RET1_ARG0 (v64df)
+DEF_RET1_ARG0 (v128df)
+DEF_RET1_ARG0 (v256df)
+DEF_RET1_ARG0 (v512df)
+
+DEF_RET1_ARG1 (v1df)
+DEF_RET1_ARG1 (v2df)
+DEF_RET1_ARG1 (v4df)
+DEF_RET1_ARG1 (v8df)
+DEF_RET1_ARG1 (v16df)
+DEF_RET1_ARG1 (v32df)
+DEF_RET1_ARG1 (v64df)
+DEF_RET1_ARG1 (v128df)
+DEF_RET1_ARG1 (v256df)
+DEF_RET1_ARG1 (v512df)
+
+DEF_RET1_ARG2 (v1df)
+DEF_RET1_ARG2 (v2df)
+DEF_RET1_ARG2 (v4df)
+DEF_RET1_ARG2 (v8df)
+DEF_RET1_ARG2 (v16df)
+DEF_RET1_ARG2 (v32df)
+DEF_RET1_ARG2 (v64df)
+DEF_RET1_ARG2 (v128df)
+DEF_RET1_ARG2 (v256df)
+DEF_RET1_ARG2 (v512df)
+
+DEF_RET1_ARG3 (v1df)
+DEF_RET1_ARG3 (v2df)
+DEF_RET1_ARG3 (v4df)
+DEF_RET1_ARG3 (v8df)
+DEF_RET1_ARG3 (v16df)
+DEF_RET1_ARG3 (v32df)
+DEF_RET1_ARG3 (v64df)
+DEF_RET1_ARG3 (v128df)
+DEF_RET1_ARG3 (v256df)
+DEF_RET1_ARG3 (v512df)
+
+DEF_RET1_ARG4 (v1df)
+DEF_RET1_ARG4 (v2df)
+DEF_RET1_ARG4 (v4df)
+DEF_RET1_ARG4 (v8df)
+DEF_RET1_ARG4 (v16df)
+DEF_RET1_ARG4 (v32df)
+DEF_RET1_ARG4 (v64df)
+DEF_RET1_ARG4 (v128df)
+DEF_RET1_ARG4 (v256df)
+DEF_RET1_ARG4 (v512df)
+
+DEF_RET1_ARG5 (v1df)
+DEF_RET1_ARG5 (v2df)
+DEF_RET1_ARG5 (v4df)
+DEF_RET1_ARG5 (v8df)
+DEF_RET1_ARG5 (v16df)
+DEF_RET1_ARG5 (v32df)
+DEF_RET1_ARG5 (v64df)
+DEF_RET1_ARG5 (v128df)
+DEF_RET1_ARG5 (v256df)
+DEF_RET1_ARG5 (v512df)
+
+DEF_RET1_ARG6 (v1df)
+DEF_RET1_ARG6 (v2df)
+DEF_RET1_ARG6 (v4df)
+DEF_RET1_ARG6 (v8df)
+DEF_RET1_ARG6 (v16df)
+DEF_RET1_ARG6 (v32df)
+DEF_RET1_ARG6 (v64df)
+DEF_RET1_ARG6 (v128df)
+DEF_RET1_ARG6 (v256df)
+DEF_RET1_ARG6 (v512df)
+
+DEF_RET1_ARG7 (v1df)
+DEF_RET1_ARG7 (v2df)
+DEF_RET1_ARG7 (v4df)
+DEF_RET1_ARG7 (v8df)
+DEF_RET1_ARG7 (v16df)
+DEF_RET1_ARG7 (v32df)
+DEF_RET1_ARG7 (v64df)
+DEF_RET1_ARG7 (v128df)
+DEF_RET1_ARG7 (v256df)
+DEF_RET1_ARG7 (v512df)
+
+DEF_RET1_ARG8 (v1df)
+DEF_RET1_ARG8 (v2df)
+DEF_RET1_ARG8 (v4df)
+DEF_RET1_ARG8 (v8df)
+DEF_RET1_ARG8 (v16df)
+DEF_RET1_ARG8 (v32df)
+DEF_RET1_ARG8 (v64df)
+DEF_RET1_ARG8 (v128df)
+DEF_RET1_ARG8 (v256df)
+DEF_RET1_ARG8 (v512df)
+
+DEF_RET1_ARG9 (v1df)
+DEF_RET1_ARG9 (v2df)
+DEF_RET1_ARG9 (v4df)
+DEF_RET1_ARG9 (v8df)
+DEF_RET1_ARG9 (v16df)
+DEF_RET1_ARG9 (v32df)
+DEF_RET1_ARG9 (v64df)
+DEF_RET1_ARG9 (v128df)
+DEF_RET1_ARG9 (v256df)
+DEF_RET1_ARG9 (v512df)
+
+/* { dg-final { scan-assembler-times {li\s+a[0-1],\s*0} 5 } } */
+/* { dg-final { scan-assembler-times {ld\s+a[0-1],\s*[0-9]+\(sp\)} 21 } } */
+/* { dg-final { scan-assembler-times {fld\s+fa[0-1],\s*[0-9]+\(sp\)} 9 } } */
+/* { dg-final { scan-assembler-times {sd\s+a[0-7],\s*[0-9]+\(sp\)} 60 } } */
+/* { dg-final { scan-assembler-times {fsd\s+fa[0-7],\s*[0-9]+\(sp\)} 43 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-8.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-8.c
new file mode 100644
index 00000000000..ed66a2cb9eb
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-8.c
@@ -0,0 +1,43 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv_zvl4096b -mabi=lp64d --param riscv-autovec-preference=scalable -O3 -fno-schedule-insns -fno-schedule-insns2" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include "def.h"
+
+/*
+** v8qi_RET1_ARG0:
+** li\s+a0,\s*0
+** ret
+*/
+DEF_RET1_ARG0 (v8qi)
+
+/*
+** v4hi_RET1_ARG1:
+** ret
+*/
+DEF_RET1_ARG1 (v4hi)
+
+/*
+** v2si_RET1_ARG2:
+** addi\s+sp,\s*sp,\s*-16
+** sd\s+a0,\s*0\(sp\)
+** sd\s+a1,\s*8\(sp\)
+** ...
+** ld\s+a0,\s*0\(sp\)
+** addi\s+sp,\s*sp,\s*16
+** jr\s+ra
+*/
+DEF_RET1_ARG2 (v2si)
+
+/*
+** v1di_RET1_ARG3:
+** addi\s+sp,\s*sp,\s*-32
+** sd\s+a0,\s*8\(sp\)
+** sd\s+a1,\s*16\(sp\)
+** sd\s+a2,\s*24\(sp\)
+** ...
+** ld\s+a0,\s*8\(sp\)
+** addi\s+sp,\s*sp,\s*32
+** jr\s+ra
+*/
+DEF_RET1_ARG3 (v1di)
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-9.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-9.c
new file mode 100644
index 00000000000..dd8e709ee59
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-9.c
@@ -0,0 +1,51 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv_zvfh_zvl4096b -mabi=lp64d --param riscv-autovec-preference=scalable -O3 -fno-schedule-insns -fno-schedule-insns2" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include "def.h"
+
+/*
+** v4hf_RET1_ARG1:
+** ret
+*/
+DEF_RET1_ARG1 (v4hf)
+
+/*
+** v2sf_RET1_ARG2:
+** addi\s+sp,\s*sp,\s*-16
+** fsd\s+fa0,\s*0\(sp\)
+** fsd\s+fa1,\s*8\(sp\)
+** ...
+** fld\s+fa0,\s*0\(sp\)
+** addi\s+sp,\s*sp,\s*16
+** jr\s+ra
+*/
+DEF_RET1_ARG2 (v2sf)
+
+/*
+** v4sf_RET1_ARG2:
+** addi\s+sp,\s*sp,\s*-32
+** sd\s+a0,\s*0\(sp\)
+** sd\s+a1,\s*8\(sp\)
+** sd\s+a2,\s*16\(sp\)
+** sd\s+a3,\s*24\(sp\)
+** ...
+** ld\s+a0,\s*0\(sp\)
+** ld\s+a1,\s*8\(sp\)
+** addi\s+sp,\s*sp,\s*32
+** jr\s+ra
+*/
+DEF_RET1_ARG2 (v4sf)
+
+/*
+** v1df_RET1_ARG3:
+** addi\s+sp,\s*sp,\s*-32
+** fsd\s+fa0,\s*8\(sp\)
+** fsd\s+fa1,\s*16\(sp\)
+** fsd\s+fa2,\s*24\(sp\)
+** ...
+** fld\s+fa0,\s*8\(sp\)
+** addi\s+sp,\s*sp,\s*32
+** jr\s+ra
+*/
+DEF_RET1_ARG3 (v1df)
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-run-1.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-run-1.c
new file mode 100644
index 00000000000..d8aa5c51cac
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-run-1.c
@@ -0,0 +1,55 @@
+/* { dg-do run { target { riscv_v } } } */
+/* { dg-additional-options "-std=c99 -fno-vect-cost-model --param=riscv-autovec-preference=scalable" } */
+
+typedef char v16qi __attribute__ ((vector_size (16)));
+
+v16qi
+add (v16qi a1, v16qi a2, v16qi a3, v16qi a4, v16qi a5, v16qi a6, v16qi a7,
+     v16qi a8, v16qi a9)
+{
+  return a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8 + a9;
+}
+
+int
+main ()
+{
+  v16qi a1 = {
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  };
+  v16qi a2 = {
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  };
+  v16qi a3 = {
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  };
+  v16qi a4 = {
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  };
+  v16qi a5 = {
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  };
+  v16qi a6 = {
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  };
+  v16qi a7 = {
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  };
+  v16qi a8 = {
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  };
+  v16qi a9 = {
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  };
+  v16qi expected = {
+    9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+  };
+  v16qi result = add (a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+  unsigned i;
+
+  for (i = 0; i < 16; i++)
+    if (result[i] != expected[i])
+      __builtin_abort ();
+
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-run-2.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-run-2.c
new file mode 100644
index 00000000000..57376a3924c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-run-2.c
@@ -0,0 +1,55 @@
+/* { dg-do run { target { riscv_v } } } */
+/* { dg-additional-options "-std=c99 -fno-vect-cost-model --param=riscv-autovec-preference=scalable" } */
+
+typedef short v8hi __attribute__ ((vector_size (16)));
+
+v8hi
+add (v8hi a1, v8hi a2, v8hi a3, v8hi a4, v8hi a5, v8hi a6, v8hi a7,
+     v8hi a8, v8hi a9)
+{
+  return a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8 + a9;
+}
+
+int
+main ()
+{
+  v8hi a1 = {
+    1, 1, 1, 1, 1, 1, 1, 1,
+  };
+  v8hi a2 = {
+    1, 1, 1, 1, 1, 1, 1, 1,
+  };
+  v8hi a3 = {
+    1, 1, 1, 1, 1, 1, 1, 1,
+  };
+  v8hi a4 = {
+    1, 1, 1, 1, 1, 1, 1, 1,
+  };
+  v8hi a5 = {
+    1, 1, 1, 1, 1, 1, 1, 1,
+  };
+  v8hi a6 = {
+    1, 1, 1, 1, 1, 1, 1, 1,
+  };
+  v8hi a7 = {
+    1, 1, 1, 1, 1, 1, 1, 1,
+  };
+  v8hi a8 = {
+    1, 1, 1, 1, 1, 1, 1, 1,
+  };
+  v8hi a9 = {
+    1, 1, 1, 1, 1, 1, 1, 1,
+  };
+  v8hi expected = {
+    9, 9, 9, 9, 9, 9, 9, 9,
+  };
+  v8hi result = add (a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+  unsigned i;
+
+  for (i = 0; i < 8; i++)
+    if (result[i] != expected[i])
+      __builtin_abort ();
+
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-run-3.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-run-3.c
new file mode 100644
index 00000000000..b37cd5669d4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-run-3.c
@@ -0,0 +1,55 @@
+/* { dg-do run { target { riscv_v } } } */
+/* { dg-additional-options "-std=c99 -fno-vect-cost-model --param=riscv-autovec-preference=scalable" } */
+
+typedef int v4si __attribute__ ((vector_size (16)));
+
+v4si
+add (v4si a1, v4si a2, v4si a3, v4si a4, v4si a5, v4si a6, v4si a7,
+     v4si a8, v4si a9)
+{
+  return a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8 + a9;
+}
+
+int
+main ()
+{
+  v4si a1 = {
+    1, 1, 1, 1,
+  };
+  v4si a2 = {
+    1, 1, 1, 1,
+  };
+  v4si a3 = {
+    1, 1, 1, 1,
+  };
+  v4si a4 = {
+    1, 1, 1, 1,
+  };
+  v4si a5 = {
+    1, 1, 1, 1,
+  };
+  v4si a6 = {
+    1, 1, 1, 1,
+  };
+  v4si a7 = {
+    1, 1, 1, 1,
+  };
+  v4si a8 = {
+    1, 1, 1, 1,
+  };
+  v4si a9 = {
+    1, 1, 1, 1,
+  };
+  v4si expected = {
+    9, 9, 9, 9,
+  };
+  v4si result = add (a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+  unsigned i;
+
+  for (i = 0; i < 4; i++)
+    if (result[i] != expected[i])
+      __builtin_abort ();
+
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-run-4.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-run-4.c
new file mode 100644
index 00000000000..0788447b501
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-run-4.c
@@ -0,0 +1,55 @@
+/* { dg-do run { target { riscv_v } } } */
+/* { dg-additional-options "-std=c99 -fno-vect-cost-model --param=riscv-autovec-preference=scalable" } */
+
+typedef long long v2di __attribute__ ((vector_size (16)));
+
+v2di
+add (v2di a1, v2di a2, v2di a3, v2di a4, v2di a5, v2di a6, v2di a7,
+     v2di a8, v2di a9)
+{
+  return a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8 + a9;
+}
+
+int
+main ()
+{
+  v2di a1 = {
+    1, 1,
+  };
+  v2di a2 = {
+    1, 1,
+  };
+  v2di a3 = {
+    1, 1,
+  };
+  v2di a4 = {
+    1, 1,
+  };
+  v2di a5 = {
+    1, 1,
+  };
+  v2di a6 = {
+    1, 1,
+  };
+  v2di a7 = {
+    1, 1,
+  };
+  v2di a8 = {
+    1, 1,
+  };
+  v2di a9 = {
+    1, 1,
+  };
+  v2di expected = {
+    9, 9,
+  };
+  v2di result = add (a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+  unsigned i;
+
+  for (i = 0; i < 2; i++)
+    if (result[i] != expected[i])
+      __builtin_abort ();
+
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-run-5.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-run-5.c
new file mode 100644
index 00000000000..ec8658d6a02
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-run-5.c
@@ -0,0 +1,55 @@
+/* { dg-do run { target { riscv_v } } } */
+/* { dg-additional-options "-std=c99 -fno-vect-cost-model --param=riscv-autovec-preference=scalable" } */
+
+typedef float v4sf __attribute__ ((vector_size (16)));
+
+v4sf
+add (v4sf a1, v4sf a2, v4sf a3, v4sf a4, v4sf a5, v4sf a6, v4sf a7,
+     v4sf a8, v4sf a9)
+{
+  return a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8 + a9;
+}
+
+int
+main ()
+{
+  v4sf a1 = {
+    1.0, 1.0, 1.0, 1.0,
+  };
+  v4sf a2 = {
+    1.0, 1.0, 1.0, 1.0,
+  };
+  v4sf a3 = {
+    1.0, 1.0, 1.0, 1.0,
+  };
+  v4sf a4 = {
+    1.0, 1.0, 1.0, 1.0,
+  };
+  v4sf a5 = {
+    1.0, 1.0, 1.0, 1.0,
+  };
+  v4sf a6 = {
+    1.0, 1.0, 1.0, 1.0,
+  };
+  v4sf a7 = {
+    1.0, 1.0, 1.0, 1.0,
+  };
+  v4sf a8 = {
+    1.0, 1.0, 1.0, 1.0,
+  };
+  v4sf a9 = {
+    1.0, 1.0, 1.0, 1.0,
+  };
+  v4sf expected = {
+    9.0, 9.0, 9.0, 9.0,
+  };
+  v4sf result = add (a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+  unsigned i;
+
+  for (i = 0; i < 4; i++)
+    if (result[i] != expected[i])
+      __builtin_abort ();
+
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-run-6.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-run-6.c
new file mode 100644
index 00000000000..bbb53a1a4af
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-run-6.c
@@ -0,0 +1,55 @@
+/* { dg-do run { target { riscv_v } } } */
+/* { dg-additional-options "-std=c99 -fno-vect-cost-model --param=riscv-autovec-preference=scalable" } */
+
+typedef long long v2df __attribute__ ((vector_size (16)));
+
+v2df
+add (v2df a1, v2df a2, v2df a3, v2df a4, v2df a5, v2df a6, v2df a7,
+     v2df a8, v2df a9)
+{
+  return a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8 + a9;
+}
+
+int
+main ()
+{
+  v2df a1 = {
+    1.0, 1.0,
+  };
+  v2df a2 = {
+    1.0, 1.0,
+  };
+  v2df a3 = {
+    1.0, 1.0,
+  };
+  v2df a4 = {
+    1.0, 1.0,
+  };
+  v2df a5 = {
+    1.0, 1.0,
+  };
+  v2df a6 = {
+    1.0, 1.0,
+  };
+  v2df a7 = {
+    1.0, 1.0,
+  };
+  v2df a8 = {
+    1.0, 1.0,
+  };
+  v2df a9 = {
+    1.0, 1.0,
+  };
+  v2df expected = {
+    9.0, 9.0,
+  };
+  v2df result = add (a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+  unsigned i;
+
+  for (i = 0; i < 2; i++)
+    if (result[i] != expected[i])
+      __builtin_abort ();
+
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/def.h b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/def.h
index cb7a1c97ded..ef55c4d7ecf 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/def.h
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/def.h
@@ -860,3 +860,77 @@ typedef double v512df __attribute__ ((vector_size (4096)));
     TYPE1 v = {__VA_ARGS__};                                                   \
     *(TYPE1 *) out = v;                                                        \
   }
+
+#define DEF_RET1_ARG0(TYPE)                                                    \
+  TYPE __attribute__((noinline))                                               \
+  TYPE##_RET1_ARG0 ()                                                          \
+  {                                                                            \
+    TYPE r = {};                                                               \
+    return r;                                                                  \
+  }
+
+#define DEF_RET1_ARG1(TYPE)                                                    \
+  TYPE __attribute__((noinline))                                               \
+  TYPE##_RET1_ARG1 (TYPE a1)                                                   \
+  {                                                                            \
+    return a1;                                                                 \
+  }
+
+#define DEF_RET1_ARG2(TYPE)                                                    \
+  TYPE __attribute__((noinline))                                               \
+  TYPE##_RET1_ARG2 (TYPE a1, TYPE a2)                                          \
+  {                                                                            \
+    return a1 + a2;                                                            \
+  }
+
+#define DEF_RET1_ARG3(TYPE)                                                    \
+  TYPE __attribute__((noinline))                                               \
+  TYPE##_RET1_ARG3 (TYPE a1, TYPE a2, TYPE a3)                                 \
+  {                                                                            \
+    return a1 + a2 + a3;                                                       \
+  }
+
+#define DEF_RET1_ARG4(TYPE)                                                    \
+  TYPE __attribute__((noinline))                                               \
+  TYPE##_RET1_ARG4 (TYPE a1, TYPE a2, TYPE a3, TYPE a4)                        \
+  {                                                                            \
+    return a1 + a2 + a3 + a4;                                                  \
+  }
+
+#define DEF_RET1_ARG5(TYPE)                                                    \
+  TYPE __attribute__((noinline))                                               \
+  TYPE##_RET1_ARG5 (TYPE a1, TYPE a2, TYPE a3, TYPE a4, TYPE a5)               \
+  {                                                                            \
+    return a1 + a2 + a3 + a4 + a5;                                             \
+  }
+
+#define DEF_RET1_ARG6(TYPE)                                                    \
+  TYPE __attribute__((noinline))                                               \
+  TYPE##_RET1_ARG6 (TYPE a1, TYPE a2, TYPE a3, TYPE a4, TYPE a5, TYPE a6)      \
+  {                                                                            \
+    return a1 + a2 + a3 + a4 + a5 + a6;                                        \
+  }
+
+#define DEF_RET1_ARG7(TYPE)                                                    \
+  TYPE __attribute__((noinline))                                               \
+  TYPE##_RET1_ARG7 (TYPE a1, TYPE a2, TYPE a3, TYPE a4, TYPE a5, TYPE a6,      \
+		    TYPE a7)                                                   \
+  {                                                                            \
+    return a1 + a2 + a3 + a4 + a5 + a6 + a7;                                   \
+  }
+
+#define DEF_RET1_ARG8(TYPE)                                                    \
+  TYPE __attribute__((noinline))                                               \
+  TYPE##_RET1_ARG8 (TYPE a1, TYPE a2, TYPE a3, TYPE a4, TYPE a5, TYPE a6,      \
+		    TYPE a7, TYPE a8)                                          \
+  {                                                                            \
+    return a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8;                              \
+  }
+
+#define DEF_RET1_ARG9(TYPE)                                                    \
+  TYPE __attribute__((noinline))                                               \
+  TYPE##_RET1_ARG9 (TYPE a1, TYPE a2, TYPE a3, TYPE a4, TYPE a5, TYPE a6,      \
+		    TYPE a7, TYPE a8, TYPE a9)                                 \
+  {                                                                            \
+    return a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8 + a9;                         \
+  }
-- 
2.34.1


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

* Re: [PATCH v1] RISC-V: Bugfix for vls integer mode calling convention
  2024-01-24  3:16 [PATCH v1] RISC-V: Bugfix for vls integer mode calling convention pan2.li
@ 2024-01-24  3:18 ` juzhe.zhong
  2024-01-24  3:41   ` Li, Pan2
  2024-01-29 13:22 ` Kito Cheng
  2024-01-30  8:37 ` [PATCH v2] RISC-V: Bugfix for vls mode aggregated in GPR " pan2.li
  2 siblings, 1 reply; 10+ messages in thread
From: juzhe.zhong @ 2024-01-24  3:18 UTC (permalink / raw)
  To: pan2.li, gcc-patches; +Cc: pan2.li, yanzhang.wang, kito.cheng

[-- Attachment #1: Type: text/plain, Size: 57320 bytes --]

>> After this patch:
>>add:
>>  addi     sp,sp,-32
>>  sd       a0,0(sp)  <== arg by register a0 - a3
>>  sd       a1,8(sp)
>>  sd       a2,16(sp)
>>  sd       a3,24(sp)
>>  addi     a5,sp,16
>>  vsetivli zero,8,e16,m1,ta,ma
>>  vle16.v  v2,0(sp)
>>  vle16.v  v1,0(a5)
 >> vadd.vv  v1,v1,v2
>>  vse16.v  v1,0(sp)
>>  ld       a0,0(sp)  <== return by a0 - a1.
>>  ld       a1,8(sp)
>>  addi     sp,sp,32
>>  jr       ra

But clang is :

        vsetivli        zero, 2, e64, m1, ta, ma
        vmv.v.x v8, a0
        vslide1down.vx  v8, v8, a1
        vmv.v.x v9, a2
        vslide1down.vx  v9, v9, a3
        vsetivli        zero, 8, e16, m1, ta, ma
        vadd.vv v8, v9, v8
        vsetivli        zero, 1, e64, m1, ta, ma
        vmv.x.s a0, v8
        vslidedown.vi   v8, v8, 1
        vmv.x.s a1, v8
        ret



juzhe.zhong@rivai.ai
 
From: pan2.li
Date: 2024-01-24 11:16
To: gcc-patches
CC: juzhe.zhong; pan2.li; yanzhang.wang; kito.cheng
Subject: [PATCH v1] RISC-V: Bugfix for vls integer mode calling convention
From: Pan Li <pan2.li@intel.com>
 
According to the issue as below.
 
https://hub.fgit.cf/riscv-non-isa/riscv-elf-psabi-doc/pull/416
 
When the mode size of vls integer mode is less than 2 * XLEN, we will
take the gpr/fpr for both the args and the return values. Instead of
the reference. For example the below code:
 
typedef short v8hi __attribute__ ((vector_size (16)));
 
v8hi __attribute__((noinline))
add (v8hi a, v8hi b)
{
  v8hi r = a + b;
  return r;
}
 
Before this patch:
add:
  vsetivli zero,8,e16,m1,ta,ma
  vle16.v  v1,0(a1) <== arg by reference
  vle16.v  v2,0(a2) <== arg by reference
  vadd.vv  v1,v1,v2
  vse16.v  v1,0(a0) <== return by reference
  ret
 
After this patch:
add:
  addi     sp,sp,-32
  sd       a0,0(sp)  <== arg by register a0 - a3
  sd       a1,8(sp)
  sd       a2,16(sp)
  sd       a3,24(sp)
  addi     a5,sp,16
  vsetivli zero,8,e16,m1,ta,ma
  vle16.v  v2,0(sp)
  vle16.v  v1,0(a5)
  vadd.vv  v1,v1,v2
  vse16.v  v1,0(sp)
  ld       a0,0(sp)  <== return by a0 - a1.
  ld       a1,8(sp)
  addi     sp,sp,32
  jr       ra
 
For vls floating point, the things get more complicated.  We follow
the below rules.
 
1. Vls element count <= 2 and vls size <= 2 * xlen, go fpr.
2. Vls size <= 2 * xlen, go gpr.
3. Vls size > 2 * xlen, go reference.
 
One exceptions is V2DF mode, we treat vls mode as aggregated and we will
have TFmode here.  Unforturnately, the emit_move_multi_word cannot take
care of TFmode elegantly and we go to gpr for V2DF mode.
 
The riscv regression passed for this patch.
 
gcc/ChangeLog:
 
* config/riscv/riscv.cc (riscv_v_ext_vector_or_tuple_mode_p):
New predicate function for vector or tuple vector.
(riscv_v_vls_mode_aggregate_reg_count): New function to
calculate the gpr/fpr count required by vls mode.
(riscv_gpr_unit_size): New function to get gpr in bytes.
(riscv_fpr_unit_size): New function to get fpr in bytes.
(riscv_v_vls_to_gpr_mode): New function convert vls mode to gpr mode.
(riscv_v_vls_to_fpr_mode): New function convert vls mode to fpr mode.
(riscv_pass_vls_aggregate_in_gpr_or_fpr): New function to return
the rtx of gpr/fpr for vls mode.
(riscv_mode_pass_by_reference_p): New predicate function to
indicate the mode will be passed by reference or not.
(riscv_get_arg_info): Add vls mode handling.
(riscv_pass_by_reference): Return false if arg info has no zero
gpr count.
 
gcc/testsuite/ChangeLog:
 
* gcc.target/riscv/rvv/autovec/vls/def.h: Add helper marcos.
* gcc.target/riscv/rvv/autovec/vls/calling-convention-1.c: New test.
* gcc.target/riscv/rvv/autovec/vls/calling-convention-10.c: New test.
* gcc.target/riscv/rvv/autovec/vls/calling-convention-2.c: New test.
* gcc.target/riscv/rvv/autovec/vls/calling-convention-3.c: New test.
* gcc.target/riscv/rvv/autovec/vls/calling-convention-4.c: New test.
* gcc.target/riscv/rvv/autovec/vls/calling-convention-5.c: New test.
* gcc.target/riscv/rvv/autovec/vls/calling-convention-6.c: New test.
* gcc.target/riscv/rvv/autovec/vls/calling-convention-7.c: New test.
* gcc.target/riscv/rvv/autovec/vls/calling-convention-8.c: New test.
* gcc.target/riscv/rvv/autovec/vls/calling-convention-9.c: New test.
* gcc.target/riscv/rvv/autovec/vls/calling-convention-run-1.c: New test.
* gcc.target/riscv/rvv/autovec/vls/calling-convention-run-2.c: New test.
* gcc.target/riscv/rvv/autovec/vls/calling-convention-run-3.c: New test.
* gcc.target/riscv/rvv/autovec/vls/calling-convention-run-4.c: New test.
* gcc.target/riscv/rvv/autovec/vls/calling-convention-run-5.c: New test.
* gcc.target/riscv/rvv/autovec/vls/calling-convention-run-6.c: New test.
 
Signed-off-by: Pan Li <pan2.li@intel.com>
---
gcc/config/riscv/riscv.cc                     | 185 +++++++++++++++++-
.../rvv/autovec/vls/calling-convention-1.c    | 154 +++++++++++++++
.../rvv/autovec/vls/calling-convention-10.c   |  51 +++++
.../rvv/autovec/vls/calling-convention-2.c    | 142 ++++++++++++++
.../rvv/autovec/vls/calling-convention-3.c    | 130 ++++++++++++
.../rvv/autovec/vls/calling-convention-4.c    | 118 +++++++++++
.../rvv/autovec/vls/calling-convention-5.c    | 141 +++++++++++++
.../rvv/autovec/vls/calling-convention-6.c    | 129 ++++++++++++
.../rvv/autovec/vls/calling-convention-7.c    | 120 ++++++++++++
.../rvv/autovec/vls/calling-convention-8.c    |  43 ++++
.../rvv/autovec/vls/calling-convention-9.c    |  51 +++++
.../autovec/vls/calling-convention-run-1.c    |  55 ++++++
.../autovec/vls/calling-convention-run-2.c    |  55 ++++++
.../autovec/vls/calling-convention-run-3.c    |  55 ++++++
.../autovec/vls/calling-convention-run-4.c    |  55 ++++++
.../autovec/vls/calling-convention-run-5.c    |  55 ++++++
.../autovec/vls/calling-convention-run-6.c    |  55 ++++++
.../gcc.target/riscv/rvv/autovec/vls/def.h    |  74 +++++++
18 files changed, 1665 insertions(+), 3 deletions(-)
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-1.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-10.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-2.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-3.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-4.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-5.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-6.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-7.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-8.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-9.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-run-1.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-run-2.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-run-3.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-run-4.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-run-5.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-run-6.c
 
diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 3ba45ffaa74..fb79a475bbe 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -1382,6 +1382,106 @@ riscv_v_ext_mode_p (machine_mode mode)
|| riscv_v_ext_vls_mode_p (mode);
}
+/* Return true if it is either of below modes.
+   1. RVV vector mode.
+   2. RVV tuple mode.  */
+
+static bool
+riscv_v_ext_vector_or_tuple_mode_p (machine_mode mode)
+{
+  return riscv_v_ext_vector_mode_p (mode) || riscv_v_ext_tuple_mode_p (mode);
+}
+
+static unsigned
+riscv_v_vls_mode_aggregate_reg_count (unsigned vls_unit_size,
+       unsigned scalar_unit_size)
+{
+  gcc_assert (vls_unit_size != 0 && scalar_unit_size != 0);
+
+  if (vls_unit_size < scalar_unit_size)
+    return 1;
+
+  return vls_unit_size / scalar_unit_size;
+}
+
+static unsigned short
+riscv_gpr_unit_size ()
+{
+  return GET_MODE_SIZE (Xmode);
+}
+
+static unsigned short
+riscv_fpr_unit_size ()
+{
+  unsigned fpr_size = 0;
+
+  if (TARGET_HARD_FLOAT && !TARGET_DOUBLE_FLOAT)
+    {
+      switch (riscv_abi)
+ {
+   case ABI_LP64F:
+   case ABI_ILP32F:
+     fpr_size = GET_MODE_SIZE (SFmode);
+     break;
+ }
+    }
+
+  if (TARGET_DOUBLE_FLOAT)
+    {
+      switch (riscv_abi)
+ {
+   case ABI_LP64F:
+   case ABI_ILP32F:
+     fpr_size = GET_MODE_SIZE (SFmode);
+     break;
+   case ABI_LP64D:
+   case ABI_ILP32D:
+     fpr_size = GET_MODE_SIZE (DFmode);
+     break;
+ }
+    }
+
+  return fpr_size;
+}
+
+static machine_mode
+riscv_v_vls_to_gpr_mode (unsigned vls_mode_size)
+{
+  switch (vls_mode_size)
+    {
+      case 16:
+ return TImode;
+      case 8:
+ return DImode;
+      case 4:
+ return SImode;
+      case 2:
+ return HImode;
+      case 1:
+ return QImode;
+      default:
+ gcc_unreachable ();
+    }
+}
+
+static machine_mode
+riscv_v_vls_to_fpr_mode (unsigned vls_mode_size)
+{
+  switch (vls_mode_size)
+    {
+      case 16:
+ return TFmode;
+      case 8:
+ return DFmode;
+      case 4:
+ return SFmode;
+      case 2:
+ return HFmode;
+      default:
+ gcc_unreachable ();
+    }
+}
+
/* Call from ADJUST_NUNITS in riscv-modes.def. Return the correct
    NUNITS size for corresponding machine_mode.  */
@@ -4868,6 +4968,63 @@ riscv_pass_fpr_pair (machine_mode mode, unsigned regno1,
   GEN_INT (offset2))));
}
+static rtx
+riscv_pass_vls_aggregate_in_gpr_or_fpr (struct riscv_arg_info *info,
+ machine_mode mode, unsigned gpr_base,
+ unsigned fpr_base)
+{
+  gcc_assert (riscv_v_ext_vls_mode_p (mode));
+
+  unsigned vls_size = GET_MODE_SIZE (mode).to_constant ();
+  unsigned gpr_size = riscv_gpr_unit_size ();
+  unsigned fpr_size = riscv_fpr_unit_size ();
+  unsigned regnum = 0, count = 0;
+  unsigned vls_elem_count = vls_size / GET_MODE_SIZE (GET_MODE_INNER (mode));
+  machine_mode smode = VOIDmode;
+
+  /* For vls floating point >= 16 bytes, it cannot be well token care of when
+     emit_move_multi_word.  For example vls size == 16 bytes when move multi
+     word.  We will hit assert similar to gcc_assert (xpart && ypart).
+     x=(reg:TF 42 fa0)
+     y=(subreg:TF (reg:TI 136) 0)
+
+     Thus, we will go with gpr for vls size >= 16.
+  */
+  if (vls_elem_count <= 2 && FLOAT_MODE_P (mode) && fpr_size && vls_size < 16
+    && IN_RANGE (vls_size, 0, fpr_size * 2))
+    {
+      count = riscv_v_vls_mode_aggregate_reg_count (vls_size, fpr_size);
+
+      if (count + info->fpr_offset <= MAX_ARGS_IN_REGISTERS)
+ {
+   regnum = fpr_base + info->fpr_offset;
+   info->num_fprs = count;
+   smode = riscv_v_vls_to_fpr_mode (vls_size);
+ }
+    }
+  else if (IN_RANGE (vls_size, 0, gpr_size * 2))
+    {
+      count = riscv_v_vls_mode_aggregate_reg_count (vls_size, gpr_size);
+
+      if (count + info->gpr_offset <= MAX_ARGS_IN_REGISTERS)
+ {
+   regnum = gpr_base + info->gpr_offset;
+   info->num_gprs = count;
+   smode = riscv_v_vls_to_gpr_mode (vls_size);
+ }
+    }
+
+  if (!regnum)
+    return NULL_RTX; /* Return NULL_RTX if we cannot find a suitable reg.  */
+
+  gcc_assert (smode != VOIDmode);
+
+  rtx reg = gen_rtx_REG (smode, regnum);
+  rtx x = gen_rtx_EXPR_LIST (VOIDmode, reg, CONST0_RTX (smode));
+
+  return gen_rtx_PARALLEL (mode, gen_rtvec (1, x));
+}
+
/* Initialize a variable CUM of type CUMULATIVE_ARGS
    for a call to a function whose data type is FNTYPE.
    For a library call, FNTYPE is 0.  */
@@ -4975,6 +5132,22 @@ riscv_get_vector_arg (struct riscv_arg_info *info, const CUMULATIVE_ARGS *cum,
   return NULL_RTX;
}
+/* Return true if the argument mode is passed by reference. Aka:
+   1. Scalable vector argument is anonymous.
+   2. The vector abi is disabled for vector or tuple mode.
+   Else return false.  */
+static bool
+riscv_mode_pass_by_reference_p (machine_mode mode, bool named)
+{
+  if (riscv_v_ext_mode_p (mode) && !named)
+    return true;
+
+  if (riscv_v_ext_vector_or_tuple_mode_p (mode) && !riscv_vector_abi)
+    return true;
+
+  return false;
+}
+
/* Fill INFO with information about a single argument, and return an RTL
    pattern to pass or return the argument. Return NULL_RTX if argument cannot
    pass or return in registers, then the argument may be passed by reference or
@@ -4997,9 +5170,7 @@ riscv_get_arg_info (struct riscv_arg_info *info, const CUMULATIVE_ARGS *cum,
   info->gpr_offset = cum->num_gprs;
   info->fpr_offset = cum->num_fprs;
-  /* When disable vector_abi or scalable vector argument is anonymous, this
-     argument is passed by reference.  */
-  if (riscv_v_ext_mode_p (mode) && (!riscv_vector_abi || !named))
+  if (riscv_mode_pass_by_reference_p (mode, named))
     return NULL_RTX;
   if (named)
@@ -5064,6 +5235,10 @@ riscv_get_arg_info (struct riscv_arg_info *info, const CUMULATIVE_ARGS *cum,
      fields[1].offset);
}
+      if (riscv_v_ext_vls_mode_p (mode))
+ return riscv_pass_vls_aggregate_in_gpr_or_fpr (info, mode, gpr_base,
+        fpr_base);
+
       /* For scalable vector argument.  */
       if (riscv_vector_type_p (type) && riscv_v_ext_mode_p (mode))
return riscv_get_vector_arg (info, cum, mode, return_p);
@@ -5196,6 +5371,10 @@ riscv_pass_by_reference (cumulative_args_t cum_v, const function_arg_info &arg)
       if (info.num_fprs)
return false;
+      /* Don't pass by reference if we can use general register(s) for vls.  */
+      if (info.num_gprs && riscv_v_ext_vls_mode_p (arg.mode))
+ return false;
+
       /* Don't pass by reference if we can use vector register groups.  */
       if (info.num_vrs > 0 || info.num_mrs > 0)
return false;
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-1.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-1.c
new file mode 100644
index 00000000000..41e31c258f8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-1.c
@@ -0,0 +1,154 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv_zvl4096b --param riscv-autovec-preference=scalable -mabi=lp64d -O3" } */
+
+#include "def.h"
+
+DEF_RET1_ARG0 (v1qi)
+DEF_RET1_ARG0 (v2qi)
+DEF_RET1_ARG0 (v4qi)
+DEF_RET1_ARG0 (v8qi)
+DEF_RET1_ARG0 (v16qi)
+DEF_RET1_ARG0 (v32qi)
+DEF_RET1_ARG0 (v64qi)
+DEF_RET1_ARG0 (v128qi)
+DEF_RET1_ARG0 (v256qi)
+DEF_RET1_ARG0 (v512qi)
+DEF_RET1_ARG0 (v1024qi)
+DEF_RET1_ARG0 (v2048qi)
+DEF_RET1_ARG0 (v4096qi)
+
+DEF_RET1_ARG1 (v1qi)
+DEF_RET1_ARG1 (v2qi)
+DEF_RET1_ARG1 (v4qi)
+DEF_RET1_ARG1 (v8qi)
+DEF_RET1_ARG1 (v16qi)
+DEF_RET1_ARG1 (v32qi)
+DEF_RET1_ARG1 (v64qi)
+DEF_RET1_ARG1 (v128qi)
+DEF_RET1_ARG1 (v256qi)
+DEF_RET1_ARG1 (v512qi)
+DEF_RET1_ARG1 (v1024qi)
+DEF_RET1_ARG1 (v2048qi)
+DEF_RET1_ARG1 (v4096qi)
+
+DEF_RET1_ARG2 (v1qi)
+DEF_RET1_ARG2 (v2qi)
+DEF_RET1_ARG2 (v4qi)
+DEF_RET1_ARG2 (v8qi)
+DEF_RET1_ARG2 (v16qi)
+DEF_RET1_ARG2 (v32qi)
+DEF_RET1_ARG2 (v64qi)
+DEF_RET1_ARG2 (v128qi)
+DEF_RET1_ARG2 (v256qi)
+DEF_RET1_ARG2 (v512qi)
+DEF_RET1_ARG2 (v1024qi)
+DEF_RET1_ARG2 (v2048qi)
+DEF_RET1_ARG2 (v4096qi)
+
+DEF_RET1_ARG3 (v1qi)
+DEF_RET1_ARG3 (v2qi)
+DEF_RET1_ARG3 (v4qi)
+DEF_RET1_ARG3 (v8qi)
+DEF_RET1_ARG3 (v16qi)
+DEF_RET1_ARG3 (v32qi)
+DEF_RET1_ARG3 (v64qi)
+DEF_RET1_ARG3 (v128qi)
+DEF_RET1_ARG3 (v256qi)
+DEF_RET1_ARG3 (v512qi)
+DEF_RET1_ARG3 (v1024qi)
+DEF_RET1_ARG3 (v2048qi)
+DEF_RET1_ARG3 (v4096qi)
+
+DEF_RET1_ARG4 (v1qi)
+DEF_RET1_ARG4 (v2qi)
+DEF_RET1_ARG4 (v4qi)
+DEF_RET1_ARG4 (v8qi)
+DEF_RET1_ARG4 (v16qi)
+DEF_RET1_ARG4 (v32qi)
+DEF_RET1_ARG4 (v64qi)
+DEF_RET1_ARG4 (v128qi)
+DEF_RET1_ARG4 (v256qi)
+DEF_RET1_ARG4 (v512qi)
+DEF_RET1_ARG4 (v1024qi)
+DEF_RET1_ARG4 (v2048qi)
+DEF_RET1_ARG4 (v4096qi)
+
+DEF_RET1_ARG5 (v1qi)
+DEF_RET1_ARG5 (v2qi)
+DEF_RET1_ARG5 (v4qi)
+DEF_RET1_ARG5 (v8qi)
+DEF_RET1_ARG5 (v16qi)
+DEF_RET1_ARG5 (v32qi)
+DEF_RET1_ARG5 (v64qi)
+DEF_RET1_ARG5 (v128qi)
+DEF_RET1_ARG5 (v256qi)
+DEF_RET1_ARG5 (v512qi)
+DEF_RET1_ARG5 (v1024qi)
+DEF_RET1_ARG5 (v2048qi)
+DEF_RET1_ARG5 (v4096qi)
+
+DEF_RET1_ARG6 (v1qi)
+DEF_RET1_ARG6 (v2qi)
+DEF_RET1_ARG6 (v4qi)
+DEF_RET1_ARG6 (v8qi)
+DEF_RET1_ARG6 (v16qi)
+DEF_RET1_ARG6 (v32qi)
+DEF_RET1_ARG6 (v64qi)
+DEF_RET1_ARG6 (v128qi)
+DEF_RET1_ARG6 (v256qi)
+DEF_RET1_ARG6 (v512qi)
+DEF_RET1_ARG6 (v1024qi)
+DEF_RET1_ARG6 (v2048qi)
+DEF_RET1_ARG6 (v4096qi)
+
+DEF_RET1_ARG7 (v1qi)
+DEF_RET1_ARG7 (v2qi)
+DEF_RET1_ARG7 (v4qi)
+DEF_RET1_ARG7 (v8qi)
+DEF_RET1_ARG7 (v16qi)
+DEF_RET1_ARG7 (v32qi)
+DEF_RET1_ARG7 (v64qi)
+DEF_RET1_ARG7 (v128qi)
+DEF_RET1_ARG7 (v256qi)
+DEF_RET1_ARG7 (v512qi)
+DEF_RET1_ARG7 (v1024qi)
+DEF_RET1_ARG7 (v2048qi)
+DEF_RET1_ARG7 (v4096qi)
+
+DEF_RET1_ARG8 (v1qi)
+DEF_RET1_ARG8 (v2qi)
+DEF_RET1_ARG8 (v4qi)
+DEF_RET1_ARG8 (v8qi)
+DEF_RET1_ARG8 (v16qi)
+DEF_RET1_ARG8 (v32qi)
+DEF_RET1_ARG8 (v64qi)
+DEF_RET1_ARG8 (v128qi)
+DEF_RET1_ARG8 (v256qi)
+DEF_RET1_ARG8 (v512qi)
+DEF_RET1_ARG8 (v1024qi)
+DEF_RET1_ARG8 (v2048qi)
+DEF_RET1_ARG8 (v4096qi)
+
+DEF_RET1_ARG9 (v1qi)
+DEF_RET1_ARG9 (v2qi)
+DEF_RET1_ARG9 (v4qi)
+DEF_RET1_ARG9 (v8qi)
+DEF_RET1_ARG9 (v16qi)
+DEF_RET1_ARG9 (v32qi)
+DEF_RET1_ARG9 (v64qi)
+DEF_RET1_ARG9 (v128qi)
+DEF_RET1_ARG9 (v256qi)
+DEF_RET1_ARG9 (v512qi)
+DEF_RET1_ARG9 (v1024qi)
+DEF_RET1_ARG9 (v2048qi)
+DEF_RET1_ARG9 (v4096qi)
+
+/* { dg-final { scan-assembler-times {li\s+a[0-1],\s*0} 9 } } */
+/* { dg-final { scan-assembler-times {lbu\s+a0,\s*[0-9]+\(sp\)} 8 } } */
+/* { dg-final { scan-assembler-times {lhu\s+a0,\s*[0-9]+\(sp\)} 8 } } */
+/* { dg-final { scan-assembler-times {lw\s+a0,\s*[0-9]+\(sp\)} 8 } } */
+/* { dg-final { scan-assembler-times {ld\s+a[0-1],\s*[0-9]+\(sp\)} 35 } } */
+/* { dg-final { scan-assembler-times {sb\s+a[0-7],\s*[0-9]+\(sp\)} 43 } } */
+/* { dg-final { scan-assembler-times {sh\s+a[0-7],\s*[0-9]+\(sp\)} 43 } } */
+/* { dg-final { scan-assembler-times {sw\s+a[0-7],\s*[0-9]+\(sp\)} 43 } } */
+/* { dg-final { scan-assembler-times {sd\s+a[0-7],\s*[0-9]+\(sp\)} 103 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-10.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-10.c
new file mode 100644
index 00000000000..0abc6cf0146
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-10.c
@@ -0,0 +1,51 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv_zvfh_zvl4096b -mabi=lp64 --param riscv-autovec-preference=scalable -O3 -fno-schedule-insns -fno-schedule-insns2" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include "def.h"
+
+/*
+** v4hf_RET1_ARG1:
+** ret
+*/
+DEF_RET1_ARG1 (v4hf)
+
+/*
+** v2sf_RET1_ARG2:
+** addi\s+sp,\s*sp,\s*-16
+** sd\s+a0,\s*0\(sp\)
+** sd\s+a1,\s*8\(sp\)
+** ...
+** ld\s+a0,\s*0\(sp\)
+** addi\s+sp,\s*sp,\s*16
+** jr\s+ra
+*/
+DEF_RET1_ARG2 (v2sf)
+
+/*
+** v4sf_RET1_ARG2:
+** addi\s+sp,\s*sp,\s*-32
+** sd\s+a0,\s*0\(sp\)
+** sd\s+a1,\s*8\(sp\)
+** sd\s+a2,\s*16\(sp\)
+** sd\s+a3,\s*24\(sp\)
+** ...
+** ld\s+a0,\s*0\(sp\)
+** ld\s+a1,\s*8\(sp\)
+** addi\s+sp,\s*sp,\s*32
+** jr\s+ra
+*/
+DEF_RET1_ARG2 (v4sf)
+
+/*
+** v1df_RET1_ARG3:
+** addi\s+sp,\s*sp,\s*-32
+** sd\s+a0,\s*8\(sp\)
+** sd\s+a1,\s*16\(sp\)
+** sd\s+a2,\s*24\(sp\)
+** ...
+** ld\s+a0,\s*8\(sp\)
+** addi\s+sp,\s*sp,\s*32
+** jr\s+ra
+*/
+DEF_RET1_ARG3 (v1df)
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-2.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-2.c
new file mode 100644
index 00000000000..8544f160e93
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-2.c
@@ -0,0 +1,142 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv_zvl4096b --param riscv-autovec-preference=scalable -mabi=lp64d -O3" } */
+
+#include "def.h"
+
+DEF_RET1_ARG0 (v1hi)
+DEF_RET1_ARG0 (v2hi)
+DEF_RET1_ARG0 (v4hi)
+DEF_RET1_ARG0 (v8hi)
+DEF_RET1_ARG0 (v16hi)
+DEF_RET1_ARG0 (v32hi)
+DEF_RET1_ARG0 (v64hi)
+DEF_RET1_ARG0 (v128hi)
+DEF_RET1_ARG0 (v256hi)
+DEF_RET1_ARG0 (v512hi)
+DEF_RET1_ARG0 (v1024hi)
+DEF_RET1_ARG0 (v2048hi)
+
+DEF_RET1_ARG1 (v1hi)
+DEF_RET1_ARG1 (v2hi)
+DEF_RET1_ARG1 (v4hi)
+DEF_RET1_ARG1 (v8hi)
+DEF_RET1_ARG1 (v16hi)
+DEF_RET1_ARG1 (v32hi)
+DEF_RET1_ARG1 (v64hi)
+DEF_RET1_ARG1 (v128hi)
+DEF_RET1_ARG1 (v256hi)
+DEF_RET1_ARG1 (v512hi)
+DEF_RET1_ARG1 (v1024hi)
+DEF_RET1_ARG1 (v2048hi)
+
+DEF_RET1_ARG2 (v1hi)
+DEF_RET1_ARG2 (v2hi)
+DEF_RET1_ARG2 (v4hi)
+DEF_RET1_ARG2 (v8hi)
+DEF_RET1_ARG2 (v16hi)
+DEF_RET1_ARG2 (v32hi)
+DEF_RET1_ARG2 (v64hi)
+DEF_RET1_ARG2 (v128hi)
+DEF_RET1_ARG2 (v256hi)
+DEF_RET1_ARG2 (v512hi)
+DEF_RET1_ARG2 (v1024hi)
+DEF_RET1_ARG2 (v2048hi)
+
+DEF_RET1_ARG3 (v1hi)
+DEF_RET1_ARG3 (v2hi)
+DEF_RET1_ARG3 (v4hi)
+DEF_RET1_ARG3 (v8hi)
+DEF_RET1_ARG3 (v16hi)
+DEF_RET1_ARG3 (v32hi)
+DEF_RET1_ARG3 (v64hi)
+DEF_RET1_ARG3 (v128hi)
+DEF_RET1_ARG3 (v256hi)
+DEF_RET1_ARG3 (v512hi)
+DEF_RET1_ARG3 (v1024hi)
+DEF_RET1_ARG3 (v2048hi)
+
+DEF_RET1_ARG4 (v1hi)
+DEF_RET1_ARG4 (v2hi)
+DEF_RET1_ARG4 (v4hi)
+DEF_RET1_ARG4 (v8hi)
+DEF_RET1_ARG4 (v16hi)
+DEF_RET1_ARG4 (v32hi)
+DEF_RET1_ARG4 (v64hi)
+DEF_RET1_ARG4 (v128hi)
+DEF_RET1_ARG4 (v256hi)
+DEF_RET1_ARG4 (v512hi)
+DEF_RET1_ARG4 (v1024hi)
+DEF_RET1_ARG4 (v2048hi)
+
+DEF_RET1_ARG5 (v1hi)
+DEF_RET1_ARG5 (v2hi)
+DEF_RET1_ARG5 (v4hi)
+DEF_RET1_ARG5 (v8hi)
+DEF_RET1_ARG5 (v16hi)
+DEF_RET1_ARG5 (v32hi)
+DEF_RET1_ARG5 (v64hi)
+DEF_RET1_ARG5 (v128hi)
+DEF_RET1_ARG5 (v256hi)
+DEF_RET1_ARG5 (v512hi)
+DEF_RET1_ARG5 (v1024hi)
+DEF_RET1_ARG5 (v2048hi)
+
+DEF_RET1_ARG6 (v1hi)
+DEF_RET1_ARG6 (v2hi)
+DEF_RET1_ARG6 (v4hi)
+DEF_RET1_ARG6 (v8hi)
+DEF_RET1_ARG6 (v16hi)
+DEF_RET1_ARG6 (v32hi)
+DEF_RET1_ARG6 (v64hi)
+DEF_RET1_ARG6 (v128hi)
+DEF_RET1_ARG6 (v256hi)
+DEF_RET1_ARG6 (v512hi)
+DEF_RET1_ARG6 (v1024hi)
+DEF_RET1_ARG6 (v2048hi)
+
+DEF_RET1_ARG7 (v1hi)
+DEF_RET1_ARG7 (v2hi)
+DEF_RET1_ARG7 (v4hi)
+DEF_RET1_ARG7 (v8hi)
+DEF_RET1_ARG7 (v16hi)
+DEF_RET1_ARG7 (v32hi)
+DEF_RET1_ARG7 (v64hi)
+DEF_RET1_ARG7 (v128hi)
+DEF_RET1_ARG7 (v256hi)
+DEF_RET1_ARG7 (v512hi)
+DEF_RET1_ARG7 (v1024hi)
+DEF_RET1_ARG7 (v2048hi)
+
+DEF_RET1_ARG8 (v1hi)
+DEF_RET1_ARG8 (v2hi)
+DEF_RET1_ARG8 (v4hi)
+DEF_RET1_ARG8 (v8hi)
+DEF_RET1_ARG8 (v16hi)
+DEF_RET1_ARG8 (v32hi)
+DEF_RET1_ARG8 (v64hi)
+DEF_RET1_ARG8 (v128hi)
+DEF_RET1_ARG8 (v256hi)
+DEF_RET1_ARG8 (v512hi)
+DEF_RET1_ARG8 (v1024hi)
+DEF_RET1_ARG8 (v2048hi)
+
+DEF_RET1_ARG9 (v1hi)
+DEF_RET1_ARG9 (v2hi)
+DEF_RET1_ARG9 (v4hi)
+DEF_RET1_ARG9 (v8hi)
+DEF_RET1_ARG9 (v16hi)
+DEF_RET1_ARG9 (v32hi)
+DEF_RET1_ARG9 (v64hi)
+DEF_RET1_ARG9 (v128hi)
+DEF_RET1_ARG9 (v256hi)
+DEF_RET1_ARG9 (v512hi)
+DEF_RET1_ARG9 (v1024hi)
+DEF_RET1_ARG9 (v2048hi)
+
+/* { dg-final { scan-assembler-times {li\s+a[0-1],\s*0} 8 } } */
+/* { dg-final { scan-assembler-times {lhu\s+a0,\s*[0-9]+\(sp\)} 8 } } */
+/* { dg-final { scan-assembler-times {lw\s+a0,\s*[0-9]+\(sp\)} 8 } } */
+/* { dg-final { scan-assembler-times {ld\s+a[0-1],\s*[0-9]+\(sp\)} 33 } } */
+/* { dg-final { scan-assembler-times {sh\s+a[0-7],\s*[0-9]+\(sp\)} 43 } } */
+/* { dg-final { scan-assembler-times {sw\s+a[0-7],\s*[0-9]+\(sp\)} 43 } } */
+/* { dg-final { scan-assembler-times {sd\s+a[0-7],\s*[0-9]+\(sp\)} 103 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-3.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-3.c
new file mode 100644
index 00000000000..17b06933c72
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-3.c
@@ -0,0 +1,130 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv_zvl4096b --param riscv-autovec-preference=scalable -mabi=lp64d -O3" } */
+
+#include "def.h"
+
+DEF_RET1_ARG0 (v1si)
+DEF_RET1_ARG0 (v2si)
+DEF_RET1_ARG0 (v4si)
+DEF_RET1_ARG0 (v8si)
+DEF_RET1_ARG0 (v16si)
+DEF_RET1_ARG0 (v32si)
+DEF_RET1_ARG0 (v64si)
+DEF_RET1_ARG0 (v128si)
+DEF_RET1_ARG0 (v256si)
+DEF_RET1_ARG0 (v512si)
+DEF_RET1_ARG0 (v1024si)
+
+DEF_RET1_ARG1 (v1si)
+DEF_RET1_ARG1 (v2si)
+DEF_RET1_ARG1 (v4si)
+DEF_RET1_ARG1 (v8si)
+DEF_RET1_ARG1 (v16si)
+DEF_RET1_ARG1 (v32si)
+DEF_RET1_ARG1 (v64si)
+DEF_RET1_ARG1 (v128si)
+DEF_RET1_ARG1 (v256si)
+DEF_RET1_ARG1 (v512si)
+DEF_RET1_ARG1 (v1024si)
+
+DEF_RET1_ARG2 (v1si)
+DEF_RET1_ARG2 (v2si)
+DEF_RET1_ARG2 (v4si)
+DEF_RET1_ARG2 (v8si)
+DEF_RET1_ARG2 (v16si)
+DEF_RET1_ARG2 (v32si)
+DEF_RET1_ARG2 (v64si)
+DEF_RET1_ARG2 (v128si)
+DEF_RET1_ARG2 (v256si)
+DEF_RET1_ARG2 (v512si)
+DEF_RET1_ARG2 (v1024si)
+
+DEF_RET1_ARG3 (v1si)
+DEF_RET1_ARG3 (v2si)
+DEF_RET1_ARG3 (v4si)
+DEF_RET1_ARG3 (v8si)
+DEF_RET1_ARG3 (v16si)
+DEF_RET1_ARG3 (v32si)
+DEF_RET1_ARG3 (v64si)
+DEF_RET1_ARG3 (v128si)
+DEF_RET1_ARG3 (v256si)
+DEF_RET1_ARG3 (v512si)
+DEF_RET1_ARG3 (v1024si)
+
+DEF_RET1_ARG4 (v1si)
+DEF_RET1_ARG4 (v2si)
+DEF_RET1_ARG4 (v4si)
+DEF_RET1_ARG4 (v8si)
+DEF_RET1_ARG4 (v16si)
+DEF_RET1_ARG4 (v32si)
+DEF_RET1_ARG4 (v64si)
+DEF_RET1_ARG4 (v128si)
+DEF_RET1_ARG4 (v256si)
+DEF_RET1_ARG4 (v512si)
+DEF_RET1_ARG4 (v1024si)
+
+DEF_RET1_ARG5 (v1si)
+DEF_RET1_ARG5 (v2si)
+DEF_RET1_ARG5 (v4si)
+DEF_RET1_ARG5 (v8si)
+DEF_RET1_ARG5 (v16si)
+DEF_RET1_ARG5 (v32si)
+DEF_RET1_ARG5 (v64si)
+DEF_RET1_ARG5 (v128si)
+DEF_RET1_ARG5 (v256si)
+DEF_RET1_ARG5 (v512si)
+DEF_RET1_ARG5 (v1024si)
+
+DEF_RET1_ARG6 (v1si)
+DEF_RET1_ARG6 (v2si)
+DEF_RET1_ARG6 (v4si)
+DEF_RET1_ARG6 (v8si)
+DEF_RET1_ARG6 (v16si)
+DEF_RET1_ARG6 (v32si)
+DEF_RET1_ARG6 (v64si)
+DEF_RET1_ARG6 (v128si)
+DEF_RET1_ARG6 (v256si)
+DEF_RET1_ARG6 (v512si)
+DEF_RET1_ARG6 (v1024si)
+
+DEF_RET1_ARG7 (v1si)
+DEF_RET1_ARG7 (v2si)
+DEF_RET1_ARG7 (v4si)
+DEF_RET1_ARG7 (v8si)
+DEF_RET1_ARG7 (v16si)
+DEF_RET1_ARG7 (v32si)
+DEF_RET1_ARG7 (v64si)
+DEF_RET1_ARG7 (v128si)
+DEF_RET1_ARG7 (v256si)
+DEF_RET1_ARG7 (v512si)
+DEF_RET1_ARG7 (v1024si)
+
+DEF_RET1_ARG8 (v1si)
+DEF_RET1_ARG8 (v2si)
+DEF_RET1_ARG8 (v4si)
+DEF_RET1_ARG8 (v8si)
+DEF_RET1_ARG8 (v16si)
+DEF_RET1_ARG8 (v32si)
+DEF_RET1_ARG8 (v64si)
+DEF_RET1_ARG8 (v128si)
+DEF_RET1_ARG8 (v256si)
+DEF_RET1_ARG8 (v512si)
+DEF_RET1_ARG8 (v1024si)
+
+DEF_RET1_ARG9 (v1si)
+DEF_RET1_ARG9 (v2si)
+DEF_RET1_ARG9 (v4si)
+DEF_RET1_ARG9 (v8si)
+DEF_RET1_ARG9 (v16si)
+DEF_RET1_ARG9 (v32si)
+DEF_RET1_ARG9 (v64si)
+DEF_RET1_ARG9 (v128si)
+DEF_RET1_ARG9 (v256si)
+DEF_RET1_ARG9 (v512si)
+DEF_RET1_ARG9 (v1024si)
+
+/* { dg-final { scan-assembler-times {li\s+a[0-1],\s*0} 7 } } */
+/* { dg-final { scan-assembler-times {lw\s+a0,\s*[0-9]+\(sp\)} 8 } } */
+/* { dg-final { scan-assembler-times {ld\s+a[0-1],\s*[0-9]+\(sp\)} 31 } } */
+/* { dg-final { scan-assembler-times {sw\s+a[0-7],\s*[0-9]+\(sp\)} 43 } } */
+/* { dg-final { scan-assembler-times {sd\s+a[0-7],\s*[0-9]+\(sp\)} 103 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-4.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-4.c
new file mode 100644
index 00000000000..8c3f6ba98e3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-4.c
@@ -0,0 +1,118 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv_zvl4096b --param riscv-autovec-preference=scalable -mabi=lp64d -O3" } */
+
+#include "def.h"
+
+DEF_RET1_ARG0 (v1di)
+DEF_RET1_ARG0 (v2di)
+DEF_RET1_ARG0 (v4di)
+DEF_RET1_ARG0 (v8di)
+DEF_RET1_ARG0 (v16di)
+DEF_RET1_ARG0 (v32di)
+DEF_RET1_ARG0 (v64di)
+DEF_RET1_ARG0 (v128di)
+DEF_RET1_ARG0 (v256di)
+DEF_RET1_ARG0 (v512di)
+
+DEF_RET1_ARG1 (v1di)
+DEF_RET1_ARG1 (v2di)
+DEF_RET1_ARG1 (v4di)
+DEF_RET1_ARG1 (v8di)
+DEF_RET1_ARG1 (v16di)
+DEF_RET1_ARG1 (v32di)
+DEF_RET1_ARG1 (v64di)
+DEF_RET1_ARG1 (v128di)
+DEF_RET1_ARG1 (v256di)
+DEF_RET1_ARG1 (v512di)
+
+DEF_RET1_ARG2 (v1di)
+DEF_RET1_ARG2 (v2di)
+DEF_RET1_ARG2 (v4di)
+DEF_RET1_ARG2 (v8di)
+DEF_RET1_ARG2 (v16di)
+DEF_RET1_ARG2 (v32di)
+DEF_RET1_ARG2 (v64di)
+DEF_RET1_ARG2 (v128di)
+DEF_RET1_ARG2 (v256di)
+DEF_RET1_ARG2 (v512di)
+
+DEF_RET1_ARG3 (v1di)
+DEF_RET1_ARG3 (v2di)
+DEF_RET1_ARG3 (v4di)
+DEF_RET1_ARG3 (v8di)
+DEF_RET1_ARG3 (v16di)
+DEF_RET1_ARG3 (v32di)
+DEF_RET1_ARG3 (v64di)
+DEF_RET1_ARG3 (v128di)
+DEF_RET1_ARG3 (v256di)
+DEF_RET1_ARG3 (v512di)
+
+DEF_RET1_ARG4 (v1di)
+DEF_RET1_ARG4 (v2di)
+DEF_RET1_ARG4 (v4di)
+DEF_RET1_ARG4 (v8di)
+DEF_RET1_ARG4 (v16di)
+DEF_RET1_ARG4 (v32di)
+DEF_RET1_ARG4 (v64di)
+DEF_RET1_ARG4 (v128di)
+DEF_RET1_ARG4 (v256di)
+DEF_RET1_ARG4 (v512di)
+
+DEF_RET1_ARG5 (v1di)
+DEF_RET1_ARG5 (v2di)
+DEF_RET1_ARG5 (v4di)
+DEF_RET1_ARG5 (v8di)
+DEF_RET1_ARG5 (v16di)
+DEF_RET1_ARG5 (v32di)
+DEF_RET1_ARG5 (v64di)
+DEF_RET1_ARG5 (v128di)
+DEF_RET1_ARG5 (v256di)
+DEF_RET1_ARG5 (v512di)
+
+DEF_RET1_ARG6 (v1di)
+DEF_RET1_ARG6 (v2di)
+DEF_RET1_ARG6 (v4di)
+DEF_RET1_ARG6 (v8di)
+DEF_RET1_ARG6 (v16di)
+DEF_RET1_ARG6 (v32di)
+DEF_RET1_ARG6 (v64di)
+DEF_RET1_ARG6 (v128di)
+DEF_RET1_ARG6 (v256di)
+DEF_RET1_ARG6 (v512di)
+
+DEF_RET1_ARG7 (v1di)
+DEF_RET1_ARG7 (v2di)
+DEF_RET1_ARG7 (v4di)
+DEF_RET1_ARG7 (v8di)
+DEF_RET1_ARG7 (v16di)
+DEF_RET1_ARG7 (v32di)
+DEF_RET1_ARG7 (v64di)
+DEF_RET1_ARG7 (v128di)
+DEF_RET1_ARG7 (v256di)
+DEF_RET1_ARG7 (v512di)
+
+DEF_RET1_ARG8 (v1di)
+DEF_RET1_ARG8 (v2di)
+DEF_RET1_ARG8 (v4di)
+DEF_RET1_ARG8 (v8di)
+DEF_RET1_ARG8 (v16di)
+DEF_RET1_ARG8 (v32di)
+DEF_RET1_ARG8 (v64di)
+DEF_RET1_ARG8 (v128di)
+DEF_RET1_ARG8 (v256di)
+DEF_RET1_ARG8 (v512di)
+
+DEF_RET1_ARG9 (v1di)
+DEF_RET1_ARG9 (v2di)
+DEF_RET1_ARG9 (v4di)
+DEF_RET1_ARG9 (v8di)
+DEF_RET1_ARG9 (v16di)
+DEF_RET1_ARG9 (v32di)
+DEF_RET1_ARG9 (v64di)
+DEF_RET1_ARG9 (v128di)
+DEF_RET1_ARG9 (v256di)
+DEF_RET1_ARG9 (v512di)
+
+/* { dg-final { scan-assembler-times {li\s+a[0-1],\s*0} 6 } } */
+/* { dg-final { scan-assembler-times {ld\s+a[0-1],\s*[0-9]+\(sp\)} 29 } } */
+/* { dg-final { scan-assembler-times {sd\s+a[0-7],\s*[0-9]+\(sp\)} 103 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-5.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-5.c
new file mode 100644
index 00000000000..cfa4f5db372
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-5.c
@@ -0,0 +1,141 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv_zvfh_zvl4096b --param riscv-autovec-preference=scalable -mabi=lp64d -O3" } */
+
+#include "def.h"
+
+DEF_RET1_ARG0 (v1hf)
+DEF_RET1_ARG0 (v2hf)
+DEF_RET1_ARG0 (v4hf)
+DEF_RET1_ARG0 (v8hf)
+DEF_RET1_ARG0 (v16hf)
+DEF_RET1_ARG0 (v32hf)
+DEF_RET1_ARG0 (v64hf)
+DEF_RET1_ARG0 (v128hf)
+DEF_RET1_ARG0 (v256hf)
+DEF_RET1_ARG0 (v512hf)
+DEF_RET1_ARG0 (v1024hf)
+DEF_RET1_ARG0 (v2048hf)
+
+DEF_RET1_ARG1 (v1hf)
+DEF_RET1_ARG1 (v2hf)
+DEF_RET1_ARG1 (v4hf)
+DEF_RET1_ARG1 (v8hf)
+DEF_RET1_ARG1 (v16hf)
+DEF_RET1_ARG1 (v32hf)
+DEF_RET1_ARG1 (v64hf)
+DEF_RET1_ARG1 (v128hf)
+DEF_RET1_ARG1 (v256hf)
+DEF_RET1_ARG1 (v512hf)
+DEF_RET1_ARG1 (v1024hf)
+DEF_RET1_ARG1 (v2048hf)
+
+DEF_RET1_ARG2 (v1hf)
+DEF_RET1_ARG2 (v2hf)
+DEF_RET1_ARG2 (v4hf)
+DEF_RET1_ARG2 (v8hf)
+DEF_RET1_ARG2 (v16hf)
+DEF_RET1_ARG2 (v32hf)
+DEF_RET1_ARG2 (v64hf)
+DEF_RET1_ARG2 (v128hf)
+DEF_RET1_ARG2 (v256hf)
+DEF_RET1_ARG2 (v512hf)
+DEF_RET1_ARG2 (v1024hf)
+DEF_RET1_ARG2 (v2048hf)
+
+DEF_RET1_ARG3 (v1hf)
+DEF_RET1_ARG3 (v2hf)
+DEF_RET1_ARG3 (v4hf)
+DEF_RET1_ARG3 (v8hf)
+DEF_RET1_ARG3 (v16hf)
+DEF_RET1_ARG3 (v32hf)
+DEF_RET1_ARG3 (v64hf)
+DEF_RET1_ARG3 (v128hf)
+DEF_RET1_ARG3 (v256hf)
+DEF_RET1_ARG3 (v512hf)
+DEF_RET1_ARG3 (v1024hf)
+DEF_RET1_ARG3 (v2048hf)
+
+DEF_RET1_ARG4 (v1hf)
+DEF_RET1_ARG4 (v2hf)
+DEF_RET1_ARG4 (v4hf)
+DEF_RET1_ARG4 (v8hf)
+DEF_RET1_ARG4 (v16hf)
+DEF_RET1_ARG4 (v32hf)
+DEF_RET1_ARG4 (v64hf)
+DEF_RET1_ARG4 (v128hf)
+DEF_RET1_ARG4 (v256hf)
+DEF_RET1_ARG4 (v512hf)
+DEF_RET1_ARG4 (v1024hf)
+DEF_RET1_ARG4 (v2048hf)
+
+DEF_RET1_ARG5 (v1hf)
+DEF_RET1_ARG5 (v2hf)
+DEF_RET1_ARG5 (v4hf)
+DEF_RET1_ARG5 (v8hf)
+DEF_RET1_ARG5 (v16hf)
+DEF_RET1_ARG5 (v32hf)
+DEF_RET1_ARG5 (v64hf)
+DEF_RET1_ARG5 (v128hf)
+DEF_RET1_ARG5 (v256hf)
+DEF_RET1_ARG5 (v512hf)
+DEF_RET1_ARG5 (v1024hf)
+DEF_RET1_ARG5 (v2048hf)
+
+DEF_RET1_ARG6 (v1hf)
+DEF_RET1_ARG6 (v2hf)
+DEF_RET1_ARG6 (v4hf)
+DEF_RET1_ARG6 (v8hf)
+DEF_RET1_ARG6 (v16hf)
+DEF_RET1_ARG6 (v32hf)
+DEF_RET1_ARG6 (v64hf)
+DEF_RET1_ARG6 (v128hf)
+DEF_RET1_ARG6 (v256hf)
+DEF_RET1_ARG6 (v512hf)
+DEF_RET1_ARG6 (v1024hf)
+DEF_RET1_ARG6 (v2048hf)
+
+DEF_RET1_ARG7 (v1hf)
+DEF_RET1_ARG7 (v2hf)
+DEF_RET1_ARG7 (v4hf)
+DEF_RET1_ARG7 (v8hf)
+DEF_RET1_ARG7 (v16hf)
+DEF_RET1_ARG7 (v32hf)
+DEF_RET1_ARG7 (v64hf)
+DEF_RET1_ARG7 (v128hf)
+DEF_RET1_ARG7 (v256hf)
+DEF_RET1_ARG7 (v512hf)
+DEF_RET1_ARG7 (v1024hf)
+DEF_RET1_ARG7 (v2048hf)
+
+DEF_RET1_ARG8 (v1hf)
+DEF_RET1_ARG8 (v2hf)
+DEF_RET1_ARG8 (v4hf)
+DEF_RET1_ARG8 (v8hf)
+DEF_RET1_ARG8 (v16hf)
+DEF_RET1_ARG8 (v32hf)
+DEF_RET1_ARG8 (v64hf)
+DEF_RET1_ARG8 (v128hf)
+DEF_RET1_ARG8 (v256hf)
+DEF_RET1_ARG8 (v512hf)
+DEF_RET1_ARG8 (v1024hf)
+DEF_RET1_ARG8 (v2048hf)
+
+DEF_RET1_ARG9 (v1hf)
+DEF_RET1_ARG9 (v2hf)
+DEF_RET1_ARG9 (v4hf)
+DEF_RET1_ARG9 (v8hf)
+DEF_RET1_ARG9 (v16hf)
+DEF_RET1_ARG9 (v32hf)
+DEF_RET1_ARG9 (v64hf)
+DEF_RET1_ARG9 (v128hf)
+DEF_RET1_ARG9 (v256hf)
+DEF_RET1_ARG9 (v512hf)
+DEF_RET1_ARG9 (v1024hf)
+DEF_RET1_ARG9 (v2048hf)
+
+/* { dg-final { scan-assembler-times {li\s+a[0-1],\s*0} 6 } } */
+/* { dg-final { scan-assembler-times {flh\s+fa[0-1],\s*[0-9]+\(sp\)} 9 } } */
+/* { dg-final { scan-assembler-times {flw\s+fa[0-1],\s*[0-9]+\(sp\)} 9 } } */
+/* { dg-final { scan-assembler-times {fsh\s+fa[0-7],\s*[0-9]+\(sp\)} 43 } } */
+/* { dg-final { scan-assembler-times {fsw\s+fa[0-7],\s*[0-9]+\(sp\)} 43 } } */
+/* { dg-final { scan-assembler-times {sd\s+a[0-7],\s*[0-9]+\(sp\)} 103 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-6.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-6.c
new file mode 100644
index 00000000000..45a9e2debe8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-6.c
@@ -0,0 +1,129 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv_zvl4096b --param riscv-autovec-preference=scalable -mabi=lp64d -O3" } */
+
+#include "def.h"
+
+DEF_RET1_ARG0 (v1sf)
+DEF_RET1_ARG0 (v2sf)
+DEF_RET1_ARG0 (v4sf)
+DEF_RET1_ARG0 (v8sf)
+DEF_RET1_ARG0 (v16sf)
+DEF_RET1_ARG0 (v32sf)
+DEF_RET1_ARG0 (v64sf)
+DEF_RET1_ARG0 (v128sf)
+DEF_RET1_ARG0 (v256sf)
+DEF_RET1_ARG0 (v512sf)
+DEF_RET1_ARG0 (v1024sf)
+
+DEF_RET1_ARG1 (v1sf)
+DEF_RET1_ARG1 (v2sf)
+DEF_RET1_ARG1 (v4sf)
+DEF_RET1_ARG1 (v8sf)
+DEF_RET1_ARG1 (v16sf)
+DEF_RET1_ARG1 (v32sf)
+DEF_RET1_ARG1 (v64sf)
+DEF_RET1_ARG1 (v128sf)
+DEF_RET1_ARG1 (v256sf)
+DEF_RET1_ARG1 (v512sf)
+DEF_RET1_ARG1 (v1024sf)
+
+DEF_RET1_ARG2 (v1sf)
+DEF_RET1_ARG2 (v2sf)
+DEF_RET1_ARG2 (v4sf)
+DEF_RET1_ARG2 (v8sf)
+DEF_RET1_ARG2 (v16sf)
+DEF_RET1_ARG2 (v32sf)
+DEF_RET1_ARG2 (v64sf)
+DEF_RET1_ARG2 (v128sf)
+DEF_RET1_ARG2 (v256sf)
+DEF_RET1_ARG2 (v512sf)
+DEF_RET1_ARG2 (v1024sf)
+
+DEF_RET1_ARG3 (v1sf)
+DEF_RET1_ARG3 (v2sf)
+DEF_RET1_ARG3 (v4sf)
+DEF_RET1_ARG3 (v8sf)
+DEF_RET1_ARG3 (v16sf)
+DEF_RET1_ARG3 (v32sf)
+DEF_RET1_ARG3 (v64sf)
+DEF_RET1_ARG3 (v128sf)
+DEF_RET1_ARG3 (v256sf)
+DEF_RET1_ARG3 (v512sf)
+DEF_RET1_ARG3 (v1024sf)
+
+DEF_RET1_ARG4 (v1sf)
+DEF_RET1_ARG4 (v2sf)
+DEF_RET1_ARG4 (v4sf)
+DEF_RET1_ARG4 (v8sf)
+DEF_RET1_ARG4 (v16sf)
+DEF_RET1_ARG4 (v32sf)
+DEF_RET1_ARG4 (v64sf)
+DEF_RET1_ARG4 (v128sf)
+DEF_RET1_ARG4 (v256sf)
+DEF_RET1_ARG4 (v512sf)
+DEF_RET1_ARG4 (v1024sf)
+
+DEF_RET1_ARG5 (v1sf)
+DEF_RET1_ARG5 (v2sf)
+DEF_RET1_ARG5 (v4sf)
+DEF_RET1_ARG5 (v8sf)
+DEF_RET1_ARG5 (v16sf)
+DEF_RET1_ARG5 (v32sf)
+DEF_RET1_ARG5 (v64sf)
+DEF_RET1_ARG5 (v128sf)
+DEF_RET1_ARG5 (v256sf)
+DEF_RET1_ARG5 (v512sf)
+DEF_RET1_ARG5 (v1024sf)
+
+DEF_RET1_ARG6 (v1sf)
+DEF_RET1_ARG6 (v2sf)
+DEF_RET1_ARG6 (v4sf)
+DEF_RET1_ARG6 (v8sf)
+DEF_RET1_ARG6 (v16sf)
+DEF_RET1_ARG6 (v32sf)
+DEF_RET1_ARG6 (v64sf)
+DEF_RET1_ARG6 (v128sf)
+DEF_RET1_ARG6 (v256sf)
+DEF_RET1_ARG6 (v512sf)
+DEF_RET1_ARG6 (v1024sf)
+
+DEF_RET1_ARG7 (v1sf)
+DEF_RET1_ARG7 (v2sf)
+DEF_RET1_ARG7 (v4sf)
+DEF_RET1_ARG7 (v8sf)
+DEF_RET1_ARG7 (v16sf)
+DEF_RET1_ARG7 (v32sf)
+DEF_RET1_ARG7 (v64sf)
+DEF_RET1_ARG7 (v128sf)
+DEF_RET1_ARG7 (v256sf)
+DEF_RET1_ARG7 (v512sf)
+DEF_RET1_ARG7 (v1024sf)
+
+DEF_RET1_ARG8 (v1sf)
+DEF_RET1_ARG8 (v2sf)
+DEF_RET1_ARG8 (v4sf)
+DEF_RET1_ARG8 (v8sf)
+DEF_RET1_ARG8 (v16sf)
+DEF_RET1_ARG8 (v32sf)
+DEF_RET1_ARG8 (v64sf)
+DEF_RET1_ARG8 (v128sf)
+DEF_RET1_ARG8 (v256sf)
+DEF_RET1_ARG8 (v512sf)
+DEF_RET1_ARG8 (v1024sf)
+
+DEF_RET1_ARG9 (v1sf)
+DEF_RET1_ARG9 (v2sf)
+DEF_RET1_ARG9 (v4sf)
+DEF_RET1_ARG9 (v8sf)
+DEF_RET1_ARG9 (v16sf)
+DEF_RET1_ARG9 (v32sf)
+DEF_RET1_ARG9 (v64sf)
+DEF_RET1_ARG9 (v128sf)
+DEF_RET1_ARG9 (v256sf)
+DEF_RET1_ARG9 (v512sf)
+DEF_RET1_ARG9 (v1024sf)
+
+/* { dg-final { scan-assembler-times {li\s+a[0-1],\s*0} 5 } } */
+/* { dg-final { scan-assembler-times {flw\s+fa[0-1],\s*[0-9]+\(sp\)} 9 } } */
+/* { dg-final { scan-assembler-times {fsw\s+fa[0-7],\s*[0-9]+\(sp\)} 43 } } */
+/* { dg-final { scan-assembler-times {sd\s+a[0-7],\s*[0-9]+\(sp\)} 60 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-7.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-7.c
new file mode 100644
index 00000000000..a607786afea
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-7.c
@@ -0,0 +1,120 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv_zvl4096b --param riscv-autovec-preference=scalable -mabi=lp64d -O3" } */
+
+#include "def.h"
+
+DEF_RET1_ARG0 (v1df)
+DEF_RET1_ARG0 (v2df)
+DEF_RET1_ARG0 (v4df)
+DEF_RET1_ARG0 (v8df)
+DEF_RET1_ARG0 (v16df)
+DEF_RET1_ARG0 (v32df)
+DEF_RET1_ARG0 (v64df)
+DEF_RET1_ARG0 (v128df)
+DEF_RET1_ARG0 (v256df)
+DEF_RET1_ARG0 (v512df)
+
+DEF_RET1_ARG1 (v1df)
+DEF_RET1_ARG1 (v2df)
+DEF_RET1_ARG1 (v4df)
+DEF_RET1_ARG1 (v8df)
+DEF_RET1_ARG1 (v16df)
+DEF_RET1_ARG1 (v32df)
+DEF_RET1_ARG1 (v64df)
+DEF_RET1_ARG1 (v128df)
+DEF_RET1_ARG1 (v256df)
+DEF_RET1_ARG1 (v512df)
+
+DEF_RET1_ARG2 (v1df)
+DEF_RET1_ARG2 (v2df)
+DEF_RET1_ARG2 (v4df)
+DEF_RET1_ARG2 (v8df)
+DEF_RET1_ARG2 (v16df)
+DEF_RET1_ARG2 (v32df)
+DEF_RET1_ARG2 (v64df)
+DEF_RET1_ARG2 (v128df)
+DEF_RET1_ARG2 (v256df)
+DEF_RET1_ARG2 (v512df)
+
+DEF_RET1_ARG3 (v1df)
+DEF_RET1_ARG3 (v2df)
+DEF_RET1_ARG3 (v4df)
+DEF_RET1_ARG3 (v8df)
+DEF_RET1_ARG3 (v16df)
+DEF_RET1_ARG3 (v32df)
+DEF_RET1_ARG3 (v64df)
+DEF_RET1_ARG3 (v128df)
+DEF_RET1_ARG3 (v256df)
+DEF_RET1_ARG3 (v512df)
+
+DEF_RET1_ARG4 (v1df)
+DEF_RET1_ARG4 (v2df)
+DEF_RET1_ARG4 (v4df)
+DEF_RET1_ARG4 (v8df)
+DEF_RET1_ARG4 (v16df)
+DEF_RET1_ARG4 (v32df)
+DEF_RET1_ARG4 (v64df)
+DEF_RET1_ARG4 (v128df)
+DEF_RET1_ARG4 (v256df)
+DEF_RET1_ARG4 (v512df)
+
+DEF_RET1_ARG5 (v1df)
+DEF_RET1_ARG5 (v2df)
+DEF_RET1_ARG5 (v4df)
+DEF_RET1_ARG5 (v8df)
+DEF_RET1_ARG5 (v16df)
+DEF_RET1_ARG5 (v32df)
+DEF_RET1_ARG5 (v64df)
+DEF_RET1_ARG5 (v128df)
+DEF_RET1_ARG5 (v256df)
+DEF_RET1_ARG5 (v512df)
+
+DEF_RET1_ARG6 (v1df)
+DEF_RET1_ARG6 (v2df)
+DEF_RET1_ARG6 (v4df)
+DEF_RET1_ARG6 (v8df)
+DEF_RET1_ARG6 (v16df)
+DEF_RET1_ARG6 (v32df)
+DEF_RET1_ARG6 (v64df)
+DEF_RET1_ARG6 (v128df)
+DEF_RET1_ARG6 (v256df)
+DEF_RET1_ARG6 (v512df)
+
+DEF_RET1_ARG7 (v1df)
+DEF_RET1_ARG7 (v2df)
+DEF_RET1_ARG7 (v4df)
+DEF_RET1_ARG7 (v8df)
+DEF_RET1_ARG7 (v16df)
+DEF_RET1_ARG7 (v32df)
+DEF_RET1_ARG7 (v64df)
+DEF_RET1_ARG7 (v128df)
+DEF_RET1_ARG7 (v256df)
+DEF_RET1_ARG7 (v512df)
+
+DEF_RET1_ARG8 (v1df)
+DEF_RET1_ARG8 (v2df)
+DEF_RET1_ARG8 (v4df)
+DEF_RET1_ARG8 (v8df)
+DEF_RET1_ARG8 (v16df)
+DEF_RET1_ARG8 (v32df)
+DEF_RET1_ARG8 (v64df)
+DEF_RET1_ARG8 (v128df)
+DEF_RET1_ARG8 (v256df)
+DEF_RET1_ARG8 (v512df)
+
+DEF_RET1_ARG9 (v1df)
+DEF_RET1_ARG9 (v2df)
+DEF_RET1_ARG9 (v4df)
+DEF_RET1_ARG9 (v8df)
+DEF_RET1_ARG9 (v16df)
+DEF_RET1_ARG9 (v32df)
+DEF_RET1_ARG9 (v64df)
+DEF_RET1_ARG9 (v128df)
+DEF_RET1_ARG9 (v256df)
+DEF_RET1_ARG9 (v512df)
+
+/* { dg-final { scan-assembler-times {li\s+a[0-1],\s*0} 5 } } */
+/* { dg-final { scan-assembler-times {ld\s+a[0-1],\s*[0-9]+\(sp\)} 21 } } */
+/* { dg-final { scan-assembler-times {fld\s+fa[0-1],\s*[0-9]+\(sp\)} 9 } } */
+/* { dg-final { scan-assembler-times {sd\s+a[0-7],\s*[0-9]+\(sp\)} 60 } } */
+/* { dg-final { scan-assembler-times {fsd\s+fa[0-7],\s*[0-9]+\(sp\)} 43 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-8.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-8.c
new file mode 100644
index 00000000000..ed66a2cb9eb
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-8.c
@@ -0,0 +1,43 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv_zvl4096b -mabi=lp64d --param riscv-autovec-preference=scalable -O3 -fno-schedule-insns -fno-schedule-insns2" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include "def.h"
+
+/*
+** v8qi_RET1_ARG0:
+** li\s+a0,\s*0
+** ret
+*/
+DEF_RET1_ARG0 (v8qi)
+
+/*
+** v4hi_RET1_ARG1:
+** ret
+*/
+DEF_RET1_ARG1 (v4hi)
+
+/*
+** v2si_RET1_ARG2:
+** addi\s+sp,\s*sp,\s*-16
+** sd\s+a0,\s*0\(sp\)
+** sd\s+a1,\s*8\(sp\)
+** ...
+** ld\s+a0,\s*0\(sp\)
+** addi\s+sp,\s*sp,\s*16
+** jr\s+ra
+*/
+DEF_RET1_ARG2 (v2si)
+
+/*
+** v1di_RET1_ARG3:
+** addi\s+sp,\s*sp,\s*-32
+** sd\s+a0,\s*8\(sp\)
+** sd\s+a1,\s*16\(sp\)
+** sd\s+a2,\s*24\(sp\)
+** ...
+** ld\s+a0,\s*8\(sp\)
+** addi\s+sp,\s*sp,\s*32
+** jr\s+ra
+*/
+DEF_RET1_ARG3 (v1di)
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-9.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-9.c
new file mode 100644
index 00000000000..dd8e709ee59
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-9.c
@@ -0,0 +1,51 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv_zvfh_zvl4096b -mabi=lp64d --param riscv-autovec-preference=scalable -O3 -fno-schedule-insns -fno-schedule-insns2" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include "def.h"
+
+/*
+** v4hf_RET1_ARG1:
+** ret
+*/
+DEF_RET1_ARG1 (v4hf)
+
+/*
+** v2sf_RET1_ARG2:
+** addi\s+sp,\s*sp,\s*-16
+** fsd\s+fa0,\s*0\(sp\)
+** fsd\s+fa1,\s*8\(sp\)
+** ...
+** fld\s+fa0,\s*0\(sp\)
+** addi\s+sp,\s*sp,\s*16
+** jr\s+ra
+*/
+DEF_RET1_ARG2 (v2sf)
+
+/*
+** v4sf_RET1_ARG2:
+** addi\s+sp,\s*sp,\s*-32
+** sd\s+a0,\s*0\(sp\)
+** sd\s+a1,\s*8\(sp\)
+** sd\s+a2,\s*16\(sp\)
+** sd\s+a3,\s*24\(sp\)
+** ...
+** ld\s+a0,\s*0\(sp\)
+** ld\s+a1,\s*8\(sp\)
+** addi\s+sp,\s*sp,\s*32
+** jr\s+ra
+*/
+DEF_RET1_ARG2 (v4sf)
+
+/*
+** v1df_RET1_ARG3:
+** addi\s+sp,\s*sp,\s*-32
+** fsd\s+fa0,\s*8\(sp\)
+** fsd\s+fa1,\s*16\(sp\)
+** fsd\s+fa2,\s*24\(sp\)
+** ...
+** fld\s+fa0,\s*8\(sp\)
+** addi\s+sp,\s*sp,\s*32
+** jr\s+ra
+*/
+DEF_RET1_ARG3 (v1df)
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-run-1.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-run-1.c
new file mode 100644
index 00000000000..d8aa5c51cac
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-run-1.c
@@ -0,0 +1,55 @@
+/* { dg-do run { target { riscv_v } } } */
+/* { dg-additional-options "-std=c99 -fno-vect-cost-model --param=riscv-autovec-preference=scalable" } */
+
+typedef char v16qi __attribute__ ((vector_size (16)));
+
+v16qi
+add (v16qi a1, v16qi a2, v16qi a3, v16qi a4, v16qi a5, v16qi a6, v16qi a7,
+     v16qi a8, v16qi a9)
+{
+  return a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8 + a9;
+}
+
+int
+main ()
+{
+  v16qi a1 = {
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  };
+  v16qi a2 = {
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  };
+  v16qi a3 = {
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  };
+  v16qi a4 = {
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  };
+  v16qi a5 = {
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  };
+  v16qi a6 = {
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  };
+  v16qi a7 = {
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  };
+  v16qi a8 = {
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  };
+  v16qi a9 = {
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  };
+  v16qi expected = {
+    9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+  };
+  v16qi result = add (a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+  unsigned i;
+
+  for (i = 0; i < 16; i++)
+    if (result[i] != expected[i])
+      __builtin_abort ();
+
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-run-2.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-run-2.c
new file mode 100644
index 00000000000..57376a3924c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-run-2.c
@@ -0,0 +1,55 @@
+/* { dg-do run { target { riscv_v } } } */
+/* { dg-additional-options "-std=c99 -fno-vect-cost-model --param=riscv-autovec-preference=scalable" } */
+
+typedef short v8hi __attribute__ ((vector_size (16)));
+
+v8hi
+add (v8hi a1, v8hi a2, v8hi a3, v8hi a4, v8hi a5, v8hi a6, v8hi a7,
+     v8hi a8, v8hi a9)
+{
+  return a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8 + a9;
+}
+
+int
+main ()
+{
+  v8hi a1 = {
+    1, 1, 1, 1, 1, 1, 1, 1,
+  };
+  v8hi a2 = {
+    1, 1, 1, 1, 1, 1, 1, 1,
+  };
+  v8hi a3 = {
+    1, 1, 1, 1, 1, 1, 1, 1,
+  };
+  v8hi a4 = {
+    1, 1, 1, 1, 1, 1, 1, 1,
+  };
+  v8hi a5 = {
+    1, 1, 1, 1, 1, 1, 1, 1,
+  };
+  v8hi a6 = {
+    1, 1, 1, 1, 1, 1, 1, 1,
+  };
+  v8hi a7 = {
+    1, 1, 1, 1, 1, 1, 1, 1,
+  };
+  v8hi a8 = {
+    1, 1, 1, 1, 1, 1, 1, 1,
+  };
+  v8hi a9 = {
+    1, 1, 1, 1, 1, 1, 1, 1,
+  };
+  v8hi expected = {
+    9, 9, 9, 9, 9, 9, 9, 9,
+  };
+  v8hi result = add (a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+  unsigned i;
+
+  for (i = 0; i < 8; i++)
+    if (result[i] != expected[i])
+      __builtin_abort ();
+
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-run-3.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-run-3.c
new file mode 100644
index 00000000000..b37cd5669d4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-run-3.c
@@ -0,0 +1,55 @@
+/* { dg-do run { target { riscv_v } } } */
+/* { dg-additional-options "-std=c99 -fno-vect-cost-model --param=riscv-autovec-preference=scalable" } */
+
+typedef int v4si __attribute__ ((vector_size (16)));
+
+v4si
+add (v4si a1, v4si a2, v4si a3, v4si a4, v4si a5, v4si a6, v4si a7,
+     v4si a8, v4si a9)
+{
+  return a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8 + a9;
+}
+
+int
+main ()
+{
+  v4si a1 = {
+    1, 1, 1, 1,
+  };
+  v4si a2 = {
+    1, 1, 1, 1,
+  };
+  v4si a3 = {
+    1, 1, 1, 1,
+  };
+  v4si a4 = {
+    1, 1, 1, 1,
+  };
+  v4si a5 = {
+    1, 1, 1, 1,
+  };
+  v4si a6 = {
+    1, 1, 1, 1,
+  };
+  v4si a7 = {
+    1, 1, 1, 1,
+  };
+  v4si a8 = {
+    1, 1, 1, 1,
+  };
+  v4si a9 = {
+    1, 1, 1, 1,
+  };
+  v4si expected = {
+    9, 9, 9, 9,
+  };
+  v4si result = add (a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+  unsigned i;
+
+  for (i = 0; i < 4; i++)
+    if (result[i] != expected[i])
+      __builtin_abort ();
+
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-run-4.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-run-4.c
new file mode 100644
index 00000000000..0788447b501
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-run-4.c
@@ -0,0 +1,55 @@
+/* { dg-do run { target { riscv_v } } } */
+/* { dg-additional-options "-std=c99 -fno-vect-cost-model --param=riscv-autovec-preference=scalable" } */
+
+typedef long long v2di __attribute__ ((vector_size (16)));
+
+v2di
+add (v2di a1, v2di a2, v2di a3, v2di a4, v2di a5, v2di a6, v2di a7,
+     v2di a8, v2di a9)
+{
+  return a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8 + a9;
+}
+
+int
+main ()
+{
+  v2di a1 = {
+    1, 1,
+  };
+  v2di a2 = {
+    1, 1,
+  };
+  v2di a3 = {
+    1, 1,
+  };
+  v2di a4 = {
+    1, 1,
+  };
+  v2di a5 = {
+    1, 1,
+  };
+  v2di a6 = {
+    1, 1,
+  };
+  v2di a7 = {
+    1, 1,
+  };
+  v2di a8 = {
+    1, 1,
+  };
+  v2di a9 = {
+    1, 1,
+  };
+  v2di expected = {
+    9, 9,
+  };
+  v2di result = add (a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+  unsigned i;
+
+  for (i = 0; i < 2; i++)
+    if (result[i] != expected[i])
+      __builtin_abort ();
+
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-run-5.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-run-5.c
new file mode 100644
index 00000000000..ec8658d6a02
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-run-5.c
@@ -0,0 +1,55 @@
+/* { dg-do run { target { riscv_v } } } */
+/* { dg-additional-options "-std=c99 -fno-vect-cost-model --param=riscv-autovec-preference=scalable" } */
+
+typedef float v4sf __attribute__ ((vector_size (16)));
+
+v4sf
+add (v4sf a1, v4sf a2, v4sf a3, v4sf a4, v4sf a5, v4sf a6, v4sf a7,
+     v4sf a8, v4sf a9)
+{
+  return a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8 + a9;
+}
+
+int
+main ()
+{
+  v4sf a1 = {
+    1.0, 1.0, 1.0, 1.0,
+  };
+  v4sf a2 = {
+    1.0, 1.0, 1.0, 1.0,
+  };
+  v4sf a3 = {
+    1.0, 1.0, 1.0, 1.0,
+  };
+  v4sf a4 = {
+    1.0, 1.0, 1.0, 1.0,
+  };
+  v4sf a5 = {
+    1.0, 1.0, 1.0, 1.0,
+  };
+  v4sf a6 = {
+    1.0, 1.0, 1.0, 1.0,
+  };
+  v4sf a7 = {
+    1.0, 1.0, 1.0, 1.0,
+  };
+  v4sf a8 = {
+    1.0, 1.0, 1.0, 1.0,
+  };
+  v4sf a9 = {
+    1.0, 1.0, 1.0, 1.0,
+  };
+  v4sf expected = {
+    9.0, 9.0, 9.0, 9.0,
+  };
+  v4sf result = add (a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+  unsigned i;
+
+  for (i = 0; i < 4; i++)
+    if (result[i] != expected[i])
+      __builtin_abort ();
+
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-run-6.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-run-6.c
new file mode 100644
index 00000000000..bbb53a1a4af
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-run-6.c
@@ -0,0 +1,55 @@
+/* { dg-do run { target { riscv_v } } } */
+/* { dg-additional-options "-std=c99 -fno-vect-cost-model --param=riscv-autovec-preference=scalable" } */
+
+typedef long long v2df __attribute__ ((vector_size (16)));
+
+v2df
+add (v2df a1, v2df a2, v2df a3, v2df a4, v2df a5, v2df a6, v2df a7,
+     v2df a8, v2df a9)
+{
+  return a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8 + a9;
+}
+
+int
+main ()
+{
+  v2df a1 = {
+    1.0, 1.0,
+  };
+  v2df a2 = {
+    1.0, 1.0,
+  };
+  v2df a3 = {
+    1.0, 1.0,
+  };
+  v2df a4 = {
+    1.0, 1.0,
+  };
+  v2df a5 = {
+    1.0, 1.0,
+  };
+  v2df a6 = {
+    1.0, 1.0,
+  };
+  v2df a7 = {
+    1.0, 1.0,
+  };
+  v2df a8 = {
+    1.0, 1.0,
+  };
+  v2df a9 = {
+    1.0, 1.0,
+  };
+  v2df expected = {
+    9.0, 9.0,
+  };
+  v2df result = add (a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+  unsigned i;
+
+  for (i = 0; i < 2; i++)
+    if (result[i] != expected[i])
+      __builtin_abort ();
+
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/def.h b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/def.h
index cb7a1c97ded..ef55c4d7ecf 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/def.h
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/def.h
@@ -860,3 +860,77 @@ typedef double v512df __attribute__ ((vector_size (4096)));
     TYPE1 v = {__VA_ARGS__};                                                   \
     *(TYPE1 *) out = v;                                                        \
   }
+
+#define DEF_RET1_ARG0(TYPE)                                                    \
+  TYPE __attribute__((noinline))                                               \
+  TYPE##_RET1_ARG0 ()                                                          \
+  {                                                                            \
+    TYPE r = {};                                                               \
+    return r;                                                                  \
+  }
+
+#define DEF_RET1_ARG1(TYPE)                                                    \
+  TYPE __attribute__((noinline))                                               \
+  TYPE##_RET1_ARG1 (TYPE a1)                                                   \
+  {                                                                            \
+    return a1;                                                                 \
+  }
+
+#define DEF_RET1_ARG2(TYPE)                                                    \
+  TYPE __attribute__((noinline))                                               \
+  TYPE##_RET1_ARG2 (TYPE a1, TYPE a2)                                          \
+  {                                                                            \
+    return a1 + a2;                                                            \
+  }
+
+#define DEF_RET1_ARG3(TYPE)                                                    \
+  TYPE __attribute__((noinline))                                               \
+  TYPE##_RET1_ARG3 (TYPE a1, TYPE a2, TYPE a3)                                 \
+  {                                                                            \
+    return a1 + a2 + a3;                                                       \
+  }
+
+#define DEF_RET1_ARG4(TYPE)                                                    \
+  TYPE __attribute__((noinline))                                               \
+  TYPE##_RET1_ARG4 (TYPE a1, TYPE a2, TYPE a3, TYPE a4)                        \
+  {                                                                            \
+    return a1 + a2 + a3 + a4;                                                  \
+  }
+
+#define DEF_RET1_ARG5(TYPE)                                                    \
+  TYPE __attribute__((noinline))                                               \
+  TYPE##_RET1_ARG5 (TYPE a1, TYPE a2, TYPE a3, TYPE a4, TYPE a5)               \
+  {                                                                            \
+    return a1 + a2 + a3 + a4 + a5;                                             \
+  }
+
+#define DEF_RET1_ARG6(TYPE)                                                    \
+  TYPE __attribute__((noinline))                                               \
+  TYPE##_RET1_ARG6 (TYPE a1, TYPE a2, TYPE a3, TYPE a4, TYPE a5, TYPE a6)      \
+  {                                                                            \
+    return a1 + a2 + a3 + a4 + a5 + a6;                                        \
+  }
+
+#define DEF_RET1_ARG7(TYPE)                                                    \
+  TYPE __attribute__((noinline))                                               \
+  TYPE##_RET1_ARG7 (TYPE a1, TYPE a2, TYPE a3, TYPE a4, TYPE a5, TYPE a6,      \
+     TYPE a7)                                                   \
+  {                                                                            \
+    return a1 + a2 + a3 + a4 + a5 + a6 + a7;                                   \
+  }
+
+#define DEF_RET1_ARG8(TYPE)                                                    \
+  TYPE __attribute__((noinline))                                               \
+  TYPE##_RET1_ARG8 (TYPE a1, TYPE a2, TYPE a3, TYPE a4, TYPE a5, TYPE a6,      \
+     TYPE a7, TYPE a8)                                          \
+  {                                                                            \
+    return a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8;                              \
+  }
+
+#define DEF_RET1_ARG9(TYPE)                                                    \
+  TYPE __attribute__((noinline))                                               \
+  TYPE##_RET1_ARG9 (TYPE a1, TYPE a2, TYPE a3, TYPE a4, TYPE a5, TYPE a6,      \
+     TYPE a7, TYPE a8, TYPE a9)                                 \
+  {                                                                            \
+    return a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8 + a9;                         \
+  }
-- 
2.34.1
 
 

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

* RE: [PATCH v1] RISC-V: Bugfix for vls integer mode calling convention
  2024-01-24  3:18 ` juzhe.zhong
@ 2024-01-24  3:41   ` Li, Pan2
  2024-01-24  3:43     ` juzhe.zhong
  0 siblings, 1 reply; 10+ messages in thread
From: Li, Pan2 @ 2024-01-24  3:41 UTC (permalink / raw)
  To: juzhe.zhong, gcc-patches; +Cc: Wang, Yanzhang, kito.cheng

[-- Attachment #1: Type: text/plain, Size: 58309 bytes --]

The title should remove integer, and sorry for misleading here.

Looks the clang leverage the vmv + vslide1down to build the vls while gcc goes to the stack. Not very sure if it related to the last comment of

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111720

But it is one optimization case which may be handled in another patch up to a point.

Pan

From: juzhe.zhong@rivai.ai <juzhe.zhong@rivai.ai>
Sent: Wednesday, January 24, 2024 11:19 AM
To: Li, Pan2 <pan2.li@intel.com>; gcc-patches <gcc-patches@gcc.gnu.org>
Cc: Li, Pan2 <pan2.li@intel.com>; Wang, Yanzhang <yanzhang.wang@intel.com>; kito.cheng <kito.cheng@gmail.com>
Subject: Re: [PATCH v1] RISC-V: Bugfix for vls integer mode calling convention

>> After this patch:
>>add:
>>  addi     sp,sp,-32
>>  sd       a0,0(sp)  <== arg by register a0 - a3
>>  sd       a1,8(sp)
>>  sd       a2,16(sp)
>>  sd       a3,24(sp)
>>  addi     a5,sp,16
>>  vsetivli zero,8,e16,m1,ta,ma
>>  vle16.v  v2,0(sp)
>>  vle16.v  v1,0(a5)
 >> vadd.vv  v1,v1,v2
>>  vse16.v  v1,0(sp)
>>  ld       a0,0(sp)  <== return by a0 - a1.
>>  ld       a1,8(sp)
>>  addi     sp,sp,32
>>  jr       ra

But clang is :

        vsetivli        zero, 2, e64, m1, ta, ma
        vmv.v.x v8, a0
        vslide1down.vx  v8, v8, a1
        vmv.v.x v9, a2
        vslide1down.vx  v9, v9, a3
        vsetivli        zero, 8, e16, m1, ta, ma
        vadd.vv v8, v9, v8
        vsetivli        zero, 1, e64, m1, ta, ma
        vmv.x.s a0, v8
        vslidedown.vi   v8, v8, 1
        vmv.x.s a1, v8
        ret

________________________________
juzhe.zhong@rivai.ai<mailto:juzhe.zhong@rivai.ai>

From: pan2.li<mailto:pan2.li@intel.com>
Date: 2024-01-24 11:16
To: gcc-patches<mailto:gcc-patches@gcc.gnu.org>
CC: juzhe.zhong<mailto:juzhe.zhong@rivai.ai>; pan2.li<mailto:pan2.li@intel.com>; yanzhang.wang<mailto:yanzhang.wang@intel.com>; kito.cheng<mailto:kito.cheng@gmail.com>
Subject: [PATCH v1] RISC-V: Bugfix for vls integer mode calling convention
From: Pan Li <pan2.li@intel.com<mailto:pan2.li@intel.com>>

According to the issue as below.

https://hub.fgit.cf/riscv-non-isa/riscv-elf-psabi-doc/pull/416

When the mode size of vls integer mode is less than 2 * XLEN, we will
take the gpr/fpr for both the args and the return values. Instead of
the reference. For example the below code:

typedef short v8hi __attribute__ ((vector_size (16)));

v8hi __attribute__((noinline))
add (v8hi a, v8hi b)
{
  v8hi r = a + b;
  return r;
}

Before this patch:
add:
  vsetivli zero,8,e16,m1,ta,ma
  vle16.v  v1,0(a1) <== arg by reference
  vle16.v  v2,0(a2) <== arg by reference
  vadd.vv  v1,v1,v2
  vse16.v  v1,0(a0) <== return by reference
  ret

After this patch:
add:
  addi     sp,sp,-32
  sd       a0,0(sp)  <== arg by register a0 - a3
  sd       a1,8(sp)
  sd       a2,16(sp)
  sd       a3,24(sp)
  addi     a5,sp,16
  vsetivli zero,8,e16,m1,ta,ma
  vle16.v  v2,0(sp)
  vle16.v  v1,0(a5)
  vadd.vv  v1,v1,v2
  vse16.v  v1,0(sp)
  ld       a0,0(sp)  <== return by a0 - a1.
  ld       a1,8(sp)
  addi     sp,sp,32
  jr       ra

For vls floating point, the things get more complicated.  We follow
the below rules.

1. Vls element count <= 2 and vls size <= 2 * xlen, go fpr.
2. Vls size <= 2 * xlen, go gpr.
3. Vls size > 2 * xlen, go reference.

One exceptions is V2DF mode, we treat vls mode as aggregated and we will
have TFmode here.  Unforturnately, the emit_move_multi_word cannot take
care of TFmode elegantly and we go to gpr for V2DF mode.

The riscv regression passed for this patch.

gcc/ChangeLog:

* config/riscv/riscv.cc (riscv_v_ext_vector_or_tuple_mode_p):
New predicate function for vector or tuple vector.
(riscv_v_vls_mode_aggregate_reg_count): New function to
calculate the gpr/fpr count required by vls mode.
(riscv_gpr_unit_size): New function to get gpr in bytes.
(riscv_fpr_unit_size): New function to get fpr in bytes.
(riscv_v_vls_to_gpr_mode): New function convert vls mode to gpr mode.
(riscv_v_vls_to_fpr_mode): New function convert vls mode to fpr mode.
(riscv_pass_vls_aggregate_in_gpr_or_fpr): New function to return
the rtx of gpr/fpr for vls mode.
(riscv_mode_pass_by_reference_p): New predicate function to
indicate the mode will be passed by reference or not.
(riscv_get_arg_info): Add vls mode handling.
(riscv_pass_by_reference): Return false if arg info has no zero
gpr count.

gcc/testsuite/ChangeLog:

* gcc.target/riscv/rvv/autovec/vls/def.h: Add helper marcos.
* gcc.target/riscv/rvv/autovec/vls/calling-convention-1.c: New test.
* gcc.target/riscv/rvv/autovec/vls/calling-convention-10.c: New test.
* gcc.target/riscv/rvv/autovec/vls/calling-convention-2.c: New test.
* gcc.target/riscv/rvv/autovec/vls/calling-convention-3.c: New test.
* gcc.target/riscv/rvv/autovec/vls/calling-convention-4.c: New test.
* gcc.target/riscv/rvv/autovec/vls/calling-convention-5.c: New test.
* gcc.target/riscv/rvv/autovec/vls/calling-convention-6.c: New test.
* gcc.target/riscv/rvv/autovec/vls/calling-convention-7.c: New test.
* gcc.target/riscv/rvv/autovec/vls/calling-convention-8.c: New test.
* gcc.target/riscv/rvv/autovec/vls/calling-convention-9.c: New test.
* gcc.target/riscv/rvv/autovec/vls/calling-convention-run-1.c: New test.
* gcc.target/riscv/rvv/autovec/vls/calling-convention-run-2.c: New test.
* gcc.target/riscv/rvv/autovec/vls/calling-convention-run-3.c: New test.
* gcc.target/riscv/rvv/autovec/vls/calling-convention-run-4.c: New test.
* gcc.target/riscv/rvv/autovec/vls/calling-convention-run-5.c: New test.
* gcc.target/riscv/rvv/autovec/vls/calling-convention-run-6.c: New test.

Signed-off-by: Pan Li <pan2.li@intel.com<mailto:pan2.li@intel.com>>
---
gcc/config/riscv/riscv.cc                     | 185 +++++++++++++++++-
.../rvv/autovec/vls/calling-convention-1.c    | 154 +++++++++++++++
.../rvv/autovec/vls/calling-convention-10.c   |  51 +++++
.../rvv/autovec/vls/calling-convention-2.c    | 142 ++++++++++++++
.../rvv/autovec/vls/calling-convention-3.c    | 130 ++++++++++++
.../rvv/autovec/vls/calling-convention-4.c    | 118 +++++++++++
.../rvv/autovec/vls/calling-convention-5.c    | 141 +++++++++++++
.../rvv/autovec/vls/calling-convention-6.c    | 129 ++++++++++++
.../rvv/autovec/vls/calling-convention-7.c    | 120 ++++++++++++
.../rvv/autovec/vls/calling-convention-8.c    |  43 ++++
.../rvv/autovec/vls/calling-convention-9.c    |  51 +++++
.../autovec/vls/calling-convention-run-1.c    |  55 ++++++
.../autovec/vls/calling-convention-run-2.c    |  55 ++++++
.../autovec/vls/calling-convention-run-3.c    |  55 ++++++
.../autovec/vls/calling-convention-run-4.c    |  55 ++++++
.../autovec/vls/calling-convention-run-5.c    |  55 ++++++
.../autovec/vls/calling-convention-run-6.c    |  55 ++++++
.../gcc.target/riscv/rvv/autovec/vls/def.h    |  74 +++++++
18 files changed, 1665 insertions(+), 3 deletions(-)
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-1.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-10.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-2.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-3.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-4.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-5.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-6.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-7.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-8.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-9.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-run-1.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-run-2.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-run-3.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-run-4.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-run-5.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-run-6.c

diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 3ba45ffaa74..fb79a475bbe 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -1382,6 +1382,106 @@ riscv_v_ext_mode_p (machine_mode mode)
|| riscv_v_ext_vls_mode_p (mode);
}
+/* Return true if it is either of below modes.
+   1. RVV vector mode.
+   2. RVV tuple mode.  */
+
+static bool
+riscv_v_ext_vector_or_tuple_mode_p (machine_mode mode)
+{
+  return riscv_v_ext_vector_mode_p (mode) || riscv_v_ext_tuple_mode_p (mode);
+}
+
+static unsigned
+riscv_v_vls_mode_aggregate_reg_count (unsigned vls_unit_size,
+       unsigned scalar_unit_size)
+{
+  gcc_assert (vls_unit_size != 0 && scalar_unit_size != 0);
+
+  if (vls_unit_size < scalar_unit_size)
+    return 1;
+
+  return vls_unit_size / scalar_unit_size;
+}
+
+static unsigned short
+riscv_gpr_unit_size ()
+{
+  return GET_MODE_SIZE (Xmode);
+}
+
+static unsigned short
+riscv_fpr_unit_size ()
+{
+  unsigned fpr_size = 0;
+
+  if (TARGET_HARD_FLOAT && !TARGET_DOUBLE_FLOAT)
+    {
+      switch (riscv_abi)
+ {
+   case ABI_LP64F:
+   case ABI_ILP32F:
+     fpr_size = GET_MODE_SIZE (SFmode);
+     break;
+ }
+    }
+
+  if (TARGET_DOUBLE_FLOAT)
+    {
+      switch (riscv_abi)
+ {
+   case ABI_LP64F:
+   case ABI_ILP32F:
+     fpr_size = GET_MODE_SIZE (SFmode);
+     break;
+   case ABI_LP64D:
+   case ABI_ILP32D:
+     fpr_size = GET_MODE_SIZE (DFmode);
+     break;
+ }
+    }
+
+  return fpr_size;
+}
+
+static machine_mode
+riscv_v_vls_to_gpr_mode (unsigned vls_mode_size)
+{
+  switch (vls_mode_size)
+    {
+      case 16:
+ return TImode;
+      case 8:
+ return DImode;
+      case 4:
+ return SImode;
+      case 2:
+ return HImode;
+      case 1:
+ return QImode;
+      default:
+ gcc_unreachable ();
+    }
+}
+
+static machine_mode
+riscv_v_vls_to_fpr_mode (unsigned vls_mode_size)
+{
+  switch (vls_mode_size)
+    {
+      case 16:
+ return TFmode;
+      case 8:
+ return DFmode;
+      case 4:
+ return SFmode;
+      case 2:
+ return HFmode;
+      default:
+ gcc_unreachable ();
+    }
+}
+
/* Call from ADJUST_NUNITS in riscv-modes.def. Return the correct
    NUNITS size for corresponding machine_mode.  */
@@ -4868,6 +4968,63 @@ riscv_pass_fpr_pair (machine_mode mode, unsigned regno1,
   GEN_INT (offset2))));
}
+static rtx
+riscv_pass_vls_aggregate_in_gpr_or_fpr (struct riscv_arg_info *info,
+ machine_mode mode, unsigned gpr_base,
+ unsigned fpr_base)
+{
+  gcc_assert (riscv_v_ext_vls_mode_p (mode));
+
+  unsigned vls_size = GET_MODE_SIZE (mode).to_constant ();
+  unsigned gpr_size = riscv_gpr_unit_size ();
+  unsigned fpr_size = riscv_fpr_unit_size ();
+  unsigned regnum = 0, count = 0;
+  unsigned vls_elem_count = vls_size / GET_MODE_SIZE (GET_MODE_INNER (mode));
+  machine_mode smode = VOIDmode;
+
+  /* For vls floating point >= 16 bytes, it cannot be well token care of when
+     emit_move_multi_word.  For example vls size == 16 bytes when move multi
+     word.  We will hit assert similar to gcc_assert (xpart && ypart).
+     x=(reg:TF 42 fa0)
+     y=(subreg:TF (reg:TI 136) 0)
+
+     Thus, we will go with gpr for vls size >= 16.
+  */
+  if (vls_elem_count <= 2 && FLOAT_MODE_P (mode) && fpr_size && vls_size < 16
+    && IN_RANGE (vls_size, 0, fpr_size * 2))
+    {
+      count = riscv_v_vls_mode_aggregate_reg_count (vls_size, fpr_size);
+
+      if (count + info->fpr_offset <= MAX_ARGS_IN_REGISTERS)
+ {
+   regnum = fpr_base + info->fpr_offset;
+   info->num_fprs = count;
+   smode = riscv_v_vls_to_fpr_mode (vls_size);
+ }
+    }
+  else if (IN_RANGE (vls_size, 0, gpr_size * 2))
+    {
+      count = riscv_v_vls_mode_aggregate_reg_count (vls_size, gpr_size);
+
+      if (count + info->gpr_offset <= MAX_ARGS_IN_REGISTERS)
+ {
+   regnum = gpr_base + info->gpr_offset;
+   info->num_gprs = count;
+   smode = riscv_v_vls_to_gpr_mode (vls_size);
+ }
+    }
+
+  if (!regnum)
+    return NULL_RTX; /* Return NULL_RTX if we cannot find a suitable reg.  */
+
+  gcc_assert (smode != VOIDmode);
+
+  rtx reg = gen_rtx_REG (smode, regnum);
+  rtx x = gen_rtx_EXPR_LIST (VOIDmode, reg, CONST0_RTX (smode));
+
+  return gen_rtx_PARALLEL (mode, gen_rtvec (1, x));
+}
+
/* Initialize a variable CUM of type CUMULATIVE_ARGS
    for a call to a function whose data type is FNTYPE.
    For a library call, FNTYPE is 0.  */
@@ -4975,6 +5132,22 @@ riscv_get_vector_arg (struct riscv_arg_info *info, const CUMULATIVE_ARGS *cum,
   return NULL_RTX;
}
+/* Return true if the argument mode is passed by reference. Aka:
+   1. Scalable vector argument is anonymous.
+   2. The vector abi is disabled for vector or tuple mode.
+   Else return false.  */
+static bool
+riscv_mode_pass_by_reference_p (machine_mode mode, bool named)
+{
+  if (riscv_v_ext_mode_p (mode) && !named)
+    return true;
+
+  if (riscv_v_ext_vector_or_tuple_mode_p (mode) && !riscv_vector_abi)
+    return true;
+
+  return false;
+}
+
/* Fill INFO with information about a single argument, and return an RTL
    pattern to pass or return the argument. Return NULL_RTX if argument cannot
    pass or return in registers, then the argument may be passed by reference or
@@ -4997,9 +5170,7 @@ riscv_get_arg_info (struct riscv_arg_info *info, const CUMULATIVE_ARGS *cum,
   info->gpr_offset = cum->num_gprs;
   info->fpr_offset = cum->num_fprs;
-  /* When disable vector_abi or scalable vector argument is anonymous, this
-     argument is passed by reference.  */
-  if (riscv_v_ext_mode_p (mode) && (!riscv_vector_abi || !named))
+  if (riscv_mode_pass_by_reference_p (mode, named))
     return NULL_RTX;
   if (named)
@@ -5064,6 +5235,10 @@ riscv_get_arg_info (struct riscv_arg_info *info, const CUMULATIVE_ARGS *cum,
      fields[1].offset);
}
+      if (riscv_v_ext_vls_mode_p (mode))
+ return riscv_pass_vls_aggregate_in_gpr_or_fpr (info, mode, gpr_base,
+        fpr_base);
+
       /* For scalable vector argument.  */
       if (riscv_vector_type_p (type) && riscv_v_ext_mode_p (mode))
return riscv_get_vector_arg (info, cum, mode, return_p);
@@ -5196,6 +5371,10 @@ riscv_pass_by_reference (cumulative_args_t cum_v, const function_arg_info &arg)
       if (info.num_fprs)
return false;
+      /* Don't pass by reference if we can use general register(s) for vls.  */
+      if (info.num_gprs && riscv_v_ext_vls_mode_p (arg.mode))
+ return false;
+
       /* Don't pass by reference if we can use vector register groups.  */
       if (info.num_vrs > 0 || info.num_mrs > 0)
return false;
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-1.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-1.c
new file mode 100644
index 00000000000..41e31c258f8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-1.c
@@ -0,0 +1,154 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv_zvl4096b --param riscv-autovec-preference=scalable -mabi=lp64d -O3" } */
+
+#include "def.h"
+
+DEF_RET1_ARG0 (v1qi)
+DEF_RET1_ARG0 (v2qi)
+DEF_RET1_ARG0 (v4qi)
+DEF_RET1_ARG0 (v8qi)
+DEF_RET1_ARG0 (v16qi)
+DEF_RET1_ARG0 (v32qi)
+DEF_RET1_ARG0 (v64qi)
+DEF_RET1_ARG0 (v128qi)
+DEF_RET1_ARG0 (v256qi)
+DEF_RET1_ARG0 (v512qi)
+DEF_RET1_ARG0 (v1024qi)
+DEF_RET1_ARG0 (v2048qi)
+DEF_RET1_ARG0 (v4096qi)
+
+DEF_RET1_ARG1 (v1qi)
+DEF_RET1_ARG1 (v2qi)
+DEF_RET1_ARG1 (v4qi)
+DEF_RET1_ARG1 (v8qi)
+DEF_RET1_ARG1 (v16qi)
+DEF_RET1_ARG1 (v32qi)
+DEF_RET1_ARG1 (v64qi)
+DEF_RET1_ARG1 (v128qi)
+DEF_RET1_ARG1 (v256qi)
+DEF_RET1_ARG1 (v512qi)
+DEF_RET1_ARG1 (v1024qi)
+DEF_RET1_ARG1 (v2048qi)
+DEF_RET1_ARG1 (v4096qi)
+
+DEF_RET1_ARG2 (v1qi)
+DEF_RET1_ARG2 (v2qi)
+DEF_RET1_ARG2 (v4qi)
+DEF_RET1_ARG2 (v8qi)
+DEF_RET1_ARG2 (v16qi)
+DEF_RET1_ARG2 (v32qi)
+DEF_RET1_ARG2 (v64qi)
+DEF_RET1_ARG2 (v128qi)
+DEF_RET1_ARG2 (v256qi)
+DEF_RET1_ARG2 (v512qi)
+DEF_RET1_ARG2 (v1024qi)
+DEF_RET1_ARG2 (v2048qi)
+DEF_RET1_ARG2 (v4096qi)
+
+DEF_RET1_ARG3 (v1qi)
+DEF_RET1_ARG3 (v2qi)
+DEF_RET1_ARG3 (v4qi)
+DEF_RET1_ARG3 (v8qi)
+DEF_RET1_ARG3 (v16qi)
+DEF_RET1_ARG3 (v32qi)
+DEF_RET1_ARG3 (v64qi)
+DEF_RET1_ARG3 (v128qi)
+DEF_RET1_ARG3 (v256qi)
+DEF_RET1_ARG3 (v512qi)
+DEF_RET1_ARG3 (v1024qi)
+DEF_RET1_ARG3 (v2048qi)
+DEF_RET1_ARG3 (v4096qi)
+
+DEF_RET1_ARG4 (v1qi)
+DEF_RET1_ARG4 (v2qi)
+DEF_RET1_ARG4 (v4qi)
+DEF_RET1_ARG4 (v8qi)
+DEF_RET1_ARG4 (v16qi)
+DEF_RET1_ARG4 (v32qi)
+DEF_RET1_ARG4 (v64qi)
+DEF_RET1_ARG4 (v128qi)
+DEF_RET1_ARG4 (v256qi)
+DEF_RET1_ARG4 (v512qi)
+DEF_RET1_ARG4 (v1024qi)
+DEF_RET1_ARG4 (v2048qi)
+DEF_RET1_ARG4 (v4096qi)
+
+DEF_RET1_ARG5 (v1qi)
+DEF_RET1_ARG5 (v2qi)
+DEF_RET1_ARG5 (v4qi)
+DEF_RET1_ARG5 (v8qi)
+DEF_RET1_ARG5 (v16qi)
+DEF_RET1_ARG5 (v32qi)
+DEF_RET1_ARG5 (v64qi)
+DEF_RET1_ARG5 (v128qi)
+DEF_RET1_ARG5 (v256qi)
+DEF_RET1_ARG5 (v512qi)
+DEF_RET1_ARG5 (v1024qi)
+DEF_RET1_ARG5 (v2048qi)
+DEF_RET1_ARG5 (v4096qi)
+
+DEF_RET1_ARG6 (v1qi)
+DEF_RET1_ARG6 (v2qi)
+DEF_RET1_ARG6 (v4qi)
+DEF_RET1_ARG6 (v8qi)
+DEF_RET1_ARG6 (v16qi)
+DEF_RET1_ARG6 (v32qi)
+DEF_RET1_ARG6 (v64qi)
+DEF_RET1_ARG6 (v128qi)
+DEF_RET1_ARG6 (v256qi)
+DEF_RET1_ARG6 (v512qi)
+DEF_RET1_ARG6 (v1024qi)
+DEF_RET1_ARG6 (v2048qi)
+DEF_RET1_ARG6 (v4096qi)
+
+DEF_RET1_ARG7 (v1qi)
+DEF_RET1_ARG7 (v2qi)
+DEF_RET1_ARG7 (v4qi)
+DEF_RET1_ARG7 (v8qi)
+DEF_RET1_ARG7 (v16qi)
+DEF_RET1_ARG7 (v32qi)
+DEF_RET1_ARG7 (v64qi)
+DEF_RET1_ARG7 (v128qi)
+DEF_RET1_ARG7 (v256qi)
+DEF_RET1_ARG7 (v512qi)
+DEF_RET1_ARG7 (v1024qi)
+DEF_RET1_ARG7 (v2048qi)
+DEF_RET1_ARG7 (v4096qi)
+
+DEF_RET1_ARG8 (v1qi)
+DEF_RET1_ARG8 (v2qi)
+DEF_RET1_ARG8 (v4qi)
+DEF_RET1_ARG8 (v8qi)
+DEF_RET1_ARG8 (v16qi)
+DEF_RET1_ARG8 (v32qi)
+DEF_RET1_ARG8 (v64qi)
+DEF_RET1_ARG8 (v128qi)
+DEF_RET1_ARG8 (v256qi)
+DEF_RET1_ARG8 (v512qi)
+DEF_RET1_ARG8 (v1024qi)
+DEF_RET1_ARG8 (v2048qi)
+DEF_RET1_ARG8 (v4096qi)
+
+DEF_RET1_ARG9 (v1qi)
+DEF_RET1_ARG9 (v2qi)
+DEF_RET1_ARG9 (v4qi)
+DEF_RET1_ARG9 (v8qi)
+DEF_RET1_ARG9 (v16qi)
+DEF_RET1_ARG9 (v32qi)
+DEF_RET1_ARG9 (v64qi)
+DEF_RET1_ARG9 (v128qi)
+DEF_RET1_ARG9 (v256qi)
+DEF_RET1_ARG9 (v512qi)
+DEF_RET1_ARG9 (v1024qi)
+DEF_RET1_ARG9 (v2048qi)
+DEF_RET1_ARG9 (v4096qi)
+
+/* { dg-final { scan-assembler-times {li\s+a[0-1],\s*0} 9 } } */
+/* { dg-final { scan-assembler-times {lbu\s+a0,\s*[0-9]+\(sp\)} 8 } } */
+/* { dg-final { scan-assembler-times {lhu\s+a0,\s*[0-9]+\(sp\)} 8 } } */
+/* { dg-final { scan-assembler-times {lw\s+a0,\s*[0-9]+\(sp\)} 8 } } */
+/* { dg-final { scan-assembler-times {ld\s+a[0-1],\s*[0-9]+\(sp\)} 35 } } */
+/* { dg-final { scan-assembler-times {sb\s+a[0-7],\s*[0-9]+\(sp\)} 43 } } */
+/* { dg-final { scan-assembler-times {sh\s+a[0-7],\s*[0-9]+\(sp\)} 43 } } */
+/* { dg-final { scan-assembler-times {sw\s+a[0-7],\s*[0-9]+\(sp\)} 43 } } */
+/* { dg-final { scan-assembler-times {sd\s+a[0-7],\s*[0-9]+\(sp\)} 103 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-10.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-10.c
new file mode 100644
index 00000000000..0abc6cf0146
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-10.c
@@ -0,0 +1,51 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv_zvfh_zvl4096b -mabi=lp64 --param riscv-autovec-preference=scalable -O3 -fno-schedule-insns -fno-schedule-insns2" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include "def.h"
+
+/*
+** v4hf_RET1_ARG1:
+** ret
+*/
+DEF_RET1_ARG1 (v4hf)
+
+/*
+** v2sf_RET1_ARG2:
+** addi\s+sp,\s*sp,\s*-16
+** sd\s+a0,\s*0\(sp\)
+** sd\s+a1,\s*8\(sp\)
+** ...
+** ld\s+a0,\s*0\(sp\)
+** addi\s+sp,\s*sp,\s*16
+** jr\s+ra
+*/
+DEF_RET1_ARG2 (v2sf)
+
+/*
+** v4sf_RET1_ARG2:
+** addi\s+sp,\s*sp,\s*-32
+** sd\s+a0,\s*0\(sp\)
+** sd\s+a1,\s*8\(sp\)
+** sd\s+a2,\s*16\(sp\)
+** sd\s+a3,\s*24\(sp\)
+** ...
+** ld\s+a0,\s*0\(sp\)
+** ld\s+a1,\s*8\(sp\)
+** addi\s+sp,\s*sp,\s*32
+** jr\s+ra
+*/
+DEF_RET1_ARG2 (v4sf)
+
+/*
+** v1df_RET1_ARG3:
+** addi\s+sp,\s*sp,\s*-32
+** sd\s+a0,\s*8\(sp\)
+** sd\s+a1,\s*16\(sp\)
+** sd\s+a2,\s*24\(sp\)
+** ...
+** ld\s+a0,\s*8\(sp\)
+** addi\s+sp,\s*sp,\s*32
+** jr\s+ra
+*/
+DEF_RET1_ARG3 (v1df)
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-2.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-2.c
new file mode 100644
index 00000000000..8544f160e93
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-2.c
@@ -0,0 +1,142 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv_zvl4096b --param riscv-autovec-preference=scalable -mabi=lp64d -O3" } */
+
+#include "def.h"
+
+DEF_RET1_ARG0 (v1hi)
+DEF_RET1_ARG0 (v2hi)
+DEF_RET1_ARG0 (v4hi)
+DEF_RET1_ARG0 (v8hi)
+DEF_RET1_ARG0 (v16hi)
+DEF_RET1_ARG0 (v32hi)
+DEF_RET1_ARG0 (v64hi)
+DEF_RET1_ARG0 (v128hi)
+DEF_RET1_ARG0 (v256hi)
+DEF_RET1_ARG0 (v512hi)
+DEF_RET1_ARG0 (v1024hi)
+DEF_RET1_ARG0 (v2048hi)
+
+DEF_RET1_ARG1 (v1hi)
+DEF_RET1_ARG1 (v2hi)
+DEF_RET1_ARG1 (v4hi)
+DEF_RET1_ARG1 (v8hi)
+DEF_RET1_ARG1 (v16hi)
+DEF_RET1_ARG1 (v32hi)
+DEF_RET1_ARG1 (v64hi)
+DEF_RET1_ARG1 (v128hi)
+DEF_RET1_ARG1 (v256hi)
+DEF_RET1_ARG1 (v512hi)
+DEF_RET1_ARG1 (v1024hi)
+DEF_RET1_ARG1 (v2048hi)
+
+DEF_RET1_ARG2 (v1hi)
+DEF_RET1_ARG2 (v2hi)
+DEF_RET1_ARG2 (v4hi)
+DEF_RET1_ARG2 (v8hi)
+DEF_RET1_ARG2 (v16hi)
+DEF_RET1_ARG2 (v32hi)
+DEF_RET1_ARG2 (v64hi)
+DEF_RET1_ARG2 (v128hi)
+DEF_RET1_ARG2 (v256hi)
+DEF_RET1_ARG2 (v512hi)
+DEF_RET1_ARG2 (v1024hi)
+DEF_RET1_ARG2 (v2048hi)
+
+DEF_RET1_ARG3 (v1hi)
+DEF_RET1_ARG3 (v2hi)
+DEF_RET1_ARG3 (v4hi)
+DEF_RET1_ARG3 (v8hi)
+DEF_RET1_ARG3 (v16hi)
+DEF_RET1_ARG3 (v32hi)
+DEF_RET1_ARG3 (v64hi)
+DEF_RET1_ARG3 (v128hi)
+DEF_RET1_ARG3 (v256hi)
+DEF_RET1_ARG3 (v512hi)
+DEF_RET1_ARG3 (v1024hi)
+DEF_RET1_ARG3 (v2048hi)
+
+DEF_RET1_ARG4 (v1hi)
+DEF_RET1_ARG4 (v2hi)
+DEF_RET1_ARG4 (v4hi)
+DEF_RET1_ARG4 (v8hi)
+DEF_RET1_ARG4 (v16hi)
+DEF_RET1_ARG4 (v32hi)
+DEF_RET1_ARG4 (v64hi)
+DEF_RET1_ARG4 (v128hi)
+DEF_RET1_ARG4 (v256hi)
+DEF_RET1_ARG4 (v512hi)
+DEF_RET1_ARG4 (v1024hi)
+DEF_RET1_ARG4 (v2048hi)
+
+DEF_RET1_ARG5 (v1hi)
+DEF_RET1_ARG5 (v2hi)
+DEF_RET1_ARG5 (v4hi)
+DEF_RET1_ARG5 (v8hi)
+DEF_RET1_ARG5 (v16hi)
+DEF_RET1_ARG5 (v32hi)
+DEF_RET1_ARG5 (v64hi)
+DEF_RET1_ARG5 (v128hi)
+DEF_RET1_ARG5 (v256hi)
+DEF_RET1_ARG5 (v512hi)
+DEF_RET1_ARG5 (v1024hi)
+DEF_RET1_ARG5 (v2048hi)
+
+DEF_RET1_ARG6 (v1hi)
+DEF_RET1_ARG6 (v2hi)
+DEF_RET1_ARG6 (v4hi)
+DEF_RET1_ARG6 (v8hi)
+DEF_RET1_ARG6 (v16hi)
+DEF_RET1_ARG6 (v32hi)
+DEF_RET1_ARG6 (v64hi)
+DEF_RET1_ARG6 (v128hi)
+DEF_RET1_ARG6 (v256hi)
+DEF_RET1_ARG6 (v512hi)
+DEF_RET1_ARG6 (v1024hi)
+DEF_RET1_ARG6 (v2048hi)
+
+DEF_RET1_ARG7 (v1hi)
+DEF_RET1_ARG7 (v2hi)
+DEF_RET1_ARG7 (v4hi)
+DEF_RET1_ARG7 (v8hi)
+DEF_RET1_ARG7 (v16hi)
+DEF_RET1_ARG7 (v32hi)
+DEF_RET1_ARG7 (v64hi)
+DEF_RET1_ARG7 (v128hi)
+DEF_RET1_ARG7 (v256hi)
+DEF_RET1_ARG7 (v512hi)
+DEF_RET1_ARG7 (v1024hi)
+DEF_RET1_ARG7 (v2048hi)
+
+DEF_RET1_ARG8 (v1hi)
+DEF_RET1_ARG8 (v2hi)
+DEF_RET1_ARG8 (v4hi)
+DEF_RET1_ARG8 (v8hi)
+DEF_RET1_ARG8 (v16hi)
+DEF_RET1_ARG8 (v32hi)
+DEF_RET1_ARG8 (v64hi)
+DEF_RET1_ARG8 (v128hi)
+DEF_RET1_ARG8 (v256hi)
+DEF_RET1_ARG8 (v512hi)
+DEF_RET1_ARG8 (v1024hi)
+DEF_RET1_ARG8 (v2048hi)
+
+DEF_RET1_ARG9 (v1hi)
+DEF_RET1_ARG9 (v2hi)
+DEF_RET1_ARG9 (v4hi)
+DEF_RET1_ARG9 (v8hi)
+DEF_RET1_ARG9 (v16hi)
+DEF_RET1_ARG9 (v32hi)
+DEF_RET1_ARG9 (v64hi)
+DEF_RET1_ARG9 (v128hi)
+DEF_RET1_ARG9 (v256hi)
+DEF_RET1_ARG9 (v512hi)
+DEF_RET1_ARG9 (v1024hi)
+DEF_RET1_ARG9 (v2048hi)
+
+/* { dg-final { scan-assembler-times {li\s+a[0-1],\s*0} 8 } } */
+/* { dg-final { scan-assembler-times {lhu\s+a0,\s*[0-9]+\(sp\)} 8 } } */
+/* { dg-final { scan-assembler-times {lw\s+a0,\s*[0-9]+\(sp\)} 8 } } */
+/* { dg-final { scan-assembler-times {ld\s+a[0-1],\s*[0-9]+\(sp\)} 33 } } */
+/* { dg-final { scan-assembler-times {sh\s+a[0-7],\s*[0-9]+\(sp\)} 43 } } */
+/* { dg-final { scan-assembler-times {sw\s+a[0-7],\s*[0-9]+\(sp\)} 43 } } */
+/* { dg-final { scan-assembler-times {sd\s+a[0-7],\s*[0-9]+\(sp\)} 103 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-3.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-3.c
new file mode 100644
index 00000000000..17b06933c72
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-3.c
@@ -0,0 +1,130 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv_zvl4096b --param riscv-autovec-preference=scalable -mabi=lp64d -O3" } */
+
+#include "def.h"
+
+DEF_RET1_ARG0 (v1si)
+DEF_RET1_ARG0 (v2si)
+DEF_RET1_ARG0 (v4si)
+DEF_RET1_ARG0 (v8si)
+DEF_RET1_ARG0 (v16si)
+DEF_RET1_ARG0 (v32si)
+DEF_RET1_ARG0 (v64si)
+DEF_RET1_ARG0 (v128si)
+DEF_RET1_ARG0 (v256si)
+DEF_RET1_ARG0 (v512si)
+DEF_RET1_ARG0 (v1024si)
+
+DEF_RET1_ARG1 (v1si)
+DEF_RET1_ARG1 (v2si)
+DEF_RET1_ARG1 (v4si)
+DEF_RET1_ARG1 (v8si)
+DEF_RET1_ARG1 (v16si)
+DEF_RET1_ARG1 (v32si)
+DEF_RET1_ARG1 (v64si)
+DEF_RET1_ARG1 (v128si)
+DEF_RET1_ARG1 (v256si)
+DEF_RET1_ARG1 (v512si)
+DEF_RET1_ARG1 (v1024si)
+
+DEF_RET1_ARG2 (v1si)
+DEF_RET1_ARG2 (v2si)
+DEF_RET1_ARG2 (v4si)
+DEF_RET1_ARG2 (v8si)
+DEF_RET1_ARG2 (v16si)
+DEF_RET1_ARG2 (v32si)
+DEF_RET1_ARG2 (v64si)
+DEF_RET1_ARG2 (v128si)
+DEF_RET1_ARG2 (v256si)
+DEF_RET1_ARG2 (v512si)
+DEF_RET1_ARG2 (v1024si)
+
+DEF_RET1_ARG3 (v1si)
+DEF_RET1_ARG3 (v2si)
+DEF_RET1_ARG3 (v4si)
+DEF_RET1_ARG3 (v8si)
+DEF_RET1_ARG3 (v16si)
+DEF_RET1_ARG3 (v32si)
+DEF_RET1_ARG3 (v64si)
+DEF_RET1_ARG3 (v128si)
+DEF_RET1_ARG3 (v256si)
+DEF_RET1_ARG3 (v512si)
+DEF_RET1_ARG3 (v1024si)
+
+DEF_RET1_ARG4 (v1si)
+DEF_RET1_ARG4 (v2si)
+DEF_RET1_ARG4 (v4si)
+DEF_RET1_ARG4 (v8si)
+DEF_RET1_ARG4 (v16si)
+DEF_RET1_ARG4 (v32si)
+DEF_RET1_ARG4 (v64si)
+DEF_RET1_ARG4 (v128si)
+DEF_RET1_ARG4 (v256si)
+DEF_RET1_ARG4 (v512si)
+DEF_RET1_ARG4 (v1024si)
+
+DEF_RET1_ARG5 (v1si)
+DEF_RET1_ARG5 (v2si)
+DEF_RET1_ARG5 (v4si)
+DEF_RET1_ARG5 (v8si)
+DEF_RET1_ARG5 (v16si)
+DEF_RET1_ARG5 (v32si)
+DEF_RET1_ARG5 (v64si)
+DEF_RET1_ARG5 (v128si)
+DEF_RET1_ARG5 (v256si)
+DEF_RET1_ARG5 (v512si)
+DEF_RET1_ARG5 (v1024si)
+
+DEF_RET1_ARG6 (v1si)
+DEF_RET1_ARG6 (v2si)
+DEF_RET1_ARG6 (v4si)
+DEF_RET1_ARG6 (v8si)
+DEF_RET1_ARG6 (v16si)
+DEF_RET1_ARG6 (v32si)
+DEF_RET1_ARG6 (v64si)
+DEF_RET1_ARG6 (v128si)
+DEF_RET1_ARG6 (v256si)
+DEF_RET1_ARG6 (v512si)
+DEF_RET1_ARG6 (v1024si)
+
+DEF_RET1_ARG7 (v1si)
+DEF_RET1_ARG7 (v2si)
+DEF_RET1_ARG7 (v4si)
+DEF_RET1_ARG7 (v8si)
+DEF_RET1_ARG7 (v16si)
+DEF_RET1_ARG7 (v32si)
+DEF_RET1_ARG7 (v64si)
+DEF_RET1_ARG7 (v128si)
+DEF_RET1_ARG7 (v256si)
+DEF_RET1_ARG7 (v512si)
+DEF_RET1_ARG7 (v1024si)
+
+DEF_RET1_ARG8 (v1si)
+DEF_RET1_ARG8 (v2si)
+DEF_RET1_ARG8 (v4si)
+DEF_RET1_ARG8 (v8si)
+DEF_RET1_ARG8 (v16si)
+DEF_RET1_ARG8 (v32si)
+DEF_RET1_ARG8 (v64si)
+DEF_RET1_ARG8 (v128si)
+DEF_RET1_ARG8 (v256si)
+DEF_RET1_ARG8 (v512si)
+DEF_RET1_ARG8 (v1024si)
+
+DEF_RET1_ARG9 (v1si)
+DEF_RET1_ARG9 (v2si)
+DEF_RET1_ARG9 (v4si)
+DEF_RET1_ARG9 (v8si)
+DEF_RET1_ARG9 (v16si)
+DEF_RET1_ARG9 (v32si)
+DEF_RET1_ARG9 (v64si)
+DEF_RET1_ARG9 (v128si)
+DEF_RET1_ARG9 (v256si)
+DEF_RET1_ARG9 (v512si)
+DEF_RET1_ARG9 (v1024si)
+
+/* { dg-final { scan-assembler-times {li\s+a[0-1],\s*0} 7 } } */
+/* { dg-final { scan-assembler-times {lw\s+a0,\s*[0-9]+\(sp\)} 8 } } */
+/* { dg-final { scan-assembler-times {ld\s+a[0-1],\s*[0-9]+\(sp\)} 31 } } */
+/* { dg-final { scan-assembler-times {sw\s+a[0-7],\s*[0-9]+\(sp\)} 43 } } */
+/* { dg-final { scan-assembler-times {sd\s+a[0-7],\s*[0-9]+\(sp\)} 103 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-4.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-4.c
new file mode 100644
index 00000000000..8c3f6ba98e3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-4.c
@@ -0,0 +1,118 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv_zvl4096b --param riscv-autovec-preference=scalable -mabi=lp64d -O3" } */
+
+#include "def.h"
+
+DEF_RET1_ARG0 (v1di)
+DEF_RET1_ARG0 (v2di)
+DEF_RET1_ARG0 (v4di)
+DEF_RET1_ARG0 (v8di)
+DEF_RET1_ARG0 (v16di)
+DEF_RET1_ARG0 (v32di)
+DEF_RET1_ARG0 (v64di)
+DEF_RET1_ARG0 (v128di)
+DEF_RET1_ARG0 (v256di)
+DEF_RET1_ARG0 (v512di)
+
+DEF_RET1_ARG1 (v1di)
+DEF_RET1_ARG1 (v2di)
+DEF_RET1_ARG1 (v4di)
+DEF_RET1_ARG1 (v8di)
+DEF_RET1_ARG1 (v16di)
+DEF_RET1_ARG1 (v32di)
+DEF_RET1_ARG1 (v64di)
+DEF_RET1_ARG1 (v128di)
+DEF_RET1_ARG1 (v256di)
+DEF_RET1_ARG1 (v512di)
+
+DEF_RET1_ARG2 (v1di)
+DEF_RET1_ARG2 (v2di)
+DEF_RET1_ARG2 (v4di)
+DEF_RET1_ARG2 (v8di)
+DEF_RET1_ARG2 (v16di)
+DEF_RET1_ARG2 (v32di)
+DEF_RET1_ARG2 (v64di)
+DEF_RET1_ARG2 (v128di)
+DEF_RET1_ARG2 (v256di)
+DEF_RET1_ARG2 (v512di)
+
+DEF_RET1_ARG3 (v1di)
+DEF_RET1_ARG3 (v2di)
+DEF_RET1_ARG3 (v4di)
+DEF_RET1_ARG3 (v8di)
+DEF_RET1_ARG3 (v16di)
+DEF_RET1_ARG3 (v32di)
+DEF_RET1_ARG3 (v64di)
+DEF_RET1_ARG3 (v128di)
+DEF_RET1_ARG3 (v256di)
+DEF_RET1_ARG3 (v512di)
+
+DEF_RET1_ARG4 (v1di)
+DEF_RET1_ARG4 (v2di)
+DEF_RET1_ARG4 (v4di)
+DEF_RET1_ARG4 (v8di)
+DEF_RET1_ARG4 (v16di)
+DEF_RET1_ARG4 (v32di)
+DEF_RET1_ARG4 (v64di)
+DEF_RET1_ARG4 (v128di)
+DEF_RET1_ARG4 (v256di)
+DEF_RET1_ARG4 (v512di)
+
+DEF_RET1_ARG5 (v1di)
+DEF_RET1_ARG5 (v2di)
+DEF_RET1_ARG5 (v4di)
+DEF_RET1_ARG5 (v8di)
+DEF_RET1_ARG5 (v16di)
+DEF_RET1_ARG5 (v32di)
+DEF_RET1_ARG5 (v64di)
+DEF_RET1_ARG5 (v128di)
+DEF_RET1_ARG5 (v256di)
+DEF_RET1_ARG5 (v512di)
+
+DEF_RET1_ARG6 (v1di)
+DEF_RET1_ARG6 (v2di)
+DEF_RET1_ARG6 (v4di)
+DEF_RET1_ARG6 (v8di)
+DEF_RET1_ARG6 (v16di)
+DEF_RET1_ARG6 (v32di)
+DEF_RET1_ARG6 (v64di)
+DEF_RET1_ARG6 (v128di)
+DEF_RET1_ARG6 (v256di)
+DEF_RET1_ARG6 (v512di)
+
+DEF_RET1_ARG7 (v1di)
+DEF_RET1_ARG7 (v2di)
+DEF_RET1_ARG7 (v4di)
+DEF_RET1_ARG7 (v8di)
+DEF_RET1_ARG7 (v16di)
+DEF_RET1_ARG7 (v32di)
+DEF_RET1_ARG7 (v64di)
+DEF_RET1_ARG7 (v128di)
+DEF_RET1_ARG7 (v256di)
+DEF_RET1_ARG7 (v512di)
+
+DEF_RET1_ARG8 (v1di)
+DEF_RET1_ARG8 (v2di)
+DEF_RET1_ARG8 (v4di)
+DEF_RET1_ARG8 (v8di)
+DEF_RET1_ARG8 (v16di)
+DEF_RET1_ARG8 (v32di)
+DEF_RET1_ARG8 (v64di)
+DEF_RET1_ARG8 (v128di)
+DEF_RET1_ARG8 (v256di)
+DEF_RET1_ARG8 (v512di)
+
+DEF_RET1_ARG9 (v1di)
+DEF_RET1_ARG9 (v2di)
+DEF_RET1_ARG9 (v4di)
+DEF_RET1_ARG9 (v8di)
+DEF_RET1_ARG9 (v16di)
+DEF_RET1_ARG9 (v32di)
+DEF_RET1_ARG9 (v64di)
+DEF_RET1_ARG9 (v128di)
+DEF_RET1_ARG9 (v256di)
+DEF_RET1_ARG9 (v512di)
+
+/* { dg-final { scan-assembler-times {li\s+a[0-1],\s*0} 6 } } */
+/* { dg-final { scan-assembler-times {ld\s+a[0-1],\s*[0-9]+\(sp\)} 29 } } */
+/* { dg-final { scan-assembler-times {sd\s+a[0-7],\s*[0-9]+\(sp\)} 103 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-5.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-5.c
new file mode 100644
index 00000000000..cfa4f5db372
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-5.c
@@ -0,0 +1,141 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv_zvfh_zvl4096b --param riscv-autovec-preference=scalable -mabi=lp64d -O3" } */
+
+#include "def.h"
+
+DEF_RET1_ARG0 (v1hf)
+DEF_RET1_ARG0 (v2hf)
+DEF_RET1_ARG0 (v4hf)
+DEF_RET1_ARG0 (v8hf)
+DEF_RET1_ARG0 (v16hf)
+DEF_RET1_ARG0 (v32hf)
+DEF_RET1_ARG0 (v64hf)
+DEF_RET1_ARG0 (v128hf)
+DEF_RET1_ARG0 (v256hf)
+DEF_RET1_ARG0 (v512hf)
+DEF_RET1_ARG0 (v1024hf)
+DEF_RET1_ARG0 (v2048hf)
+
+DEF_RET1_ARG1 (v1hf)
+DEF_RET1_ARG1 (v2hf)
+DEF_RET1_ARG1 (v4hf)
+DEF_RET1_ARG1 (v8hf)
+DEF_RET1_ARG1 (v16hf)
+DEF_RET1_ARG1 (v32hf)
+DEF_RET1_ARG1 (v64hf)
+DEF_RET1_ARG1 (v128hf)
+DEF_RET1_ARG1 (v256hf)
+DEF_RET1_ARG1 (v512hf)
+DEF_RET1_ARG1 (v1024hf)
+DEF_RET1_ARG1 (v2048hf)
+
+DEF_RET1_ARG2 (v1hf)
+DEF_RET1_ARG2 (v2hf)
+DEF_RET1_ARG2 (v4hf)
+DEF_RET1_ARG2 (v8hf)
+DEF_RET1_ARG2 (v16hf)
+DEF_RET1_ARG2 (v32hf)
+DEF_RET1_ARG2 (v64hf)
+DEF_RET1_ARG2 (v128hf)
+DEF_RET1_ARG2 (v256hf)
+DEF_RET1_ARG2 (v512hf)
+DEF_RET1_ARG2 (v1024hf)
+DEF_RET1_ARG2 (v2048hf)
+
+DEF_RET1_ARG3 (v1hf)
+DEF_RET1_ARG3 (v2hf)
+DEF_RET1_ARG3 (v4hf)
+DEF_RET1_ARG3 (v8hf)
+DEF_RET1_ARG3 (v16hf)
+DEF_RET1_ARG3 (v32hf)
+DEF_RET1_ARG3 (v64hf)
+DEF_RET1_ARG3 (v128hf)
+DEF_RET1_ARG3 (v256hf)
+DEF_RET1_ARG3 (v512hf)
+DEF_RET1_ARG3 (v1024hf)
+DEF_RET1_ARG3 (v2048hf)
+
+DEF_RET1_ARG4 (v1hf)
+DEF_RET1_ARG4 (v2hf)
+DEF_RET1_ARG4 (v4hf)
+DEF_RET1_ARG4 (v8hf)
+DEF_RET1_ARG4 (v16hf)
+DEF_RET1_ARG4 (v32hf)
+DEF_RET1_ARG4 (v64hf)
+DEF_RET1_ARG4 (v128hf)
+DEF_RET1_ARG4 (v256hf)
+DEF_RET1_ARG4 (v512hf)
+DEF_RET1_ARG4 (v1024hf)
+DEF_RET1_ARG4 (v2048hf)
+
+DEF_RET1_ARG5 (v1hf)
+DEF_RET1_ARG5 (v2hf)
+DEF_RET1_ARG5 (v4hf)
+DEF_RET1_ARG5 (v8hf)
+DEF_RET1_ARG5 (v16hf)
+DEF_RET1_ARG5 (v32hf)
+DEF_RET1_ARG5 (v64hf)
+DEF_RET1_ARG5 (v128hf)
+DEF_RET1_ARG5 (v256hf)
+DEF_RET1_ARG5 (v512hf)
+DEF_RET1_ARG5 (v1024hf)
+DEF_RET1_ARG5 (v2048hf)
+
+DEF_RET1_ARG6 (v1hf)
+DEF_RET1_ARG6 (v2hf)
+DEF_RET1_ARG6 (v4hf)
+DEF_RET1_ARG6 (v8hf)
+DEF_RET1_ARG6 (v16hf)
+DEF_RET1_ARG6 (v32hf)
+DEF_RET1_ARG6 (v64hf)
+DEF_RET1_ARG6 (v128hf)
+DEF_RET1_ARG6 (v256hf)
+DEF_RET1_ARG6 (v512hf)
+DEF_RET1_ARG6 (v1024hf)
+DEF_RET1_ARG6 (v2048hf)
+
+DEF_RET1_ARG7 (v1hf)
+DEF_RET1_ARG7 (v2hf)
+DEF_RET1_ARG7 (v4hf)
+DEF_RET1_ARG7 (v8hf)
+DEF_RET1_ARG7 (v16hf)
+DEF_RET1_ARG7 (v32hf)
+DEF_RET1_ARG7 (v64hf)
+DEF_RET1_ARG7 (v128hf)
+DEF_RET1_ARG7 (v256hf)
+DEF_RET1_ARG7 (v512hf)
+DEF_RET1_ARG7 (v1024hf)
+DEF_RET1_ARG7 (v2048hf)
+
+DEF_RET1_ARG8 (v1hf)
+DEF_RET1_ARG8 (v2hf)
+DEF_RET1_ARG8 (v4hf)
+DEF_RET1_ARG8 (v8hf)
+DEF_RET1_ARG8 (v16hf)
+DEF_RET1_ARG8 (v32hf)
+DEF_RET1_ARG8 (v64hf)
+DEF_RET1_ARG8 (v128hf)
+DEF_RET1_ARG8 (v256hf)
+DEF_RET1_ARG8 (v512hf)
+DEF_RET1_ARG8 (v1024hf)
+DEF_RET1_ARG8 (v2048hf)
+
+DEF_RET1_ARG9 (v1hf)
+DEF_RET1_ARG9 (v2hf)
+DEF_RET1_ARG9 (v4hf)
+DEF_RET1_ARG9 (v8hf)
+DEF_RET1_ARG9 (v16hf)
+DEF_RET1_ARG9 (v32hf)
+DEF_RET1_ARG9 (v64hf)
+DEF_RET1_ARG9 (v128hf)
+DEF_RET1_ARG9 (v256hf)
+DEF_RET1_ARG9 (v512hf)
+DEF_RET1_ARG9 (v1024hf)
+DEF_RET1_ARG9 (v2048hf)
+
+/* { dg-final { scan-assembler-times {li\s+a[0-1],\s*0} 6 } } */
+/* { dg-final { scan-assembler-times {flh\s+fa[0-1],\s*[0-9]+\(sp\)} 9 } } */
+/* { dg-final { scan-assembler-times {flw\s+fa[0-1],\s*[0-9]+\(sp\)} 9 } } */
+/* { dg-final { scan-assembler-times {fsh\s+fa[0-7],\s*[0-9]+\(sp\)} 43 } } */
+/* { dg-final { scan-assembler-times {fsw\s+fa[0-7],\s*[0-9]+\(sp\)} 43 } } */
+/* { dg-final { scan-assembler-times {sd\s+a[0-7],\s*[0-9]+\(sp\)} 103 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-6.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-6.c
new file mode 100644
index 00000000000..45a9e2debe8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-6.c
@@ -0,0 +1,129 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv_zvl4096b --param riscv-autovec-preference=scalable -mabi=lp64d -O3" } */
+
+#include "def.h"
+
+DEF_RET1_ARG0 (v1sf)
+DEF_RET1_ARG0 (v2sf)
+DEF_RET1_ARG0 (v4sf)
+DEF_RET1_ARG0 (v8sf)
+DEF_RET1_ARG0 (v16sf)
+DEF_RET1_ARG0 (v32sf)
+DEF_RET1_ARG0 (v64sf)
+DEF_RET1_ARG0 (v128sf)
+DEF_RET1_ARG0 (v256sf)
+DEF_RET1_ARG0 (v512sf)
+DEF_RET1_ARG0 (v1024sf)
+
+DEF_RET1_ARG1 (v1sf)
+DEF_RET1_ARG1 (v2sf)
+DEF_RET1_ARG1 (v4sf)
+DEF_RET1_ARG1 (v8sf)
+DEF_RET1_ARG1 (v16sf)
+DEF_RET1_ARG1 (v32sf)
+DEF_RET1_ARG1 (v64sf)
+DEF_RET1_ARG1 (v128sf)
+DEF_RET1_ARG1 (v256sf)
+DEF_RET1_ARG1 (v512sf)
+DEF_RET1_ARG1 (v1024sf)
+
+DEF_RET1_ARG2 (v1sf)
+DEF_RET1_ARG2 (v2sf)
+DEF_RET1_ARG2 (v4sf)
+DEF_RET1_ARG2 (v8sf)
+DEF_RET1_ARG2 (v16sf)
+DEF_RET1_ARG2 (v32sf)
+DEF_RET1_ARG2 (v64sf)
+DEF_RET1_ARG2 (v128sf)
+DEF_RET1_ARG2 (v256sf)
+DEF_RET1_ARG2 (v512sf)
+DEF_RET1_ARG2 (v1024sf)
+
+DEF_RET1_ARG3 (v1sf)
+DEF_RET1_ARG3 (v2sf)
+DEF_RET1_ARG3 (v4sf)
+DEF_RET1_ARG3 (v8sf)
+DEF_RET1_ARG3 (v16sf)
+DEF_RET1_ARG3 (v32sf)
+DEF_RET1_ARG3 (v64sf)
+DEF_RET1_ARG3 (v128sf)
+DEF_RET1_ARG3 (v256sf)
+DEF_RET1_ARG3 (v512sf)
+DEF_RET1_ARG3 (v1024sf)
+
+DEF_RET1_ARG4 (v1sf)
+DEF_RET1_ARG4 (v2sf)
+DEF_RET1_ARG4 (v4sf)
+DEF_RET1_ARG4 (v8sf)
+DEF_RET1_ARG4 (v16sf)
+DEF_RET1_ARG4 (v32sf)
+DEF_RET1_ARG4 (v64sf)
+DEF_RET1_ARG4 (v128sf)
+DEF_RET1_ARG4 (v256sf)
+DEF_RET1_ARG4 (v512sf)
+DEF_RET1_ARG4 (v1024sf)
+
+DEF_RET1_ARG5 (v1sf)
+DEF_RET1_ARG5 (v2sf)
+DEF_RET1_ARG5 (v4sf)
+DEF_RET1_ARG5 (v8sf)
+DEF_RET1_ARG5 (v16sf)
+DEF_RET1_ARG5 (v32sf)
+DEF_RET1_ARG5 (v64sf)
+DEF_RET1_ARG5 (v128sf)
+DEF_RET1_ARG5 (v256sf)
+DEF_RET1_ARG5 (v512sf)
+DEF_RET1_ARG5 (v1024sf)
+
+DEF_RET1_ARG6 (v1sf)
+DEF_RET1_ARG6 (v2sf)
+DEF_RET1_ARG6 (v4sf)
+DEF_RET1_ARG6 (v8sf)
+DEF_RET1_ARG6 (v16sf)
+DEF_RET1_ARG6 (v32sf)
+DEF_RET1_ARG6 (v64sf)
+DEF_RET1_ARG6 (v128sf)
+DEF_RET1_ARG6 (v256sf)
+DEF_RET1_ARG6 (v512sf)
+DEF_RET1_ARG6 (v1024sf)
+
+DEF_RET1_ARG7 (v1sf)
+DEF_RET1_ARG7 (v2sf)
+DEF_RET1_ARG7 (v4sf)
+DEF_RET1_ARG7 (v8sf)
+DEF_RET1_ARG7 (v16sf)
+DEF_RET1_ARG7 (v32sf)
+DEF_RET1_ARG7 (v64sf)
+DEF_RET1_ARG7 (v128sf)
+DEF_RET1_ARG7 (v256sf)
+DEF_RET1_ARG7 (v512sf)
+DEF_RET1_ARG7 (v1024sf)
+
+DEF_RET1_ARG8 (v1sf)
+DEF_RET1_ARG8 (v2sf)
+DEF_RET1_ARG8 (v4sf)
+DEF_RET1_ARG8 (v8sf)
+DEF_RET1_ARG8 (v16sf)
+DEF_RET1_ARG8 (v32sf)
+DEF_RET1_ARG8 (v64sf)
+DEF_RET1_ARG8 (v128sf)
+DEF_RET1_ARG8 (v256sf)
+DEF_RET1_ARG8 (v512sf)
+DEF_RET1_ARG8 (v1024sf)
+
+DEF_RET1_ARG9 (v1sf)
+DEF_RET1_ARG9 (v2sf)
+DEF_RET1_ARG9 (v4sf)
+DEF_RET1_ARG9 (v8sf)
+DEF_RET1_ARG9 (v16sf)
+DEF_RET1_ARG9 (v32sf)
+DEF_RET1_ARG9 (v64sf)
+DEF_RET1_ARG9 (v128sf)
+DEF_RET1_ARG9 (v256sf)
+DEF_RET1_ARG9 (v512sf)
+DEF_RET1_ARG9 (v1024sf)
+
+/* { dg-final { scan-assembler-times {li\s+a[0-1],\s*0} 5 } } */
+/* { dg-final { scan-assembler-times {flw\s+fa[0-1],\s*[0-9]+\(sp\)} 9 } } */
+/* { dg-final { scan-assembler-times {fsw\s+fa[0-7],\s*[0-9]+\(sp\)} 43 } } */
+/* { dg-final { scan-assembler-times {sd\s+a[0-7],\s*[0-9]+\(sp\)} 60 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-7.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-7.c
new file mode 100644
index 00000000000..a607786afea
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-7.c
@@ -0,0 +1,120 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv_zvl4096b --param riscv-autovec-preference=scalable -mabi=lp64d -O3" } */
+
+#include "def.h"
+
+DEF_RET1_ARG0 (v1df)
+DEF_RET1_ARG0 (v2df)
+DEF_RET1_ARG0 (v4df)
+DEF_RET1_ARG0 (v8df)
+DEF_RET1_ARG0 (v16df)
+DEF_RET1_ARG0 (v32df)
+DEF_RET1_ARG0 (v64df)
+DEF_RET1_ARG0 (v128df)
+DEF_RET1_ARG0 (v256df)
+DEF_RET1_ARG0 (v512df)
+
+DEF_RET1_ARG1 (v1df)
+DEF_RET1_ARG1 (v2df)
+DEF_RET1_ARG1 (v4df)
+DEF_RET1_ARG1 (v8df)
+DEF_RET1_ARG1 (v16df)
+DEF_RET1_ARG1 (v32df)
+DEF_RET1_ARG1 (v64df)
+DEF_RET1_ARG1 (v128df)
+DEF_RET1_ARG1 (v256df)
+DEF_RET1_ARG1 (v512df)
+
+DEF_RET1_ARG2 (v1df)
+DEF_RET1_ARG2 (v2df)
+DEF_RET1_ARG2 (v4df)
+DEF_RET1_ARG2 (v8df)
+DEF_RET1_ARG2 (v16df)
+DEF_RET1_ARG2 (v32df)
+DEF_RET1_ARG2 (v64df)
+DEF_RET1_ARG2 (v128df)
+DEF_RET1_ARG2 (v256df)
+DEF_RET1_ARG2 (v512df)
+
+DEF_RET1_ARG3 (v1df)
+DEF_RET1_ARG3 (v2df)
+DEF_RET1_ARG3 (v4df)
+DEF_RET1_ARG3 (v8df)
+DEF_RET1_ARG3 (v16df)
+DEF_RET1_ARG3 (v32df)
+DEF_RET1_ARG3 (v64df)
+DEF_RET1_ARG3 (v128df)
+DEF_RET1_ARG3 (v256df)
+DEF_RET1_ARG3 (v512df)
+
+DEF_RET1_ARG4 (v1df)
+DEF_RET1_ARG4 (v2df)
+DEF_RET1_ARG4 (v4df)
+DEF_RET1_ARG4 (v8df)
+DEF_RET1_ARG4 (v16df)
+DEF_RET1_ARG4 (v32df)
+DEF_RET1_ARG4 (v64df)
+DEF_RET1_ARG4 (v128df)
+DEF_RET1_ARG4 (v256df)
+DEF_RET1_ARG4 (v512df)
+
+DEF_RET1_ARG5 (v1df)
+DEF_RET1_ARG5 (v2df)
+DEF_RET1_ARG5 (v4df)
+DEF_RET1_ARG5 (v8df)
+DEF_RET1_ARG5 (v16df)
+DEF_RET1_ARG5 (v32df)
+DEF_RET1_ARG5 (v64df)
+DEF_RET1_ARG5 (v128df)
+DEF_RET1_ARG5 (v256df)
+DEF_RET1_ARG5 (v512df)
+
+DEF_RET1_ARG6 (v1df)
+DEF_RET1_ARG6 (v2df)
+DEF_RET1_ARG6 (v4df)
+DEF_RET1_ARG6 (v8df)
+DEF_RET1_ARG6 (v16df)
+DEF_RET1_ARG6 (v32df)
+DEF_RET1_ARG6 (v64df)
+DEF_RET1_ARG6 (v128df)
+DEF_RET1_ARG6 (v256df)
+DEF_RET1_ARG6 (v512df)
+
+DEF_RET1_ARG7 (v1df)
+DEF_RET1_ARG7 (v2df)
+DEF_RET1_ARG7 (v4df)
+DEF_RET1_ARG7 (v8df)
+DEF_RET1_ARG7 (v16df)
+DEF_RET1_ARG7 (v32df)
+DEF_RET1_ARG7 (v64df)
+DEF_RET1_ARG7 (v128df)
+DEF_RET1_ARG7 (v256df)
+DEF_RET1_ARG7 (v512df)
+
+DEF_RET1_ARG8 (v1df)
+DEF_RET1_ARG8 (v2df)
+DEF_RET1_ARG8 (v4df)
+DEF_RET1_ARG8 (v8df)
+DEF_RET1_ARG8 (v16df)
+DEF_RET1_ARG8 (v32df)
+DEF_RET1_ARG8 (v64df)
+DEF_RET1_ARG8 (v128df)
+DEF_RET1_ARG8 (v256df)
+DEF_RET1_ARG8 (v512df)
+
+DEF_RET1_ARG9 (v1df)
+DEF_RET1_ARG9 (v2df)
+DEF_RET1_ARG9 (v4df)
+DEF_RET1_ARG9 (v8df)
+DEF_RET1_ARG9 (v16df)
+DEF_RET1_ARG9 (v32df)
+DEF_RET1_ARG9 (v64df)
+DEF_RET1_ARG9 (v128df)
+DEF_RET1_ARG9 (v256df)
+DEF_RET1_ARG9 (v512df)
+
+/* { dg-final { scan-assembler-times {li\s+a[0-1],\s*0} 5 } } */
+/* { dg-final { scan-assembler-times {ld\s+a[0-1],\s*[0-9]+\(sp\)} 21 } } */
+/* { dg-final { scan-assembler-times {fld\s+fa[0-1],\s*[0-9]+\(sp\)} 9 } } */
+/* { dg-final { scan-assembler-times {sd\s+a[0-7],\s*[0-9]+\(sp\)} 60 } } */
+/* { dg-final { scan-assembler-times {fsd\s+fa[0-7],\s*[0-9]+\(sp\)} 43 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-8.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-8.c
new file mode 100644
index 00000000000..ed66a2cb9eb
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-8.c
@@ -0,0 +1,43 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv_zvl4096b -mabi=lp64d --param riscv-autovec-preference=scalable -O3 -fno-schedule-insns -fno-schedule-insns2" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include "def.h"
+
+/*
+** v8qi_RET1_ARG0:
+** li\s+a0,\s*0
+** ret
+*/
+DEF_RET1_ARG0 (v8qi)
+
+/*
+** v4hi_RET1_ARG1:
+** ret
+*/
+DEF_RET1_ARG1 (v4hi)
+
+/*
+** v2si_RET1_ARG2:
+** addi\s+sp,\s*sp,\s*-16
+** sd\s+a0,\s*0\(sp\)
+** sd\s+a1,\s*8\(sp\)
+** ...
+** ld\s+a0,\s*0\(sp\)
+** addi\s+sp,\s*sp,\s*16
+** jr\s+ra
+*/
+DEF_RET1_ARG2 (v2si)
+
+/*
+** v1di_RET1_ARG3:
+** addi\s+sp,\s*sp,\s*-32
+** sd\s+a0,\s*8\(sp\)
+** sd\s+a1,\s*16\(sp\)
+** sd\s+a2,\s*24\(sp\)
+** ...
+** ld\s+a0,\s*8\(sp\)
+** addi\s+sp,\s*sp,\s*32
+** jr\s+ra
+*/
+DEF_RET1_ARG3 (v1di)
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-9.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-9.c
new file mode 100644
index 00000000000..dd8e709ee59
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-9.c
@@ -0,0 +1,51 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv_zvfh_zvl4096b -mabi=lp64d --param riscv-autovec-preference=scalable -O3 -fno-schedule-insns -fno-schedule-insns2" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include "def.h"
+
+/*
+** v4hf_RET1_ARG1:
+** ret
+*/
+DEF_RET1_ARG1 (v4hf)
+
+/*
+** v2sf_RET1_ARG2:
+** addi\s+sp,\s*sp,\s*-16
+** fsd\s+fa0,\s*0\(sp\)
+** fsd\s+fa1,\s*8\(sp\)
+** ...
+** fld\s+fa0,\s*0\(sp\)
+** addi\s+sp,\s*sp,\s*16
+** jr\s+ra
+*/
+DEF_RET1_ARG2 (v2sf)
+
+/*
+** v4sf_RET1_ARG2:
+** addi\s+sp,\s*sp,\s*-32
+** sd\s+a0,\s*0\(sp\)
+** sd\s+a1,\s*8\(sp\)
+** sd\s+a2,\s*16\(sp\)
+** sd\s+a3,\s*24\(sp\)
+** ...
+** ld\s+a0,\s*0\(sp\)
+** ld\s+a1,\s*8\(sp\)
+** addi\s+sp,\s*sp,\s*32
+** jr\s+ra
+*/
+DEF_RET1_ARG2 (v4sf)
+
+/*
+** v1df_RET1_ARG3:
+** addi\s+sp,\s*sp,\s*-32
+** fsd\s+fa0,\s*8\(sp\)
+** fsd\s+fa1,\s*16\(sp\)
+** fsd\s+fa2,\s*24\(sp\)
+** ...
+** fld\s+fa0,\s*8\(sp\)
+** addi\s+sp,\s*sp,\s*32
+** jr\s+ra
+*/
+DEF_RET1_ARG3 (v1df)
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-run-1.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-run-1.c
new file mode 100644
index 00000000000..d8aa5c51cac
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-run-1.c
@@ -0,0 +1,55 @@
+/* { dg-do run { target { riscv_v } } } */
+/* { dg-additional-options "-std=c99 -fno-vect-cost-model --param=riscv-autovec-preference=scalable" } */
+
+typedef char v16qi __attribute__ ((vector_size (16)));
+
+v16qi
+add (v16qi a1, v16qi a2, v16qi a3, v16qi a4, v16qi a5, v16qi a6, v16qi a7,
+     v16qi a8, v16qi a9)
+{
+  return a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8 + a9;
+}
+
+int
+main ()
+{
+  v16qi a1 = {
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  };
+  v16qi a2 = {
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  };
+  v16qi a3 = {
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  };
+  v16qi a4 = {
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  };
+  v16qi a5 = {
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  };
+  v16qi a6 = {
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  };
+  v16qi a7 = {
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  };
+  v16qi a8 = {
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  };
+  v16qi a9 = {
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  };
+  v16qi expected = {
+    9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+  };
+  v16qi result = add (a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+  unsigned i;
+
+  for (i = 0; i < 16; i++)
+    if (result[i] != expected[i])
+      __builtin_abort ();
+
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-run-2.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-run-2.c
new file mode 100644
index 00000000000..57376a3924c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-run-2.c
@@ -0,0 +1,55 @@
+/* { dg-do run { target { riscv_v } } } */
+/* { dg-additional-options "-std=c99 -fno-vect-cost-model --param=riscv-autovec-preference=scalable" } */
+
+typedef short v8hi __attribute__ ((vector_size (16)));
+
+v8hi
+add (v8hi a1, v8hi a2, v8hi a3, v8hi a4, v8hi a5, v8hi a6, v8hi a7,
+     v8hi a8, v8hi a9)
+{
+  return a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8 + a9;
+}
+
+int
+main ()
+{
+  v8hi a1 = {
+    1, 1, 1, 1, 1, 1, 1, 1,
+  };
+  v8hi a2 = {
+    1, 1, 1, 1, 1, 1, 1, 1,
+  };
+  v8hi a3 = {
+    1, 1, 1, 1, 1, 1, 1, 1,
+  };
+  v8hi a4 = {
+    1, 1, 1, 1, 1, 1, 1, 1,
+  };
+  v8hi a5 = {
+    1, 1, 1, 1, 1, 1, 1, 1,
+  };
+  v8hi a6 = {
+    1, 1, 1, 1, 1, 1, 1, 1,
+  };
+  v8hi a7 = {
+    1, 1, 1, 1, 1, 1, 1, 1,
+  };
+  v8hi a8 = {
+    1, 1, 1, 1, 1, 1, 1, 1,
+  };
+  v8hi a9 = {
+    1, 1, 1, 1, 1, 1, 1, 1,
+  };
+  v8hi expected = {
+    9, 9, 9, 9, 9, 9, 9, 9,
+  };
+  v8hi result = add (a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+  unsigned i;
+
+  for (i = 0; i < 8; i++)
+    if (result[i] != expected[i])
+      __builtin_abort ();
+
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-run-3.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-run-3.c
new file mode 100644
index 00000000000..b37cd5669d4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-run-3.c
@@ -0,0 +1,55 @@
+/* { dg-do run { target { riscv_v } } } */
+/* { dg-additional-options "-std=c99 -fno-vect-cost-model --param=riscv-autovec-preference=scalable" } */
+
+typedef int v4si __attribute__ ((vector_size (16)));
+
+v4si
+add (v4si a1, v4si a2, v4si a3, v4si a4, v4si a5, v4si a6, v4si a7,
+     v4si a8, v4si a9)
+{
+  return a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8 + a9;
+}
+
+int
+main ()
+{
+  v4si a1 = {
+    1, 1, 1, 1,
+  };
+  v4si a2 = {
+    1, 1, 1, 1,
+  };
+  v4si a3 = {
+    1, 1, 1, 1,
+  };
+  v4si a4 = {
+    1, 1, 1, 1,
+  };
+  v4si a5 = {
+    1, 1, 1, 1,
+  };
+  v4si a6 = {
+    1, 1, 1, 1,
+  };
+  v4si a7 = {
+    1, 1, 1, 1,
+  };
+  v4si a8 = {
+    1, 1, 1, 1,
+  };
+  v4si a9 = {
+    1, 1, 1, 1,
+  };
+  v4si expected = {
+    9, 9, 9, 9,
+  };
+  v4si result = add (a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+  unsigned i;
+
+  for (i = 0; i < 4; i++)
+    if (result[i] != expected[i])
+      __builtin_abort ();
+
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-run-4.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-run-4.c
new file mode 100644
index 00000000000..0788447b501
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-run-4.c
@@ -0,0 +1,55 @@
+/* { dg-do run { target { riscv_v } } } */
+/* { dg-additional-options "-std=c99 -fno-vect-cost-model --param=riscv-autovec-preference=scalable" } */
+
+typedef long long v2di __attribute__ ((vector_size (16)));
+
+v2di
+add (v2di a1, v2di a2, v2di a3, v2di a4, v2di a5, v2di a6, v2di a7,
+     v2di a8, v2di a9)
+{
+  return a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8 + a9;
+}
+
+int
+main ()
+{
+  v2di a1 = {
+    1, 1,
+  };
+  v2di a2 = {
+    1, 1,
+  };
+  v2di a3 = {
+    1, 1,
+  };
+  v2di a4 = {
+    1, 1,
+  };
+  v2di a5 = {
+    1, 1,
+  };
+  v2di a6 = {
+    1, 1,
+  };
+  v2di a7 = {
+    1, 1,
+  };
+  v2di a8 = {
+    1, 1,
+  };
+  v2di a9 = {
+    1, 1,
+  };
+  v2di expected = {
+    9, 9,
+  };
+  v2di result = add (a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+  unsigned i;
+
+  for (i = 0; i < 2; i++)
+    if (result[i] != expected[i])
+      __builtin_abort ();
+
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-run-5.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-run-5.c
new file mode 100644
index 00000000000..ec8658d6a02
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-run-5.c
@@ -0,0 +1,55 @@
+/* { dg-do run { target { riscv_v } } } */
+/* { dg-additional-options "-std=c99 -fno-vect-cost-model --param=riscv-autovec-preference=scalable" } */
+
+typedef float v4sf __attribute__ ((vector_size (16)));
+
+v4sf
+add (v4sf a1, v4sf a2, v4sf a3, v4sf a4, v4sf a5, v4sf a6, v4sf a7,
+     v4sf a8, v4sf a9)
+{
+  return a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8 + a9;
+}
+
+int
+main ()
+{
+  v4sf a1 = {
+    1.0, 1.0, 1.0, 1.0,
+  };
+  v4sf a2 = {
+    1.0, 1.0, 1.0, 1.0,
+  };
+  v4sf a3 = {
+    1.0, 1.0, 1.0, 1.0,
+  };
+  v4sf a4 = {
+    1.0, 1.0, 1.0, 1.0,
+  };
+  v4sf a5 = {
+    1.0, 1.0, 1.0, 1.0,
+  };
+  v4sf a6 = {
+    1.0, 1.0, 1.0, 1.0,
+  };
+  v4sf a7 = {
+    1.0, 1.0, 1.0, 1.0,
+  };
+  v4sf a8 = {
+    1.0, 1.0, 1.0, 1.0,
+  };
+  v4sf a9 = {
+    1.0, 1.0, 1.0, 1.0,
+  };
+  v4sf expected = {
+    9.0, 9.0, 9.0, 9.0,
+  };
+  v4sf result = add (a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+  unsigned i;
+
+  for (i = 0; i < 4; i++)
+    if (result[i] != expected[i])
+      __builtin_abort ();
+
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-run-6.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-run-6.c
new file mode 100644
index 00000000000..bbb53a1a4af
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-run-6.c
@@ -0,0 +1,55 @@
+/* { dg-do run { target { riscv_v } } } */
+/* { dg-additional-options "-std=c99 -fno-vect-cost-model --param=riscv-autovec-preference=scalable" } */
+
+typedef long long v2df __attribute__ ((vector_size (16)));
+
+v2df
+add (v2df a1, v2df a2, v2df a3, v2df a4, v2df a5, v2df a6, v2df a7,
+     v2df a8, v2df a9)
+{
+  return a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8 + a9;
+}
+
+int
+main ()
+{
+  v2df a1 = {
+    1.0, 1.0,
+  };
+  v2df a2 = {
+    1.0, 1.0,
+  };
+  v2df a3 = {
+    1.0, 1.0,
+  };
+  v2df a4 = {
+    1.0, 1.0,
+  };
+  v2df a5 = {
+    1.0, 1.0,
+  };
+  v2df a6 = {
+    1.0, 1.0,
+  };
+  v2df a7 = {
+    1.0, 1.0,
+  };
+  v2df a8 = {
+    1.0, 1.0,
+  };
+  v2df a9 = {
+    1.0, 1.0,
+  };
+  v2df expected = {
+    9.0, 9.0,
+  };
+  v2df result = add (a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+  unsigned i;
+
+  for (i = 0; i < 2; i++)
+    if (result[i] != expected[i])
+      __builtin_abort ();
+
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/def.h b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/def.h
index cb7a1c97ded..ef55c4d7ecf 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/def.h
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/def.h
@@ -860,3 +860,77 @@ typedef double v512df __attribute__ ((vector_size (4096)));
     TYPE1 v = {__VA_ARGS__};                                                   \
     *(TYPE1 *) out = v;                                                        \
   }
+
+#define DEF_RET1_ARG0(TYPE)                                                    \
+  TYPE __attribute__((noinline))                                               \
+  TYPE##_RET1_ARG0 ()                                                          \
+  {                                                                            \
+    TYPE r = {};                                                               \
+    return r;                                                                  \
+  }
+
+#define DEF_RET1_ARG1(TYPE)                                                    \
+  TYPE __attribute__((noinline))                                               \
+  TYPE##_RET1_ARG1 (TYPE a1)                                                   \
+  {                                                                            \
+    return a1;                                                                 \
+  }
+
+#define DEF_RET1_ARG2(TYPE)                                                    \
+  TYPE __attribute__((noinline))                                               \
+  TYPE##_RET1_ARG2 (TYPE a1, TYPE a2)                                          \
+  {                                                                            \
+    return a1 + a2;                                                            \
+  }
+
+#define DEF_RET1_ARG3(TYPE)                                                    \
+  TYPE __attribute__((noinline))                                               \
+  TYPE##_RET1_ARG3 (TYPE a1, TYPE a2, TYPE a3)                                 \
+  {                                                                            \
+    return a1 + a2 + a3;                                                       \
+  }
+
+#define DEF_RET1_ARG4(TYPE)                                                    \
+  TYPE __attribute__((noinline))                                               \
+  TYPE##_RET1_ARG4 (TYPE a1, TYPE a2, TYPE a3, TYPE a4)                        \
+  {                                                                            \
+    return a1 + a2 + a3 + a4;                                                  \
+  }
+
+#define DEF_RET1_ARG5(TYPE)                                                    \
+  TYPE __attribute__((noinline))                                               \
+  TYPE##_RET1_ARG5 (TYPE a1, TYPE a2, TYPE a3, TYPE a4, TYPE a5)               \
+  {                                                                            \
+    return a1 + a2 + a3 + a4 + a5;                                             \
+  }
+
+#define DEF_RET1_ARG6(TYPE)                                                    \
+  TYPE __attribute__((noinline))                                               \
+  TYPE##_RET1_ARG6 (TYPE a1, TYPE a2, TYPE a3, TYPE a4, TYPE a5, TYPE a6)      \
+  {                                                                            \
+    return a1 + a2 + a3 + a4 + a5 + a6;                                        \
+  }
+
+#define DEF_RET1_ARG7(TYPE)                                                    \
+  TYPE __attribute__((noinline))                                               \
+  TYPE##_RET1_ARG7 (TYPE a1, TYPE a2, TYPE a3, TYPE a4, TYPE a5, TYPE a6,      \
+     TYPE a7)                                                   \
+  {                                                                            \
+    return a1 + a2 + a3 + a4 + a5 + a6 + a7;                                   \
+  }
+
+#define DEF_RET1_ARG8(TYPE)                                                    \
+  TYPE __attribute__((noinline))                                               \
+  TYPE##_RET1_ARG8 (TYPE a1, TYPE a2, TYPE a3, TYPE a4, TYPE a5, TYPE a6,      \
+     TYPE a7, TYPE a8)                                          \
+  {                                                                            \
+    return a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8;                              \
+  }
+
+#define DEF_RET1_ARG9(TYPE)                                                    \
+  TYPE __attribute__((noinline))                                               \
+  TYPE##_RET1_ARG9 (TYPE a1, TYPE a2, TYPE a3, TYPE a4, TYPE a5, TYPE a6,      \
+     TYPE a7, TYPE a8, TYPE a9)                                 \
+  {                                                                            \
+    return a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8 + a9;                         \
+  }
--
2.34.1



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

* Re: RE: [PATCH v1] RISC-V: Bugfix for vls integer mode calling convention
  2024-01-24  3:41   ` Li, Pan2
@ 2024-01-24  3:43     ` juzhe.zhong
  0 siblings, 0 replies; 10+ messages in thread
From: juzhe.zhong @ 2024-01-24  3:43 UTC (permalink / raw)
  To: pan2.li, gcc-patches; +Cc: yanzhang.wang, kito.cheng

[-- Attachment #1: Type: text/plain, Size: 58360 bytes --]

No. It's related. I think it should be easily just generate slide to handle this.



juzhe.zhong@rivai.ai
 
From: Li, Pan2
Date: 2024-01-24 11:41
To: juzhe.zhong@rivai.ai; gcc-patches
CC: Wang, Yanzhang; kito.cheng
Subject: RE: [PATCH v1] RISC-V: Bugfix for vls integer mode calling convention
The title should remove integer, and sorry for misleading here.
 
Looks the clang leverage the vmv + vslide1down to build the vls while gcc goes to the stack. Not very sure if it related to the last comment of
 
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111720
 
But it is one optimization case which may be handled in another patch up to a point.
 
Pan
 
From: juzhe.zhong@rivai.ai <juzhe.zhong@rivai.ai> 
Sent: Wednesday, January 24, 2024 11:19 AM
To: Li, Pan2 <pan2.li@intel.com>; gcc-patches <gcc-patches@gcc.gnu.org>
Cc: Li, Pan2 <pan2.li@intel.com>; Wang, Yanzhang <yanzhang.wang@intel.com>; kito.cheng <kito.cheng@gmail.com>
Subject: Re: [PATCH v1] RISC-V: Bugfix for vls integer mode calling convention
 
>> After this patch:
>>add:
>>  addi     sp,sp,-32
>>  sd       a0,0(sp)  <== arg by register a0 - a3
>>  sd       a1,8(sp)
>>  sd       a2,16(sp)
>>  sd       a3,24(sp)
>>  addi     a5,sp,16
>>  vsetivli zero,8,e16,m1,ta,ma
>>  vle16.v  v2,0(sp)
>>  vle16.v  v1,0(a5)
 >> vadd.vv  v1,v1,v2
>>  vse16.v  v1,0(sp)
>>  ld       a0,0(sp)  <== return by a0 - a1.
>>  ld       a1,8(sp)
>>  addi     sp,sp,32
>>  jr       ra
 
But clang is :
 
        vsetivli        zero, 2, e64, m1, ta, ma
        vmv.v.x v8, a0
        vslide1down.vx  v8, v8, a1
        vmv.v.x v9, a2
        vslide1down.vx  v9, v9, a3
        vsetivli        zero, 8, e16, m1, ta, ma
        vadd.vv v8, v9, v8
        vsetivli        zero, 1, e64, m1, ta, ma
        vmv.x.s a0, v8
        vslidedown.vi   v8, v8, 1
        vmv.x.s a1, v8
        ret
 


juzhe.zhong@rivai.ai
 
From: pan2.li
Date: 2024-01-24 11:16
To: gcc-patches
CC: juzhe.zhong; pan2.li; yanzhang.wang; kito.cheng
Subject: [PATCH v1] RISC-V: Bugfix for vls integer mode calling convention
From: Pan Li <pan2.li@intel.com>
 
According to the issue as below.
 
https://hub.fgit.cf/riscv-non-isa/riscv-elf-psabi-doc/pull/416
 
When the mode size of vls integer mode is less than 2 * XLEN, we will
take the gpr/fpr for both the args and the return values. Instead of
the reference. For example the below code:
 
typedef short v8hi __attribute__ ((vector_size (16)));
 
v8hi __attribute__((noinline))
add (v8hi a, v8hi b)
{
  v8hi r = a + b;
  return r;
}
 
Before this patch:
add:
  vsetivli zero,8,e16,m1,ta,ma
  vle16.v  v1,0(a1) <== arg by reference
  vle16.v  v2,0(a2) <== arg by reference
  vadd.vv  v1,v1,v2
  vse16.v  v1,0(a0) <== return by reference
  ret
 
After this patch:
add:
  addi     sp,sp,-32
  sd       a0,0(sp)  <== arg by register a0 - a3
  sd       a1,8(sp)
  sd       a2,16(sp)
  sd       a3,24(sp)
  addi     a5,sp,16
  vsetivli zero,8,e16,m1,ta,ma
  vle16.v  v2,0(sp)
  vle16.v  v1,0(a5)
  vadd.vv  v1,v1,v2
  vse16.v  v1,0(sp)
  ld       a0,0(sp)  <== return by a0 - a1.
  ld       a1,8(sp)
  addi     sp,sp,32
  jr       ra
 
For vls floating point, the things get more complicated.  We follow
the below rules.
 
1. Vls element count <= 2 and vls size <= 2 * xlen, go fpr.
2. Vls size <= 2 * xlen, go gpr.
3. Vls size > 2 * xlen, go reference.
 
One exceptions is V2DF mode, we treat vls mode as aggregated and we will
have TFmode here.  Unforturnately, the emit_move_multi_word cannot take
care of TFmode elegantly and we go to gpr for V2DF mode.
 
The riscv regression passed for this patch.
 
gcc/ChangeLog:
 
* config/riscv/riscv.cc (riscv_v_ext_vector_or_tuple_mode_p):
New predicate function for vector or tuple vector.
(riscv_v_vls_mode_aggregate_reg_count): New function to
calculate the gpr/fpr count required by vls mode.
(riscv_gpr_unit_size): New function to get gpr in bytes.
(riscv_fpr_unit_size): New function to get fpr in bytes.
(riscv_v_vls_to_gpr_mode): New function convert vls mode to gpr mode.
(riscv_v_vls_to_fpr_mode): New function convert vls mode to fpr mode.
(riscv_pass_vls_aggregate_in_gpr_or_fpr): New function to return
the rtx of gpr/fpr for vls mode.
(riscv_mode_pass_by_reference_p): New predicate function to
indicate the mode will be passed by reference or not.
(riscv_get_arg_info): Add vls mode handling.
(riscv_pass_by_reference): Return false if arg info has no zero
gpr count.
 
gcc/testsuite/ChangeLog:
 
* gcc.target/riscv/rvv/autovec/vls/def.h: Add helper marcos.
* gcc.target/riscv/rvv/autovec/vls/calling-convention-1.c: New test.
* gcc.target/riscv/rvv/autovec/vls/calling-convention-10.c: New test.
* gcc.target/riscv/rvv/autovec/vls/calling-convention-2.c: New test.
* gcc.target/riscv/rvv/autovec/vls/calling-convention-3.c: New test.
* gcc.target/riscv/rvv/autovec/vls/calling-convention-4.c: New test.
* gcc.target/riscv/rvv/autovec/vls/calling-convention-5.c: New test.
* gcc.target/riscv/rvv/autovec/vls/calling-convention-6.c: New test.
* gcc.target/riscv/rvv/autovec/vls/calling-convention-7.c: New test.
* gcc.target/riscv/rvv/autovec/vls/calling-convention-8.c: New test.
* gcc.target/riscv/rvv/autovec/vls/calling-convention-9.c: New test.
* gcc.target/riscv/rvv/autovec/vls/calling-convention-run-1.c: New test.
* gcc.target/riscv/rvv/autovec/vls/calling-convention-run-2.c: New test.
* gcc.target/riscv/rvv/autovec/vls/calling-convention-run-3.c: New test.
* gcc.target/riscv/rvv/autovec/vls/calling-convention-run-4.c: New test.
* gcc.target/riscv/rvv/autovec/vls/calling-convention-run-5.c: New test.
* gcc.target/riscv/rvv/autovec/vls/calling-convention-run-6.c: New test.
 
Signed-off-by: Pan Li <pan2.li@intel.com>
---
gcc/config/riscv/riscv.cc                     | 185 +++++++++++++++++-
.../rvv/autovec/vls/calling-convention-1.c    | 154 +++++++++++++++
.../rvv/autovec/vls/calling-convention-10.c   |  51 +++++
.../rvv/autovec/vls/calling-convention-2.c    | 142 ++++++++++++++
.../rvv/autovec/vls/calling-convention-3.c    | 130 ++++++++++++
.../rvv/autovec/vls/calling-convention-4.c    | 118 +++++++++++
.../rvv/autovec/vls/calling-convention-5.c    | 141 +++++++++++++
.../rvv/autovec/vls/calling-convention-6.c    | 129 ++++++++++++
.../rvv/autovec/vls/calling-convention-7.c    | 120 ++++++++++++
.../rvv/autovec/vls/calling-convention-8.c    |  43 ++++
.../rvv/autovec/vls/calling-convention-9.c    |  51 +++++
.../autovec/vls/calling-convention-run-1.c    |  55 ++++++
.../autovec/vls/calling-convention-run-2.c    |  55 ++++++
.../autovec/vls/calling-convention-run-3.c    |  55 ++++++
.../autovec/vls/calling-convention-run-4.c    |  55 ++++++
.../autovec/vls/calling-convention-run-5.c    |  55 ++++++
.../autovec/vls/calling-convention-run-6.c    |  55 ++++++
.../gcc.target/riscv/rvv/autovec/vls/def.h    |  74 +++++++
18 files changed, 1665 insertions(+), 3 deletions(-)
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-1.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-10.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-2.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-3.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-4.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-5.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-6.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-7.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-8.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-9.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-run-1.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-run-2.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-run-3.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-run-4.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-run-5.c
create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-run-6.c
 
diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 3ba45ffaa74..fb79a475bbe 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -1382,6 +1382,106 @@ riscv_v_ext_mode_p (machine_mode mode)
|| riscv_v_ext_vls_mode_p (mode);
}
+/* Return true if it is either of below modes.
+   1. RVV vector mode.
+   2. RVV tuple mode.  */
+
+static bool
+riscv_v_ext_vector_or_tuple_mode_p (machine_mode mode)
+{
+  return riscv_v_ext_vector_mode_p (mode) || riscv_v_ext_tuple_mode_p (mode);
+}
+
+static unsigned
+riscv_v_vls_mode_aggregate_reg_count (unsigned vls_unit_size,
+       unsigned scalar_unit_size)
+{
+  gcc_assert (vls_unit_size != 0 && scalar_unit_size != 0);
+
+  if (vls_unit_size < scalar_unit_size)
+    return 1;
+
+  return vls_unit_size / scalar_unit_size;
+}
+
+static unsigned short
+riscv_gpr_unit_size ()
+{
+  return GET_MODE_SIZE (Xmode);
+}
+
+static unsigned short
+riscv_fpr_unit_size ()
+{
+  unsigned fpr_size = 0;
+
+  if (TARGET_HARD_FLOAT && !TARGET_DOUBLE_FLOAT)
+    {
+      switch (riscv_abi)
+ {
+   case ABI_LP64F:
+   case ABI_ILP32F:
+     fpr_size = GET_MODE_SIZE (SFmode);
+     break;
+ }
+    }
+
+  if (TARGET_DOUBLE_FLOAT)
+    {
+      switch (riscv_abi)
+ {
+   case ABI_LP64F:
+   case ABI_ILP32F:
+     fpr_size = GET_MODE_SIZE (SFmode);
+     break;
+   case ABI_LP64D:
+   case ABI_ILP32D:
+     fpr_size = GET_MODE_SIZE (DFmode);
+     break;
+ }
+    }
+
+  return fpr_size;
+}
+
+static machine_mode
+riscv_v_vls_to_gpr_mode (unsigned vls_mode_size)
+{
+  switch (vls_mode_size)
+    {
+      case 16:
+ return TImode;
+      case 8:
+ return DImode;
+      case 4:
+ return SImode;
+      case 2:
+ return HImode;
+      case 1:
+ return QImode;
+      default:
+ gcc_unreachable ();
+    }
+}
+
+static machine_mode
+riscv_v_vls_to_fpr_mode (unsigned vls_mode_size)
+{
+  switch (vls_mode_size)
+    {
+      case 16:
+ return TFmode;
+      case 8:
+ return DFmode;
+      case 4:
+ return SFmode;
+      case 2:
+ return HFmode;
+      default:
+ gcc_unreachable ();
+    }
+}
+
/* Call from ADJUST_NUNITS in riscv-modes.def. Return the correct
    NUNITS size for corresponding machine_mode.  */
@@ -4868,6 +4968,63 @@ riscv_pass_fpr_pair (machine_mode mode, unsigned regno1,
   GEN_INT (offset2))));
}
+static rtx
+riscv_pass_vls_aggregate_in_gpr_or_fpr (struct riscv_arg_info *info,
+ machine_mode mode, unsigned gpr_base,
+ unsigned fpr_base)
+{
+  gcc_assert (riscv_v_ext_vls_mode_p (mode));
+
+  unsigned vls_size = GET_MODE_SIZE (mode).to_constant ();
+  unsigned gpr_size = riscv_gpr_unit_size ();
+  unsigned fpr_size = riscv_fpr_unit_size ();
+  unsigned regnum = 0, count = 0;
+  unsigned vls_elem_count = vls_size / GET_MODE_SIZE (GET_MODE_INNER (mode));
+  machine_mode smode = VOIDmode;
+
+  /* For vls floating point >= 16 bytes, it cannot be well token care of when
+     emit_move_multi_word.  For example vls size == 16 bytes when move multi
+     word.  We will hit assert similar to gcc_assert (xpart && ypart).
+     x=(reg:TF 42 fa0)
+     y=(subreg:TF (reg:TI 136) 0)
+
+     Thus, we will go with gpr for vls size >= 16.
+  */
+  if (vls_elem_count <= 2 && FLOAT_MODE_P (mode) && fpr_size && vls_size < 16
+    && IN_RANGE (vls_size, 0, fpr_size * 2))
+    {
+      count = riscv_v_vls_mode_aggregate_reg_count (vls_size, fpr_size);
+
+      if (count + info->fpr_offset <= MAX_ARGS_IN_REGISTERS)
+ {
+   regnum = fpr_base + info->fpr_offset;
+   info->num_fprs = count;
+   smode = riscv_v_vls_to_fpr_mode (vls_size);
+ }
+    }
+  else if (IN_RANGE (vls_size, 0, gpr_size * 2))
+    {
+      count = riscv_v_vls_mode_aggregate_reg_count (vls_size, gpr_size);
+
+      if (count + info->gpr_offset <= MAX_ARGS_IN_REGISTERS)
+ {
+   regnum = gpr_base + info->gpr_offset;
+   info->num_gprs = count;
+   smode = riscv_v_vls_to_gpr_mode (vls_size);
+ }
+    }
+
+  if (!regnum)
+    return NULL_RTX; /* Return NULL_RTX if we cannot find a suitable reg.  */
+
+  gcc_assert (smode != VOIDmode);
+
+  rtx reg = gen_rtx_REG (smode, regnum);
+  rtx x = gen_rtx_EXPR_LIST (VOIDmode, reg, CONST0_RTX (smode));
+
+  return gen_rtx_PARALLEL (mode, gen_rtvec (1, x));
+}
+
/* Initialize a variable CUM of type CUMULATIVE_ARGS
    for a call to a function whose data type is FNTYPE.
    For a library call, FNTYPE is 0.  */
@@ -4975,6 +5132,22 @@ riscv_get_vector_arg (struct riscv_arg_info *info, const CUMULATIVE_ARGS *cum,
   return NULL_RTX;
}
+/* Return true if the argument mode is passed by reference. Aka:
+   1. Scalable vector argument is anonymous.
+   2. The vector abi is disabled for vector or tuple mode.
+   Else return false.  */
+static bool
+riscv_mode_pass_by_reference_p (machine_mode mode, bool named)
+{
+  if (riscv_v_ext_mode_p (mode) && !named)
+    return true;
+
+  if (riscv_v_ext_vector_or_tuple_mode_p (mode) && !riscv_vector_abi)
+    return true;
+
+  return false;
+}
+
/* Fill INFO with information about a single argument, and return an RTL
    pattern to pass or return the argument. Return NULL_RTX if argument cannot
    pass or return in registers, then the argument may be passed by reference or
@@ -4997,9 +5170,7 @@ riscv_get_arg_info (struct riscv_arg_info *info, const CUMULATIVE_ARGS *cum,
   info->gpr_offset = cum->num_gprs;
   info->fpr_offset = cum->num_fprs;
-  /* When disable vector_abi or scalable vector argument is anonymous, this
-     argument is passed by reference.  */
-  if (riscv_v_ext_mode_p (mode) && (!riscv_vector_abi || !named))
+  if (riscv_mode_pass_by_reference_p (mode, named))
     return NULL_RTX;
   if (named)
@@ -5064,6 +5235,10 @@ riscv_get_arg_info (struct riscv_arg_info *info, const CUMULATIVE_ARGS *cum,
      fields[1].offset);
}
+      if (riscv_v_ext_vls_mode_p (mode))
+ return riscv_pass_vls_aggregate_in_gpr_or_fpr (info, mode, gpr_base,
+        fpr_base);
+
       /* For scalable vector argument.  */
       if (riscv_vector_type_p (type) && riscv_v_ext_mode_p (mode))
return riscv_get_vector_arg (info, cum, mode, return_p);
@@ -5196,6 +5371,10 @@ riscv_pass_by_reference (cumulative_args_t cum_v, const function_arg_info &arg)
       if (info.num_fprs)
return false;
+      /* Don't pass by reference if we can use general register(s) for vls.  */
+      if (info.num_gprs && riscv_v_ext_vls_mode_p (arg.mode))
+ return false;
+
       /* Don't pass by reference if we can use vector register groups.  */
       if (info.num_vrs > 0 || info.num_mrs > 0)
return false;
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-1.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-1.c
new file mode 100644
index 00000000000..41e31c258f8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-1.c
@@ -0,0 +1,154 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv_zvl4096b --param riscv-autovec-preference=scalable -mabi=lp64d -O3" } */
+
+#include "def.h"
+
+DEF_RET1_ARG0 (v1qi)
+DEF_RET1_ARG0 (v2qi)
+DEF_RET1_ARG0 (v4qi)
+DEF_RET1_ARG0 (v8qi)
+DEF_RET1_ARG0 (v16qi)
+DEF_RET1_ARG0 (v32qi)
+DEF_RET1_ARG0 (v64qi)
+DEF_RET1_ARG0 (v128qi)
+DEF_RET1_ARG0 (v256qi)
+DEF_RET1_ARG0 (v512qi)
+DEF_RET1_ARG0 (v1024qi)
+DEF_RET1_ARG0 (v2048qi)
+DEF_RET1_ARG0 (v4096qi)
+
+DEF_RET1_ARG1 (v1qi)
+DEF_RET1_ARG1 (v2qi)
+DEF_RET1_ARG1 (v4qi)
+DEF_RET1_ARG1 (v8qi)
+DEF_RET1_ARG1 (v16qi)
+DEF_RET1_ARG1 (v32qi)
+DEF_RET1_ARG1 (v64qi)
+DEF_RET1_ARG1 (v128qi)
+DEF_RET1_ARG1 (v256qi)
+DEF_RET1_ARG1 (v512qi)
+DEF_RET1_ARG1 (v1024qi)
+DEF_RET1_ARG1 (v2048qi)
+DEF_RET1_ARG1 (v4096qi)
+
+DEF_RET1_ARG2 (v1qi)
+DEF_RET1_ARG2 (v2qi)
+DEF_RET1_ARG2 (v4qi)
+DEF_RET1_ARG2 (v8qi)
+DEF_RET1_ARG2 (v16qi)
+DEF_RET1_ARG2 (v32qi)
+DEF_RET1_ARG2 (v64qi)
+DEF_RET1_ARG2 (v128qi)
+DEF_RET1_ARG2 (v256qi)
+DEF_RET1_ARG2 (v512qi)
+DEF_RET1_ARG2 (v1024qi)
+DEF_RET1_ARG2 (v2048qi)
+DEF_RET1_ARG2 (v4096qi)
+
+DEF_RET1_ARG3 (v1qi)
+DEF_RET1_ARG3 (v2qi)
+DEF_RET1_ARG3 (v4qi)
+DEF_RET1_ARG3 (v8qi)
+DEF_RET1_ARG3 (v16qi)
+DEF_RET1_ARG3 (v32qi)
+DEF_RET1_ARG3 (v64qi)
+DEF_RET1_ARG3 (v128qi)
+DEF_RET1_ARG3 (v256qi)
+DEF_RET1_ARG3 (v512qi)
+DEF_RET1_ARG3 (v1024qi)
+DEF_RET1_ARG3 (v2048qi)
+DEF_RET1_ARG3 (v4096qi)
+
+DEF_RET1_ARG4 (v1qi)
+DEF_RET1_ARG4 (v2qi)
+DEF_RET1_ARG4 (v4qi)
+DEF_RET1_ARG4 (v8qi)
+DEF_RET1_ARG4 (v16qi)
+DEF_RET1_ARG4 (v32qi)
+DEF_RET1_ARG4 (v64qi)
+DEF_RET1_ARG4 (v128qi)
+DEF_RET1_ARG4 (v256qi)
+DEF_RET1_ARG4 (v512qi)
+DEF_RET1_ARG4 (v1024qi)
+DEF_RET1_ARG4 (v2048qi)
+DEF_RET1_ARG4 (v4096qi)
+
+DEF_RET1_ARG5 (v1qi)
+DEF_RET1_ARG5 (v2qi)
+DEF_RET1_ARG5 (v4qi)
+DEF_RET1_ARG5 (v8qi)
+DEF_RET1_ARG5 (v16qi)
+DEF_RET1_ARG5 (v32qi)
+DEF_RET1_ARG5 (v64qi)
+DEF_RET1_ARG5 (v128qi)
+DEF_RET1_ARG5 (v256qi)
+DEF_RET1_ARG5 (v512qi)
+DEF_RET1_ARG5 (v1024qi)
+DEF_RET1_ARG5 (v2048qi)
+DEF_RET1_ARG5 (v4096qi)
+
+DEF_RET1_ARG6 (v1qi)
+DEF_RET1_ARG6 (v2qi)
+DEF_RET1_ARG6 (v4qi)
+DEF_RET1_ARG6 (v8qi)
+DEF_RET1_ARG6 (v16qi)
+DEF_RET1_ARG6 (v32qi)
+DEF_RET1_ARG6 (v64qi)
+DEF_RET1_ARG6 (v128qi)
+DEF_RET1_ARG6 (v256qi)
+DEF_RET1_ARG6 (v512qi)
+DEF_RET1_ARG6 (v1024qi)
+DEF_RET1_ARG6 (v2048qi)
+DEF_RET1_ARG6 (v4096qi)
+
+DEF_RET1_ARG7 (v1qi)
+DEF_RET1_ARG7 (v2qi)
+DEF_RET1_ARG7 (v4qi)
+DEF_RET1_ARG7 (v8qi)
+DEF_RET1_ARG7 (v16qi)
+DEF_RET1_ARG7 (v32qi)
+DEF_RET1_ARG7 (v64qi)
+DEF_RET1_ARG7 (v128qi)
+DEF_RET1_ARG7 (v256qi)
+DEF_RET1_ARG7 (v512qi)
+DEF_RET1_ARG7 (v1024qi)
+DEF_RET1_ARG7 (v2048qi)
+DEF_RET1_ARG7 (v4096qi)
+
+DEF_RET1_ARG8 (v1qi)
+DEF_RET1_ARG8 (v2qi)
+DEF_RET1_ARG8 (v4qi)
+DEF_RET1_ARG8 (v8qi)
+DEF_RET1_ARG8 (v16qi)
+DEF_RET1_ARG8 (v32qi)
+DEF_RET1_ARG8 (v64qi)
+DEF_RET1_ARG8 (v128qi)
+DEF_RET1_ARG8 (v256qi)
+DEF_RET1_ARG8 (v512qi)
+DEF_RET1_ARG8 (v1024qi)
+DEF_RET1_ARG8 (v2048qi)
+DEF_RET1_ARG8 (v4096qi)
+
+DEF_RET1_ARG9 (v1qi)
+DEF_RET1_ARG9 (v2qi)
+DEF_RET1_ARG9 (v4qi)
+DEF_RET1_ARG9 (v8qi)
+DEF_RET1_ARG9 (v16qi)
+DEF_RET1_ARG9 (v32qi)
+DEF_RET1_ARG9 (v64qi)
+DEF_RET1_ARG9 (v128qi)
+DEF_RET1_ARG9 (v256qi)
+DEF_RET1_ARG9 (v512qi)
+DEF_RET1_ARG9 (v1024qi)
+DEF_RET1_ARG9 (v2048qi)
+DEF_RET1_ARG9 (v4096qi)
+
+/* { dg-final { scan-assembler-times {li\s+a[0-1],\s*0} 9 } } */
+/* { dg-final { scan-assembler-times {lbu\s+a0,\s*[0-9]+\(sp\)} 8 } } */
+/* { dg-final { scan-assembler-times {lhu\s+a0,\s*[0-9]+\(sp\)} 8 } } */
+/* { dg-final { scan-assembler-times {lw\s+a0,\s*[0-9]+\(sp\)} 8 } } */
+/* { dg-final { scan-assembler-times {ld\s+a[0-1],\s*[0-9]+\(sp\)} 35 } } */
+/* { dg-final { scan-assembler-times {sb\s+a[0-7],\s*[0-9]+\(sp\)} 43 } } */
+/* { dg-final { scan-assembler-times {sh\s+a[0-7],\s*[0-9]+\(sp\)} 43 } } */
+/* { dg-final { scan-assembler-times {sw\s+a[0-7],\s*[0-9]+\(sp\)} 43 } } */
+/* { dg-final { scan-assembler-times {sd\s+a[0-7],\s*[0-9]+\(sp\)} 103 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-10.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-10.c
new file mode 100644
index 00000000000..0abc6cf0146
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-10.c
@@ -0,0 +1,51 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv_zvfh_zvl4096b -mabi=lp64 --param riscv-autovec-preference=scalable -O3 -fno-schedule-insns -fno-schedule-insns2" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include "def.h"
+
+/*
+** v4hf_RET1_ARG1:
+** ret
+*/
+DEF_RET1_ARG1 (v4hf)
+
+/*
+** v2sf_RET1_ARG2:
+** addi\s+sp,\s*sp,\s*-16
+** sd\s+a0,\s*0\(sp\)
+** sd\s+a1,\s*8\(sp\)
+** ...
+** ld\s+a0,\s*0\(sp\)
+** addi\s+sp,\s*sp,\s*16
+** jr\s+ra
+*/
+DEF_RET1_ARG2 (v2sf)
+
+/*
+** v4sf_RET1_ARG2:
+** addi\s+sp,\s*sp,\s*-32
+** sd\s+a0,\s*0\(sp\)
+** sd\s+a1,\s*8\(sp\)
+** sd\s+a2,\s*16\(sp\)
+** sd\s+a3,\s*24\(sp\)
+** ...
+** ld\s+a0,\s*0\(sp\)
+** ld\s+a1,\s*8\(sp\)
+** addi\s+sp,\s*sp,\s*32
+** jr\s+ra
+*/
+DEF_RET1_ARG2 (v4sf)
+
+/*
+** v1df_RET1_ARG3:
+** addi\s+sp,\s*sp,\s*-32
+** sd\s+a0,\s*8\(sp\)
+** sd\s+a1,\s*16\(sp\)
+** sd\s+a2,\s*24\(sp\)
+** ...
+** ld\s+a0,\s*8\(sp\)
+** addi\s+sp,\s*sp,\s*32
+** jr\s+ra
+*/
+DEF_RET1_ARG3 (v1df)
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-2.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-2.c
new file mode 100644
index 00000000000..8544f160e93
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-2.c
@@ -0,0 +1,142 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv_zvl4096b --param riscv-autovec-preference=scalable -mabi=lp64d -O3" } */
+
+#include "def.h"
+
+DEF_RET1_ARG0 (v1hi)
+DEF_RET1_ARG0 (v2hi)
+DEF_RET1_ARG0 (v4hi)
+DEF_RET1_ARG0 (v8hi)
+DEF_RET1_ARG0 (v16hi)
+DEF_RET1_ARG0 (v32hi)
+DEF_RET1_ARG0 (v64hi)
+DEF_RET1_ARG0 (v128hi)
+DEF_RET1_ARG0 (v256hi)
+DEF_RET1_ARG0 (v512hi)
+DEF_RET1_ARG0 (v1024hi)
+DEF_RET1_ARG0 (v2048hi)
+
+DEF_RET1_ARG1 (v1hi)
+DEF_RET1_ARG1 (v2hi)
+DEF_RET1_ARG1 (v4hi)
+DEF_RET1_ARG1 (v8hi)
+DEF_RET1_ARG1 (v16hi)
+DEF_RET1_ARG1 (v32hi)
+DEF_RET1_ARG1 (v64hi)
+DEF_RET1_ARG1 (v128hi)
+DEF_RET1_ARG1 (v256hi)
+DEF_RET1_ARG1 (v512hi)
+DEF_RET1_ARG1 (v1024hi)
+DEF_RET1_ARG1 (v2048hi)
+
+DEF_RET1_ARG2 (v1hi)
+DEF_RET1_ARG2 (v2hi)
+DEF_RET1_ARG2 (v4hi)
+DEF_RET1_ARG2 (v8hi)
+DEF_RET1_ARG2 (v16hi)
+DEF_RET1_ARG2 (v32hi)
+DEF_RET1_ARG2 (v64hi)
+DEF_RET1_ARG2 (v128hi)
+DEF_RET1_ARG2 (v256hi)
+DEF_RET1_ARG2 (v512hi)
+DEF_RET1_ARG2 (v1024hi)
+DEF_RET1_ARG2 (v2048hi)
+
+DEF_RET1_ARG3 (v1hi)
+DEF_RET1_ARG3 (v2hi)
+DEF_RET1_ARG3 (v4hi)
+DEF_RET1_ARG3 (v8hi)
+DEF_RET1_ARG3 (v16hi)
+DEF_RET1_ARG3 (v32hi)
+DEF_RET1_ARG3 (v64hi)
+DEF_RET1_ARG3 (v128hi)
+DEF_RET1_ARG3 (v256hi)
+DEF_RET1_ARG3 (v512hi)
+DEF_RET1_ARG3 (v1024hi)
+DEF_RET1_ARG3 (v2048hi)
+
+DEF_RET1_ARG4 (v1hi)
+DEF_RET1_ARG4 (v2hi)
+DEF_RET1_ARG4 (v4hi)
+DEF_RET1_ARG4 (v8hi)
+DEF_RET1_ARG4 (v16hi)
+DEF_RET1_ARG4 (v32hi)
+DEF_RET1_ARG4 (v64hi)
+DEF_RET1_ARG4 (v128hi)
+DEF_RET1_ARG4 (v256hi)
+DEF_RET1_ARG4 (v512hi)
+DEF_RET1_ARG4 (v1024hi)
+DEF_RET1_ARG4 (v2048hi)
+
+DEF_RET1_ARG5 (v1hi)
+DEF_RET1_ARG5 (v2hi)
+DEF_RET1_ARG5 (v4hi)
+DEF_RET1_ARG5 (v8hi)
+DEF_RET1_ARG5 (v16hi)
+DEF_RET1_ARG5 (v32hi)
+DEF_RET1_ARG5 (v64hi)
+DEF_RET1_ARG5 (v128hi)
+DEF_RET1_ARG5 (v256hi)
+DEF_RET1_ARG5 (v512hi)
+DEF_RET1_ARG5 (v1024hi)
+DEF_RET1_ARG5 (v2048hi)
+
+DEF_RET1_ARG6 (v1hi)
+DEF_RET1_ARG6 (v2hi)
+DEF_RET1_ARG6 (v4hi)
+DEF_RET1_ARG6 (v8hi)
+DEF_RET1_ARG6 (v16hi)
+DEF_RET1_ARG6 (v32hi)
+DEF_RET1_ARG6 (v64hi)
+DEF_RET1_ARG6 (v128hi)
+DEF_RET1_ARG6 (v256hi)
+DEF_RET1_ARG6 (v512hi)
+DEF_RET1_ARG6 (v1024hi)
+DEF_RET1_ARG6 (v2048hi)
+
+DEF_RET1_ARG7 (v1hi)
+DEF_RET1_ARG7 (v2hi)
+DEF_RET1_ARG7 (v4hi)
+DEF_RET1_ARG7 (v8hi)
+DEF_RET1_ARG7 (v16hi)
+DEF_RET1_ARG7 (v32hi)
+DEF_RET1_ARG7 (v64hi)
+DEF_RET1_ARG7 (v128hi)
+DEF_RET1_ARG7 (v256hi)
+DEF_RET1_ARG7 (v512hi)
+DEF_RET1_ARG7 (v1024hi)
+DEF_RET1_ARG7 (v2048hi)
+
+DEF_RET1_ARG8 (v1hi)
+DEF_RET1_ARG8 (v2hi)
+DEF_RET1_ARG8 (v4hi)
+DEF_RET1_ARG8 (v8hi)
+DEF_RET1_ARG8 (v16hi)
+DEF_RET1_ARG8 (v32hi)
+DEF_RET1_ARG8 (v64hi)
+DEF_RET1_ARG8 (v128hi)
+DEF_RET1_ARG8 (v256hi)
+DEF_RET1_ARG8 (v512hi)
+DEF_RET1_ARG8 (v1024hi)
+DEF_RET1_ARG8 (v2048hi)
+
+DEF_RET1_ARG9 (v1hi)
+DEF_RET1_ARG9 (v2hi)
+DEF_RET1_ARG9 (v4hi)
+DEF_RET1_ARG9 (v8hi)
+DEF_RET1_ARG9 (v16hi)
+DEF_RET1_ARG9 (v32hi)
+DEF_RET1_ARG9 (v64hi)
+DEF_RET1_ARG9 (v128hi)
+DEF_RET1_ARG9 (v256hi)
+DEF_RET1_ARG9 (v512hi)
+DEF_RET1_ARG9 (v1024hi)
+DEF_RET1_ARG9 (v2048hi)
+
+/* { dg-final { scan-assembler-times {li\s+a[0-1],\s*0} 8 } } */
+/* { dg-final { scan-assembler-times {lhu\s+a0,\s*[0-9]+\(sp\)} 8 } } */
+/* { dg-final { scan-assembler-times {lw\s+a0,\s*[0-9]+\(sp\)} 8 } } */
+/* { dg-final { scan-assembler-times {ld\s+a[0-1],\s*[0-9]+\(sp\)} 33 } } */
+/* { dg-final { scan-assembler-times {sh\s+a[0-7],\s*[0-9]+\(sp\)} 43 } } */
+/* { dg-final { scan-assembler-times {sw\s+a[0-7],\s*[0-9]+\(sp\)} 43 } } */
+/* { dg-final { scan-assembler-times {sd\s+a[0-7],\s*[0-9]+\(sp\)} 103 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-3.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-3.c
new file mode 100644
index 00000000000..17b06933c72
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-3.c
@@ -0,0 +1,130 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv_zvl4096b --param riscv-autovec-preference=scalable -mabi=lp64d -O3" } */
+
+#include "def.h"
+
+DEF_RET1_ARG0 (v1si)
+DEF_RET1_ARG0 (v2si)
+DEF_RET1_ARG0 (v4si)
+DEF_RET1_ARG0 (v8si)
+DEF_RET1_ARG0 (v16si)
+DEF_RET1_ARG0 (v32si)
+DEF_RET1_ARG0 (v64si)
+DEF_RET1_ARG0 (v128si)
+DEF_RET1_ARG0 (v256si)
+DEF_RET1_ARG0 (v512si)
+DEF_RET1_ARG0 (v1024si)
+
+DEF_RET1_ARG1 (v1si)
+DEF_RET1_ARG1 (v2si)
+DEF_RET1_ARG1 (v4si)
+DEF_RET1_ARG1 (v8si)
+DEF_RET1_ARG1 (v16si)
+DEF_RET1_ARG1 (v32si)
+DEF_RET1_ARG1 (v64si)
+DEF_RET1_ARG1 (v128si)
+DEF_RET1_ARG1 (v256si)
+DEF_RET1_ARG1 (v512si)
+DEF_RET1_ARG1 (v1024si)
+
+DEF_RET1_ARG2 (v1si)
+DEF_RET1_ARG2 (v2si)
+DEF_RET1_ARG2 (v4si)
+DEF_RET1_ARG2 (v8si)
+DEF_RET1_ARG2 (v16si)
+DEF_RET1_ARG2 (v32si)
+DEF_RET1_ARG2 (v64si)
+DEF_RET1_ARG2 (v128si)
+DEF_RET1_ARG2 (v256si)
+DEF_RET1_ARG2 (v512si)
+DEF_RET1_ARG2 (v1024si)
+
+DEF_RET1_ARG3 (v1si)
+DEF_RET1_ARG3 (v2si)
+DEF_RET1_ARG3 (v4si)
+DEF_RET1_ARG3 (v8si)
+DEF_RET1_ARG3 (v16si)
+DEF_RET1_ARG3 (v32si)
+DEF_RET1_ARG3 (v64si)
+DEF_RET1_ARG3 (v128si)
+DEF_RET1_ARG3 (v256si)
+DEF_RET1_ARG3 (v512si)
+DEF_RET1_ARG3 (v1024si)
+
+DEF_RET1_ARG4 (v1si)
+DEF_RET1_ARG4 (v2si)
+DEF_RET1_ARG4 (v4si)
+DEF_RET1_ARG4 (v8si)
+DEF_RET1_ARG4 (v16si)
+DEF_RET1_ARG4 (v32si)
+DEF_RET1_ARG4 (v64si)
+DEF_RET1_ARG4 (v128si)
+DEF_RET1_ARG4 (v256si)
+DEF_RET1_ARG4 (v512si)
+DEF_RET1_ARG4 (v1024si)
+
+DEF_RET1_ARG5 (v1si)
+DEF_RET1_ARG5 (v2si)
+DEF_RET1_ARG5 (v4si)
+DEF_RET1_ARG5 (v8si)
+DEF_RET1_ARG5 (v16si)
+DEF_RET1_ARG5 (v32si)
+DEF_RET1_ARG5 (v64si)
+DEF_RET1_ARG5 (v128si)
+DEF_RET1_ARG5 (v256si)
+DEF_RET1_ARG5 (v512si)
+DEF_RET1_ARG5 (v1024si)
+
+DEF_RET1_ARG6 (v1si)
+DEF_RET1_ARG6 (v2si)
+DEF_RET1_ARG6 (v4si)
+DEF_RET1_ARG6 (v8si)
+DEF_RET1_ARG6 (v16si)
+DEF_RET1_ARG6 (v32si)
+DEF_RET1_ARG6 (v64si)
+DEF_RET1_ARG6 (v128si)
+DEF_RET1_ARG6 (v256si)
+DEF_RET1_ARG6 (v512si)
+DEF_RET1_ARG6 (v1024si)
+
+DEF_RET1_ARG7 (v1si)
+DEF_RET1_ARG7 (v2si)
+DEF_RET1_ARG7 (v4si)
+DEF_RET1_ARG7 (v8si)
+DEF_RET1_ARG7 (v16si)
+DEF_RET1_ARG7 (v32si)
+DEF_RET1_ARG7 (v64si)
+DEF_RET1_ARG7 (v128si)
+DEF_RET1_ARG7 (v256si)
+DEF_RET1_ARG7 (v512si)
+DEF_RET1_ARG7 (v1024si)
+
+DEF_RET1_ARG8 (v1si)
+DEF_RET1_ARG8 (v2si)
+DEF_RET1_ARG8 (v4si)
+DEF_RET1_ARG8 (v8si)
+DEF_RET1_ARG8 (v16si)
+DEF_RET1_ARG8 (v32si)
+DEF_RET1_ARG8 (v64si)
+DEF_RET1_ARG8 (v128si)
+DEF_RET1_ARG8 (v256si)
+DEF_RET1_ARG8 (v512si)
+DEF_RET1_ARG8 (v1024si)
+
+DEF_RET1_ARG9 (v1si)
+DEF_RET1_ARG9 (v2si)
+DEF_RET1_ARG9 (v4si)
+DEF_RET1_ARG9 (v8si)
+DEF_RET1_ARG9 (v16si)
+DEF_RET1_ARG9 (v32si)
+DEF_RET1_ARG9 (v64si)
+DEF_RET1_ARG9 (v128si)
+DEF_RET1_ARG9 (v256si)
+DEF_RET1_ARG9 (v512si)
+DEF_RET1_ARG9 (v1024si)
+
+/* { dg-final { scan-assembler-times {li\s+a[0-1],\s*0} 7 } } */
+/* { dg-final { scan-assembler-times {lw\s+a0,\s*[0-9]+\(sp\)} 8 } } */
+/* { dg-final { scan-assembler-times {ld\s+a[0-1],\s*[0-9]+\(sp\)} 31 } } */
+/* { dg-final { scan-assembler-times {sw\s+a[0-7],\s*[0-9]+\(sp\)} 43 } } */
+/* { dg-final { scan-assembler-times {sd\s+a[0-7],\s*[0-9]+\(sp\)} 103 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-4.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-4.c
new file mode 100644
index 00000000000..8c3f6ba98e3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-4.c
@@ -0,0 +1,118 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv_zvl4096b --param riscv-autovec-preference=scalable -mabi=lp64d -O3" } */
+
+#include "def.h"
+
+DEF_RET1_ARG0 (v1di)
+DEF_RET1_ARG0 (v2di)
+DEF_RET1_ARG0 (v4di)
+DEF_RET1_ARG0 (v8di)
+DEF_RET1_ARG0 (v16di)
+DEF_RET1_ARG0 (v32di)
+DEF_RET1_ARG0 (v64di)
+DEF_RET1_ARG0 (v128di)
+DEF_RET1_ARG0 (v256di)
+DEF_RET1_ARG0 (v512di)
+
+DEF_RET1_ARG1 (v1di)
+DEF_RET1_ARG1 (v2di)
+DEF_RET1_ARG1 (v4di)
+DEF_RET1_ARG1 (v8di)
+DEF_RET1_ARG1 (v16di)
+DEF_RET1_ARG1 (v32di)
+DEF_RET1_ARG1 (v64di)
+DEF_RET1_ARG1 (v128di)
+DEF_RET1_ARG1 (v256di)
+DEF_RET1_ARG1 (v512di)
+
+DEF_RET1_ARG2 (v1di)
+DEF_RET1_ARG2 (v2di)
+DEF_RET1_ARG2 (v4di)
+DEF_RET1_ARG2 (v8di)
+DEF_RET1_ARG2 (v16di)
+DEF_RET1_ARG2 (v32di)
+DEF_RET1_ARG2 (v64di)
+DEF_RET1_ARG2 (v128di)
+DEF_RET1_ARG2 (v256di)
+DEF_RET1_ARG2 (v512di)
+
+DEF_RET1_ARG3 (v1di)
+DEF_RET1_ARG3 (v2di)
+DEF_RET1_ARG3 (v4di)
+DEF_RET1_ARG3 (v8di)
+DEF_RET1_ARG3 (v16di)
+DEF_RET1_ARG3 (v32di)
+DEF_RET1_ARG3 (v64di)
+DEF_RET1_ARG3 (v128di)
+DEF_RET1_ARG3 (v256di)
+DEF_RET1_ARG3 (v512di)
+
+DEF_RET1_ARG4 (v1di)
+DEF_RET1_ARG4 (v2di)
+DEF_RET1_ARG4 (v4di)
+DEF_RET1_ARG4 (v8di)
+DEF_RET1_ARG4 (v16di)
+DEF_RET1_ARG4 (v32di)
+DEF_RET1_ARG4 (v64di)
+DEF_RET1_ARG4 (v128di)
+DEF_RET1_ARG4 (v256di)
+DEF_RET1_ARG4 (v512di)
+
+DEF_RET1_ARG5 (v1di)
+DEF_RET1_ARG5 (v2di)
+DEF_RET1_ARG5 (v4di)
+DEF_RET1_ARG5 (v8di)
+DEF_RET1_ARG5 (v16di)
+DEF_RET1_ARG5 (v32di)
+DEF_RET1_ARG5 (v64di)
+DEF_RET1_ARG5 (v128di)
+DEF_RET1_ARG5 (v256di)
+DEF_RET1_ARG5 (v512di)
+
+DEF_RET1_ARG6 (v1di)
+DEF_RET1_ARG6 (v2di)
+DEF_RET1_ARG6 (v4di)
+DEF_RET1_ARG6 (v8di)
+DEF_RET1_ARG6 (v16di)
+DEF_RET1_ARG6 (v32di)
+DEF_RET1_ARG6 (v64di)
+DEF_RET1_ARG6 (v128di)
+DEF_RET1_ARG6 (v256di)
+DEF_RET1_ARG6 (v512di)
+
+DEF_RET1_ARG7 (v1di)
+DEF_RET1_ARG7 (v2di)
+DEF_RET1_ARG7 (v4di)
+DEF_RET1_ARG7 (v8di)
+DEF_RET1_ARG7 (v16di)
+DEF_RET1_ARG7 (v32di)
+DEF_RET1_ARG7 (v64di)
+DEF_RET1_ARG7 (v128di)
+DEF_RET1_ARG7 (v256di)
+DEF_RET1_ARG7 (v512di)
+
+DEF_RET1_ARG8 (v1di)
+DEF_RET1_ARG8 (v2di)
+DEF_RET1_ARG8 (v4di)
+DEF_RET1_ARG8 (v8di)
+DEF_RET1_ARG8 (v16di)
+DEF_RET1_ARG8 (v32di)
+DEF_RET1_ARG8 (v64di)
+DEF_RET1_ARG8 (v128di)
+DEF_RET1_ARG8 (v256di)
+DEF_RET1_ARG8 (v512di)
+
+DEF_RET1_ARG9 (v1di)
+DEF_RET1_ARG9 (v2di)
+DEF_RET1_ARG9 (v4di)
+DEF_RET1_ARG9 (v8di)
+DEF_RET1_ARG9 (v16di)
+DEF_RET1_ARG9 (v32di)
+DEF_RET1_ARG9 (v64di)
+DEF_RET1_ARG9 (v128di)
+DEF_RET1_ARG9 (v256di)
+DEF_RET1_ARG9 (v512di)
+
+/* { dg-final { scan-assembler-times {li\s+a[0-1],\s*0} 6 } } */
+/* { dg-final { scan-assembler-times {ld\s+a[0-1],\s*[0-9]+\(sp\)} 29 } } */
+/* { dg-final { scan-assembler-times {sd\s+a[0-7],\s*[0-9]+\(sp\)} 103 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-5.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-5.c
new file mode 100644
index 00000000000..cfa4f5db372
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-5.c
@@ -0,0 +1,141 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv_zvfh_zvl4096b --param riscv-autovec-preference=scalable -mabi=lp64d -O3" } */
+
+#include "def.h"
+
+DEF_RET1_ARG0 (v1hf)
+DEF_RET1_ARG0 (v2hf)
+DEF_RET1_ARG0 (v4hf)
+DEF_RET1_ARG0 (v8hf)
+DEF_RET1_ARG0 (v16hf)
+DEF_RET1_ARG0 (v32hf)
+DEF_RET1_ARG0 (v64hf)
+DEF_RET1_ARG0 (v128hf)
+DEF_RET1_ARG0 (v256hf)
+DEF_RET1_ARG0 (v512hf)
+DEF_RET1_ARG0 (v1024hf)
+DEF_RET1_ARG0 (v2048hf)
+
+DEF_RET1_ARG1 (v1hf)
+DEF_RET1_ARG1 (v2hf)
+DEF_RET1_ARG1 (v4hf)
+DEF_RET1_ARG1 (v8hf)
+DEF_RET1_ARG1 (v16hf)
+DEF_RET1_ARG1 (v32hf)
+DEF_RET1_ARG1 (v64hf)
+DEF_RET1_ARG1 (v128hf)
+DEF_RET1_ARG1 (v256hf)
+DEF_RET1_ARG1 (v512hf)
+DEF_RET1_ARG1 (v1024hf)
+DEF_RET1_ARG1 (v2048hf)
+
+DEF_RET1_ARG2 (v1hf)
+DEF_RET1_ARG2 (v2hf)
+DEF_RET1_ARG2 (v4hf)
+DEF_RET1_ARG2 (v8hf)
+DEF_RET1_ARG2 (v16hf)
+DEF_RET1_ARG2 (v32hf)
+DEF_RET1_ARG2 (v64hf)
+DEF_RET1_ARG2 (v128hf)
+DEF_RET1_ARG2 (v256hf)
+DEF_RET1_ARG2 (v512hf)
+DEF_RET1_ARG2 (v1024hf)
+DEF_RET1_ARG2 (v2048hf)
+
+DEF_RET1_ARG3 (v1hf)
+DEF_RET1_ARG3 (v2hf)
+DEF_RET1_ARG3 (v4hf)
+DEF_RET1_ARG3 (v8hf)
+DEF_RET1_ARG3 (v16hf)
+DEF_RET1_ARG3 (v32hf)
+DEF_RET1_ARG3 (v64hf)
+DEF_RET1_ARG3 (v128hf)
+DEF_RET1_ARG3 (v256hf)
+DEF_RET1_ARG3 (v512hf)
+DEF_RET1_ARG3 (v1024hf)
+DEF_RET1_ARG3 (v2048hf)
+
+DEF_RET1_ARG4 (v1hf)
+DEF_RET1_ARG4 (v2hf)
+DEF_RET1_ARG4 (v4hf)
+DEF_RET1_ARG4 (v8hf)
+DEF_RET1_ARG4 (v16hf)
+DEF_RET1_ARG4 (v32hf)
+DEF_RET1_ARG4 (v64hf)
+DEF_RET1_ARG4 (v128hf)
+DEF_RET1_ARG4 (v256hf)
+DEF_RET1_ARG4 (v512hf)
+DEF_RET1_ARG4 (v1024hf)
+DEF_RET1_ARG4 (v2048hf)
+
+DEF_RET1_ARG5 (v1hf)
+DEF_RET1_ARG5 (v2hf)
+DEF_RET1_ARG5 (v4hf)
+DEF_RET1_ARG5 (v8hf)
+DEF_RET1_ARG5 (v16hf)
+DEF_RET1_ARG5 (v32hf)
+DEF_RET1_ARG5 (v64hf)
+DEF_RET1_ARG5 (v128hf)
+DEF_RET1_ARG5 (v256hf)
+DEF_RET1_ARG5 (v512hf)
+DEF_RET1_ARG5 (v1024hf)
+DEF_RET1_ARG5 (v2048hf)
+
+DEF_RET1_ARG6 (v1hf)
+DEF_RET1_ARG6 (v2hf)
+DEF_RET1_ARG6 (v4hf)
+DEF_RET1_ARG6 (v8hf)
+DEF_RET1_ARG6 (v16hf)
+DEF_RET1_ARG6 (v32hf)
+DEF_RET1_ARG6 (v64hf)
+DEF_RET1_ARG6 (v128hf)
+DEF_RET1_ARG6 (v256hf)
+DEF_RET1_ARG6 (v512hf)
+DEF_RET1_ARG6 (v1024hf)
+DEF_RET1_ARG6 (v2048hf)
+
+DEF_RET1_ARG7 (v1hf)
+DEF_RET1_ARG7 (v2hf)
+DEF_RET1_ARG7 (v4hf)
+DEF_RET1_ARG7 (v8hf)
+DEF_RET1_ARG7 (v16hf)
+DEF_RET1_ARG7 (v32hf)
+DEF_RET1_ARG7 (v64hf)
+DEF_RET1_ARG7 (v128hf)
+DEF_RET1_ARG7 (v256hf)
+DEF_RET1_ARG7 (v512hf)
+DEF_RET1_ARG7 (v1024hf)
+DEF_RET1_ARG7 (v2048hf)
+
+DEF_RET1_ARG8 (v1hf)
+DEF_RET1_ARG8 (v2hf)
+DEF_RET1_ARG8 (v4hf)
+DEF_RET1_ARG8 (v8hf)
+DEF_RET1_ARG8 (v16hf)
+DEF_RET1_ARG8 (v32hf)
+DEF_RET1_ARG8 (v64hf)
+DEF_RET1_ARG8 (v128hf)
+DEF_RET1_ARG8 (v256hf)
+DEF_RET1_ARG8 (v512hf)
+DEF_RET1_ARG8 (v1024hf)
+DEF_RET1_ARG8 (v2048hf)
+
+DEF_RET1_ARG9 (v1hf)
+DEF_RET1_ARG9 (v2hf)
+DEF_RET1_ARG9 (v4hf)
+DEF_RET1_ARG9 (v8hf)
+DEF_RET1_ARG9 (v16hf)
+DEF_RET1_ARG9 (v32hf)
+DEF_RET1_ARG9 (v64hf)
+DEF_RET1_ARG9 (v128hf)
+DEF_RET1_ARG9 (v256hf)
+DEF_RET1_ARG9 (v512hf)
+DEF_RET1_ARG9 (v1024hf)
+DEF_RET1_ARG9 (v2048hf)
+
+/* { dg-final { scan-assembler-times {li\s+a[0-1],\s*0} 6 } } */
+/* { dg-final { scan-assembler-times {flh\s+fa[0-1],\s*[0-9]+\(sp\)} 9 } } */
+/* { dg-final { scan-assembler-times {flw\s+fa[0-1],\s*[0-9]+\(sp\)} 9 } } */
+/* { dg-final { scan-assembler-times {fsh\s+fa[0-7],\s*[0-9]+\(sp\)} 43 } } */
+/* { dg-final { scan-assembler-times {fsw\s+fa[0-7],\s*[0-9]+\(sp\)} 43 } } */
+/* { dg-final { scan-assembler-times {sd\s+a[0-7],\s*[0-9]+\(sp\)} 103 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-6.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-6.c
new file mode 100644
index 00000000000..45a9e2debe8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-6.c
@@ -0,0 +1,129 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv_zvl4096b --param riscv-autovec-preference=scalable -mabi=lp64d -O3" } */
+
+#include "def.h"
+
+DEF_RET1_ARG0 (v1sf)
+DEF_RET1_ARG0 (v2sf)
+DEF_RET1_ARG0 (v4sf)
+DEF_RET1_ARG0 (v8sf)
+DEF_RET1_ARG0 (v16sf)
+DEF_RET1_ARG0 (v32sf)
+DEF_RET1_ARG0 (v64sf)
+DEF_RET1_ARG0 (v128sf)
+DEF_RET1_ARG0 (v256sf)
+DEF_RET1_ARG0 (v512sf)
+DEF_RET1_ARG0 (v1024sf)
+
+DEF_RET1_ARG1 (v1sf)
+DEF_RET1_ARG1 (v2sf)
+DEF_RET1_ARG1 (v4sf)
+DEF_RET1_ARG1 (v8sf)
+DEF_RET1_ARG1 (v16sf)
+DEF_RET1_ARG1 (v32sf)
+DEF_RET1_ARG1 (v64sf)
+DEF_RET1_ARG1 (v128sf)
+DEF_RET1_ARG1 (v256sf)
+DEF_RET1_ARG1 (v512sf)
+DEF_RET1_ARG1 (v1024sf)
+
+DEF_RET1_ARG2 (v1sf)
+DEF_RET1_ARG2 (v2sf)
+DEF_RET1_ARG2 (v4sf)
+DEF_RET1_ARG2 (v8sf)
+DEF_RET1_ARG2 (v16sf)
+DEF_RET1_ARG2 (v32sf)
+DEF_RET1_ARG2 (v64sf)
+DEF_RET1_ARG2 (v128sf)
+DEF_RET1_ARG2 (v256sf)
+DEF_RET1_ARG2 (v512sf)
+DEF_RET1_ARG2 (v1024sf)
+
+DEF_RET1_ARG3 (v1sf)
+DEF_RET1_ARG3 (v2sf)
+DEF_RET1_ARG3 (v4sf)
+DEF_RET1_ARG3 (v8sf)
+DEF_RET1_ARG3 (v16sf)
+DEF_RET1_ARG3 (v32sf)
+DEF_RET1_ARG3 (v64sf)
+DEF_RET1_ARG3 (v128sf)
+DEF_RET1_ARG3 (v256sf)
+DEF_RET1_ARG3 (v512sf)
+DEF_RET1_ARG3 (v1024sf)
+
+DEF_RET1_ARG4 (v1sf)
+DEF_RET1_ARG4 (v2sf)
+DEF_RET1_ARG4 (v4sf)
+DEF_RET1_ARG4 (v8sf)
+DEF_RET1_ARG4 (v16sf)
+DEF_RET1_ARG4 (v32sf)
+DEF_RET1_ARG4 (v64sf)
+DEF_RET1_ARG4 (v128sf)
+DEF_RET1_ARG4 (v256sf)
+DEF_RET1_ARG4 (v512sf)
+DEF_RET1_ARG4 (v1024sf)
+
+DEF_RET1_ARG5 (v1sf)
+DEF_RET1_ARG5 (v2sf)
+DEF_RET1_ARG5 (v4sf)
+DEF_RET1_ARG5 (v8sf)
+DEF_RET1_ARG5 (v16sf)
+DEF_RET1_ARG5 (v32sf)
+DEF_RET1_ARG5 (v64sf)
+DEF_RET1_ARG5 (v128sf)
+DEF_RET1_ARG5 (v256sf)
+DEF_RET1_ARG5 (v512sf)
+DEF_RET1_ARG5 (v1024sf)
+
+DEF_RET1_ARG6 (v1sf)
+DEF_RET1_ARG6 (v2sf)
+DEF_RET1_ARG6 (v4sf)
+DEF_RET1_ARG6 (v8sf)
+DEF_RET1_ARG6 (v16sf)
+DEF_RET1_ARG6 (v32sf)
+DEF_RET1_ARG6 (v64sf)
+DEF_RET1_ARG6 (v128sf)
+DEF_RET1_ARG6 (v256sf)
+DEF_RET1_ARG6 (v512sf)
+DEF_RET1_ARG6 (v1024sf)
+
+DEF_RET1_ARG7 (v1sf)
+DEF_RET1_ARG7 (v2sf)
+DEF_RET1_ARG7 (v4sf)
+DEF_RET1_ARG7 (v8sf)
+DEF_RET1_ARG7 (v16sf)
+DEF_RET1_ARG7 (v32sf)
+DEF_RET1_ARG7 (v64sf)
+DEF_RET1_ARG7 (v128sf)
+DEF_RET1_ARG7 (v256sf)
+DEF_RET1_ARG7 (v512sf)
+DEF_RET1_ARG7 (v1024sf)
+
+DEF_RET1_ARG8 (v1sf)
+DEF_RET1_ARG8 (v2sf)
+DEF_RET1_ARG8 (v4sf)
+DEF_RET1_ARG8 (v8sf)
+DEF_RET1_ARG8 (v16sf)
+DEF_RET1_ARG8 (v32sf)
+DEF_RET1_ARG8 (v64sf)
+DEF_RET1_ARG8 (v128sf)
+DEF_RET1_ARG8 (v256sf)
+DEF_RET1_ARG8 (v512sf)
+DEF_RET1_ARG8 (v1024sf)
+
+DEF_RET1_ARG9 (v1sf)
+DEF_RET1_ARG9 (v2sf)
+DEF_RET1_ARG9 (v4sf)
+DEF_RET1_ARG9 (v8sf)
+DEF_RET1_ARG9 (v16sf)
+DEF_RET1_ARG9 (v32sf)
+DEF_RET1_ARG9 (v64sf)
+DEF_RET1_ARG9 (v128sf)
+DEF_RET1_ARG9 (v256sf)
+DEF_RET1_ARG9 (v512sf)
+DEF_RET1_ARG9 (v1024sf)
+
+/* { dg-final { scan-assembler-times {li\s+a[0-1],\s*0} 5 } } */
+/* { dg-final { scan-assembler-times {flw\s+fa[0-1],\s*[0-9]+\(sp\)} 9 } } */
+/* { dg-final { scan-assembler-times {fsw\s+fa[0-7],\s*[0-9]+\(sp\)} 43 } } */
+/* { dg-final { scan-assembler-times {sd\s+a[0-7],\s*[0-9]+\(sp\)} 60 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-7.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-7.c
new file mode 100644
index 00000000000..a607786afea
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-7.c
@@ -0,0 +1,120 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv_zvl4096b --param riscv-autovec-preference=scalable -mabi=lp64d -O3" } */
+
+#include "def.h"
+
+DEF_RET1_ARG0 (v1df)
+DEF_RET1_ARG0 (v2df)
+DEF_RET1_ARG0 (v4df)
+DEF_RET1_ARG0 (v8df)
+DEF_RET1_ARG0 (v16df)
+DEF_RET1_ARG0 (v32df)
+DEF_RET1_ARG0 (v64df)
+DEF_RET1_ARG0 (v128df)
+DEF_RET1_ARG0 (v256df)
+DEF_RET1_ARG0 (v512df)
+
+DEF_RET1_ARG1 (v1df)
+DEF_RET1_ARG1 (v2df)
+DEF_RET1_ARG1 (v4df)
+DEF_RET1_ARG1 (v8df)
+DEF_RET1_ARG1 (v16df)
+DEF_RET1_ARG1 (v32df)
+DEF_RET1_ARG1 (v64df)
+DEF_RET1_ARG1 (v128df)
+DEF_RET1_ARG1 (v256df)
+DEF_RET1_ARG1 (v512df)
+
+DEF_RET1_ARG2 (v1df)
+DEF_RET1_ARG2 (v2df)
+DEF_RET1_ARG2 (v4df)
+DEF_RET1_ARG2 (v8df)
+DEF_RET1_ARG2 (v16df)
+DEF_RET1_ARG2 (v32df)
+DEF_RET1_ARG2 (v64df)
+DEF_RET1_ARG2 (v128df)
+DEF_RET1_ARG2 (v256df)
+DEF_RET1_ARG2 (v512df)
+
+DEF_RET1_ARG3 (v1df)
+DEF_RET1_ARG3 (v2df)
+DEF_RET1_ARG3 (v4df)
+DEF_RET1_ARG3 (v8df)
+DEF_RET1_ARG3 (v16df)
+DEF_RET1_ARG3 (v32df)
+DEF_RET1_ARG3 (v64df)
+DEF_RET1_ARG3 (v128df)
+DEF_RET1_ARG3 (v256df)
+DEF_RET1_ARG3 (v512df)
+
+DEF_RET1_ARG4 (v1df)
+DEF_RET1_ARG4 (v2df)
+DEF_RET1_ARG4 (v4df)
+DEF_RET1_ARG4 (v8df)
+DEF_RET1_ARG4 (v16df)
+DEF_RET1_ARG4 (v32df)
+DEF_RET1_ARG4 (v64df)
+DEF_RET1_ARG4 (v128df)
+DEF_RET1_ARG4 (v256df)
+DEF_RET1_ARG4 (v512df)
+
+DEF_RET1_ARG5 (v1df)
+DEF_RET1_ARG5 (v2df)
+DEF_RET1_ARG5 (v4df)
+DEF_RET1_ARG5 (v8df)
+DEF_RET1_ARG5 (v16df)
+DEF_RET1_ARG5 (v32df)
+DEF_RET1_ARG5 (v64df)
+DEF_RET1_ARG5 (v128df)
+DEF_RET1_ARG5 (v256df)
+DEF_RET1_ARG5 (v512df)
+
+DEF_RET1_ARG6 (v1df)
+DEF_RET1_ARG6 (v2df)
+DEF_RET1_ARG6 (v4df)
+DEF_RET1_ARG6 (v8df)
+DEF_RET1_ARG6 (v16df)
+DEF_RET1_ARG6 (v32df)
+DEF_RET1_ARG6 (v64df)
+DEF_RET1_ARG6 (v128df)
+DEF_RET1_ARG6 (v256df)
+DEF_RET1_ARG6 (v512df)
+
+DEF_RET1_ARG7 (v1df)
+DEF_RET1_ARG7 (v2df)
+DEF_RET1_ARG7 (v4df)
+DEF_RET1_ARG7 (v8df)
+DEF_RET1_ARG7 (v16df)
+DEF_RET1_ARG7 (v32df)
+DEF_RET1_ARG7 (v64df)
+DEF_RET1_ARG7 (v128df)
+DEF_RET1_ARG7 (v256df)
+DEF_RET1_ARG7 (v512df)
+
+DEF_RET1_ARG8 (v1df)
+DEF_RET1_ARG8 (v2df)
+DEF_RET1_ARG8 (v4df)
+DEF_RET1_ARG8 (v8df)
+DEF_RET1_ARG8 (v16df)
+DEF_RET1_ARG8 (v32df)
+DEF_RET1_ARG8 (v64df)
+DEF_RET1_ARG8 (v128df)
+DEF_RET1_ARG8 (v256df)
+DEF_RET1_ARG8 (v512df)
+
+DEF_RET1_ARG9 (v1df)
+DEF_RET1_ARG9 (v2df)
+DEF_RET1_ARG9 (v4df)
+DEF_RET1_ARG9 (v8df)
+DEF_RET1_ARG9 (v16df)
+DEF_RET1_ARG9 (v32df)
+DEF_RET1_ARG9 (v64df)
+DEF_RET1_ARG9 (v128df)
+DEF_RET1_ARG9 (v256df)
+DEF_RET1_ARG9 (v512df)
+
+/* { dg-final { scan-assembler-times {li\s+a[0-1],\s*0} 5 } } */
+/* { dg-final { scan-assembler-times {ld\s+a[0-1],\s*[0-9]+\(sp\)} 21 } } */
+/* { dg-final { scan-assembler-times {fld\s+fa[0-1],\s*[0-9]+\(sp\)} 9 } } */
+/* { dg-final { scan-assembler-times {sd\s+a[0-7],\s*[0-9]+\(sp\)} 60 } } */
+/* { dg-final { scan-assembler-times {fsd\s+fa[0-7],\s*[0-9]+\(sp\)} 43 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-8.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-8.c
new file mode 100644
index 00000000000..ed66a2cb9eb
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-8.c
@@ -0,0 +1,43 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv_zvl4096b -mabi=lp64d --param riscv-autovec-preference=scalable -O3 -fno-schedule-insns -fno-schedule-insns2" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include "def.h"
+
+/*
+** v8qi_RET1_ARG0:
+** li\s+a0,\s*0
+** ret
+*/
+DEF_RET1_ARG0 (v8qi)
+
+/*
+** v4hi_RET1_ARG1:
+** ret
+*/
+DEF_RET1_ARG1 (v4hi)
+
+/*
+** v2si_RET1_ARG2:
+** addi\s+sp,\s*sp,\s*-16
+** sd\s+a0,\s*0\(sp\)
+** sd\s+a1,\s*8\(sp\)
+** ...
+** ld\s+a0,\s*0\(sp\)
+** addi\s+sp,\s*sp,\s*16
+** jr\s+ra
+*/
+DEF_RET1_ARG2 (v2si)
+
+/*
+** v1di_RET1_ARG3:
+** addi\s+sp,\s*sp,\s*-32
+** sd\s+a0,\s*8\(sp\)
+** sd\s+a1,\s*16\(sp\)
+** sd\s+a2,\s*24\(sp\)
+** ...
+** ld\s+a0,\s*8\(sp\)
+** addi\s+sp,\s*sp,\s*32
+** jr\s+ra
+*/
+DEF_RET1_ARG3 (v1di)
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-9.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-9.c
new file mode 100644
index 00000000000..dd8e709ee59
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-9.c
@@ -0,0 +1,51 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv_zvfh_zvl4096b -mabi=lp64d --param riscv-autovec-preference=scalable -O3 -fno-schedule-insns -fno-schedule-insns2" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include "def.h"
+
+/*
+** v4hf_RET1_ARG1:
+** ret
+*/
+DEF_RET1_ARG1 (v4hf)
+
+/*
+** v2sf_RET1_ARG2:
+** addi\s+sp,\s*sp,\s*-16
+** fsd\s+fa0,\s*0\(sp\)
+** fsd\s+fa1,\s*8\(sp\)
+** ...
+** fld\s+fa0,\s*0\(sp\)
+** addi\s+sp,\s*sp,\s*16
+** jr\s+ra
+*/
+DEF_RET1_ARG2 (v2sf)
+
+/*
+** v4sf_RET1_ARG2:
+** addi\s+sp,\s*sp,\s*-32
+** sd\s+a0,\s*0\(sp\)
+** sd\s+a1,\s*8\(sp\)
+** sd\s+a2,\s*16\(sp\)
+** sd\s+a3,\s*24\(sp\)
+** ...
+** ld\s+a0,\s*0\(sp\)
+** ld\s+a1,\s*8\(sp\)
+** addi\s+sp,\s*sp,\s*32
+** jr\s+ra
+*/
+DEF_RET1_ARG2 (v4sf)
+
+/*
+** v1df_RET1_ARG3:
+** addi\s+sp,\s*sp,\s*-32
+** fsd\s+fa0,\s*8\(sp\)
+** fsd\s+fa1,\s*16\(sp\)
+** fsd\s+fa2,\s*24\(sp\)
+** ...
+** fld\s+fa0,\s*8\(sp\)
+** addi\s+sp,\s*sp,\s*32
+** jr\s+ra
+*/
+DEF_RET1_ARG3 (v1df)
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-run-1.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-run-1.c
new file mode 100644
index 00000000000..d8aa5c51cac
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-run-1.c
@@ -0,0 +1,55 @@
+/* { dg-do run { target { riscv_v } } } */
+/* { dg-additional-options "-std=c99 -fno-vect-cost-model --param=riscv-autovec-preference=scalable" } */
+
+typedef char v16qi __attribute__ ((vector_size (16)));
+
+v16qi
+add (v16qi a1, v16qi a2, v16qi a3, v16qi a4, v16qi a5, v16qi a6, v16qi a7,
+     v16qi a8, v16qi a9)
+{
+  return a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8 + a9;
+}
+
+int
+main ()
+{
+  v16qi a1 = {
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  };
+  v16qi a2 = {
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  };
+  v16qi a3 = {
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  };
+  v16qi a4 = {
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  };
+  v16qi a5 = {
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  };
+  v16qi a6 = {
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  };
+  v16qi a7 = {
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  };
+  v16qi a8 = {
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  };
+  v16qi a9 = {
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  };
+  v16qi expected = {
+    9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+  };
+  v16qi result = add (a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+  unsigned i;
+
+  for (i = 0; i < 16; i++)
+    if (result[i] != expected[i])
+      __builtin_abort ();
+
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-run-2.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-run-2.c
new file mode 100644
index 00000000000..57376a3924c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-run-2.c
@@ -0,0 +1,55 @@
+/* { dg-do run { target { riscv_v } } } */
+/* { dg-additional-options "-std=c99 -fno-vect-cost-model --param=riscv-autovec-preference=scalable" } */
+
+typedef short v8hi __attribute__ ((vector_size (16)));
+
+v8hi
+add (v8hi a1, v8hi a2, v8hi a3, v8hi a4, v8hi a5, v8hi a6, v8hi a7,
+     v8hi a8, v8hi a9)
+{
+  return a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8 + a9;
+}
+
+int
+main ()
+{
+  v8hi a1 = {
+    1, 1, 1, 1, 1, 1, 1, 1,
+  };
+  v8hi a2 = {
+    1, 1, 1, 1, 1, 1, 1, 1,
+  };
+  v8hi a3 = {
+    1, 1, 1, 1, 1, 1, 1, 1,
+  };
+  v8hi a4 = {
+    1, 1, 1, 1, 1, 1, 1, 1,
+  };
+  v8hi a5 = {
+    1, 1, 1, 1, 1, 1, 1, 1,
+  };
+  v8hi a6 = {
+    1, 1, 1, 1, 1, 1, 1, 1,
+  };
+  v8hi a7 = {
+    1, 1, 1, 1, 1, 1, 1, 1,
+  };
+  v8hi a8 = {
+    1, 1, 1, 1, 1, 1, 1, 1,
+  };
+  v8hi a9 = {
+    1, 1, 1, 1, 1, 1, 1, 1,
+  };
+  v8hi expected = {
+    9, 9, 9, 9, 9, 9, 9, 9,
+  };
+  v8hi result = add (a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+  unsigned i;
+
+  for (i = 0; i < 8; i++)
+    if (result[i] != expected[i])
+      __builtin_abort ();
+
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-run-3.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-run-3.c
new file mode 100644
index 00000000000..b37cd5669d4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-run-3.c
@@ -0,0 +1,55 @@
+/* { dg-do run { target { riscv_v } } } */
+/* { dg-additional-options "-std=c99 -fno-vect-cost-model --param=riscv-autovec-preference=scalable" } */
+
+typedef int v4si __attribute__ ((vector_size (16)));
+
+v4si
+add (v4si a1, v4si a2, v4si a3, v4si a4, v4si a5, v4si a6, v4si a7,
+     v4si a8, v4si a9)
+{
+  return a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8 + a9;
+}
+
+int
+main ()
+{
+  v4si a1 = {
+    1, 1, 1, 1,
+  };
+  v4si a2 = {
+    1, 1, 1, 1,
+  };
+  v4si a3 = {
+    1, 1, 1, 1,
+  };
+  v4si a4 = {
+    1, 1, 1, 1,
+  };
+  v4si a5 = {
+    1, 1, 1, 1,
+  };
+  v4si a6 = {
+    1, 1, 1, 1,
+  };
+  v4si a7 = {
+    1, 1, 1, 1,
+  };
+  v4si a8 = {
+    1, 1, 1, 1,
+  };
+  v4si a9 = {
+    1, 1, 1, 1,
+  };
+  v4si expected = {
+    9, 9, 9, 9,
+  };
+  v4si result = add (a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+  unsigned i;
+
+  for (i = 0; i < 4; i++)
+    if (result[i] != expected[i])
+      __builtin_abort ();
+
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-run-4.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-run-4.c
new file mode 100644
index 00000000000..0788447b501
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-run-4.c
@@ -0,0 +1,55 @@
+/* { dg-do run { target { riscv_v } } } */
+/* { dg-additional-options "-std=c99 -fno-vect-cost-model --param=riscv-autovec-preference=scalable" } */
+
+typedef long long v2di __attribute__ ((vector_size (16)));
+
+v2di
+add (v2di a1, v2di a2, v2di a3, v2di a4, v2di a5, v2di a6, v2di a7,
+     v2di a8, v2di a9)
+{
+  return a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8 + a9;
+}
+
+int
+main ()
+{
+  v2di a1 = {
+    1, 1,
+  };
+  v2di a2 = {
+    1, 1,
+  };
+  v2di a3 = {
+    1, 1,
+  };
+  v2di a4 = {
+    1, 1,
+  };
+  v2di a5 = {
+    1, 1,
+  };
+  v2di a6 = {
+    1, 1,
+  };
+  v2di a7 = {
+    1, 1,
+  };
+  v2di a8 = {
+    1, 1,
+  };
+  v2di a9 = {
+    1, 1,
+  };
+  v2di expected = {
+    9, 9,
+  };
+  v2di result = add (a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+  unsigned i;
+
+  for (i = 0; i < 2; i++)
+    if (result[i] != expected[i])
+      __builtin_abort ();
+
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-run-5.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-run-5.c
new file mode 100644
index 00000000000..ec8658d6a02
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-run-5.c
@@ -0,0 +1,55 @@
+/* { dg-do run { target { riscv_v } } } */
+/* { dg-additional-options "-std=c99 -fno-vect-cost-model --param=riscv-autovec-preference=scalable" } */
+
+typedef float v4sf __attribute__ ((vector_size (16)));
+
+v4sf
+add (v4sf a1, v4sf a2, v4sf a3, v4sf a4, v4sf a5, v4sf a6, v4sf a7,
+     v4sf a8, v4sf a9)
+{
+  return a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8 + a9;
+}
+
+int
+main ()
+{
+  v4sf a1 = {
+    1.0, 1.0, 1.0, 1.0,
+  };
+  v4sf a2 = {
+    1.0, 1.0, 1.0, 1.0,
+  };
+  v4sf a3 = {
+    1.0, 1.0, 1.0, 1.0,
+  };
+  v4sf a4 = {
+    1.0, 1.0, 1.0, 1.0,
+  };
+  v4sf a5 = {
+    1.0, 1.0, 1.0, 1.0,
+  };
+  v4sf a6 = {
+    1.0, 1.0, 1.0, 1.0,
+  };
+  v4sf a7 = {
+    1.0, 1.0, 1.0, 1.0,
+  };
+  v4sf a8 = {
+    1.0, 1.0, 1.0, 1.0,
+  };
+  v4sf a9 = {
+    1.0, 1.0, 1.0, 1.0,
+  };
+  v4sf expected = {
+    9.0, 9.0, 9.0, 9.0,
+  };
+  v4sf result = add (a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+  unsigned i;
+
+  for (i = 0; i < 4; i++)
+    if (result[i] != expected[i])
+      __builtin_abort ();
+
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-run-6.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-run-6.c
new file mode 100644
index 00000000000..bbb53a1a4af
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-run-6.c
@@ -0,0 +1,55 @@
+/* { dg-do run { target { riscv_v } } } */
+/* { dg-additional-options "-std=c99 -fno-vect-cost-model --param=riscv-autovec-preference=scalable" } */
+
+typedef long long v2df __attribute__ ((vector_size (16)));
+
+v2df
+add (v2df a1, v2df a2, v2df a3, v2df a4, v2df a5, v2df a6, v2df a7,
+     v2df a8, v2df a9)
+{
+  return a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8 + a9;
+}
+
+int
+main ()
+{
+  v2df a1 = {
+    1.0, 1.0,
+  };
+  v2df a2 = {
+    1.0, 1.0,
+  };
+  v2df a3 = {
+    1.0, 1.0,
+  };
+  v2df a4 = {
+    1.0, 1.0,
+  };
+  v2df a5 = {
+    1.0, 1.0,
+  };
+  v2df a6 = {
+    1.0, 1.0,
+  };
+  v2df a7 = {
+    1.0, 1.0,
+  };
+  v2df a8 = {
+    1.0, 1.0,
+  };
+  v2df a9 = {
+    1.0, 1.0,
+  };
+  v2df expected = {
+    9.0, 9.0,
+  };
+  v2df result = add (a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+  unsigned i;
+
+  for (i = 0; i < 2; i++)
+    if (result[i] != expected[i])
+      __builtin_abort ();
+
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/def.h b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/def.h
index cb7a1c97ded..ef55c4d7ecf 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/def.h
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/def.h
@@ -860,3 +860,77 @@ typedef double v512df __attribute__ ((vector_size (4096)));
     TYPE1 v = {__VA_ARGS__};                                                   \
     *(TYPE1 *) out = v;                                                        \
   }
+
+#define DEF_RET1_ARG0(TYPE)                                                    \
+  TYPE __attribute__((noinline))                                               \
+  TYPE##_RET1_ARG0 ()                                                          \
+  {                                                                            \
+    TYPE r = {};                                                               \
+    return r;                                                                  \
+  }
+
+#define DEF_RET1_ARG1(TYPE)                                                    \
+  TYPE __attribute__((noinline))                                               \
+  TYPE##_RET1_ARG1 (TYPE a1)                                                   \
+  {                                                                            \
+    return a1;                                                                 \
+  }
+
+#define DEF_RET1_ARG2(TYPE)                                                    \
+  TYPE __attribute__((noinline))                                               \
+  TYPE##_RET1_ARG2 (TYPE a1, TYPE a2)                                          \
+  {                                                                            \
+    return a1 + a2;                                                            \
+  }
+
+#define DEF_RET1_ARG3(TYPE)                                                    \
+  TYPE __attribute__((noinline))                                               \
+  TYPE##_RET1_ARG3 (TYPE a1, TYPE a2, TYPE a3)                                 \
+  {                                                                            \
+    return a1 + a2 + a3;                                                       \
+  }
+
+#define DEF_RET1_ARG4(TYPE)                                                    \
+  TYPE __attribute__((noinline))                                               \
+  TYPE##_RET1_ARG4 (TYPE a1, TYPE a2, TYPE a3, TYPE a4)                        \
+  {                                                                            \
+    return a1 + a2 + a3 + a4;                                                  \
+  }
+
+#define DEF_RET1_ARG5(TYPE)                                                    \
+  TYPE __attribute__((noinline))                                               \
+  TYPE##_RET1_ARG5 (TYPE a1, TYPE a2, TYPE a3, TYPE a4, TYPE a5)               \
+  {                                                                            \
+    return a1 + a2 + a3 + a4 + a5;                                             \
+  }
+
+#define DEF_RET1_ARG6(TYPE)                                                    \
+  TYPE __attribute__((noinline))                                               \
+  TYPE##_RET1_ARG6 (TYPE a1, TYPE a2, TYPE a3, TYPE a4, TYPE a5, TYPE a6)      \
+  {                                                                            \
+    return a1 + a2 + a3 + a4 + a5 + a6;                                        \
+  }
+
+#define DEF_RET1_ARG7(TYPE)                                                    \
+  TYPE __attribute__((noinline))                                               \
+  TYPE##_RET1_ARG7 (TYPE a1, TYPE a2, TYPE a3, TYPE a4, TYPE a5, TYPE a6,      \
+     TYPE a7)                                                   \
+  {                                                                            \
+    return a1 + a2 + a3 + a4 + a5 + a6 + a7;                                   \
+  }
+
+#define DEF_RET1_ARG8(TYPE)                                                    \
+  TYPE __attribute__((noinline))                                               \
+  TYPE##_RET1_ARG8 (TYPE a1, TYPE a2, TYPE a3, TYPE a4, TYPE a5, TYPE a6,      \
+     TYPE a7, TYPE a8)                                          \
+  {                                                                            \
+    return a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8;                              \
+  }
+
+#define DEF_RET1_ARG9(TYPE)                                                    \
+  TYPE __attribute__((noinline))                                               \
+  TYPE##_RET1_ARG9 (TYPE a1, TYPE a2, TYPE a3, TYPE a4, TYPE a5, TYPE a6,      \
+     TYPE a7, TYPE a8, TYPE a9)                                 \
+  {                                                                            \
+    return a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8 + a9;                         \
+  }
-- 
2.34.1
 
 

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

* Re: [PATCH v1] RISC-V: Bugfix for vls integer mode calling convention
  2024-01-24  3:16 [PATCH v1] RISC-V: Bugfix for vls integer mode calling convention pan2.li
  2024-01-24  3:18 ` juzhe.zhong
@ 2024-01-29 13:22 ` Kito Cheng
  2024-01-30  8:39   ` Li, Pan2
  2024-01-30  8:37 ` [PATCH v2] RISC-V: Bugfix for vls mode aggregated in GPR " pan2.li
  2 siblings, 1 reply; 10+ messages in thread
From: Kito Cheng @ 2024-01-29 13:22 UTC (permalink / raw)
  To: pan2.li; +Cc: gcc-patches, juzhe.zhong, yanzhang.wang

> @@ -4868,6 +4968,63 @@ riscv_pass_fpr_pair (machine_mode mode, unsigned regno1,
>                                    GEN_INT (offset2))));
>  }
>
> +static rtx
> +riscv_pass_vls_aggregate_in_gpr_or_fpr (struct riscv_arg_info *info,
> +                                       machine_mode mode, unsigned gpr_base,
> +                                       unsigned fpr_base)

Tried a few more clang and GCC code gen and I found VLS vector is
always passed in
GPR, and never passed in FPR, so I think I should update psABI rather than fix
that on GCC side.

> @@ -4997,9 +5170,7 @@ riscv_get_arg_info (struct riscv_arg_info *info, const CUMULATIVE_ARGS *cum,
>    info->gpr_offset = cum->num_gprs;
>    info->fpr_offset = cum->num_fprs;
>
> -  /* When disable vector_abi or scalable vector argument is anonymous, this
> -     argument is passed by reference.  */
> -  if (riscv_v_ext_mode_p (mode) && (!riscv_vector_abi || !named))
> +  if (riscv_mode_pass_by_reference_p (mode, named))

Keep as it is fine since riscv_vector_abi is gone.

>      return NULL_RTX;
>
>    if (named)

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

* [PATCH v2] RISC-V: Bugfix for vls mode aggregated in GPR calling convention
  2024-01-24  3:16 [PATCH v1] RISC-V: Bugfix for vls integer mode calling convention pan2.li
  2024-01-24  3:18 ` juzhe.zhong
  2024-01-29 13:22 ` Kito Cheng
@ 2024-01-30  8:37 ` pan2.li
  2024-01-30 12:54   ` Kito Cheng
  2 siblings, 1 reply; 10+ messages in thread
From: pan2.li @ 2024-01-30  8:37 UTC (permalink / raw)
  To: gcc-patches; +Cc: juzhe.zhong, pan2.li, yanzhang.wang, kito.cheng

From: Pan Li <pan2.li@intel.com>

According to the issue as below.

https://hub.fgit.cf/riscv-non-isa/riscv-elf-psabi-doc/pull/416

When the mode size of vls integer mode is less than 2 * XLEN, we will
take the gpr for both the args and the return values. Instead of the
reference. For example the below code:

typedef short v8hi __attribute__ ((vector_size (16)));

v8hi __attribute__((noinline))
add (v8hi a, v8hi b)
{
  v8hi r = a + b;
  return r;
}

Before this patch:
add:
  vsetivli zero,8,e16,m1,ta,ma
  vle16.v  v1,0(a1) <== arg by reference
  vle16.v  v2,0(a2) <== arg by reference
  vadd.vv  v1,v1,v2
  vse16.v  v1,0(a0) <== return by reference
  ret

After this patch:
add:
  addi     sp,sp,-32
  sd       a0,0(sp)  <== arg by register a0 - a3
  sd       a1,8(sp)
  sd       a2,16(sp)
  sd       a3,24(sp)
  addi     a5,sp,16
  vsetivli zero,8,e16,m1,ta,ma
  vle16.v  v2,0(sp)
  vle16.v  v1,0(a5)
  vadd.vv  v1,v1,v2
  vse16.v  v1,0(sp)
  ld       a0,0(sp)  <== return by a0 - a1.
  ld       a1,8(sp)
  addi     sp,sp,32
  jr       ra

For vls floating point, we take the same rules as integer and passed by
the gpr or reference.  However, we can simplify the above code by vmv,
and avoid the read/write values to the stack.  We will prepare another
patch for it as it isn't the scope of bugfix.

The riscv regression passed for this patch.

gcc/ChangeLog:

	* config/riscv/riscv.cc (riscv_v_vls_mode_aggregate_gpr_count): New function to
	calculate the gpr count required by vls mode.
	(riscv_v_vls_to_gpr_mode): New function convert vls mode to gpr mode.
	(riscv_pass_vls_aggregate_in_gpr): New function to return the rtx of gpr
	for vls mode.
	(riscv_get_arg_info): Add vls mode handling.
	(riscv_pass_by_reference): Return false if arg info has no zero gpr count.

gcc/testsuite/ChangeLog:

	* gcc.target/riscv/rvv/autovec/vls/def.h: Add new helper macro.
	* gcc.target/riscv/rvv/autovec/vls/calling-convention-1.c: New test.
	* gcc.target/riscv/rvv/autovec/vls/calling-convention-10.c: New test.
	* gcc.target/riscv/rvv/autovec/vls/calling-convention-2.c: New test.
	* gcc.target/riscv/rvv/autovec/vls/calling-convention-3.c: New test.
	* gcc.target/riscv/rvv/autovec/vls/calling-convention-4.c: New test.
	* gcc.target/riscv/rvv/autovec/vls/calling-convention-5.c: New test.
	* gcc.target/riscv/rvv/autovec/vls/calling-convention-6.c: New test.
	* gcc.target/riscv/rvv/autovec/vls/calling-convention-7.c: New test.
	* gcc.target/riscv/rvv/autovec/vls/calling-convention-8.c: New test.
	* gcc.target/riscv/rvv/autovec/vls/calling-convention-9.c: New test.
	* gcc.target/riscv/rvv/autovec/vls/calling-convention-run-1.c: New test.
	* gcc.target/riscv/rvv/autovec/vls/calling-convention-run-2.c: New test.
	* gcc.target/riscv/rvv/autovec/vls/calling-convention-run-3.c: New test.
	* gcc.target/riscv/rvv/autovec/vls/calling-convention-run-4.c: New test.
	* gcc.target/riscv/rvv/autovec/vls/calling-convention-run-5.c: New test.
	* gcc.target/riscv/rvv/autovec/vls/calling-convention-run-6.c: New test.

Signed-off-by: Pan Li <pan2.li@intel.com>
---
 gcc/config/riscv/riscv.cc                     |  75 +++++++++
 .../rvv/autovec/vls/calling-convention-1.c    | 154 ++++++++++++++++++
 .../rvv/autovec/vls/calling-convention-10.c   |  51 ++++++
 .../rvv/autovec/vls/calling-convention-2.c    | 142 ++++++++++++++++
 .../rvv/autovec/vls/calling-convention-3.c    | 130 +++++++++++++++
 .../rvv/autovec/vls/calling-convention-4.c    | 118 ++++++++++++++
 .../rvv/autovec/vls/calling-convention-5.c    | 141 ++++++++++++++++
 .../rvv/autovec/vls/calling-convention-6.c    | 129 +++++++++++++++
 .../rvv/autovec/vls/calling-convention-7.c    | 118 ++++++++++++++
 .../rvv/autovec/vls/calling-convention-8.c    |  43 +++++
 .../rvv/autovec/vls/calling-convention-9.c    |  51 ++++++
 .../autovec/vls/calling-convention-run-1.c    |  55 +++++++
 .../autovec/vls/calling-convention-run-2.c    |  55 +++++++
 .../autovec/vls/calling-convention-run-3.c    |  55 +++++++
 .../autovec/vls/calling-convention-run-4.c    |  55 +++++++
 .../autovec/vls/calling-convention-run-5.c    |  55 +++++++
 .../autovec/vls/calling-convention-run-6.c    |  55 +++++++
 .../gcc.target/riscv/rvv/autovec/vls/def.h    |  74 +++++++++
 18 files changed, 1556 insertions(+)
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-1.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-10.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-2.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-3.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-4.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-5.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-6.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-7.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-8.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-9.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-run-1.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-run-2.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-run-3.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-run-4.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-run-5.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-run-6.c

diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 7b6111aa545..1de69019cd4 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -1382,6 +1382,38 @@ riscv_v_ext_mode_p (machine_mode mode)
 	 || riscv_v_ext_vls_mode_p (mode);
 }
 
+static unsigned
+riscv_v_vls_mode_aggregate_gpr_count (unsigned vls_unit_size,
+				      unsigned scalar_unit_size)
+{
+  gcc_assert (vls_unit_size != 0 && scalar_unit_size != 0);
+
+  if (vls_unit_size < scalar_unit_size)
+    return 1;
+
+  return vls_unit_size / scalar_unit_size;
+}
+
+static machine_mode
+riscv_v_vls_to_gpr_mode (unsigned vls_mode_size)
+{
+  switch (vls_mode_size)
+    {
+      case 16:
+	return TImode;
+      case 8:
+	return DImode;
+      case 4:
+	return SImode;
+      case 2:
+	return HImode;
+      case 1:
+	return QImode;
+      default:
+	gcc_unreachable ();
+    }
+}
+
 /* Call from ADJUST_NUNITS in riscv-modes.def. Return the correct
    NUNITS size for corresponding machine_mode.  */
 
@@ -4868,6 +4900,41 @@ riscv_pass_fpr_pair (machine_mode mode, unsigned regno1,
 				   GEN_INT (offset2))));
 }
 
+static rtx
+riscv_pass_vls_aggregate_in_gpr (struct riscv_arg_info *info, machine_mode mode,
+				 unsigned gpr_base)
+{
+  gcc_assert (riscv_v_ext_vls_mode_p (mode));
+
+  unsigned count = 0;
+  unsigned regnum = 0;
+  machine_mode gpr_mode = VOIDmode;
+  unsigned vls_size = GET_MODE_SIZE (mode).to_constant ();
+  unsigned gpr_size =  GET_MODE_SIZE (Xmode);
+
+  if (IN_RANGE (vls_size, 0, gpr_size * 2))
+    {
+      count = riscv_v_vls_mode_aggregate_gpr_count (vls_size, gpr_size);
+
+      if (count + info->gpr_offset <= MAX_ARGS_IN_REGISTERS)
+	{
+	  regnum = gpr_base + info->gpr_offset;
+	  info->num_gprs = count;
+	  gpr_mode = riscv_v_vls_to_gpr_mode (vls_size);
+	}
+    }
+
+  if (!regnum)
+    return NULL_RTX; /* Return NULL_RTX if we cannot find a suitable reg.  */
+
+  gcc_assert (gpr_mode != VOIDmode);
+
+  rtx reg = gen_rtx_REG (gpr_mode, regnum);
+  rtx x = gen_rtx_EXPR_LIST (VOIDmode, reg, CONST0_RTX (gpr_mode));
+
+  return gen_rtx_PARALLEL (mode, gen_rtvec (1, x));
+}
+
 /* Initialize a variable CUM of type CUMULATIVE_ARGS
    for a call to a function whose data type is FNTYPE.
    For a library call, FNTYPE is 0.  */
@@ -5067,6 +5134,10 @@ riscv_get_arg_info (struct riscv_arg_info *info, const CUMULATIVE_ARGS *cum,
       /* For scalable vector argument.  */
       if (riscv_vector_type_p (type) && riscv_v_ext_mode_p (mode))
 	return riscv_get_vector_arg (info, cum, mode, return_p);
+
+      /* For vls mode aggregated in gpr.  */
+      if (riscv_v_ext_vls_mode_p (mode))
+	return riscv_pass_vls_aggregate_in_gpr (info, mode, gpr_base);
     }
 
   /* Work out the size of the argument.  */
@@ -5196,6 +5267,10 @@ riscv_pass_by_reference (cumulative_args_t cum_v, const function_arg_info &arg)
       if (info.num_fprs)
 	return false;
 
+      /* Don't pass by reference if we can use general register(s) for vls.  */
+      if (info.num_gprs && riscv_v_ext_vls_mode_p (arg.mode))
+	return false;
+
       /* Don't pass by reference if we can use vector register groups.  */
       if (info.num_vrs > 0 || info.num_mrs > 0)
 	return false;
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-1.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-1.c
new file mode 100644
index 00000000000..41e31c258f8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-1.c
@@ -0,0 +1,154 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv_zvl4096b --param riscv-autovec-preference=scalable -mabi=lp64d -O3" } */
+
+#include "def.h"
+
+DEF_RET1_ARG0 (v1qi)
+DEF_RET1_ARG0 (v2qi)
+DEF_RET1_ARG0 (v4qi)
+DEF_RET1_ARG0 (v8qi)
+DEF_RET1_ARG0 (v16qi)
+DEF_RET1_ARG0 (v32qi)
+DEF_RET1_ARG0 (v64qi)
+DEF_RET1_ARG0 (v128qi)
+DEF_RET1_ARG0 (v256qi)
+DEF_RET1_ARG0 (v512qi)
+DEF_RET1_ARG0 (v1024qi)
+DEF_RET1_ARG0 (v2048qi)
+DEF_RET1_ARG0 (v4096qi)
+
+DEF_RET1_ARG1 (v1qi)
+DEF_RET1_ARG1 (v2qi)
+DEF_RET1_ARG1 (v4qi)
+DEF_RET1_ARG1 (v8qi)
+DEF_RET1_ARG1 (v16qi)
+DEF_RET1_ARG1 (v32qi)
+DEF_RET1_ARG1 (v64qi)
+DEF_RET1_ARG1 (v128qi)
+DEF_RET1_ARG1 (v256qi)
+DEF_RET1_ARG1 (v512qi)
+DEF_RET1_ARG1 (v1024qi)
+DEF_RET1_ARG1 (v2048qi)
+DEF_RET1_ARG1 (v4096qi)
+
+DEF_RET1_ARG2 (v1qi)
+DEF_RET1_ARG2 (v2qi)
+DEF_RET1_ARG2 (v4qi)
+DEF_RET1_ARG2 (v8qi)
+DEF_RET1_ARG2 (v16qi)
+DEF_RET1_ARG2 (v32qi)
+DEF_RET1_ARG2 (v64qi)
+DEF_RET1_ARG2 (v128qi)
+DEF_RET1_ARG2 (v256qi)
+DEF_RET1_ARG2 (v512qi)
+DEF_RET1_ARG2 (v1024qi)
+DEF_RET1_ARG2 (v2048qi)
+DEF_RET1_ARG2 (v4096qi)
+
+DEF_RET1_ARG3 (v1qi)
+DEF_RET1_ARG3 (v2qi)
+DEF_RET1_ARG3 (v4qi)
+DEF_RET1_ARG3 (v8qi)
+DEF_RET1_ARG3 (v16qi)
+DEF_RET1_ARG3 (v32qi)
+DEF_RET1_ARG3 (v64qi)
+DEF_RET1_ARG3 (v128qi)
+DEF_RET1_ARG3 (v256qi)
+DEF_RET1_ARG3 (v512qi)
+DEF_RET1_ARG3 (v1024qi)
+DEF_RET1_ARG3 (v2048qi)
+DEF_RET1_ARG3 (v4096qi)
+
+DEF_RET1_ARG4 (v1qi)
+DEF_RET1_ARG4 (v2qi)
+DEF_RET1_ARG4 (v4qi)
+DEF_RET1_ARG4 (v8qi)
+DEF_RET1_ARG4 (v16qi)
+DEF_RET1_ARG4 (v32qi)
+DEF_RET1_ARG4 (v64qi)
+DEF_RET1_ARG4 (v128qi)
+DEF_RET1_ARG4 (v256qi)
+DEF_RET1_ARG4 (v512qi)
+DEF_RET1_ARG4 (v1024qi)
+DEF_RET1_ARG4 (v2048qi)
+DEF_RET1_ARG4 (v4096qi)
+
+DEF_RET1_ARG5 (v1qi)
+DEF_RET1_ARG5 (v2qi)
+DEF_RET1_ARG5 (v4qi)
+DEF_RET1_ARG5 (v8qi)
+DEF_RET1_ARG5 (v16qi)
+DEF_RET1_ARG5 (v32qi)
+DEF_RET1_ARG5 (v64qi)
+DEF_RET1_ARG5 (v128qi)
+DEF_RET1_ARG5 (v256qi)
+DEF_RET1_ARG5 (v512qi)
+DEF_RET1_ARG5 (v1024qi)
+DEF_RET1_ARG5 (v2048qi)
+DEF_RET1_ARG5 (v4096qi)
+
+DEF_RET1_ARG6 (v1qi)
+DEF_RET1_ARG6 (v2qi)
+DEF_RET1_ARG6 (v4qi)
+DEF_RET1_ARG6 (v8qi)
+DEF_RET1_ARG6 (v16qi)
+DEF_RET1_ARG6 (v32qi)
+DEF_RET1_ARG6 (v64qi)
+DEF_RET1_ARG6 (v128qi)
+DEF_RET1_ARG6 (v256qi)
+DEF_RET1_ARG6 (v512qi)
+DEF_RET1_ARG6 (v1024qi)
+DEF_RET1_ARG6 (v2048qi)
+DEF_RET1_ARG6 (v4096qi)
+
+DEF_RET1_ARG7 (v1qi)
+DEF_RET1_ARG7 (v2qi)
+DEF_RET1_ARG7 (v4qi)
+DEF_RET1_ARG7 (v8qi)
+DEF_RET1_ARG7 (v16qi)
+DEF_RET1_ARG7 (v32qi)
+DEF_RET1_ARG7 (v64qi)
+DEF_RET1_ARG7 (v128qi)
+DEF_RET1_ARG7 (v256qi)
+DEF_RET1_ARG7 (v512qi)
+DEF_RET1_ARG7 (v1024qi)
+DEF_RET1_ARG7 (v2048qi)
+DEF_RET1_ARG7 (v4096qi)
+
+DEF_RET1_ARG8 (v1qi)
+DEF_RET1_ARG8 (v2qi)
+DEF_RET1_ARG8 (v4qi)
+DEF_RET1_ARG8 (v8qi)
+DEF_RET1_ARG8 (v16qi)
+DEF_RET1_ARG8 (v32qi)
+DEF_RET1_ARG8 (v64qi)
+DEF_RET1_ARG8 (v128qi)
+DEF_RET1_ARG8 (v256qi)
+DEF_RET1_ARG8 (v512qi)
+DEF_RET1_ARG8 (v1024qi)
+DEF_RET1_ARG8 (v2048qi)
+DEF_RET1_ARG8 (v4096qi)
+
+DEF_RET1_ARG9 (v1qi)
+DEF_RET1_ARG9 (v2qi)
+DEF_RET1_ARG9 (v4qi)
+DEF_RET1_ARG9 (v8qi)
+DEF_RET1_ARG9 (v16qi)
+DEF_RET1_ARG9 (v32qi)
+DEF_RET1_ARG9 (v64qi)
+DEF_RET1_ARG9 (v128qi)
+DEF_RET1_ARG9 (v256qi)
+DEF_RET1_ARG9 (v512qi)
+DEF_RET1_ARG9 (v1024qi)
+DEF_RET1_ARG9 (v2048qi)
+DEF_RET1_ARG9 (v4096qi)
+
+/* { dg-final { scan-assembler-times {li\s+a[0-1],\s*0} 9 } } */
+/* { dg-final { scan-assembler-times {lbu\s+a0,\s*[0-9]+\(sp\)} 8 } } */
+/* { dg-final { scan-assembler-times {lhu\s+a0,\s*[0-9]+\(sp\)} 8 } } */
+/* { dg-final { scan-assembler-times {lw\s+a0,\s*[0-9]+\(sp\)} 8 } } */
+/* { dg-final { scan-assembler-times {ld\s+a[0-1],\s*[0-9]+\(sp\)} 35 } } */
+/* { dg-final { scan-assembler-times {sb\s+a[0-7],\s*[0-9]+\(sp\)} 43 } } */
+/* { dg-final { scan-assembler-times {sh\s+a[0-7],\s*[0-9]+\(sp\)} 43 } } */
+/* { dg-final { scan-assembler-times {sw\s+a[0-7],\s*[0-9]+\(sp\)} 43 } } */
+/* { dg-final { scan-assembler-times {sd\s+a[0-7],\s*[0-9]+\(sp\)} 103 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-10.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-10.c
new file mode 100644
index 00000000000..0abc6cf0146
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-10.c
@@ -0,0 +1,51 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv_zvfh_zvl4096b -mabi=lp64 --param riscv-autovec-preference=scalable -O3 -fno-schedule-insns -fno-schedule-insns2" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include "def.h"
+
+/*
+** v4hf_RET1_ARG1:
+** ret
+*/
+DEF_RET1_ARG1 (v4hf)
+
+/*
+** v2sf_RET1_ARG2:
+** addi\s+sp,\s*sp,\s*-16
+** sd\s+a0,\s*0\(sp\)
+** sd\s+a1,\s*8\(sp\)
+** ...
+** ld\s+a0,\s*0\(sp\)
+** addi\s+sp,\s*sp,\s*16
+** jr\s+ra
+*/
+DEF_RET1_ARG2 (v2sf)
+
+/*
+** v4sf_RET1_ARG2:
+** addi\s+sp,\s*sp,\s*-32
+** sd\s+a0,\s*0\(sp\)
+** sd\s+a1,\s*8\(sp\)
+** sd\s+a2,\s*16\(sp\)
+** sd\s+a3,\s*24\(sp\)
+** ...
+** ld\s+a0,\s*0\(sp\)
+** ld\s+a1,\s*8\(sp\)
+** addi\s+sp,\s*sp,\s*32
+** jr\s+ra
+*/
+DEF_RET1_ARG2 (v4sf)
+
+/*
+** v1df_RET1_ARG3:
+** addi\s+sp,\s*sp,\s*-32
+** sd\s+a0,\s*8\(sp\)
+** sd\s+a1,\s*16\(sp\)
+** sd\s+a2,\s*24\(sp\)
+** ...
+** ld\s+a0,\s*8\(sp\)
+** addi\s+sp,\s*sp,\s*32
+** jr\s+ra
+*/
+DEF_RET1_ARG3 (v1df)
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-2.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-2.c
new file mode 100644
index 00000000000..8544f160e93
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-2.c
@@ -0,0 +1,142 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv_zvl4096b --param riscv-autovec-preference=scalable -mabi=lp64d -O3" } */
+
+#include "def.h"
+
+DEF_RET1_ARG0 (v1hi)
+DEF_RET1_ARG0 (v2hi)
+DEF_RET1_ARG0 (v4hi)
+DEF_RET1_ARG0 (v8hi)
+DEF_RET1_ARG0 (v16hi)
+DEF_RET1_ARG0 (v32hi)
+DEF_RET1_ARG0 (v64hi)
+DEF_RET1_ARG0 (v128hi)
+DEF_RET1_ARG0 (v256hi)
+DEF_RET1_ARG0 (v512hi)
+DEF_RET1_ARG0 (v1024hi)
+DEF_RET1_ARG0 (v2048hi)
+
+DEF_RET1_ARG1 (v1hi)
+DEF_RET1_ARG1 (v2hi)
+DEF_RET1_ARG1 (v4hi)
+DEF_RET1_ARG1 (v8hi)
+DEF_RET1_ARG1 (v16hi)
+DEF_RET1_ARG1 (v32hi)
+DEF_RET1_ARG1 (v64hi)
+DEF_RET1_ARG1 (v128hi)
+DEF_RET1_ARG1 (v256hi)
+DEF_RET1_ARG1 (v512hi)
+DEF_RET1_ARG1 (v1024hi)
+DEF_RET1_ARG1 (v2048hi)
+
+DEF_RET1_ARG2 (v1hi)
+DEF_RET1_ARG2 (v2hi)
+DEF_RET1_ARG2 (v4hi)
+DEF_RET1_ARG2 (v8hi)
+DEF_RET1_ARG2 (v16hi)
+DEF_RET1_ARG2 (v32hi)
+DEF_RET1_ARG2 (v64hi)
+DEF_RET1_ARG2 (v128hi)
+DEF_RET1_ARG2 (v256hi)
+DEF_RET1_ARG2 (v512hi)
+DEF_RET1_ARG2 (v1024hi)
+DEF_RET1_ARG2 (v2048hi)
+
+DEF_RET1_ARG3 (v1hi)
+DEF_RET1_ARG3 (v2hi)
+DEF_RET1_ARG3 (v4hi)
+DEF_RET1_ARG3 (v8hi)
+DEF_RET1_ARG3 (v16hi)
+DEF_RET1_ARG3 (v32hi)
+DEF_RET1_ARG3 (v64hi)
+DEF_RET1_ARG3 (v128hi)
+DEF_RET1_ARG3 (v256hi)
+DEF_RET1_ARG3 (v512hi)
+DEF_RET1_ARG3 (v1024hi)
+DEF_RET1_ARG3 (v2048hi)
+
+DEF_RET1_ARG4 (v1hi)
+DEF_RET1_ARG4 (v2hi)
+DEF_RET1_ARG4 (v4hi)
+DEF_RET1_ARG4 (v8hi)
+DEF_RET1_ARG4 (v16hi)
+DEF_RET1_ARG4 (v32hi)
+DEF_RET1_ARG4 (v64hi)
+DEF_RET1_ARG4 (v128hi)
+DEF_RET1_ARG4 (v256hi)
+DEF_RET1_ARG4 (v512hi)
+DEF_RET1_ARG4 (v1024hi)
+DEF_RET1_ARG4 (v2048hi)
+
+DEF_RET1_ARG5 (v1hi)
+DEF_RET1_ARG5 (v2hi)
+DEF_RET1_ARG5 (v4hi)
+DEF_RET1_ARG5 (v8hi)
+DEF_RET1_ARG5 (v16hi)
+DEF_RET1_ARG5 (v32hi)
+DEF_RET1_ARG5 (v64hi)
+DEF_RET1_ARG5 (v128hi)
+DEF_RET1_ARG5 (v256hi)
+DEF_RET1_ARG5 (v512hi)
+DEF_RET1_ARG5 (v1024hi)
+DEF_RET1_ARG5 (v2048hi)
+
+DEF_RET1_ARG6 (v1hi)
+DEF_RET1_ARG6 (v2hi)
+DEF_RET1_ARG6 (v4hi)
+DEF_RET1_ARG6 (v8hi)
+DEF_RET1_ARG6 (v16hi)
+DEF_RET1_ARG6 (v32hi)
+DEF_RET1_ARG6 (v64hi)
+DEF_RET1_ARG6 (v128hi)
+DEF_RET1_ARG6 (v256hi)
+DEF_RET1_ARG6 (v512hi)
+DEF_RET1_ARG6 (v1024hi)
+DEF_RET1_ARG6 (v2048hi)
+
+DEF_RET1_ARG7 (v1hi)
+DEF_RET1_ARG7 (v2hi)
+DEF_RET1_ARG7 (v4hi)
+DEF_RET1_ARG7 (v8hi)
+DEF_RET1_ARG7 (v16hi)
+DEF_RET1_ARG7 (v32hi)
+DEF_RET1_ARG7 (v64hi)
+DEF_RET1_ARG7 (v128hi)
+DEF_RET1_ARG7 (v256hi)
+DEF_RET1_ARG7 (v512hi)
+DEF_RET1_ARG7 (v1024hi)
+DEF_RET1_ARG7 (v2048hi)
+
+DEF_RET1_ARG8 (v1hi)
+DEF_RET1_ARG8 (v2hi)
+DEF_RET1_ARG8 (v4hi)
+DEF_RET1_ARG8 (v8hi)
+DEF_RET1_ARG8 (v16hi)
+DEF_RET1_ARG8 (v32hi)
+DEF_RET1_ARG8 (v64hi)
+DEF_RET1_ARG8 (v128hi)
+DEF_RET1_ARG8 (v256hi)
+DEF_RET1_ARG8 (v512hi)
+DEF_RET1_ARG8 (v1024hi)
+DEF_RET1_ARG8 (v2048hi)
+
+DEF_RET1_ARG9 (v1hi)
+DEF_RET1_ARG9 (v2hi)
+DEF_RET1_ARG9 (v4hi)
+DEF_RET1_ARG9 (v8hi)
+DEF_RET1_ARG9 (v16hi)
+DEF_RET1_ARG9 (v32hi)
+DEF_RET1_ARG9 (v64hi)
+DEF_RET1_ARG9 (v128hi)
+DEF_RET1_ARG9 (v256hi)
+DEF_RET1_ARG9 (v512hi)
+DEF_RET1_ARG9 (v1024hi)
+DEF_RET1_ARG9 (v2048hi)
+
+/* { dg-final { scan-assembler-times {li\s+a[0-1],\s*0} 8 } } */
+/* { dg-final { scan-assembler-times {lhu\s+a0,\s*[0-9]+\(sp\)} 8 } } */
+/* { dg-final { scan-assembler-times {lw\s+a0,\s*[0-9]+\(sp\)} 8 } } */
+/* { dg-final { scan-assembler-times {ld\s+a[0-1],\s*[0-9]+\(sp\)} 33 } } */
+/* { dg-final { scan-assembler-times {sh\s+a[0-7],\s*[0-9]+\(sp\)} 43 } } */
+/* { dg-final { scan-assembler-times {sw\s+a[0-7],\s*[0-9]+\(sp\)} 43 } } */
+/* { dg-final { scan-assembler-times {sd\s+a[0-7],\s*[0-9]+\(sp\)} 103 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-3.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-3.c
new file mode 100644
index 00000000000..17b06933c72
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-3.c
@@ -0,0 +1,130 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv_zvl4096b --param riscv-autovec-preference=scalable -mabi=lp64d -O3" } */
+
+#include "def.h"
+
+DEF_RET1_ARG0 (v1si)
+DEF_RET1_ARG0 (v2si)
+DEF_RET1_ARG0 (v4si)
+DEF_RET1_ARG0 (v8si)
+DEF_RET1_ARG0 (v16si)
+DEF_RET1_ARG0 (v32si)
+DEF_RET1_ARG0 (v64si)
+DEF_RET1_ARG0 (v128si)
+DEF_RET1_ARG0 (v256si)
+DEF_RET1_ARG0 (v512si)
+DEF_RET1_ARG0 (v1024si)
+
+DEF_RET1_ARG1 (v1si)
+DEF_RET1_ARG1 (v2si)
+DEF_RET1_ARG1 (v4si)
+DEF_RET1_ARG1 (v8si)
+DEF_RET1_ARG1 (v16si)
+DEF_RET1_ARG1 (v32si)
+DEF_RET1_ARG1 (v64si)
+DEF_RET1_ARG1 (v128si)
+DEF_RET1_ARG1 (v256si)
+DEF_RET1_ARG1 (v512si)
+DEF_RET1_ARG1 (v1024si)
+
+DEF_RET1_ARG2 (v1si)
+DEF_RET1_ARG2 (v2si)
+DEF_RET1_ARG2 (v4si)
+DEF_RET1_ARG2 (v8si)
+DEF_RET1_ARG2 (v16si)
+DEF_RET1_ARG2 (v32si)
+DEF_RET1_ARG2 (v64si)
+DEF_RET1_ARG2 (v128si)
+DEF_RET1_ARG2 (v256si)
+DEF_RET1_ARG2 (v512si)
+DEF_RET1_ARG2 (v1024si)
+
+DEF_RET1_ARG3 (v1si)
+DEF_RET1_ARG3 (v2si)
+DEF_RET1_ARG3 (v4si)
+DEF_RET1_ARG3 (v8si)
+DEF_RET1_ARG3 (v16si)
+DEF_RET1_ARG3 (v32si)
+DEF_RET1_ARG3 (v64si)
+DEF_RET1_ARG3 (v128si)
+DEF_RET1_ARG3 (v256si)
+DEF_RET1_ARG3 (v512si)
+DEF_RET1_ARG3 (v1024si)
+
+DEF_RET1_ARG4 (v1si)
+DEF_RET1_ARG4 (v2si)
+DEF_RET1_ARG4 (v4si)
+DEF_RET1_ARG4 (v8si)
+DEF_RET1_ARG4 (v16si)
+DEF_RET1_ARG4 (v32si)
+DEF_RET1_ARG4 (v64si)
+DEF_RET1_ARG4 (v128si)
+DEF_RET1_ARG4 (v256si)
+DEF_RET1_ARG4 (v512si)
+DEF_RET1_ARG4 (v1024si)
+
+DEF_RET1_ARG5 (v1si)
+DEF_RET1_ARG5 (v2si)
+DEF_RET1_ARG5 (v4si)
+DEF_RET1_ARG5 (v8si)
+DEF_RET1_ARG5 (v16si)
+DEF_RET1_ARG5 (v32si)
+DEF_RET1_ARG5 (v64si)
+DEF_RET1_ARG5 (v128si)
+DEF_RET1_ARG5 (v256si)
+DEF_RET1_ARG5 (v512si)
+DEF_RET1_ARG5 (v1024si)
+
+DEF_RET1_ARG6 (v1si)
+DEF_RET1_ARG6 (v2si)
+DEF_RET1_ARG6 (v4si)
+DEF_RET1_ARG6 (v8si)
+DEF_RET1_ARG6 (v16si)
+DEF_RET1_ARG6 (v32si)
+DEF_RET1_ARG6 (v64si)
+DEF_RET1_ARG6 (v128si)
+DEF_RET1_ARG6 (v256si)
+DEF_RET1_ARG6 (v512si)
+DEF_RET1_ARG6 (v1024si)
+
+DEF_RET1_ARG7 (v1si)
+DEF_RET1_ARG7 (v2si)
+DEF_RET1_ARG7 (v4si)
+DEF_RET1_ARG7 (v8si)
+DEF_RET1_ARG7 (v16si)
+DEF_RET1_ARG7 (v32si)
+DEF_RET1_ARG7 (v64si)
+DEF_RET1_ARG7 (v128si)
+DEF_RET1_ARG7 (v256si)
+DEF_RET1_ARG7 (v512si)
+DEF_RET1_ARG7 (v1024si)
+
+DEF_RET1_ARG8 (v1si)
+DEF_RET1_ARG8 (v2si)
+DEF_RET1_ARG8 (v4si)
+DEF_RET1_ARG8 (v8si)
+DEF_RET1_ARG8 (v16si)
+DEF_RET1_ARG8 (v32si)
+DEF_RET1_ARG8 (v64si)
+DEF_RET1_ARG8 (v128si)
+DEF_RET1_ARG8 (v256si)
+DEF_RET1_ARG8 (v512si)
+DEF_RET1_ARG8 (v1024si)
+
+DEF_RET1_ARG9 (v1si)
+DEF_RET1_ARG9 (v2si)
+DEF_RET1_ARG9 (v4si)
+DEF_RET1_ARG9 (v8si)
+DEF_RET1_ARG9 (v16si)
+DEF_RET1_ARG9 (v32si)
+DEF_RET1_ARG9 (v64si)
+DEF_RET1_ARG9 (v128si)
+DEF_RET1_ARG9 (v256si)
+DEF_RET1_ARG9 (v512si)
+DEF_RET1_ARG9 (v1024si)
+
+/* { dg-final { scan-assembler-times {li\s+a[0-1],\s*0} 7 } } */
+/* { dg-final { scan-assembler-times {lw\s+a0,\s*[0-9]+\(sp\)} 8 } } */
+/* { dg-final { scan-assembler-times {ld\s+a[0-1],\s*[0-9]+\(sp\)} 31 } } */
+/* { dg-final { scan-assembler-times {sw\s+a[0-7],\s*[0-9]+\(sp\)} 43 } } */
+/* { dg-final { scan-assembler-times {sd\s+a[0-7],\s*[0-9]+\(sp\)} 103 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-4.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-4.c
new file mode 100644
index 00000000000..8c3f6ba98e3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-4.c
@@ -0,0 +1,118 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv_zvl4096b --param riscv-autovec-preference=scalable -mabi=lp64d -O3" } */
+
+#include "def.h"
+
+DEF_RET1_ARG0 (v1di)
+DEF_RET1_ARG0 (v2di)
+DEF_RET1_ARG0 (v4di)
+DEF_RET1_ARG0 (v8di)
+DEF_RET1_ARG0 (v16di)
+DEF_RET1_ARG0 (v32di)
+DEF_RET1_ARG0 (v64di)
+DEF_RET1_ARG0 (v128di)
+DEF_RET1_ARG0 (v256di)
+DEF_RET1_ARG0 (v512di)
+
+DEF_RET1_ARG1 (v1di)
+DEF_RET1_ARG1 (v2di)
+DEF_RET1_ARG1 (v4di)
+DEF_RET1_ARG1 (v8di)
+DEF_RET1_ARG1 (v16di)
+DEF_RET1_ARG1 (v32di)
+DEF_RET1_ARG1 (v64di)
+DEF_RET1_ARG1 (v128di)
+DEF_RET1_ARG1 (v256di)
+DEF_RET1_ARG1 (v512di)
+
+DEF_RET1_ARG2 (v1di)
+DEF_RET1_ARG2 (v2di)
+DEF_RET1_ARG2 (v4di)
+DEF_RET1_ARG2 (v8di)
+DEF_RET1_ARG2 (v16di)
+DEF_RET1_ARG2 (v32di)
+DEF_RET1_ARG2 (v64di)
+DEF_RET1_ARG2 (v128di)
+DEF_RET1_ARG2 (v256di)
+DEF_RET1_ARG2 (v512di)
+
+DEF_RET1_ARG3 (v1di)
+DEF_RET1_ARG3 (v2di)
+DEF_RET1_ARG3 (v4di)
+DEF_RET1_ARG3 (v8di)
+DEF_RET1_ARG3 (v16di)
+DEF_RET1_ARG3 (v32di)
+DEF_RET1_ARG3 (v64di)
+DEF_RET1_ARG3 (v128di)
+DEF_RET1_ARG3 (v256di)
+DEF_RET1_ARG3 (v512di)
+
+DEF_RET1_ARG4 (v1di)
+DEF_RET1_ARG4 (v2di)
+DEF_RET1_ARG4 (v4di)
+DEF_RET1_ARG4 (v8di)
+DEF_RET1_ARG4 (v16di)
+DEF_RET1_ARG4 (v32di)
+DEF_RET1_ARG4 (v64di)
+DEF_RET1_ARG4 (v128di)
+DEF_RET1_ARG4 (v256di)
+DEF_RET1_ARG4 (v512di)
+
+DEF_RET1_ARG5 (v1di)
+DEF_RET1_ARG5 (v2di)
+DEF_RET1_ARG5 (v4di)
+DEF_RET1_ARG5 (v8di)
+DEF_RET1_ARG5 (v16di)
+DEF_RET1_ARG5 (v32di)
+DEF_RET1_ARG5 (v64di)
+DEF_RET1_ARG5 (v128di)
+DEF_RET1_ARG5 (v256di)
+DEF_RET1_ARG5 (v512di)
+
+DEF_RET1_ARG6 (v1di)
+DEF_RET1_ARG6 (v2di)
+DEF_RET1_ARG6 (v4di)
+DEF_RET1_ARG6 (v8di)
+DEF_RET1_ARG6 (v16di)
+DEF_RET1_ARG6 (v32di)
+DEF_RET1_ARG6 (v64di)
+DEF_RET1_ARG6 (v128di)
+DEF_RET1_ARG6 (v256di)
+DEF_RET1_ARG6 (v512di)
+
+DEF_RET1_ARG7 (v1di)
+DEF_RET1_ARG7 (v2di)
+DEF_RET1_ARG7 (v4di)
+DEF_RET1_ARG7 (v8di)
+DEF_RET1_ARG7 (v16di)
+DEF_RET1_ARG7 (v32di)
+DEF_RET1_ARG7 (v64di)
+DEF_RET1_ARG7 (v128di)
+DEF_RET1_ARG7 (v256di)
+DEF_RET1_ARG7 (v512di)
+
+DEF_RET1_ARG8 (v1di)
+DEF_RET1_ARG8 (v2di)
+DEF_RET1_ARG8 (v4di)
+DEF_RET1_ARG8 (v8di)
+DEF_RET1_ARG8 (v16di)
+DEF_RET1_ARG8 (v32di)
+DEF_RET1_ARG8 (v64di)
+DEF_RET1_ARG8 (v128di)
+DEF_RET1_ARG8 (v256di)
+DEF_RET1_ARG8 (v512di)
+
+DEF_RET1_ARG9 (v1di)
+DEF_RET1_ARG9 (v2di)
+DEF_RET1_ARG9 (v4di)
+DEF_RET1_ARG9 (v8di)
+DEF_RET1_ARG9 (v16di)
+DEF_RET1_ARG9 (v32di)
+DEF_RET1_ARG9 (v64di)
+DEF_RET1_ARG9 (v128di)
+DEF_RET1_ARG9 (v256di)
+DEF_RET1_ARG9 (v512di)
+
+/* { dg-final { scan-assembler-times {li\s+a[0-1],\s*0} 6 } } */
+/* { dg-final { scan-assembler-times {ld\s+a[0-1],\s*[0-9]+\(sp\)} 29 } } */
+/* { dg-final { scan-assembler-times {sd\s+a[0-7],\s*[0-9]+\(sp\)} 103 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-5.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-5.c
new file mode 100644
index 00000000000..a0208d8f42b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-5.c
@@ -0,0 +1,141 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv_zvfh_zvl4096b --param riscv-autovec-preference=scalable -mabi=lp64d -O3" } */
+
+#include "def.h"
+
+DEF_RET1_ARG0 (v1hf)
+DEF_RET1_ARG0 (v2hf)
+DEF_RET1_ARG0 (v4hf)
+DEF_RET1_ARG0 (v8hf)
+DEF_RET1_ARG0 (v16hf)
+DEF_RET1_ARG0 (v32hf)
+DEF_RET1_ARG0 (v64hf)
+DEF_RET1_ARG0 (v128hf)
+DEF_RET1_ARG0 (v256hf)
+DEF_RET1_ARG0 (v512hf)
+DEF_RET1_ARG0 (v1024hf)
+DEF_RET1_ARG0 (v2048hf)
+
+DEF_RET1_ARG1 (v1hf)
+DEF_RET1_ARG1 (v2hf)
+DEF_RET1_ARG1 (v4hf)
+DEF_RET1_ARG1 (v8hf)
+DEF_RET1_ARG1 (v16hf)
+DEF_RET1_ARG1 (v32hf)
+DEF_RET1_ARG1 (v64hf)
+DEF_RET1_ARG1 (v128hf)
+DEF_RET1_ARG1 (v256hf)
+DEF_RET1_ARG1 (v512hf)
+DEF_RET1_ARG1 (v1024hf)
+DEF_RET1_ARG1 (v2048hf)
+
+DEF_RET1_ARG2 (v1hf)
+DEF_RET1_ARG2 (v2hf)
+DEF_RET1_ARG2 (v4hf)
+DEF_RET1_ARG2 (v8hf)
+DEF_RET1_ARG2 (v16hf)
+DEF_RET1_ARG2 (v32hf)
+DEF_RET1_ARG2 (v64hf)
+DEF_RET1_ARG2 (v128hf)
+DEF_RET1_ARG2 (v256hf)
+DEF_RET1_ARG2 (v512hf)
+DEF_RET1_ARG2 (v1024hf)
+DEF_RET1_ARG2 (v2048hf)
+
+DEF_RET1_ARG3 (v1hf)
+DEF_RET1_ARG3 (v2hf)
+DEF_RET1_ARG3 (v4hf)
+DEF_RET1_ARG3 (v8hf)
+DEF_RET1_ARG3 (v16hf)
+DEF_RET1_ARG3 (v32hf)
+DEF_RET1_ARG3 (v64hf)
+DEF_RET1_ARG3 (v128hf)
+DEF_RET1_ARG3 (v256hf)
+DEF_RET1_ARG3 (v512hf)
+DEF_RET1_ARG3 (v1024hf)
+DEF_RET1_ARG3 (v2048hf)
+
+DEF_RET1_ARG4 (v1hf)
+DEF_RET1_ARG4 (v2hf)
+DEF_RET1_ARG4 (v4hf)
+DEF_RET1_ARG4 (v8hf)
+DEF_RET1_ARG4 (v16hf)
+DEF_RET1_ARG4 (v32hf)
+DEF_RET1_ARG4 (v64hf)
+DEF_RET1_ARG4 (v128hf)
+DEF_RET1_ARG4 (v256hf)
+DEF_RET1_ARG4 (v512hf)
+DEF_RET1_ARG4 (v1024hf)
+DEF_RET1_ARG4 (v2048hf)
+
+DEF_RET1_ARG5 (v1hf)
+DEF_RET1_ARG5 (v2hf)
+DEF_RET1_ARG5 (v4hf)
+DEF_RET1_ARG5 (v8hf)
+DEF_RET1_ARG5 (v16hf)
+DEF_RET1_ARG5 (v32hf)
+DEF_RET1_ARG5 (v64hf)
+DEF_RET1_ARG5 (v128hf)
+DEF_RET1_ARG5 (v256hf)
+DEF_RET1_ARG5 (v512hf)
+DEF_RET1_ARG5 (v1024hf)
+DEF_RET1_ARG5 (v2048hf)
+
+DEF_RET1_ARG6 (v1hf)
+DEF_RET1_ARG6 (v2hf)
+DEF_RET1_ARG6 (v4hf)
+DEF_RET1_ARG6 (v8hf)
+DEF_RET1_ARG6 (v16hf)
+DEF_RET1_ARG6 (v32hf)
+DEF_RET1_ARG6 (v64hf)
+DEF_RET1_ARG6 (v128hf)
+DEF_RET1_ARG6 (v256hf)
+DEF_RET1_ARG6 (v512hf)
+DEF_RET1_ARG6 (v1024hf)
+DEF_RET1_ARG6 (v2048hf)
+
+DEF_RET1_ARG7 (v1hf)
+DEF_RET1_ARG7 (v2hf)
+DEF_RET1_ARG7 (v4hf)
+DEF_RET1_ARG7 (v8hf)
+DEF_RET1_ARG7 (v16hf)
+DEF_RET1_ARG7 (v32hf)
+DEF_RET1_ARG7 (v64hf)
+DEF_RET1_ARG7 (v128hf)
+DEF_RET1_ARG7 (v256hf)
+DEF_RET1_ARG7 (v512hf)
+DEF_RET1_ARG7 (v1024hf)
+DEF_RET1_ARG7 (v2048hf)
+
+DEF_RET1_ARG8 (v1hf)
+DEF_RET1_ARG8 (v2hf)
+DEF_RET1_ARG8 (v4hf)
+DEF_RET1_ARG8 (v8hf)
+DEF_RET1_ARG8 (v16hf)
+DEF_RET1_ARG8 (v32hf)
+DEF_RET1_ARG8 (v64hf)
+DEF_RET1_ARG8 (v128hf)
+DEF_RET1_ARG8 (v256hf)
+DEF_RET1_ARG8 (v512hf)
+DEF_RET1_ARG8 (v1024hf)
+DEF_RET1_ARG8 (v2048hf)
+
+DEF_RET1_ARG9 (v1hf)
+DEF_RET1_ARG9 (v2hf)
+DEF_RET1_ARG9 (v4hf)
+DEF_RET1_ARG9 (v8hf)
+DEF_RET1_ARG9 (v16hf)
+DEF_RET1_ARG9 (v32hf)
+DEF_RET1_ARG9 (v64hf)
+DEF_RET1_ARG9 (v128hf)
+DEF_RET1_ARG9 (v256hf)
+DEF_RET1_ARG9 (v512hf)
+DEF_RET1_ARG9 (v1024hf)
+DEF_RET1_ARG9 (v2048hf)
+
+/* { dg-final { scan-assembler-times {li\s+a[0-1],\s*0} 8 } } */
+/* { dg-final { scan-assembler-times {lhu\s+a[0-1],\s*[0-9]+\(sp\)} 8 } } */
+/* { dg-final { scan-assembler-times {lw\s+a[0-1],\s*[0-9]+\(sp\)} 8 } } */
+/* { dg-final { scan-assembler-times {sh\s+a[0-7],\s*[0-9]+\(sp\)} 43 } } */
+/* { dg-final { scan-assembler-times {sw\s+a[0-7],\s*[0-9]+\(sp\)} 43 } } */
+/* { dg-final { scan-assembler-times {sd\s+a[0-7],\s*[0-9]+\(sp\)} 103 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-6.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-6.c
new file mode 100644
index 00000000000..58ef8bf65f3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-6.c
@@ -0,0 +1,129 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv_zvl4096b --param riscv-autovec-preference=scalable -mabi=lp64d -O3" } */
+
+#include "def.h"
+
+DEF_RET1_ARG0 (v1sf)
+DEF_RET1_ARG0 (v2sf)
+DEF_RET1_ARG0 (v4sf)
+DEF_RET1_ARG0 (v8sf)
+DEF_RET1_ARG0 (v16sf)
+DEF_RET1_ARG0 (v32sf)
+DEF_RET1_ARG0 (v64sf)
+DEF_RET1_ARG0 (v128sf)
+DEF_RET1_ARG0 (v256sf)
+DEF_RET1_ARG0 (v512sf)
+DEF_RET1_ARG0 (v1024sf)
+
+DEF_RET1_ARG1 (v1sf)
+DEF_RET1_ARG1 (v2sf)
+DEF_RET1_ARG1 (v4sf)
+DEF_RET1_ARG1 (v8sf)
+DEF_RET1_ARG1 (v16sf)
+DEF_RET1_ARG1 (v32sf)
+DEF_RET1_ARG1 (v64sf)
+DEF_RET1_ARG1 (v128sf)
+DEF_RET1_ARG1 (v256sf)
+DEF_RET1_ARG1 (v512sf)
+DEF_RET1_ARG1 (v1024sf)
+
+DEF_RET1_ARG2 (v1sf)
+DEF_RET1_ARG2 (v2sf)
+DEF_RET1_ARG2 (v4sf)
+DEF_RET1_ARG2 (v8sf)
+DEF_RET1_ARG2 (v16sf)
+DEF_RET1_ARG2 (v32sf)
+DEF_RET1_ARG2 (v64sf)
+DEF_RET1_ARG2 (v128sf)
+DEF_RET1_ARG2 (v256sf)
+DEF_RET1_ARG2 (v512sf)
+DEF_RET1_ARG2 (v1024sf)
+
+DEF_RET1_ARG3 (v1sf)
+DEF_RET1_ARG3 (v2sf)
+DEF_RET1_ARG3 (v4sf)
+DEF_RET1_ARG3 (v8sf)
+DEF_RET1_ARG3 (v16sf)
+DEF_RET1_ARG3 (v32sf)
+DEF_RET1_ARG3 (v64sf)
+DEF_RET1_ARG3 (v128sf)
+DEF_RET1_ARG3 (v256sf)
+DEF_RET1_ARG3 (v512sf)
+DEF_RET1_ARG3 (v1024sf)
+
+DEF_RET1_ARG4 (v1sf)
+DEF_RET1_ARG4 (v2sf)
+DEF_RET1_ARG4 (v4sf)
+DEF_RET1_ARG4 (v8sf)
+DEF_RET1_ARG4 (v16sf)
+DEF_RET1_ARG4 (v32sf)
+DEF_RET1_ARG4 (v64sf)
+DEF_RET1_ARG4 (v128sf)
+DEF_RET1_ARG4 (v256sf)
+DEF_RET1_ARG4 (v512sf)
+DEF_RET1_ARG4 (v1024sf)
+
+DEF_RET1_ARG5 (v1sf)
+DEF_RET1_ARG5 (v2sf)
+DEF_RET1_ARG5 (v4sf)
+DEF_RET1_ARG5 (v8sf)
+DEF_RET1_ARG5 (v16sf)
+DEF_RET1_ARG5 (v32sf)
+DEF_RET1_ARG5 (v64sf)
+DEF_RET1_ARG5 (v128sf)
+DEF_RET1_ARG5 (v256sf)
+DEF_RET1_ARG5 (v512sf)
+DEF_RET1_ARG5 (v1024sf)
+
+DEF_RET1_ARG6 (v1sf)
+DEF_RET1_ARG6 (v2sf)
+DEF_RET1_ARG6 (v4sf)
+DEF_RET1_ARG6 (v8sf)
+DEF_RET1_ARG6 (v16sf)
+DEF_RET1_ARG6 (v32sf)
+DEF_RET1_ARG6 (v64sf)
+DEF_RET1_ARG6 (v128sf)
+DEF_RET1_ARG6 (v256sf)
+DEF_RET1_ARG6 (v512sf)
+DEF_RET1_ARG6 (v1024sf)
+
+DEF_RET1_ARG7 (v1sf)
+DEF_RET1_ARG7 (v2sf)
+DEF_RET1_ARG7 (v4sf)
+DEF_RET1_ARG7 (v8sf)
+DEF_RET1_ARG7 (v16sf)
+DEF_RET1_ARG7 (v32sf)
+DEF_RET1_ARG7 (v64sf)
+DEF_RET1_ARG7 (v128sf)
+DEF_RET1_ARG7 (v256sf)
+DEF_RET1_ARG7 (v512sf)
+DEF_RET1_ARG7 (v1024sf)
+
+DEF_RET1_ARG8 (v1sf)
+DEF_RET1_ARG8 (v2sf)
+DEF_RET1_ARG8 (v4sf)
+DEF_RET1_ARG8 (v8sf)
+DEF_RET1_ARG8 (v16sf)
+DEF_RET1_ARG8 (v32sf)
+DEF_RET1_ARG8 (v64sf)
+DEF_RET1_ARG8 (v128sf)
+DEF_RET1_ARG8 (v256sf)
+DEF_RET1_ARG8 (v512sf)
+DEF_RET1_ARG8 (v1024sf)
+
+DEF_RET1_ARG9 (v1sf)
+DEF_RET1_ARG9 (v2sf)
+DEF_RET1_ARG9 (v4sf)
+DEF_RET1_ARG9 (v8sf)
+DEF_RET1_ARG9 (v16sf)
+DEF_RET1_ARG9 (v32sf)
+DEF_RET1_ARG9 (v64sf)
+DEF_RET1_ARG9 (v128sf)
+DEF_RET1_ARG9 (v256sf)
+DEF_RET1_ARG9 (v512sf)
+DEF_RET1_ARG9 (v1024sf)
+
+/* { dg-final { scan-assembler-times {li\s+a[0-1],\s*0} 7 } } */
+/* { dg-final { scan-assembler-times {lw\s+a[0-1],\s*[0-9]+\(sp\)} 8 } } */
+/* { dg-final { scan-assembler-times {sw\s+a[0-7],\s*[0-9]+\(sp\)} 43 } } */
+/* { dg-final { scan-assembler-times {sd\s+a[0-7],\s*[0-9]+\(sp\)} 103 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-7.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-7.c
new file mode 100644
index 00000000000..e35ccd52e51
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-7.c
@@ -0,0 +1,118 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv_zvl4096b --param riscv-autovec-preference=scalable -mabi=lp64d -O3" } */
+
+#include "def.h"
+
+DEF_RET1_ARG0 (v1df)
+DEF_RET1_ARG0 (v2df)
+DEF_RET1_ARG0 (v4df)
+DEF_RET1_ARG0 (v8df)
+DEF_RET1_ARG0 (v16df)
+DEF_RET1_ARG0 (v32df)
+DEF_RET1_ARG0 (v64df)
+DEF_RET1_ARG0 (v128df)
+DEF_RET1_ARG0 (v256df)
+DEF_RET1_ARG0 (v512df)
+
+DEF_RET1_ARG1 (v1df)
+DEF_RET1_ARG1 (v2df)
+DEF_RET1_ARG1 (v4df)
+DEF_RET1_ARG1 (v8df)
+DEF_RET1_ARG1 (v16df)
+DEF_RET1_ARG1 (v32df)
+DEF_RET1_ARG1 (v64df)
+DEF_RET1_ARG1 (v128df)
+DEF_RET1_ARG1 (v256df)
+DEF_RET1_ARG1 (v512df)
+
+DEF_RET1_ARG2 (v1df)
+DEF_RET1_ARG2 (v2df)
+DEF_RET1_ARG2 (v4df)
+DEF_RET1_ARG2 (v8df)
+DEF_RET1_ARG2 (v16df)
+DEF_RET1_ARG2 (v32df)
+DEF_RET1_ARG2 (v64df)
+DEF_RET1_ARG2 (v128df)
+DEF_RET1_ARG2 (v256df)
+DEF_RET1_ARG2 (v512df)
+
+DEF_RET1_ARG3 (v1df)
+DEF_RET1_ARG3 (v2df)
+DEF_RET1_ARG3 (v4df)
+DEF_RET1_ARG3 (v8df)
+DEF_RET1_ARG3 (v16df)
+DEF_RET1_ARG3 (v32df)
+DEF_RET1_ARG3 (v64df)
+DEF_RET1_ARG3 (v128df)
+DEF_RET1_ARG3 (v256df)
+DEF_RET1_ARG3 (v512df)
+
+DEF_RET1_ARG4 (v1df)
+DEF_RET1_ARG4 (v2df)
+DEF_RET1_ARG4 (v4df)
+DEF_RET1_ARG4 (v8df)
+DEF_RET1_ARG4 (v16df)
+DEF_RET1_ARG4 (v32df)
+DEF_RET1_ARG4 (v64df)
+DEF_RET1_ARG4 (v128df)
+DEF_RET1_ARG4 (v256df)
+DEF_RET1_ARG4 (v512df)
+
+DEF_RET1_ARG5 (v1df)
+DEF_RET1_ARG5 (v2df)
+DEF_RET1_ARG5 (v4df)
+DEF_RET1_ARG5 (v8df)
+DEF_RET1_ARG5 (v16df)
+DEF_RET1_ARG5 (v32df)
+DEF_RET1_ARG5 (v64df)
+DEF_RET1_ARG5 (v128df)
+DEF_RET1_ARG5 (v256df)
+DEF_RET1_ARG5 (v512df)
+
+DEF_RET1_ARG6 (v1df)
+DEF_RET1_ARG6 (v2df)
+DEF_RET1_ARG6 (v4df)
+DEF_RET1_ARG6 (v8df)
+DEF_RET1_ARG6 (v16df)
+DEF_RET1_ARG6 (v32df)
+DEF_RET1_ARG6 (v64df)
+DEF_RET1_ARG6 (v128df)
+DEF_RET1_ARG6 (v256df)
+DEF_RET1_ARG6 (v512df)
+
+DEF_RET1_ARG7 (v1df)
+DEF_RET1_ARG7 (v2df)
+DEF_RET1_ARG7 (v4df)
+DEF_RET1_ARG7 (v8df)
+DEF_RET1_ARG7 (v16df)
+DEF_RET1_ARG7 (v32df)
+DEF_RET1_ARG7 (v64df)
+DEF_RET1_ARG7 (v128df)
+DEF_RET1_ARG7 (v256df)
+DEF_RET1_ARG7 (v512df)
+
+DEF_RET1_ARG8 (v1df)
+DEF_RET1_ARG8 (v2df)
+DEF_RET1_ARG8 (v4df)
+DEF_RET1_ARG8 (v8df)
+DEF_RET1_ARG8 (v16df)
+DEF_RET1_ARG8 (v32df)
+DEF_RET1_ARG8 (v64df)
+DEF_RET1_ARG8 (v128df)
+DEF_RET1_ARG8 (v256df)
+DEF_RET1_ARG8 (v512df)
+
+DEF_RET1_ARG9 (v1df)
+DEF_RET1_ARG9 (v2df)
+DEF_RET1_ARG9 (v4df)
+DEF_RET1_ARG9 (v8df)
+DEF_RET1_ARG9 (v16df)
+DEF_RET1_ARG9 (v32df)
+DEF_RET1_ARG9 (v64df)
+DEF_RET1_ARG9 (v128df)
+DEF_RET1_ARG9 (v256df)
+DEF_RET1_ARG9 (v512df)
+
+/* { dg-final { scan-assembler-times {li\s+a[0-1],\s*0} 6 } } */
+/* { dg-final { scan-assembler-times {ld\s+a[0-1],\s*[0-9]+\(sp\)} 29 } } */
+/* { dg-final { scan-assembler-times {sd\s+a[0-7],\s*[0-9]+\(sp\)} 103 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-8.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-8.c
new file mode 100644
index 00000000000..ed66a2cb9eb
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-8.c
@@ -0,0 +1,43 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv_zvl4096b -mabi=lp64d --param riscv-autovec-preference=scalable -O3 -fno-schedule-insns -fno-schedule-insns2" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include "def.h"
+
+/*
+** v8qi_RET1_ARG0:
+** li\s+a0,\s*0
+** ret
+*/
+DEF_RET1_ARG0 (v8qi)
+
+/*
+** v4hi_RET1_ARG1:
+** ret
+*/
+DEF_RET1_ARG1 (v4hi)
+
+/*
+** v2si_RET1_ARG2:
+** addi\s+sp,\s*sp,\s*-16
+** sd\s+a0,\s*0\(sp\)
+** sd\s+a1,\s*8\(sp\)
+** ...
+** ld\s+a0,\s*0\(sp\)
+** addi\s+sp,\s*sp,\s*16
+** jr\s+ra
+*/
+DEF_RET1_ARG2 (v2si)
+
+/*
+** v1di_RET1_ARG3:
+** addi\s+sp,\s*sp,\s*-32
+** sd\s+a0,\s*8\(sp\)
+** sd\s+a1,\s*16\(sp\)
+** sd\s+a2,\s*24\(sp\)
+** ...
+** ld\s+a0,\s*8\(sp\)
+** addi\s+sp,\s*sp,\s*32
+** jr\s+ra
+*/
+DEF_RET1_ARG3 (v1di)
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-9.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-9.c
new file mode 100644
index 00000000000..ab8e79c3cb8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-9.c
@@ -0,0 +1,51 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv_zvfh_zvl4096b -mabi=lp64d --param riscv-autovec-preference=scalable -O3 -fno-schedule-insns -fno-schedule-insns2" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include "def.h"
+
+/*
+** v4hf_RET1_ARG1:
+** ret
+*/
+DEF_RET1_ARG1 (v4hf)
+
+/*
+** v2sf_RET1_ARG2:
+** addi\s+sp,\s*sp,\s*-16
+** sd\s+a0,\s*0\(sp\)
+** sd\s+a1,\s*8\(sp\)
+** ...
+** ld\s+a0,\s*0\(sp\)
+** addi\s+sp,\s*sp,\s*16
+** jr\s+ra
+*/
+DEF_RET1_ARG2 (v2sf)
+
+/*
+** v4sf_RET1_ARG2:
+** addi\s+sp,\s*sp,\s*-32
+** sd\s+a0,\s*0\(sp\)
+** sd\s+a1,\s*8\(sp\)
+** sd\s+a2,\s*16\(sp\)
+** sd\s+a3,\s*24\(sp\)
+** ...
+** ld\s+a0,\s*0\(sp\)
+** ld\s+a1,\s*8\(sp\)
+** addi\s+sp,\s*sp,\s*32
+** jr\s+ra
+*/
+DEF_RET1_ARG2 (v4sf)
+
+/*
+** v1df_RET1_ARG3:
+** addi\s+sp,\s*sp,\s*-32
+** sd\s+a0,\s*8\(sp\)
+** sd\s+a1,\s*16\(sp\)
+** sd\s+a2,\s*24\(sp\)
+** ...
+** ld\s+a0,\s*8\(sp\)
+** addi\s+sp,\s*sp,\s*32
+** jr\s+ra
+*/
+DEF_RET1_ARG3 (v1df)
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-run-1.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-run-1.c
new file mode 100644
index 00000000000..d8aa5c51cac
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-run-1.c
@@ -0,0 +1,55 @@
+/* { dg-do run { target { riscv_v } } } */
+/* { dg-additional-options "-std=c99 -fno-vect-cost-model --param=riscv-autovec-preference=scalable" } */
+
+typedef char v16qi __attribute__ ((vector_size (16)));
+
+v16qi
+add (v16qi a1, v16qi a2, v16qi a3, v16qi a4, v16qi a5, v16qi a6, v16qi a7,
+     v16qi a8, v16qi a9)
+{
+  return a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8 + a9;
+}
+
+int
+main ()
+{
+  v16qi a1 = {
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  };
+  v16qi a2 = {
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  };
+  v16qi a3 = {
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  };
+  v16qi a4 = {
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  };
+  v16qi a5 = {
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  };
+  v16qi a6 = {
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  };
+  v16qi a7 = {
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  };
+  v16qi a8 = {
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  };
+  v16qi a9 = {
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  };
+  v16qi expected = {
+    9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+  };
+  v16qi result = add (a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+  unsigned i;
+
+  for (i = 0; i < 16; i++)
+    if (result[i] != expected[i])
+      __builtin_abort ();
+
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-run-2.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-run-2.c
new file mode 100644
index 00000000000..57376a3924c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-run-2.c
@@ -0,0 +1,55 @@
+/* { dg-do run { target { riscv_v } } } */
+/* { dg-additional-options "-std=c99 -fno-vect-cost-model --param=riscv-autovec-preference=scalable" } */
+
+typedef short v8hi __attribute__ ((vector_size (16)));
+
+v8hi
+add (v8hi a1, v8hi a2, v8hi a3, v8hi a4, v8hi a5, v8hi a6, v8hi a7,
+     v8hi a8, v8hi a9)
+{
+  return a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8 + a9;
+}
+
+int
+main ()
+{
+  v8hi a1 = {
+    1, 1, 1, 1, 1, 1, 1, 1,
+  };
+  v8hi a2 = {
+    1, 1, 1, 1, 1, 1, 1, 1,
+  };
+  v8hi a3 = {
+    1, 1, 1, 1, 1, 1, 1, 1,
+  };
+  v8hi a4 = {
+    1, 1, 1, 1, 1, 1, 1, 1,
+  };
+  v8hi a5 = {
+    1, 1, 1, 1, 1, 1, 1, 1,
+  };
+  v8hi a6 = {
+    1, 1, 1, 1, 1, 1, 1, 1,
+  };
+  v8hi a7 = {
+    1, 1, 1, 1, 1, 1, 1, 1,
+  };
+  v8hi a8 = {
+    1, 1, 1, 1, 1, 1, 1, 1,
+  };
+  v8hi a9 = {
+    1, 1, 1, 1, 1, 1, 1, 1,
+  };
+  v8hi expected = {
+    9, 9, 9, 9, 9, 9, 9, 9,
+  };
+  v8hi result = add (a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+  unsigned i;
+
+  for (i = 0; i < 8; i++)
+    if (result[i] != expected[i])
+      __builtin_abort ();
+
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-run-3.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-run-3.c
new file mode 100644
index 00000000000..b37cd5669d4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-run-3.c
@@ -0,0 +1,55 @@
+/* { dg-do run { target { riscv_v } } } */
+/* { dg-additional-options "-std=c99 -fno-vect-cost-model --param=riscv-autovec-preference=scalable" } */
+
+typedef int v4si __attribute__ ((vector_size (16)));
+
+v4si
+add (v4si a1, v4si a2, v4si a3, v4si a4, v4si a5, v4si a6, v4si a7,
+     v4si a8, v4si a9)
+{
+  return a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8 + a9;
+}
+
+int
+main ()
+{
+  v4si a1 = {
+    1, 1, 1, 1,
+  };
+  v4si a2 = {
+    1, 1, 1, 1,
+  };
+  v4si a3 = {
+    1, 1, 1, 1,
+  };
+  v4si a4 = {
+    1, 1, 1, 1,
+  };
+  v4si a5 = {
+    1, 1, 1, 1,
+  };
+  v4si a6 = {
+    1, 1, 1, 1,
+  };
+  v4si a7 = {
+    1, 1, 1, 1,
+  };
+  v4si a8 = {
+    1, 1, 1, 1,
+  };
+  v4si a9 = {
+    1, 1, 1, 1,
+  };
+  v4si expected = {
+    9, 9, 9, 9,
+  };
+  v4si result = add (a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+  unsigned i;
+
+  for (i = 0; i < 4; i++)
+    if (result[i] != expected[i])
+      __builtin_abort ();
+
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-run-4.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-run-4.c
new file mode 100644
index 00000000000..0788447b501
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-run-4.c
@@ -0,0 +1,55 @@
+/* { dg-do run { target { riscv_v } } } */
+/* { dg-additional-options "-std=c99 -fno-vect-cost-model --param=riscv-autovec-preference=scalable" } */
+
+typedef long long v2di __attribute__ ((vector_size (16)));
+
+v2di
+add (v2di a1, v2di a2, v2di a3, v2di a4, v2di a5, v2di a6, v2di a7,
+     v2di a8, v2di a9)
+{
+  return a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8 + a9;
+}
+
+int
+main ()
+{
+  v2di a1 = {
+    1, 1,
+  };
+  v2di a2 = {
+    1, 1,
+  };
+  v2di a3 = {
+    1, 1,
+  };
+  v2di a4 = {
+    1, 1,
+  };
+  v2di a5 = {
+    1, 1,
+  };
+  v2di a6 = {
+    1, 1,
+  };
+  v2di a7 = {
+    1, 1,
+  };
+  v2di a8 = {
+    1, 1,
+  };
+  v2di a9 = {
+    1, 1,
+  };
+  v2di expected = {
+    9, 9,
+  };
+  v2di result = add (a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+  unsigned i;
+
+  for (i = 0; i < 2; i++)
+    if (result[i] != expected[i])
+      __builtin_abort ();
+
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-run-5.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-run-5.c
new file mode 100644
index 00000000000..ec8658d6a02
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-run-5.c
@@ -0,0 +1,55 @@
+/* { dg-do run { target { riscv_v } } } */
+/* { dg-additional-options "-std=c99 -fno-vect-cost-model --param=riscv-autovec-preference=scalable" } */
+
+typedef float v4sf __attribute__ ((vector_size (16)));
+
+v4sf
+add (v4sf a1, v4sf a2, v4sf a3, v4sf a4, v4sf a5, v4sf a6, v4sf a7,
+     v4sf a8, v4sf a9)
+{
+  return a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8 + a9;
+}
+
+int
+main ()
+{
+  v4sf a1 = {
+    1.0, 1.0, 1.0, 1.0,
+  };
+  v4sf a2 = {
+    1.0, 1.0, 1.0, 1.0,
+  };
+  v4sf a3 = {
+    1.0, 1.0, 1.0, 1.0,
+  };
+  v4sf a4 = {
+    1.0, 1.0, 1.0, 1.0,
+  };
+  v4sf a5 = {
+    1.0, 1.0, 1.0, 1.0,
+  };
+  v4sf a6 = {
+    1.0, 1.0, 1.0, 1.0,
+  };
+  v4sf a7 = {
+    1.0, 1.0, 1.0, 1.0,
+  };
+  v4sf a8 = {
+    1.0, 1.0, 1.0, 1.0,
+  };
+  v4sf a9 = {
+    1.0, 1.0, 1.0, 1.0,
+  };
+  v4sf expected = {
+    9.0, 9.0, 9.0, 9.0,
+  };
+  v4sf result = add (a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+  unsigned i;
+
+  for (i = 0; i < 4; i++)
+    if (result[i] != expected[i])
+      __builtin_abort ();
+
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-run-6.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-run-6.c
new file mode 100644
index 00000000000..bbb53a1a4af
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-run-6.c
@@ -0,0 +1,55 @@
+/* { dg-do run { target { riscv_v } } } */
+/* { dg-additional-options "-std=c99 -fno-vect-cost-model --param=riscv-autovec-preference=scalable" } */
+
+typedef long long v2df __attribute__ ((vector_size (16)));
+
+v2df
+add (v2df a1, v2df a2, v2df a3, v2df a4, v2df a5, v2df a6, v2df a7,
+     v2df a8, v2df a9)
+{
+  return a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8 + a9;
+}
+
+int
+main ()
+{
+  v2df a1 = {
+    1.0, 1.0,
+  };
+  v2df a2 = {
+    1.0, 1.0,
+  };
+  v2df a3 = {
+    1.0, 1.0,
+  };
+  v2df a4 = {
+    1.0, 1.0,
+  };
+  v2df a5 = {
+    1.0, 1.0,
+  };
+  v2df a6 = {
+    1.0, 1.0,
+  };
+  v2df a7 = {
+    1.0, 1.0,
+  };
+  v2df a8 = {
+    1.0, 1.0,
+  };
+  v2df a9 = {
+    1.0, 1.0,
+  };
+  v2df expected = {
+    9.0, 9.0,
+  };
+  v2df result = add (a1, a2, a3, a4, a5, a6, a7, a8, a9);
+
+  unsigned i;
+
+  for (i = 0; i < 2; i++)
+    if (result[i] != expected[i])
+      __builtin_abort ();
+
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/def.h b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/def.h
index cb7a1c97ded..ef55c4d7ecf 100644
--- a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/def.h
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/def.h
@@ -860,3 +860,77 @@ typedef double v512df __attribute__ ((vector_size (4096)));
     TYPE1 v = {__VA_ARGS__};                                                   \
     *(TYPE1 *) out = v;                                                        \
   }
+
+#define DEF_RET1_ARG0(TYPE)                                                    \
+  TYPE __attribute__((noinline))                                               \
+  TYPE##_RET1_ARG0 ()                                                          \
+  {                                                                            \
+    TYPE r = {};                                                               \
+    return r;                                                                  \
+  }
+
+#define DEF_RET1_ARG1(TYPE)                                                    \
+  TYPE __attribute__((noinline))                                               \
+  TYPE##_RET1_ARG1 (TYPE a1)                                                   \
+  {                                                                            \
+    return a1;                                                                 \
+  }
+
+#define DEF_RET1_ARG2(TYPE)                                                    \
+  TYPE __attribute__((noinline))                                               \
+  TYPE##_RET1_ARG2 (TYPE a1, TYPE a2)                                          \
+  {                                                                            \
+    return a1 + a2;                                                            \
+  }
+
+#define DEF_RET1_ARG3(TYPE)                                                    \
+  TYPE __attribute__((noinline))                                               \
+  TYPE##_RET1_ARG3 (TYPE a1, TYPE a2, TYPE a3)                                 \
+  {                                                                            \
+    return a1 + a2 + a3;                                                       \
+  }
+
+#define DEF_RET1_ARG4(TYPE)                                                    \
+  TYPE __attribute__((noinline))                                               \
+  TYPE##_RET1_ARG4 (TYPE a1, TYPE a2, TYPE a3, TYPE a4)                        \
+  {                                                                            \
+    return a1 + a2 + a3 + a4;                                                  \
+  }
+
+#define DEF_RET1_ARG5(TYPE)                                                    \
+  TYPE __attribute__((noinline))                                               \
+  TYPE##_RET1_ARG5 (TYPE a1, TYPE a2, TYPE a3, TYPE a4, TYPE a5)               \
+  {                                                                            \
+    return a1 + a2 + a3 + a4 + a5;                                             \
+  }
+
+#define DEF_RET1_ARG6(TYPE)                                                    \
+  TYPE __attribute__((noinline))                                               \
+  TYPE##_RET1_ARG6 (TYPE a1, TYPE a2, TYPE a3, TYPE a4, TYPE a5, TYPE a6)      \
+  {                                                                            \
+    return a1 + a2 + a3 + a4 + a5 + a6;                                        \
+  }
+
+#define DEF_RET1_ARG7(TYPE)                                                    \
+  TYPE __attribute__((noinline))                                               \
+  TYPE##_RET1_ARG7 (TYPE a1, TYPE a2, TYPE a3, TYPE a4, TYPE a5, TYPE a6,      \
+		    TYPE a7)                                                   \
+  {                                                                            \
+    return a1 + a2 + a3 + a4 + a5 + a6 + a7;                                   \
+  }
+
+#define DEF_RET1_ARG8(TYPE)                                                    \
+  TYPE __attribute__((noinline))                                               \
+  TYPE##_RET1_ARG8 (TYPE a1, TYPE a2, TYPE a3, TYPE a4, TYPE a5, TYPE a6,      \
+		    TYPE a7, TYPE a8)                                          \
+  {                                                                            \
+    return a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8;                              \
+  }
+
+#define DEF_RET1_ARG9(TYPE)                                                    \
+  TYPE __attribute__((noinline))                                               \
+  TYPE##_RET1_ARG9 (TYPE a1, TYPE a2, TYPE a3, TYPE a4, TYPE a5, TYPE a6,      \
+		    TYPE a7, TYPE a8, TYPE a9)                                 \
+  {                                                                            \
+    return a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8 + a9;                         \
+  }
-- 
2.34.1


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

* RE: [PATCH v1] RISC-V: Bugfix for vls integer mode calling convention
  2024-01-29 13:22 ` Kito Cheng
@ 2024-01-30  8:39   ` Li, Pan2
  0 siblings, 0 replies; 10+ messages in thread
From: Li, Pan2 @ 2024-01-30  8:39 UTC (permalink / raw)
  To: Kito Cheng; +Cc: gcc-patches, juzhe.zhong, Wang, Yanzhang

Thanks Kito for comments, rebase the upstream and always goes to GPR in V2.

https://gcc.gnu.org/pipermail/gcc-patches/2024-January/644291.html

Pan

-----Original Message-----
From: Kito Cheng <kito.cheng@gmail.com> 
Sent: Monday, January 29, 2024 9:23 PM
To: Li, Pan2 <pan2.li@intel.com>
Cc: gcc-patches@gcc.gnu.org; juzhe.zhong@rivai.ai; Wang, Yanzhang <yanzhang.wang@intel.com>
Subject: Re: [PATCH v1] RISC-V: Bugfix for vls integer mode calling convention

> @@ -4868,6 +4968,63 @@ riscv_pass_fpr_pair (machine_mode mode, unsigned regno1,
>                                    GEN_INT (offset2))));
>  }
>
> +static rtx
> +riscv_pass_vls_aggregate_in_gpr_or_fpr (struct riscv_arg_info *info,
> +                                       machine_mode mode, unsigned gpr_base,
> +                                       unsigned fpr_base)

Tried a few more clang and GCC code gen and I found VLS vector is
always passed in
GPR, and never passed in FPR, so I think I should update psABI rather than fix
that on GCC side.

> @@ -4997,9 +5170,7 @@ riscv_get_arg_info (struct riscv_arg_info *info, const CUMULATIVE_ARGS *cum,
>    info->gpr_offset = cum->num_gprs;
>    info->fpr_offset = cum->num_fprs;
>
> -  /* When disable vector_abi or scalable vector argument is anonymous, this
> -     argument is passed by reference.  */
> -  if (riscv_v_ext_mode_p (mode) && (!riscv_vector_abi || !named))
> +  if (riscv_mode_pass_by_reference_p (mode, named))

Keep as it is fine since riscv_vector_abi is gone.

>      return NULL_RTX;
>
>    if (named)

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

* Re: [PATCH v2] RISC-V: Bugfix for vls mode aggregated in GPR calling convention
  2024-01-30  8:37 ` [PATCH v2] RISC-V: Bugfix for vls mode aggregated in GPR " pan2.li
@ 2024-01-30 12:54   ` Kito Cheng
  2024-01-30 13:10     ` Li, Pan2
  0 siblings, 1 reply; 10+ messages in thread
From: Kito Cheng @ 2024-01-30 12:54 UTC (permalink / raw)
  To: pan2.li; +Cc: gcc-patches, juzhe.zhong, yanzhang.wang

Thanks for fixing this bug! LGTM with one minor comment :)


> diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
> index 7b6111aa545..1de69019cd4 100644
> --- a/gcc/config/riscv/riscv.cc
> +++ b/gcc/config/riscv/riscv.cc
> @@ -1382,6 +1382,38 @@ riscv_v_ext_mode_p (machine_mode mode)
>          || riscv_v_ext_vls_mode_p (mode);
>  }
>
> +static unsigned
> +riscv_v_vls_mode_aggregate_gpr_count (unsigned vls_unit_size,
> +                                     unsigned scalar_unit_size)
> +{
> +  gcc_assert (vls_unit_size != 0 && scalar_unit_size != 0);
> +
> +  if (vls_unit_size < scalar_unit_size)
> +    return 1;
> +

Add gcc_assert ((vls_unit_size % scalar_unit_size) == 0); here to make
sure no accident :P

> +  return vls_unit_size / scalar_unit_size;
> +}
> +

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

* RE: [PATCH v2] RISC-V: Bugfix for vls mode aggregated in GPR calling convention
  2024-01-30 12:54   ` Kito Cheng
@ 2024-01-30 13:10     ` Li, Pan2
  2024-01-30 13:49       ` Li, Pan2
  0 siblings, 1 reply; 10+ messages in thread
From: Li, Pan2 @ 2024-01-30 13:10 UTC (permalink / raw)
  To: Kito Cheng; +Cc: gcc-patches, juzhe.zhong, Wang, Yanzhang

Thanks Kito, will add assertion here, and commit it if there is no surprise in riscv regression test.

Pan

-----Original Message-----
From: Kito Cheng <kito.cheng@gmail.com> 
Sent: Tuesday, January 30, 2024 8:54 PM
To: Li, Pan2 <pan2.li@intel.com>
Cc: gcc-patches@gcc.gnu.org; juzhe.zhong@rivai.ai; Wang, Yanzhang <yanzhang.wang@intel.com>
Subject: Re: [PATCH v2] RISC-V: Bugfix for vls mode aggregated in GPR calling convention

Thanks for fixing this bug! LGTM with one minor comment :)


> diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
> index 7b6111aa545..1de69019cd4 100644
> --- a/gcc/config/riscv/riscv.cc
> +++ b/gcc/config/riscv/riscv.cc
> @@ -1382,6 +1382,38 @@ riscv_v_ext_mode_p (machine_mode mode)
>          || riscv_v_ext_vls_mode_p (mode);
>  }
>
> +static unsigned
> +riscv_v_vls_mode_aggregate_gpr_count (unsigned vls_unit_size,
> +                                     unsigned scalar_unit_size)
> +{
> +  gcc_assert (vls_unit_size != 0 && scalar_unit_size != 0);
> +
> +  if (vls_unit_size < scalar_unit_size)
> +    return 1;
> +

Add gcc_assert ((vls_unit_size % scalar_unit_size) == 0); here to make
sure no accident :P

> +  return vls_unit_size / scalar_unit_size;
> +}
> +

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

* RE: [PATCH v2] RISC-V: Bugfix for vls mode aggregated in GPR calling convention
  2024-01-30 13:10     ` Li, Pan2
@ 2024-01-30 13:49       ` Li, Pan2
  0 siblings, 0 replies; 10+ messages in thread
From: Li, Pan2 @ 2024-01-30 13:49 UTC (permalink / raw)
  To: Kito Cheng; +Cc: gcc-patches, juzhe.zhong, Wang, Yanzhang

Thanks Kito. Committed with assertion, as well as pass the riscv regression test.

Pan

-----Original Message-----
From: Li, Pan2 
Sent: Tuesday, January 30, 2024 9:11 PM
To: Kito Cheng <kito.cheng@gmail.com>
Cc: gcc-patches@gcc.gnu.org; juzhe.zhong@rivai.ai; Wang, Yanzhang <yanzhang.wang@intel.com>
Subject: RE: [PATCH v2] RISC-V: Bugfix for vls mode aggregated in GPR calling convention

Thanks Kito, will add assertion here, and commit it if there is no surprise in riscv regression test.

Pan

-----Original Message-----
From: Kito Cheng <kito.cheng@gmail.com> 
Sent: Tuesday, January 30, 2024 8:54 PM
To: Li, Pan2 <pan2.li@intel.com>
Cc: gcc-patches@gcc.gnu.org; juzhe.zhong@rivai.ai; Wang, Yanzhang <yanzhang.wang@intel.com>
Subject: Re: [PATCH v2] RISC-V: Bugfix for vls mode aggregated in GPR calling convention

Thanks for fixing this bug! LGTM with one minor comment :)


> diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
> index 7b6111aa545..1de69019cd4 100644
> --- a/gcc/config/riscv/riscv.cc
> +++ b/gcc/config/riscv/riscv.cc
> @@ -1382,6 +1382,38 @@ riscv_v_ext_mode_p (machine_mode mode)
>          || riscv_v_ext_vls_mode_p (mode);
>  }
>
> +static unsigned
> +riscv_v_vls_mode_aggregate_gpr_count (unsigned vls_unit_size,
> +                                     unsigned scalar_unit_size)
> +{
> +  gcc_assert (vls_unit_size != 0 && scalar_unit_size != 0);
> +
> +  if (vls_unit_size < scalar_unit_size)
> +    return 1;
> +

Add gcc_assert ((vls_unit_size % scalar_unit_size) == 0); here to make
sure no accident :P

> +  return vls_unit_size / scalar_unit_size;
> +}
> +

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

end of thread, other threads:[~2024-01-30 13:49 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-01-24  3:16 [PATCH v1] RISC-V: Bugfix for vls integer mode calling convention pan2.li
2024-01-24  3:18 ` juzhe.zhong
2024-01-24  3:41   ` Li, Pan2
2024-01-24  3:43     ` juzhe.zhong
2024-01-29 13:22 ` Kito Cheng
2024-01-30  8:39   ` Li, Pan2
2024-01-30  8:37 ` [PATCH v2] RISC-V: Bugfix for vls mode aggregated in GPR " pan2.li
2024-01-30 12:54   ` Kito Cheng
2024-01-30 13:10     ` Li, Pan2
2024-01-30 13:49       ` Li, Pan2

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