aboutsummaryrefslogtreecommitdiff
path: root/gcc/reg-stack.c
diff options
context:
space:
mode:
authorRoger Sayle <roger@eyesopen.com>2004-11-30 02:34:56 +0000
committerRoger Sayle <roger@eyesopen.com>2004-11-30 02:34:56 +0000
commit7f03421433ea98c87f0f80bd31bbb3c32a776bd7 (patch)
tree47b89458332f6451d363ae2fe1ba25b30d151a12 /gcc/reg-stack.c
parent8c611ca156eea15f64d03f4efa8aabde9497e518 (diff)
* reg-stack.c (change_stack): Improve algorithm used to pop regs
off the stack to maximize ffreep usage and reduce fxch count. git-svn-id: https://gcc.gnu.org/svn/gcc/trunk@91506 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/reg-stack.c')
-rw-r--r--gcc/reg-stack.c64
1 files changed, 60 insertions, 4 deletions
diff --git a/gcc/reg-stack.c b/gcc/reg-stack.c
index d5983bbaf18..11dd8495e88 100644
--- a/gcc/reg-stack.c
+++ b/gcc/reg-stack.c
@@ -2367,10 +2367,66 @@ change_stack (rtx insn, stack old, stack new, enum emit_where where)
/* Pop any registers that are not needed in the new block. */
- for (reg = old->top; reg >= 0; reg--)
- if (! TEST_HARD_REG_BIT (new->reg_set, old->reg[reg]))
- emit_pop_insn (insn, old, FP_MODE_REG (old->reg[reg], DFmode),
- EMIT_BEFORE);
+ /* If the destination block's stack already has a specified layout
+ and contains two or more registers, use a more intelligent algorithm
+ to pop registers that minimizes the number number of fxchs below. */
+ if (new->top > 0)
+ {
+ bool slots[REG_STACK_SIZE];
+ int pops[REG_STACK_SIZE];
+ int next, dest;
+
+ /* First pass to determine the free slots. */
+ for (reg = 0; reg <= new->top; reg++)
+ slots[reg] = TEST_HARD_REG_BIT (new->reg_set, old->reg[reg]);
+
+ /* Second pass to allocate preferred slots. */
+ for (reg = old->top; reg > new->top; reg--)
+ if (TEST_HARD_REG_BIT (new->reg_set, old->reg[reg]))
+ {
+ dest = -1;
+ for (next = 0; next <= new->top; next++)
+ if (!slots[next] && new->reg[next] == old->reg[reg])
+ {
+ slots[next] = true;
+ dest = next;
+ break;
+ }
+ pops[reg] = dest;
+ }
+ else
+ pops[reg] = reg;
+
+ /* Third pass allocates remaining slots and emits pop insns. */
+ next = 0;
+ for (reg = old->top; reg > new->top; reg--)
+ {
+ dest = pops[reg];
+ if (dest == -1)
+ {
+ /* Find next free slot. */
+ while (slots[next])
+ next++;
+ dest = next++;
+ }
+ emit_pop_insn (insn, old, FP_MODE_REG (old->reg[dest], DFmode),
+ EMIT_BEFORE);
+ }
+ }
+ else
+ /* The following loop attempts to maximize the number of times we
+ pop the top of the stack, as this permits the use of the faster
+ ffreep instruction on platforms that support it. */
+ for (reg = 0; reg <= old->top; reg++)
+ if (! TEST_HARD_REG_BIT (new->reg_set, old->reg[reg]))
+ {
+ while (old->top > reg
+ && ! TEST_HARD_REG_BIT (new->reg_set, old->reg[old->top]))
+ emit_pop_insn (insn, old, FP_MODE_REG (old->reg[old->top], DFmode),
+ EMIT_BEFORE);
+ emit_pop_insn (insn, old, FP_MODE_REG (old->reg[reg], DFmode),
+ EMIT_BEFORE);
+ }
if (new->top == -2)
{