@@ -447,12 +447,18 @@ riscv_remove_unneeded_save_restore_calls (void)
&& !SIBCALL_REG_P (REGNO (target)))
return;
+ /* Extract RISCV CC from the UNSPEC rtx. */
+ rtx unspec = XVECEXP (callpat, 0, 1);
+ gcc_assert (GET_CODE (unspec) == UNSPEC
+ && XINT (unspec, 1) == UNSPEC_CALLEE_CC);
+ riscv_cc cc = (riscv_cc) INTVAL (XVECEXP (unspec, 0, 0));
rtx sibcall = NULL;
if (set_target != NULL)
- sibcall
- = gen_sibcall_value_internal (set_target, target, const0_rtx);
+ sibcall = gen_sibcall_value_internal (set_target, target, const0_rtx,
+ gen_int_mode (cc, SImode));
else
- sibcall = gen_sibcall_internal (target, const0_rtx);
+ sibcall
+ = gen_sibcall_internal (target, const0_rtx, gen_int_mode (cc, SImode));
rtx_insn *before_call = PREV_INSN (call);
remove_insn (call);
@@ -108,6 +108,9 @@ struct GTY(()) riscv_frame_info {
/* Likewise FPR X. */
unsigned int fmask;
+ /* Likewise for vector registers. */
+ unsigned int vmask;
+
/* How much the GPR save/restore routines adjust sp (or 0 if unused). */
unsigned save_libcall_adjustment;
@@ -115,6 +118,10 @@ struct GTY(()) riscv_frame_info {
poly_int64 gp_sp_offset;
poly_int64 fp_sp_offset;
+ /* Top and bottom offsets of vector save areas from frame bottom. */
+ poly_int64 v_sp_offset_top;
+ poly_int64 v_sp_offset_bottom;
+
/* Offset of virtual frame pointer from stack pointer/frame bottom */
poly_int64 frame_pointer_offset;
@@ -265,7 +272,7 @@ unsigned riscv_stack_boundary;
/* If non-zero, this is an offset to be added to SP to redefine the CFA
when restoring the FP register from the stack. Only valid when generating
the epilogue. */
-static int epilogue_cfa_sp_offset;
+static poly_int64 epilogue_cfa_sp_offset;
/* Which tuning parameters to use. */
static const struct riscv_tune_param *tune_param;
@@ -425,10 +432,13 @@ void riscv_frame_info::reset(void)
total_size = 0;
mask = 0;
fmask = 0;
+ vmask = 0;
save_libcall_adjustment = 0;
gp_sp_offset = 0;
fp_sp_offset = 0;
+ v_sp_offset_top = 0;
+ v_sp_offset_bottom = 0;
frame_pointer_offset = 0;
@@ -1727,7 +1737,8 @@ riscv_call_tls_get_addr (rtx sym, rtx result)
start_sequence ();
emit_insn (riscv_got_load_tls_gd (a0, sym));
- insn = emit_call_insn (gen_call_value (result, func, const0_rtx, NULL));
+ insn = emit_call_insn (gen_call_value (result, func, const0_rtx,
+ gen_int_mode (RISCV_CC_BASE, SImode)));
RTL_CONST_CALL_P (insn) = 1;
use_reg (&CALL_INSN_FUNCTION_USAGE (insn), a0);
insn = get_insns ();
@@ -4385,7 +4396,8 @@ riscv_function_arg (cumulative_args_t cum_v, const function_arg_info &arg)
struct riscv_arg_info info;
if (arg.end_marker_p ())
- return NULL;
+ /* Return the calling convention that used by the current function. */
+ return gen_int_mode (cum->variant_cc, SImode);
return riscv_get_arg_info (&info, cum, arg.mode, arg.type, arg.named, false);
}
@@ -4625,6 +4637,21 @@ riscv_fntype_abi (const_tree fntype)
return default_function_abi;
}
+/* Implement TARGET_INSN_CALLEE_ABI. */
+
+const predefined_function_abi &
+riscv_insn_callee_abi (const rtx_insn *insn)
+{
+ rtx pat = PATTERN (insn);
+ gcc_assert (GET_CODE (pat) == PARALLEL);
+ rtx unspec = XVECEXP (pat, 0, 1);
+ gcc_assert (GET_CODE (unspec) == UNSPEC
+ && XINT (unspec, 1) == UNSPEC_CALLEE_CC);
+ riscv_cc cc = (riscv_cc) INTVAL (XVECEXP (unspec, 0, 0));
+ gcc_assert (cc < RISCV_CC_UNKNOWN);
+ return function_abis[cc];
+}
+
/* Handle an attribute requiring a FUNCTION_DECL;
arguments as in struct attribute_spec.handler. */
static tree
@@ -5446,6 +5473,11 @@ riscv_save_reg_p (unsigned int regno)
if (call_saved && might_clobber)
return true;
+ /* Save callee-saved V registers. */
+ if (V_REG_P (regno) && !crtl->abi->clobbers_full_reg_p (regno)
+ && might_clobber)
+ return true;
+
if (regno == HARD_FRAME_POINTER_REGNUM && frame_pointer_needed)
return true;
@@ -5546,6 +5578,12 @@ riscv_save_libcall_count (unsigned mask)
| | + UNITS_PER_HWVALUE
| FPR save area |
| |
+ +-------------------------------+ <-- stack_pointer_rtx
+ | | + v_sp_offset_top
+ | Vector Registers save area |
+ | |
+ | ----------------------------- | <-- stack_pointer_rtx
+ | area padding | + v_sp_offset_bottom
+-------------------------------+ <-- frame_pointer_rtx (virtual)
| |
| local variables |
@@ -5582,6 +5620,7 @@ riscv_compute_frame_info (void)
poly_int64 offset;
bool interrupt_save_prologue_temp = false;
unsigned int regno, i, num_x_saved = 0, num_f_saved = 0, x_save_size = 0;
+ unsigned int num_v_saved = 0;
frame = &cfun->machine->frame;
@@ -5620,6 +5659,15 @@ riscv_compute_frame_info (void)
for (regno = FP_REG_FIRST; regno <= FP_REG_LAST; regno++)
if (riscv_save_reg_p (regno))
frame->fmask |= 1 << (regno - FP_REG_FIRST), num_f_saved++;
+
+ /* Find out which V registers we need to save. */
+ if (TARGET_VECTOR)
+ for (regno = V_REG_FIRST; regno <= V_REG_LAST; regno++)
+ if (riscv_save_reg_p (regno))
+ {
+ frame->vmask |= 1 << (regno - V_REG_FIRST);
+ num_v_saved++;
+ }
}
if (frame->mask)
@@ -5657,6 +5705,12 @@ riscv_compute_frame_info (void)
offset += riscv_stack_align (get_frame_size ());
/* The virtual frame pointer points above the local variables. */
frame->frame_pointer_offset = offset;
+ /* Next are the callee-saved VRs. */
+ if (frame->vmask)
+ offset += riscv_stack_align (num_v_saved * UNITS_PER_V_REG);
+ frame->v_sp_offset_top = offset;
+ frame->v_sp_offset_bottom
+ = frame->v_sp_offset_top - num_v_saved * UNITS_PER_V_REG;
/* Next are the callee-saved FPRs. */
if (frame->fmask)
offset += riscv_stack_align (num_f_saved * UNITS_PER_FP_REG);
@@ -5761,10 +5815,12 @@ riscv_restore_reg (rtx reg, rtx mem)
rtx dwarf = NULL_RTX;
dwarf = alloc_reg_note (REG_CFA_RESTORE, reg, dwarf);
- if (epilogue_cfa_sp_offset && REGNO (reg) == HARD_FRAME_POINTER_REGNUM)
+ if (known_gt (epilogue_cfa_sp_offset, 0)
+ && REGNO (reg) == HARD_FRAME_POINTER_REGNUM)
{
- rtx cfa_adjust_rtx = gen_rtx_PLUS (Pmode, stack_pointer_rtx,
- GEN_INT (epilogue_cfa_sp_offset));
+ rtx cfa_adjust_rtx
+ = gen_rtx_PLUS (Pmode, stack_pointer_rtx,
+ gen_int_mode (epilogue_cfa_sp_offset, Pmode));
dwarf = alloc_reg_note (REG_CFA_DEF_CFA, cfa_adjust_rtx, dwarf);
}
@@ -5942,6 +5998,79 @@ riscv_for_each_saved_reg (poly_int64 sp_offset, riscv_save_restore_fn fn,
}
}
+/* Call FN for each V register that is saved by the current function. */
+
+static void
+riscv_for_each_saved_v_reg (poly_int64 &remaining_size,
+ riscv_save_restore_fn fn, bool prologue)
+{
+ rtx vlen = NULL_RTX;
+ if (cfun->machine->frame.vmask != 0)
+ {
+ if (UNITS_PER_V_REG.is_constant ()
+ && SMALL_OPERAND (UNITS_PER_V_REG.to_constant ()))
+ vlen = GEN_INT (UNITS_PER_V_REG.to_constant ());
+ else
+ {
+ vlen = RISCV_PROLOGUE_TEMP (Pmode);
+ rtx insn
+ = emit_move_insn (vlen, gen_int_mode (UNITS_PER_V_REG, Pmode));
+ RTX_FRAME_RELATED_P (insn) = 1;
+ }
+ }
+
+ /* Select the mode where LMUL is 1 and SEW is largest. */
+ machine_mode m1_mode = TARGET_VECTOR_ELEN_64 ? RVVM1DImode : RVVM1SImode;
+
+ if (prologue)
+ {
+ /* This loop must iterate over the same space as its companion in
+ riscv_compute_frame_info. */
+ for (unsigned int regno = V_REG_FIRST; regno <= V_REG_LAST; regno++)
+ if (BITSET_P (cfun->machine->frame.vmask, regno - V_REG_FIRST))
+ {
+ bool handle_reg = !cfun->machine->reg_is_wrapped_separately[regno];
+ if (handle_reg)
+ {
+ rtx insn = NULL_RTX;
+ if (CONST_INT_P (vlen))
+ {
+ gcc_assert (SMALL_OPERAND (-INTVAL (vlen)));
+ insn = emit_insn (gen_add3_insn (stack_pointer_rtx,
+ stack_pointer_rtx,
+ GEN_INT (-INTVAL (vlen))));
+ }
+ else
+ insn = emit_insn (
+ gen_sub3_insn (stack_pointer_rtx, stack_pointer_rtx, vlen));
+ gcc_assert (insn != NULL_RTX);
+ RTX_FRAME_RELATED_P (insn) = 1;
+ riscv_save_restore_reg (m1_mode, regno, 0, fn);
+ remaining_size -= UNITS_PER_V_REG;
+ }
+ }
+ }
+ else
+ {
+ /* This loop must iterate over the same space as its companion in
+ riscv_compute_frame_info. */
+ for (unsigned int regno = V_REG_LAST; regno >= V_REG_FIRST; regno--)
+ if (BITSET_P (cfun->machine->frame.vmask, regno - V_REG_FIRST))
+ {
+ bool handle_reg = !cfun->machine->reg_is_wrapped_separately[regno];
+ if (handle_reg)
+ {
+ riscv_save_restore_reg (m1_mode, regno, 0, fn);
+ rtx insn = emit_insn (
+ gen_add3_insn (stack_pointer_rtx, stack_pointer_rtx, vlen));
+ gcc_assert (insn != NULL_RTX);
+ RTX_FRAME_RELATED_P (insn) = 1;
+ remaining_size -= UNITS_PER_V_REG;
+ }
+ }
+ }
+}
+
/* For stack frames that can't be allocated with a single ADDI instruction,
compute the best value to initially allocate. It must at a minimum
allocate enough space to spill the callee-saved registers. If TARGET_RVC,
@@ -5959,6 +6088,11 @@ riscv_first_stack_step (struct riscv_frame_info *frame, poly_int64 remaining_siz
else
remaining_const_size = remaining_size.to_constant ();
+ /* First step must be set to the top of vector registers save area if any
+ vector registers need be preversed. */
+ if (frame->vmask != 0)
+ return (remaining_size - frame->v_sp_offset_top).to_constant ();
+
if (SMALL_OPERAND (remaining_const_size))
return remaining_const_size;
@@ -6074,31 +6208,47 @@ riscv_expand_prologue (void)
REG_NOTES (insn) = dwarf;
}
- /* Save the registers. */
- if ((frame->mask | frame->fmask) != 0)
+ /* Save the GP, FP, and V registers. */
+ if ((frame->mask | frame->fmask | frame->vmask) != 0)
{
HOST_WIDE_INT step1 = riscv_first_stack_step (frame, remaining_size);
-
- insn = gen_add3_insn (stack_pointer_rtx,
- stack_pointer_rtx,
- GEN_INT (-step1));
- RTX_FRAME_RELATED_P (emit_insn (insn)) = 1;
- remaining_size -= step1;
+ if (step1 != 0)
+ {
+ insn = gen_add3_insn (stack_pointer_rtx, stack_pointer_rtx,
+ GEN_INT (-step1));
+ RTX_FRAME_RELATED_P (emit_insn (insn)) = 1;
+ remaining_size -= step1;
+ }
riscv_for_each_saved_reg (remaining_size, riscv_save_reg, false, false);
- }
- frame->mask = mask; /* Undo the above fib. */
+ /* Set up the frame pointer, if we're using one. */
+ if (frame_pointer_needed)
+ {
+ insn = gen_add3_insn (hard_frame_pointer_rtx, stack_pointer_rtx,
+ GEN_INT ((frame->hard_frame_pointer_offset
+ - remaining_size)
+ .to_constant ()));
+ RTX_FRAME_RELATED_P (emit_insn (insn)) = 1;
+
+ riscv_emit_stack_tie ();
+ }
+ riscv_for_each_saved_v_reg (remaining_size, riscv_save_reg, true);
+ }
/* Set up the frame pointer, if we're using one. */
- if (frame_pointer_needed)
+ else if (frame_pointer_needed)
{
- insn = gen_add3_insn (hard_frame_pointer_rtx, stack_pointer_rtx,
- GEN_INT ((frame->hard_frame_pointer_offset - remaining_size).to_constant ()));
+ insn = gen_add3_insn (
+ hard_frame_pointer_rtx, stack_pointer_rtx,
+ GEN_INT (
+ (frame->hard_frame_pointer_offset - remaining_size).to_constant ()));
RTX_FRAME_RELATED_P (emit_insn (insn)) = 1;
riscv_emit_stack_tie ();
}
+ frame->mask = mask; /* Undo the above fib. */
+
/* Allocate the rest of the frame. */
if (known_gt (remaining_size, 0))
{
@@ -6178,7 +6328,7 @@ riscv_expand_epilogue (int style)
Start off by assuming that no registers need to be restored. */
struct riscv_frame_info *frame = &cfun->machine->frame;
unsigned mask = frame->mask;
- HOST_WIDE_INT step2 = 0;
+ poly_int64 step2 = 0;
bool use_restore_libcall = ((style == NORMAL_RETURN)
&& riscv_use_save_libcall (frame));
unsigned libcall_size = (use_restore_libcall
@@ -6258,13 +6408,22 @@ riscv_expand_epilogue (int style)
/* If we need to restore registers, deallocate as much stack as
possible in the second step without going out of range. */
- if ((frame->mask | frame->fmask) != 0)
+ if ((frame->mask | frame->fmask | frame->vmask) != 0)
step2 = riscv_first_stack_step (frame, frame->total_size - libcall_size);
if (use_restore_libcall)
frame->mask = mask; /* Undo the above fib. */
- poly_int64 step1 = frame->total_size - step2 - libcall_size;
+ poly_int64 step1;
+ /* STEP1 must be set to the bottom of vector registers save area if any
+ vector registers need be preversed. */
+ if (frame->vmask != 0)
+ {
+ step1 = frame->v_sp_offset_bottom;
+ step2 = frame->total_size - step1 - libcall_size;
+ }
+ else
+ step1 = frame->total_size - step2 - libcall_size;
/* Set TARGET to BASE + STEP1. */
if (known_gt (step1, 0))
@@ -6298,8 +6457,9 @@ riscv_expand_epilogue (int style)
stack_pointer_rtx,
adjust));
rtx dwarf = NULL_RTX;
- rtx cfa_adjust_rtx = gen_rtx_PLUS (Pmode, stack_pointer_rtx,
- GEN_INT (step2 + libcall_size));
+ rtx cfa_adjust_rtx
+ = gen_rtx_PLUS (Pmode, stack_pointer_rtx,
+ gen_int_mode (step2 + libcall_size, Pmode));
dwarf = alloc_reg_note (REG_CFA_DEF_CFA, cfa_adjust_rtx, dwarf);
RTX_FRAME_RELATED_P (insn) = 1;
@@ -6318,9 +6478,9 @@ riscv_expand_epilogue (int style)
frame->mask = 0; /* Temporarily fib that we need not save GPRs. */
/* Restore the registers. */
+ riscv_for_each_saved_v_reg (step2, riscv_restore_reg, false);
riscv_for_each_saved_reg (frame->total_size - step2 - libcall_size,
- riscv_restore_reg,
- true, style == EXCEPTION_RETURN);
+ riscv_restore_reg, true, style == EXCEPTION_RETURN);
if (use_restore_libcall)
frame->mask = mask; /* Undo the above fib. */
@@ -6329,10 +6489,10 @@ riscv_expand_epilogue (int style)
riscv_emit_stack_tie ();
/* Deallocate the final bit of the frame. */
- if (step2 > 0)
+ if (step2.to_constant () > 0)
{
insn = emit_insn (gen_add3_insn (stack_pointer_rtx, stack_pointer_rtx,
- GEN_INT (step2)));
+ GEN_INT (step2.to_constant ())));
rtx dwarf = NULL_RTX;
rtx cfa_adjust_rtx = gen_rtx_PLUS (Pmode, stack_pointer_rtx,
@@ -6951,7 +7111,8 @@ riscv_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED,
}
/* Jump to the target function. */
- insn = emit_call_insn (gen_sibcall (fnaddr, const0_rtx, NULL, const0_rtx));
+ rtx callee_cc = gen_int_mode (fndecl_abi (function).id (), SImode);
+ insn = emit_call_insn (gen_sibcall (fnaddr, const0_rtx, callee_cc));
SIBLING_CALL_P (insn) = 1;
/* Run just enough of rest_of_compilation. This sequence was
@@ -8868,6 +9029,9 @@ riscv_frame_pointer_required (void)
#undef TARGET_FNTYPE_ABI
#define TARGET_FNTYPE_ABI riscv_fntype_abi
+#undef TARGET_INSN_CALLEE_ABI
+#define TARGET_INSN_CALLEE_ABI riscv_insn_callee_abi
+
struct gcc_target targetm = TARGET_INITIALIZER;
#include "gt-riscv.h"
@@ -70,6 +70,9 @@
UNSPEC_CLMUL
UNSPEC_CLMULH
UNSPEC_CLMULR
+
+ ;; the calling convention of callee
+ UNSPEC_CALLEE_CC
])
(define_c_enum "unspecv" [
@@ -2928,18 +2931,20 @@
(define_expand "sibcall"
[(parallel [(call (match_operand 0 "")
(match_operand 1 ""))
- (use (match_operand 2 "")) ;; next_arg_reg
- (use (match_operand 3 ""))])] ;; struct_value_size_rtx
+ (unspec:SI [
+ (match_operand 2 "const_int_operand")
+ ] UNSPEC_CALLEE_CC)])]
""
{
rtx target = riscv_legitimize_call_address (XEXP (operands[0], 0));
- emit_call_insn (gen_sibcall_internal (target, operands[1]));
+ emit_call_insn (gen_sibcall_internal (target, operands[1], operands[2]));
DONE;
})
(define_insn "sibcall_internal"
[(call (mem:SI (match_operand 0 "call_insn_operand" "j,S,U"))
- (match_operand 1 "" ""))]
+ (match_operand 1 "" ""))
+ (unspec:SI [(match_operand 2 "const_int_operand")] UNSPEC_CALLEE_CC)]
"SIBLING_CALL_P (insn)"
"@
jr\t%0
@@ -2951,18 +2956,22 @@
[(parallel [(set (match_operand 0 "")
(call (match_operand 1 "")
(match_operand 2 "")))
- (use (match_operand 3 ""))])] ;; next_arg_reg
+ (unspec:SI [
+ (match_operand 3 "const_int_operand")
+ ] UNSPEC_CALLEE_CC)])]
""
{
rtx target = riscv_legitimize_call_address (XEXP (operands[1], 0));
- emit_call_insn (gen_sibcall_value_internal (operands[0], target, operands[2]));
+ emit_call_insn (gen_sibcall_value_internal (operands[0], target, operands[2],
+ operands[3]));
DONE;
})
(define_insn "sibcall_value_internal"
[(set (match_operand 0 "" "")
(call (mem:SI (match_operand 1 "call_insn_operand" "j,S,U"))
- (match_operand 2 "" "")))]
+ (match_operand 2 "" "")))
+ (unspec:SI [(match_operand 3 "const_int_operand")] UNSPEC_CALLEE_CC)]
"SIBLING_CALL_P (insn)"
"@
jr\t%1
@@ -2973,18 +2982,20 @@
(define_expand "call"
[(parallel [(call (match_operand 0 "")
(match_operand 1 ""))
- (use (match_operand 2 "")) ;; next_arg_reg
- (use (match_operand 3 ""))])] ;; struct_value_size_rtx
+ (unspec:SI [
+ (match_operand 2 "const_int_operand")
+ ] UNSPEC_CALLEE_CC)])]
""
{
rtx target = riscv_legitimize_call_address (XEXP (operands[0], 0));
- emit_call_insn (gen_call_internal (target, operands[1]));
+ emit_call_insn (gen_call_internal (target, operands[1], operands[2]));
DONE;
})
(define_insn "call_internal"
[(call (mem:SI (match_operand 0 "call_insn_operand" "l,S,U"))
(match_operand 1 "" ""))
+ (unspec:SI [(match_operand 2 "const_int_operand")] UNSPEC_CALLEE_CC)
(clobber (reg:SI RETURN_ADDR_REGNUM))]
""
"@
@@ -2997,11 +3008,14 @@
[(parallel [(set (match_operand 0 "")
(call (match_operand 1 "")
(match_operand 2 "")))
- (use (match_operand 3 ""))])] ;; next_arg_reg
+ (unspec:SI [
+ (match_operand 3 "const_int_operand")
+ ] UNSPEC_CALLEE_CC)])]
""
{
rtx target = riscv_legitimize_call_address (XEXP (operands[1], 0));
- emit_call_insn (gen_call_value_internal (operands[0], target, operands[2]));
+ emit_call_insn (gen_call_value_internal (operands[0], target, operands[2],
+ operands[3]));
DONE;
})
@@ -3009,6 +3023,7 @@
[(set (match_operand 0 "" "")
(call (mem:SI (match_operand 1 "call_insn_operand" "l,S,U"))
(match_operand 2 "" "")))
+ (unspec:SI [(match_operand 3 "const_int_operand")] UNSPEC_CALLEE_CC)
(clobber (reg:SI RETURN_ADDR_REGNUM))]
""
"@
@@ -3028,7 +3043,9 @@
{
int i;
- emit_call_insn (gen_call (operands[0], const0_rtx, NULL, const0_rtx));
+ /* Untyped calls always use the RISCV_CC_BASE calling convention. */
+ emit_call_insn (gen_call (operands[0], const0_rtx,
+ gen_int_mode (RISCV_CC_BASE, SImode)));
for (i = 0; i < XVECLEN (operands[2], 0); i++)
{
new file mode 100644
@@ -0,0 +1,85 @@
+/* { dg-do compile } */
+/* { dg-options "-O1 -march=rv64gczve32x -mabi=lp64d --param=riscv-vector-abi --param=riscv-autovec-preference=fixed-vlmax -Wno-psabi" } */
+
+#include <riscv_vector.h>
+
+void bar (int8_t *data);
+
+/*
+** foo1:
+** addi\tsp,sp,-16
+** sd\tra,8\(sp\)
+** addi\tsp,sp,-4
+** vs1r\.v\tv1,0\(sp\)
+** addi\tsp,sp,-4
+** vs1r\.v\tv2,0\(sp\)
+** addi\tsp,sp,-4
+** vs1r\.v\tv3,0\(sp\)
+** addi\tsp,sp,-4
+** vs1r\.v\tv4,0\(sp\)
+** addi\tsp,sp,-4
+** vs1r\.v\tv5,0\(sp\)
+** addi\tsp,sp,-4
+** vs1r\.v\tv6,0\(sp\)
+** addi\tsp,sp,-4
+** vs1r\.v\tv7,0\(sp\)
+** addi\tsp,sp,-4
+** vs1r\.v\tv24,0\(sp\)
+** addi\tsp,sp,-4
+** vs1r\.v\tv25,0\(sp\)
+** addi\tsp,sp,-4
+** vs1r\.v\tv26,0\(sp\)
+** addi\tsp,sp,-4
+** vs1r\.v\tv27,0\(sp\)
+** addi\tsp,sp,-4
+** vs1r\.v\tv28,0\(sp\)
+** addi\tsp,sp,-4
+** vs1r\.v\tv29,0\(sp\)
+** addi\tsp,sp,-4
+** vs1r\.v\tv30,0\(sp\)
+** addi\tsp,sp,-4
+** vs1r\.v\tv31,0\(sp\)
+** addi\tsp,sp,-1028
+** mv\ta0,sp
+** call\tbar
+** addi\tsp,sp,1028
+** vl1re32\.v\tv31,0\(sp\)
+** addi\tsp,sp,4
+** vl1re32\.v\tv30,0\(sp\)
+** addi\tsp,sp,4
+** vl1re32\.v\tv29,0\(sp\)
+** addi\tsp,sp,4
+** vl1re32\.v\tv28,0\(sp\)
+** addi\tsp,sp,4
+** vl1re32\.v\tv27,0\(sp\)
+** addi\tsp,sp,4
+** vl1re32\.v\tv26,0\(sp\)
+** addi\tsp,sp,4
+** vl1re32\.v\tv25,0\(sp\)
+** addi\tsp,sp,4
+** vl1re32\.v\tv24,0\(sp\)
+** addi\tsp,sp,4
+** vl1re32\.v\tv7,0\(sp\)
+** addi\tsp,sp,4
+** vl1re32\.v\tv6,0\(sp\)
+** addi\tsp,sp,4
+** vl1re32\.v\tv5,0\(sp\)
+** addi\tsp,sp,4
+** vl1re32\.v\tv4,0\(sp\)
+** addi\tsp,sp,4
+** vl1re32\.v\tv3,0\(sp\)
+** addi\tsp,sp,4
+** vl1re32\.v\tv2,0\(sp\)
+** addi\tsp,sp,4
+** vl1re32\.v\tv1,0\(sp\)
+** addi\tsp,sp,4
+** ld\tra,8\(sp\)
+** addi\tsp,sp,16
+** jr\tra
+*/
+void
+foo1 (vint8m1_t a)
+{
+ int8_t data[1024];
+ bar (data);
+}
new file mode 100644
@@ -0,0 +1,85 @@
+/* { dg-do compile } */
+/* { dg-options "-O1 -march=rv64gcv_zvl4096b -mabi=lp64d --param=riscv-vector-abi --param=riscv-autovec-preference=fixed-vlmax -Wno-psabi" } */
+
+#include <riscv_vector.h>
+
+void bar (int8_t *data);
+
+/*
+** foo1:
+** addi\tsp,sp,-16
+** sd\tra,8\(sp\)
+** addi\tsp,sp,-512
+** vs1r\.v\tv1,0\(sp\)
+** addi\tsp,sp,-512
+** vs1r\.v\tv2,0\(sp\)
+** addi\tsp,sp,-512
+** vs1r\.v\tv3,0\(sp\)
+** addi\tsp,sp,-512
+** vs1r\.v\tv4,0\(sp\)
+** addi\tsp,sp,-512
+** vs1r\.v\tv5,0\(sp\)
+** addi\tsp,sp,-512
+** vs1r\.v\tv6,0\(sp\)
+** addi\tsp,sp,-512
+** vs1r\.v\tv7,0\(sp\)
+** addi\tsp,sp,-512
+** vs1r\.v\tv24,0\(sp\)
+** addi\tsp,sp,-512
+** vs1r\.v\tv25,0\(sp\)
+** addi\tsp,sp,-512
+** vs1r\.v\tv26,0\(sp\)
+** addi\tsp,sp,-512
+** vs1r\.v\tv27,0\(sp\)
+** addi\tsp,sp,-512
+** vs1r\.v\tv28,0\(sp\)
+** addi\tsp,sp,-512
+** vs1r\.v\tv29,0\(sp\)
+** addi\tsp,sp,-512
+** vs1r\.v\tv30,0\(sp\)
+** addi\tsp,sp,-512
+** vs1r\.v\tv31,0\(sp\)
+** addi\tsp,sp,-1028
+** mv\ta0,sp
+** call\tbar
+** addi\tsp,sp,1028
+** vl1re32\.v\tv31,0\(sp\)
+** addi\tsp,sp,512
+** vl1re32\.v\tv30,0\(sp\)
+** addi\tsp,sp,512
+** vl1re32\.v\tv29,0\(sp\)
+** addi\tsp,sp,512
+** vl1re32\.v\tv28,0\(sp\)
+** addi\tsp,sp,512
+** vl1re32\.v\tv27,0\(sp\)
+** addi\tsp,sp,512
+** vl1re32\.v\tv26,0\(sp\)
+** addi\tsp,sp,512
+** vl1re32\.v\tv25,0\(sp\)
+** addi\tsp,sp,512
+** vl1re32\.v\tv24,0\(sp\)
+** addi\tsp,sp,512
+** vl1re32\.v\tv7,0\(sp\)
+** addi\tsp,sp,512
+** vl1re32\.v\tv6,0\(sp\)
+** addi\tsp,sp,512
+** vl1re32\.v\tv5,0\(sp\)
+** addi\tsp,sp,512
+** vl1re32\.v\tv4,0\(sp\)
+** addi\tsp,sp,512
+** vl1re32\.v\tv3,0\(sp\)
+** addi\tsp,sp,512
+** vl1re32\.v\tv2,0\(sp\)
+** addi\tsp,sp,512
+** vl1re32\.v\tv1,0\(sp\)
+** addi\tsp,sp,512
+** ld\tra,8\(sp\)
+** addi\tsp,sp,16
+** jr\tra
+*/
+void
+foo1 (vint8m1_t a)
+{
+ int8_t data[1024];
+ bar (data);
+}
new file mode 100644
@@ -0,0 +1,87 @@
+/* { dg-do compile } */
+/* { dg-options "-O1 -march=rv64gcv_zfh -mabi=lp64d --param=riscv-vector-abi -Wno-psabi" } */
+
+#include <riscv_vector.h>
+
+void bar (int8_t *data);
+
+/*
+** foo1:
+** addi\tsp,sp,-16
+** sd\tra,8\(sp\)
+** csrr\tt0,vlenb
+** sub\tsp,sp,t0
+** vs1r\.v\tv1,0\(sp\)
+** sub\tsp,sp,t0
+** vs1r\.v\tv2,0\(sp\)
+** sub\tsp,sp,t0
+** vs1r\.v\tv3,0\(sp\)
+** sub\tsp,sp,t0
+** vs1r\.v\tv4,0\(sp\)
+** sub\tsp,sp,t0
+** vs1r\.v\tv5,0\(sp\)
+** sub\tsp,sp,t0
+** vs1r\.v\tv6,0\(sp\)
+** sub\tsp,sp,t0
+** vs1r\.v\tv7,0\(sp\)
+** sub\tsp,sp,t0
+** vs1r\.v\tv24,0\(sp\)
+** sub\tsp,sp,t0
+** vs1r\.v\tv25,0\(sp\)
+** sub\tsp,sp,t0
+** vs1r\.v\tv26,0\(sp\)
+** sub\tsp,sp,t0
+** vs1r\.v\tv27,0\(sp\)
+** sub\tsp,sp,t0
+** vs1r\.v\tv28,0\(sp\)
+** sub\tsp,sp,t0
+** vs1r\.v\tv29,0\(sp\)
+** sub\tsp,sp,t0
+** vs1r\.v\tv30,0\(sp\)
+** sub\tsp,sp,t0
+** vs1r\.v\tv31,0\(sp\)
+** addi\tsp,sp,-1024
+** mv\ta0,sp
+** call\tbar
+** addi\tsp,sp,1024
+** csrr\tt0,vlenb
+** vl1re64\.v\tv31,0\(sp\)
+** add\tsp,sp,t0
+** vl1re64\.v\tv30,0\(sp\)
+** add\tsp,sp,t0
+** vl1re64\.v\tv29,0\(sp\)
+** add\tsp,sp,t0
+** vl1re64\.v\tv28,0\(sp\)
+** add\tsp,sp,t0
+** vl1re64\.v\tv27,0\(sp\)
+** add\tsp,sp,t0
+** vl1re64\.v\tv26,0\(sp\)
+** add\tsp,sp,t0
+** vl1re64\.v\tv25,0\(sp\)
+** add\tsp,sp,t0
+** vl1re64\.v\tv24,0\(sp\)
+** add\tsp,sp,t0
+** vl1re64\.v\tv7,0\(sp\)
+** add\tsp,sp,t0
+** vl1re64\.v\tv6,0\(sp\)
+** add\tsp,sp,t0
+** vl1re64\.v\tv5,0\(sp\)
+** add\tsp,sp,t0
+** vl1re64\.v\tv4,0\(sp\)
+** add\tsp,sp,t0
+** vl1re64\.v\tv3,0\(sp\)
+** add\tsp,sp,t0
+** vl1re64\.v\tv2,0\(sp\)
+** add\tsp,sp,t0
+** vl1re64\.v\tv1,0\(sp\)
+** add\tsp,sp,t0
+** ld\tra,8\(sp\)
+** addi\tsp,sp,16
+** jr\tra
+*/
+void
+foo1 (vint8m1_t a)
+{
+ int8_t data[1024];
+ bar (data);
+}
new file mode 100644
@@ -0,0 +1,117 @@
+/* { dg-do compile } */
+/* { dg-options "-O1 -march=rv64gcv_zfh -mabi=lp64d --param=riscv-vector-abi -Wno-psabi" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include <riscv_vector.h>
+
+void bar1 (vint8m1_t a);
+void bar2 ();
+
+/*
+** foo1:
+** addi\tsp,sp,-16
+** sd\tra,8\(sp\)
+** call\tbar1
+** ld\tra,8\(sp\)
+** addi\tsp,sp,16
+** jr\tra
+*/
+void
+foo1 (vint8m1_t a)
+{
+ bar1 (a);
+}
+
+/*
+** foo2:
+** addi\tsp,sp,-16
+** sd\tra,8\(sp\)
+** csrr\tt0,vlenb
+** sub\tsp,sp,t0
+** vs1r\.v\tv1,0\(sp\)
+** sub\tsp,sp,t0
+** vs1r\.v\tv2,0\(sp\)
+** sub\tsp,sp,t0
+** vs1r\.v\tv3,0\(sp\)
+** sub\tsp,sp,t0
+** vs1r\.v\tv4,0\(sp\)
+** sub\tsp,sp,t0
+** vs1r\.v\tv5,0\(sp\)
+** sub\tsp,sp,t0
+** vs1r\.v\tv6,0\(sp\)
+** sub\tsp,sp,t0
+** vs1r\.v\tv7,0\(sp\)
+** sub\tsp,sp,t0
+** vs1r\.v\tv24,0\(sp\)
+** sub\tsp,sp,t0
+** vs1r\.v\tv25,0\(sp\)
+** sub\tsp,sp,t0
+** vs1r\.v\tv26,0\(sp\)
+** sub\tsp,sp,t0
+** vs1r\.v\tv27,0\(sp\)
+** sub\tsp,sp,t0
+** vs1r\.v\tv28,0\(sp\)
+** sub\tsp,sp,t0
+** vs1r\.v\tv29,0\(sp\)
+** sub\tsp,sp,t0
+** vs1r\.v\tv30,0\(sp\)
+** sub\tsp,sp,t0
+** vs1r\.v\tv31,0\(sp\)
+** call\tbar2
+** csrr\tt0,vlenb
+** vl1re64\.v\tv31,0\(sp\)
+** add\tsp,sp,t0
+** vl1re64\.v\tv30,0\(sp\)
+** add\tsp,sp,t0
+** vl1re64\.v\tv29,0\(sp\)
+** add\tsp,sp,t0
+** vl1re64\.v\tv28,0\(sp\)
+** add\tsp,sp,t0
+** vl1re64\.v\tv27,0\(sp\)
+** add\tsp,sp,t0
+** vl1re64\.v\tv26,0\(sp\)
+** add\tsp,sp,t0
+** vl1re64\.v\tv25,0\(sp\)
+** add\tsp,sp,t0
+** vl1re64\.v\tv24,0\(sp\)
+** add\tsp,sp,t0
+** vl1re64\.v\tv7,0\(sp\)
+** add\tsp,sp,t0
+** vl1re64\.v\tv6,0\(sp\)
+** add\tsp,sp,t0
+** vl1re64\.v\tv5,0\(sp\)
+** add\tsp,sp,t0
+** vl1re64\.v\tv4,0\(sp\)
+** add\tsp,sp,t0
+** vl1re64\.v\tv3,0\(sp\)
+** add\tsp,sp,t0
+** vl1re64\.v\tv2,0\(sp\)
+** add\tsp,sp,t0
+** vl1re64\.v\tv1,0\(sp\)
+** add\tsp,sp,t0
+** ld\tra,8\(sp\)
+** addi\tsp,sp,16
+** jr\tra
+
+*/
+void
+foo2 (vint8m1_t a)
+{
+ bar2 ();
+}
+
+/*
+** foo3:
+** addi\tsp,sp,-16
+** sd\tra,8\(sp\)
+** vl1re8\.v\tv8,0\(a0\)
+** call\tbar1
+** ld\tra,8\(sp\)
+** addi\tsp,sp,16
+** jr\tra
+*/
+void
+foo3 (vint8m1_t *a)
+{
+ bar1 (*a);
+}