From patchwork Tue Aug 29 08:37:44 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Fei Gao X-Patchwork-Id: 1827137 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=8.43.85.97; helo=server2.sourceware.org; envelope-from=gcc-patches-bounces+incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=patchwork.ozlabs.org) Received: from server2.sourceware.org (ip-8-43-85-97.sourceware.org [8.43.85.97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4RZgnX4z8Jz1yfy for ; Tue, 29 Aug 2023 18:38:56 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id B6E64385700D for ; Tue, 29 Aug 2023 08:38:54 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from zg8tndyumtaxlji0oc4xnzya.icoremail.net (zg8tndyumtaxlji0oc4xnzya.icoremail.net [46.101.248.176]) by sourceware.org (Postfix) with ESMTP id C55EC3858D33 for ; Tue, 29 Aug 2023 08:38:04 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org C55EC3858D33 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=eswincomputing.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=eswincomputing.com Received: from localhost.localdomain (unknown [10.12.130.31]) by app2 (Coremail) with SMTP id EggMCgB3vpRmru1k10lCAA--.2645S5; Tue, 29 Aug 2023 16:37:59 +0800 (CST) From: Fei Gao To: gcc-patches@gcc.gnu.org Subject: [PATCH 1/3] [V6] [RISC-V] support cm.push cm.pop cm.popret in zcmp Date: Tue, 29 Aug 2023 08:37:44 +0000 Message-Id: <20230829083746.1458-2-gaofei@eswincomputing.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20230829083746.1458-1-gaofei@eswincomputing.com> References: <20230829083746.1458-1-gaofei@eswincomputing.com> X-CM-TRANSID: EggMCgB3vpRmru1k10lCAA--.2645S5 X-Coremail-Antispam: 1UD129KBjvAXoWDZr4DZF48GF4fKF47Gr4kZwb_yoW3AF1Duo W0ganYyw1rGryDu395u3y3tw1rJr4vgr48X3Z5Zr4UA3Wxtw47tr9I9an3WF17Gr13Xay8 XFs2vr1vyay3Jwnxn29KB7ZKAUJUUUUU529EdanIXcx71UUUUU7v73VFW2AGmfu7bjvjm3 AaLaJ3UjIYCTnIWjp_UUUOe7AC8VAFwI0_Xr0_Wr1l1xkIjI8I6I8E6xAIw20EY4v20xva j40_Wr0E3s1l1IIY67AEw4v_Jr0_Jr4l82xGYIkIc2x26280x7IE14v26r18M28IrcIa0x kI8VCY1x0267AKxVWUCVW8JwA2ocxC64kIII0Yj41l84x0c7CEw4AK67xGY2AK021l84AC jcxK6xIIjxv20xvE14v26w1j6s0DM28EF7xvwVC0I7IYx2IY6xkF7I0E14v26r4UJVWxJr 1l84ACjcxK6I8E87Iv67AKxVW0oVCq3wA2z4x0Y4vEx4A2jsIEc7CjxVAFwI0_GcCE3s1l e2I262IYc4CY6c8Ij28IcVAaY2xG8wAqx4xG64xvF2IEw4CE5I8CrVC2j2WlYx0E2Ix0cI 8IcVAFwI0_Jr0_Jr4lYx0Ex4A2jsIE14v26r1j6r4UMcvjeVCFs4IE7xkEbVWUJVW8JwAC jcxG0xvY0x0EwIxGrwACjI8F5VA0II8E6IAqYI8I648v4I1lc7CjxVAKzI0EY4vE52x082 I5MxkIecxEwVCm-wCF04k20xvY0x0EwIxGrwCFx2IqxVCFs4IE7xkEbVWUJVW8JwC20s02 6c02F40E14v26r1j6r18MI8I3I0E7480Y4vE14v26r106r1rMI8E67AF67kF1VAFwI0_Jw 0_GFylIxkGc2Ij64vIr41lIxAIcVC0I7IYx2IY67AKxVWUJVWUCwCI42IY6xIIjxv20xvE c7CjxVAFwI0_Gr0_Cr1lIxAIcVCF04k26cxKx2IYs7xG6r1j6r1xMIIF0xvEx4A2jsIE14 v26r1j6r4UMIIF0xvEx4A2jsIEc7CjxVAFwI0_Gr0_Gr1UYxBIdaVFxhVjvjDU0xZFpf9x 0JUnvtZUUUUU= X-CM-SenderInfo: xjdrwv3l6h245lqf0zpsxwx03jof0z/ X-Spam-Status: No, score=-10.9 required=5.0 tests=BAYES_00, GIT_PATCH_0, KAM_ASCII_DIVIDERS, KAM_DMARC_STATUS, KAM_SHORT, RCVD_IN_MSPIKE_H2, SPF_HELO_NONE, SPF_PASS, TXREP 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.30 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: kito.cheng@gmail.com, jiawei@iscas.ac.cn Errors-To: gcc-patches-bounces+incoming=patchwork.ozlabs.org@gcc.gnu.org Sender: "Gcc-patches" Zcmp can share the same logic as save-restore in stack allocation: pre-allocation by cm.push, step 1 and step 2. Pre-allocation not only saves callee saved GPRs, but also saves callee saved FPRs and local variables if any. Please be noted cm.push pushes ra, s0-s11 in reverse order than what save-restore does. So adaption has been done in .cfi directives in my patch. gcc/ChangeLog: * config/riscv/iterators.md slot0_offset: slot 0 offset in stack GPRs area in bytes slot1_offset: slot 1 offset in stack GPRs area in bytes slot2_offset: likewise slot3_offset: likewise slot4_offset: likewise slot5_offset: likewise slot6_offset: likewise slot7_offset: likewise slot8_offset: likewise slot9_offset: likewise slot10_offset: likewise slot11_offset: likewise slot12_offset: likewise * config/riscv/predicates.md (stack_push_up_to_ra_operand): predicates of stack adjust pushing ra (stack_push_up_to_s0_operand): predicates of stack adjust pushing ra, s0 (stack_push_up_to_s1_operand): likewise (stack_push_up_to_s2_operand): likewise (stack_push_up_to_s3_operand): likewise (stack_push_up_to_s4_operand): likewise (stack_push_up_to_s5_operand): likewise (stack_push_up_to_s6_operand): likewise (stack_push_up_to_s7_operand): likewise (stack_push_up_to_s8_operand): likewise (stack_push_up_to_s9_operand): likewise (stack_push_up_to_s11_operand): likewise (stack_pop_up_to_ra_operand): predicates of stack adjust poping ra (stack_pop_up_to_s0_operand): predicates of stack adjust poping ra, s0 (stack_pop_up_to_s1_operand): likewise (stack_pop_up_to_s2_operand): likewise (stack_pop_up_to_s3_operand): likewise (stack_pop_up_to_s4_operand): likewise (stack_pop_up_to_s5_operand): likewise (stack_pop_up_to_s6_operand): likewise (stack_pop_up_to_s7_operand): likewise (stack_pop_up_to_s8_operand): likewise (stack_pop_up_to_s9_operand): likewise (stack_pop_up_to_s11_operand): likewise * config/riscv/riscv-protos.h (riscv_zcmp_valid_stack_adj_bytes_p):declaration * config/riscv/riscv.cc (struct riscv_frame_info): comment change (riscv_avoid_multi_push): helper function of riscv_use_multi_push (riscv_use_multi_push): true if multi push is used (riscv_multi_push_sregs_count): num of sregs in multi-push (riscv_multi_push_regs_count): num of regs in multi-push (riscv_16bytes_align): align to 16 bytes (riscv_stack_align): moved to a better place (riscv_save_libcall_count): no functional change (riscv_compute_frame_info): add zcmp frame info (riscv_for_each_saved_reg): save or restore fprs in specified slot for zcmp (riscv_adjust_multi_push_cfi_prologue): adjust cfi for cm.push (riscv_gen_multi_push_pop_insn): gen function for multi push and pop (get_multi_push_fpr_mask): get mask for the fprs pushed by cm.push (riscv_expand_prologue): allocate stack by cm.push (riscv_adjust_multi_pop_cfi_epilogue): adjust cfi for cm.pop[ret] (riscv_expand_epilogue): allocate stack by cm.pop[ret] (zcmp_base_adj): calculate stack adjustment base size (zcmp_additional_adj): calculate stack adjustment additional size (riscv_zcmp_valid_stack_adj_bytes_p): check if stack adjustment valid * config/riscv/riscv.h (RETURN_ADDR_MASK): mask of ra (S0_MASK): likewise (S1_MASK): likewise (S2_MASK): likewise (S3_MASK): likewise (S4_MASK): likewise (S5_MASK): likewise (S6_MASK): likewise (S7_MASK): likewise (S8_MASK): likewise (S9_MASK): likewise (S10_MASK): likewise (S11_MASK): likewise (MULTI_PUSH_GPR_MASK): GPR_MASK that cm.push can cover at most (ZCMP_MAX_SPIMM): max spimm value (ZCMP_SP_INC_STEP): zcmp sp increment step (ZCMP_INVALID_S0S10_SREGS_COUNTS): num of s0-s10 (ZCMP_S0S11_SREGS_COUNTS): num of s0-s11 (ZCMP_MAX_GRP_SLOTS): max slots of pushing and poping in zcmp (CALLEE_SAVED_FREG_NUMBER): get x of fsx(fs0 ~ fs11) * config/riscv/riscv.md: include zc.md * config/riscv/zc.md: New file. machine description for zcmp gcc/testsuite/ChangeLog: * gcc.target/riscv/rv32e_zcmp.c: New test. * gcc.target/riscv/rv32i_zcmp.c: New test. * gcc.target/riscv/zcmp_push_fpr.c: New test. * gcc.target/riscv/zcmp_stack_alignment.c: New test. --- gcc/config/riscv/iterators.md | 15 + gcc/config/riscv/predicates.md | 96 ++ gcc/config/riscv/riscv-protos.h | 2 + gcc/config/riscv/riscv.cc | 435 ++++++- gcc/config/riscv/riscv.h | 25 + gcc/config/riscv/riscv.md | 2 + gcc/config/riscv/zc.md | 1042 +++++++++++++++++ gcc/testsuite/gcc.target/riscv/rv32e_zcmp.c | 256 ++++ gcc/testsuite/gcc.target/riscv/rv32i_zcmp.c | 256 ++++ .../gcc.target/riscv/zcmp_push_fpr.c | 34 + .../gcc.target/riscv/zcmp_stack_alignment.c | 24 + 11 files changed, 2136 insertions(+), 51 deletions(-) create mode 100644 gcc/config/riscv/zc.md create mode 100644 gcc/testsuite/gcc.target/riscv/rv32e_zcmp.c create mode 100644 gcc/testsuite/gcc.target/riscv/rv32i_zcmp.c create mode 100644 gcc/testsuite/gcc.target/riscv/zcmp_push_fpr.c create mode 100644 gcc/testsuite/gcc.target/riscv/zcmp_stack_alignment.c diff --git a/gcc/config/riscv/iterators.md b/gcc/config/riscv/iterators.md index a4070de1510..ecf033f2fa7 100644 --- a/gcc/config/riscv/iterators.md +++ b/gcc/config/riscv/iterators.md @@ -125,6 +125,21 @@ (define_mode_attr shiftm1 [(SI "const_si_mask_operand") (DI "const_di_mask_operand")]) (define_mode_attr shiftm1p [(SI "DsS") (DI "DsD")]) +; zcmp mode attribute +(define_mode_attr slot0_offset [(SI "-4") (DI "-8")]) +(define_mode_attr slot1_offset [(SI "-8") (DI "-16")]) +(define_mode_attr slot2_offset [(SI "-12") (DI "-24")]) +(define_mode_attr slot3_offset [(SI "-16") (DI "-32")]) +(define_mode_attr slot4_offset [(SI "-20") (DI "-40")]) +(define_mode_attr slot5_offset [(SI "-24") (DI "-48")]) +(define_mode_attr slot6_offset [(SI "-28") (DI "-56")]) +(define_mode_attr slot7_offset [(SI "-32") (DI "-64")]) +(define_mode_attr slot8_offset [(SI "-36") (DI "-72")]) +(define_mode_attr slot9_offset [(SI "-40") (DI "-80")]) +(define_mode_attr slot10_offset [(SI "-44") (DI "-88")]) +(define_mode_attr slot11_offset [(SI "-48") (DI "-96")]) +(define_mode_attr slot12_offset [(SI "-52") (DI "-104")]) + ;; ------------------------------------------------------------------- ;; Code Iterators ;; ------------------------------------------------------------------- diff --git a/gcc/config/riscv/predicates.md b/gcc/config/riscv/predicates.md index 618ad607047..3ef09996a85 100644 --- a/gcc/config/riscv/predicates.md +++ b/gcc/config/riscv/predicates.md @@ -69,6 +69,102 @@ (ior (match_operand 0 "const_0_operand") (match_operand 0 "register_operand"))) +(define_predicate "stack_push_up_to_ra_operand" + (and (match_code "const_int") + (match_test "riscv_zcmp_valid_stack_adj_bytes_p (INTVAL (op) * -1, 1)"))) + +(define_predicate "stack_push_up_to_s0_operand" + (and (match_code "const_int") + (match_test "riscv_zcmp_valid_stack_adj_bytes_p (INTVAL (op) * -1, 2)"))) + +(define_predicate "stack_push_up_to_s1_operand" + (and (match_code "const_int") + (match_test "riscv_zcmp_valid_stack_adj_bytes_p (INTVAL (op) * -1, 3)"))) + +(define_predicate "stack_push_up_to_s2_operand" + (and (match_code "const_int") + (match_test "riscv_zcmp_valid_stack_adj_bytes_p (INTVAL (op) * -1, 4)"))) + +(define_predicate "stack_push_up_to_s3_operand" + (and (match_code "const_int") + (match_test "riscv_zcmp_valid_stack_adj_bytes_p (INTVAL (op) * -1, 5)"))) + +(define_predicate "stack_push_up_to_s4_operand" + (and (match_code "const_int") + (match_test "riscv_zcmp_valid_stack_adj_bytes_p (INTVAL (op) * -1, 6)"))) + +(define_predicate "stack_push_up_to_s5_operand" + (and (match_code "const_int") + (match_test "riscv_zcmp_valid_stack_adj_bytes_p (INTVAL (op) * -1, 7)"))) + +(define_predicate "stack_push_up_to_s6_operand" + (and (match_code "const_int") + (match_test "riscv_zcmp_valid_stack_adj_bytes_p (INTVAL (op) * -1, 8)"))) + +(define_predicate "stack_push_up_to_s7_operand" + (and (match_code "const_int") + (match_test "riscv_zcmp_valid_stack_adj_bytes_p (INTVAL (op) * -1, 9)"))) + +(define_predicate "stack_push_up_to_s8_operand" + (and (match_code "const_int") + (match_test "riscv_zcmp_valid_stack_adj_bytes_p (INTVAL (op) * -1, 10)"))) + +(define_predicate "stack_push_up_to_s9_operand" + (and (match_code "const_int") + (match_test "riscv_zcmp_valid_stack_adj_bytes_p (INTVAL (op) * -1, 11)"))) + +(define_predicate "stack_push_up_to_s11_operand" + (and (match_code "const_int") + (match_test "riscv_zcmp_valid_stack_adj_bytes_p (INTVAL (op) * -1, 13)"))) + +(define_predicate "stack_pop_up_to_ra_operand" + (and (match_code "const_int") + (match_test "riscv_zcmp_valid_stack_adj_bytes_p (INTVAL (op), 1)"))) + +(define_predicate "stack_pop_up_to_s0_operand" + (and (match_code "const_int") + (match_test "riscv_zcmp_valid_stack_adj_bytes_p (INTVAL (op), 2)"))) + +(define_predicate "stack_pop_up_to_s1_operand" + (and (match_code "const_int") + (match_test "riscv_zcmp_valid_stack_adj_bytes_p (INTVAL (op), 3)"))) + +(define_predicate "stack_pop_up_to_s2_operand" + (and (match_code "const_int") + (match_test "riscv_zcmp_valid_stack_adj_bytes_p (INTVAL (op), 4)"))) + +(define_predicate "stack_pop_up_to_s3_operand" + (and (match_code "const_int") + (match_test "riscv_zcmp_valid_stack_adj_bytes_p (INTVAL (op), 5)"))) + +(define_predicate "stack_pop_up_to_s4_operand" + (and (match_code "const_int") + (match_test "riscv_zcmp_valid_stack_adj_bytes_p (INTVAL (op), 6)"))) + +(define_predicate "stack_pop_up_to_s5_operand" + (and (match_code "const_int") + (match_test "riscv_zcmp_valid_stack_adj_bytes_p (INTVAL (op), 7)"))) + +(define_predicate "stack_pop_up_to_s6_operand" + (and (match_code "const_int") + (match_test "riscv_zcmp_valid_stack_adj_bytes_p (INTVAL (op), 8)"))) + +(define_predicate "stack_pop_up_to_s7_operand" + (and (match_code "const_int") + (match_test "riscv_zcmp_valid_stack_adj_bytes_p (INTVAL (op), 9)"))) + +(define_predicate "stack_pop_up_to_s8_operand" + (and (match_code "const_int") + (match_test "riscv_zcmp_valid_stack_adj_bytes_p (INTVAL (op), 10)"))) + +(define_predicate "stack_pop_up_to_s9_operand" + (and (match_code "const_int") + (match_test "riscv_zcmp_valid_stack_adj_bytes_p (INTVAL (op), 11)"))) + +(define_predicate "stack_pop_up_to_s11_operand" + (and (match_code "const_int") + (match_test "riscv_zcmp_valid_stack_adj_bytes_p (INTVAL (op), 13)"))) + ;; Only use branch-on-bit sequences when the mask is not an ANDI immediate. (define_predicate "branch_on_bit_operand" (and (match_code "const_int") diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h index 0e0470280f8..04885bbebd2 100644 --- a/gcc/config/riscv/riscv-protos.h +++ b/gcc/config/riscv/riscv-protos.h @@ -102,6 +102,8 @@ extern bool riscv_split_64bit_move_p (rtx, rtx); extern void riscv_split_doubleword_move (rtx, rtx); extern const char *riscv_output_move (rtx, rtx); extern const char *riscv_output_return (); +extern bool +riscv_zcmp_valid_stack_adj_bytes_p (HOST_WIDE_INT, int); #ifdef RTX_CODE extern void riscv_expand_int_scc (rtx, enum rtx_code, rtx, rtx, bool *invert_ptr = 0); diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc index 1d6e278ea90..ed4d28b2eb0 100644 --- a/gcc/config/riscv/riscv.cc +++ b/gcc/config/riscv/riscv.cc @@ -112,6 +112,14 @@ struct GTY(()) riscv_frame_info { /* How much the GPR save/restore routines adjust sp (or 0 if unused). */ unsigned save_libcall_adjustment; + /* the minimum number of bytes, in multiples of 16-byte address increments, + required to cover the registers in a multi push & pop. */ + unsigned multi_push_adj_base; + + /* the number of additional 16-byte address increments allocated for the stack + frame in a multi push & pop. */ + unsigned multi_push_adj_addi; + /* Offsets of fixed-point and floating-point save areas from frame bottom */ poly_int64 gp_sp_offset; poly_int64 fp_sp_offset; @@ -409,6 +417,16 @@ static const struct riscv_tune_info riscv_tune_info_table[] = { function. */ static bool riscv_save_frame_pointer; +typedef enum +{ + PUSH_IDX = 0, + POP_IDX, + POPRET_IDX, + ZCMP_OP_NUM +} riscv_zcmp_op_t; + +typedef insn_code (*code_for_push_pop_t) (machine_mode); + void riscv_frame_info::reset(void) { total_size = 0; @@ -5539,6 +5557,34 @@ riscv_save_reg_p (unsigned int regno) return false; } +/* Return TRUE if Zcmp push and pop insns should be + avoided. FALSE otherwise. + Only use multi push & pop if all GPRs masked can be covered, + and stack access is SP based, + and GPRs are at top of the stack frame, + and no conflicts in stack allocation with other features */ +static bool +riscv_avoid_multi_push (const struct riscv_frame_info *frame) +{ + if (!TARGET_ZCMP || crtl->calls_eh_return || frame_pointer_needed + || cfun->machine->interrupt_handler_p || cfun->machine->varargs_size != 0 + || crtl->args.pretend_args_size != 0 || flag_shrink_wrap_separate + || (frame->mask & ~MULTI_PUSH_GPR_MASK)) + return true; + + return false; +} + +/* Determine whether to use multi push insn. */ +static bool +riscv_use_multi_push (const struct riscv_frame_info *frame) +{ + if (riscv_avoid_multi_push (frame)) + return false; + + return (frame->multi_push_adj_base != 0); +} + /* Return TRUE if a libcall to save/restore GPRs should be avoided. FALSE otherwise. */ static bool @@ -5576,6 +5622,50 @@ riscv_save_libcall_count (unsigned mask) abort (); } +/* calculate number of s regs in multi push and pop. + Note that {s0-s10} is not valid in Zcmp, use {s0-s11} instead. */ +static unsigned +riscv_multi_push_sregs_count (unsigned mask) +{ + unsigned num = riscv_save_libcall_count (mask); + return (num == ZCMP_INVALID_S0S10_SREGS_COUNTS) ? ZCMP_S0S11_SREGS_COUNTS + : num; +} + +/* calculate number of regs(ra, s0-sx) in multi push and pop. */ +static unsigned +riscv_multi_push_regs_count (unsigned mask) +{ + /* 1 is for ra */ + return riscv_multi_push_sregs_count (mask) + 1; +} + +/* Handle 16 bytes align for poly_int. */ +static poly_int64 +riscv_16bytes_align (poly_int64 value) +{ + return aligned_upper_bound (value, 16); +} + +static HOST_WIDE_INT +riscv_16bytes_align (HOST_WIDE_INT value) +{ + return ROUND_UP (value, 16); +} + +/* 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); +} + /* Populate the current function's riscv_frame_info structure. RISC-V stack frames grown downward. High addresses are at the top. @@ -5601,7 +5691,7 @@ riscv_save_libcall_count (unsigned mask) | GPR save area | + UNITS_PER_WORD | | +-------------------------------+ <-- stack_pointer_rtx + fp_sp_offset - | | + UNITS_PER_HWVALUE + | | + UNITS_PER_FP_REG | FPR save area | | | +-------------------------------+ <-- frame_pointer_rtx (virtual) @@ -5620,19 +5710,6 @@ riscv_save_libcall_count (unsigned mask) static HOST_WIDE_INT riscv_first_stack_step (struct riscv_frame_info *frame, poly_int64 remaining_size); -/* 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) { @@ -5683,8 +5760,9 @@ riscv_compute_frame_info (void) if (frame->mask) { x_save_size = riscv_stack_align (num_x_saved * UNITS_PER_WORD); - unsigned num_save_restore = 1 + riscv_save_libcall_count (frame->mask); + /* 1 is for ra */ + 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 && !riscv_avoid_save_libcall ()) @@ -5696,6 +5774,14 @@ riscv_compute_frame_info (void) frame->save_libcall_adjustment = x_save_size; } + + if (!riscv_avoid_multi_push (frame)) + { + /* num(ra, s0-sx) */ + unsigned num_multi_push = riscv_multi_push_regs_count (frame->mask); + x_save_size = riscv_stack_align (num_multi_push * UNITS_PER_WORD); + frame->multi_push_adj_base = riscv_16bytes_align (x_save_size); + } } /* In an interrupt function, we need extra space for the initial saves of CSRs. */ @@ -5721,7 +5807,15 @@ riscv_compute_frame_info (void) frame->fp_sp_offset = offset - UNITS_PER_FP_REG; /* Next are the callee-saved GPRs. */ if (frame->mask) - offset += x_save_size; + { + offset += x_save_size; + /* align to 16 bytes and add paddings to GPR part to honor + both stack alignment and zcmp pus/pop size alignment. */ + if (riscv_use_multi_push (frame) + && known_lt (offset, frame->multi_push_adj_base + + ZCMP_SP_INC_STEP * ZCMP_MAX_SPIMM)) + offset = riscv_16bytes_align (offset); + } frame->gp_sp_offset = offset - UNITS_PER_WORD; /* The hard frame pointer points above the callee-saved GPRs. */ frame->hard_frame_pointer_offset = offset; @@ -5900,8 +5994,8 @@ static void riscv_for_each_saved_reg (poly_int64 sp_offset, riscv_save_restore_fn fn, bool epilogue, bool maybe_eh_return) { - HOST_WIDE_INT offset; - unsigned int regno; + HOST_WIDE_INT offset, first_fp_offset; + unsigned int regno, num_masked_fp = 0; unsigned int start = GP_REG_FIRST; unsigned int limit = GP_REG_LAST; @@ -5987,16 +6081,20 @@ riscv_for_each_saved_reg (poly_int64 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).to_constant (); + first_fp_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)) { bool handle_reg = !cfun->machine->reg_is_wrapped_separately[regno]; machine_mode mode = TARGET_DOUBLE_FLOAT ? DFmode : SFmode; - + unsigned int slot = (riscv_use_multi_push (&cfun->machine->frame)) + ? CALLEE_SAVED_FREG_NUMBER (regno) + : num_masked_fp; + offset = first_fp_offset - slot * GET_MODE_SIZE (mode).to_constant (); if (handle_reg) riscv_save_restore_reg (mode, regno, offset, fn); - offset -= GET_MODE_SIZE (mode).to_constant (); + num_masked_fp++; } } @@ -6093,6 +6191,41 @@ riscv_adjust_libcall_cfi_prologue () return dwarf; } +static rtx +riscv_adjust_multi_push_cfi_prologue (int saved_size) +{ + rtx dwarf = NULL_RTX; + rtx adjust_sp_rtx, reg, mem, insn; + unsigned int mask = cfun->machine->frame.mask; + int offset; + int saved_cnt = 0; + + if (mask & S10_MASK) + mask |= S11_MASK; + + for (int regno = GP_REG_LAST; regno >= GP_REG_FIRST; regno--) + if (BITSET_P (mask & MULTI_PUSH_GPR_MASK, regno - GP_REG_FIRST)) + { + /* The save order is s11-s0, ra + from high to low addr. */ + offset = saved_size - UNITS_PER_WORD * (++saved_cnt); + + reg = gen_rtx_REG (Pmode, regno); + mem = gen_frame_mem (Pmode, + plus_constant (Pmode, stack_pointer_rtx, offset)); + + insn = gen_rtx_SET (mem, reg); + dwarf = alloc_reg_note (REG_CFA_OFFSET, insn, dwarf); + } + + /* Debug info for adjust sp. */ + adjust_sp_rtx + = gen_rtx_SET (stack_pointer_rtx, + plus_constant (Pmode, stack_pointer_rtx, -saved_size)); + dwarf = alloc_reg_note (REG_CFA_ADJUST_CFA, adjust_sp_rtx, dwarf); + return dwarf; +} + static void riscv_emit_stack_tie (void) { @@ -6102,6 +6235,56 @@ riscv_emit_stack_tie (void) emit_insn (gen_stack_tiedi (stack_pointer_rtx, hard_frame_pointer_rtx)); } +/*zcmp multi push and pop code_for_push_pop function ptr array */ +const code_for_push_pop_t code_for_push_pop[ZCMP_MAX_GRP_SLOTS][ZCMP_OP_NUM] + = {{code_for_gpr_multi_push_up_to_ra, code_for_gpr_multi_pop_up_to_ra, + code_for_gpr_multi_popret_up_to_ra}, + {code_for_gpr_multi_push_up_to_s0, code_for_gpr_multi_pop_up_to_s0, + code_for_gpr_multi_popret_up_to_s0}, + {code_for_gpr_multi_push_up_to_s1, code_for_gpr_multi_pop_up_to_s1, + code_for_gpr_multi_popret_up_to_s1}, + {code_for_gpr_multi_push_up_to_s2, code_for_gpr_multi_pop_up_to_s2, + code_for_gpr_multi_popret_up_to_s2}, + {code_for_gpr_multi_push_up_to_s3, code_for_gpr_multi_pop_up_to_s3, + code_for_gpr_multi_popret_up_to_s3}, + {code_for_gpr_multi_push_up_to_s4, code_for_gpr_multi_pop_up_to_s4, + code_for_gpr_multi_popret_up_to_s4}, + {code_for_gpr_multi_push_up_to_s5, code_for_gpr_multi_pop_up_to_s5, + code_for_gpr_multi_popret_up_to_s5}, + {code_for_gpr_multi_push_up_to_s6, code_for_gpr_multi_pop_up_to_s6, + code_for_gpr_multi_popret_up_to_s6}, + {code_for_gpr_multi_push_up_to_s7, code_for_gpr_multi_pop_up_to_s7, + code_for_gpr_multi_popret_up_to_s7}, + {code_for_gpr_multi_push_up_to_s8, code_for_gpr_multi_pop_up_to_s8, + code_for_gpr_multi_popret_up_to_s8}, + {code_for_gpr_multi_push_up_to_s9, code_for_gpr_multi_pop_up_to_s9, + code_for_gpr_multi_popret_up_to_s9}, + {nullptr, nullptr, nullptr}, + {code_for_gpr_multi_push_up_to_s11, code_for_gpr_multi_pop_up_to_s11, + code_for_gpr_multi_popret_up_to_s11}}; + +static rtx +riscv_gen_multi_push_pop_insn (riscv_zcmp_op_t op, HOST_WIDE_INT adj_size, + unsigned int regs_num) +{ + gcc_assert (op < ZCMP_OP_NUM); + gcc_assert (regs_num <= ZCMP_MAX_GRP_SLOTS + && regs_num != ZCMP_INVALID_S0S10_SREGS_COUNTS + 1); /* 1 for ra*/ + rtx stack_adj = GEN_INT (adj_size); + return GEN_FCN (code_for_push_pop[regs_num - 1][op](Pmode)) (stack_adj); +} + +static unsigned +get_multi_push_fpr_mask (unsigned max_fprs_push) +{ + unsigned mask_fprs_push = 0, num_f_pushed = 0; + for (unsigned regno = FP_REG_FIRST; + regno <= FP_REG_LAST && num_f_pushed < max_fprs_push; regno++) + if (riscv_save_reg_p (regno)) + mask_fprs_push |= 1 << (regno - FP_REG_FIRST), num_f_pushed++; + return mask_fprs_push; +} + /* Expand the "prologue" pattern. */ void @@ -6110,7 +6293,9 @@ riscv_expand_prologue (void) struct riscv_frame_info *frame = &cfun->machine->frame; poly_int64 remaining_size = frame->total_size; unsigned mask = frame->mask; - rtx insn; + unsigned fmask = frame->fmask; + int spimm, multi_push_additional, stack_adj; + rtx insn, dwarf = NULL_RTX; if (flag_stack_usage_info) current_function_static_stack_size = constant_lower_bound (remaining_size); @@ -6118,8 +6303,46 @@ riscv_expand_prologue (void) if (cfun->machine->naked_p) return; + /* prefer muti-push to save-restore libcall. */ + if (riscv_use_multi_push (frame)) + { + remaining_size -= frame->multi_push_adj_base; + if (known_gt (remaining_size, 2 * ZCMP_SP_INC_STEP)) + spimm = 3; + else if (known_gt (remaining_size, ZCMP_SP_INC_STEP)) + spimm = 2; + else if (known_gt (remaining_size, 0)) + spimm = 1; + else + spimm = 0; + multi_push_additional = spimm * ZCMP_SP_INC_STEP; + frame->multi_push_adj_addi = multi_push_additional; + remaining_size -= multi_push_additional; + + /* emit multi push insn & dwarf along with it. */ + stack_adj = frame->multi_push_adj_base + multi_push_additional; + insn = emit_insn (riscv_gen_multi_push_pop_insn ( + PUSH_IDX, -stack_adj, riscv_multi_push_regs_count (frame->mask))); + dwarf = riscv_adjust_multi_push_cfi_prologue (stack_adj); + RTX_FRAME_RELATED_P (insn) = 1; + REG_NOTES (insn) = dwarf; + + /* Temporarily fib that we need not save GPRs. */ + frame->mask = 0; + + /* push FPRs into the addtional reserved space by cm.push. */ + if (fmask) + { + unsigned mask_fprs_push + = get_multi_push_fpr_mask (multi_push_additional / UNITS_PER_WORD); + frame->fmask &= mask_fprs_push; + riscv_for_each_saved_reg (remaining_size, riscv_save_reg, false, + false); + frame->fmask = fmask & ~mask_fprs_push; /* mask for the rest FPRs. */ + } + } /* When optimizing for size, call a subroutine to save the registers. */ - if (riscv_use_save_libcall (frame)) + else if (riscv_use_save_libcall (frame)) { rtx dwarf = NULL_RTX; dwarf = riscv_adjust_libcall_cfi_prologue (); @@ -6135,17 +6358,20 @@ riscv_expand_prologue (void) /* Save the registers. */ if ((frame->mask | frame->fmask) != 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 (known_gt (remaining_size, frame->frame_pointer_offset)) + { + HOST_WIDE_INT step1 = riscv_first_stack_step (frame, remaining_size); + remaining_size -= step1; + insn = gen_add3_insn (stack_pointer_rtx, stack_pointer_rtx, + GEN_INT (-step1)); + RTX_FRAME_RELATED_P (emit_insn (insn)) = 1; + } riscv_for_each_saved_reg (remaining_size, riscv_save_reg, false, false); } - frame->mask = mask; /* Undo the above fib. */ + /* Undo the above fib. */ + frame->mask = mask; + frame->fmask = fmask; /* Set up the frame pointer, if we're using one. */ if (frame_pointer_needed) @@ -6198,6 +6424,32 @@ riscv_expand_prologue (void) } } +static rtx +riscv_adjust_multi_pop_cfi_epilogue (int saved_size) +{ + rtx dwarf = NULL_RTX; + rtx adjust_sp_rtx, reg; + unsigned int mask = cfun->machine->frame.mask; + + if (mask & S10_MASK) + mask |= S11_MASK; + + /* Debug info for adjust sp. */ + adjust_sp_rtx + = gen_rtx_SET (stack_pointer_rtx, + plus_constant (Pmode, stack_pointer_rtx, saved_size)); + dwarf = alloc_reg_note (REG_CFA_ADJUST_CFA, adjust_sp_rtx, dwarf); + + for (int regno = GP_REG_FIRST; regno <= GP_REG_LAST; regno++) + if (BITSET_P (mask, regno - GP_REG_FIRST)) + { + reg = gen_rtx_REG (Pmode, regno); + dwarf = alloc_reg_note (REG_CFA_RESTORE, reg, dwarf); + } + + return dwarf; +} + static rtx riscv_adjust_libcall_cfi_epilogue () { @@ -6236,11 +6488,24 @@ 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; + unsigned fmask = frame->fmask; + unsigned mask_fprs_push = 0; HOST_WIDE_INT step2 = 0; - bool use_restore_libcall = ((style == NORMAL_RETURN) - && riscv_use_save_libcall (frame)); - unsigned libcall_size = (use_restore_libcall - ? frame->save_libcall_adjustment : 0); + bool use_multi_pop_normal + = ((style == NORMAL_RETURN) && riscv_use_multi_push (frame)); + bool use_multi_pop_sibcall + = ((style == SIBCALL_RETURN) && riscv_use_multi_push (frame)); + bool use_multi_pop = use_multi_pop_normal || use_multi_pop_sibcall; + + bool use_restore_libcall + = !use_multi_pop + && ((style == NORMAL_RETURN) && riscv_use_save_libcall (frame)); + unsigned libcall_size = use_restore_libcall && !use_multi_pop + ? frame->save_libcall_adjustment + : 0; + unsigned multipop_size + = use_multi_pop ? frame->multi_push_adj_base + frame->multi_push_adj_addi + : 0; rtx ra = gen_rtx_REG (Pmode, RETURN_ADDR_REGNUM); rtx insn; @@ -6311,18 +6576,26 @@ riscv_expand_epilogue (int style) REG_NOTES (insn) = dwarf; } - if (use_restore_libcall) - frame->mask = 0; /* Temporarily fib for GPRs. */ + if (use_restore_libcall || use_multi_pop) + frame->mask = 0; /* Temporarily fib that we need not restore GPRs. */ /* 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 (use_multi_pop) + { + if (frame->fmask + && known_gt (frame->total_size - multipop_size, + frame->frame_pointer_offset)) + step2 + = riscv_first_stack_step (frame, frame->total_size - multipop_size); + } + else if ((frame->mask | frame->fmask) != 0) step2 = riscv_first_stack_step (frame, frame->total_size - libcall_size); - if (use_restore_libcall) + if (use_restore_libcall || use_multi_pop) frame->mask = mask; /* Undo the above fib. */ - poly_int64 step1 = frame->total_size - step2 - libcall_size; + poly_int64 step1 = frame->total_size - step2 - libcall_size - multipop_size; /* Set TARGET to BASE + STEP1. */ if (known_gt (step1, 0)) @@ -6356,8 +6629,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 (step2 + libcall_size + multipop_size)); dwarf = alloc_reg_note (REG_CFA_DEF_CFA, cfa_adjust_rtx, dwarf); RTX_FRAME_RELATED_P (insn) = 1; @@ -6372,16 +6646,26 @@ riscv_expand_epilogue (int style) epilogue_cfa_sp_offset = step2; } - if (use_restore_libcall) - frame->mask = 0; /* Temporarily fib that we need not save GPRs. */ + if (use_multi_pop) + { + frame->mask = 0; /* Temporarily fib that we need not restore GPRs. */ + if (fmask) + { + mask_fprs_push = get_multi_push_fpr_mask (frame->multi_push_adj_addi + / UNITS_PER_WORD); + frame->fmask &= ~mask_fprs_push; /* FPRs not saved by cm.push */ + } + } + else if (use_restore_libcall) + frame->mask = 0; /* Temporarily fib that we need not restore GPRs. */ /* Restore the registers. */ - riscv_for_each_saved_reg (frame->total_size - step2 - libcall_size, - riscv_restore_reg, - true, style == EXCEPTION_RETURN); + riscv_for_each_saved_reg (frame->total_size - step2 - libcall_size + - multipop_size, + riscv_restore_reg, true, style == EXCEPTION_RETURN); if (use_restore_libcall) - frame->mask = mask; /* Undo the above fib. */ + frame->mask = mask; /* Undo the above fib. */ if (need_barrier_p) riscv_emit_stack_tie (); @@ -6393,15 +6677,43 @@ riscv_expand_epilogue (int style) GEN_INT (step2))); rtx dwarf = NULL_RTX; - rtx cfa_adjust_rtx = gen_rtx_PLUS (Pmode, stack_pointer_rtx, - GEN_INT (libcall_size)); + rtx cfa_adjust_rtx + = gen_rtx_PLUS (Pmode, stack_pointer_rtx, + GEN_INT (libcall_size + multipop_size)); dwarf = alloc_reg_note (REG_CFA_DEF_CFA, cfa_adjust_rtx, dwarf); RTX_FRAME_RELATED_P (insn) = 1; REG_NOTES (insn) = dwarf; } - if (use_restore_libcall) + if (use_multi_pop) + { + /* restore FPRs pushed by cm.push. */ + frame->fmask = fmask & mask_fprs_push; + if (frame->fmask) + riscv_for_each_saved_reg (frame->total_size - libcall_size + - multipop_size, + riscv_restore_reg, true, + style == EXCEPTION_RETURN); + /* Undo the above fib. */ + frame->mask = mask; + frame->fmask = fmask; + unsigned regs_count = riscv_multi_push_regs_count (frame->mask); + if (use_multi_pop_normal) + insn = emit_jump_insn (riscv_gen_multi_push_pop_insn (POPRET_IDX, + multipop_size, + regs_count)); + else + insn = emit_insn ( + riscv_gen_multi_push_pop_insn (POP_IDX, multipop_size, regs_count)); + + rtx dwarf = riscv_adjust_multi_pop_cfi_epilogue (multipop_size); + RTX_FRAME_RELATED_P (insn) = 1; + REG_NOTES (insn) = dwarf; + if (use_multi_pop_normal) + return; + } + else if (use_restore_libcall) { rtx dwarf = riscv_adjust_libcall_cfi_epilogue (); insn = emit_insn (gen_gpr_restore (GEN_INT (riscv_save_libcall_count (mask)))); @@ -7744,6 +8056,27 @@ riscv_gen_gpr_save_insn (struct riscv_frame_info *frame) return gen_rtx_PARALLEL (VOIDmode, vec); } +static HOST_WIDE_INT +zcmp_base_adj (int regs_num) +{ + return riscv_16bytes_align ((regs_num) *GET_MODE_SIZE (word_mode)); +} + +static HOST_WIDE_INT +zcmp_additional_adj (HOST_WIDE_INT total, int regs_num) +{ + return total - zcmp_base_adj (regs_num); +} + +bool +riscv_zcmp_valid_stack_adj_bytes_p (HOST_WIDE_INT total, int regs_num) +{ + HOST_WIDE_INT additioanl_bytes = zcmp_additional_adj (total, regs_num); + return additioanl_bytes == 0 || additioanl_bytes == 1 * ZCMP_SP_INC_STEP + || additioanl_bytes == 2 * ZCMP_SP_INC_STEP + || additioanl_bytes == ZCMP_MAX_SPIMM * ZCMP_SP_INC_STEP; +} + /* Return true if it's valid gpr_save pattern. */ bool diff --git a/gcc/config/riscv/riscv.h b/gcc/config/riscv/riscv.h index e18a0081297..42b6eb784d4 100644 --- a/gcc/config/riscv/riscv.h +++ b/gcc/config/riscv/riscv.h @@ -420,6 +420,29 @@ ASM_MISA_SPEC #define RISCV_CALL_ADDRESS_TEMP(MODE) \ gen_rtx_REG (MODE, RISCV_CALL_ADDRESS_TEMP_REGNUM) +#define RETURN_ADDR_MASK (1 << RETURN_ADDR_REGNUM) +#define S0_MASK (1 << S0_REGNUM) +#define S1_MASK (1 << S1_REGNUM) +#define S2_MASK (1 << S2_REGNUM) +#define S3_MASK (1 << S3_REGNUM) +#define S4_MASK (1 << S4_REGNUM) +#define S5_MASK (1 << S5_REGNUM) +#define S6_MASK (1 << S6_REGNUM) +#define S7_MASK (1 << S7_REGNUM) +#define S8_MASK (1 << S8_REGNUM) +#define S9_MASK (1 << S9_REGNUM) +#define S10_MASK (1 << S10_REGNUM) +#define S11_MASK (1 << S11_REGNUM) + +#define MULTI_PUSH_GPR_MASK \ + (RETURN_ADDR_MASK | S0_MASK | S1_MASK | S2_MASK | S3_MASK | S4_MASK \ + | S5_MASK | S6_MASK | S7_MASK | S8_MASK | S9_MASK | S10_MASK | S11_MASK) +#define ZCMP_MAX_SPIMM 3 +#define ZCMP_SP_INC_STEP 16 +#define ZCMP_INVALID_S0S10_SREGS_COUNTS 11 +#define ZCMP_S0S11_SREGS_COUNTS 12 +#define ZCMP_MAX_GRP_SLOTS 13 + #define MCOUNT_NAME "_mcount" #define NO_PROFILE_COUNTERS 1 @@ -655,6 +678,8 @@ enum reg_class ((REGNO) >= 8 && (REGNO) <= 9 ? (REGNO) - 8 : \ (REGNO) >= 18 && (REGNO) <= 27 ? (REGNO) - 16 : -1) +#define CALLEE_SAVED_FREG_NUMBER(REGNO) CALLEE_SAVED_REG_NUMBER (REGNO - 32) + #define LIBCALL_VALUE(MODE) \ riscv_function_value (NULL_TREE, NULL_TREE, MODE) diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md index 47d14d99903..f489646cec3 100644 --- a/gcc/config/riscv/riscv.md +++ b/gcc/config/riscv/riscv.md @@ -124,6 +124,7 @@ (define_constants [(RETURN_ADDR_REGNUM 1) + (SP_REGNUM 2) (GP_REGNUM 3) (TP_REGNUM 4) (T0_REGNUM 5) @@ -3431,3 +3432,4 @@ (include "thead.md") (include "vector.md") (include "zicond.md") +(include "zc.md") diff --git a/gcc/config/riscv/zc.md b/gcc/config/riscv/zc.md new file mode 100644 index 00000000000..5c1bf031b8d --- /dev/null +++ b/gcc/config/riscv/zc.md @@ -0,0 +1,1042 @@ +;; Machine description for RISC-V Zc extention. +;; Copyright (C) 2023 Free Software Foundation, Inc. +;; Contributed by Fei Gao (gaofei@eswincomputing.com). + +;; This file is part of GCC. + +;; GCC is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 3, or (at your option) +;; any later version. + +;; GCC is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GCC; see the file COPYING3. If not see +;; . + +(define_insn "@gpr_multi_pop_up_to_ra_" + [(set (reg:X SP_REGNUM) + (plus:X (reg:X SP_REGNUM) + (match_operand 0 "stack_pop_up_to_ra_operand" "I"))) + (set (reg:X RETURN_ADDR_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int ))))] + "TARGET_ZCMP" + "cm.pop {ra}, %0" +) + +(define_insn "@gpr_multi_pop_up_to_s0_" + [(set (reg:X SP_REGNUM) + (plus:X (reg:X SP_REGNUM) + (match_operand 0 "stack_pop_up_to_s0_operand" "I"))) + (set (reg:X S0_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X RETURN_ADDR_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int ))))] + "TARGET_ZCMP" + "cm.pop {ra, s0}, %0" +) + +(define_insn "@gpr_multi_pop_up_to_s1_" + [(set (reg:X SP_REGNUM) + (plus:X (reg:X SP_REGNUM) + (match_operand 0 "stack_pop_up_to_s1_operand" "I"))) + (set (reg:X S1_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S0_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X RETURN_ADDR_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int ))))] + "TARGET_ZCMP" + "cm.pop {ra, s0-s1}, %0" +) + +(define_insn "@gpr_multi_pop_up_to_s2_" + [(set (reg:X SP_REGNUM) + (plus:X (reg:X SP_REGNUM) + (match_operand 0 "stack_pop_up_to_s2_operand" "I"))) + (set (reg:X S2_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S1_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S0_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X RETURN_ADDR_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int ))))] + "TARGET_ZCMP" + "cm.pop {ra, s0-s2}, %0" +) + +(define_insn "@gpr_multi_pop_up_to_s3_" + [(set (reg:X SP_REGNUM) + (plus:X (reg:X SP_REGNUM) + (match_operand 0 "stack_pop_up_to_s3_operand" "I"))) + (set (reg:X S3_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S2_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S1_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S0_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X RETURN_ADDR_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int ))))] + "TARGET_ZCMP" + "cm.pop {ra, s0-s3}, %0" +) + +(define_insn "@gpr_multi_pop_up_to_s4_" + [(set (reg:X SP_REGNUM) + (plus:X (reg:X SP_REGNUM) + (match_operand 0 "stack_pop_up_to_s4_operand" "I"))) + (set (reg:X S4_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S3_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S2_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S1_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S0_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X RETURN_ADDR_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int ))))] + "TARGET_ZCMP" + "cm.pop {ra, s0-s4}, %0" +) + +(define_insn "@gpr_multi_pop_up_to_s5_" + [(set (reg:X SP_REGNUM) + (plus:X (reg:X SP_REGNUM) + (match_operand 0 "stack_pop_up_to_s5_operand" "I"))) + (set (reg:X S5_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S4_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S3_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S2_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S1_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S0_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X RETURN_ADDR_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int ))))] + "TARGET_ZCMP" + "cm.pop {ra, s0-s5}, %0" +) + +(define_insn "@gpr_multi_pop_up_to_s6_" + [(set (reg:X SP_REGNUM) + (plus:X (reg:X SP_REGNUM) + (match_operand 0 "stack_pop_up_to_s6_operand" "I"))) + (set (reg:X S6_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S5_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S4_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S3_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S2_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S1_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S0_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X RETURN_ADDR_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int ))))] + "TARGET_ZCMP" + "cm.pop {ra, s0-s6}, %0" +) + +(define_insn "@gpr_multi_pop_up_to_s7_" + [(set (reg:X SP_REGNUM) + (plus:X (reg:X SP_REGNUM) + (match_operand 0 "stack_pop_up_to_s7_operand" "I"))) + (set (reg:X S7_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S6_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S5_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S4_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S3_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S2_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S1_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S0_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X RETURN_ADDR_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int ))))] + "TARGET_ZCMP" + "cm.pop {ra, s0-s7}, %0" +) + +(define_insn "@gpr_multi_pop_up_to_s8_" + [(set (reg:X SP_REGNUM) + (plus:X (reg:X SP_REGNUM) + (match_operand 0 "stack_pop_up_to_s8_operand" "I"))) + (set (reg:X S8_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S7_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S6_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S5_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S4_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S3_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S2_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S1_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S0_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X RETURN_ADDR_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int ))))] + "TARGET_ZCMP" + "cm.pop {ra, s0-s8}, %0" +) + +(define_insn "@gpr_multi_pop_up_to_s9_" + [(set (reg:X SP_REGNUM) + (plus:X (reg:X SP_REGNUM) + (match_operand 0 "stack_pop_up_to_s9_operand" "I"))) + (set (reg:X S9_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S8_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S7_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S6_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S5_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S4_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S3_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S2_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S1_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S0_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X RETURN_ADDR_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int ))))] + "TARGET_ZCMP" + "cm.pop {ra, s0-s9}, %0" +) + +(define_insn "@gpr_multi_pop_up_to_s11_" + [(set (reg:X SP_REGNUM) + (plus:X (reg:X SP_REGNUM) + (match_operand 0 "stack_pop_up_to_s11_operand" "I"))) + (set (reg:X S11_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S10_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S9_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S8_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S7_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S6_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S5_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S4_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S3_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S2_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S1_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S0_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X RETURN_ADDR_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int ))))] + "TARGET_ZCMP" + "cm.pop {ra, s0-s11}, %0" +) + +(define_insn "@gpr_multi_popret_up_to_ra_" + [(set (reg:X SP_REGNUM) + (plus:X (reg:X SP_REGNUM) + (match_operand 0 "stack_pop_up_to_ra_operand" "I"))) + (set (reg:X RETURN_ADDR_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (return) + (use (reg:SI RETURN_ADDR_REGNUM))] + "TARGET_ZCMP" + "cm.popret {ra}, %0" +) + +(define_insn "@gpr_multi_popret_up_to_s0_" + [(set (reg:X SP_REGNUM) + (plus:X (reg:X SP_REGNUM) + (match_operand 0 "stack_pop_up_to_s0_operand" "I"))) + (set (reg:X S0_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X RETURN_ADDR_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (return) + (use (reg:SI RETURN_ADDR_REGNUM))] + "TARGET_ZCMP" + "cm.popret {ra, s0}, %0" +) + +(define_insn "@gpr_multi_popret_up_to_s1_" + [(set (reg:X SP_REGNUM) + (plus:X (reg:X SP_REGNUM) + (match_operand 0 "stack_pop_up_to_s1_operand" "I"))) + (set (reg:X S1_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S0_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X RETURN_ADDR_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (return) + (use (reg:SI RETURN_ADDR_REGNUM))] + "TARGET_ZCMP" + "cm.popret {ra, s0-s1}, %0" +) + +(define_insn "@gpr_multi_popret_up_to_s2_" + [(set (reg:X SP_REGNUM) + (plus:X (reg:X SP_REGNUM) + (match_operand 0 "stack_pop_up_to_s2_operand" "I"))) + (set (reg:X S2_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S1_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S0_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X RETURN_ADDR_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (return) + (use (reg:SI RETURN_ADDR_REGNUM))] + "TARGET_ZCMP" + "cm.popret {ra, s0-s2}, %0" +) + +(define_insn "@gpr_multi_popret_up_to_s3_" + [(set (reg:X SP_REGNUM) + (plus:X (reg:X SP_REGNUM) + (match_operand 0 "stack_pop_up_to_s3_operand" "I"))) + (set (reg:X S3_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S2_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S1_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S0_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X RETURN_ADDR_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (return) + (use (reg:SI RETURN_ADDR_REGNUM))] + "TARGET_ZCMP" + "cm.popret {ra, s0-s3}, %0" +) + +(define_insn "@gpr_multi_popret_up_to_s4_" + [(set (reg:X SP_REGNUM) + (plus:X (reg:X SP_REGNUM) + (match_operand 0 "stack_pop_up_to_s4_operand" "I"))) + (set (reg:X S4_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S3_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S2_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S1_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S0_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X RETURN_ADDR_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (return) + (use (reg:SI RETURN_ADDR_REGNUM))] + "TARGET_ZCMP" + "cm.popret {ra, s0-s4}, %0" +) + +(define_insn "@gpr_multi_popret_up_to_s5_" + [(set (reg:X SP_REGNUM) + (plus:X (reg:X SP_REGNUM) + (match_operand 0 "stack_pop_up_to_s5_operand" "I"))) + (set (reg:X S5_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S4_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S3_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S2_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S1_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S0_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X RETURN_ADDR_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (return) + (use (reg:SI RETURN_ADDR_REGNUM))] + "TARGET_ZCMP" + "cm.popret {ra, s0-s5}, %0" +) + +(define_insn "@gpr_multi_popret_up_to_s6_" + [(set (reg:X SP_REGNUM) + (plus:X (reg:X SP_REGNUM) + (match_operand 0 "stack_pop_up_to_s6_operand" "I"))) + (set (reg:X S6_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S5_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S4_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S3_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S2_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S1_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S0_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X RETURN_ADDR_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (return) + (use (reg:SI RETURN_ADDR_REGNUM))] + "TARGET_ZCMP" + "cm.popret {ra, s0-s6}, %0" +) + +(define_insn "@gpr_multi_popret_up_to_s7_" + [(set (reg:X SP_REGNUM) + (plus:X (reg:X SP_REGNUM) + (match_operand 0 "stack_pop_up_to_s7_operand" "I"))) + (set (reg:X S7_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S6_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S5_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S4_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S3_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S2_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S1_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S0_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X RETURN_ADDR_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (return) + (use (reg:SI RETURN_ADDR_REGNUM))] + "TARGET_ZCMP" + "cm.popret {ra, s0-s7}, %0" +) + +(define_insn "@gpr_multi_popret_up_to_s8_" + [(set (reg:X SP_REGNUM) + (plus:X (reg:X SP_REGNUM) + (match_operand 0 "stack_pop_up_to_s8_operand" "I"))) + (set (reg:X S8_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S7_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S6_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S5_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S4_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S3_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S2_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S1_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S0_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X RETURN_ADDR_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (return) + (use (reg:SI RETURN_ADDR_REGNUM))] + "TARGET_ZCMP" + "cm.popret {ra, s0-s8}, %0" +) + +(define_insn "@gpr_multi_popret_up_to_s9_" + [(set (reg:X SP_REGNUM) + (plus:X (reg:X SP_REGNUM) + (match_operand 0 "stack_pop_up_to_s9_operand" "I"))) + (set (reg:X S9_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S8_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S7_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S6_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S5_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S4_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S3_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S2_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S1_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S0_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X RETURN_ADDR_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (return) + (use (reg:SI RETURN_ADDR_REGNUM))] + "TARGET_ZCMP" + "cm.popret {ra, s0-s9}, %0" +) + +(define_insn "@gpr_multi_popret_up_to_s11_" + [(set (reg:X SP_REGNUM) + (plus:X (reg:X SP_REGNUM) + (match_operand 0 "stack_pop_up_to_s11_operand" "I"))) + (set (reg:X S11_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S10_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S9_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S8_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S7_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S6_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S5_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S4_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S3_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S2_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S1_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S0_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X RETURN_ADDR_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (return) + (use (reg:SI RETURN_ADDR_REGNUM))] + "TARGET_ZCMP" + "cm.popret {ra, s0-s11}, %0" +) + +(define_insn "@gpr_multi_push_up_to_ra_" + [(set (mem:X (plus:X (reg:X SP_REGNUM) + (const_int ))) + (reg:X RETURN_ADDR_REGNUM)) + (set (reg:X SP_REGNUM) + (plus:X (reg:X SP_REGNUM) + (match_operand 0 "stack_push_up_to_ra_operand" "I")))] + "TARGET_ZCMP" + "cm.push {ra}, %0" +) + +(define_insn "@gpr_multi_push_up_to_s0_" + [(set (mem:X (plus:X (reg:X SP_REGNUM) + (const_int ))) + (reg:X S0_REGNUM)) + (set (mem:X (plus:X (reg:X SP_REGNUM) + (const_int ))) + (reg:X RETURN_ADDR_REGNUM)) + (set (reg:X SP_REGNUM) + (plus:X (reg:X SP_REGNUM) + (match_operand 0 "stack_push_up_to_s0_operand" "I")))] + "TARGET_ZCMP" + "cm.push {ra, s0}, %0" +) + +(define_insn "@gpr_multi_push_up_to_s1_" + [(set (mem:X (plus:X (reg:X SP_REGNUM) + (const_int ))) + (reg:X S1_REGNUM)) + (set (mem:X (plus:X (reg:X SP_REGNUM) + (const_int ))) + (reg:X S0_REGNUM)) + (set (mem:X (plus:X (reg:X SP_REGNUM) + (const_int ))) + (reg:X RETURN_ADDR_REGNUM)) + (set (reg:X SP_REGNUM) + (plus:X (reg:X SP_REGNUM) + (match_operand 0 "stack_push_up_to_s1_operand" "I")))] + "TARGET_ZCMP" + "cm.push {ra, s0-s1}, %0" +) + +(define_insn "@gpr_multi_push_up_to_s2_" + [(set (mem:X (plus:X (reg:X SP_REGNUM) + (const_int ))) + (reg:X S2_REGNUM)) + (set (mem:X (plus:X (reg:X SP_REGNUM) + (const_int ))) + (reg:X S1_REGNUM)) + (set (mem:X (plus:X (reg:X SP_REGNUM) + (const_int ))) + (reg:X S0_REGNUM)) + (set (mem:X (plus:X (reg:X SP_REGNUM) + (const_int ))) + (reg:X RETURN_ADDR_REGNUM)) + (set (reg:X SP_REGNUM) + (plus:X (reg:X SP_REGNUM) + (match_operand 0 "stack_push_up_to_s2_operand" "I")))] + "TARGET_ZCMP" + "cm.push {ra, s0-s2}, %0" +) + +(define_insn "@gpr_multi_push_up_to_s3_" + [(set (mem:X (plus:X (reg:X SP_REGNUM) + (const_int ))) + (reg:X S3_REGNUM)) + (set (mem:X (plus:X (reg:X SP_REGNUM) + (const_int ))) + (reg:X S2_REGNUM)) + (set (mem:X (plus:X (reg:X SP_REGNUM) + (const_int ))) + (reg:X S1_REGNUM)) + (set (mem:X (plus:X (reg:X SP_REGNUM) + (const_int ))) + (reg:X S0_REGNUM)) + (set (mem:X (plus:X (reg:X SP_REGNUM) + (const_int ))) + (reg:X RETURN_ADDR_REGNUM)) + (set (reg:X SP_REGNUM) + (plus:X (reg:X SP_REGNUM) + (match_operand 0 "stack_push_up_to_s3_operand" "I")))] + "TARGET_ZCMP" + "cm.push {ra, s0-s3}, %0" +) + +(define_insn "@gpr_multi_push_up_to_s4_" + [(set (mem:X (plus:X (reg:X SP_REGNUM) + (const_int ))) + (reg:X S4_REGNUM)) + (set (mem:X (plus:X (reg:X SP_REGNUM) + (const_int ))) + (reg:X S3_REGNUM)) + (set (mem:X (plus:X (reg:X SP_REGNUM) + (const_int ))) + (reg:X S2_REGNUM)) + (set (mem:X (plus:X (reg:X SP_REGNUM) + (const_int ))) + (reg:X S1_REGNUM)) + (set (mem:X (plus:X (reg:X SP_REGNUM) + (const_int ))) + (reg:X S0_REGNUM)) + (set (mem:X (plus:X (reg:X SP_REGNUM) + (const_int ))) + (reg:X RETURN_ADDR_REGNUM)) + (set (reg:X SP_REGNUM) + (plus:X (reg:X SP_REGNUM) + (match_operand 0 "stack_push_up_to_s4_operand" "I")))] + "TARGET_ZCMP" + "cm.push {ra, s0-s4}, %0" +) + +(define_insn "@gpr_multi_push_up_to_s5_" + [(set (mem:X (plus:X (reg:X SP_REGNUM) + (const_int ))) + (reg:X S5_REGNUM)) + (set (mem:X (plus:X (reg:X SP_REGNUM) + (const_int ))) + (reg:X S4_REGNUM)) + (set (mem:X (plus:X (reg:X SP_REGNUM) + (const_int ))) + (reg:X S3_REGNUM)) + (set (mem:X (plus:X (reg:X SP_REGNUM) + (const_int ))) + (reg:X S2_REGNUM)) + (set (mem:X (plus:X (reg:X SP_REGNUM) + (const_int ))) + (reg:X S1_REGNUM)) + (set (mem:X (plus:X (reg:X SP_REGNUM) + (const_int ))) + (reg:X S0_REGNUM)) + (set (mem:X (plus:X (reg:X SP_REGNUM) + (const_int ))) + (reg:X RETURN_ADDR_REGNUM)) + (set (reg:X SP_REGNUM) + (plus:X (reg:X SP_REGNUM) + (match_operand 0 "stack_push_up_to_s5_operand" "I")))] + "TARGET_ZCMP" + "cm.push {ra, s0-s5}, %0" +) + +(define_insn "@gpr_multi_push_up_to_s6_" + [(set (mem:X (plus:X (reg:X SP_REGNUM) + (const_int ))) + (reg:X S6_REGNUM)) + (set (mem:X (plus:X (reg:X SP_REGNUM) + (const_int ))) + (reg:X S5_REGNUM)) + (set (mem:X (plus:X (reg:X SP_REGNUM) + (const_int ))) + (reg:X S4_REGNUM)) + (set (mem:X (plus:X (reg:X SP_REGNUM) + (const_int ))) + (reg:X S3_REGNUM)) + (set (mem:X (plus:X (reg:X SP_REGNUM) + (const_int ))) + (reg:X S2_REGNUM)) + (set (mem:X (plus:X (reg:X SP_REGNUM) + (const_int ))) + (reg:X S1_REGNUM)) + (set (mem:X (plus:X (reg:X SP_REGNUM) + (const_int ))) + (reg:X S0_REGNUM)) + (set (mem:X (plus:X (reg:X SP_REGNUM) + (const_int ))) + (reg:X RETURN_ADDR_REGNUM)) + (set (reg:X SP_REGNUM) + (plus:X (reg:X SP_REGNUM) + (match_operand 0 "stack_push_up_to_s6_operand" "I")))] + "TARGET_ZCMP" + "cm.push {ra, s0-s6}, %0" +) + +(define_insn "@gpr_multi_push_up_to_s7_" + [(set (mem:X (plus:X (reg:X SP_REGNUM) + (const_int ))) + (reg:X S7_REGNUM)) + (set (mem:X (plus:X (reg:X SP_REGNUM) + (const_int ))) + (reg:X S6_REGNUM)) + (set (mem:X (plus:X (reg:X SP_REGNUM) + (const_int ))) + (reg:X S5_REGNUM)) + (set (mem:X (plus:X (reg:X SP_REGNUM) + (const_int ))) + (reg:X S4_REGNUM)) + (set (mem:X (plus:X (reg:X SP_REGNUM) + (const_int ))) + (reg:X S3_REGNUM)) + (set (mem:X (plus:X (reg:X SP_REGNUM) + (const_int ))) + (reg:X S2_REGNUM)) + (set (mem:X (plus:X (reg:X SP_REGNUM) + (const_int ))) + (reg:X S1_REGNUM)) + (set (mem:X (plus:X (reg:X SP_REGNUM) + (const_int ))) + (reg:X S0_REGNUM)) + (set (mem:X (plus:X (reg:X SP_REGNUM) + (const_int ))) + (reg:X RETURN_ADDR_REGNUM)) + (set (reg:X SP_REGNUM) + (plus:X (reg:X SP_REGNUM) + (match_operand 0 "stack_push_up_to_s7_operand" "I")))] + "TARGET_ZCMP" + "cm.push {ra, s0-s7}, %0" +) + +(define_insn "@gpr_multi_push_up_to_s8_" + [(set (mem:X (plus:X (reg:X SP_REGNUM) + (const_int ))) + (reg:X S8_REGNUM)) + (set (mem:X (plus:X (reg:X SP_REGNUM) + (const_int ))) + (reg:X S7_REGNUM)) + (set (mem:X (plus:X (reg:X SP_REGNUM) + (const_int ))) + (reg:X S6_REGNUM)) + (set (mem:X (plus:X (reg:X SP_REGNUM) + (const_int ))) + (reg:X S5_REGNUM)) + (set (mem:X (plus:X (reg:X SP_REGNUM) + (const_int ))) + (reg:X S4_REGNUM)) + (set (mem:X (plus:X (reg:X SP_REGNUM) + (const_int ))) + (reg:X S3_REGNUM)) + (set (mem:X (plus:X (reg:X SP_REGNUM) + (const_int ))) + (reg:X S2_REGNUM)) + (set (mem:X (plus:X (reg:X SP_REGNUM) + (const_int ))) + (reg:X S1_REGNUM)) + (set (mem:X (plus:X (reg:X SP_REGNUM) + (const_int ))) + (reg:X S0_REGNUM)) + (set (mem:X (plus:X (reg:X SP_REGNUM) + (const_int ))) + (reg:X RETURN_ADDR_REGNUM)) + (set (reg:X SP_REGNUM) + (plus:X (reg:X SP_REGNUM) + (match_operand 0 "stack_push_up_to_s8_operand" "I")))] + "TARGET_ZCMP" + "cm.push {ra, s0-s8}, %0" +) + +(define_insn "@gpr_multi_push_up_to_s9_" + [(set (mem:X (plus:X (reg:X SP_REGNUM) + (const_int ))) + (reg:X S9_REGNUM)) + (set (mem:X (plus:X (reg:X SP_REGNUM) + (const_int ))) + (reg:X S8_REGNUM)) + (set (mem:X (plus:X (reg:X SP_REGNUM) + (const_int ))) + (reg:X S7_REGNUM)) + (set (mem:X (plus:X (reg:X SP_REGNUM) + (const_int ))) + (reg:X S6_REGNUM)) + (set (mem:X (plus:X (reg:X SP_REGNUM) + (const_int ))) + (reg:X S5_REGNUM)) + (set (mem:X (plus:X (reg:X SP_REGNUM) + (const_int ))) + (reg:X S4_REGNUM)) + (set (mem:X (plus:X (reg:X SP_REGNUM) + (const_int ))) + (reg:X S3_REGNUM)) + (set (mem:X (plus:X (reg:X SP_REGNUM) + (const_int ))) + (reg:X S2_REGNUM)) + (set (mem:X (plus:X (reg:X SP_REGNUM) + (const_int ))) + (reg:X S1_REGNUM)) + (set (mem:X (plus:X (reg:X SP_REGNUM) + (const_int ))) + (reg:X S0_REGNUM)) + (set (mem:X (plus:X (reg:X SP_REGNUM) + (const_int ))) + (reg:X RETURN_ADDR_REGNUM)) + (set (reg:X SP_REGNUM) + (plus:X (reg:X SP_REGNUM) + (match_operand 0 "stack_push_up_to_s9_operand" "I")))] + "TARGET_ZCMP" + "cm.push {ra, s0-s9}, %0" +) + +(define_insn "@gpr_multi_push_up_to_s11_" + [(set (mem:X (plus:X (reg:X SP_REGNUM) + (const_int ))) + (reg:X S11_REGNUM)) + (set (mem:X (plus:X (reg:X SP_REGNUM) + (const_int ))) + (reg:X S10_REGNUM)) + (set (mem:X (plus:X (reg:X SP_REGNUM) + (const_int ))) + (reg:X S9_REGNUM)) + (set (mem:X (plus:X (reg:X SP_REGNUM) + (const_int ))) + (reg:X S8_REGNUM)) + (set (mem:X (plus:X (reg:X SP_REGNUM) + (const_int ))) + (reg:X S7_REGNUM)) + (set (mem:X (plus:X (reg:X SP_REGNUM) + (const_int ))) + (reg:X S6_REGNUM)) + (set (mem:X (plus:X (reg:X SP_REGNUM) + (const_int ))) + (reg:X S5_REGNUM)) + (set (mem:X (plus:X (reg:X SP_REGNUM) + (const_int ))) + (reg:X S4_REGNUM)) + (set (mem:X (plus:X (reg:X SP_REGNUM) + (const_int ))) + (reg:X S3_REGNUM)) + (set (mem:X (plus:X (reg:X SP_REGNUM) + (const_int ))) + (reg:X S2_REGNUM)) + (set (mem:X (plus:X (reg:X SP_REGNUM) + (const_int ))) + (reg:X S1_REGNUM)) + (set (mem:X (plus:X (reg:X SP_REGNUM) + (const_int ))) + (reg:X S0_REGNUM)) + (set (mem:X (plus:X (reg:X SP_REGNUM) + (const_int ))) + (reg:X RETURN_ADDR_REGNUM)) + (set (reg:X SP_REGNUM) + (plus:X (reg:X SP_REGNUM) + (match_operand 0 "stack_push_up_to_s11_operand" "I")))] + "TARGET_ZCMP" + "cm.push {ra, s0-s11}, %0" +) diff --git a/gcc/testsuite/gcc.target/riscv/rv32e_zcmp.c b/gcc/testsuite/gcc.target/riscv/rv32e_zcmp.c new file mode 100644 index 00000000000..57c83249741 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rv32e_zcmp.c @@ -0,0 +1,256 @@ +/* { dg-do compile } */ +/* { dg-options " -Os -march=rv32e_zca_zcmp -mabi=ilp32e -mcmodel=medlow -fno-shrink-wrap-separate" } */ +/* { dg-skip-if "" { *-*-* } {"-O0" "-O1" "-O2" "-Og" "-O3" "-Oz" "-flto"} } */ +/* { dg-final { check-function-bodies "**" "" } } */ + +char +my_getchar (); +float +getf (); +int __attribute__ ((noinline)) +incoming_stack_args (int arg0, int arg1, int arg2, int arg3, int arg4, int arg5, + int arg6, int arg7, int arg8); +int +getint (); +void +PrintInts (int n, ...); // varargs +void __attribute__ ((noinline)) PrintIntsNoVaStart (int n, ...); // varargs +void +PrintInts2 (int arg0, int arg1, int arg2, int arg3, int arg4, int arg5, int n, + ...); +extern void +f1 (void); +extern void +f2 (void); + +/* +**test1: +** ... +** cm.push {ra, s0-s1}, -64 +** ... +** cm.popret {ra, s0-s1}, 64 +** ... +*/ +int +test1 () +{ + char volatile array[3120]; + float volatile farray[3120]; + + float sum = 0; + for (int i = 0; i < 3120; i++) + { + array[i] = my_getchar (); + farray[i] = my_getchar () * 1.2; + sum += array[i] + farray[i]; + } + return sum; +} + +/* +**test2_step1_0_size: +** ... +** cm.push {ra, s0}, -64 +** ... +** cm.popret {ra, s0}, 64 +** ... +*/ +int +test2_step1_0_size () +{ + int volatile iarray[3120 + 1824 / 4 - 8]; + + for (int i = 0; i < 3120 + 1824 / 4 - 8; i++) + { + iarray[i] = my_getchar () * 2; + } + return iarray[0] + iarray[1]; +} + +/* +**test3: +** ... +** cm.push {ra, s0-s1}, -64 +** ... +** cm.popret {ra, s0-s1}, 64 +** ... +*/ +float +test3 () +{ + char volatile array[3120]; + float volatile farray[3120]; + + float sum = 0, f1 = 0, f2 = 0, f3 = 0, f4 = 0, f5 = 0, f6 = 0, f7 = 0; + + for (int i = 0; i < 3120; i++) + { + f1 = getf (); + f2 = getf (); + f3 = getf (); + f4 = getf (); + array[i] = my_getchar (); + farray[i] = my_getchar () * 1.2; + sum += array[i] + farray[i] + f1 + f2 + f3 + f4; + } + return sum; +} + +/* +**outgoing_stack_args: +** ... +** cm.push {ra, s0}, -32 +** ... +** cm.popret {ra, s0}, 32 +** ... +*/ +int +outgoing_stack_args () +{ + int local = getint (); + return local + incoming_stack_args (0, 1, 2, 3, 4, 5, 6, 7, 8); +} + +/* +**callPrintInts: +** ... +** cm.push {ra}, -32 +** ... +** cm.popret {ra}, 32 +** ... +*/ +float +callPrintInts () +{ + volatile float f = getf (); // f in local + PrintInts (9, 1, 2, 3, 4, 5, 6, 7, 8, 9); + return f; +} + +/* +**callPrint: +** ... +** cm.push {ra}, -32 +** ... +** cm.popret {ra}, 32 +** ... +*/ +float +callPrint () +{ + volatile float f = getf (); // f in local + PrintIntsNoVaStart (0, 1, 2, 3, 4, 5, 6, 7, 8, 9); + return f; +} + +/* +**callPrint_S: +** ... +** cm.push {ra, s0}, -32 +** ... +** cm.popret {ra, s0}, 32 +** ... +*/ +float +callPrint_S () +{ + float f = getf (); + PrintIntsNoVaStart (0, 1, 2, 3, 4, 5, 6, 7, 8, 9); + return f; +} + +/* +**callPrint_2: +** ... +** cm.push {ra, s0}, -32 +** ... +** cm.popret {ra, s0}, 32 +** ... +*/ +float +callPrint_2 () +{ + float f = getf (); + PrintInts2 (0, 1, 2, 3, 4, 5, 6, 7, 8, 9); + return f; +} + +/* +**test_step1_0bytes_save_restore: +** ... +** cm.push {ra}, -16 +** ... +** cm.popret {ra}, 16 +** ... +*/ +int +test_step1_0bytes_save_restore () +{ + int a = 9; + int b = my_getchar (); + return a + b; +} + +/* +**test_s0: +** ... +** cm.push {ra, s0}, -16 +** ... +** cm.popret {ra, s0}, 16 +** ... +*/ +int +test_s0 () +{ + int a = my_getchar (); + int b = my_getchar (); + return a + b; +} + +/* +**test_s1: +** ... +** cm.push {ra, s0-s1}, -16 +** ... +** cm.popret {ra, s0-s1}, 16 +** ... +*/ +int +test_s1 () +{ + int s0 = my_getchar (); + int s1 = my_getchar (); + int b = my_getchar (); + return s1 + s0 + b; +} + +/* +**test_f0: +** ... +** cm.push {ra, s0-s1}, -16 +** ... +** cm.popret {ra, s0-s1}, 16 +** ... +*/ +int +test_f0 () +{ + int s0 = my_getchar (); + float f0 = getf (); + int b = my_getchar (); + return f0 + s0 + b; +} + +/* +**foo: +** cm.push {ra}, -16 +** call f1 +** cm.pop {ra}, 16 +** tail f2 +*/ +void +foo (void) +{ + f1 (); + f2 (); +} diff --git a/gcc/testsuite/gcc.target/riscv/rv32i_zcmp.c b/gcc/testsuite/gcc.target/riscv/rv32i_zcmp.c new file mode 100644 index 00000000000..f24e0a8bab9 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rv32i_zcmp.c @@ -0,0 +1,256 @@ +/* { dg-do compile } */ +/* { dg-options " -Os -march=rv32imaf_zca_zcmp -mabi=ilp32f -mcmodel=medlow -fno-shrink-wrap-separate" }*/ +/* { dg-skip-if "" { *-*-* } {"-O0" "-O1" "-O2" "-Og" "-O3" "-Oz" "-flto"} } */ +/* { dg-final { check-function-bodies "**" "" } } */ + +char +my_getchar (); +float +getf (); +int __attribute__ ((noinline)) +incoming_stack_args (int arg0, int arg1, int arg2, int arg3, int arg4, int arg5, + int arg6, int arg7, int arg8); +int +getint (); +void +PrintInts (int n, ...); // varargs +void __attribute__ ((noinline)) PrintIntsNoVaStart (int n, ...); // varargs +void +PrintInts2 (int arg0, int arg1, int arg2, int arg3, int arg4, int arg5, int n, + ...); +extern void +f1 (void); +extern void +f2 (void); + +/* +**test1: +** ... +** cm.push {ra, s0-s4}, -80 +** ... +** cm.popret {ra, s0-s4}, 80 +** ... +*/ +int +test1 () +{ + char volatile array[3120]; + float volatile farray[3120]; + + float sum = 0; + for (int i = 0; i < 3120; i++) + { + array[i] = my_getchar (); + farray[i] = my_getchar () * 1.2; + sum += array[i] + farray[i]; + } + return sum; +} + +/* +**test2_step1_0_size: +** ... +** cm.push {ra, s0-s1}, -64 +** ... +** cm.popret {ra, s0-s1}, 64 +** ... +*/ +int +test2_step1_0_size () +{ + int volatile iarray[3120 + 1824 / 4 - 8]; + + for (int i = 0; i < 3120 + 1824 / 4 - 8; i++) + { + iarray[i] = my_getchar () * 2; + } + return iarray[0] + iarray[1]; +} + +/* +**test3: +** ... +** cm.push {ra, s0-s4}, -80 +** ... +** cm.popret {ra, s0-s4}, 80 +** ... +*/ +float +test3 () +{ + char volatile array[3120]; + float volatile farray[3120]; + + float sum = 0, f1 = 0, f2 = 0, f3 = 0, f4 = 0, f5 = 0, f6 = 0, f7 = 0; + + for (int i = 0; i < 3120; i++) + { + f1 = getf (); + f2 = getf (); + f3 = getf (); + f4 = getf (); + array[i] = my_getchar (); + farray[i] = my_getchar () * 1.2; + sum += array[i] + farray[i] + f1 + f2 + f3 + f4; + } + return sum; +} + +/* +**outgoing_stack_args: +** ... +** cm.push {ra, s0}, -32 +** ... +** cm.popret {ra, s0}, 32 +** ... +*/ +int +outgoing_stack_args () +{ + int local = getint (); + return local + incoming_stack_args (0, 1, 2, 3, 4, 5, 6, 7, 8); +} + +/* +**callPrintInts: +** ... +** cm.push {ra}, -48 +** ... +** cm.popret {ra}, 48 +** ... +*/ +float +callPrintInts () +{ + volatile float f = getf (); // f in local + PrintInts (9, 1, 2, 3, 4, 5, 6, 7, 8, 9); + return f; +} + +/* +**callPrint: +** ... +** cm.push {ra}, -48 +** ... +** cm.popret {ra}, 48 +** ... +*/ +float +callPrint () +{ + volatile float f = getf (); // f in local + PrintIntsNoVaStart (0, 1, 2, 3, 4, 5, 6, 7, 8, 9); + return f; +} + +/* +**callPrint_S: +** ... +** cm.push {ra}, -48 +** ... +** cm.popret {ra}, 48 +** ... +*/ +float +callPrint_S () +{ + float f = getf (); + PrintIntsNoVaStart (0, 1, 2, 3, 4, 5, 6, 7, 8, 9); + return f; +} + +/* +**callPrint_2: +** ... +** cm.push {ra}, -48 +** ... +** cm.popret {ra}, 48 +** ... +*/ +float +callPrint_2 () +{ + float f = getf (); + PrintInts2 (0, 1, 2, 3, 4, 5, 6, 7, 8, 9); + return f; +} + +/* +**test_step1_0bytes_save_restore: +** ... +** cm.push {ra}, -16 +** ... +** cm.popret {ra}, 16 +** ... +*/ +int +test_step1_0bytes_save_restore () +{ + int a = 9; + int b = my_getchar (); + return a + b; +} + +/* +**test_s0: +** ... +** cm.push {ra, s0}, -16 +** ... +** cm.popret {ra, s0}, 16 +** ... +*/ +int +test_s0 () +{ + int a = my_getchar (); + int b = my_getchar (); + return a + b; +} + +/* +**test_s1: +** ... +** cm.push {ra, s0-s1}, -16 +** ... +** cm.popret {ra, s0-s1}, 16 +** ... +*/ +int +test_s1 () +{ + int s0 = my_getchar (); + int s1 = my_getchar (); + int b = my_getchar (); + return s1 + s0 + b; +} + +/* +**test_f0: +** ... +** cm.push {ra, s0}, -32 +** ... +** cm.popret {ra, s0}, 32 +** ... +*/ +int +test_f0 () +{ + int s0 = my_getchar (); + float f0 = getf (); + int b = my_getchar (); + return f0 + s0 + b; +} + +/* +**foo: +** cm.push {ra}, -16 +** call f1 +** cm.pop {ra}, 16 +** tail f2 +*/ +void +foo (void) +{ + f1 (); + f2 (); +} diff --git a/gcc/testsuite/gcc.target/riscv/zcmp_push_fpr.c b/gcc/testsuite/gcc.target/riscv/zcmp_push_fpr.c new file mode 100644 index 00000000000..530b35b53dd --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/zcmp_push_fpr.c @@ -0,0 +1,34 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64imafd_zicsr_zifencei_zca_zcmp -mabi=lp64d -Os -fno-shrink-wrap-separate" } */ +/* { dg-skip-if "" { *-*-* } {"-O0" "-O1" "-O2" "-Og" "-O3" "-Oz" "-flto"} } */ + +typedef struct +{ + struct + { + struct + { + struct + { + long a; + }; + } a[129]; + }; +} b; + +struct c +{ + void *a[129]; +}; + +extern void +f (struct c, b *); + +struct c +d () +{ + struct c a; + __builtin_unwind_init (); + b e; + f (a, &e); +} diff --git a/gcc/testsuite/gcc.target/riscv/zcmp_stack_alignment.c b/gcc/testsuite/gcc.target/riscv/zcmp_stack_alignment.c new file mode 100644 index 00000000000..2f2fa55baac --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/zcmp_stack_alignment.c @@ -0,0 +1,24 @@ +/* { dg-do compile } */ +/* { dg-options " -O0 -march=rv32e_zca_zcb_zcmp -mabi=ilp32e -mcmodel=medlow -fomit-frame-pointer -fno-shrink-wrap-separate" } */ +/* { dg-skip-if "" { *-*-* } {"-O2" "-O1" "-Os" "-Og" "-O3" "-Oz" "-flto"} } */ +/* { dg-final { check-function-bodies "**" "" } } */ + +void +bar (); + +/* +**fool_rv32e: +** cm.push {ra}, -32 +** ... +** call bar +** ... +** lw a[0-5],32\(sp\) +** ... +** cm.popret {ra}, 32 +*/ +int +fool_rv32e (int a0, int a1, int a2, int a3, int a4, int a5, int incoming0) +{ + bar (); + return a0 + a1 + a2 + a3 + a4 + a5 + incoming0; +} From patchwork Tue Aug 29 08:37:45 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Fei Gao X-Patchwork-Id: 1827140 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=8.43.85.97; helo=server2.sourceware.org; envelope-from=gcc-patches-bounces+incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=patchwork.ozlabs.org) Received: from server2.sourceware.org (ip-8-43-85-97.sourceware.org [8.43.85.97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4RZgpF0NPCz1yfy for ; Tue, 29 Aug 2023 18:39:32 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id D4D493857736 for ; Tue, 29 Aug 2023 08:39:30 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from azure-sdnproxy.icoremail.net (azure-sdnproxy.icoremail.net [52.237.72.81]) by sourceware.org (Postfix) with ESMTP id 420783858C74 for ; Tue, 29 Aug 2023 08:38:07 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 420783858C74 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=eswincomputing.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=eswincomputing.com Received: from localhost.localdomain (unknown [10.12.130.31]) by app2 (Coremail) with SMTP id EggMCgB3vpRmru1k10lCAA--.2645S6; Tue, 29 Aug 2023 16:38:02 +0800 (CST) From: Fei Gao To: gcc-patches@gcc.gnu.org Subject: [PATCH 2/3] [V2] [RISC-V] support cm.popretz in zcmp Date: Tue, 29 Aug 2023 08:37:45 +0000 Message-Id: <20230829083746.1458-3-gaofei@eswincomputing.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20230829083746.1458-1-gaofei@eswincomputing.com> References: <20230829083746.1458-1-gaofei@eswincomputing.com> X-CM-TRANSID: EggMCgB3vpRmru1k10lCAA--.2645S6 X-Coremail-Antispam: 1UD129KBjvAXoWfAr4rZw13GryDGFykXFW5Wrg_yoW8uFy3Wo W0ganYyw1rGF9ru3s5C3y3t3s5JrWvgrW8WFn5Zr1UAas3try2qr9F93WkZFn7tr10qw48 XFs7AF1vvay5Jrn8n29KB7ZKAUJUUUUU529EdanIXcx71UUUUU7v73VFW2AGmfu7bjvjm3 AaLaJ3UjIYCTnIWjp_UUUOe7AC8VAFwI0_Wr0E3s1l1xkIjI8I6I8E6xAIw20EY4v20xva j40_Wr0E3s1l1IIY67AEw4v_Jr0_Jr4l82xGYIkIc2x26280x7IE14v26r15M28IrcIa0x kI8VCY1x0267AKxVW8JVW5JwA2ocxC64kIII0Yj41l84x0c7CEw4AK67xGY2AK021l84AC jcxK6xIIjxv20xvE14v26w1j6s0DM28EF7xvwVC0I7IYx2IY6xkF7I0E14v26r4UJVWxJr 1l84ACjcxK6I8E87Iv67AKxVW0oVCq3wA2z4x0Y4vEx4A2jsIEc7CjxVAFwI0_GcCE3s1l e2I262IYc4CY6c8Ij28IcVAaY2xG8wAqx4xG64xvF2IEw4CE5I8CrVC2j2WlYx0E2Ix0cI 8IcVAFwI0_Jr0_Jr4lYx0Ex4A2jsIE14v26r1j6r4UMcvjeVCFs4IE7xkEbVWUJVW8JwAC jcxG0xvY0x0EwIxGrwACjI8F5VA0II8E6IAqYI8I648v4I1lc7CjxVAKzI0EY4vE52x082 I5MxkIecxEwVCm-wCF04k20xvY0x0EwIxGrwCFx2IqxVCFs4IE7xkEbVWUJVW8JwC20s02 6c02F40E14v26r1j6r18MI8I3I0E7480Y4vE14v26r106r1rMI8E67AF67kF1VAFwI0_Jw 0_GFylIxkGc2Ij64vIr41lIxAIcVC0I7IYx2IY67AKxVWUJVWUCwCI42IY6xIIjxv20xvE c7CjxVAFwI0_Gr0_Cr1lIxAIcVCF04k26cxKx2IYs7xG6r1j6r1xMIIF0xvEx4A2jsIE14 v26r1j6r4UMIIF0xvEx4A2jsIEc7CjxVAFwI0_Gr0_Gr1UYxBIdaVFxhVjvjDU0xZFpf9x 0pRLqXdUUUUU= X-CM-SenderInfo: xjdrwv3l6h245lqf0zpsxwx03jof0z/ X-Spam-Status: No, score=-11.7 required=5.0 tests=BAYES_00, GIT_PATCH_0, KAM_DMARC_STATUS, KAM_SHORT, RCVD_IN_DNSWL_LOW, RCVD_IN_MSPIKE_H2, SPF_HELO_NONE, SPF_PASS, TXREP 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.30 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: kito.cheng@gmail.com, jiawei@iscas.ac.cn Errors-To: gcc-patches-bounces+incoming=patchwork.ozlabs.org@gcc.gnu.org Sender: "Gcc-patches" Generate cm.popretz instead of cm.popret if return value is 0. gcc/ChangeLog: * config/riscv/riscv.cc (riscv_zcmp_can_use_popretz): true if popretz can be used (riscv_gen_multi_pop_insn): interface to generate cm.pop[ret][z] (riscv_expand_epilogue): expand cm.pop[ret][z] in epilogue * config/riscv/riscv.md: define A0_REGNUM * config/riscv/zc.md (@gpr_multi_popretz_up_to_ra_): md for popretz ra (@gpr_multi_popretz_up_to_s0_): md for popretz ra, s0 (@gpr_multi_popretz_up_to_s1_): likewise (@gpr_multi_popretz_up_to_s2_): likewise (@gpr_multi_popretz_up_to_s3_): likewise (@gpr_multi_popretz_up_to_s4_): likewise (@gpr_multi_popretz_up_to_s5_): likewise (@gpr_multi_popretz_up_to_s6_): likewise (@gpr_multi_popretz_up_to_s7_): likewise (@gpr_multi_popretz_up_to_s8_): likewise (@gpr_multi_popretz_up_to_s9_): likewise (@gpr_multi_popretz_up_to_s11_): likewise gcc/testsuite/ChangeLog: * gcc.target/riscv/rv32e_zcmp.c: add testcase for cm.popretz in rv32e * gcc.target/riscv/rv32i_zcmp.c: add testcase for cm.popretz in rv32i --- gcc/config/riscv/riscv.cc | 114 ++++-- gcc/config/riscv/riscv.md | 1 + gcc/config/riscv/zc.md | 393 ++++++++++++++++++++ gcc/testsuite/gcc.target/riscv/rv32e_zcmp.c | 13 + gcc/testsuite/gcc.target/riscv/rv32i_zcmp.c | 13 + 5 files changed, 509 insertions(+), 25 deletions(-) diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc index ed4d28b2eb0..78600ba73b6 100644 --- a/gcc/config/riscv/riscv.cc +++ b/gcc/config/riscv/riscv.cc @@ -422,6 +422,7 @@ typedef enum PUSH_IDX = 0, POP_IDX, POPRET_IDX, + POPRETZ_IDX, ZCMP_OP_NUM } riscv_zcmp_op_t; @@ -6238,30 +6239,31 @@ riscv_emit_stack_tie (void) /*zcmp multi push and pop code_for_push_pop function ptr array */ const code_for_push_pop_t code_for_push_pop[ZCMP_MAX_GRP_SLOTS][ZCMP_OP_NUM] = {{code_for_gpr_multi_push_up_to_ra, code_for_gpr_multi_pop_up_to_ra, - code_for_gpr_multi_popret_up_to_ra}, + code_for_gpr_multi_popret_up_to_ra, code_for_gpr_multi_popretz_up_to_ra}, {code_for_gpr_multi_push_up_to_s0, code_for_gpr_multi_pop_up_to_s0, - code_for_gpr_multi_popret_up_to_s0}, + code_for_gpr_multi_popret_up_to_s0, code_for_gpr_multi_popretz_up_to_s0}, {code_for_gpr_multi_push_up_to_s1, code_for_gpr_multi_pop_up_to_s1, - code_for_gpr_multi_popret_up_to_s1}, + code_for_gpr_multi_popret_up_to_s1, code_for_gpr_multi_popretz_up_to_s1}, {code_for_gpr_multi_push_up_to_s2, code_for_gpr_multi_pop_up_to_s2, - code_for_gpr_multi_popret_up_to_s2}, + code_for_gpr_multi_popret_up_to_s2, code_for_gpr_multi_popretz_up_to_s2}, {code_for_gpr_multi_push_up_to_s3, code_for_gpr_multi_pop_up_to_s3, - code_for_gpr_multi_popret_up_to_s3}, + code_for_gpr_multi_popret_up_to_s3, code_for_gpr_multi_popretz_up_to_s3}, {code_for_gpr_multi_push_up_to_s4, code_for_gpr_multi_pop_up_to_s4, - code_for_gpr_multi_popret_up_to_s4}, + code_for_gpr_multi_popret_up_to_s4, code_for_gpr_multi_popretz_up_to_s4}, {code_for_gpr_multi_push_up_to_s5, code_for_gpr_multi_pop_up_to_s5, - code_for_gpr_multi_popret_up_to_s5}, + code_for_gpr_multi_popret_up_to_s5, code_for_gpr_multi_popretz_up_to_s5}, {code_for_gpr_multi_push_up_to_s6, code_for_gpr_multi_pop_up_to_s6, - code_for_gpr_multi_popret_up_to_s6}, + code_for_gpr_multi_popret_up_to_s6, code_for_gpr_multi_popretz_up_to_s6}, {code_for_gpr_multi_push_up_to_s7, code_for_gpr_multi_pop_up_to_s7, - code_for_gpr_multi_popret_up_to_s7}, + code_for_gpr_multi_popret_up_to_s7, code_for_gpr_multi_popretz_up_to_s7}, {code_for_gpr_multi_push_up_to_s8, code_for_gpr_multi_pop_up_to_s8, - code_for_gpr_multi_popret_up_to_s8}, + code_for_gpr_multi_popret_up_to_s8, code_for_gpr_multi_popretz_up_to_s8}, {code_for_gpr_multi_push_up_to_s9, code_for_gpr_multi_pop_up_to_s9, - code_for_gpr_multi_popret_up_to_s9}, - {nullptr, nullptr, nullptr}, + code_for_gpr_multi_popret_up_to_s9, code_for_gpr_multi_popretz_up_to_s9}, + {nullptr, nullptr, nullptr, nullptr}, {code_for_gpr_multi_push_up_to_s11, code_for_gpr_multi_pop_up_to_s11, - code_for_gpr_multi_popret_up_to_s11}}; + code_for_gpr_multi_popret_up_to_s11, + code_for_gpr_multi_popretz_up_to_s11}}; static rtx riscv_gen_multi_push_pop_insn (riscv_zcmp_op_t op, HOST_WIDE_INT adj_size, @@ -6474,6 +6476,78 @@ riscv_adjust_libcall_cfi_epilogue () return dwarf; } +/* return true if popretz pattern can be matched. + set (reg 10 a0) (const_int 0) + use (reg 10 a0) + NOTE_INSN_EPILOGUE_BEG */ +static rtx_insn * +riscv_zcmp_can_use_popretz (void) +{ + rtx_insn *insn = NULL, *use = NULL, *clear = NULL; + + /* sequence stack for NOTE_INSN_EPILOGUE_BEG*/ + struct sequence_stack *outer_seq = get_current_sequence ()->next; + if (!outer_seq) + return NULL; + insn = outer_seq->first; + if (!insn || !NOTE_P (insn) || NOTE_KIND (insn) != NOTE_INSN_EPILOGUE_BEG) + return NULL; + + /* sequence stack for the insn before NOTE_INSN_EPILOGUE_BEG*/ + outer_seq = outer_seq->next; + if (outer_seq) + insn = outer_seq->last; + + /* skip notes */ + while (insn && NOTE_P (insn)) + { + insn = PREV_INSN (insn); + } + use = insn; + + /* match use (reg 10 a0) */ + if (use == NULL || !INSN_P (use) || GET_CODE (PATTERN (use)) != USE + || !REG_P (XEXP (PATTERN (use), 0)) + || REGNO (XEXP (PATTERN (use), 0)) != A0_REGNUM) + return NULL; + + /* match set (reg 10 a0) (const_int 0 [0]) */ + clear = PREV_INSN (use); + if (clear != NULL && INSN_P (clear) && GET_CODE (PATTERN (clear)) == SET + && REG_P (SET_DEST (PATTERN (clear))) + && REGNO (SET_DEST (PATTERN (clear))) == A0_REGNUM + && SET_SRC (PATTERN (clear)) == const0_rtx) + return clear; + + return NULL; +} + +static void +riscv_gen_multi_pop_insn (bool use_multi_pop_normal, unsigned mask, + unsigned multipop_size) +{ + rtx insn; + unsigned regs_count = riscv_multi_push_regs_count (mask); + + if (!use_multi_pop_normal) + insn = emit_insn ( + riscv_gen_multi_push_pop_insn (POP_IDX, multipop_size, regs_count)); + else if (rtx_insn *clear_a0_insn = riscv_zcmp_can_use_popretz ()) + { + delete_insn (NEXT_INSN (clear_a0_insn)); + delete_insn (clear_a0_insn); + insn = emit_jump_insn ( + riscv_gen_multi_push_pop_insn (POPRETZ_IDX, multipop_size, regs_count)); + } + else + insn = emit_jump_insn ( + riscv_gen_multi_push_pop_insn (POPRET_IDX, multipop_size, regs_count)); + + rtx dwarf = riscv_adjust_multi_pop_cfi_epilogue (multipop_size); + RTX_FRAME_RELATED_P (insn) = 1; + REG_NOTES (insn) = dwarf; +} + /* Expand an "epilogue", "sibcall_epilogue", or "eh_return_internal" pattern; style says which. */ @@ -6698,18 +6772,8 @@ riscv_expand_epilogue (int style) /* Undo the above fib. */ frame->mask = mask; frame->fmask = fmask; - unsigned regs_count = riscv_multi_push_regs_count (frame->mask); - if (use_multi_pop_normal) - insn = emit_jump_insn (riscv_gen_multi_push_pop_insn (POPRET_IDX, - multipop_size, - regs_count)); - else - insn = emit_insn ( - riscv_gen_multi_push_pop_insn (POP_IDX, multipop_size, regs_count)); - - rtx dwarf = riscv_adjust_multi_pop_cfi_epilogue (multipop_size); - RTX_FRAME_RELATED_P (insn) = 1; - REG_NOTES (insn) = dwarf; + riscv_gen_multi_pop_insn (use_multi_pop_normal, frame->mask, + multipop_size); if (use_multi_pop_normal) return; } diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md index f489646cec3..8e09df6ff63 100644 --- a/gcc/config/riscv/riscv.md +++ b/gcc/config/riscv/riscv.md @@ -131,6 +131,7 @@ (T1_REGNUM 6) (S0_REGNUM 8) (S1_REGNUM 9) + (A0_REGNUM 10) (S2_REGNUM 18) (S3_REGNUM 19) (S4_REGNUM 20) diff --git a/gcc/config/riscv/zc.md b/gcc/config/riscv/zc.md index 5c1bf031b8d..8d7de97daad 100644 --- a/gcc/config/riscv/zc.md +++ b/gcc/config/riscv/zc.md @@ -708,6 +708,399 @@ "cm.popret {ra, s0-s11}, %0" ) +(define_insn "@gpr_multi_popretz_up_to_ra_" + [(set (reg:X SP_REGNUM) + (plus:X (reg:X SP_REGNUM) + (match_operand 0 "stack_pop_up_to_ra_operand" "I"))) + (set (reg:X RETURN_ADDR_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X A0_REGNUM) + (const_int 0)) + (use (reg:X A0_REGNUM)) + (return) + (use (reg:SI RETURN_ADDR_REGNUM))] + "TARGET_ZCMP" + "cm.popretz {ra}, %0" +) + +(define_insn "@gpr_multi_popretz_up_to_s0_" + [(set (reg:X SP_REGNUM) + (plus:X (reg:X SP_REGNUM) + (match_operand 0 "stack_pop_up_to_s0_operand" "I"))) + (set (reg:X S0_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X RETURN_ADDR_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X A0_REGNUM) + (const_int 0)) + (use (reg:X A0_REGNUM)) + (return) + (use (reg:SI RETURN_ADDR_REGNUM))] + "TARGET_ZCMP" + "cm.popretz {ra, s0}, %0" +) + +(define_insn "@gpr_multi_popretz_up_to_s1_" + [(set (reg:X SP_REGNUM) + (plus:X (reg:X SP_REGNUM) + (match_operand 0 "stack_pop_up_to_s1_operand" "I"))) + (set (reg:X S1_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S0_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X RETURN_ADDR_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X A0_REGNUM) + (const_int 0)) + (use (reg:X A0_REGNUM)) + (return) + (use (reg:SI RETURN_ADDR_REGNUM))] + "TARGET_ZCMP" + "cm.popretz {ra, s0-s1}, %0" +) + +(define_insn "@gpr_multi_popretz_up_to_s2_" + [(set (reg:X SP_REGNUM) + (plus:X (reg:X SP_REGNUM) + (match_operand 0 "stack_pop_up_to_s2_operand" "I"))) + (set (reg:X S2_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S1_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S0_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X RETURN_ADDR_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X A0_REGNUM) + (const_int 0)) + (use (reg:X A0_REGNUM)) + (return) + (use (reg:SI RETURN_ADDR_REGNUM))] + "TARGET_ZCMP" + "cm.popretz {ra, s0-s2}, %0" +) + +(define_insn "@gpr_multi_popretz_up_to_s3_" + [(set (reg:X SP_REGNUM) + (plus:X (reg:X SP_REGNUM) + (match_operand 0 "stack_pop_up_to_s3_operand" "I"))) + (set (reg:X S3_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S2_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S1_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S0_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X RETURN_ADDR_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X A0_REGNUM) + (const_int 0)) + (use (reg:X A0_REGNUM)) + (return) + (use (reg:SI RETURN_ADDR_REGNUM))] + "TARGET_ZCMP" + "cm.popretz {ra, s0-s3}, %0" +) + +(define_insn "@gpr_multi_popretz_up_to_s4_" + [(set (reg:X SP_REGNUM) + (plus:X (reg:X SP_REGNUM) + (match_operand 0 "stack_pop_up_to_s4_operand" "I"))) + (set (reg:X S4_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S3_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S2_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S1_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S0_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X RETURN_ADDR_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X A0_REGNUM) + (const_int 0)) + (use (reg:X A0_REGNUM)) + (return) + (use (reg:SI RETURN_ADDR_REGNUM))] + "TARGET_ZCMP" + "cm.popretz {ra, s0-s4}, %0" +) + +(define_insn "@gpr_multi_popretz_up_to_s5_" + [(set (reg:X SP_REGNUM) + (plus:X (reg:X SP_REGNUM) + (match_operand 0 "stack_pop_up_to_s5_operand" "I"))) + (set (reg:X S5_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S4_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S3_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S2_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S1_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S0_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X RETURN_ADDR_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X A0_REGNUM) + (const_int 0)) + (use (reg:X A0_REGNUM)) + (return) + (use (reg:SI RETURN_ADDR_REGNUM))] + "TARGET_ZCMP" + "cm.popretz {ra, s0-s5}, %0" +) + +(define_insn "@gpr_multi_popretz_up_to_s6_" + [(set (reg:X SP_REGNUM) + (plus:X (reg:X SP_REGNUM) + (match_operand 0 "stack_pop_up_to_s6_operand" "I"))) + (set (reg:X S6_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S5_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S4_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S3_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S2_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S1_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S0_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X RETURN_ADDR_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X A0_REGNUM) + (const_int 0)) + (use (reg:X A0_REGNUM)) + (return) + (use (reg:SI RETURN_ADDR_REGNUM))] + "TARGET_ZCMP" + "cm.popretz {ra, s0-s6}, %0" +) + +(define_insn "@gpr_multi_popretz_up_to_s7_" + [(set (reg:X SP_REGNUM) + (plus:X (reg:X SP_REGNUM) + (match_operand 0 "stack_pop_up_to_s7_operand" "I"))) + (set (reg:X S7_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S6_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S5_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S4_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S3_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S2_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S1_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S0_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X RETURN_ADDR_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X A0_REGNUM) + (const_int 0)) + (use (reg:X A0_REGNUM)) + (return) + (use (reg:SI RETURN_ADDR_REGNUM))] + "TARGET_ZCMP" + "cm.popretz {ra, s0-s7}, %0" +) + +(define_insn "@gpr_multi_popretz_up_to_s8_" + [(set (reg:X SP_REGNUM) + (plus:X (reg:X SP_REGNUM) + (match_operand 0 "stack_pop_up_to_s8_operand" "I"))) + (set (reg:X S8_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S7_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S6_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S5_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S4_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S3_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S2_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S1_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S0_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X RETURN_ADDR_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X A0_REGNUM) + (const_int 0)) + (use (reg:X A0_REGNUM)) + (return) + (use (reg:SI RETURN_ADDR_REGNUM))] + "TARGET_ZCMP" + "cm.popretz {ra, s0-s8}, %0" +) + +(define_insn "@gpr_multi_popretz_up_to_s9_" + [(set (reg:X SP_REGNUM) + (plus:X (reg:X SP_REGNUM) + (match_operand 0 "stack_pop_up_to_s9_operand" "I"))) + (set (reg:X S9_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S8_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S7_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S6_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S5_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S4_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S3_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S2_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S1_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S0_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X RETURN_ADDR_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X A0_REGNUM) + (const_int 0)) + (use (reg:X A0_REGNUM)) + (return) + (use (reg:SI RETURN_ADDR_REGNUM))] + "TARGET_ZCMP" + "cm.popretz {ra, s0-s9}, %0" +) + +(define_insn "@gpr_multi_popretz_up_to_s11_" + [(set (reg:X SP_REGNUM) + (plus:X (reg:X SP_REGNUM) + (match_operand 0 "stack_pop_up_to_s11_operand" "I"))) + (set (reg:X S11_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S10_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S9_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S8_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S7_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S6_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S5_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S4_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S3_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S2_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S1_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X S0_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X RETURN_ADDR_REGNUM) + (mem:X (plus:X (reg:X SP_REGNUM) + (const_int )))) + (set (reg:X A0_REGNUM) + (const_int 0)) + (use (reg:X A0_REGNUM)) + (return) + (use (reg:SI RETURN_ADDR_REGNUM))] + "TARGET_ZCMP" + "cm.popretz {ra, s0-s11}, %0" +) + (define_insn "@gpr_multi_push_up_to_ra_" [(set (mem:X (plus:X (reg:X SP_REGNUM) (const_int ))) diff --git a/gcc/testsuite/gcc.target/riscv/rv32e_zcmp.c b/gcc/testsuite/gcc.target/riscv/rv32e_zcmp.c index 57c83249741..394459c4ed7 100644 --- a/gcc/testsuite/gcc.target/riscv/rv32e_zcmp.c +++ b/gcc/testsuite/gcc.target/riscv/rv32e_zcmp.c @@ -254,3 +254,16 @@ foo (void) f1 (); f2 (); } + +/* +**test_popretz: +** cm.push {ra}, -16 +** call f1 +** cm.popretz {ra}, 16 +*/ +long +test_popretz () +{ + f1 (); + return 0; +} diff --git a/gcc/testsuite/gcc.target/riscv/rv32i_zcmp.c b/gcc/testsuite/gcc.target/riscv/rv32i_zcmp.c index f24e0a8bab9..f00338a9d17 100644 --- a/gcc/testsuite/gcc.target/riscv/rv32i_zcmp.c +++ b/gcc/testsuite/gcc.target/riscv/rv32i_zcmp.c @@ -254,3 +254,16 @@ foo (void) f1 (); f2 (); } + +/* +**test_popretz: +** cm.push {ra}, -16 +** call f1 +** cm.popretz {ra}, 16 +*/ +long +test_popretz () +{ + f1 (); + return 0; +} From patchwork Tue Aug 29 08:37:46 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Fei Gao X-Patchwork-Id: 1827138 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=2620:52:3:1:0:246e:9693:128c; helo=server2.sourceware.org; envelope-from=gcc-patches-bounces+incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=patchwork.ozlabs.org) Received: from server2.sourceware.org (server2.sourceware.org [IPv6:2620:52:3:1:0:246e:9693:128c]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4RZgnb5Ctrz1yfy for ; Tue, 29 Aug 2023 18:38:59 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id C873C385703C for ; Tue, 29 Aug 2023 08:38:57 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from zg8tndyumtaxlji0oc4xnzya.icoremail.net (zg8tndyumtaxlji0oc4xnzya.icoremail.net [46.101.248.176]) by sourceware.org (Postfix) with ESMTP id A89833858C20 for ; Tue, 29 Aug 2023 08:38:07 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org A89833858C20 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=eswincomputing.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=eswincomputing.com Received: from localhost.localdomain (unknown [10.12.130.31]) by app2 (Coremail) with SMTP id EggMCgB3vpRmru1k10lCAA--.2645S7; Tue, 29 Aug 2023 16:38:04 +0800 (CST) From: Fei Gao To: gcc-patches@gcc.gnu.org Subject: [PATCH 3/3] [V2] [RISC-V] support cm.mva01s cm.mvsa01 in zcmp Date: Tue, 29 Aug 2023 08:37:46 +0000 Message-Id: <20230829083746.1458-4-gaofei@eswincomputing.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20230829083746.1458-1-gaofei@eswincomputing.com> References: <20230829083746.1458-1-gaofei@eswincomputing.com> X-CM-TRANSID: EggMCgB3vpRmru1k10lCAA--.2645S7 X-Coremail-Antispam: 1UD129KBjvJXoW3JFW8Zw4kJrykAr4xWr13XFb_yoW7WF47pr 4UKw1YkrW8Zrs3K34ftFWxJw4Ykrs3KFWYy39xCasFk3yUJryDJF1vkFyaqFWDXF4ftr43 Ca1xCw4Y9w1Yk3DanT9S1TB71UUUUUUqnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUUPS14x267AKxVWrJVCq3wAFc2x0x2IEx4CE42xK8VAvwI8IcIk0 rVWrJVCq3wAFIxvE14AKwVWUJVWUGwA2048vs2IY020E87I2jVAFwI0_JrWl82xGYIkIc2 x26xkF7I0E14v26ryj6s0DM28lY4IEw2IIxxk0rwA2F7IY1VAKz4vEj48ve4kI8wA2z4x0 Y4vE2Ix0cI8IcVAFwI0_tr0E3s1l84ACjcxK6xIIjxv20xvEc7CjxVAFwI0_Gr1j6F4UJw A2z4x0Y4vEx4A2jsIE14v26rxl6s0DM28EF7xvwVC2z280aVCY1x0267AKxVW0oVCq3wAS 0I0E0xvYzxvE52x082IY62kv0487Mc02F40EFcxC0VAKzVAqx4xG6I80ewAv7VC0I7IYx2 IY67AKxVWUJVWUGwAv7VC2z280aVAFwI0_Jr0_Gr1lOx8S6xCaFVCjc4AY6r1j6r4UM4x0 Y48IcxkI7VAKI48JM4x0x7Aq67IIx4CEVc8vx2IErcIFxwCY1x0264kExVAvwVAq07x20x ylc2xSY4AK6svPMxAIw28IcxkI7VAKI48JMxC20s026xCaFVCjc4AY6r1j6r4UMI8I3I0E 5I8CrVAFwI0_Jr0_Jr4lx2IqxVCjr7xvwVAFwI0_JrI_JrWlx4CE17CEb7AF67AKxVWUtV W8ZwCIc40Y0x0EwIxGrwCI42IY6xIIjxv20xvE14v26r1j6r1xMIIF0xvE2Ix0cI8IcVCY 1x0267AKxVW8JVWxJwCI42IY6xAIw20EY4v20xvaj40_Jr0_JF4lIxAIcVC2z280aVAFwI 0_Jr0_Gr1lIxAIcVC2z280aVCY1x0267AKxVW8JVW8JrUvcSsGvfC2KfnxnUUI43ZEXa7V Uj1xR3UUUUU== X-CM-SenderInfo: xjdrwv3l6h245lqf0zpsxwx03jof0z/ X-Spam-Status: No, score=-10.2 required=5.0 tests=BAYES_00, GIT_PATCH_0, KAM_DMARC_STATUS, KAM_SHORT, LIKELY_SPAM_BODY, RCVD_IN_MSPIKE_H2, SPF_HELO_NONE, SPF_PASS, TXREP 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.30 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: kito.cheng@gmail.com, jiawei@iscas.ac.cn, Die Li Errors-To: gcc-patches-bounces+incoming=patchwork.ozlabs.org@gcc.gnu.org Sender: "Gcc-patches" From: Die Li Signed-off-by: Die Li Co-Authored-By: Fei Gao gcc/ChangeLog: * config/riscv/peephole.md: New pattern. * config/riscv/predicates.md (a0a1_reg_operand): New predicate. (zcmp_mv_sreg_operand): New predicate. * config/riscv/riscv.md: New predicate. * config/riscv/zc.md (*mva01s): New pattern. (*mvsa01): New pattern. gcc/testsuite/ChangeLog: * gcc.target/riscv/cm_mv_rv32.c: New test. --- gcc/config/riscv/peephole.md | 28 +++++++++++++++++++++ gcc/config/riscv/predicates.md | 11 ++++++++ gcc/config/riscv/riscv.md | 1 + gcc/config/riscv/zc.md | 22 ++++++++++++++++ gcc/testsuite/gcc.target/riscv/cm_mv_rv32.c | 23 +++++++++++++++++ 5 files changed, 85 insertions(+) create mode 100644 gcc/testsuite/gcc.target/riscv/cm_mv_rv32.c diff --git a/gcc/config/riscv/peephole.md b/gcc/config/riscv/peephole.md index 0ef0c04410b..92e57f9a447 100644 --- a/gcc/config/riscv/peephole.md +++ b/gcc/config/riscv/peephole.md @@ -38,3 +38,31 @@ { operands[5] = GEN_INT (INTVAL (operands[2]) - INTVAL (operands[5])); }) + +;; ZCMP +(define_peephole2 + [(set (match_operand:X 0 "a0a1_reg_operand") + (match_operand:X 1 "zcmp_mv_sreg_operand")) + (set (match_operand:X 2 "a0a1_reg_operand") + (match_operand:X 3 "zcmp_mv_sreg_operand"))] + "TARGET_ZCMP + && (REGNO (operands[2]) != REGNO (operands[0]))" + [(parallel [(set (match_dup 0) + (match_dup 1)) + (set (match_dup 2) + (match_dup 3))])] +) + +(define_peephole2 + [(set (match_operand:X 0 "zcmp_mv_sreg_operand") + (match_operand:X 1 "a0a1_reg_operand")) + (set (match_operand:X 2 "zcmp_mv_sreg_operand") + (match_operand:X 3 "a0a1_reg_operand"))] + "TARGET_ZCMP + && (REGNO (operands[0]) != REGNO (operands[2])) + && (REGNO (operands[1]) != REGNO (operands[3]))" + [(parallel [(set (match_dup 0) + (match_dup 1)) + (set (match_dup 2) + (match_dup 3))])] +) diff --git a/gcc/config/riscv/predicates.md b/gcc/config/riscv/predicates.md index 3ef09996a85..772f45df65c 100644 --- a/gcc/config/riscv/predicates.md +++ b/gcc/config/riscv/predicates.md @@ -165,6 +165,17 @@ (and (match_code "const_int") (match_test "riscv_zcmp_valid_stack_adj_bytes_p (INTVAL (op), 13)"))) +;; ZCMP predicates +(define_predicate "a0a1_reg_operand" + (and (match_operand 0 "register_operand") + (match_test "IN_RANGE (REGNO (op), A0_REGNUM, A1_REGNUM)"))) + +(define_predicate "zcmp_mv_sreg_operand" + (and (match_operand 0 "register_operand") + (match_test "TARGET_RVE ? IN_RANGE (REGNO (op), S0_REGNUM, S1_REGNUM) + : IN_RANGE (REGNO (op), S0_REGNUM, S1_REGNUM) + || IN_RANGE (REGNO (op), S2_REGNUM, S7_REGNUM)"))) + ;; Only use branch-on-bit sequences when the mask is not an ANDI immediate. (define_predicate "branch_on_bit_operand" (and (match_code "const_int") diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md index 8e09df6ff63..aa2b5b960dc 100644 --- a/gcc/config/riscv/riscv.md +++ b/gcc/config/riscv/riscv.md @@ -132,6 +132,7 @@ (S0_REGNUM 8) (S1_REGNUM 9) (A0_REGNUM 10) + (A1_REGNUM 11) (S2_REGNUM 18) (S3_REGNUM 19) (S4_REGNUM 20) diff --git a/gcc/config/riscv/zc.md b/gcc/config/riscv/zc.md index 8d7de97daad..77b28adde95 100644 --- a/gcc/config/riscv/zc.md +++ b/gcc/config/riscv/zc.md @@ -1433,3 +1433,25 @@ "TARGET_ZCMP" "cm.push {ra, s0-s11}, %0" ) + +;; ZCMP mv +(define_insn "*mva01s" + [(set (match_operand:X 0 "a0a1_reg_operand" "=r") + (match_operand:X 1 "zcmp_mv_sreg_operand" "r")) + (set (match_operand:X 2 "a0a1_reg_operand" "=r") + (match_operand:X 3 "zcmp_mv_sreg_operand" "r"))] + "TARGET_ZCMP + && (REGNO (operands[2]) != REGNO (operands[0]))" + { return (REGNO (operands[0]) == A0_REGNUM)?"cm.mva01s\t%1,%3":"cm.mva01s\t%3,%1"; } + [(set_attr "mode" "")]) + +(define_insn "*mvsa01" + [(set (match_operand:X 0 "zcmp_mv_sreg_operand" "=r") + (match_operand:X 1 "a0a1_reg_operand" "r")) + (set (match_operand:X 2 "zcmp_mv_sreg_operand" "=r") + (match_operand:X 3 "a0a1_reg_operand" "r"))] + "TARGET_ZCMP + && (REGNO (operands[0]) != REGNO (operands[2])) + && (REGNO (operands[1]) != REGNO (operands[3]))" + { return (REGNO (operands[1]) == A0_REGNUM)?"cm.mvsa01\t%0,%2":"cm.mvsa01\t%2,%0"; } + [(set_attr "mode" "")]) diff --git a/gcc/testsuite/gcc.target/riscv/cm_mv_rv32.c b/gcc/testsuite/gcc.target/riscv/cm_mv_rv32.c new file mode 100644 index 00000000000..2c1b3f9cabf --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/cm_mv_rv32.c @@ -0,0 +1,23 @@ +/* { dg-do compile } */ +/* { dg-options " -Os -march=rv32i_zca_zcmp -mabi=ilp32 " } */ +/* { dg-skip-if "" { *-*-* } {"-O0" "-O1" "-O2" "-Og" "-O3" "-Oz" "-flto"} } */ +/* { dg-final { check-function-bodies "**" "" } } */ + +int +func (int a, int b); + +/* +**sum: +** ... +** cm.mvsa01 s1,s2 +** call func +** mv s0,a0 +** cm.mva01s s1,s2 +** call func +** ... +*/ +int +sum (int a, int b) +{ + return func (a, b) + func (a, b); +}