From patchwork Wed Aug 17 07:19:50 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "juzhe.zhong@rivai.ai" X-Patchwork-Id: 56800 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id A89993857C44 for ; Wed, 17 Aug 2022 07:20:33 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from smtpbg153.qq.com (smtpbg153.qq.com [13.245.218.24]) by sourceware.org (Postfix) with ESMTPS id 3E8253858D1E for ; Wed, 17 Aug 2022 07:20:09 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 3E8253858D1E Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=rivai.ai Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=rivai.ai X-QQ-mid: bizesmtp67t1660720795t8dneu0l Received: from server1.localdomain ( [42.247.22.66]) by bizesmtp.qq.com (ESMTP) with id ; Wed, 17 Aug 2022 15:19:53 +0800 (CST) X-QQ-SSF: 01400000002000C0H000B00A0000000 X-QQ-FEAT: VNWd8gjdZNqsE+PbWxcK4mQgNNZqVXAey7+riSJLJwAGJBMVq84M69soQdI1D /nebeKn6iwDgamByQ44/j+URn0Fi5XvuvYIigztkbSJMoeJRtMZ28cJk5nS8eatBvrhA+Q5 Cc+aqG2xX2uAnWOYQV3yj2ODLBrltkawyDGMzqgVLzI1/9DstBZJT8mrr/SpZ+4bDlzC+0o dX4jSptKWQ+W5SL+BQqrTrwQAywARdrIWhIE9EP6qqaqgNM/VGbzwrXRv37JBmVzi6Fxjkn lA+jE3fvLBGHeUuwQAwHsG60nkirXXKttVzTCjxJXFI3H7tZfw6WFg4qAokxhZxg+rNmpzJ aIauUsZQw8aBrksHd8CWuW9JusIlGFq6fseo2lkZuGQq++hMjlI/dEKsa1LY6keh9lXbi4j X-QQ-GoodBg: 2 From: juzhe.zhong@rivai.ai To: gcc-patches@gcc.gnu.org Subject: [PATCH] RISC-V: Add runtime invariant support Date: Wed, 17 Aug 2022 15:19:50 +0800 Message-Id: <20220817071950.271762-1-juzhe.zhong@rivai.ai> X-Mailer: git-send-email 2.36.1 MIME-Version: 1.0 X-QQ-SENDSIZE: 520 Feedback-ID: bizesmtp:rivai.ai:qybglogicsvr:qybglogicsvr7 X-Spam-Status: No, score=-11.9 required=5.0 tests=BAYES_00, GIT_PATCH_0, KAM_DMARC_STATUS, RCVD_IN_DNSWL_NONE, SPF_HELO_PASS, SPF_PASS, TXREP, T_SCC_BODY_TEXT_LINE, URIBL_BLACK autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: zhongjuzhe , kito.cheng@gmail.com, andrew@sifive.com Errors-To: gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org Sender: "Gcc-patches" From: zhongjuzhe 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. --- gcc/config/riscv/predicates.md | 2 +- gcc/config/riscv/riscv-modes.def | 12 ++ gcc/config/riscv/riscv-protos.h | 2 +- gcc/config/riscv/riscv-sr.cc | 2 +- gcc/config/riscv/riscv.cc | 181 ++++++++++++++++++++----------- gcc/config/riscv/riscv.h | 9 ++ gcc/config/riscv/riscv.md | 2 +- 7 files changed, 142 insertions(+), 68 deletions(-) diff --git a/gcc/config/riscv/predicates.md b/gcc/config/riscv/predicates.md index e98db2cb574..79e0c1d5589 100644 --- a/gcc/config/riscv/predicates.md +++ b/gcc/config/riscv/predicates.md @@ -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 diff --git a/gcc/config/riscv/riscv-modes.def b/gcc/config/riscv/riscv-modes.def index 5cf2fc8e9e6..b47909ef78b 100644 --- a/gcc/config/riscv/riscv-modes.def +++ b/gcc/config/riscv/riscv-modes.def @@ -21,3 +21,15 @@ 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 \ No newline at end of file diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h index 20c2381c21a..2bc0ef06f93 100644 --- a/gcc/config/riscv/riscv-protos.h +++ b/gcc/config/riscv/riscv-protos.h @@ -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); diff --git a/gcc/config/riscv/riscv-sr.cc b/gcc/config/riscv/riscv-sr.cc index 694f90c1583..7248f04d68f 100644 --- a/gcc/config/riscv/riscv-sr.cc +++ b/gcc/config/riscv/riscv-sr.cc @@ -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 diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc index 9d70974c893..5ae3e7fe857 100644 --- a/gcc/config/riscv/riscv.cc +++ b/gcc/config/riscv/riscv.cc @@ -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,38 @@ riscv_init_machine_status (void) return ggc_cleared_alloc (); } +/* 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 +5255,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 +5614,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 (mode), unsignedp, type); *punsignedp = unsignedp; return mode; } diff --git a/gcc/config/riscv/riscv.h b/gcc/config/riscv/riscv.h index 6f7f4d3fbdc..4b07c5487c6 100644 --- a/gcc/config/riscv/riscv.h +++ b/gcc/config/riscv/riscv.h @@ -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) \ diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md index 493f00cdb80..c517ae0d0f7 100644 --- a/gcc/config/riscv/riscv.md +++ b/gcc/config/riscv/riscv.md @@ -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)); })