diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc index 09a30dc260fcf404e7033331a55a2abbd781a23d..4c3cf7167a2ae26892a959563807d9701ce52acd 100644 --- a/gcc/config/riscv/riscv.cc +++ b/gcc/config/riscv/riscv.cc @@ -4780,12 +4780,27 @@ riscv_save_reg_p (unsigned int regno) return false; } +/* Return TRUE if a libcall to save/restore GPRs should be + avoided. FALSE otherwise. */ +static bool +riscv_avoid_save_libcall (void) +{ + if (!TARGET_SAVE_RESTORE + || crtl->calls_eh_return + || frame_pointer_needed + || cfun->machine->interrupt_handler_p + || cfun->machine->varargs_size != 0 + || crtl->args.pretend_args_size != 0) + return true; + + return false; +} + /* Determine whether to call GPR save/restore routines. */ static bool riscv_use_save_libcall (const struct riscv_frame_info *frame) { - if (!TARGET_SAVE_RESTORE || crtl->calls_eh_return || frame_pointer_needed - || cfun->machine->interrupt_handler_p) + if (riscv_avoid_save_libcall ()) return false; return frame->save_libcall_adjustment != 0; @@ -4865,7 +4880,7 @@ riscv_compute_frame_info (void) struct riscv_frame_info *frame; poly_int64 offset; bool interrupt_save_prologue_temp = false; - unsigned int regno, i, num_x_saved = 0, num_f_saved = 0; + unsigned int regno, i, num_x_saved = 0, num_f_saved = 0, x_save_size = 0; frame = &cfun->machine->frame; @@ -4903,24 +4918,14 @@ riscv_compute_frame_info (void) frame->fmask |= 1 << (regno - FP_REG_FIRST), num_f_saved++; } - /* At the bottom of the frame are any outgoing stack arguments. */ - offset = riscv_stack_align (crtl->outgoing_args_size); - /* Next are local stack variables. */ - offset += riscv_stack_align (get_frame_size ()); - /* The virtual frame pointer points above the local variables. */ - frame->frame_pointer_offset = offset; - /* Next are the callee-saved FPRs. */ - if (frame->fmask) - offset += riscv_stack_align (num_f_saved * UNITS_PER_FP_REG); - frame->fp_sp_offset = offset - UNITS_PER_FP_REG; - /* Next are the callee-saved GPRs. */ if (frame->mask) { - unsigned x_save_size = riscv_stack_align (num_x_saved * UNITS_PER_WORD); + x_save_size = riscv_stack_align (num_x_saved * UNITS_PER_WORD); unsigned num_save_restore = 1 + riscv_save_libcall_count (frame->mask); /* Only use save/restore routines if they don't alter the stack size. */ - if (riscv_stack_align (num_save_restore * UNITS_PER_WORD) == x_save_size) + if (riscv_stack_align (num_save_restore * UNITS_PER_WORD) == x_save_size + && !riscv_avoid_save_libcall ()) { /* Libcall saves/restores 3 registers at once, so we need to allocate 12 bytes for callee-saved register. */ @@ -4929,9 +4934,21 @@ riscv_compute_frame_info (void) frame->save_libcall_adjustment = x_save_size; } - - offset += x_save_size; } + + /* At the bottom of the frame are any outgoing stack arguments. */ + offset = riscv_stack_align (crtl->outgoing_args_size); + /* Next are local stack variables. */ + offset += riscv_stack_align (get_frame_size ()); + /* The virtual frame pointer points above the local variables. */ + frame->frame_pointer_offset = offset; + /* Next are the callee-saved FPRs. */ + if (frame->fmask) + offset += riscv_stack_align (num_f_saved * UNITS_PER_FP_REG); + frame->fp_sp_offset = offset - UNITS_PER_FP_REG; + /* Next are the callee-saved GPRs. */ + if (frame->mask) + offset += x_save_size; frame->gp_sp_offset = offset - UNITS_PER_WORD; /* The hard frame pointer points above the callee-saved GPRs. */ frame->hard_frame_pointer_offset = offset; @@ -4943,11 +4960,8 @@ riscv_compute_frame_info (void) padding. */ frame->arg_pointer_offset = offset - crtl->args.pretend_args_size; frame->total_size = offset; - /* Next points the incoming stack pointer and any incoming arguments. */ - /* Only use save/restore routines when the GPRs are atop the frame. */ - if (known_ne (frame->hard_frame_pointer_offset, frame->total_size)) - frame->save_libcall_adjustment = 0; + /* Next points the incoming stack pointer and any incoming arguments. */ } /* Make sure that we're not trying to eliminate to the wrong hard frame diff --git a/gcc/testsuite/gcc.target/riscv/rv32e_stack.c b/gcc/testsuite/gcc.target/riscv/rv32e_stack.c new file mode 100644 index 0000000000000000000000000000000000000000..cec90ede4b52fca7c240197abf01e945c3a98180 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rv32e_stack.c @@ -0,0 +1,14 @@ +/* { dg-do compile} */ +/* { dg-options "-O0 -march=rv32e -mabi=ilp32e -fomit-frame-pointer" } */ + +int getInt(); +void PrintInts(int); + +int callPrintInts() +{ + int i = getInt(); + PrintInts(i); + return i; +} + +/* { dg-final { scan-assembler-not "addi sp,sp,-16" } } */