Could you rebase the patch again, it seems got some conflict with zcmt which I commit in the past few days...
On Wed, Aug 30, 2023 at 9:54 AM Lehua Ding <lehua.d...@rivai.ai> wrote: > > Because functions which follow vector calling convention variant has > callee-saved vector reigsters but functions which follow standard calling > convention don't have. We need to distinguish which function callee is so that > we can tell GCC exactly which vector registers callee will clobber. So I > encode > the callee's calling convention information into the calls rtx pattern like > AArch64. The old operand 2 and 3 of call pattern which copy from MIPS target > are > useless and removed according to my analysis. > > gcc/ChangeLog: > > * config/riscv/riscv-sr.cc > (riscv_remove_unneeded_save_restore_calls): Pass riscv_cc. > * config/riscv/riscv.cc (struct riscv_frame_info): Add new fileds. > (riscv_frame_info::reset): Reset new fileds. > (riscv_call_tls_get_addr): Pass riscv_cc. > (riscv_function_arg): Return riscv_cc for call patterm. > (riscv_insn_callee_abi): Implement TARGET_INSN_CALLEE_ABI. > (riscv_save_reg_p): Add vector callee-saved check. > (riscv_save_libcall_count): Add vector save area. > (riscv_compute_frame_info): Ditto. > (riscv_restore_reg): Update for type change. > (riscv_for_each_saved_v_reg): New function save vector registers. > (riscv_first_stack_step): Handle funciton with vector callee-saved > registers. > (riscv_expand_prologue): Ditto. > (riscv_expand_epilogue): Ditto. > (riscv_output_mi_thunk): Pass riscv_cc. > (TARGET_INSN_CALLEE_ABI): Implement TARGET_INSN_CALLEE_ABI. > * config/riscv/riscv.md: Add CALLEE_CC operand for call pattern. > > gcc/testsuite/ChangeLog: > > * gcc.target/riscv/rvv/base/abi-callee-saved-1-fixed-1.c: New test. > * gcc.target/riscv/rvv/base/abi-callee-saved-1-fixed-2.c: New test. > * gcc.target/riscv/rvv/base/abi-callee-saved-1.c: New test. > * gcc.target/riscv/rvv/base/abi-callee-saved-2.c: New test. > --- > gcc/config/riscv/riscv-sr.cc | 12 +- > gcc/config/riscv/riscv.cc | 222 +++++++++++++++--- > gcc/config/riscv/riscv.md | 43 +++- > .../rvv/base/abi-callee-saved-1-fixed-1.c | 85 +++++++ > .../rvv/base/abi-callee-saved-1-fixed-2.c | 85 +++++++ > .../riscv/rvv/base/abi-callee-saved-1.c | 87 +++++++ > .../riscv/rvv/base/abi-callee-saved-2.c | 117 +++++++++ > 7 files changed, 606 insertions(+), 45 deletions(-) > create mode 100644 > gcc/testsuite/gcc.target/riscv/rvv/base/abi-callee-saved-1-fixed-1.c > create mode 100644 > gcc/testsuite/gcc.target/riscv/rvv/base/abi-callee-saved-1-fixed-2.c > create mode 100644 > gcc/testsuite/gcc.target/riscv/rvv/base/abi-callee-saved-1.c > create mode 100644 > gcc/testsuite/gcc.target/riscv/rvv/base/abi-callee-saved-2.c > > diff --git a/gcc/config/riscv/riscv-sr.cc b/gcc/config/riscv/riscv-sr.cc > index 7248f04d68f..e6e17685df5 100644 > --- a/gcc/config/riscv/riscv-sr.cc > +++ b/gcc/config/riscv/riscv-sr.cc > @@ -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); > diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc > index aa6b46d7611..09c9e09e83a 100644 > --- a/gcc/config/riscv/riscv.cc > +++ b/gcc/config/riscv/riscv.cc > @@ -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" > diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md > index 688fd697255..371e9959e61 100644 > --- a/gcc/config/riscv/riscv.md > +++ b/gcc/config/riscv/riscv.md > @@ -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++) > { > diff --git > a/gcc/testsuite/gcc.target/riscv/rvv/base/abi-callee-saved-1-fixed-1.c > b/gcc/testsuite/gcc.target/riscv/rvv/base/abi-callee-saved-1-fixed-1.c > new file mode 100644 > index 00000000000..d0660588c63 > --- /dev/null > +++ b/gcc/testsuite/gcc.target/riscv/rvv/base/abi-callee-saved-1-fixed-1.c > @@ -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); > +} > diff --git > a/gcc/testsuite/gcc.target/riscv/rvv/base/abi-callee-saved-1-fixed-2.c > b/gcc/testsuite/gcc.target/riscv/rvv/base/abi-callee-saved-1-fixed-2.c > new file mode 100644 > index 00000000000..77c5fee24ce > --- /dev/null > +++ b/gcc/testsuite/gcc.target/riscv/rvv/base/abi-callee-saved-1-fixed-2.c > @@ -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); > +} > diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/abi-callee-saved-1.c > b/gcc/testsuite/gcc.target/riscv/rvv/base/abi-callee-saved-1.c > new file mode 100644 > index 00000000000..a2a7f78100e > --- /dev/null > +++ b/gcc/testsuite/gcc.target/riscv/rvv/base/abi-callee-saved-1.c > @@ -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); > +} > diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/abi-callee-saved-2.c > b/gcc/testsuite/gcc.target/riscv/rvv/base/abi-callee-saved-2.c > new file mode 100644 > index 00000000000..0ea3e247368 > --- /dev/null > +++ b/gcc/testsuite/gcc.target/riscv/rvv/base/abi-callee-saved-2.c > @@ -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); > +} > -- > 2.36.3 >