Seems I got one fail for pr120436.c, will send v2 for fixing that
On Thu, Oct 9, 2025 at 6:48 PM Kito Cheng <[email protected]> wrote: > > This patch implements the standard fixed-length vector calling convention > variant as specified in the RISC-V ELF psABI document. The implementation > introduces ABI_VLEN to serve as the minimal VLEN for fixed-length vectors. > > For example, int32x8_t is a 256-bit vector type. If ABI_VLEN is 128, it > will be passed in two vector registers as LMUL 2. If ABI_VLEN is larger > than 256, it will be passed in one vector register as LMUL 1. > > This differs from the minimal VLEN (defined by ZVL*B extension) to ensure > ABI stability when the program compiles with different VLEN/ZVL*B settings. > > Ref: https://github.com/riscv-non-isa/riscv-elf-psabi-doc/pull/418 > > gcc/ChangeLog: > > * config/riscv/riscv.h (enum riscv_cc): Add RISCV_CC_VLS_V_32, > RISCV_CC_VLS_V_64, RISCV_CC_VLS_V_128, RISCV_CC_VLS_V_256, > RISCV_CC_VLS_V_512, RISCV_CC_VLS_V_1024, RISCV_CC_VLS_V_2048, > RISCV_CC_VLS_V_4096, RISCV_CC_VLS_V_8192, RISCV_CC_VLS_V_16384. > (CUMULATIVE_ARGS): Add abi_vlen field. > * config/riscv/riscv.cc (riscv_handle_rvv_vls_cc_attribute): New > function. > (riscv_gnu_attributes): Add vls_cc attribute entry. > (riscv_attributes): Add riscv_vls_cc attribute entry. > (riscv_flatten_aggregate_field): Add vls_p and abi_vlen parameters > to handle VLS vector types. > (riscv_flatten_aggregate_argument): Update call to > riscv_flatten_aggregate_field. > (riscv_get_vector_arg): Add vls_p parameter for VLS handling. > (riscv_vls_cc_p): New function. > (riscv_get_cc_abi_vlen): New function. > (riscv_valid_abi_vlen_vls_cc_p): New function. > (riscv_get_riscv_cc_by_abi_vlen): New function. > (riscv_get_vls_container_type): New function. > (riscv_pass_vls_in_vr): New function. > (riscv_pass_aggregate_in_vr): New function. > (riscv_get_arg_info): Add VLS calling convention handling. > (riscv_function_arg_advance): Update for VLS calling convention. > (riscv_return_in_memory): Add fntype parameter and initialize > cumulative args properly. > (riscv_v_abi): Add abi parameter. > (riscv_get_vls_cc_attr): New function. > (riscv_vls_cc_function_abi): New function. > (riscv_fntype_abi): Add VLS calling convention detection. > (riscv_asm_output_variant_cc): Update for VLS calling convention. > --- > gcc/config/riscv/riscv.cc | 409 ++++++++++++++++++++++++++++++++++---- > gcc/config/riscv/riscv.h | 13 ++ > 2 files changed, 384 insertions(+), 38 deletions(-) > > diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc > index a30c9f1dd14..b4a0f61f1d2 100644 > --- a/gcc/config/riscv/riscv.cc > +++ b/gcc/config/riscv/riscv.cc > @@ -740,6 +740,7 @@ static tree riscv_handle_fndecl_attribute (tree *, tree, > tree, int, bool *); > static tree riscv_handle_type_attribute (tree *, tree, tree, int, bool *); > static tree riscv_handle_rvv_vector_bits_attribute (tree *, tree, tree, int, > bool *); > +static tree riscv_handle_rvv_vls_cc_attribute (tree *, tree, tree, int, bool > *); > > /* Defining target-specific uses of __attribute__. */ > static const attribute_spec riscv_gnu_attributes[] = > @@ -763,6 +764,8 @@ static const attribute_spec riscv_gnu_attributes[] = > standard vector calling convention variant. Syntax: > __attribute__((riscv_vector_cc)). */ > {"riscv_vector_cc", 0, 0, false, true, true, true, NULL, NULL}, > + {"riscv_vls_cc", 0, 1, false, true, true, true, > + riscv_handle_rvv_vls_cc_attribute, NULL}, > /* This attribute is used to declare a new type, to appoint the exactly > bits size of the type. For example: > > @@ -790,6 +793,8 @@ static const attribute_spec riscv_attributes[] = > standard vector calling convention variant. Syntax: > [[riscv::vector_cc]]. */ > {"vector_cc", 0, 0, false, true, true, true, NULL, NULL}, > + {"vls_cc", 0, 1, false, true, true, true, > riscv_handle_rvv_vls_cc_attribute, > + NULL}, > /* This attribute is used to declare a new type, to appoint the exactly > bits size of the type. For example: > > @@ -5872,11 +5877,12 @@ typedef struct { > floating-point registers. */ > > static int > -riscv_flatten_aggregate_field (const_tree type, > - riscv_aggregate_field fields[2], > +riscv_flatten_aggregate_field (const_tree type, riscv_aggregate_field > *fields, > int n, HOST_WIDE_INT offset, > - bool ignore_zero_width_bit_field_p) > + bool ignore_zero_width_bit_field_p, > + bool vls_p = false, unsigned abi_vlen = 0) > { > + int max_aggregate_field = vls_p ? 8 : 2; > switch (TREE_CODE (type)) > { > case RECORD_TYPE: > @@ -5903,9 +5909,9 @@ riscv_flatten_aggregate_field (const_tree type, > else > { > HOST_WIDE_INT pos = offset + int_byte_position (f); > - n = riscv_flatten_aggregate_field (TREE_TYPE (f), > - fields, n, pos, > - > ignore_zero_width_bit_field_p); > + n = riscv_flatten_aggregate_field ( > + TREE_TYPE (f), fields, n, pos, > ignore_zero_width_bit_field_p, > + vls_p, abi_vlen); > } > if (n < 0) > return -1; > @@ -5915,13 +5921,14 @@ riscv_flatten_aggregate_field (const_tree type, > case ARRAY_TYPE: > { > HOST_WIDE_INT n_elts; > - riscv_aggregate_field subfields[2]; > + riscv_aggregate_field subfields[8]; > tree index = TYPE_DOMAIN (type); > tree elt_size = TYPE_SIZE_UNIT (TREE_TYPE (type)); > - int n_subfields = riscv_flatten_aggregate_field (TREE_TYPE (type), > - subfields, 0, offset, > - > ignore_zero_width_bit_field_p); > - > + int n_subfields > + = riscv_flatten_aggregate_field (TREE_TYPE (type), subfields, 0, > + offset, > + ignore_zero_width_bit_field_p, > vls_p, > + abi_vlen); > /* Can't handle incomplete types nor sizes that are not fixed. */ > if (n_subfields <= 0 > || !COMPLETE_TYPE_P (type) > @@ -5941,7 +5948,7 @@ riscv_flatten_aggregate_field (const_tree type, > for (HOST_WIDE_INT i = 0; i < n_elts; i++) > for (int j = 0; j < n_subfields; j++) > { > - if (n >= 2) > + if (n >= max_aggregate_field) > return -1; > > fields[n] = subfields[j]; > @@ -5973,18 +5980,36 @@ riscv_flatten_aggregate_field (const_tree type, > } > > default: > - if (n < 2 > - && ((SCALAR_FLOAT_TYPE_P (type) > - && GET_MODE_SIZE (TYPE_MODE (type)).to_constant () <= > UNITS_PER_FP_ARG) > - || (INTEGRAL_TYPE_P (type) > - && GET_MODE_SIZE (TYPE_MODE (type)).to_constant () <= > UNITS_PER_WORD))) > + poly_uint64 mode_size = GET_MODE_SIZE (TYPE_MODE (type)); > + if (vls_p) > { > - fields[n].type = type; > - fields[n].offset = offset; > - return n + 1; > + gcc_assert (abi_vlen != 0); > + if (n < max_aggregate_field > + && (VECTOR_TYPE_P (type) && mode_size.is_constant () > + && (mode_size.to_constant () <= abi_vlen * 8))) > + { > + fields[n].type = type; > + fields[n].offset = offset; > + return n + 1; > + } > + else > + return -1; > } > else > - return -1; > + { > + if (n < max_aggregate_field > + && ((SCALAR_FLOAT_TYPE_P (type) > + && mode_size.to_constant () <= UNITS_PER_FP_ARG) > + || (INTEGRAL_TYPE_P (type) > + && mode_size.to_constant () <= UNITS_PER_WORD))) > + { > + fields[n].type = type; > + fields[n].offset = offset; > + return n + 1; > + } > + else > + return -1; > + } > } > } > > @@ -5993,14 +6018,16 @@ riscv_flatten_aggregate_field (const_tree type, > > static int > riscv_flatten_aggregate_argument (const_tree type, > - riscv_aggregate_field fields[2], > - bool ignore_zero_width_bit_field_p) > + riscv_aggregate_field *fields, > + bool ignore_zero_width_bit_field_p, > + bool vls_p = false, unsigned abi_vlen = 0) > { > if (!type || TREE_CODE (type) != RECORD_TYPE) > return -1; > > return riscv_flatten_aggregate_field (type, fields, 0, 0, > - ignore_zero_width_bit_field_p); > + ignore_zero_width_bit_field_p, vls_p, > + abi_vlen); > } > > /* See whether TYPE is a record whose fields should be returned in one or > @@ -6197,7 +6224,7 @@ riscv_hard_regno_nregs (unsigned int regno, > machine_mode mode); > > static rtx > riscv_get_vector_arg (struct riscv_arg_info *info, const CUMULATIVE_ARGS > *cum, > - machine_mode mode, bool return_p) > + machine_mode mode, bool return_p, bool vls_p = false) > { > gcc_assert (riscv_v_ext_mode_p (mode)); > > @@ -6233,8 +6260,9 @@ riscv_get_vector_arg (struct riscv_arg_info *info, > const CUMULATIVE_ARGS *cum, > int arg_reg_end = V_ARG_LAST - V_REG_FIRST; > int aligned_reg_start = ROUND_UP (arg_reg_start, LMUL); > > - /* For scalable data and scalable tuple return value. */ > - if (return_p) > + /* For scalable data and scalable tuple return value. > + For VLS CC, we may pass struct like tuple, so need defer the handling. > */ > + if (return_p && !vls_p) > return gen_rtx_REG (mode, aligned_reg_start + V_REG_FIRST); > > /* Iterate through the USED_VRS array to find vector register groups that > have > @@ -6271,6 +6299,224 @@ riscv_get_vector_arg (struct riscv_arg_info *info, > const CUMULATIVE_ARGS *cum, > return NULL_RTX; > } > > + > +#define RISCV_ALL_VALID_ABI_VLEN(F) \ > + F (32) \ > + F (64) \ > + F (128) \ > + F (256) \ > + F (512) \ > + F (1024) \ > + F (2048) \ > + F (4096) \ > + F (8192) \ > + F (16384) > + > +/* Return true if CC is a variant of VLS CC. */ > + > +static bool > +riscv_vls_cc_p (riscv_cc cc) > +{ > + switch (cc) > + { > +#define VLS_CC_ABI_VLEN_CASE(ABI_VLEN) \ > + case RISCV_CC_VLS_V_##ABI_VLEN: > + RISCV_ALL_VALID_ABI_VLEN(VLS_CC_ABI_VLEN_CASE) > + > +#undef VLS_CC_ABI_VLEN_CASE > + return true; > + default: > + return false; > + } > +} > + > +/* Get ABI_VLEN from cc. */ > + > +static unsigned int > +riscv_get_cc_abi_vlen (riscv_cc cc) > +{ > + switch (cc) > + { > +#define VLS_CC_ABI_VLEN_CASE(ABI_VLEN) \ > + case RISCV_CC_VLS_V_##ABI_VLEN: \ > + return ABI_VLEN; > + RISCV_ALL_VALID_ABI_VLEN(VLS_CC_ABI_VLEN_CASE) > + > +#undef VLS_CC_ABI_VLEN_CASE > + default: > + gcc_unreachable (); > + } > +} > + > +/* Return true if ABI_VLEN is a valid for VLS_CC. */ > + > +static bool > +riscv_valid_abi_vlen_vls_cc_p (unsigned abi_vlen) > +{ > + switch (abi_vlen) > + { > +#define VLS_CC_ABI_VLEN_CASE(ABI_VLEN) \ > + case ABI_VLEN: > + RISCV_ALL_VALID_ABI_VLEN(VLS_CC_ABI_VLEN_CASE) > + > +#undef VLS_CC_ABI_VLEN_CASE > + return true; > + default: > + return false; > + } > +} > + > +static riscv_cc > +riscv_get_riscv_cc_by_abi_vlen (unsigned abi_vlen) > +{ > + switch (abi_vlen) > + { > +#define VLS_CC_ABI_VLEN_CASE(ABI_VLEN) \ > + case ABI_VLEN: \ > + return RISCV_CC_VLS_V_##ABI_VLEN; > + RISCV_ALL_VALID_ABI_VLEN(VLS_CC_ABI_VLEN_CASE) > + > +#undef VLS_CC_ABI_VLEN_CASE > + default: > + gcc_unreachable (); > + } > +} > + > +/* Get a VLS type has same size as MODE in ABI_VLEN, but element is always > + in integer mode. */ > + > +static machine_mode > +riscv_get_vls_container_type (machine_mode mode, unsigned abi_vlen) > +{ > + machine_mode element_mode = GET_MODE_INNER (mode); > + unsigned int mode_size = GET_MODE_SIZE (mode).to_constant (); > + unsigned int lmul = ROUND_UP (mode_size * 8, abi_vlen) / abi_vlen; > + > + /* Always use integer mode to pass to simplify the logic - we allow pass > + unsupported vector type in vector register, e.g. float16x4_t even no > vector > + fp16 support. */ > + switch (GET_MODE_SIZE (element_mode).to_constant ()) > + { > + case 1: > + element_mode = QImode; > + break; > + case 2: > + element_mode = HImode; > + break; > + case 4: > + element_mode = SImode; > + break; > + case 8: > + element_mode = DImode; > + break; > + default: > + gcc_unreachable (); > + } > + > + scalar_mode smode = as_a<scalar_mode> (element_mode); > + return get_lmul_mode (smode, lmul).require (); > +} > + > +/* Pass VLS type argument in vector argument register. */ > + > +static rtx > +riscv_pass_vls_in_vr (struct riscv_arg_info *info, const CUMULATIVE_ARGS > *cum, > + machine_mode mode, bool return_p) > +{ > + gcc_assert (riscv_v_ext_vls_mode_p (mode)); > + > + unsigned int abi_vlen = riscv_get_cc_abi_vlen (cum->variant_cc); > + unsigned int mode_size = GET_MODE_SIZE (mode).to_constant (); > + unsigned int lmul = ROUND_UP (mode_size * 8, abi_vlen) / abi_vlen; > + > + /* Put into memory if it need more than 8 registers (> LMUL 8). */ > + if (lmul > 8) > + return NULL_RTX; > + > + machine_mode vla_mode = riscv_get_vls_container_type (mode, abi_vlen); > + rtx reg = riscv_get_vector_arg (info, cum, vla_mode, > + return_p, /* vls_p */ true); > + > + /* Can't get vector register to pass, pass by memory. */ > + if (!reg) > + return NULL_RTX; > + > + PUT_MODE (reg, mode); > + > + return reg; > +} > + > +/* Pass aggregate with VLS type argument in vector argument registers. */ > + > +static rtx > +riscv_pass_aggregate_in_vr (struct riscv_arg_info *info, > + const CUMULATIVE_ARGS *cum, const_tree type, > + bool return_p) > +{ > + riscv_aggregate_field fields[8]; > + unsigned int abi_vlen = riscv_get_cc_abi_vlen (cum->variant_cc); > + int i; > + int n = riscv_flatten_aggregate_argument (type, fields, true, > + /* vls_p */ true, abi_vlen); > + > + if (n == -1) > + return NULL_RTX; > + > + /* Check all field has same size. */ > + unsigned int mode_size > + = GET_MODE_SIZE (TYPE_MODE (fields[0].type)).to_constant (); > + for (int i = 1; i < n; i++) > + if (GET_MODE_SIZE (TYPE_MODE (fields[i].type)).to_constant () != > mode_size) > + return NULL_RTX; /* Return NULL_RTX if we cannot find a suitable reg. > */ > + > + /* Check total size is <= abi_vlen * 8, we use up to 8 vector register to > + pass argument. */ > + if (mode_size * 8 > abi_vlen) > + return NULL_RTX; /* Return NULL_RTX if we cannot find a suitable reg. */ > + > + /* Backup cum->used_vrs since we will defer the update until > + riscv_function_arg_advance. */ > + CUMULATIVE_ARGS local_cum; > + memcpy (&local_cum, cum, sizeof (local_cum)); > + > + unsigned num_vrs = 0; > + > + /* Allocate vector registers for the arguments. */ > + rtx expr_list[8]; > + for (i = 0; i < n; i++) > + { > + machine_mode mode = TYPE_MODE (fields[i].type); > + machine_mode vla_mode = riscv_get_vls_container_type (mode, abi_vlen); > + /* Use riscv_get_vector_arg with VLA type to simplify the calling > + convention implementation. */ > + rtx reg > + = riscv_get_vector_arg (info, &local_cum, vla_mode, > + return_p, /* vls_p */true); > + > + /* Can't get vector register to pass, pass by memory. */ > + if (!reg) > + return NULL_RTX; > + > + PUT_MODE (reg, mode); > + > + expr_list[i] > + = gen_rtx_EXPR_LIST (VOIDmode, reg, GEN_INT (fields[i].offset)); > + > + num_vrs += info->num_vrs; > + > + /* Set the corresponding register in USED_VRS to used status. */ > + for (unsigned int i = 0; i < info->num_vrs; i++) > + { > + gcc_assert (!local_cum.used_vrs[info->vr_offset + i]); > + local_cum.used_vrs[info->vr_offset + i] = true; > + } > + } > + > + info->num_vrs = num_vrs; > + > + return gen_rtx_PARALLEL (BLKmode, gen_rtvec_v (n, expr_list)); > +} > + > /* Fill INFO with information about a single argument, and return an RTL > pattern to pass or return the argument. Return NULL_RTX if argument cannot > pass or return in registers, then the argument may be passed by reference > or > @@ -6363,7 +6609,17 @@ riscv_get_arg_info (struct riscv_arg_info *info, const > CUMULATIVE_ARGS *cum, > if (riscv_vector_type_p (type) && riscv_v_ext_mode_p (mode)) > return riscv_get_vector_arg (info, cum, mode, return_p); > > - /* For vls mode aggregated in gpr. */ > + if (riscv_vls_cc_p (cum->variant_cc)) > + { > + if (riscv_v_ext_vls_mode_p (mode)) > + return riscv_pass_vls_in_vr (info, cum, mode, return_p); > + > + rtx ret = riscv_pass_aggregate_in_vr (info, cum, type, return_p); > + if (ret) > + return ret; > + } > + > + /* For vls mode aggregated in gpr (for non-VLS-CC). */ > if (riscv_v_ext_vls_mode_p (mode)) > return riscv_pass_vls_aggregate_in_gpr (info, mode, gpr_base); > } > @@ -6420,7 +6676,8 @@ riscv_function_arg_advance (cumulative_args_t cum_v, > cum->used_vrs[info.vr_offset + i] = true; > } > > - if ((info.num_vrs > 0 || info.num_mrs > 0) && cum->variant_cc != > RISCV_CC_V) > + if ((info.num_vrs > 0 || info.num_mrs > 0) && cum->variant_cc != RISCV_CC_V > + && !riscv_vls_cc_p (cum->variant_cc)) > { > error ("RVV type %qT cannot be passed to an unprototyped function", > arg.type); > @@ -6532,14 +6789,19 @@ riscv_pass_by_reference (cumulative_args_t cum_v, > const function_arg_info &arg) > /* Implement TARGET_RETURN_IN_MEMORY. */ > > static bool > -riscv_return_in_memory (const_tree type, const_tree fndecl ATTRIBUTE_UNUSED) > +riscv_return_in_memory (const_tree type, const_tree fntype) > { > CUMULATIVE_ARGS args; > + > + if (fntype) > + riscv_init_cumulative_args (&args, fntype, NULL_RTX, NULL_TREE, 0); > + else > + /* The rules for returning in memory are the same as for passing the > + first named argument by reference. */ > + memset (&args, 0, sizeof args); > + > cumulative_args_t cum = pack_cumulative_args (&args); > > - /* The rules for returning in memory are the same as for passing the > - first named argument by reference. */ > - memset (&args, 0, sizeof args); > function_arg_info arg (const_cast<tree> (type), /*named=*/true); > return riscv_pass_by_reference (cum, arg); > } > @@ -6583,9 +6845,9 @@ riscv_setup_incoming_varargs (cumulative_args_t cum, > /* Return the descriptor of the Standard Vector Calling Convention Variant. > */ > > static const predefined_function_abi & > -riscv_v_abi () > +riscv_v_abi (riscv_cc abi) > { > - predefined_function_abi &v_abi = function_abis[RISCV_CC_V]; > + predefined_function_abi &v_abi = function_abis[abi]; > if (!v_abi.initialized_p ()) > { > HARD_REG_SET full_reg_clobbers > @@ -6595,7 +6857,7 @@ riscv_v_abi () > CLEAR_HARD_REG_BIT (full_reg_clobbers, regno); > for (int regno = V_REG_FIRST + 24; regno <= V_REG_FIRST + 31; regno += > 1) > CLEAR_HARD_REG_BIT (full_reg_clobbers, regno); > - v_abi.initialize (RISCV_CC_V, full_reg_clobbers); > + v_abi.initialize (abi, full_reg_clobbers); > } > return v_abi; > } > @@ -6807,6 +7069,54 @@ riscv_vector_cc_function_p (const_tree fntype) > return vector_cc_p; > } > > +static riscv_cc > +riscv_get_vls_cc_attr (const_tree args) > +{ > + /* Default ABI_VLEN is 128. */ > + int abi_vlen = 128; > + > + if (args && TREE_CODE (args) == TREE_LIST) > + { > + tree vlen_arg = TREE_VALUE (args); > + if (vlen_arg && TREE_CODE (vlen_arg) == INTEGER_CST) > + abi_vlen = TREE_INT_CST_LOW (vlen_arg); > + } > + > + if (!riscv_valid_abi_vlen_vls_cc_p (abi_vlen)) > + { > + error_at (input_location, > + "unsupported ABI_VLEN value %d for %qs attribute;" > + "ABI_VLEN must be in the range [32, 16384] and must be " > + "a power of 2.", > + "riscv_vls_cc", abi_vlen); > + return RISCV_CC_UNKNOWN; > + } > + > + return riscv_get_riscv_cc_by_abi_vlen (abi_vlen); > +} > + > +/* Return true if FUNC is a riscv_vector_cc function. > + For more details please reference the below link. > + https://github.com/riscv-non-isa/riscv-c-api-doc/pull/67 */ > +static riscv_cc > +riscv_vls_cc_function_abi (const_tree fntype) > +{ > + tree attr = TYPE_ATTRIBUTES (fntype); > + bool vls_cc_p = lookup_attribute ("vls_cc", attr) != NULL_TREE > + || lookup_attribute ("riscv_vls_cc", attr) != NULL_TREE; > + > + if (!vls_cc_p) > + return RISCV_CC_UNKNOWN; > + > + if (!TARGET_VECTOR) > + error_at (input_location, > + "function attribute %qs requires the vector ISA extension", > + "riscv_vls_cc"); > + > + tree args = TREE_VALUE (attr); > + return riscv_get_vls_cc_attr (args); > +} > + > /* Implement TARGET_FNTYPE_ABI. */ > > static const predefined_function_abi & > @@ -6822,7 +7132,11 @@ riscv_fntype_abi (const_tree fntype) > validate_v_abi_p |= riscv_vector_cc_function_p (fntype); > > if (validate_v_abi_p) > - return riscv_v_abi (); > + return riscv_v_abi (RISCV_CC_V); > + > + riscv_cc abi = riscv_vls_cc_function_abi (fntype); > + if (abi != RISCV_CC_UNKNOWN) > + return riscv_v_abi (abi); > > return default_function_abi; > } > @@ -6915,6 +7229,25 @@ riscv_handle_type_attribute (tree *node > ATTRIBUTE_UNUSED, tree name, tree args, > return NULL_TREE; > } > > +static tree > +riscv_handle_rvv_vls_cc_attribute (tree *node, tree name, tree args, > + ATTRIBUTE_UNUSED int flags, > + bool *no_add_attrs) > +{ > + bool vls_cc_p = is_attribute_p ("vls_cc", name) > + || is_attribute_p ("riscv_vls_cc", name); > + > + if (!vls_cc_p) > + return NULL_TREE; > + > + riscv_cc cc = riscv_get_vls_cc_attr (args); > + > + if (cc == RISCV_CC_UNKNOWN) > + *no_add_attrs = true; > + > + return NULL_TREE; > +} > + > static tree > riscv_handle_rvv_vector_bits_attribute (tree *node, tree name, tree args, > ATTRIBUTE_UNUSED int flags, > @@ -11082,7 +11415,7 @@ riscv_asm_output_variant_cc (FILE *stream, const tree > decl, const char *name) > if (TREE_CODE (decl) == FUNCTION_DECL) > { > riscv_cc cc = (riscv_cc) fndecl_abi (decl).id (); > - if (cc == RISCV_CC_V) > + if (cc == RISCV_CC_V || riscv_vls_cc_p (cc)) > { > fprintf (stream, "\t.variant_cc\t"); > assemble_name (stream, name); > diff --git a/gcc/config/riscv/riscv.h b/gcc/config/riscv/riscv.h > index 9146571908f..a229928677f 100644 > --- a/gcc/config/riscv/riscv.h > +++ b/gcc/config/riscv/riscv.h > @@ -779,6 +779,17 @@ enum riscv_cc > { > RISCV_CC_BASE = 0, /* Base standard RISC-V ABI. */ > RISCV_CC_V, /* For functions that pass or return values in V registers. */ > + /* For functions that pass or return values in V registers. */ > + RISCV_CC_VLS_V_32, > + RISCV_CC_VLS_V_64, > + RISCV_CC_VLS_V_128, > + RISCV_CC_VLS_V_256, > + RISCV_CC_VLS_V_512, > + RISCV_CC_VLS_V_1024, > + RISCV_CC_VLS_V_2048, > + RISCV_CC_VLS_V_4096, > + RISCV_CC_VLS_V_8192, > + RISCV_CC_VLS_V_16384, > RISCV_CC_UNKNOWN > }; > > @@ -786,6 +797,8 @@ typedef struct { > /* The calling convention that current function used. */ > enum riscv_cc variant_cc; > > + unsigned int abi_vlen; > + > /* Number of integer registers used so far, up to MAX_ARGS_IN_REGISTERS. */ > unsigned int num_gprs; > > -- > 2.34.1 >
