OSDN Git Service

* reg-stack.c (change_stack): Improve algorithm used to pop regs
authorsayle <sayle@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 30 Nov 2004 02:34:56 +0000 (02:34 +0000)
committersayle <sayle@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 30 Nov 2004 02:34:56 +0000 (02:34 +0000)
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

gcc/ChangeLog
gcc/reg-stack.c

index e2e6d82..701b7c5 100644 (file)
@@ -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
index d5983bb..11dd849 100644 (file)
@@ -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)
     {