aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorAndrew Waterman <waterman@cs.berkeley.edu>2015-07-05 23:06:06 -0700
committerAndrew Waterman <waterman@cs.berkeley.edu>2015-07-06 23:41:14 -0700
commitb84d3753bf481903e7fa7f2a5f882686da1b7e9d (patch)
tree6720ae9ea404640e4e3b218ef40ac603ec6ae34c /gcc
parentddf8d39d08bfc31b4a95f8cac5c6fc2bf13e41df (diff)
downloadriscv-gnu-toolchain-b84d3753bf481903e7fa7f2a5f882686da1b7e9d.zip
riscv-gnu-toolchain-b84d3753bf481903e7fa7f2a5f882686da1b7e9d.tar.gz
riscv-gnu-toolchain-b84d3753bf481903e7fa7f2a5f882686da1b7e9d.tar.bz2
gcc: only use save/restore routines if they don't increase stack usage
When a function clobbers only s0 and s1, but not ra, we don't want to use the save/restore routines because the stack would grow more than needed.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/gcc/config/riscv/riscv.c70
1 files changed, 37 insertions, 33 deletions
diff --git a/gcc/gcc/config/riscv/riscv.c b/gcc/gcc/config/riscv/riscv.c
index 52bedff..d07814b 100644
--- a/gcc/gcc/config/riscv/riscv.c
+++ b/gcc/gcc/config/riscv/riscv.c
@@ -3066,6 +3066,27 @@ riscv_save_reg_p (unsigned int regno)
|| (regno == RETURN_ADDR_REGNUM && crtl->calls_eh_return);
}
+/* 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)
+ return false;
+
+ return frame->save_libcall_adjustment != 0;
+}
+
+/* Determine which GPR save/restore routine to call. */
+
+static unsigned
+riscv_save_libcall_count (unsigned mask)
+{
+ for (unsigned n = GP_REG_LAST; n > GP_REG_FIRST; n--)
+ if (BITSET_P (mask, n))
+ return CALLEE_SAVED_REG_NUMBER (n) + 1;
+ abort ();
+}
+
/* Populate the current function's riscv_frame_info structure.
RISC-V stack frames grown downward. High addresses are at the top.
@@ -3113,7 +3134,7 @@ riscv_compute_frame_info (void)
{
struct riscv_frame_info *frame;
HOST_WIDE_INT offset;
- unsigned int regno, i;
+ unsigned int regno, i, num_x_saved = 0, num_f_saved = 0;
frame = &cfun->machine->frame;
memset (frame, 0, sizeof (*frame));
@@ -3121,20 +3142,20 @@ riscv_compute_frame_info (void)
/* Find out which GPRs we need to save. */
for (regno = GP_REG_FIRST; regno <= GP_REG_LAST; regno++)
if (riscv_save_reg_p (regno))
- frame->mask |= 1 << (regno - GP_REG_FIRST);
+ frame->mask |= 1 << (regno - GP_REG_FIRST), num_x_saved++;
/* If this function calls eh_return, we must also save and restore the
EH data registers. */
if (crtl->calls_eh_return)
- for (i = 0; EH_RETURN_DATA_REGNO (i) != INVALID_REGNUM; i++)
- frame->mask |= 1 << (EH_RETURN_DATA_REGNO (i) - GP_REG_FIRST);
+ for (i = 0; (regno = EH_RETURN_DATA_REGNO (i)) != INVALID_REGNUM; i++)
+ frame->mask |= 1 << (regno - GP_REG_FIRST), num_x_saved++;
/* Find out which FPRs we need to save. This loop must iterate over
the same space as its companion in riscv_for_each_saved_gpr_and_fpr. */
if (TARGET_HARD_FLOAT)
for (regno = FP_REG_FIRST; regno <= FP_REG_LAST; regno++)
if (riscv_save_reg_p (regno))
- frame->fmask |= 1 << (regno - FP_REG_FIRST);
+ frame->fmask |= 1 << (regno - FP_REG_FIRST), num_f_saved++;
/* At the bottom of the frame are any outgoing stack arguments. */
offset = crtl->outgoing_args_size;
@@ -3145,17 +3166,20 @@ riscv_compute_frame_info (void)
/* Next are the callee-saved FPRs. */
if (frame->fmask)
{
- unsigned num_saved = __builtin_popcount(frame->fmask);
- offset += RISCV_STACK_ALIGN (num_saved * UNITS_PER_FPREG);
+ offset += RISCV_STACK_ALIGN (num_f_saved * UNITS_PER_FPREG);
frame->fp_sp_offset = offset - UNITS_PER_HWFPVALUE;
}
/* Next are the callee-saved GPRs. */
if (frame->mask)
{
- unsigned num_saved = __builtin_popcount(frame->mask);
- frame->save_libcall_adjustment =
- RISCV_STACK_ALIGN (num_saved * UNITS_PER_WORD);
- offset += frame->save_libcall_adjustment;
+ unsigned x_save_size = RISCV_STACK_ALIGN (num_x_saved * UNITS_PER_WORD);
+ unsigned num_save_restore = 1 + riscv_save_libcall_count (frame->mask);
+
+ /* Only use save/restore routines if they don't alter the stack size. */
+ if (RISCV_STACK_ALIGN (num_save_restore * UNITS_PER_WORD) == x_save_size)
+ frame->save_libcall_adjustment = x_save_size;
+
+ offset += x_save_size;
frame->gp_sp_offset = offset - UNITS_PER_WORD;
}
/* The hard frame pointer points above the callee-saved GPRs. */
@@ -3331,17 +3355,6 @@ riscv_save_reg (rtx reg, rtx mem)
riscv_emit_save_slot_move (mem, reg, RISCV_PROLOGUE_TEMP (GET_MODE (reg)));
}
-/* Determine which GPR save/restore routine to call. */
-
-static unsigned
-riscv_save_restore_count (unsigned mask)
-{
- for (unsigned n = GP_REG_LAST; n > GP_REG_FIRST; n--)
- if (BITSET_P (mask, n))
- return CALLEE_SAVED_REG_NUMBER (n) + 1;
- abort ();
-}
-
/* Return the code to invoke the GPR save routine. */
const char *
@@ -3349,7 +3362,7 @@ riscv_output_gpr_save (unsigned mask)
{
static char buf[GP_REG_NUM * 32];
size_t len = 0;
- unsigned n = riscv_save_restore_count (mask), i;
+ unsigned n = riscv_save_libcall_count (mask), i;
unsigned frame_size = RISCV_STACK_ALIGN ((n + 1) * UNITS_PER_WORD);
len += sprintf (buf + len, "call\tt0,__riscv_save_%u", n);
@@ -3370,15 +3383,6 @@ riscv_output_gpr_save (unsigned mask)
return buf;
}
-static bool
-riscv_use_save_libcall (const struct riscv_frame_info *frame)
-{
- if (!TARGET_SAVE_RESTORE || crtl->calls_eh_return || frame_pointer_needed)
- return false;
-
- return frame->save_libcall_adjustment != 0;
-}
-
/* Expand the "prologue" pattern. */
void
@@ -3538,7 +3542,7 @@ riscv_expand_epilogue (bool sibcall_p)
if (use_restore_libcall)
{
- emit_insn (gen_gpr_restore (GEN_INT (riscv_save_restore_count (mask))));
+ emit_insn (gen_gpr_restore (GEN_INT (riscv_save_libcall_count (mask))));
emit_jump_insn (gen_gpr_restore_return (ra));
return;
}