OSDN Git Service

PR/6552
authorkenner <kenner@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 14 Nov 2003 17:28:25 +0000 (17:28 +0000)
committerkenner <kenner@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 14 Nov 2003 17:28:25 +0000 (17:28 +0000)
* function.c (struct epi_info): New field const_equiv.
(update_epilogue_consts): New function.
(keep_stack_depressed): Clear new field and verify scratch register
doesn't have it set.
Call new function via note_stores.
(handle_epilogue_set): Allow setting SP equiv reg in different mode.
Allow PLUS where second operand is register known set to constant.
(emit_equiv_load): Write load using proper mode if source different.
* config/mips/mips.md (return_internal): Put (return) first.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@73609 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/config/mips/mips.md
gcc/function.c

index 41aa8e0..64c3dba 100644 (file)
@@ -1,3 +1,16 @@
+2003-11-14  Richard Kenner  <kenner@vlsi1.ultra.nyu.edu>
+
+       PR/6552
+       * function.c (struct epi_info): New field const_equiv.
+       (update_epilogue_consts): New function.
+       (keep_stack_depressed): Clear new field and verify scratch register
+       doesn't have it set.
+       Call new function via note_stores.
+       (handle_epilogue_set): Allow setting SP equiv reg in different mode.
+       Allow PLUS where second operand is register known set to constant.
+       (emit_equiv_load): Write load using proper mode if source different.
+       * config/mips/mips.md (return_internal): Put (return) first.
+
 2003-11-14  Kazu Hirata  <kazu@cs.umass.edu>
 
        * config/h8300/lib1funcs.asm (___udivsi3): Add a comment.
index 5a4e89e..203ac2e 100644 (file)
@@ -8249,8 +8249,8 @@ ld\t%2,%1-%S1(%2)\;daddu\t%2,%2,$31\;%*j\t%2%/"
 ;; Normal return.
 
 (define_insn "return_internal"
-  [(use (match_operand 0 "pmode_register_operand" ""))
-   (return)]
+  [(return)
+   (use (match_operand 0 "pmode_register_operand" ""))]
   ""
   "%*j\t%0%/"
   [(set_attr "type"    "jump")
index ef1afaa..f191aec 100644 (file)
@@ -7296,9 +7296,12 @@ struct epi_info
   rtx equiv_reg_src;           /* If nonzero, the value that SP_EQUIV_REG
                                   should be set to once we no longer need
                                   its value.  */
+  rtx const_equiv[FIRST_PSEUDO_REGISTER]; /* Any known constant equivalences
+                                            for registers.  */
 };
 
 static void handle_epilogue_set (rtx, struct epi_info *);
+static void update_epilogue_consts PARAMS ((rtx, rtx, void *));
 static void emit_equiv_load (struct epi_info *);
 
 /* Modify INSN, a list of one or more insns that is part of the epilogue, to
@@ -7311,8 +7314,7 @@ keep_stack_depressed (rtx insns)
   struct epi_info info;
   rtx insn, next;
 
-  /* If the epilogue is just a single instruction, it ust be OK as is.  */
-
+  /* If the epilogue is just a single instruction, it must be OK as is.  */
   if (NEXT_INSN (insns) == NULL_RTX)
     return insns;
 
@@ -7324,6 +7326,9 @@ keep_stack_depressed (rtx insns)
   info.sp_offset = 0;
   info.equiv_reg_src = 0;
 
+  for (j = 0; j < FIRST_PSEUDO_REGISTER; j++)
+    info.const_equiv[j] = 0;
+
   insn = insns;
   next = NULL_RTX;
   while (insn != NULL_RTX)
@@ -7415,7 +7420,8 @@ keep_stack_depressed (rtx insns)
                    && !refers_to_regno_p (regno,
                                           regno + HARD_REGNO_NREGS (regno,
                                                                     Pmode),
-                                          info.equiv_reg_src, NULL))
+                                          info.equiv_reg_src, NULL)
+                   && info.const_equiv[regno] == 0)
                  break;
 
              if (regno == FIRST_PSEUDO_REGISTER)
@@ -7471,6 +7477,8 @@ keep_stack_depressed (rtx insns)
       info.sp_equiv_reg = info.new_sp_equiv_reg;
       info.sp_offset = info.new_sp_offset;
 
+      /* Now update any constants this insn sets.  */
+      note_stores (PATTERN (insn), update_epilogue_consts, &info);
       insn = next;
     }
 
@@ -7494,11 +7502,18 @@ handle_epilogue_set (rtx set, struct epi_info *p)
       if (SET_DEST (set) != stack_pointer_rtx)
        abort ();
 
-      if (GET_CODE (SET_SRC (set)) == PLUS
-         && GET_CODE (XEXP (SET_SRC (set), 1)) == CONST_INT)
+      if (GET_CODE (SET_SRC (set)) == PLUS)
        {
          p->new_sp_equiv_reg = XEXP (SET_SRC (set), 0);
-         p->new_sp_offset = INTVAL (XEXP (SET_SRC (set), 1));
+         if (GET_CODE (XEXP (SET_SRC (set), 1)) == CONST_INT)
+           p->new_sp_offset = INTVAL (XEXP (SET_SRC (set), 1));
+         else if (GET_CODE (XEXP (SET_SRC (set), 1)) == REG
+                  && REGNO (XEXP (SET_SRC (set), 1)) < FIRST_PSEUDO_REGISTER
+                  && p->const_equiv[REGNO (XEXP (SET_SRC (set), 1))] != 0)
+           p->new_sp_offset
+             = INTVAL (p->const_equiv[REGNO (XEXP (SET_SRC (set), 1))]);
+         else
+           abort ();
        }
       else
        p->new_sp_equiv_reg = SET_SRC (set), p->new_sp_offset = 0;
@@ -7521,11 +7536,16 @@ handle_epilogue_set (rtx set, struct epi_info *p)
      there seems little point in handling that case.  Note that we have
      to allow for the case where we are setting the register set in
      the previous part of a PARALLEL inside a single insn.  But use the
-     old offset for any updates within this insn.  */
+     old offset for any updates within this insn.  We must allow for the case
+     where the register is being set in a different (usually wider) mode than
+     Pmode).  */
   else if (p->new_sp_equiv_reg != 0 && reg_set_p (p->new_sp_equiv_reg, set))
     {
-      if (!rtx_equal_p (p->new_sp_equiv_reg, SET_DEST (set))
-         || p->equiv_reg_src != 0)
+      if (p->equiv_reg_src != 0
+         || GET_CODE (p->new_sp_equiv_reg) != REG
+         || GET_CODE (SET_DEST (set)) != REG
+         || GET_MODE_BITSIZE (GET_MODE (SET_DEST (set))) > BITS_PER_WORD
+         || REGNO (p->new_sp_equiv_reg) != REGNO (SET_DEST (set)))
        abort ();
       else
        p->equiv_reg_src
@@ -7548,15 +7568,38 @@ handle_epilogue_set (rtx set, struct epi_info *p)
     }
 }
 
+/* Update the tracking information for registers set to constants.  */
+
+static void
+update_epilogue_consts (rtx dest, rtx x, void *data)
+{
+  struct epi_info *p = (struct epi_info *) data;
+
+  if (GET_CODE (dest) != REG || REGNO (dest) >= FIRST_PSEUDO_REGISTER)
+    return;
+  else if (GET_CODE (x) == CLOBBER || ! rtx_equal_p (dest, SET_DEST (x))
+          || GET_CODE (SET_SRC (x)) != CONST_INT)
+    p->const_equiv[REGNO (dest)] = 0;
+  else
+    p->const_equiv[REGNO (dest)] = SET_SRC (x);
+}
+
 /* Emit an insn to do the load shown in p->equiv_reg_src, if needed.  */
 
 static void
 emit_equiv_load (struct epi_info *p)
 {
   if (p->equiv_reg_src != 0)
-    emit_move_insn (p->sp_equiv_reg, p->equiv_reg_src);
+    {
+      rtx dest = p->sp_equiv_reg;
+
+      if (GET_MODE (p->equiv_reg_src) != GET_MODE (dest))
+       dest = gen_rtx_REG (GET_MODE (p->equiv_reg_src),
+                           REGNO (p->sp_equiv_reg));
 
-  p->equiv_reg_src = 0;
+      emit_move_insn (dest, p->equiv_reg_src);
+      p->equiv_reg_src = 0;
+    }
 }
 #endif