diff options
author | Nick Clifton <nickc@redhat.com> | 2015-05-28 07:16:51 +0000 |
---|---|---|
committer | Nick Clifton <nickc@gcc.gnu.org> | 2015-05-28 07:16:51 +0000 |
commit | 55ffa75632e635c049c238db332c20de1b3116c2 (patch) | |
tree | f3a694ae8b01dca33cfbef5748c76cca1667f7fa /gcc/config/rx | |
parent | 1a4b99c172b8a5485d84e24db16ccbd847a4b1b7 (diff) | |
download | gcc-55ffa75632e635c049c238db332c20de1b3116c2.tar.gz |
rx.c (push_regs): New function.
* config/rx/rx.c (push_regs): New function. Extracts code from...
(rx_expand_prologue): ... here. Use push_regs to push even small
spans of registers.
(pop_regs): New function.
(rx_expand_epilogue): Use pop_regs to pop even small spans of
registers.
From-SVN: r223799
Diffstat (limited to 'gcc/config/rx')
-rw-r--r-- | gcc/config/rx/rx.c | 73 |
1 files changed, 52 insertions, 21 deletions
diff --git a/gcc/config/rx/rx.c b/gcc/config/rx/rx.c index fd985f5fc94..4c1c5d161f1 100644 --- a/gcc/config/rx/rx.c +++ b/gcc/config/rx/rx.c @@ -1567,6 +1567,10 @@ rx_get_stack_layout (unsigned int * lowest, has specified --fixed-<reg-name> on the command line and in such circumstances we do not want to touch the fixed registers at all. + Note also that the code in the prologue/epilogue handlers will + automatically merge multiple PUSHes of adjacent registers into a single + PUSHM. + FIXME: Is it worth improving this heuristic ? */ pushed_mask = (-1 << low) & ~(-1 << (high + 1)); unneeded_pushes = (pushed_mask & (~ save_mask)) & pushed_mask; @@ -1716,6 +1720,19 @@ gen_safe_add (rtx dest, rtx src, rtx val, bool is_frame_related) return; } +static void +push_regs (unsigned int high, unsigned int low) +{ + rtx insn; + + if (low == high) + insn = emit_insn (gen_stack_push (gen_rtx_REG (SImode, low))); + else + insn = emit_insn (gen_stack_pushm (GEN_INT (((high - low) + 1) * UNITS_PER_WORD), + gen_rx_store_vector (low, high))); + mark_frame_related (insn); +} + void rx_expand_prologue (void) { @@ -1725,7 +1742,6 @@ rx_expand_prologue (void) unsigned int low; unsigned int high; unsigned int reg; - rtx insn; /* Naked functions use their own, programmer provided prologues. */ if (is_naked_func (NULL_TREE)) @@ -1735,7 +1751,7 @@ rx_expand_prologue (void) if (flag_stack_usage_info) current_function_static_stack_size = frame_size + stack_size; - + /* If we use any of the callee-saved registers, save them now. */ if (mask) { @@ -1743,20 +1759,25 @@ rx_expand_prologue (void) for (reg = CC_REGNUM; reg --;) if (mask & (1 << reg)) { - insn = emit_insn (gen_stack_push (gen_rtx_REG (SImode, reg))); - mark_frame_related (insn); + low = high = reg; + + /* Look for a span of registers. + Note - we do not have to worry about -Os and whether + it is better to use a single, longer PUSHM as + rx_get_stack_layout has already done that for us. */ + while (reg-- > 0) + if ((mask & (1 << reg)) == 0) + break; + else + --low; + + push_regs (high, low); + if (reg == (unsigned) -1) + break; } } else if (low) - { - if (high == low) - insn = emit_insn (gen_stack_push (gen_rtx_REG (SImode, low))); - else - insn = emit_insn (gen_stack_pushm (GEN_INT (((high - low) + 1) - * UNITS_PER_WORD), - gen_rx_store_vector (low, high))); - mark_frame_related (insn); - } + push_regs (high, low); if (MUST_SAVE_ACC_REGISTER) { @@ -2031,6 +2052,16 @@ rx_can_use_simple_return (void) && low == 0); } +static void +pop_regs (unsigned int high, unsigned int low) +{ + if (high == low) + emit_insn (gen_stack_pop (gen_rtx_REG (SImode, low))); + else + emit_insn (gen_stack_popm (GEN_INT (((high - low) + 1) * UNITS_PER_WORD), + gen_rx_popm_vector (low, high))); +} + void rx_expand_epilogue (bool is_sibcall) { @@ -2143,16 +2174,16 @@ rx_expand_epilogue (bool is_sibcall) { for (reg = 0; reg < CC_REGNUM; reg ++) if (register_mask & (1 << reg)) - emit_insn (gen_stack_pop (gen_rtx_REG (SImode, reg))); + { + low = high = reg; + while (register_mask & (1 << high)) + high ++; + pop_regs (high - 1, low); + reg = high; + } } else if (low) - { - if (high == low) - emit_insn (gen_stack_pop (gen_rtx_REG (SImode, low))); - else - emit_insn (gen_stack_popm (GEN_INT (regs_size), - gen_rx_popm_vector (low, high))); - } + pop_regs (high, low); if (is_fast_interrupt_func (NULL_TREE)) { |