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
>

Reply via email to