Disable zcmp multi push/pop if shrink-wrap-separate is active. So in -Os that prefers smaller code size, by default shrink-wrap-separate is disabled while zcmp multi push/pop is enabled.
And in -O2 and others that prefers speed, by default shrink-wrap-separate is enabled while zcmp multi push/pop is disabled. To force enabling zcmp multi push/pop in this case, -fno-shrink-wrap-separate has to be explictly given. The following TC shows the issues in -O2 before this patch with both shrink-wrap-separate and zcmp multi push/pop active. 1. duplicated store of s regs. 2. cm.push pushes ra, s0-s11 in reverse order than what normal prologue does, causing stack corruption and failure to resotre s regs. TC: zcmp_shrink_wrap_separate.c included in this patch. output asm before this patch: calc_func: cm.push {ra, s0-s3}, -32 ... beq a5,zero,.L2 ... .L2: ... sw s1,20(sp) //issue here sw s3,12(sp) //issue here ... sw s2,16(sp) //issue here output asm after this patch: calc_func: addi sp,sp,-32 sw s0,24(sp) ... beq a5,zero,.L2 ... .L2: ... sw s1,20(sp) sw s3,12(sp) ... sw s2,16(sp) Signed-off-by: Fei Gao <gao...@eswincomputing.com> Co-Authored-By: Zhangjin Liao <liaozhang...@eswincomputing.com> gcc/ChangeLog: * config/riscv/riscv.cc (riscv_avoid_shrink_wrapping_separate): wrap the condition check in riscv_avoid_shrink_wrapping_separate. (riscv_avoid_multi_push): avoid multi push if shrink_wrapping_separate is active. (riscv_get_separate_components): call riscv_avoid_shrink_wrapping_separate --- gcc/config/riscv/riscv.cc | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc index 26405b5978b..2cca5fbb62d 100644 --- a/gcc/config/riscv/riscv.cc +++ b/gcc/config/riscv/riscv.cc @@ -64,6 +64,7 @@ along with GCC; see the file COPYING3. If not see #include "cfghooks.h" #include "cfgloop.h" #include "cfgrtl.h" +#include "shrink-wrap.h" #include "sel-sched.h" #include "fold-const.h" #include "gimple-iterator.h" @@ -389,6 +390,7 @@ static const struct riscv_tune_param optimize_size_tune_info = { false, /* use_divmod_expansion */ }; +static bool riscv_avoid_shrink_wrapping_separate (); static tree riscv_handle_fndecl_attribute (tree *, tree, tree, int, bool *); static tree riscv_handle_type_attribute (tree *, tree, tree, int, bool *); @@ -5032,6 +5034,8 @@ riscv_avoid_multi_push(const struct riscv_frame_info *frame) || cfun->machine->interrupt_handler_p || cfun->machine->varargs_size != 0 || crtl->args.pretend_args_size != 0 + || (use_shrink_wrapping_separate () + && !riscv_avoid_shrink_wrapping_separate ()) || (frame->mask & ~ MULTI_PUSH_GPR_MASK)) return true; @@ -6199,6 +6203,17 @@ riscv_epilogue_uses (unsigned int regno) return false; } +static bool +riscv_avoid_shrink_wrapping_separate () +{ + if (riscv_use_save_libcall (&cfun->machine->frame) + || cfun->machine->interrupt_handler_p + || !cfun->machine->frame.gp_sp_offset.is_constant ()) + return true; + + return false; +} + /* Implement TARGET_SHRINK_WRAP_GET_SEPARATE_COMPONENTS. */ static sbitmap @@ -6208,9 +6223,7 @@ riscv_get_separate_components (void) sbitmap components = sbitmap_alloc (FIRST_PSEUDO_REGISTER); bitmap_clear (components); - if (riscv_use_save_libcall (&cfun->machine->frame) - || cfun->machine->interrupt_handler_p - || !cfun->machine->frame.gp_sp_offset.is_constant ()) + if (riscv_avoid_shrink_wrapping_separate ()) return components; offset = cfun->machine->frame.gp_sp_offset.to_constant (); -- 2.17.1