public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
From: jiawei@iscas.ac.cn
To: "Fei Gao" <gaofei@eswincomputing.com>
Cc: gcc-patches@gcc.gnu.org, kito.cheng@gmail.com,
	palmer@dabbelt.com,  jeffreyalaw@gmail.com,
	sinan.lin@linux.alibaba.com
Subject: Re: [PATCH 1/4][V4][RISC-V] support cm.push cm.pop cm.popret in zcmp
Date: Wed, 7 Jun 2023 18:11:56 +0800 (GMT+08:00)	[thread overview]
Message-ID: <62269c00.b0e9.18895577568.Coremail.jiawei@iscas.ac.cn> (raw)
In-Reply-To: <20230607055215.29332-2-gaofei@eswincomputing.com>

Seems there are some indent format problems in the patch, could you fix them :)

```
patch:509: indent with spaces.
          x_save_size = riscv_stack_align (num_multi_push * UNITS_PER_WORD);
error: patch failed: gcc/config/riscv/riscv.cc:5652
error: gcc/config/riscv/riscv.cc: patch does not apply
```

&gt; -----原始邮件-----
&gt; 发件人: "Fei Gao" <gaofei@eswincomputing.com>
&gt; 发送时间: 2023-06-07 13:52:12 (星期三)
&gt; 收件人: gcc-patches@gcc.gnu.org
&gt; 抄送: kito.cheng@gmail.com, palmer@dabbelt.com, jeffreyalaw@gmail.com, sinan.lin@linux.alibaba.com, jiawei@iscas.ac.cn, "Fei Gao" <gaofei@eswincomputing.com>
&gt; 主题: [PATCH 1/4][V4][RISC-V] support cm.push cm.pop cm.popret in zcmp
&gt; 
&gt; Zcmp can share the same logic as save-restore in stack allocation: pre-allocation
&gt; by cm.push, step 1 and step 2.
&gt; 
&gt; please be noted cm.push pushes ra, s0-s11 in reverse order than what save-restore does.
&gt; So adaption has been done in .cfi directives in my patch.
&gt; 
&gt; Signed-off-by: Fei Gao <gaofei@eswincomputing.com>
&gt; 
&gt; gcc/ChangeLog:
&gt; 
&gt;         * config/riscv/iterators.md
&gt;         slot0_offset: slot 0 offset in stack GPRs area in bytes
&gt;         slot1_offset: slot 1 offset in stack GPRs area in bytes
&gt;         slot2_offset: likewise
&gt;         slot3_offset: likewise
&gt;         slot4_offset: likewise
&gt;         slot5_offset: likewise
&gt;         slot6_offset: likewise
&gt;         slot7_offset: likewise
&gt;         slot8_offset: likewise
&gt;         slot9_offset: likewise
&gt;         slot10_offset: likewise
&gt;         slot11_offset: likewise
&gt;         slot12_offset: likewise
&gt;         * config/riscv/predicates.md
&gt;         (stack_push_up_to_ra_operand): predicates of stack adjust pushing ra
&gt;         (stack_push_up_to_s0_operand): predicates of stack adjust pushing ra, s0
&gt;         (stack_push_up_to_s1_operand): likewise
&gt;         (stack_push_up_to_s2_operand): likewise
&gt;         (stack_push_up_to_s3_operand): likewise
&gt;         (stack_push_up_to_s4_operand): likewise
&gt;         (stack_push_up_to_s5_operand): likewise
&gt;         (stack_push_up_to_s6_operand): likewise
&gt;         (stack_push_up_to_s7_operand): likewise
&gt;         (stack_push_up_to_s8_operand): likewise
&gt;         (stack_push_up_to_s9_operand): likewise
&gt;         (stack_push_up_to_s11_operand): likewise
&gt;         (stack_pop_up_to_ra_operand): predicates of stack adjust poping ra
&gt;         (stack_pop_up_to_s0_operand): predicates of stack adjust poping ra, s0
&gt;         (stack_pop_up_to_s1_operand): likewise
&gt;         (stack_pop_up_to_s2_operand): likewise
&gt;         (stack_pop_up_to_s3_operand): likewise
&gt;         (stack_pop_up_to_s4_operand): likewise
&gt;         (stack_pop_up_to_s5_operand): likewise
&gt;         (stack_pop_up_to_s6_operand): likewise
&gt;         (stack_pop_up_to_s7_operand): likewise
&gt;         (stack_pop_up_to_s8_operand): likewise
&gt;         (stack_pop_up_to_s9_operand): likewise
&gt;         (stack_pop_up_to_s11_operand): likewise
&gt;         * config/riscv/riscv-protos.h
&gt;         (riscv_zcmp_valid_stack_adj_bytes_p):declaration
&gt;         * config/riscv/riscv.cc (struct riscv_frame_info): comment change
&gt;         (riscv_avoid_multi_push): helper function of riscv_use_multi_push
&gt;         (riscv_use_multi_push): true if multi push is used
&gt;         (riscv_multi_push_sregs_count): num of sregs in multi-push
&gt;         (riscv_multi_push_regs_count): num of regs in multi-push
&gt;         (riscv_16bytes_align): align to 16 bytes
&gt;         (riscv_stack_align): moved to a better place
&gt;         (riscv_save_libcall_count): no functional change
&gt;         (riscv_compute_frame_info): add zcmp frame info
&gt;         (riscv_adjust_multi_push_cfi_prologue): adjust cfi for cm.push
&gt;         (riscv_gen_multi_push_pop_insn): gen function for multi push and pop
&gt;         (riscv_expand_prologue): allocate stack by cm.push
&gt;         (riscv_adjust_multi_pop_cfi_epilogue): adjust cfi for cm.pop[ret]
&gt;         (riscv_expand_epilogue): allocate stack by cm.pop[ret]
&gt;         (zcmp_base_adj): calculate stack adjustment base size
&gt;         (zcmp_additional_adj): calculate stack adjustment additional size
&gt;         (riscv_zcmp_valid_stack_adj_bytes_p): check if stack adjustment valid
&gt;         * config/riscv/riscv.h (RETURN_ADDR_MASK): mask of ra
&gt;         (S0_MASK): likewise
&gt;         (S1_MASK): likewise
&gt;         (S2_MASK): likewise
&gt;         (S3_MASK): likewise
&gt;         (S4_MASK): likewise
&gt;         (S5_MASK): likewise
&gt;         (S6_MASK): likewise
&gt;         (S7_MASK): likewise
&gt;         (S8_MASK): likewise
&gt;         (S9_MASK): likewise
&gt;         (S10_MASK): likewise
&gt;         (S11_MASK): likewise
&gt;         (MULTI_PUSH_GPR_MASK): GPR_MASK that cm.push can cover at most
&gt;         (ZCMP_MAX_SPIMM): max spimm value
&gt;         (ZCMP_SP_INC_STEP): zcmp sp increment step
&gt;         (ZCMP_INVALID_S0S10_SREGS_COUNTS): num of s0-s10
&gt;         (ZCMP_S0S11_SREGS_COUNTS): num of s0-s11
&gt;         (ZCMP_MAX_GRP_SLOTS): max slots of pushing and poping in zcmp
&gt;         * config/riscv/riscv.md: include zc.md
&gt;         * config/riscv/zc.md: New file. machine description for zcmp
&gt; 
&gt; gcc/testsuite/ChangeLog:
&gt; 
&gt;         * gcc.target/riscv/rv32e_zcmp.c: New test.
&gt;         * gcc.target/riscv/rv32i_zcmp.c: New test.
&gt;         * gcc.target/riscv/zcmp_stack_alignment.c: New test.
&gt; ---
&gt;  gcc/config/riscv/iterators.md                 |   15 +
&gt;  gcc/config/riscv/predicates.md                |   96 ++
&gt;  gcc/config/riscv/riscv-protos.h               |    1 +
&gt;  gcc/config/riscv/riscv.cc                     |  360 +++++-
&gt;  gcc/config/riscv/riscv.h                      |   23 +
&gt;  gcc/config/riscv/riscv.md                     |    2 +
&gt;  gcc/config/riscv/zc.md                        | 1042 +++++++++++++++++
&gt;  gcc/testsuite/gcc.target/riscv/rv32e_zcmp.c   |  239 ++++
&gt;  gcc/testsuite/gcc.target/riscv/rv32i_zcmp.c   |  239 ++++
&gt;  .../gcc.target/riscv/zcmp_stack_alignment.c   |   23 +
&gt;  10 files changed, 2000 insertions(+), 40 deletions(-)
&gt;  create mode 100644 gcc/config/riscv/zc.md
&gt;  create mode 100644 gcc/testsuite/gcc.target/riscv/rv32e_zcmp.c
&gt;  create mode 100644 gcc/testsuite/gcc.target/riscv/rv32i_zcmp.c
&gt;  create mode 100644 gcc/testsuite/gcc.target/riscv/zcmp_stack_alignment.c
&gt; 
&gt; diff --git a/gcc/config/riscv/iterators.md b/gcc/config/riscv/iterators.md
&gt; index d374a10810c..6ed4174f9cc 100644
&gt; --- a/gcc/config/riscv/iterators.md
&gt; +++ b/gcc/config/riscv/iterators.md
&gt; @@ -120,6 +120,21 @@
&gt;  (define_mode_attr shiftm1 [(SI "const_si_mask_operand") (DI "const_di_mask_operand")])
&gt;  (define_mode_attr shiftm1p [(SI "DsS") (DI "DsD")])
&gt;  
&gt; +; zcmp mode attribute
&gt; +(define_mode_attr slot0_offset  [(SI "-4")  (DI "-8")])
&gt; +(define_mode_attr slot1_offset  [(SI "-8")  (DI "-16")])
&gt; +(define_mode_attr slot2_offset  [(SI "-12") (DI "-24")])
&gt; +(define_mode_attr slot3_offset  [(SI "-16") (DI "-32")])
&gt; +(define_mode_attr slot4_offset  [(SI "-20") (DI "-40")])
&gt; +(define_mode_attr slot5_offset  [(SI "-24") (DI "-48")])
&gt; +(define_mode_attr slot6_offset  [(SI "-28") (DI "-56")])
&gt; +(define_mode_attr slot7_offset  [(SI "-32") (DI "-64")])
&gt; +(define_mode_attr slot8_offset  [(SI "-36") (DI "-72")])
&gt; +(define_mode_attr slot9_offset  [(SI "-40") (DI "-80")])
&gt; +(define_mode_attr slot10_offset [(SI "-44") (DI "-88")])
&gt; +(define_mode_attr slot11_offset [(SI "-48") (DI "-96")])
&gt; +(define_mode_attr slot12_offset [(SI "-52") (DI "-104")])
&gt; +
&gt;  ;; -------------------------------------------------------------------
&gt;  ;; Code Iterators
&gt;  ;; -------------------------------------------------------------------
&gt; diff --git a/gcc/config/riscv/predicates.md b/gcc/config/riscv/predicates.md
&gt; index 04ca6ceabc7..ab67b3332f0 100644
&gt; --- a/gcc/config/riscv/predicates.md
&gt; +++ b/gcc/config/riscv/predicates.md
&gt; @@ -65,6 +65,102 @@
&gt;    (ior (match_operand 0 "const_0_operand")
&gt;         (match_operand 0 "register_operand")))
&gt;  
&gt; +(define_predicate "stack_push_up_to_ra_operand"
&gt; +  (and (match_code "const_int")
&gt; +       (match_test "riscv_zcmp_valid_stack_adj_bytes_p (INTVAL (op) * -1, 1)")))
&gt; +
&gt; +(define_predicate "stack_push_up_to_s0_operand"
&gt; +  (and (match_code "const_int")
&gt; +       (match_test "riscv_zcmp_valid_stack_adj_bytes_p (INTVAL (op) * -1, 2)")))
&gt; +
&gt; +(define_predicate "stack_push_up_to_s1_operand"
&gt; +  (and (match_code "const_int")
&gt; +       (match_test "riscv_zcmp_valid_stack_adj_bytes_p (INTVAL (op) * -1, 3)")))
&gt; +
&gt; +(define_predicate "stack_push_up_to_s2_operand"
&gt; +  (and (match_code "const_int")
&gt; +       (match_test "riscv_zcmp_valid_stack_adj_bytes_p (INTVAL (op) * -1, 4)")))
&gt; +
&gt; +(define_predicate "stack_push_up_to_s3_operand"
&gt; +  (and (match_code "const_int")
&gt; +       (match_test "riscv_zcmp_valid_stack_adj_bytes_p (INTVAL (op) * -1, 5)")))
&gt; +
&gt; +(define_predicate "stack_push_up_to_s4_operand"
&gt; +  (and (match_code "const_int")
&gt; +       (match_test "riscv_zcmp_valid_stack_adj_bytes_p (INTVAL (op) * -1, 6)")))
&gt; +
&gt; +(define_predicate "stack_push_up_to_s5_operand"
&gt; +  (and (match_code "const_int")
&gt; +       (match_test "riscv_zcmp_valid_stack_adj_bytes_p (INTVAL (op) * -1, 7)")))
&gt; +
&gt; +(define_predicate "stack_push_up_to_s6_operand"
&gt; +  (and (match_code "const_int")
&gt; +       (match_test "riscv_zcmp_valid_stack_adj_bytes_p (INTVAL (op) * -1, 8)")))
&gt; +
&gt; +(define_predicate "stack_push_up_to_s7_operand"
&gt; +  (and (match_code "const_int")
&gt; +       (match_test "riscv_zcmp_valid_stack_adj_bytes_p (INTVAL (op) * -1, 9)")))
&gt; +
&gt; +(define_predicate "stack_push_up_to_s8_operand"
&gt; +  (and (match_code "const_int")
&gt; +       (match_test "riscv_zcmp_valid_stack_adj_bytes_p (INTVAL (op) * -1, 10)")))
&gt; +
&gt; +(define_predicate "stack_push_up_to_s9_operand"
&gt; +  (and (match_code "const_int")
&gt; +       (match_test "riscv_zcmp_valid_stack_adj_bytes_p (INTVAL (op) * -1, 11)")))
&gt; +
&gt; +(define_predicate "stack_push_up_to_s11_operand"
&gt; +  (and (match_code "const_int")
&gt; +       (match_test "riscv_zcmp_valid_stack_adj_bytes_p (INTVAL (op) * -1, 13)")))
&gt; +
&gt; +(define_predicate "stack_pop_up_to_ra_operand"
&gt; +  (and (match_code "const_int")
&gt; +       (match_test "riscv_zcmp_valid_stack_adj_bytes_p (INTVAL (op), 1)")))
&gt; +
&gt; +(define_predicate "stack_pop_up_to_s0_operand"
&gt; +  (and (match_code "const_int")
&gt; +       (match_test "riscv_zcmp_valid_stack_adj_bytes_p (INTVAL (op), 2)")))
&gt; +
&gt; +(define_predicate "stack_pop_up_to_s1_operand"
&gt; +  (and (match_code "const_int")
&gt; +       (match_test "riscv_zcmp_valid_stack_adj_bytes_p (INTVAL (op), 3)")))
&gt; +
&gt; +(define_predicate "stack_pop_up_to_s2_operand"
&gt; +  (and (match_code "const_int")
&gt; +       (match_test "riscv_zcmp_valid_stack_adj_bytes_p (INTVAL (op), 4)")))
&gt; +
&gt; +(define_predicate "stack_pop_up_to_s3_operand"
&gt; +  (and (match_code "const_int")
&gt; +       (match_test "riscv_zcmp_valid_stack_adj_bytes_p (INTVAL (op), 5)")))
&gt; +
&gt; +(define_predicate "stack_pop_up_to_s4_operand"
&gt; +  (and (match_code "const_int")
&gt; +       (match_test "riscv_zcmp_valid_stack_adj_bytes_p (INTVAL (op), 6)")))
&gt; +
&gt; +(define_predicate "stack_pop_up_to_s5_operand"
&gt; +  (and (match_code "const_int")
&gt; +       (match_test "riscv_zcmp_valid_stack_adj_bytes_p (INTVAL (op), 7)")))
&gt; +
&gt; +(define_predicate "stack_pop_up_to_s6_operand"
&gt; +  (and (match_code "const_int")
&gt; +       (match_test "riscv_zcmp_valid_stack_adj_bytes_p (INTVAL (op), 8)")))
&gt; +
&gt; +(define_predicate "stack_pop_up_to_s7_operand"
&gt; +  (and (match_code "const_int")
&gt; +       (match_test "riscv_zcmp_valid_stack_adj_bytes_p (INTVAL (op), 9)")))
&gt; +
&gt; +(define_predicate "stack_pop_up_to_s8_operand"
&gt; +  (and (match_code "const_int")
&gt; +       (match_test "riscv_zcmp_valid_stack_adj_bytes_p (INTVAL (op), 10)")))
&gt; +
&gt; +(define_predicate "stack_pop_up_to_s9_operand"
&gt; +  (and (match_code "const_int")
&gt; +       (match_test "riscv_zcmp_valid_stack_adj_bytes_p (INTVAL (op), 11)")))
&gt; +
&gt; +(define_predicate "stack_pop_up_to_s11_operand"
&gt; +  (and (match_code "const_int")
&gt; +       (match_test "riscv_zcmp_valid_stack_adj_bytes_p (INTVAL (op), 13)")))
&gt; +
&gt;  ;; Only use branch-on-bit sequences when the mask is not an ANDI immediate.
&gt;  (define_predicate "branch_on_bit_operand"
&gt;    (and (match_code "const_int")
&gt; diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h
&gt; index 00e1b20c6c6..f23b11622a2 100644
&gt; --- a/gcc/config/riscv/riscv-protos.h
&gt; +++ b/gcc/config/riscv/riscv-protos.h
&gt; @@ -56,6 +56,7 @@ extern bool riscv_split_64bit_move_p (rtx, rtx);
&gt;  extern void riscv_split_doubleword_move (rtx, rtx);
&gt;  extern const char *riscv_output_move (rtx, rtx);
&gt;  extern const char *riscv_output_return ();
&gt; +extern bool riscv_zcmp_valid_stack_adj_bytes_p(HOST_WIDE_INT, int);
&gt;  
&gt;  #ifdef RTX_CODE
&gt;  extern void riscv_expand_int_scc (rtx, enum rtx_code, rtx, rtx);
&gt; diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
&gt; index 3954c89a039..c476c699f4c 100644
&gt; --- a/gcc/config/riscv/riscv.cc
&gt; +++ b/gcc/config/riscv/riscv.cc
&gt; @@ -126,6 +126,14 @@ struct GTY(())  riscv_frame_info {
&gt;    /* How much the GPR save/restore routines adjust sp (or 0 if unused).  */
&gt;    unsigned save_libcall_adjustment;
&gt;  
&gt; +  /* the minimum number of bytes, in multiples of 16-byte address increments,
&gt; +     required to cover the registers in a multi push &amp; pop.  */
&gt; +  unsigned multi_push_adj_base;
&gt; +
&gt; +  /* the number of additional 16-byte address increments allocated for the stack frame
&gt; +     in a multi push &amp; pop.  */
&gt; +  unsigned multi_push_adj_addi;
&gt; +
&gt;    /* Offsets of fixed-point and floating-point save areas from frame bottom */
&gt;    poly_int64 gp_sp_offset;
&gt;    poly_int64 fp_sp_offset;
&gt; @@ -422,6 +430,16 @@ static const struct riscv_tune_info riscv_tune_info_table[] = {
&gt;  #include "riscv-cores.def"
&gt;  };
&gt;  
&gt; +typedef enum
&gt; +{
&gt; +  PUSH_IDX = 0,
&gt; +  POP_IDX,
&gt; +  POPRET_IDX,
&gt; +  ZCMP_OP_NUM
&gt; +} riscv_zcmp_op_t;
&gt; +
&gt; +typedef insn_code (* code_for_push_pop_t)(machine_mode);
&gt; +
&gt;  void riscv_frame_info::reset(void)
&gt;  {
&gt;    total_size = 0;
&gt; @@ -4876,6 +4894,37 @@ riscv_save_reg_p (unsigned int regno)
&gt;    return false;
&gt;  }
&gt;  
&gt; +/* Return TRUE if Zcmp push and pop insns should be
&gt; +   avoided. FALSE otherwise.
&gt; +   Only use multi push &amp; pop if all GPRs masked can be covered,
&gt; +   and stack access is SP based,
&gt; +   and GPRs are at top of the stack frame,
&gt; +   and no conflicts in stack allocation with other features  */
&gt; +static bool
&gt; +riscv_avoid_multi_push(const struct riscv_frame_info *frame)
&gt; +{
&gt; +  if (!TARGET_ZCMP
&gt; +      || crtl-&gt;calls_eh_return
&gt; +      || frame_pointer_needed
&gt; +      || cfun-&gt;machine-&gt;interrupt_handler_p
&gt; +      || cfun-&gt;machine-&gt;varargs_size != 0
&gt; +      || crtl-&gt;args.pretend_args_size != 0
&gt; +      || (frame-&gt;mask &amp; ~ MULTI_PUSH_GPR_MASK))
&gt; +    return true;
&gt; +
&gt; +  return false;
&gt; +}
&gt; +
&gt; +/* Determine whether to use multi push insn.  */
&gt; +static bool
&gt; +riscv_use_multi_push(const struct riscv_frame_info *frame)
&gt; +{
&gt; +  if (riscv_avoid_multi_push (frame))
&gt; +    return false;
&gt; +
&gt; +  return (frame-&gt;multi_push_adj_base != 0);
&gt; +}
&gt; +
&gt;  /* Return TRUE if a libcall to save/restore GPRs should be
&gt;     avoided.  FALSE otherwise.  */
&gt;  static bool
&gt; @@ -4913,6 +4962,51 @@ riscv_save_libcall_count (unsigned mask)
&gt;    abort ();
&gt;  }
&gt;  
&gt; +/* calculate number of s regs in multi push and pop.
&gt; +   Note that {s0-s10} is not valid in Zcmp, use {s0-s11} instead.  */
&gt; +static unsigned
&gt; +riscv_multi_push_sregs_count (unsigned mask)
&gt; +{
&gt; +  unsigned num = riscv_save_libcall_count (mask);
&gt; +  return (num == ZCMP_INVALID_S0S10_SREGS_COUNTS)
&gt; +    ? ZCMP_S0S11_SREGS_COUNTS
&gt; +    : num;
&gt; +}
&gt; +
&gt; +/* calculate number of regs(ra, s0-sx) in multi push and pop.  */
&gt; +static unsigned
&gt; +riscv_multi_push_regs_count (unsigned mask)
&gt; +{
&gt; +  /* 1 is for ra  */
&gt; +  return riscv_multi_push_sregs_count (mask) + 1;
&gt; +}
&gt; +
&gt; +/* Handle 16 bytes align for poly_int.  */
&gt; +static poly_int64
&gt; +riscv_16bytes_align (poly_int64 value)
&gt; +{
&gt; +  return aligned_upper_bound (value, 16);
&gt; +}
&gt; +
&gt; +static HOST_WIDE_INT
&gt; +riscv_16bytes_align (HOST_WIDE_INT value)
&gt; +{
&gt; +  return ROUND_UP(value, 16);
&gt; +}
&gt; +
&gt; +/* Handle stack align for poly_int.  */
&gt; +static poly_int64
&gt; +riscv_stack_align (poly_int64 value)
&gt; +{
&gt; +  return aligned_upper_bound (value, PREFERRED_STACK_BOUNDARY / 8);
&gt; +}
&gt; +
&gt; +static HOST_WIDE_INT
&gt; +riscv_stack_align (HOST_WIDE_INT value)
&gt; +{
&gt; +  return RISCV_STACK_ALIGN (value);
&gt; +}
&gt; +
&gt;  /* Populate the current function's riscv_frame_info structure.
&gt;  
&gt;     RISC-V stack frames grown downward.  High addresses are at the top.
&gt; @@ -4938,7 +5032,7 @@ riscv_save_libcall_count (unsigned mask)
&gt;  	|  GPR save area                |       + UNITS_PER_WORD
&gt;  	|                               |
&gt;  	+-------------------------------+ &lt;-- stack_pointer_rtx + fp_sp_offset
&gt; -	|                               |       + UNITS_PER_HWVALUE
&gt; +	|                               |       + UNITS_PER_FP_REG
&gt;  	|  FPR save area                |
&gt;  	|                               |
&gt;  	+-------------------------------+ &lt;-- frame_pointer_rtx (virtual)
&gt; @@ -4957,19 +5051,6 @@ riscv_save_libcall_count (unsigned mask)
&gt;  
&gt;  static HOST_WIDE_INT riscv_first_stack_step (struct riscv_frame_info *frame, poly_int64 remaining_size);
&gt;  
&gt; -/* Handle stack align for poly_int.  */
&gt; -static poly_int64
&gt; -riscv_stack_align (poly_int64 value)
&gt; -{
&gt; -  return aligned_upper_bound (value, PREFERRED_STACK_BOUNDARY / 8);
&gt; -}
&gt; -
&gt; -static HOST_WIDE_INT
&gt; -riscv_stack_align (HOST_WIDE_INT value)
&gt; -{
&gt; -  return RISCV_STACK_ALIGN (value);
&gt; -}
&gt; -
&gt;  static void
&gt;  riscv_compute_frame_info (void)
&gt;  {
&gt; @@ -5017,8 +5098,9 @@ riscv_compute_frame_info (void)
&gt;    if (frame-&gt;mask)
&gt;      {
&gt;        x_save_size = riscv_stack_align (num_x_saved * UNITS_PER_WORD);
&gt; -      unsigned num_save_restore = 1 + riscv_save_libcall_count (frame-&gt;mask);
&gt;  
&gt; +      /* 1 is for ra  */
&gt; +      unsigned num_save_restore = 1 + riscv_save_libcall_count (frame-&gt;mask);
&gt;        /* Only use save/restore routines if they don't alter the stack size.  */
&gt;        if (riscv_stack_align (num_save_restore * UNITS_PER_WORD) == x_save_size
&gt;            &amp;&amp; !riscv_avoid_save_libcall ())
&gt; @@ -5030,6 +5112,15 @@ riscv_compute_frame_info (void)
&gt;  
&gt;  	  frame-&gt;save_libcall_adjustment = x_save_size;
&gt;  	}
&gt; +
&gt; +      if (!riscv_avoid_multi_push (frame))
&gt; +        {
&gt; +          /* num(ra, s0-sx)  */
&gt; +          unsigned num_multi_push =
&gt; +            riscv_multi_push_regs_count (frame-&gt;mask);
&gt; +          x_save_size = riscv_stack_align (num_multi_push * UNITS_PER_WORD);
&gt; +          frame-&gt;multi_push_adj_base = riscv_16bytes_align (x_save_size);
&gt; +        }
&gt;      }
&gt;  
&gt;    /* At the bottom of the frame are any outgoing stack arguments. */
&gt; @@ -5044,7 +5135,15 @@ riscv_compute_frame_info (void)
&gt;    frame-&gt;fp_sp_offset = offset - UNITS_PER_FP_REG;
&gt;    /* Next are the callee-saved GPRs. */
&gt;    if (frame-&gt;mask)
&gt; -    offset += x_save_size;
&gt; +    {
&gt; +      offset += x_save_size;
&gt; +      /* align to 16 bytes and add paddings to GPR part to honor
&gt; +         both stack alignment and zcmp pus/pop size alignment. */
&gt; +      if (riscv_use_multi_push (frame)
&gt; +          &amp;&amp; known_lt(offset,
&gt; +                      frame-&gt;multi_push_adj_base + ZCMP_SP_INC_STEP * ZCMP_MAX_SPIMM))
&gt; +        offset = riscv_16bytes_align (offset);
&gt; +    }
&gt;    frame-&gt;gp_sp_offset = offset - UNITS_PER_WORD;
&gt;    /* The hard frame pointer points above the callee-saved GPRs. */
&gt;    frame-&gt;hard_frame_pointer_offset = offset;
&gt; @@ -5388,6 +5487,42 @@ riscv_adjust_libcall_cfi_prologue ()
&gt;    return dwarf;
&gt;  }
&gt;  
&gt; +static rtx
&gt; +riscv_adjust_multi_push_cfi_prologue (int saved_size)
&gt; +{
&gt; +  rtx dwarf = NULL_RTX;
&gt; +  rtx adjust_sp_rtx, reg, mem, insn;
&gt; +  unsigned int mask = cfun-&gt;machine-&gt;frame.mask;
&gt; +  int offset;
&gt; +  int saved_cnt = 0;
&gt; +
&gt; +  if (mask &amp; S10_MASK)
&gt; +    mask |= S11_MASK;
&gt; +
&gt; +  for (int regno = GP_REG_LAST; regno &gt;= GP_REG_FIRST; regno--)
&gt; +    if (BITSET_P (mask &amp; MULTI_PUSH_GPR_MASK, regno - GP_REG_FIRST))
&gt; +      {
&gt; +        /* The save order is s11-s0, ra
&gt; +           from high to low addr.  */
&gt; +        offset = saved_size - UNITS_PER_WORD * (++saved_cnt);
&gt; +
&gt; +        reg = gen_rtx_REG (Pmode, regno);
&gt; +        mem = gen_frame_mem (Pmode, plus_constant (Pmode,
&gt; +                                                   stack_pointer_rtx,
&gt; +                                                   offset));
&gt; +
&gt; +        insn = gen_rtx_SET (mem, reg);
&gt; +        dwarf = alloc_reg_note (REG_CFA_OFFSET, insn, dwarf);
&gt; +      }
&gt; +
&gt; +  /* Debug info for adjust sp.  */
&gt; +  adjust_sp_rtx = gen_rtx_SET (stack_pointer_rtx,
&gt; +                               plus_constant(Pmode, stack_pointer_rtx, -saved_size));
&gt; +  dwarf = alloc_reg_note (REG_CFA_ADJUST_CFA, adjust_sp_rtx,
&gt; +                          dwarf);
&gt; +  return dwarf;
&gt; +}
&gt; +
&gt;  static void
&gt;  riscv_emit_stack_tie (void)
&gt;  {
&gt; @@ -5397,6 +5532,45 @@ riscv_emit_stack_tie (void)
&gt;      emit_insn (gen_stack_tiedi (stack_pointer_rtx, hard_frame_pointer_rtx));
&gt;  }
&gt;  
&gt; +/*zcmp multi push and pop code_for_push_pop function ptr array  */
&gt; +const code_for_push_pop_t code_for_push_pop [ZCMP_MAX_GRP_SLOTS][ZCMP_OP_NUM] = {
&gt; +  {code_for_gpr_multi_push_up_to_ra,    code_for_gpr_multi_pop_up_to_ra,
&gt; +   code_for_gpr_multi_popret_up_to_ra},
&gt; +  {code_for_gpr_multi_push_up_to_s0,    code_for_gpr_multi_pop_up_to_s0,
&gt; +   code_for_gpr_multi_popret_up_to_s0},
&gt; +  {code_for_gpr_multi_push_up_to_s1,    code_for_gpr_multi_pop_up_to_s1,
&gt; +   code_for_gpr_multi_popret_up_to_s1},
&gt; +  {code_for_gpr_multi_push_up_to_s2,    code_for_gpr_multi_pop_up_to_s2,
&gt; +   code_for_gpr_multi_popret_up_to_s2},
&gt; +  {code_for_gpr_multi_push_up_to_s3,    code_for_gpr_multi_pop_up_to_s3,
&gt; +   code_for_gpr_multi_popret_up_to_s3},
&gt; +  {code_for_gpr_multi_push_up_to_s4,    code_for_gpr_multi_pop_up_to_s4,
&gt; +   code_for_gpr_multi_popret_up_to_s4},
&gt; +  {code_for_gpr_multi_push_up_to_s5,    code_for_gpr_multi_pop_up_to_s5,
&gt; +   code_for_gpr_multi_popret_up_to_s5},
&gt; +  {code_for_gpr_multi_push_up_to_s6,    code_for_gpr_multi_pop_up_to_s6,
&gt; +   code_for_gpr_multi_popret_up_to_s6},
&gt; +  {code_for_gpr_multi_push_up_to_s7,    code_for_gpr_multi_pop_up_to_s7,
&gt; +   code_for_gpr_multi_popret_up_to_s7},
&gt; +  {code_for_gpr_multi_push_up_to_s8,    code_for_gpr_multi_pop_up_to_s8,
&gt; +   code_for_gpr_multi_popret_up_to_s8},
&gt; +  {code_for_gpr_multi_push_up_to_s9,    code_for_gpr_multi_pop_up_to_s9,
&gt; +   code_for_gpr_multi_popret_up_to_s9},
&gt; +  {nullptr, nullptr, nullptr},
&gt; +  {code_for_gpr_multi_push_up_to_s11,   code_for_gpr_multi_pop_up_to_s11,
&gt; +   code_for_gpr_multi_popret_up_to_s11}};
&gt; +
&gt; +static rtx
&gt; +riscv_gen_multi_push_pop_insn (riscv_zcmp_op_t op, HOST_WIDE_INT adj_size,
&gt; +                               unsigned int regs_num)
&gt; +{
&gt; +  gcc_assert (op &lt; ZCMP_OP_NUM);
&gt; +  gcc_assert (regs_num &lt;= ZCMP_MAX_GRP_SLOTS
&gt; +              &amp;&amp; regs_num != ZCMP_INVALID_S0S10_SREGS_COUNTS + 1); /* 1 for ra*/
&gt; +  rtx stack_adj = GEN_INT (adj_size);
&gt; +  return GEN_FCN (code_for_push_pop[regs_num - 1][op] (Pmode)) (stack_adj);
&gt; +}
&gt; +
&gt;  /* Expand the "prologue" pattern.  */
&gt;  
&gt;  void
&gt; @@ -5405,7 +5579,8 @@ riscv_expand_prologue (void)
&gt;    struct riscv_frame_info *frame = &amp;cfun-&gt;machine-&gt;frame;
&gt;    poly_int64 remaining_size = frame-&gt;total_size;
&gt;    unsigned mask = frame-&gt;mask;
&gt; -  rtx insn;
&gt; +  int spimm, multi_push_additional, stack_adj;
&gt; +  rtx insn, dwarf = NULL_RTX;
&gt;  
&gt;    if (flag_stack_usage_info)
&gt;      current_function_static_stack_size = constant_lower_bound (remaining_size);
&gt; @@ -5413,8 +5588,35 @@ riscv_expand_prologue (void)
&gt;    if (cfun-&gt;machine-&gt;naked_p)
&gt;      return;
&gt;  
&gt; +  /* prefer muti-push to save-restore libcall.  */
&gt; +  if (riscv_use_multi_push(frame))
&gt; +    {
&gt; +      remaining_size -= frame-&gt;multi_push_adj_base;
&gt; +      if (known_gt(remaining_size, 2 * ZCMP_SP_INC_STEP))
&gt; +        spimm = 3;
&gt; +      else if (known_gt(remaining_size, ZCMP_SP_INC_STEP))
&gt; +        spimm = 2;
&gt; +      else if (known_gt(remaining_size, 0))
&gt; +        spimm = 1;
&gt; +      else
&gt; +        spimm = 0;
&gt; +      multi_push_additional = spimm * ZCMP_SP_INC_STEP;
&gt; +      frame-&gt;multi_push_adj_addi = multi_push_additional;
&gt; +      remaining_size -= multi_push_additional;
&gt; +
&gt; +      /* emit multi push insn &amp; dwarf along with it.  */
&gt; +      stack_adj = frame-&gt;multi_push_adj_base + multi_push_additional;
&gt; +      insn = emit_insn (riscv_gen_multi_push_pop_insn(PUSH_IDX,
&gt; +        -stack_adj, riscv_multi_push_regs_count(frame-&gt;mask)));
&gt; +      dwarf = riscv_adjust_multi_push_cfi_prologue (stack_adj);
&gt; +      RTX_FRAME_RELATED_P (insn) = 1;
&gt; +      REG_NOTES (insn) = dwarf;
&gt; +
&gt; +      /* Temporarily fib that we need not save GPRs.  */
&gt; +      frame-&gt;mask = 0;
&gt; +    }
&gt;    /* When optimizing for size, call a subroutine to save the registers.  */
&gt; -  if (riscv_use_save_libcall (frame))
&gt; +  else if (riscv_use_save_libcall (frame))
&gt;      {
&gt;        rtx dwarf = NULL_RTX;
&gt;        dwarf = riscv_adjust_libcall_cfi_prologue ();
&gt; @@ -5430,13 +5632,15 @@ riscv_expand_prologue (void)
&gt;    /* Save the registers.  */
&gt;    if ((frame-&gt;mask | frame-&gt;fmask) != 0)
&gt;      {
&gt; -      HOST_WIDE_INT step1 = riscv_first_stack_step (frame, remaining_size);
&gt; -
&gt; -      insn = gen_add3_insn (stack_pointer_rtx,
&gt; -			    stack_pointer_rtx,
&gt; -			    GEN_INT (-step1));
&gt; -      RTX_FRAME_RELATED_P (emit_insn (insn)) = 1;
&gt; -      remaining_size -= step1;
&gt; +      if (known_gt (remaining_size, frame-&gt;frame_pointer_offset))
&gt; +        {
&gt; +          HOST_WIDE_INT step1 = riscv_first_stack_step (frame, remaining_size);
&gt; +          remaining_size -= step1;
&gt; +          insn = gen_add3_insn (stack_pointer_rtx,
&gt; +                                stack_pointer_rtx,
&gt; +                                GEN_INT (-step1));
&gt; +          RTX_FRAME_RELATED_P (emit_insn (insn)) = 1;
&gt; +        }
&gt;        riscv_for_each_saved_reg (remaining_size, riscv_save_reg, false, false);
&gt;      }
&gt;  
&gt; @@ -5493,6 +5697,32 @@ riscv_expand_prologue (void)
&gt;      }
&gt;  }
&gt;  
&gt; +static rtx
&gt; +riscv_adjust_multi_pop_cfi_epilogue (int saved_size)
&gt; +{
&gt; +  rtx dwarf = NULL_RTX;
&gt; +  rtx adjust_sp_rtx, reg;
&gt; +  unsigned int mask = cfun-&gt;machine-&gt;frame.mask;
&gt; +
&gt; +  if (mask &amp; S10_MASK)
&gt; +    mask |= S11_MASK;
&gt; +
&gt; +  /* Debug info for adjust sp.  */
&gt; +  adjust_sp_rtx = gen_rtx_SET (stack_pointer_rtx,
&gt; +                               plus_constant(Pmode, stack_pointer_rtx, saved_size));
&gt; +  dwarf = alloc_reg_note (REG_CFA_ADJUST_CFA, adjust_sp_rtx,
&gt; +                          dwarf);
&gt; +
&gt; +  for (int regno = GP_REG_FIRST; regno &lt;= GP_REG_LAST; regno++)
&gt; +    if (BITSET_P (mask, regno - GP_REG_FIRST))
&gt; +      {
&gt; +        reg = gen_rtx_REG (Pmode, regno);
&gt; +        dwarf = alloc_reg_note (REG_CFA_RESTORE, reg, dwarf);
&gt; +      }
&gt; +
&gt; +  return dwarf;
&gt; +}
&gt; +
&gt;  static rtx
&gt;  riscv_adjust_libcall_cfi_epilogue ()
&gt;  {
&gt; @@ -5532,10 +5762,18 @@ riscv_expand_epilogue (int style)
&gt;    struct riscv_frame_info *frame = &amp;cfun-&gt;machine-&gt;frame;
&gt;    unsigned mask = frame-&gt;mask;
&gt;    HOST_WIDE_INT step2 = 0;
&gt; -  bool use_restore_libcall = ((style == NORMAL_RETURN)
&gt; -			      &amp;&amp; riscv_use_save_libcall (frame));
&gt; -  unsigned libcall_size = (use_restore_libcall
&gt; -			   ? frame-&gt;save_libcall_adjustment : 0);
&gt; +  bool use_multi_pop_normal = ((style == NORMAL_RETURN)
&gt; +                              &amp;&amp; riscv_use_multi_push (frame));
&gt; +  bool use_multi_pop_sibcall = ((style == SIBCALL_RETURN)
&gt; +                              &amp;&amp; riscv_use_multi_push (frame));
&gt; +  bool use_multi_pop = use_multi_pop_normal || use_multi_pop_sibcall;
&gt; +
&gt; +  bool use_restore_libcall = !use_multi_pop &amp;&amp; ((style == NORMAL_RETURN)
&gt; +                              &amp;&amp; riscv_use_save_libcall (frame));
&gt; +  unsigned libcall_size = use_restore_libcall &amp;&amp; !use_multi_pop ?
&gt; +                            frame-&gt;save_libcall_adjustment : 0;
&gt; +  unsigned multipop_size = use_multi_pop ?
&gt; +                            frame-&gt;multi_push_adj_base + frame-&gt;multi_push_adj_addi : 0;
&gt;    rtx ra = gen_rtx_REG (Pmode, RETURN_ADDR_REGNUM);
&gt;    rtx insn;
&gt;  
&gt; @@ -5606,18 +5844,25 @@ riscv_expand_epilogue (int style)
&gt;        REG_NOTES (insn) = dwarf;
&gt;      }
&gt;  
&gt; -  if (use_restore_libcall)
&gt; -    frame-&gt;mask = 0; /* Temporarily fib for GPRs.  */
&gt; +  if (use_restore_libcall || use_multi_pop)
&gt; +    frame-&gt;mask = 0; /* Temporarily fib that we need not save GPRs.  */
&gt;  
&gt;    /* If we need to restore registers, deallocate as much stack as
&gt;       possible in the second step without going out of range.  */
&gt; -  if ((frame-&gt;mask | frame-&gt;fmask) != 0)
&gt; +  if (use_multi_pop)
&gt; +    {
&gt; +      if (frame-&gt;fmask
&gt; +          &amp;&amp; known_gt (frame-&gt;total_size - multipop_size,
&gt; +                      frame-&gt;frame_pointer_offset))
&gt; +        step2 = riscv_first_stack_step (frame, frame-&gt;total_size - multipop_size);
&gt; +    }
&gt; +  else if ((frame-&gt;mask | frame-&gt;fmask) != 0)
&gt;      step2 = riscv_first_stack_step (frame, frame-&gt;total_size - libcall_size);
&gt;  
&gt; -  if (use_restore_libcall)
&gt; +  if (use_restore_libcall || use_multi_pop)
&gt;      frame-&gt;mask = mask; /* Undo the above fib.  */
&gt;  
&gt; -  poly_int64 step1 = frame-&gt;total_size - step2 - libcall_size;
&gt; +  poly_int64 step1 = frame-&gt;total_size - step2 - libcall_size - multipop_size ;
&gt;  
&gt;    /* Set TARGET to BASE + STEP1.  */
&gt;    if (known_gt (step1, 0))
&gt; @@ -5652,7 +5897,7 @@ riscv_expand_epilogue (int style)
&gt;  					   adjust));
&gt;  	  rtx dwarf = NULL_RTX;
&gt;  	  rtx cfa_adjust_rtx = gen_rtx_PLUS (Pmode, stack_pointer_rtx,
&gt; -					     GEN_INT (step2 + libcall_size));
&gt; +					     GEN_INT (step2 + libcall_size + multipop_size));
&gt;  
&gt;  	  dwarf = alloc_reg_note (REG_CFA_DEF_CFA, cfa_adjust_rtx, dwarf);
&gt;  	  RTX_FRAME_RELATED_P (insn) = 1;
&gt; @@ -5667,15 +5912,15 @@ riscv_expand_epilogue (int style)
&gt;        epilogue_cfa_sp_offset = step2;
&gt;      }
&gt;  
&gt; -  if (use_restore_libcall)
&gt; +  if (use_restore_libcall || use_multi_pop)
&gt;      frame-&gt;mask = 0; /* Temporarily fib that we need not save GPRs.  */
&gt;  
&gt;    /* Restore the registers.  */
&gt; -  riscv_for_each_saved_reg (frame-&gt;total_size - step2 - libcall_size,
&gt; +  riscv_for_each_saved_reg (frame-&gt;total_size - step2 - libcall_size - multipop_size,
&gt;  			    riscv_restore_reg,
&gt;  			    true, style == EXCEPTION_RETURN);
&gt;  
&gt; -  if (use_restore_libcall)
&gt; +  if (use_restore_libcall || use_multi_pop)
&gt;        frame-&gt;mask = mask; /* Undo the above fib.  */
&gt;  
&gt;    if (need_barrier_p)
&gt; @@ -5689,14 +5934,30 @@ riscv_expand_epilogue (int style)
&gt;  
&gt;        rtx dwarf = NULL_RTX;
&gt;        rtx cfa_adjust_rtx = gen_rtx_PLUS (Pmode, stack_pointer_rtx,
&gt; -					 GEN_INT (libcall_size));
&gt; +					 GEN_INT (libcall_size + multipop_size));
&gt;        dwarf = alloc_reg_note (REG_CFA_DEF_CFA, cfa_adjust_rtx, dwarf);
&gt;        RTX_FRAME_RELATED_P (insn) = 1;
&gt;  
&gt;        REG_NOTES (insn) = dwarf;
&gt;      }
&gt;  
&gt; -  if (use_restore_libcall)
&gt; +  if (use_multi_pop)
&gt; +    {
&gt; +      unsigned regs_count = riscv_multi_push_regs_count (frame-&gt;mask);
&gt; +      if (use_multi_pop_normal)
&gt; +        insn = emit_jump_insn (
&gt; +          riscv_gen_multi_push_pop_insn (POPRET_IDX, multipop_size, regs_count));
&gt; +      else
&gt; +        insn= emit_insn (
&gt; +          riscv_gen_multi_push_pop_insn(POP_IDX, multipop_size, regs_count));
&gt; +
&gt; +      rtx dwarf = riscv_adjust_multi_pop_cfi_epilogue (multipop_size);
&gt; +      RTX_FRAME_RELATED_P (insn) = 1;
&gt; +      REG_NOTES (insn) = dwarf;
&gt; +      if (use_multi_pop_normal)
&gt; +        return;
&gt; +    }
&gt; +  else if (use_restore_libcall)
&gt;      {
&gt;        rtx dwarf = riscv_adjust_libcall_cfi_epilogue ();
&gt;        insn = emit_insn (gen_gpr_restore (GEN_INT (riscv_save_libcall_count (mask))));
&gt; @@ -6980,6 +7241,25 @@ riscv_gen_gpr_save_insn (struct riscv_frame_info *frame)
&gt;    return gen_rtx_PARALLEL (VOIDmode, vec);
&gt;  }
&gt;  
&gt; +static HOST_WIDE_INT zcmp_base_adj(int regs_num)
&gt; +{
&gt; +  return riscv_16bytes_align ((regs_num) * GET_MODE_SIZE (word_mode));
&gt; +}
&gt; +
&gt; +static HOST_WIDE_INT zcmp_additional_adj(HOST_WIDE_INT total, int regs_num)
&gt; +{
&gt; +  return total - zcmp_base_adj(regs_num);
&gt; +}
&gt; +
&gt; +bool riscv_zcmp_valid_stack_adj_bytes_p (HOST_WIDE_INT total, int regs_num)
&gt; +{
&gt; +  HOST_WIDE_INT additioanl_bytes = zcmp_additional_adj(total, regs_num);
&gt; +  return additioanl_bytes == 0
&gt; +         || additioanl_bytes  == 1 * ZCMP_SP_INC_STEP
&gt; +         || additioanl_bytes  == 2 * ZCMP_SP_INC_STEP
&gt; +         || additioanl_bytes  == ZCMP_MAX_SPIMM * ZCMP_SP_INC_STEP;
&gt; +}
&gt; +
&gt;  /* Return true if it's valid gpr_save pattern.  */
&gt;  
&gt;  bool
&gt; diff --git a/gcc/config/riscv/riscv.h b/gcc/config/riscv/riscv.h
&gt; index 4541255a8ae..2fa555dce2d 100644
&gt; --- a/gcc/config/riscv/riscv.h
&gt; +++ b/gcc/config/riscv/riscv.h
&gt; @@ -420,6 +420,29 @@ ASM_MISA_SPEC
&gt;  #define RISCV_CALL_ADDRESS_TEMP(MODE) \
&gt;    gen_rtx_REG (MODE, RISCV_CALL_ADDRESS_TEMP_REGNUM)
&gt;  
&gt; +#define RETURN_ADDR_MASK        ( 1 &lt;&lt; RETURN_ADDR_REGNUM)
&gt; +#define S0_MASK                 ( 1 &lt;&lt; S0_REGNUM)
&gt; +#define S1_MASK                 ( 1 &lt;&lt; S1_REGNUM)
&gt; +#define S2_MASK                 ( 1 &lt;&lt; S2_REGNUM)
&gt; +#define S3_MASK                 ( 1 &lt;&lt; S3_REGNUM)
&gt; +#define S4_MASK                 ( 1 &lt;&lt; S4_REGNUM)
&gt; +#define S5_MASK                 ( 1 &lt;&lt; S5_REGNUM)
&gt; +#define S6_MASK                 ( 1 &lt;&lt; S6_REGNUM)
&gt; +#define S7_MASK                 ( 1 &lt;&lt; S7_REGNUM)
&gt; +#define S8_MASK                 ( 1 &lt;&lt; S8_REGNUM)
&gt; +#define S9_MASK                 ( 1 &lt;&lt; S9_REGNUM)
&gt; +#define S10_MASK                ( 1 &lt;&lt; S10_REGNUM)
&gt; +#define S11_MASK                ( 1 &lt;&lt; S11_REGNUM)
&gt; +
&gt; +#define MULTI_PUSH_GPR_MASK ( RETURN_ADDR_MASK | S0_MASK | S1_MASK | S2_MASK  | S3_MASK \
&gt; +                                               | S4_MASK | S5_MASK | S6_MASK  | S7_MASK \
&gt; +                                               | S8_MASK | S9_MASK | S10_MASK | S11_MASK )
&gt; +#define ZCMP_MAX_SPIMM 3
&gt; +#define ZCMP_SP_INC_STEP 16
&gt; +#define ZCMP_INVALID_S0S10_SREGS_COUNTS 11
&gt; +#define ZCMP_S0S11_SREGS_COUNTS 12
&gt; +#define ZCMP_MAX_GRP_SLOTS 13
&gt; +
&gt;  #define MCOUNT_NAME "_mcount"
&gt;  
&gt;  #define NO_PROFILE_COUNTERS 1
&gt; diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md
&gt; index be960583101..c858b3bc9ef 100644
&gt; --- a/gcc/config/riscv/riscv.md
&gt; +++ b/gcc/config/riscv/riscv.md
&gt; @@ -113,6 +113,7 @@
&gt;  
&gt;  (define_constants
&gt;    [(RETURN_ADDR_REGNUM		1)
&gt; +   (SP_REGNUM 			2)
&gt;     (GP_REGNUM 			3)
&gt;     (TP_REGNUM			4)
&gt;     (T0_REGNUM			5)
&gt; @@ -3163,3 +3164,4 @@
&gt;  (include "sifive-7.md")
&gt;  (include "thead.md")
&gt;  (include "vector.md")
&gt; +(include "zc.md")
&gt; diff --git a/gcc/config/riscv/zc.md b/gcc/config/riscv/zc.md
&gt; new file mode 100644
&gt; index 00000000000..5c1bf031b8d
&gt; --- /dev/null
&gt; +++ b/gcc/config/riscv/zc.md
&gt; @@ -0,0 +1,1042 @@
&gt; +;; Machine description for RISC-V Zc extention.
&gt; +;; Copyright (C) 2023 Free Software Foundation, Inc.
&gt; +;; Contributed by Fei Gao (gaofei@eswincomputing.com).
&gt; +
&gt; +;; This file is part of GCC.
&gt; +
&gt; +;; GCC is free software; you can redistribute it and/or modify
&gt; +;; it under the terms of the GNU General Public License as published by
&gt; +;; the Free Software Foundation; either version 3, or (at your option)
&gt; +;; any later version.
&gt; +
&gt; +;; GCC is distributed in the hope that it will be useful,
&gt; +;; but WITHOUT ANY WARRANTY; without even the implied warranty of
&gt; +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
&gt; +;; GNU General Public License for more details.
&gt; +
&gt; +;; You should have received a copy of the GNU General Public License
&gt; +;; along with GCC; see the file COPYING3.  If not see
&gt; +;; <http: www.gnu.org="" licenses=""></http:>.
&gt; +
&gt; +(define_insn "@gpr_multi_pop_up_to_ra_<mode>"
&gt; +  [(set (reg:X SP_REGNUM)
&gt; +        (plus:X (reg:X SP_REGNUM)
&gt; +                 (match_operand 0 "stack_pop_up_to_ra_operand" "I")))
&gt; +   (set (reg:X RETURN_ADDR_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot0_offset>))))]
&gt; +  "TARGET_ZCMP"
&gt; +  "cm.pop	{ra}, %0"
&gt; +)
&gt; +
&gt; +(define_insn "@gpr_multi_pop_up_to_s0_<mode>"
&gt; +  [(set (reg:X SP_REGNUM)
&gt; +        (plus:X (reg:X SP_REGNUM)
&gt; +                 (match_operand 0 "stack_pop_up_to_s0_operand" "I")))
&gt; +   (set (reg:X S0_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot0_offset>))))
&gt; +   (set (reg:X RETURN_ADDR_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot1_offset>))))]
&gt; +  "TARGET_ZCMP"
&gt; +  "cm.pop	{ra, s0}, %0"
&gt; +)
&gt; +
&gt; +(define_insn "@gpr_multi_pop_up_to_s1_<mode>"
&gt; +  [(set (reg:X SP_REGNUM)
&gt; +        (plus:X (reg:X SP_REGNUM)
&gt; +                 (match_operand 0 "stack_pop_up_to_s1_operand" "I")))
&gt; +   (set (reg:X S1_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot0_offset>))))
&gt; +   (set (reg:X S0_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot1_offset>))))
&gt; +   (set (reg:X RETURN_ADDR_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot2_offset>))))]
&gt; +  "TARGET_ZCMP"
&gt; +  "cm.pop	{ra, s0-s1}, %0"
&gt; +)
&gt; +
&gt; +(define_insn "@gpr_multi_pop_up_to_s2_<mode>"
&gt; +  [(set (reg:X SP_REGNUM)
&gt; +        (plus:X (reg:X SP_REGNUM)
&gt; +                 (match_operand 0 "stack_pop_up_to_s2_operand" "I")))
&gt; +   (set (reg:X S2_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot0_offset>))))
&gt; +   (set (reg:X S1_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot1_offset>))))
&gt; +   (set (reg:X S0_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot2_offset>))))
&gt; +   (set (reg:X RETURN_ADDR_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot3_offset>))))]
&gt; +  "TARGET_ZCMP"
&gt; +  "cm.pop	{ra, s0-s2}, %0"
&gt; +)
&gt; +
&gt; +(define_insn "@gpr_multi_pop_up_to_s3_<mode>"
&gt; +  [(set (reg:X SP_REGNUM)
&gt; +        (plus:X (reg:X SP_REGNUM)
&gt; +                 (match_operand 0 "stack_pop_up_to_s3_operand" "I")))
&gt; +   (set (reg:X S3_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot0_offset>))))
&gt; +   (set (reg:X S2_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot1_offset>))))
&gt; +   (set (reg:X S1_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot2_offset>))))
&gt; +   (set (reg:X S0_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot3_offset>))))
&gt; +   (set (reg:X RETURN_ADDR_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot4_offset>))))]
&gt; +  "TARGET_ZCMP"
&gt; +  "cm.pop	{ra, s0-s3}, %0"
&gt; +)
&gt; +
&gt; +(define_insn "@gpr_multi_pop_up_to_s4_<mode>"
&gt; +  [(set (reg:X SP_REGNUM)
&gt; +        (plus:X (reg:X SP_REGNUM)
&gt; +                 (match_operand 0 "stack_pop_up_to_s4_operand" "I")))
&gt; +   (set (reg:X S4_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot0_offset>))))
&gt; +   (set (reg:X S3_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot1_offset>))))
&gt; +   (set (reg:X S2_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot2_offset>))))
&gt; +   (set (reg:X S1_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot3_offset>))))
&gt; +   (set (reg:X S0_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot4_offset>))))
&gt; +   (set (reg:X RETURN_ADDR_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot5_offset>))))]
&gt; +  "TARGET_ZCMP"
&gt; +  "cm.pop	{ra, s0-s4}, %0"
&gt; +)
&gt; +
&gt; +(define_insn "@gpr_multi_pop_up_to_s5_<mode>"
&gt; +  [(set (reg:X SP_REGNUM)
&gt; +        (plus:X (reg:X SP_REGNUM)
&gt; +                 (match_operand 0 "stack_pop_up_to_s5_operand" "I")))
&gt; +   (set (reg:X S5_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot0_offset>))))
&gt; +   (set (reg:X S4_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot1_offset>))))
&gt; +   (set (reg:X S3_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot2_offset>))))
&gt; +   (set (reg:X S2_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot3_offset>))))
&gt; +   (set (reg:X S1_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot4_offset>))))
&gt; +   (set (reg:X S0_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot5_offset>))))
&gt; +   (set (reg:X RETURN_ADDR_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot6_offset>))))]
&gt; +  "TARGET_ZCMP"
&gt; +  "cm.pop	{ra, s0-s5}, %0"
&gt; +)
&gt; +
&gt; +(define_insn "@gpr_multi_pop_up_to_s6_<mode>"
&gt; +  [(set (reg:X SP_REGNUM)
&gt; +        (plus:X (reg:X SP_REGNUM)
&gt; +                 (match_operand 0 "stack_pop_up_to_s6_operand" "I")))
&gt; +   (set (reg:X S6_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot0_offset>))))
&gt; +   (set (reg:X S5_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot1_offset>))))
&gt; +   (set (reg:X S4_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot2_offset>))))
&gt; +   (set (reg:X S3_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot3_offset>))))
&gt; +   (set (reg:X S2_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot4_offset>))))
&gt; +   (set (reg:X S1_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot5_offset>))))
&gt; +   (set (reg:X S0_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot6_offset>))))
&gt; +   (set (reg:X RETURN_ADDR_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot7_offset>))))]
&gt; +  "TARGET_ZCMP"
&gt; +  "cm.pop	{ra, s0-s6}, %0"
&gt; +)
&gt; +
&gt; +(define_insn "@gpr_multi_pop_up_to_s7_<mode>"
&gt; +  [(set (reg:X SP_REGNUM)
&gt; +        (plus:X (reg:X SP_REGNUM)
&gt; +                 (match_operand 0 "stack_pop_up_to_s7_operand" "I")))
&gt; +   (set (reg:X S7_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot0_offset>))))
&gt; +   (set (reg:X S6_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot1_offset>))))
&gt; +   (set (reg:X S5_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot2_offset>))))
&gt; +   (set (reg:X S4_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot3_offset>))))
&gt; +   (set (reg:X S3_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot4_offset>))))
&gt; +   (set (reg:X S2_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot5_offset>))))
&gt; +   (set (reg:X S1_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot6_offset>))))
&gt; +   (set (reg:X S0_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot7_offset>))))
&gt; +   (set (reg:X RETURN_ADDR_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                      (const_int <slot8_offset>))))]
&gt; +  "TARGET_ZCMP"
&gt; +  "cm.pop	{ra, s0-s7}, %0"
&gt; +)
&gt; +
&gt; +(define_insn "@gpr_multi_pop_up_to_s8_<mode>"
&gt; +  [(set (reg:X SP_REGNUM)
&gt; +        (plus:X (reg:X SP_REGNUM)
&gt; +                 (match_operand 0 "stack_pop_up_to_s8_operand" "I")))
&gt; +   (set (reg:X S8_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot0_offset>))))
&gt; +   (set (reg:X S7_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot1_offset>))))
&gt; +   (set (reg:X S6_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot2_offset>))))
&gt; +   (set (reg:X S5_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot3_offset>))))
&gt; +   (set (reg:X S4_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot4_offset>))))
&gt; +   (set (reg:X S3_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot5_offset>))))
&gt; +   (set (reg:X S2_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot6_offset>))))
&gt; +   (set (reg:X S1_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot7_offset>))))
&gt; +   (set (reg:X S0_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot8_offset>))))
&gt; +   (set (reg:X RETURN_ADDR_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot9_offset>))))]
&gt; +  "TARGET_ZCMP"
&gt; +  "cm.pop	{ra, s0-s8}, %0"
&gt; +)
&gt; +
&gt; +(define_insn "@gpr_multi_pop_up_to_s9_<mode>"
&gt; +  [(set (reg:X SP_REGNUM)
&gt; +        (plus:X (reg:X SP_REGNUM)
&gt; +                 (match_operand 0 "stack_pop_up_to_s9_operand" "I")))
&gt; +   (set (reg:X S9_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot0_offset>))))
&gt; +   (set (reg:X S8_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot1_offset>))))
&gt; +   (set (reg:X S7_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot2_offset>))))
&gt; +   (set (reg:X S6_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot3_offset>))))
&gt; +   (set (reg:X S5_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot4_offset>))))
&gt; +   (set (reg:X S4_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot5_offset>))))
&gt; +   (set (reg:X S3_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot6_offset>))))
&gt; +   (set (reg:X S2_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot7_offset>))))
&gt; +   (set (reg:X S1_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                      (const_int <slot8_offset>))))
&gt; +   (set (reg:X S0_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot9_offset>))))
&gt; +   (set (reg:X RETURN_ADDR_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot10_offset>))))]
&gt; +  "TARGET_ZCMP"
&gt; +  "cm.pop	{ra, s0-s9}, %0"
&gt; +)
&gt; +
&gt; +(define_insn "@gpr_multi_pop_up_to_s11_<mode>"
&gt; +  [(set (reg:X SP_REGNUM)
&gt; +        (plus:X (reg:X SP_REGNUM)
&gt; +                 (match_operand 0 "stack_pop_up_to_s11_operand" "I")))
&gt; +   (set (reg:X S11_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot0_offset>))))
&gt; +   (set (reg:X S10_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot1_offset>))))
&gt; +   (set (reg:X S9_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot2_offset>))))
&gt; +   (set (reg:X S8_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot3_offset>))))
&gt; +   (set (reg:X S7_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot4_offset>))))
&gt; +   (set (reg:X S6_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot5_offset>))))
&gt; +   (set (reg:X S5_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot6_offset>))))
&gt; +   (set (reg:X S4_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot7_offset>))))
&gt; +   (set (reg:X S3_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                      (const_int <slot8_offset>))))
&gt; +   (set (reg:X S2_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot9_offset>))))
&gt; +   (set (reg:X S1_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot10_offset>))))
&gt; +   (set (reg:X S0_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot11_offset>))))
&gt; +   (set (reg:X RETURN_ADDR_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot12_offset>))))]
&gt; +  "TARGET_ZCMP"
&gt; +  "cm.pop	{ra, s0-s11}, %0"
&gt; +)
&gt; +
&gt; +(define_insn "@gpr_multi_popret_up_to_ra_<mode>"
&gt; +  [(set (reg:X SP_REGNUM)
&gt; +        (plus:X (reg:X SP_REGNUM)
&gt; +                 (match_operand 0 "stack_pop_up_to_ra_operand" "I")))
&gt; +   (set (reg:X RETURN_ADDR_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot0_offset>))))
&gt; +   (return)
&gt; +   (use (reg:SI RETURN_ADDR_REGNUM))]
&gt; +  "TARGET_ZCMP"
&gt; +  "cm.popret	{ra}, %0"
&gt; +)
&gt; +
&gt; +(define_insn "@gpr_multi_popret_up_to_s0_<mode>"
&gt; +  [(set (reg:X SP_REGNUM)
&gt; +        (plus:X (reg:X SP_REGNUM)
&gt; +                 (match_operand 0 "stack_pop_up_to_s0_operand" "I")))
&gt; +   (set (reg:X S0_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot0_offset>))))
&gt; +   (set (reg:X RETURN_ADDR_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot1_offset>))))
&gt; +   (return)
&gt; +   (use (reg:SI RETURN_ADDR_REGNUM))]
&gt; +  "TARGET_ZCMP"
&gt; +  "cm.popret	{ra, s0}, %0"
&gt; +)
&gt; +
&gt; +(define_insn "@gpr_multi_popret_up_to_s1_<mode>"
&gt; +  [(set (reg:X SP_REGNUM)
&gt; +        (plus:X (reg:X SP_REGNUM)
&gt; +                 (match_operand 0 "stack_pop_up_to_s1_operand" "I")))
&gt; +   (set (reg:X S1_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot0_offset>))))
&gt; +   (set (reg:X S0_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot1_offset>))))
&gt; +   (set (reg:X RETURN_ADDR_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot2_offset>))))
&gt; +   (return)
&gt; +   (use (reg:SI RETURN_ADDR_REGNUM))]
&gt; +  "TARGET_ZCMP"
&gt; +  "cm.popret	{ra, s0-s1}, %0"
&gt; +)
&gt; +
&gt; +(define_insn "@gpr_multi_popret_up_to_s2_<mode>"
&gt; +  [(set (reg:X SP_REGNUM)
&gt; +        (plus:X (reg:X SP_REGNUM)
&gt; +                 (match_operand 0 "stack_pop_up_to_s2_operand" "I")))
&gt; +   (set (reg:X S2_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot0_offset>))))
&gt; +   (set (reg:X S1_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot1_offset>))))
&gt; +   (set (reg:X S0_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot2_offset>))))
&gt; +   (set (reg:X RETURN_ADDR_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot3_offset>))))
&gt; +   (return)
&gt; +   (use (reg:SI RETURN_ADDR_REGNUM))]
&gt; +  "TARGET_ZCMP"
&gt; +  "cm.popret	{ra, s0-s2}, %0"
&gt; +)
&gt; +
&gt; +(define_insn "@gpr_multi_popret_up_to_s3_<mode>"
&gt; +  [(set (reg:X SP_REGNUM)
&gt; +        (plus:X (reg:X SP_REGNUM)
&gt; +                 (match_operand 0 "stack_pop_up_to_s3_operand" "I")))
&gt; +   (set (reg:X S3_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot0_offset>))))
&gt; +   (set (reg:X S2_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot1_offset>))))
&gt; +   (set (reg:X S1_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot2_offset>))))
&gt; +   (set (reg:X S0_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot3_offset>))))
&gt; +   (set (reg:X RETURN_ADDR_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot4_offset>))))
&gt; +   (return)
&gt; +   (use (reg:SI RETURN_ADDR_REGNUM))]
&gt; +  "TARGET_ZCMP"
&gt; +  "cm.popret	{ra, s0-s3}, %0"
&gt; +)
&gt; +
&gt; +(define_insn "@gpr_multi_popret_up_to_s4_<mode>"
&gt; +  [(set (reg:X SP_REGNUM)
&gt; +        (plus:X (reg:X SP_REGNUM)
&gt; +                 (match_operand 0 "stack_pop_up_to_s4_operand" "I")))
&gt; +   (set (reg:X S4_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot0_offset>))))
&gt; +   (set (reg:X S3_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot1_offset>))))
&gt; +   (set (reg:X S2_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot2_offset>))))
&gt; +   (set (reg:X S1_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot3_offset>))))
&gt; +   (set (reg:X S0_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot4_offset>))))
&gt; +   (set (reg:X RETURN_ADDR_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot5_offset>))))
&gt; +   (return)
&gt; +   (use (reg:SI RETURN_ADDR_REGNUM))]
&gt; +  "TARGET_ZCMP"
&gt; +  "cm.popret	{ra, s0-s4}, %0"
&gt; +)
&gt; +
&gt; +(define_insn "@gpr_multi_popret_up_to_s5_<mode>"
&gt; +  [(set (reg:X SP_REGNUM)
&gt; +        (plus:X (reg:X SP_REGNUM)
&gt; +                 (match_operand 0 "stack_pop_up_to_s5_operand" "I")))
&gt; +   (set (reg:X S5_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot0_offset>))))
&gt; +   (set (reg:X S4_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot1_offset>))))
&gt; +   (set (reg:X S3_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot2_offset>))))
&gt; +   (set (reg:X S2_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot3_offset>))))
&gt; +   (set (reg:X S1_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot4_offset>))))
&gt; +   (set (reg:X S0_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot5_offset>))))
&gt; +   (set (reg:X RETURN_ADDR_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot6_offset>))))
&gt; +   (return)
&gt; +   (use (reg:SI RETURN_ADDR_REGNUM))]
&gt; +  "TARGET_ZCMP"
&gt; +  "cm.popret	{ra, s0-s5}, %0"
&gt; +)
&gt; +
&gt; +(define_insn "@gpr_multi_popret_up_to_s6_<mode>"
&gt; +  [(set (reg:X SP_REGNUM)
&gt; +        (plus:X (reg:X SP_REGNUM)
&gt; +                 (match_operand 0 "stack_pop_up_to_s6_operand" "I")))
&gt; +   (set (reg:X S6_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot0_offset>))))
&gt; +   (set (reg:X S5_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot1_offset>))))
&gt; +   (set (reg:X S4_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot2_offset>))))
&gt; +   (set (reg:X S3_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot3_offset>))))
&gt; +   (set (reg:X S2_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot4_offset>))))
&gt; +   (set (reg:X S1_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot5_offset>))))
&gt; +   (set (reg:X S0_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot6_offset>))))
&gt; +   (set (reg:X RETURN_ADDR_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot7_offset>))))
&gt; +   (return)
&gt; +   (use (reg:SI RETURN_ADDR_REGNUM))]
&gt; +  "TARGET_ZCMP"
&gt; +  "cm.popret	{ra, s0-s6}, %0"
&gt; +)
&gt; +
&gt; +(define_insn "@gpr_multi_popret_up_to_s7_<mode>"
&gt; +  [(set (reg:X SP_REGNUM)
&gt; +        (plus:X (reg:X SP_REGNUM)
&gt; +                 (match_operand 0 "stack_pop_up_to_s7_operand" "I")))
&gt; +   (set (reg:X S7_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot0_offset>))))
&gt; +   (set (reg:X S6_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot1_offset>))))
&gt; +   (set (reg:X S5_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot2_offset>))))
&gt; +   (set (reg:X S4_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot3_offset>))))
&gt; +   (set (reg:X S3_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot4_offset>))))
&gt; +   (set (reg:X S2_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot5_offset>))))
&gt; +   (set (reg:X S1_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot6_offset>))))
&gt; +   (set (reg:X S0_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot7_offset>))))
&gt; +   (set (reg:X RETURN_ADDR_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot8_offset>))))
&gt; +   (return)
&gt; +   (use (reg:SI RETURN_ADDR_REGNUM))]
&gt; +  "TARGET_ZCMP"
&gt; +  "cm.popret	{ra, s0-s7}, %0"
&gt; +)
&gt; +
&gt; +(define_insn "@gpr_multi_popret_up_to_s8_<mode>"
&gt; +  [(set (reg:X SP_REGNUM)
&gt; +        (plus:X (reg:X SP_REGNUM)
&gt; +                 (match_operand 0 "stack_pop_up_to_s8_operand" "I")))
&gt; +   (set (reg:X S8_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot0_offset>))))
&gt; +   (set (reg:X S7_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot1_offset>))))
&gt; +   (set (reg:X S6_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot2_offset>))))
&gt; +   (set (reg:X S5_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot3_offset>))))
&gt; +   (set (reg:X S4_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot4_offset>))))
&gt; +   (set (reg:X S3_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot5_offset>))))
&gt; +   (set (reg:X S2_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot6_offset>))))
&gt; +   (set (reg:X S1_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot7_offset>))))
&gt; +   (set (reg:X S0_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot8_offset>))))
&gt; +   (set (reg:X RETURN_ADDR_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot9_offset>))))
&gt; +   (return)
&gt; +   (use (reg:SI RETURN_ADDR_REGNUM))]
&gt; +  "TARGET_ZCMP"
&gt; +  "cm.popret	{ra, s0-s8}, %0"
&gt; +)
&gt; +
&gt; +(define_insn "@gpr_multi_popret_up_to_s9_<mode>"
&gt; +  [(set (reg:X SP_REGNUM)
&gt; +        (plus:X (reg:X SP_REGNUM)
&gt; +                 (match_operand 0 "stack_pop_up_to_s9_operand" "I")))
&gt; +   (set (reg:X S9_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot0_offset>))))
&gt; +   (set (reg:X S8_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot1_offset>))))
&gt; +   (set (reg:X S7_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot2_offset>))))
&gt; +   (set (reg:X S6_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot3_offset>))))
&gt; +   (set (reg:X S5_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot4_offset>))))
&gt; +   (set (reg:X S4_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot5_offset>))))
&gt; +   (set (reg:X S3_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot6_offset>))))
&gt; +   (set (reg:X S2_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot7_offset>))))
&gt; +   (set (reg:X S1_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot8_offset>))))
&gt; +   (set (reg:X S0_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot9_offset>))))
&gt; +   (set (reg:X RETURN_ADDR_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot10_offset>))))
&gt; +   (return)
&gt; +   (use (reg:SI RETURN_ADDR_REGNUM))]
&gt; +  "TARGET_ZCMP"
&gt; +  "cm.popret	{ra, s0-s9}, %0"
&gt; +)
&gt; +
&gt; +(define_insn "@gpr_multi_popret_up_to_s11_<mode>"
&gt; +  [(set (reg:X SP_REGNUM)
&gt; +        (plus:X (reg:X SP_REGNUM)
&gt; +                 (match_operand 0 "stack_pop_up_to_s11_operand" "I")))
&gt; +   (set (reg:X S11_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot0_offset>))))
&gt; +   (set (reg:X S10_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot1_offset>))))
&gt; +   (set (reg:X S9_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot2_offset>))))
&gt; +   (set (reg:X S8_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot3_offset>))))
&gt; +   (set (reg:X S7_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot4_offset>))))
&gt; +   (set (reg:X S6_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot5_offset>))))
&gt; +   (set (reg:X S5_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot6_offset>))))
&gt; +   (set (reg:X S4_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot7_offset>))))
&gt; +   (set (reg:X S3_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                      (const_int <slot8_offset>))))
&gt; +   (set (reg:X S2_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot9_offset>))))
&gt; +   (set (reg:X S1_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot10_offset>))))
&gt; +   (set (reg:X S0_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot11_offset>))))
&gt; +   (set (reg:X RETURN_ADDR_REGNUM)
&gt; +        (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot12_offset>))))
&gt; +   (return)
&gt; +   (use (reg:SI RETURN_ADDR_REGNUM))]
&gt; +  "TARGET_ZCMP"
&gt; +  "cm.popret	{ra, s0-s11}, %0"
&gt; +)
&gt; +
&gt; +(define_insn "@gpr_multi_push_up_to_ra_<mode>"
&gt; +  [(set (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot0_offset>)))
&gt; +        (reg:X RETURN_ADDR_REGNUM))
&gt; +   (set (reg:X SP_REGNUM)
&gt; +        (plus:X (reg:X SP_REGNUM)
&gt; +                 (match_operand 0 "stack_push_up_to_ra_operand" "I")))]
&gt; +  "TARGET_ZCMP"
&gt; +  "cm.push	{ra}, %0"
&gt; +)
&gt; +
&gt; +(define_insn "@gpr_multi_push_up_to_s0_<mode>"
&gt; +  [(set (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot0_offset>)))
&gt; +        (reg:X S0_REGNUM))
&gt; +   (set (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot1_offset>)))
&gt; +        (reg:X RETURN_ADDR_REGNUM))
&gt; +   (set (reg:X SP_REGNUM)
&gt; +        (plus:X (reg:X SP_REGNUM)
&gt; +                 (match_operand 0 "stack_push_up_to_s0_operand" "I")))]
&gt; +  "TARGET_ZCMP"
&gt; +  "cm.push	{ra, s0}, %0"
&gt; +)
&gt; +
&gt; +(define_insn "@gpr_multi_push_up_to_s1_<mode>"
&gt; +  [(set (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot0_offset>)))
&gt; +        (reg:X S1_REGNUM))
&gt; +   (set (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot1_offset>)))
&gt; +        (reg:X S0_REGNUM))
&gt; +   (set (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot2_offset>)))
&gt; +        (reg:X RETURN_ADDR_REGNUM))
&gt; +   (set (reg:X SP_REGNUM)
&gt; +        (plus:X (reg:X SP_REGNUM)
&gt; +                 (match_operand 0 "stack_push_up_to_s1_operand" "I")))]
&gt; +  "TARGET_ZCMP"
&gt; +  "cm.push	{ra, s0-s1}, %0"
&gt; +)
&gt; +
&gt; +(define_insn "@gpr_multi_push_up_to_s2_<mode>"
&gt; +  [(set (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot0_offset>)))
&gt; +        (reg:X S2_REGNUM))
&gt; +   (set (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot1_offset>)))
&gt; +        (reg:X S1_REGNUM))
&gt; +   (set (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot2_offset>)))
&gt; +        (reg:X S0_REGNUM))
&gt; +   (set (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot3_offset>)))
&gt; +        (reg:X RETURN_ADDR_REGNUM))
&gt; +   (set (reg:X SP_REGNUM)
&gt; +        (plus:X (reg:X SP_REGNUM)
&gt; +                 (match_operand 0 "stack_push_up_to_s2_operand" "I")))]
&gt; +  "TARGET_ZCMP"
&gt; +  "cm.push	{ra, s0-s2}, %0"
&gt; +)
&gt; +
&gt; +(define_insn "@gpr_multi_push_up_to_s3_<mode>"
&gt; +  [(set (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot0_offset>)))
&gt; +        (reg:X S3_REGNUM))
&gt; +   (set (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot1_offset>)))
&gt; +        (reg:X S2_REGNUM))
&gt; +   (set (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot2_offset>)))
&gt; +        (reg:X S1_REGNUM))
&gt; +   (set (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot3_offset>)))
&gt; +        (reg:X S0_REGNUM))
&gt; +   (set (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot4_offset>)))
&gt; +        (reg:X RETURN_ADDR_REGNUM))
&gt; +   (set (reg:X SP_REGNUM)
&gt; +        (plus:X (reg:X SP_REGNUM)
&gt; +                 (match_operand 0 "stack_push_up_to_s3_operand" "I")))]
&gt; +  "TARGET_ZCMP"
&gt; +  "cm.push	{ra, s0-s3}, %0"
&gt; +)
&gt; +
&gt; +(define_insn "@gpr_multi_push_up_to_s4_<mode>"
&gt; +  [(set (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot0_offset>)))
&gt; +        (reg:X S4_REGNUM))
&gt; +   (set (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot1_offset>)))
&gt; +        (reg:X S3_REGNUM))
&gt; +   (set (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot2_offset>)))
&gt; +        (reg:X S2_REGNUM))
&gt; +   (set (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot3_offset>)))
&gt; +        (reg:X S1_REGNUM))
&gt; +   (set (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot4_offset>)))
&gt; +        (reg:X S0_REGNUM))
&gt; +   (set (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot5_offset>)))
&gt; +        (reg:X RETURN_ADDR_REGNUM))
&gt; +   (set (reg:X SP_REGNUM)
&gt; +        (plus:X (reg:X SP_REGNUM)
&gt; +                 (match_operand 0 "stack_push_up_to_s4_operand" "I")))]
&gt; +  "TARGET_ZCMP"
&gt; +  "cm.push	{ra, s0-s4}, %0"
&gt; +)
&gt; +
&gt; +(define_insn "@gpr_multi_push_up_to_s5_<mode>"
&gt; +  [(set (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot0_offset>)))
&gt; +        (reg:X S5_REGNUM))
&gt; +   (set (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot1_offset>)))
&gt; +        (reg:X S4_REGNUM))
&gt; +   (set (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot2_offset>)))
&gt; +        (reg:X S3_REGNUM))
&gt; +   (set (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot3_offset>)))
&gt; +        (reg:X S2_REGNUM))
&gt; +   (set (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot4_offset>)))
&gt; +        (reg:X S1_REGNUM))
&gt; +   (set (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot5_offset>)))
&gt; +        (reg:X S0_REGNUM))
&gt; +   (set (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot6_offset>)))
&gt; +        (reg:X RETURN_ADDR_REGNUM))
&gt; +   (set (reg:X SP_REGNUM)
&gt; +        (plus:X (reg:X SP_REGNUM)
&gt; +                 (match_operand 0 "stack_push_up_to_s5_operand" "I")))]
&gt; +  "TARGET_ZCMP"
&gt; +  "cm.push	{ra, s0-s5}, %0"
&gt; +)
&gt; +
&gt; +(define_insn "@gpr_multi_push_up_to_s6_<mode>"
&gt; +  [(set (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot0_offset>)))
&gt; +        (reg:X S6_REGNUM))
&gt; +   (set (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot1_offset>)))
&gt; +        (reg:X S5_REGNUM))
&gt; +   (set (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot2_offset>)))
&gt; +        (reg:X S4_REGNUM))
&gt; +   (set (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot3_offset>)))
&gt; +        (reg:X S3_REGNUM))
&gt; +   (set (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot4_offset>)))
&gt; +        (reg:X S2_REGNUM))
&gt; +   (set (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot5_offset>)))
&gt; +        (reg:X S1_REGNUM))
&gt; +   (set (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot6_offset>)))
&gt; +        (reg:X S0_REGNUM))
&gt; +   (set (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot7_offset>)))
&gt; +        (reg:X RETURN_ADDR_REGNUM))
&gt; +   (set (reg:X SP_REGNUM)
&gt; +        (plus:X (reg:X SP_REGNUM)
&gt; +                 (match_operand 0 "stack_push_up_to_s6_operand" "I")))]
&gt; +  "TARGET_ZCMP"
&gt; +  "cm.push	{ra, s0-s6}, %0"
&gt; +)
&gt; +
&gt; +(define_insn "@gpr_multi_push_up_to_s7_<mode>"
&gt; +  [(set (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot0_offset>)))
&gt; +        (reg:X S7_REGNUM))
&gt; +   (set (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot1_offset>)))
&gt; +        (reg:X S6_REGNUM))
&gt; +   (set (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot2_offset>)))
&gt; +        (reg:X S5_REGNUM))
&gt; +   (set (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot3_offset>)))
&gt; +        (reg:X S4_REGNUM))
&gt; +   (set (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot4_offset>)))
&gt; +        (reg:X S3_REGNUM))
&gt; +   (set (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot5_offset>)))
&gt; +        (reg:X S2_REGNUM))
&gt; +   (set (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot6_offset>)))
&gt; +        (reg:X S1_REGNUM))
&gt; +   (set (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot7_offset>)))
&gt; +        (reg:X S0_REGNUM))
&gt; +   (set (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                      (const_int <slot8_offset>)))
&gt; +        (reg:X RETURN_ADDR_REGNUM))
&gt; +   (set (reg:X SP_REGNUM)
&gt; +        (plus:X (reg:X SP_REGNUM)
&gt; +                 (match_operand 0 "stack_push_up_to_s7_operand" "I")))]
&gt; +  "TARGET_ZCMP"
&gt; +  "cm.push	{ra, s0-s7}, %0"
&gt; +)
&gt; +
&gt; +(define_insn "@gpr_multi_push_up_to_s8_<mode>"
&gt; +  [(set (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot0_offset>)))
&gt; +        (reg:X S8_REGNUM))
&gt; +   (set (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot1_offset>)))
&gt; +        (reg:X S7_REGNUM))
&gt; +   (set (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot2_offset>)))
&gt; +        (reg:X S6_REGNUM))
&gt; +   (set (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot3_offset>)))
&gt; +        (reg:X S5_REGNUM))
&gt; +   (set (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot4_offset>)))
&gt; +        (reg:X S4_REGNUM))
&gt; +   (set (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot5_offset>)))
&gt; +        (reg:X S3_REGNUM))
&gt; +   (set (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot6_offset>)))
&gt; +        (reg:X S2_REGNUM))
&gt; +   (set (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot7_offset>)))
&gt; +        (reg:X S1_REGNUM))
&gt; +   (set (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot8_offset>)))
&gt; +        (reg:X S0_REGNUM))
&gt; +   (set (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot9_offset>)))
&gt; +        (reg:X RETURN_ADDR_REGNUM))
&gt; +   (set (reg:X SP_REGNUM)
&gt; +        (plus:X (reg:X SP_REGNUM)
&gt; +                 (match_operand 0 "stack_push_up_to_s8_operand" "I")))]
&gt; +  "TARGET_ZCMP"
&gt; +  "cm.push	{ra, s0-s8}, %0"
&gt; +)
&gt; +
&gt; +(define_insn "@gpr_multi_push_up_to_s9_<mode>"
&gt; +  [(set (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot0_offset>)))
&gt; +        (reg:X S9_REGNUM))
&gt; +   (set (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot1_offset>)))
&gt; +        (reg:X S8_REGNUM))
&gt; +   (set (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot2_offset>)))
&gt; +        (reg:X S7_REGNUM))
&gt; +   (set (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot3_offset>)))
&gt; +        (reg:X S6_REGNUM))
&gt; +   (set (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot4_offset>)))
&gt; +        (reg:X S5_REGNUM))
&gt; +   (set (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot5_offset>)))
&gt; +        (reg:X S4_REGNUM))
&gt; +   (set (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot6_offset>)))
&gt; +        (reg:X S3_REGNUM))
&gt; +   (set (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot7_offset>)))
&gt; +        (reg:X S2_REGNUM))
&gt; +   (set (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot8_offset>)))
&gt; +        (reg:X S1_REGNUM))
&gt; +   (set (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot9_offset>)))
&gt; +        (reg:X S0_REGNUM))
&gt; +   (set (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot10_offset>)))
&gt; +        (reg:X RETURN_ADDR_REGNUM))
&gt; +   (set (reg:X SP_REGNUM)
&gt; +        (plus:X (reg:X SP_REGNUM)
&gt; +                 (match_operand 0 "stack_push_up_to_s9_operand" "I")))]
&gt; +  "TARGET_ZCMP"
&gt; +  "cm.push	{ra, s0-s9}, %0"
&gt; +)
&gt; +
&gt; +(define_insn "@gpr_multi_push_up_to_s11_<mode>"
&gt; +  [(set (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot0_offset>)))
&gt; +        (reg:X S11_REGNUM))
&gt; +   (set (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot1_offset>)))
&gt; +        (reg:X S10_REGNUM))
&gt; +   (set (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot2_offset>)))
&gt; +        (reg:X S9_REGNUM))
&gt; +   (set (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot3_offset>)))
&gt; +        (reg:X S8_REGNUM))
&gt; +   (set (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot4_offset>)))
&gt; +        (reg:X S7_REGNUM))
&gt; +   (set (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot5_offset>)))
&gt; +        (reg:X S6_REGNUM))
&gt; +   (set (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot6_offset>)))
&gt; +        (reg:X S5_REGNUM))
&gt; +   (set (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot7_offset>)))
&gt; +        (reg:X S4_REGNUM))
&gt; +   (set (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot8_offset>)))
&gt; +        (reg:X S3_REGNUM))
&gt; +   (set (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot9_offset>)))
&gt; +        (reg:X S2_REGNUM))
&gt; +   (set (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot10_offset>)))
&gt; +        (reg:X S1_REGNUM))
&gt; +   (set (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot11_offset>)))
&gt; +        (reg:X S0_REGNUM))
&gt; +   (set (mem:X (plus:X (reg:X SP_REGNUM)
&gt; +                       (const_int <slot12_offset>)))
&gt; +        (reg:X RETURN_ADDR_REGNUM))
&gt; +   (set (reg:X SP_REGNUM)
&gt; +        (plus:X (reg:X SP_REGNUM)
&gt; +                 (match_operand 0 "stack_push_up_to_s11_operand" "I")))]
&gt; +  "TARGET_ZCMP"
&gt; +  "cm.push	{ra, s0-s11}, %0"
&gt; +)
&gt; diff --git a/gcc/testsuite/gcc.target/riscv/rv32e_zcmp.c b/gcc/testsuite/gcc.target/riscv/rv32e_zcmp.c
&gt; new file mode 100644
&gt; index 00000000000..6dbe489da9b
&gt; --- /dev/null
&gt; +++ b/gcc/testsuite/gcc.target/riscv/rv32e_zcmp.c
&gt; @@ -0,0 +1,239 @@
&gt; +/* { dg-do compile } */
&gt; +/* { dg-options " -Os -march=rv32e_zca_zcmp -mabi=ilp32e -mcmodel=medlow" } */
&gt; +/* { dg-skip-if "" { *-*-* } {"-O0" "-O1" "-O2" "-Og" "-O3" "-Oz" "-flto"} } */
&gt; +/* { dg-final { check-function-bodies "**" "" } } */
&gt; +
&gt; +char my_getchar();
&gt; +float getf();
&gt; +int __attribute__((noinline)) incoming_stack_args
&gt; +  (int arg0, int arg1, int arg2, int arg3,
&gt; +   int arg4, int arg5, int arg6, int arg7, int arg8);
&gt; +int getint();
&gt; +void PrintInts (int n, ...); // varargs
&gt; +void __attribute__((noinline)) PrintIntsNoVaStart (int n, ...); // varargs
&gt; +void PrintInts2 (int arg0, int arg1, int arg2, int arg3, int arg4, int arg5, int n, ...);
&gt; +extern void f1(void);
&gt; +extern void f2(void);
&gt; +
&gt; +/*
&gt; +**test1:
&gt; +**	...
&gt; +**	cm.push	{ra, s0-s1}, -64
&gt; +**	...
&gt; +**	cm.popret	{ra, s0-s1}, 64
&gt; +**	...
&gt; +*/
&gt; +int test1()
&gt; +{
&gt; +  char volatile array[3120];
&gt; +  float volatile farray[3120];
&gt; +
&gt; +  float sum = 0;
&gt; +  for (int i = 0; i &lt; 3120; i++)
&gt; +  {
&gt; +    array[i] = my_getchar();
&gt; +    farray[i] = my_getchar() * 1.2;
&gt; +    sum += array[i] + farray[i];
&gt; +  }
&gt; +  return sum;
&gt; +}
&gt; +
&gt; +/*
&gt; +**test2_step1_0_size:
&gt; +**	...
&gt; +**	cm.push	{ra, s0}, -64
&gt; +**	...
&gt; +**	cm.popret	{ra, s0}, 64
&gt; +**	...
&gt; +*/
&gt; +int test2_step1_0_size()
&gt; +{
&gt; +  int volatile iarray[3120 + 1824/4 -8];
&gt; +
&gt; +  for (int i = 0; i &lt; 3120 + 1824/4 - 8; i++)
&gt; +  {
&gt; +    iarray[i] = my_getchar() * 2;
&gt; +  }
&gt; +  return iarray[0] + iarray[1];
&gt; +}
&gt; +
&gt; +/*
&gt; +**test3:
&gt; +**	...
&gt; +**	cm.push	{ra, s0-s1}, -64
&gt; +**	...
&gt; +**	cm.popret	{ra, s0-s1}, 64
&gt; +**	...
&gt; +*/
&gt; +float test3()
&gt; +{
&gt; +  char volatile array[3120];
&gt; +  float volatile farray[3120];
&gt; +
&gt; +  float sum = 0, f1 = 0, f2 = 0, f3 = 0, f4 = 0, f5 = 0, f6 = 0, f7 = 0;
&gt; +
&gt; +  for (int i = 0; i &lt; 3120; i++)
&gt; +  {
&gt; +    f1 = getf();
&gt; +    f2 = getf();
&gt; +    f3 = getf();
&gt; +    f4 = getf();
&gt; +    array[i] = my_getchar();
&gt; +    farray[i] = my_getchar() * 1.2;
&gt; +    sum += array[i] + farray[i] + f1 + f2 + f3 + f4;
&gt; +  }
&gt; +  return sum;
&gt; +}
&gt; +
&gt; +/*
&gt; +**outgoing_stack_args:
&gt; +**	...
&gt; +**	cm.push	{ra, s0}, -32
&gt; +**	...
&gt; +**	cm.popret	{ra, s0}, 32
&gt; +**	...
&gt; +*/
&gt; +int outgoing_stack_args()
&gt; +{
&gt; +  int  local = getint();
&gt; +  return local +incoming_stack_args(0, 1, 2, 3, 4, 5, 6, 7, 8);
&gt; +}
&gt; +
&gt; +/*
&gt; +**callPrintInts:
&gt; +**	...
&gt; +**	cm.push	{ra}, -32
&gt; +**	...
&gt; +**	cm.popret	{ra}, 32
&gt; +**	...
&gt; +*/
&gt; +float callPrintInts()
&gt; +{
&gt; +  volatile float f = getf(); // f in local
&gt; +  PrintInts(9,1,2,3,4,5,6,7,8,9);
&gt; +  return f;
&gt; +}
&gt; +
&gt; +/*
&gt; +**callPrint:
&gt; +**	...
&gt; +**	cm.push	{ra}, -32
&gt; +**	...
&gt; +**	cm.popret	{ra}, 32
&gt; +**	...
&gt; +*/
&gt; +float callPrint()
&gt; +{
&gt; +  volatile float f = getf(); // f in local
&gt; +  PrintIntsNoVaStart(0,1,2,3,4,5,6,7,8,9);
&gt; +  return f;
&gt; +}
&gt; +
&gt; +/*
&gt; +**callPrint_S:
&gt; +**	...
&gt; +**	cm.push	{ra, s0}, -32
&gt; +**	...
&gt; +**	cm.popret	{ra, s0}, 32
&gt; +**	...
&gt; +*/
&gt; +float callPrint_S()
&gt; +{
&gt; +  float f = getf();
&gt; +  PrintIntsNoVaStart(0,1,2,3,4,5,6,7,8,9);
&gt; +  return f;
&gt; +}
&gt; +
&gt; +/*
&gt; +**callPrint_2:
&gt; +**	...
&gt; +**	cm.push	{ra, s0}, -32
&gt; +**	...
&gt; +**	cm.popret	{ra, s0}, 32
&gt; +**	...
&gt; +*/
&gt; +float callPrint_2()
&gt; +{
&gt; +  float f = getf();
&gt; +  PrintInts2(0,1,2,3,4,5,6,7,8,9);
&gt; +  return f;
&gt; +}
&gt; +
&gt; +/*
&gt; +**test_step1_0bytes_save_restore:
&gt; +**	...
&gt; +**	cm.push	{ra}, -16
&gt; +**	...
&gt; +**	cm.popret	{ra}, 16
&gt; +**	...
&gt; +*/
&gt; +int test_step1_0bytes_save_restore()
&gt; +{
&gt; +
&gt; +  int a  =  9;
&gt; +  int b  =  my_getchar();
&gt; +  return a +b;
&gt; +}
&gt; +
&gt; +/*
&gt; +**test_s0:
&gt; +**	...
&gt; +**	cm.push	{ra, s0}, -16
&gt; +**	...
&gt; +**	cm.popret	{ra, s0}, 16
&gt; +**	...
&gt; +*/
&gt; +int test_s0()
&gt; +{
&gt; +
&gt; +  int a  =  my_getchar();
&gt; +  int b  =  my_getchar();
&gt; +  return a +b;
&gt; +}
&gt; +
&gt; +/*
&gt; +**test_s1:
&gt; +**	...
&gt; +**	cm.push	{ra, s0-s1}, -16
&gt; +**	...
&gt; +**	cm.popret	{ra, s0-s1}, 16
&gt; +**	...
&gt; +*/
&gt; +int test_s1()
&gt; +{
&gt; +
&gt; +  int s0  =  my_getchar();
&gt; +  int s1  =  my_getchar();
&gt; +  int b  =  my_getchar();
&gt; +  return s1 +s0 +b;
&gt; +}
&gt; +
&gt; +/*
&gt; +**test_f0:
&gt; +**	...
&gt; +**	cm.push	{ra, s0-s1}, -16
&gt; +**	...
&gt; +**	cm.popret	{ra, s0-s1}, 16
&gt; +**	...
&gt; +*/
&gt; +int test_f0()
&gt; +{
&gt; +
&gt; +  int s0  =  my_getchar();
&gt; +  float f0  =  getf(); 
&gt; +  int b  =  my_getchar();
&gt; +  return f0 +s0 +b;
&gt; +}
&gt; +
&gt; +/*
&gt; +**foo:
&gt; +**	cm.push	{ra}, -16
&gt; +**	call	f1
&gt; +**	cm.pop	{ra}, 16
&gt; +**	tail	f2
&gt; +*/
&gt; +void foo(void)
&gt; +{
&gt; +  f1();
&gt; +  f2();
&gt; +}
&gt; diff --git a/gcc/testsuite/gcc.target/riscv/rv32i_zcmp.c b/gcc/testsuite/gcc.target/riscv/rv32i_zcmp.c
&gt; new file mode 100644
&gt; index 00000000000..924197cb3c4
&gt; --- /dev/null
&gt; +++ b/gcc/testsuite/gcc.target/riscv/rv32i_zcmp.c
&gt; @@ -0,0 +1,239 @@
&gt; +/* { dg-do compile } */
&gt; +/* { dg-options " -Os -march=rv32imaf_zca_zcmp -mabi=ilp32f -mcmodel=medlow" } */
&gt; +/* { dg-skip-if "" { *-*-* } {"-O0" "-O1" "-O2" "-Og" "-O3" "-Oz" "-flto"} } */
&gt; +/* { dg-final { check-function-bodies "**" "" } } */
&gt; +
&gt; +char my_getchar();
&gt; +float getf();
&gt; +int __attribute__((noinline)) incoming_stack_args
&gt; +  (int arg0, int arg1, int arg2, int arg3,
&gt; +   int arg4, int arg5, int arg6, int arg7, int arg8);
&gt; +int getint();
&gt; +void PrintInts (int n, ...); // varargs
&gt; +void __attribute__((noinline)) PrintIntsNoVaStart (int n, ...); // varargs
&gt; +void PrintInts2 (int arg0, int arg1, int arg2, int arg3, int arg4, int arg5, int n, ...);
&gt; +extern void f1(void);
&gt; +extern void f2(void);
&gt; +
&gt; +/*
&gt; +**test1:
&gt; +**	...
&gt; +**	cm.push	{ra, s0-s4}, -80
&gt; +**	...
&gt; +**	cm.popret	{ra, s0-s4}, 80
&gt; +**	...
&gt; +*/
&gt; +int test1()
&gt; +{
&gt; +  char volatile array[3120];
&gt; +  float volatile farray[3120];
&gt; +
&gt; +  float sum = 0;
&gt; +  for (int i = 0; i &lt; 3120; i++)
&gt; +  {
&gt; +    array[i] = my_getchar();
&gt; +    farray[i] = my_getchar() * 1.2;
&gt; +    sum += array[i] + farray[i];
&gt; +  }
&gt; +  return sum;
&gt; +}
&gt; +
&gt; +/*
&gt; +**test2_step1_0_size:
&gt; +**	...
&gt; +**	cm.push	{ra, s0-s1}, -64
&gt; +**	...
&gt; +**	cm.popret	{ra, s0-s1}, 64
&gt; +**	...
&gt; +*/
&gt; +int test2_step1_0_size()
&gt; +{
&gt; +  int volatile iarray[3120 + 1824/4 -8];
&gt; +
&gt; +  for (int i = 0; i &lt; 3120 + 1824/4 - 8; i++)
&gt; +  {
&gt; +    iarray[i] = my_getchar() * 2;
&gt; +  }
&gt; +  return iarray[0] + iarray[1];
&gt; +}
&gt; +
&gt; +/*
&gt; +**test3:
&gt; +**	...
&gt; +**	cm.push	{ra, s0-s4}, -80
&gt; +**	...
&gt; +**	cm.popret	{ra, s0-s4}, 80
&gt; +**	...
&gt; +*/
&gt; +float test3()
&gt; +{
&gt; +  char volatile array[3120];
&gt; +  float volatile farray[3120];
&gt; +
&gt; +  float sum = 0, f1 = 0, f2 = 0, f3 = 0, f4 = 0, f5 = 0, f6 = 0, f7 = 0;
&gt; +
&gt; +  for (int i = 0; i &lt; 3120; i++)
&gt; +  {
&gt; +    f1 = getf();
&gt; +    f2 = getf();
&gt; +    f3 = getf();
&gt; +    f4 = getf();
&gt; +    array[i] = my_getchar();
&gt; +    farray[i] = my_getchar() * 1.2;
&gt; +    sum += array[i] + farray[i] + f1 + f2 + f3 + f4;
&gt; +  }
&gt; +  return sum;
&gt; +}
&gt; +
&gt; +/*
&gt; +**outgoing_stack_args:
&gt; +**	...
&gt; +**	cm.push	{ra, s0}, -32
&gt; +**	...
&gt; +**	cm.popret	{ra, s0}, 32
&gt; +**	...
&gt; +*/
&gt; +int outgoing_stack_args()
&gt; +{
&gt; +  int  local = getint();
&gt; +  return local +incoming_stack_args(0, 1, 2, 3, 4, 5, 6, 7, 8);
&gt; +}
&gt; +
&gt; +/*
&gt; +**callPrintInts:
&gt; +**	...
&gt; +**	cm.push	{ra}, -48
&gt; +**	...
&gt; +**	cm.popret	{ra}, 48
&gt; +**	...
&gt; +*/
&gt; +float callPrintInts()
&gt; +{
&gt; +  volatile float f = getf(); // f in local
&gt; +  PrintInts(9,1,2,3,4,5,6,7,8,9);
&gt; +  return f;
&gt; +}
&gt; +
&gt; +/*
&gt; +**callPrint:
&gt; +**	...
&gt; +**	cm.push	{ra}, -48
&gt; +**	...
&gt; +**	cm.popret	{ra}, 48
&gt; +**	...
&gt; +*/
&gt; +float callPrint()
&gt; +{
&gt; +  volatile float f = getf(); // f in local
&gt; +  PrintIntsNoVaStart(0,1,2,3,4,5,6,7,8,9);
&gt; +  return f;
&gt; +}
&gt; +
&gt; +/*
&gt; +**callPrint_S:
&gt; +**	...
&gt; +**	cm.push	{ra}, -48
&gt; +**	...
&gt; +**	cm.popret	{ra}, 48
&gt; +**	...
&gt; +*/
&gt; +float callPrint_S()
&gt; +{
&gt; +  float f = getf();
&gt; +  PrintIntsNoVaStart(0,1,2,3,4,5,6,7,8,9);
&gt; +  return f;
&gt; +}
&gt; +
&gt; +/*
&gt; +**callPrint_2:
&gt; +**	...
&gt; +**	cm.push	{ra}, -48
&gt; +**	...
&gt; +**	cm.popret	{ra}, 48
&gt; +**	...
&gt; +*/
&gt; +float callPrint_2()
&gt; +{
&gt; +  float f = getf();
&gt; +  PrintInts2(0,1,2,3,4,5,6,7,8,9);
&gt; +  return f;
&gt; +}
&gt; +
&gt; +/*
&gt; +**test_step1_0bytes_save_restore:
&gt; +**	...
&gt; +**	cm.push	{ra}, -16
&gt; +**	...
&gt; +**	cm.popret	{ra}, 16
&gt; +**	...
&gt; +*/
&gt; +int test_step1_0bytes_save_restore()
&gt; +{
&gt; +
&gt; +  int a  =  9;
&gt; +  int b  =  my_getchar();
&gt; +  return a +b;
&gt; +}
&gt; +
&gt; +/*
&gt; +**test_s0:
&gt; +**	...
&gt; +**	cm.push	{ra, s0}, -16
&gt; +**	...
&gt; +**	cm.popret	{ra, s0}, 16
&gt; +**	...
&gt; +*/
&gt; +int test_s0()
&gt; +{
&gt; +
&gt; +  int a  =  my_getchar();
&gt; +  int b  =  my_getchar();
&gt; +  return a +b;
&gt; +}
&gt; +
&gt; +/*
&gt; +**test_s1:
&gt; +**	...
&gt; +**	cm.push	{ra, s0-s1}, -16
&gt; +**	...
&gt; +**	cm.popret	{ra, s0-s1}, 16
&gt; +**	...
&gt; +*/
&gt; +int test_s1()
&gt; +{
&gt; +
&gt; +  int s0  =  my_getchar();
&gt; +  int s1  =  my_getchar();
&gt; +  int b  =  my_getchar();
&gt; +  return s1 +s0 +b;
&gt; +}
&gt; +
&gt; +/*
&gt; +**test_f0:
&gt; +**	...
&gt; +**	cm.push	{ra, s0}, -32
&gt; +**	...
&gt; +**	cm.popret	{ra, s0}, 32
&gt; +**	...
&gt; +*/
&gt; +int test_f0()
&gt; +{
&gt; +
&gt; +  int s0  =  my_getchar();
&gt; +  float f0  =  getf(); 
&gt; +  int b  =  my_getchar();
&gt; +  return f0 +s0 +b;
&gt; +}
&gt; +
&gt; +/*
&gt; +**foo:
&gt; +**	cm.push	{ra}, -16
&gt; +**	call	f1
&gt; +**	cm.pop	{ra}, 16
&gt; +**	tail	f2
&gt; +*/
&gt; +void foo(void)
&gt; +{
&gt; +  f1();
&gt; +  f2();
&gt; +}
&gt; diff --git a/gcc/testsuite/gcc.target/riscv/zcmp_stack_alignment.c b/gcc/testsuite/gcc.target/riscv/zcmp_stack_alignment.c
&gt; new file mode 100644
&gt; index 00000000000..05602302a8f
&gt; --- /dev/null
&gt; +++ b/gcc/testsuite/gcc.target/riscv/zcmp_stack_alignment.c
&gt; @@ -0,0 +1,23 @@
&gt; +/* { dg-do compile } */
&gt; +/* { dg-options " -O0 -march=rv32e_zca_zcb_zcmp -mabi=ilp32e -mcmodel=medlow -fomit-frame-pointer" } */
&gt; +/* { dg-skip-if "" { *-*-* } {"-O2" "-O1" "-Os" "-Og" "-O3" "-Oz" "-flto"} } */
&gt; +/* { dg-final { check-function-bodies "**" "" } } */
&gt; +
&gt; +void bar();
&gt; +
&gt; +/*
&gt; +**fool_rv32e:
&gt; +**	cm.push	{ra}, -32
&gt; +**	...
&gt; +**	call	bar
&gt; +**	...
&gt; +**	lw	a5,32\(sp\)
&gt; +**	...
&gt; +**	cm.popret	{ra}, 32
&gt; +*/
&gt; +int fool_rv32e ( int a0, int a1, int a2, int a3, int a4, int a5,
&gt; +                  int incoming0)
&gt; +{
&gt; +  bar();
&gt; +  return a0 + a1 + a2 + a3 + a4 + a5 + incoming0;
&gt; +}
&gt; -- 
&gt; 2.17.1
</slot12_offset></slot11_offset></slot10_offset></slot9_offset></slot8_offset></slot7_offset></slot6_offset></slot5_offset></slot4_offset></slot3_offset></slot2_offset></slot1_offset></slot0_offset></mode></slot10_offset></slot9_offset></slot8_offset></slot7_offset></slot6_offset></slot5_offset></slot4_offset></slot3_offset></slot2_offset></slot1_offset></slot0_offset></mode></slot9_offset></slot8_offset></slot7_offset></slot6_offset></slot5_offset></slot4_offset></slot3_offset></slot2_offset></slot1_offset></slot0_offset></mode></slot8_offset></slot7_offset></slot6_offset></slot5_offset></slot4_offset></slot3_offset></slot2_offset></slot1_offset></slot0_offset></mode></slot7_offset></slot6_offset></slot5_offset></slot4_offset></slot3_offset></slot2_offset></slot1_offset></slot0_offset></mode></slot6_offset></slot5_offset></slot4_offset></slot3_offset></slot2_offset></slot1_offset></slot0_offset></mode></slot5_offset></slot4_offset></slot3_offset></slot2_offset></slot1_offset></slot0_offset></mode></slot4_offset></slot3_offset></slot2_offset></slot1_offset></slot0_offset></mode></slot3_offset></slot2_offset></slot1_offset></slot0_offset></mode></slot2_offset></slot1_offset></slot0_offset></mode></slot1_offset></slot0_offset></mode></slot0_offset></mode></slot12_offset></slot11_offset></slot10_offset></slot9_offset></slot8_offset></slot7_offset></slot6_offset></slot5_offset></slot4_offset></slot3_offset></slot2_offset></slot1_offset></slot0_offset></mode></slot10_offset></slot9_offset></slot8_offset></slot7_offset></slot6_offset></slot5_offset></slot4_offset></slot3_offset></slot2_offset></slot1_offset></slot0_offset></mode></slot9_offset></slot8_offset></slot7_offset></slot6_offset></slot5_offset></slot4_offset></slot3_offset></slot2_offset></slot1_offset></slot0_offset></mode></slot8_offset></slot7_offset></slot6_offset></slot5_offset></slot4_offset></slot3_offset></slot2_offset></slot1_offset></slot0_offset></mode></slot7_offset></slot6_offset></slot5_offset></slot4_offset></slot3_offset></slot2_offset></slot1_offset></slot0_offset></mode></slot6_offset></slot5_offset></slot4_offset></slot3_offset></slot2_offset></slot1_offset></slot0_offset></mode></slot5_offset></slot4_offset></slot3_offset></slot2_offset></slot1_offset></slot0_offset></mode></slot4_offset></slot3_offset></slot2_offset></slot1_offset></slot0_offset></mode></slot3_offset></slot2_offset></slot1_offset></slot0_offset></mode></slot2_offset></slot1_offset></slot0_offset></mode></slot1_offset></slot0_offset></mode></slot0_offset></mode></slot12_offset></slot11_offset></slot10_offset></slot9_offset></slot8_offset></slot7_offset></slot6_offset></slot5_offset></slot4_offset></slot3_offset></slot2_offset></slot1_offset></slot0_offset></mode></slot10_offset></slot9_offset></slot8_offset></slot7_offset></slot6_offset></slot5_offset></slot4_offset></slot3_offset></slot2_offset></slot1_offset></slot0_offset></mode></slot9_offset></slot8_offset></slot7_offset></slot6_offset></slot5_offset></slot4_offset></slot3_offset></slot2_offset></slot1_offset></slot0_offset></mode></slot8_offset></slot7_offset></slot6_offset></slot5_offset></slot4_offset></slot3_offset></slot2_offset></slot1_offset></slot0_offset></mode></slot7_offset></slot6_offset></slot5_offset></slot4_offset></slot3_offset></slot2_offset></slot1_offset></slot0_offset></mode></slot6_offset></slot5_offset></slot4_offset></slot3_offset></slot2_offset></slot1_offset></slot0_offset></mode></slot5_offset></slot4_offset></slot3_offset></slot2_offset></slot1_offset></slot0_offset></mode></slot4_offset></slot3_offset></slot2_offset></slot1_offset></slot0_offset></mode></slot3_offset></slot2_offset></slot1_offset></slot0_offset></mode></slot2_offset></slot1_offset></slot0_offset></mode></slot1_offset></slot0_offset></mode></slot0_offset></mode></gaofei@eswincomputing.com></gaofei@eswincomputing.com></gaofei@eswincomputing.com>

  reply	other threads:[~2023-06-07 10:12 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-06-07  5:52 [PATCH 0/4] [RISC-V] support zcmp extention Fei Gao
2023-06-07  5:52 ` [PATCH 1/4][V4][RISC-V] support cm.push cm.pop cm.popret in zcmp Fei Gao
2023-06-07 10:11   ` jiawei [this message]
2023-08-16  8:33   ` Kito Cheng
2023-08-16  8:38     ` Kito Cheng
2023-08-16  9:03       ` Fei Gao
2023-08-20 10:53       ` Fei Gao
2023-08-28  8:04         ` Fei Gao
2023-08-17 11:39     ` Fei Gao
2023-06-07  5:52 ` [PATCH 2/4] [RISC-V] support cm.popretz " Fei Gao
2023-07-13  8:31   ` Kito Cheng
2023-06-07  5:52 ` [PATCH 3/4] [RISC-V] resolve confilct between zcmp multi push/pop and shrink-wrap-separate Fei Gao
2023-06-12 15:17   ` Kito Cheng
2023-06-12 19:26   ` Jeff Law
2023-06-13  2:35     ` Fei Gao
2023-06-07  5:52 ` [PATCH 4/4] [RISC-V] support cm.mva01s cm.mvsa01 in zcmp Fei Gao
2023-07-13  8:18   ` Kito Cheng

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=62269c00.b0e9.18895577568.Coremail.jiawei@iscas.ac.cn \
    --to=jiawei@iscas.ac.cn \
    --cc=gaofei@eswincomputing.com \
    --cc=gcc-patches@gcc.gnu.org \
    --cc=jeffreyalaw@gmail.com \
    --cc=kito.cheng@gmail.com \
    --cc=palmer@dabbelt.com \
    --cc=sinan.lin@linux.alibaba.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).