diff options
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/reg-stack.c | 64 |
2 files changed, 65 insertions, 4 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index e2e6d82..701b7c5 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2004-11-29 Roger Sayle <roger@eyesopen.com> + + * reg-stack.c (change_stack): Improve algorithm used to pop regs + off the stack to maximize ffreep usage and reduce fxch count. + 2004-11-30 James A. Morrison <phython@gcc.gnu.org> PR middle-end/18596 diff --git a/gcc/reg-stack.c b/gcc/reg-stack.c index d5983bb..11dd849 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) { |