reg-stack.c (subst_stack_regs): Pop the stack register for a computed goto which...
authorStan Cox <coxs@dg-rtp.dg.com>
Fri, 5 Sep 1997 05:14:46 +0000 (05:14 +0000)
committerJeff Law <law@gcc.gnu.org>
Fri, 5 Sep 1997 05:14:46 +0000 (23:14 -0600)
        * reg-stack.c (subst_stack_regs): Pop the stack register for a
        computed goto which sets the same stack register.

        * reg-stack.c (compare_for_stack_reg): Swap only if the source and
        destination are both on the regstack.
        (subst_stack_regs_pat): Put the destination at the top of the regstack.
Bring over regstack bugfixes from the FSF.

From-SVN: r15096

gcc/ChangeLog
gcc/reg-stack.c

index 9bea4de7d7d7590bad1bc19819105288ef711e18..8c48d61f4677b81c4a91c2ad74701bb4177196c1 100644 (file)
@@ -1,3 +1,12 @@
+Thu Sep  4 23:14:27 1997  Stan Cox  (coxs@dg-rtp.dg.com)
+
+       * reg-stack.c (subst_stack_regs): Pop the stack register for a
+       computed goto which sets the same stack register.
+
+       * reg-stack.c (compare_for_stack_reg): Swap only if the source and
+       destination are both on the regstack.
+       (subst_stack_regs_pat): Put the destination at the top of the regstack.
+
 Thu Sep  4 15:02:27 1997  Jim Wilson  <wilson@cygnus.com>
 
        * mips.md (nonlocal_goto_receiver): Define.
index 5ef93561eba50c3f43ae637989992da349ad37a0..881d94ffaa0b471a28468fd8468dcd838ca2ae16 100644 (file)
@@ -1,5 +1,5 @@
 /* Register to Stack convert for GNU compiler.
-   Copyright (C) 1992, 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
+   Copyright (C) 1992, 93, 94, 95, 96, 1997 Free Software Foundation, Inc.
 
 This file is part of GNU CC.
 
@@ -2018,6 +2018,7 @@ compare_for_stack_reg (insn, regstack, pat)
   rtx *src1, *src2;
   rtx src1_note, src2_note;
   rtx cc0_user;
+  int have_cmove; 
 
   src1 = get_true_reg (&XEXP (SET_SRC (pat), 0));
   src2 = get_true_reg (&XEXP (SET_SRC (pat), 1));
@@ -2032,11 +2033,16 @@ compare_for_stack_reg (insn, regstack, pat)
       rtx *dest, src_note;
       
       dest = get_true_reg (&SET_DEST (PATTERN (cc0_user)));
-      if (REGNO (*dest) != regstack->reg[regstack->top])
+
+      have_cmove = 1;
+      if (get_hard_regnum (regstack, *dest) >= FIRST_STACK_REG
+         && REGNO (*dest) != regstack->reg[regstack->top])
        {
          emit_swap_insn (insn, regstack, *dest);       
        }
     }
+  else
+    have_cmove = 0;
 
   /* ??? If fxch turns out to be cheaper than fstp, give priority to
      registers that die in this insn - move those to stack top first.  */
@@ -2071,7 +2077,8 @@ compare_for_stack_reg (insn, regstack, pat)
   else
     src2_note = NULL_RTX;
 
-  emit_swap_insn (insn, regstack, *src1);
+  if (! have_cmove)
+     emit_swap_insn (insn, regstack, *src1);
 
   replace_reg (src1, FIRST_STACK_REG);
 
@@ -2378,8 +2385,6 @@ subst_stack_regs_pat (insn, regstack, pat)
          for (i = 1; i <= 2; i++)
            if (src_note [i])
              {
-               int regno = get_hard_regnum (regstack, XEXP (src_note [i], 0));
-
                /* If the register that dies is not at the top of stack, then
                   move the top of stack to the dead reg */
                if (REGNO (XEXP (src_note[i], 0))
@@ -2397,13 +2402,15 @@ subst_stack_regs_pat (insn, regstack, pat)
                    replace_reg (&XEXP (src_note[i], 0), FIRST_STACK_REG);
                    regstack->top--;
                  }
-               
              }
-
-         SET_HARD_REG_BIT (regstack->reg_set, REGNO (*dest));
-         replace_reg (dest, FIRST_STACK_REG);
        }
 
+       /* Make dest the top of stack.  Add dest to regstack if not present. */
+       if (get_hard_regnum (regstack, *dest) < FIRST_STACK_REG)
+         regstack->reg[++regstack->top] = REGNO (*dest);       
+       SET_HARD_REG_BIT (regstack->reg_set, REGNO (*dest));
+       replace_reg (dest, FIRST_STACK_REG);
+
        break;
 
       default:
@@ -2719,6 +2726,7 @@ subst_stack_regs (insn, regstack)
 {
   register rtx *note_link, note;
   register int i;
+  rtx head, jump, pat, cipat;
   int n_operands;
 
   if (GET_CODE (insn) == CALL_INSN)
@@ -2790,6 +2798,39 @@ subst_stack_regs (insn, regstack)
   if (GET_CODE (insn) == NOTE)
     return;
 
+  /* If we are reached by a computed goto which sets this same stack register,
+     then pop this stack register, but maintain regstack. */
+
+  pat = single_set (insn);
+  if (pat != 0
+      && INSN_UID (insn) <= max_uid
+      && GET_CODE (block_begin[BLOCK_NUM(insn)]) == CODE_LABEL
+      && GET_CODE (pat) == SET && STACK_REG_P (SET_DEST (pat)))
+    for (head = block_begin[BLOCK_NUM(insn)], jump = LABEL_REFS (head);
+        jump != head;
+        jump = LABEL_NEXTREF (jump))
+      {
+       cipat = single_set (CONTAINING_INSN (jump));
+       if (cipat != 0
+           && GET_CODE (cipat) == SET
+           && SET_DEST (cipat) == pc_rtx
+           && uses_reg_or_mem (SET_SRC (cipat))
+           && INSN_UID (CONTAINING_INSN (jump)) <= max_uid)
+         {
+           int from_block = BLOCK_NUM (CONTAINING_INSN (jump));
+           if (TEST_HARD_REG_BIT (block_out_reg_set[from_block],
+                                  REGNO (SET_DEST (pat))))
+             {
+               struct stack_def old;
+               bcopy (regstack->reg, old.reg, sizeof (old.reg));
+               emit_pop_insn (insn, regstack, SET_DEST (pat), emit_insn_before);
+               regstack->top += 1;
+               bcopy (old.reg, regstack->reg, sizeof (old.reg));
+               SET_HARD_REG_BIT (regstack->reg_set, REGNO (SET_DEST (pat)));
+             }
+         }
+      }
+
   /* If there is a REG_UNUSED note on a stack register on this insn,
      the indicated reg must be popped.  The REG_UNUSED note is removed,
      since the form of the newly emitted pop insn references the reg,