RISC-V: Add runtime invariant support
RISC-V 'V' Extension support scalable vector like ARM SVE. To support RVV, we need to introduce runtime invariant. - For zve32*, the runtime invariant uses 32-bit chunk. - For zve64*, the runtime invariant uses 64-bit chunk. [1] https://github.com/riscv/riscv-v-spec/blob/master/v-spec.adoc#sec-vector-extensions This patch is preparing patch for RVV support. Because we didn't introduce vector machine_mode yet, it safe to just change HOST_WIDE_INT into poly_int. Also it safe to use "to_constant()" function for scalar operation. This patch has been tested by full dejagnu regression. gcc/ChangeLog: * config/riscv/predicates.md: Adjust runtime invariant. * config/riscv/riscv-modes.def (MAX_BITSIZE_MODE_ANY_MODE): New. (NUM_POLY_INT_COEFFS): New. * config/riscv/riscv-protos.h (riscv_initial_elimination_offset):Adjust runtime invariant. * config/riscv/riscv-sr.cc (riscv_remove_unneeded_save_restore_calls): Adjust runtime invariant. * config/riscv/riscv.cc (struct riscv_frame_info): Adjust runtime invariant. (enum riscv_microarchitecture_type): Ditto. (riscv_valid_offset_p): Ditto. (riscv_valid_lo_sum_p): Ditto. (riscv_address_insns): Ditto. (riscv_load_store_insns): Ditto. (riscv_legitimize_move): Ditto. (riscv_binary_cost): Ditto. (riscv_rtx_costs): Ditto. (riscv_output_move): Ditto. (riscv_extend_comparands): Ditto. (riscv_flatten_aggregate_field): Ditto. (riscv_get_arg_info): Ditto. (riscv_pass_by_reference): Ditto. (riscv_elf_select_rtx_section): Ditto. (riscv_stack_align): Ditto. (riscv_compute_frame_info): Ditto. (riscv_initial_elimination_offset): Ditto. (riscv_set_return_address): Ditto. (riscv_for_each_saved_reg): Ditto. (riscv_first_stack_step): Ditto. (riscv_expand_prologue): Ditto. (riscv_expand_epilogue): Ditto. (riscv_can_use_return_insn): Ditto. (riscv_secondary_memory_needed): Ditto. (riscv_hard_regno_nregs): Ditto. (riscv_convert_vector_bits): New. (riscv_option_override): Adjust runtime invariant. (riscv_promote_function_mode): Ditto. * config/riscv/riscv.h (POLY_SMALL_OPERAND_P): New. (BITS_PER_RISCV_VECTOR): New. (BYTES_PER_RISCV_VECTOR): New. * config/riscv/riscv.md: Adjust runtime invariant.
This commit is contained in:
parent
b7d62c551f
commit
3496ca4e65
7 changed files with 142 additions and 68 deletions
|
@ -71,7 +71,7 @@
|
|||
{
|
||||
/* Don't handle multi-word moves this way; we don't want to introduce
|
||||
the individual word-mode moves until after reload. */
|
||||
if (GET_MODE_SIZE (mode) > UNITS_PER_WORD)
|
||||
if (GET_MODE_SIZE (mode).to_constant () > UNITS_PER_WORD)
|
||||
return false;
|
||||
|
||||
/* Check whether the constant can be loaded in a single
|
||||
|
|
|
@ -21,3 +21,16 @@ along with GCC; see the file COPYING3. If not see
|
|||
|
||||
FLOAT_MODE (HF, 2, ieee_half_format);
|
||||
FLOAT_MODE (TF, 16, ieee_quad_format);
|
||||
|
||||
/* TODO: According to RISC-V 'V' ISA spec, the maximun vector length can
|
||||
be 65536 for a single vector register which means the vector mode in
|
||||
GCC can be maximum = 65536 * 8 bits (LMUL=8).
|
||||
However, 'GET_MODE_SIZE' is using poly_uint16/unsigned short which will
|
||||
overflow if we specify vector-length = 65536. To support this feature,
|
||||
we need to change the codes outside the RISC-V port. We will support it in
|
||||
the future. */
|
||||
#define MAX_BITSIZE_MODE_ANY_MODE (4096 * 8)
|
||||
|
||||
/* Coefficient 1 is multiplied by the number of 64-bit/32-bit chunks in a vector
|
||||
minus one. */
|
||||
#define NUM_POLY_INT_COEFFS 2
|
||||
|
|
|
@ -64,7 +64,7 @@ extern rtx riscv_legitimize_call_address (rtx);
|
|||
extern void riscv_set_return_address (rtx, rtx);
|
||||
extern bool riscv_expand_block_move (rtx, rtx, rtx);
|
||||
extern rtx riscv_return_addr (int, rtx);
|
||||
extern HOST_WIDE_INT riscv_initial_elimination_offset (int, int);
|
||||
extern poly_int64 riscv_initial_elimination_offset (int, int);
|
||||
extern void riscv_expand_prologue (void);
|
||||
extern void riscv_expand_epilogue (int);
|
||||
extern bool riscv_epilogue_uses (unsigned int);
|
||||
|
|
|
@ -247,7 +247,7 @@ riscv_remove_unneeded_save_restore_calls (void)
|
|||
/* We'll adjust stack size after this optimization, that require update every
|
||||
sp use site, which could be unsafe, so we decide to turn off this
|
||||
optimization if there are any arguments put on stack. */
|
||||
if (crtl->args.size != 0)
|
||||
if (known_ne (crtl->args.size, 0))
|
||||
return;
|
||||
|
||||
/* Will point to the first instruction of the function body, after the
|
||||
|
|
|
@ -100,7 +100,7 @@ enum riscv_address_type {
|
|||
/* Information about a function's frame layout. */
|
||||
struct GTY(()) riscv_frame_info {
|
||||
/* The size of the frame in bytes. */
|
||||
HOST_WIDE_INT total_size;
|
||||
poly_int64 total_size;
|
||||
|
||||
/* Bit X is set if the function saves or restores GPR X. */
|
||||
unsigned int mask;
|
||||
|
@ -112,17 +112,17 @@ struct GTY(()) riscv_frame_info {
|
|||
unsigned save_libcall_adjustment;
|
||||
|
||||
/* Offsets of fixed-point and floating-point save areas from frame bottom */
|
||||
HOST_WIDE_INT gp_sp_offset;
|
||||
HOST_WIDE_INT fp_sp_offset;
|
||||
poly_int64 gp_sp_offset;
|
||||
poly_int64 fp_sp_offset;
|
||||
|
||||
/* Offset of virtual frame pointer from stack pointer/frame bottom */
|
||||
HOST_WIDE_INT frame_pointer_offset;
|
||||
poly_int64 frame_pointer_offset;
|
||||
|
||||
/* Offset of hard frame pointer from stack pointer/frame bottom */
|
||||
HOST_WIDE_INT hard_frame_pointer_offset;
|
||||
poly_int64 hard_frame_pointer_offset;
|
||||
|
||||
/* The offset of arg_pointer_rtx from the bottom of the frame. */
|
||||
HOST_WIDE_INT arg_pointer_offset;
|
||||
poly_int64 arg_pointer_offset;
|
||||
};
|
||||
|
||||
enum riscv_privilege_levels {
|
||||
|
@ -255,6 +255,12 @@ static const struct riscv_tune_param *tune_param;
|
|||
/* Which automaton to use for tuning. */
|
||||
enum riscv_microarchitecture_type riscv_microarchitecture;
|
||||
|
||||
/* The number of chunks in a single vector register. */
|
||||
poly_uint16 riscv_vector_chunks;
|
||||
|
||||
/* The number of bytes in a vector chunk. */
|
||||
unsigned riscv_bytes_per_vector_chunk;
|
||||
|
||||
/* Index R is the smallest register class that contains register R. */
|
||||
const enum reg_class riscv_regno_to_class[FIRST_PSEUDO_REGISTER] = {
|
||||
GR_REGS, GR_REGS, GR_REGS, GR_REGS,
|
||||
|
@ -807,8 +813,8 @@ riscv_valid_offset_p (rtx x, machine_mode mode)
|
|||
|
||||
/* We may need to split multiword moves, so make sure that every word
|
||||
is accessible. */
|
||||
if (GET_MODE_SIZE (mode) > UNITS_PER_WORD
|
||||
&& !SMALL_OPERAND (INTVAL (x) + GET_MODE_SIZE (mode) - UNITS_PER_WORD))
|
||||
if (GET_MODE_SIZE (mode).to_constant () > UNITS_PER_WORD
|
||||
&& !SMALL_OPERAND (INTVAL (x) + GET_MODE_SIZE (mode).to_constant () - UNITS_PER_WORD))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
|
@ -872,7 +878,7 @@ riscv_valid_lo_sum_p (enum riscv_symbol_type sym_type, machine_mode mode,
|
|||
else
|
||||
{
|
||||
align = GET_MODE_ALIGNMENT (mode);
|
||||
size = GET_MODE_BITSIZE (mode);
|
||||
size = GET_MODE_BITSIZE (mode).to_constant ();
|
||||
}
|
||||
|
||||
/* We may need to split multiword moves, so make sure that each word
|
||||
|
@ -1013,7 +1019,7 @@ riscv_address_insns (rtx x, machine_mode mode, bool might_split_p)
|
|||
/* BLKmode is used for single unaligned loads and stores and should
|
||||
not count as a multiword mode. */
|
||||
if (mode != BLKmode && might_split_p)
|
||||
n += (GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
|
||||
n += (GET_MODE_SIZE (mode).to_constant () + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
|
||||
|
||||
if (addr.type == ADDRESS_LO_SUM)
|
||||
n += riscv_symbol_insns (addr.symbol_type) - 1;
|
||||
|
@ -1106,9 +1112,9 @@ riscv_load_store_insns (rtx mem, rtx_insn *insn)
|
|||
|
||||
/* Try to prove that INSN does not need to be split. */
|
||||
might_split_p = true;
|
||||
if (GET_MODE_BITSIZE (mode) <= 32)
|
||||
if (GET_MODE_BITSIZE (mode).to_constant () <= 32)
|
||||
might_split_p = false;
|
||||
else if (GET_MODE_BITSIZE (mode) == 64)
|
||||
else if (GET_MODE_BITSIZE (mode).to_constant () == 64)
|
||||
{
|
||||
set = single_set (insn);
|
||||
if (set && !riscv_split_64bit_move_p (SET_DEST (set), SET_SRC (set)))
|
||||
|
@ -1625,7 +1631,7 @@ riscv_legitimize_move (machine_mode mode, rtx dest, rtx src)
|
|||
(set (reg:QI target) (subreg:QI (reg:DI temp) 0))
|
||||
with auto-sign/zero extend. */
|
||||
if (GET_MODE_CLASS (mode) == MODE_INT
|
||||
&& GET_MODE_SIZE (mode) < UNITS_PER_WORD
|
||||
&& GET_MODE_SIZE (mode).to_constant () < UNITS_PER_WORD
|
||||
&& can_create_pseudo_p ()
|
||||
&& MEM_P (src))
|
||||
{
|
||||
|
@ -1650,7 +1656,7 @@ riscv_legitimize_move (machine_mode mode, rtx dest, rtx src)
|
|||
improve cse. */
|
||||
machine_mode promoted_mode = mode;
|
||||
if (GET_MODE_CLASS (mode) == MODE_INT
|
||||
&& GET_MODE_SIZE (mode) < UNITS_PER_WORD)
|
||||
&& GET_MODE_SIZE (mode).to_constant () < UNITS_PER_WORD)
|
||||
promoted_mode = word_mode;
|
||||
|
||||
if (splittable_const_int_operand (src, mode))
|
||||
|
@ -1748,7 +1754,7 @@ riscv_immediate_operand_p (int code, HOST_WIDE_INT x)
|
|||
static int
|
||||
riscv_binary_cost (rtx x, int single_insns, int double_insns)
|
||||
{
|
||||
if (GET_MODE_SIZE (GET_MODE (x)) == UNITS_PER_WORD * 2)
|
||||
if (GET_MODE_SIZE (GET_MODE (x)).to_constant () == UNITS_PER_WORD * 2)
|
||||
return COSTS_N_INSNS (double_insns);
|
||||
return COSTS_N_INSNS (single_insns);
|
||||
}
|
||||
|
@ -1881,7 +1887,7 @@ riscv_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno ATTRIBUTE_UN
|
|||
return false;
|
||||
|
||||
case NOT:
|
||||
*total = COSTS_N_INSNS (GET_MODE_SIZE (mode) > UNITS_PER_WORD ? 2 : 1);
|
||||
*total = COSTS_N_INSNS (GET_MODE_SIZE (mode).to_constant () > UNITS_PER_WORD ? 2 : 1);
|
||||
return false;
|
||||
|
||||
case AND:
|
||||
|
@ -2128,7 +2134,7 @@ riscv_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno ATTRIBUTE_UN
|
|||
if (float_mode_p)
|
||||
*total = tune_param->fp_add[mode == DFmode];
|
||||
else
|
||||
*total = COSTS_N_INSNS (GET_MODE_SIZE (mode) > UNITS_PER_WORD ? 4 : 1);
|
||||
*total = COSTS_N_INSNS (GET_MODE_SIZE (mode).to_constant () > UNITS_PER_WORD ? 4 : 1);
|
||||
return false;
|
||||
|
||||
case MULT:
|
||||
|
@ -2137,7 +2143,7 @@ riscv_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno ATTRIBUTE_UN
|
|||
else if (!TARGET_MUL)
|
||||
/* Estimate the cost of a library call. */
|
||||
*total = COSTS_N_INSNS (speed ? 32 : 6);
|
||||
else if (GET_MODE_SIZE (mode) > UNITS_PER_WORD)
|
||||
else if (GET_MODE_SIZE (mode).to_constant () > UNITS_PER_WORD)
|
||||
*total = 3 * tune_param->int_mul[0] + COSTS_N_INSNS (2);
|
||||
else if (!speed)
|
||||
*total = COSTS_N_INSNS (1);
|
||||
|
@ -2301,8 +2307,8 @@ riscv_output_move (rtx dest, rtx src)
|
|||
dest_code = GET_CODE (dest);
|
||||
src_code = GET_CODE (src);
|
||||
mode = GET_MODE (dest);
|
||||
dbl_p = (GET_MODE_SIZE (mode) == 8);
|
||||
width = GET_MODE_SIZE (mode);
|
||||
dbl_p = (GET_MODE_SIZE (mode).to_constant () == 8);
|
||||
width = GET_MODE_SIZE (mode).to_constant ();
|
||||
|
||||
if (dbl_p && riscv_split_64bit_move_p (dest, src))
|
||||
return "#";
|
||||
|
@ -2578,7 +2584,7 @@ static void
|
|||
riscv_extend_comparands (rtx_code code, rtx *op0, rtx *op1)
|
||||
{
|
||||
/* Comparisons consider all XLEN bits, so extend sub-XLEN values. */
|
||||
if (GET_MODE_SIZE (word_mode) > GET_MODE_SIZE (GET_MODE (*op0)))
|
||||
if (GET_MODE_SIZE (word_mode) > GET_MODE_SIZE (GET_MODE (*op0)).to_constant ())
|
||||
{
|
||||
/* It is more profitable to zero-extend QImode values. But not if the
|
||||
first operand has already been sign-extended, and the second one is
|
||||
|
@ -2941,7 +2947,7 @@ riscv_flatten_aggregate_field (const_tree type,
|
|||
if (n != 0)
|
||||
return -1;
|
||||
|
||||
HOST_WIDE_INT elt_size = GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (type)));
|
||||
HOST_WIDE_INT elt_size = GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (type))).to_constant ();
|
||||
|
||||
if (elt_size <= UNITS_PER_FP_ARG)
|
||||
{
|
||||
|
@ -2959,9 +2965,9 @@ riscv_flatten_aggregate_field (const_tree type,
|
|||
default:
|
||||
if (n < 2
|
||||
&& ((SCALAR_FLOAT_TYPE_P (type)
|
||||
&& GET_MODE_SIZE (TYPE_MODE (type)) <= UNITS_PER_FP_ARG)
|
||||
&& GET_MODE_SIZE (TYPE_MODE (type)).to_constant () <= UNITS_PER_FP_ARG)
|
||||
|| (INTEGRAL_TYPE_P (type)
|
||||
&& GET_MODE_SIZE (TYPE_MODE (type)) <= UNITS_PER_WORD)))
|
||||
&& GET_MODE_SIZE (TYPE_MODE (type)).to_constant () <= UNITS_PER_WORD)))
|
||||
{
|
||||
fields[n].type = type;
|
||||
fields[n].offset = offset;
|
||||
|
@ -3197,7 +3203,7 @@ riscv_get_arg_info (struct riscv_arg_info *info, const CUMULATIVE_ARGS *cum,
|
|||
}
|
||||
|
||||
/* Work out the size of the argument. */
|
||||
num_bytes = type ? int_size_in_bytes (type) : GET_MODE_SIZE (mode);
|
||||
num_bytes = type ? int_size_in_bytes (type) : GET_MODE_SIZE (mode).to_constant ();
|
||||
num_words = (num_bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
|
||||
|
||||
/* Doubleword-aligned varargs start on an even register boundary. */
|
||||
|
@ -3291,7 +3297,7 @@ riscv_function_value (const_tree type, const_tree func, machine_mode mode)
|
|||
static bool
|
||||
riscv_pass_by_reference (cumulative_args_t cum_v, const function_arg_info &arg)
|
||||
{
|
||||
HOST_WIDE_INT size = arg.type_size_in_bytes ();
|
||||
HOST_WIDE_INT size = arg.type_size_in_bytes ().to_constant ();;
|
||||
struct riscv_arg_info info;
|
||||
CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
|
||||
|
||||
|
@ -3920,7 +3926,7 @@ riscv_elf_select_rtx_section (machine_mode mode, rtx x,
|
|||
{
|
||||
section *s = default_elf_select_rtx_section (mode, x, align);
|
||||
|
||||
if (riscv_size_ok_for_small_data_p (GET_MODE_SIZE (mode)))
|
||||
if (riscv_size_ok_for_small_data_p (GET_MODE_SIZE (mode).to_constant ()))
|
||||
{
|
||||
if (startswith (s->named.name, ".rodata.cst"))
|
||||
{
|
||||
|
@ -4072,11 +4078,24 @@ riscv_save_libcall_count (unsigned mask)
|
|||
|
||||
static HOST_WIDE_INT riscv_first_stack_step (struct riscv_frame_info *frame);
|
||||
|
||||
/* Handle stack align for poly_int. */
|
||||
static poly_int64
|
||||
riscv_stack_align (poly_int64 value)
|
||||
{
|
||||
return aligned_upper_bound (value, PREFERRED_STACK_BOUNDARY / 8);
|
||||
}
|
||||
|
||||
static HOST_WIDE_INT
|
||||
riscv_stack_align (HOST_WIDE_INT value)
|
||||
{
|
||||
return RISCV_STACK_ALIGN (value);
|
||||
}
|
||||
|
||||
static void
|
||||
riscv_compute_frame_info (void)
|
||||
{
|
||||
struct riscv_frame_info *frame;
|
||||
HOST_WIDE_INT offset;
|
||||
poly_int64 offset;
|
||||
bool interrupt_save_prologue_temp = false;
|
||||
unsigned int regno, i, num_x_saved = 0, num_f_saved = 0;
|
||||
|
||||
|
@ -4087,7 +4106,7 @@ riscv_compute_frame_info (void)
|
|||
if (cfun->machine->interrupt_handler_p)
|
||||
{
|
||||
HOST_WIDE_INT step1 = riscv_first_stack_step (frame);
|
||||
if (! SMALL_OPERAND (frame->total_size - step1))
|
||||
if (! POLY_SMALL_OPERAND_P ((frame->total_size - step1)))
|
||||
interrupt_save_prologue_temp = true;
|
||||
}
|
||||
|
||||
|
@ -4117,23 +4136,23 @@ riscv_compute_frame_info (void)
|
|||
}
|
||||
|
||||
/* At the bottom of the frame are any outgoing stack arguments. */
|
||||
offset = RISCV_STACK_ALIGN (crtl->outgoing_args_size);
|
||||
offset = riscv_stack_align (crtl->outgoing_args_size);
|
||||
/* Next are local stack variables. */
|
||||
offset += RISCV_STACK_ALIGN (get_frame_size ());
|
||||
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 FPRs. */
|
||||
if (frame->fmask)
|
||||
offset += RISCV_STACK_ALIGN (num_f_saved * UNITS_PER_FP_REG);
|
||||
offset += riscv_stack_align (num_f_saved * UNITS_PER_FP_REG);
|
||||
frame->fp_sp_offset = offset - UNITS_PER_FP_REG;
|
||||
/* Next are the callee-saved GPRs. */
|
||||
if (frame->mask)
|
||||
{
|
||||
unsigned x_save_size = RISCV_STACK_ALIGN (num_x_saved * UNITS_PER_WORD);
|
||||
unsigned x_save_size = riscv_stack_align (num_x_saved * UNITS_PER_WORD);
|
||||
unsigned num_save_restore = 1 + riscv_save_libcall_count (frame->mask);
|
||||
|
||||
/* Only use save/restore routines if they don't alter the stack size. */
|
||||
if (RISCV_STACK_ALIGN (num_save_restore * UNITS_PER_WORD) == x_save_size)
|
||||
if (riscv_stack_align (num_save_restore * UNITS_PER_WORD) == x_save_size)
|
||||
{
|
||||
/* Libcall saves/restores 3 registers at once, so we need to
|
||||
allocate 12 bytes for callee-saved register. */
|
||||
|
@ -4149,9 +4168,9 @@ riscv_compute_frame_info (void)
|
|||
/* The hard frame pointer points above the callee-saved GPRs. */
|
||||
frame->hard_frame_pointer_offset = offset;
|
||||
/* Above the hard frame pointer is the callee-allocated varags save area. */
|
||||
offset += RISCV_STACK_ALIGN (cfun->machine->varargs_size);
|
||||
offset += riscv_stack_align (cfun->machine->varargs_size);
|
||||
/* Next is the callee-allocated area for pretend stack arguments. */
|
||||
offset += RISCV_STACK_ALIGN (crtl->args.pretend_args_size);
|
||||
offset += riscv_stack_align (crtl->args.pretend_args_size);
|
||||
/* Arg pointer must be below pretend args, but must be above alignment
|
||||
padding. */
|
||||
frame->arg_pointer_offset = offset - crtl->args.pretend_args_size;
|
||||
|
@ -4159,7 +4178,7 @@ riscv_compute_frame_info (void)
|
|||
/* Next points the incoming stack pointer and any incoming arguments. */
|
||||
|
||||
/* Only use save/restore routines when the GPRs are atop the frame. */
|
||||
if (frame->hard_frame_pointer_offset != frame->total_size)
|
||||
if (known_ne (frame->hard_frame_pointer_offset, frame->total_size))
|
||||
frame->save_libcall_adjustment = 0;
|
||||
}
|
||||
|
||||
|
@ -4176,10 +4195,10 @@ riscv_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to)
|
|||
or argument pointer. TO is either the stack pointer or hard frame
|
||||
pointer. */
|
||||
|
||||
HOST_WIDE_INT
|
||||
poly_int64
|
||||
riscv_initial_elimination_offset (int from, int to)
|
||||
{
|
||||
HOST_WIDE_INT src, dest;
|
||||
poly_int64 src, dest;
|
||||
|
||||
riscv_compute_frame_info ();
|
||||
|
||||
|
@ -4223,7 +4242,7 @@ riscv_set_return_address (rtx address, rtx scratch)
|
|||
|
||||
gcc_assert (BITSET_P (cfun->machine->frame.mask, RETURN_ADDR_REGNUM));
|
||||
slot_address = riscv_add_offset (scratch, stack_pointer_rtx,
|
||||
cfun->machine->frame.gp_sp_offset);
|
||||
cfun->machine->frame.gp_sp_offset.to_constant());
|
||||
riscv_emit_move (gen_frame_mem (GET_MODE (address), slot_address), address);
|
||||
}
|
||||
|
||||
|
@ -4250,13 +4269,13 @@ riscv_save_restore_reg (machine_mode mode, int regno,
|
|||
of the frame. */
|
||||
|
||||
static void
|
||||
riscv_for_each_saved_reg (HOST_WIDE_INT sp_offset, riscv_save_restore_fn fn,
|
||||
riscv_for_each_saved_reg (poly_int64 sp_offset, riscv_save_restore_fn fn,
|
||||
bool epilogue, bool maybe_eh_return)
|
||||
{
|
||||
HOST_WIDE_INT offset;
|
||||
|
||||
/* Save the link register and s-registers. */
|
||||
offset = cfun->machine->frame.gp_sp_offset - sp_offset;
|
||||
offset = (cfun->machine->frame.gp_sp_offset - sp_offset).to_constant ();
|
||||
for (unsigned int regno = GP_REG_FIRST; regno <= GP_REG_LAST; regno++)
|
||||
if (BITSET_P (cfun->machine->frame.mask, regno - GP_REG_FIRST))
|
||||
{
|
||||
|
@ -4287,14 +4306,14 @@ riscv_for_each_saved_reg (HOST_WIDE_INT sp_offset, riscv_save_restore_fn fn,
|
|||
|
||||
/* This loop must iterate over the same space as its companion in
|
||||
riscv_compute_frame_info. */
|
||||
offset = cfun->machine->frame.fp_sp_offset - sp_offset;
|
||||
offset = (cfun->machine->frame.fp_sp_offset - sp_offset).to_constant ();
|
||||
for (unsigned int regno = FP_REG_FIRST; regno <= FP_REG_LAST; regno++)
|
||||
if (BITSET_P (cfun->machine->frame.fmask, regno - FP_REG_FIRST))
|
||||
{
|
||||
machine_mode mode = TARGET_DOUBLE_FLOAT ? DFmode : SFmode;
|
||||
|
||||
riscv_save_restore_reg (mode, regno, offset, fn);
|
||||
offset -= GET_MODE_SIZE (mode);
|
||||
offset -= GET_MODE_SIZE (mode).to_constant ();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4336,21 +4355,21 @@ riscv_restore_reg (rtx reg, rtx mem)
|
|||
static HOST_WIDE_INT
|
||||
riscv_first_stack_step (struct riscv_frame_info *frame)
|
||||
{
|
||||
if (SMALL_OPERAND (frame->total_size))
|
||||
return frame->total_size;
|
||||
if (SMALL_OPERAND (frame->total_size.to_constant()))
|
||||
return frame->total_size.to_constant();
|
||||
|
||||
HOST_WIDE_INT min_first_step =
|
||||
RISCV_STACK_ALIGN (frame->total_size - frame->fp_sp_offset);
|
||||
RISCV_STACK_ALIGN ((frame->total_size - frame->fp_sp_offset).to_constant());
|
||||
HOST_WIDE_INT max_first_step = IMM_REACH / 2 - PREFERRED_STACK_BOUNDARY / 8;
|
||||
HOST_WIDE_INT min_second_step = frame->total_size - max_first_step;
|
||||
HOST_WIDE_INT min_second_step = frame->total_size.to_constant() - max_first_step;
|
||||
gcc_assert (min_first_step <= max_first_step);
|
||||
|
||||
/* As an optimization, use the least-significant bits of the total frame
|
||||
size, so that the second adjustment step is just LUI + ADD. */
|
||||
if (!SMALL_OPERAND (min_second_step)
|
||||
&& frame->total_size % IMM_REACH < IMM_REACH / 2
|
||||
&& frame->total_size % IMM_REACH >= min_first_step)
|
||||
return frame->total_size % IMM_REACH;
|
||||
&& frame->total_size.to_constant() % IMM_REACH < IMM_REACH / 2
|
||||
&& frame->total_size.to_constant() % IMM_REACH >= min_first_step)
|
||||
return frame->total_size.to_constant() % IMM_REACH;
|
||||
|
||||
if (TARGET_RVC)
|
||||
{
|
||||
|
@ -4423,7 +4442,7 @@ void
|
|||
riscv_expand_prologue (void)
|
||||
{
|
||||
struct riscv_frame_info *frame = &cfun->machine->frame;
|
||||
HOST_WIDE_INT size = frame->total_size;
|
||||
HOST_WIDE_INT size = frame->total_size.to_constant ();
|
||||
unsigned mask = frame->mask;
|
||||
rtx insn;
|
||||
|
||||
|
@ -4466,7 +4485,7 @@ riscv_expand_prologue (void)
|
|||
if (frame_pointer_needed)
|
||||
{
|
||||
insn = gen_add3_insn (hard_frame_pointer_rtx, stack_pointer_rtx,
|
||||
GEN_INT (frame->hard_frame_pointer_offset - size));
|
||||
GEN_INT ((frame->hard_frame_pointer_offset - size).to_constant ()));
|
||||
RTX_FRAME_RELATED_P (emit_insn (insn)) = 1;
|
||||
|
||||
riscv_emit_stack_tie ();
|
||||
|
@ -4532,7 +4551,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 step1 = frame->total_size;
|
||||
HOST_WIDE_INT step1 = frame->total_size.to_constant ();
|
||||
HOST_WIDE_INT step2 = 0;
|
||||
bool use_restore_libcall = ((style == NORMAL_RETURN)
|
||||
&& riscv_use_save_libcall (frame));
|
||||
|
@ -4540,8 +4559,8 @@ riscv_expand_epilogue (int style)
|
|||
rtx insn;
|
||||
|
||||
/* We need to add memory barrier to prevent read from deallocated stack. */
|
||||
bool need_barrier_p = (get_frame_size ()
|
||||
+ cfun->machine->frame.arg_pointer_offset) != 0;
|
||||
bool need_barrier_p
|
||||
= known_ne (get_frame_size (), cfun->machine->frame.arg_pointer_offset);
|
||||
|
||||
if (cfun->machine->naked_p)
|
||||
{
|
||||
|
@ -4568,7 +4587,7 @@ riscv_expand_epilogue (int style)
|
|||
riscv_emit_stack_tie ();
|
||||
need_barrier_p = false;
|
||||
|
||||
rtx adjust = GEN_INT (-frame->hard_frame_pointer_offset);
|
||||
rtx adjust = GEN_INT (-frame->hard_frame_pointer_offset.to_constant ());
|
||||
if (!SMALL_OPERAND (INTVAL (adjust)))
|
||||
{
|
||||
riscv_emit_move (RISCV_PROLOGUE_TEMP (Pmode), adjust);
|
||||
|
@ -4582,7 +4601,7 @@ riscv_expand_epilogue (int style)
|
|||
rtx dwarf = NULL_RTX;
|
||||
rtx cfa_adjust_value = gen_rtx_PLUS (
|
||||
Pmode, hard_frame_pointer_rtx,
|
||||
GEN_INT (-frame->hard_frame_pointer_offset));
|
||||
GEN_INT (-frame->hard_frame_pointer_offset.to_constant ()));
|
||||
rtx cfa_adjust_rtx = gen_rtx_SET (stack_pointer_rtx, cfa_adjust_value);
|
||||
dwarf = alloc_reg_note (REG_CFA_ADJUST_CFA, cfa_adjust_rtx, dwarf);
|
||||
RTX_FRAME_RELATED_P (insn) = 1;
|
||||
|
@ -4599,7 +4618,7 @@ riscv_expand_epilogue (int style)
|
|||
}
|
||||
|
||||
/* Set TARGET to BASE + STEP1. */
|
||||
if (step1 > 0)
|
||||
if (known_gt (step1, 0))
|
||||
{
|
||||
/* Emit a barrier to prevent loads from a deallocated stack. */
|
||||
riscv_emit_stack_tie ();
|
||||
|
@ -4725,7 +4744,7 @@ riscv_epilogue_uses (unsigned int regno)
|
|||
bool
|
||||
riscv_can_use_return_insn (void)
|
||||
{
|
||||
return (reload_completed && cfun->machine->frame.total_size == 0
|
||||
return (reload_completed && known_eq (cfun->machine->frame.total_size, 0)
|
||||
&& ! cfun->machine->interrupt_handler_p);
|
||||
}
|
||||
|
||||
|
@ -4825,7 +4844,7 @@ static bool
|
|||
riscv_secondary_memory_needed (machine_mode mode, reg_class_t class1,
|
||||
reg_class_t class2)
|
||||
{
|
||||
return (GET_MODE_SIZE (mode) > UNITS_PER_WORD
|
||||
return (GET_MODE_SIZE (mode).to_constant () > UNITS_PER_WORD
|
||||
&& (class1 == FP_REGS) != (class2 == FP_REGS));
|
||||
}
|
||||
|
||||
|
@ -4848,10 +4867,10 @@ static unsigned int
|
|||
riscv_hard_regno_nregs (unsigned int regno, machine_mode mode)
|
||||
{
|
||||
if (FP_REG_P (regno))
|
||||
return (GET_MODE_SIZE (mode) + UNITS_PER_FP_REG - 1) / UNITS_PER_FP_REG;
|
||||
return (GET_MODE_SIZE (mode).to_constant () + UNITS_PER_FP_REG - 1) / UNITS_PER_FP_REG;
|
||||
|
||||
/* All other registers are word-sized. */
|
||||
return (GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
|
||||
return (GET_MODE_SIZE (mode).to_constant () + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
|
||||
}
|
||||
|
||||
/* Implement TARGET_HARD_REGNO_MODE_OK. */
|
||||
|
@ -5058,6 +5077,37 @@ riscv_init_machine_status (void)
|
|||
return ggc_cleared_alloc<machine_function> ();
|
||||
}
|
||||
|
||||
/* Return the VLEN value associated with -march.
|
||||
TODO: So far we only support length-agnostic value. */
|
||||
static poly_uint16
|
||||
riscv_convert_vector_bits (void)
|
||||
{
|
||||
/* The runtime invariant is only meaningful when vector is enabled. */
|
||||
if (!TARGET_VECTOR)
|
||||
return 0;
|
||||
|
||||
if (TARGET_VECTOR_ELEN_64 || TARGET_VECTOR_ELEN_FP_64)
|
||||
{
|
||||
/* When targetting Zve64* (ELEN = 64) extensions, we should use 64-bit
|
||||
chunk size. Runtime invariant: The single indeterminate represent the
|
||||
number of 64-bit chunks in a vector beyond minimum length of 64 bits.
|
||||
Thus the number of bytes in a vector is 8 + 8 * x1 which is
|
||||
riscv_vector_chunks * 8 = poly_int (8, 8). */
|
||||
riscv_bytes_per_vector_chunk = 8;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* When targetting Zve32* (ELEN = 32) extensions, we should use 32-bit
|
||||
chunk size. Runtime invariant: The single indeterminate represent the
|
||||
number of 32-bit chunks in a vector beyond minimum length of 32 bits.
|
||||
Thus the number of bytes in a vector is 4 + 4 * x1 which is
|
||||
riscv_vector_chunks * 4 = poly_int (4, 4). */
|
||||
riscv_bytes_per_vector_chunk = 4;
|
||||
}
|
||||
|
||||
return poly_uint16 (1, 1);
|
||||
}
|
||||
|
||||
/* Implement TARGET_OPTION_OVERRIDE. */
|
||||
|
||||
static void
|
||||
|
@ -5204,6 +5254,8 @@ riscv_option_override (void)
|
|||
riscv_stack_protector_guard_offset = offs;
|
||||
}
|
||||
|
||||
/* Convert -march to a chunks count. */
|
||||
riscv_vector_chunks = riscv_convert_vector_bits ();
|
||||
}
|
||||
|
||||
/* Implement TARGET_CONDITIONAL_REGISTER_USAGE. */
|
||||
|
@ -5561,7 +5613,7 @@ riscv_promote_function_mode (const_tree type ATTRIBUTE_UNUSED,
|
|||
return promote_mode (type, mode, punsignedp);
|
||||
|
||||
unsignedp = *punsignedp;
|
||||
PROMOTE_MODE (mode, unsignedp, type);
|
||||
PROMOTE_MODE (as_a <scalar_mode> (mode), unsignedp, type);
|
||||
*punsignedp = unsignedp;
|
||||
return mode;
|
||||
}
|
||||
|
|
|
@ -522,6 +522,10 @@ enum reg_class
|
|||
#define SMALL_OPERAND(VALUE) \
|
||||
((unsigned HOST_WIDE_INT) (VALUE) + IMM_REACH/2 < IMM_REACH)
|
||||
|
||||
#define POLY_SMALL_OPERAND_P(POLY_VALUE) \
|
||||
(POLY_VALUE.is_constant () ? \
|
||||
SMALL_OPERAND (POLY_VALUE.to_constant ()) : false)
|
||||
|
||||
/* True if VALUE can be loaded into a register using LUI. */
|
||||
|
||||
#define LUI_OPERAND(VALUE) \
|
||||
|
@ -952,6 +956,11 @@ while (0)
|
|||
extern const enum reg_class riscv_regno_to_class[];
|
||||
extern bool riscv_slow_unaligned_access_p;
|
||||
extern unsigned riscv_stack_boundary;
|
||||
extern unsigned riscv_bytes_per_vector_chunk;
|
||||
extern poly_uint16 riscv_vector_chunks;
|
||||
/* The number of bits and bytes in a RVV vector. */
|
||||
#define BITS_PER_RISCV_VECTOR (poly_uint16 (riscv_vector_chunks * riscv_bytes_per_vector_chunk * 8))
|
||||
#define BYTES_PER_RISCV_VECTOR (poly_uint16 (riscv_vector_chunks * riscv_bytes_per_vector_chunk))
|
||||
#endif
|
||||
|
||||
#define ASM_PREFERRED_EH_DATA_FORMAT(CODE,GLOBAL) \
|
||||
|
|
|
@ -2162,7 +2162,7 @@
|
|||
(lshiftrt:GPR (match_dup 3) (match_dup 2)))]
|
||||
{
|
||||
/* Op2 is a VOIDmode constant, so get the mode size from op1. */
|
||||
operands[2] = GEN_INT (GET_MODE_BITSIZE (GET_MODE (operands[1]))
|
||||
operands[2] = GEN_INT (GET_MODE_BITSIZE (GET_MODE (operands[1])).to_constant ()
|
||||
- exact_log2 (INTVAL (operands[2]) + 1));
|
||||
})
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue