diff options
author | sayle <sayle@138bc75d-0d04-0410-961f-82ee72b054a4> | 2004-11-30 02:34:56 +0000 |
---|---|---|
committer | sayle <sayle@138bc75d-0d04-0410-961f-82ee72b054a4> | 2004-11-30 02:34:56 +0000 |
commit | 7e542714b02f5f021a647159f11eca56386c6421 (patch) | |
tree | 47b89458332f6451d363ae2fe1ba25b30d151a12 /gcc/reg-stack.c | |
parent | 2542b94a0a8791d2f5317a1136fb8ff75cb646df (diff) | |
download | gcc-7e542714b02f5f021a647159f11eca56386c6421.tar.gz |
* 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: svn+ssh://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.c | 64 |
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) { |