OSDN Git Service

* alias.c (find_base_term, case ZERO_EXTEND, case SIGN_EXTEND):
[pf3gnuchains/gcc-fork.git] / gcc / local-alloc.c
index f0492c4..1a6e3cf 100644 (file)
@@ -1,6 +1,6 @@
 /* Allocate registers within a basic block, for GNU compiler.
    Copyright (C) 1987, 1988, 1991, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2001 Free Software Foundation, Inc.
+   1999, 2000, 2001, 2002 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -74,12 +74,13 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "output.h"
 #include "toplev.h"
 #include "except.h"
+#include "integrate.h"
 \f
 /* Next quantity number available for allocation.  */
 
 static int next_qty;
 
-/* Information we maitain about each quantity.  */
+/* Information we maintain about each quantity.  */
 struct qty
 {
   /* The number of refs to quantity Q.  */
@@ -312,7 +313,7 @@ alloc_qty (regno, mode, size, birth)
      enum machine_mode mode;
      int size, birth;
 {
-  register int qtyno = next_qty++;
+  int qtyno = next_qty++;
 
   reg_qty[regno] = qtyno;
   reg_offset[regno] = 0;
@@ -335,7 +336,7 @@ alloc_qty (regno, mode, size, birth)
 int
 local_alloc ()
 {
-  register int b, i;
+  int b, i;
   int max_qty;
 
   /* We need to keep track of whether or not we recorded a LABEL_REF so
@@ -372,9 +373,6 @@ local_alloc ()
   reg_offset = (char *) xmalloc (max_regno * sizeof (char));
   reg_next_in_qty = (int *) xmalloc (max_regno * sizeof (int));
 
-  /* Allocate the reg_renumber array.  */
-  allocate_reg_info (max_regno, FALSE, TRUE);
-
   /* Determine which pseudo-registers can be allocated by local-alloc.
      In general, these are the registers used only in a single block and
      which only die once.
@@ -526,9 +524,9 @@ static int
 equiv_init_varies_p (x)
      rtx x;
 {
-  register RTX_CODE code = GET_CODE (x);
-  register int i;
-  register const char *fmt;
+  RTX_CODE code = GET_CODE (x);
+  int i;
+  const char *fmt;
 
   switch (code)
     {
@@ -781,6 +779,12 @@ memref_used_between_p (memref, start, end)
 }
 \f
 /* Return nonzero if the rtx X is invariant over the current function.  */
+/* ??? Actually, the places this is used in reload expect exactly what
+   is tested here, and not everything that is function invariant.  In
+   particular, the frame pointer and arg pointer are special cased;
+   pic_offset_table_rtx is not, and this will cause aborts when we
+   go to spill these things to memory.  */
+
 int
 function_invariant_p (x)
      rtx x;
@@ -932,8 +936,7 @@ update_equiv_regs ()
             REG_EQUAL note on the insn.  Since this note would be redundant,
             there's no point creating it earlier than here.  */
          if (! note && ! rtx_varies_p (src, 0))
-           REG_NOTES (insn)
-             = note = gen_rtx_EXPR_LIST (REG_EQUAL, src, REG_NOTES (insn));
+           note = set_unique_reg_note (insn, REG_EQUAL, src);
 
          /* Don't bother considering a REG_EQUAL note containing an EXPR_LIST
             since it represents a function call */
@@ -1110,9 +1113,7 @@ update_equiv_regs ()
                      remove_death (regno, insn);
                      REG_N_REFS (regno) = 0;
                      REG_FREQ (regno) = 0;
-                     PUT_CODE (equiv_insn, NOTE);
-                     NOTE_LINE_NUMBER (equiv_insn) = NOTE_INSN_DELETED;
-                     NOTE_SOURCE_FILE (equiv_insn) = 0;
+                     delete_insn (equiv_insn);
                      
                      reg_equiv[regno].init_insns
                        = XEXP (reg_equiv[regno].init_insns, 1);
@@ -1131,9 +1132,7 @@ update_equiv_regs ()
                         otherwise eliminate_regs_in_insn will abort.  */
                      INSN_CODE (new_insn) = INSN_CODE (equiv_insn);
 
-                     PUT_CODE (equiv_insn, NOTE);
-                     NOTE_LINE_NUMBER (equiv_insn) = NOTE_INSN_DELETED;
-                     NOTE_SOURCE_FILE (equiv_insn) = 0;
+                     delete_insn (equiv_insn);
 
                      XEXP (reg_equiv[regno].init_insns, 0) = new_insn;
 
@@ -1222,9 +1221,9 @@ static void
 block_alloc (b)
      int b;
 {
-  register int i, q;
-  register rtx insn;
-  rtx note;
+  int i, q;
+  rtx insn;
+  rtx note, hard_reg;
   int insn_number = 0;
   int insn_count = 0;
   int max_uid = get_max_uid ();
@@ -1265,9 +1264,9 @@ block_alloc (b)
 
       if (INSN_P (insn))
        {
-         register rtx link, set;
-         register int win = 0;
-         register rtx r0, r1 = NULL_RTX;
+         rtx link, set;
+         int win = 0;
+         rtx r0, r1 = NULL_RTX;
          int combined_regno = -1;
          int i;
 
@@ -1309,7 +1308,7 @@ block_alloc (b)
              for (i = 1; i < recog_data.n_operands; i++)
                {
                  const char *p = recog_data.constraints[i];
-                 int this_match = (requires_inout (p));
+                 int this_match = requires_inout (p);
 
                  n_matching_alts += this_match;
                  if (this_match == recog_data.n_alternatives)
@@ -1348,6 +1347,18 @@ block_alloc (b)
                    while (GET_CODE (r1) == PLUS || GET_CODE (r1) == MULT)
                      r1 = XEXP (r1, 0);
 
+                 /* Avoid making a call-saved register unnecessarily
+                     clobbered.  */
+                 hard_reg = get_hard_reg_initial_reg (cfun, r1);
+                 if (hard_reg != NULL_RTX)
+                   {
+                     if (GET_CODE (hard_reg) == REG
+                         && IN_RANGE (REGNO (hard_reg),
+                                      0, FIRST_PSEUDO_REGISTER - 1)
+                         && ! call_used_regs[REGNO (hard_reg)])
+                       continue;
+                   }
+
                  if (GET_CODE (r0) == REG || GET_CODE (r0) == SUBREG)
                    {
                      /* We have two priorities for hard register preferences.
@@ -1590,7 +1601,7 @@ block_alloc (b)
             discourage the register allocator from creating false
             dependencies.
 
-            The adjustment value is choosen to indicate that this qty
+            The adjustment value is chosen to indicate that this qty
             conflicts with all the qtys in the instructions immediately
             before and after the lifetime of this qty.
 
@@ -1697,8 +1708,8 @@ qty_compare_1 (q1p, q2p)
      const PTR q1p;
      const PTR q2p;
 {
-  register int q1 = *(const int *) q1p, q2 = *(const int *) q2p;
-  register int tem = QTY_CMP_PRI (q2) - QTY_CMP_PRI (q1);
+  int q1 = *(const int *) q1p, q2 = *(const int *) q2p;
+  int tem = QTY_CMP_PRI (q2) - QTY_CMP_PRI (q1);
 
   if (tem != 0)
     return tem;
@@ -1724,7 +1735,7 @@ static int
 qty_sugg_compare (q1, q2)
      int q1, q2;
 {
-  register int tem = QTY_CMP_SUGG (q1) - QTY_CMP_SUGG (q2);
+  int tem = QTY_CMP_SUGG (q1) - QTY_CMP_SUGG (q2);
 
   if (tem != 0)
     return tem;
@@ -1737,8 +1748,8 @@ qty_sugg_compare_1 (q1p, q2p)
      const PTR q1p;
      const PTR q2p;
 {
-  register int q1 = *(const int *) q1p, q2 = *(const int *) q2p;
-  register int tem = QTY_CMP_SUGG (q1) - QTY_CMP_SUGG (q2);
+  int q1 = *(const int *) q1p, q2 = *(const int *) q2p;
+  int tem = QTY_CMP_SUGG (q1) - QTY_CMP_SUGG (q2);
 
   if (tem != 0)
     return tem;
@@ -1785,10 +1796,10 @@ combine_regs (usedreg, setreg, may_save_copy, insn_number, insn, already_dead)
      rtx insn;
      int already_dead;
 {
-  register int ureg, sreg;
-  register int offset = 0;
+  int ureg, sreg;
+  int offset = 0;
   int usize, ssize;
-  register int sqty;
+  int sqty;
 
   /* Determine the numbers and sizes of registers being used.  If a subreg
      is present that does not change the entire register, don't consider
@@ -1796,20 +1807,29 @@ combine_regs (usedreg, setreg, may_save_copy, insn_number, insn, already_dead)
 
   while (GET_CODE (usedreg) == SUBREG)
     {
-      if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (usedreg))) > UNITS_PER_WORD)
-       may_save_copy = 0;
-      if (REGNO (SUBREG_REG (usedreg)) < FIRST_PSEUDO_REGISTER)
-       offset += subreg_regno_offset (REGNO (SUBREG_REG (usedreg)),
-                                      GET_MODE (SUBREG_REG (usedreg)),
-                                      SUBREG_BYTE (usedreg),
-                                      GET_MODE (usedreg));
-      else
-       offset += (SUBREG_BYTE (usedreg)
-                  / REGMODE_NATURAL_SIZE (GET_MODE (usedreg)));
-      usedreg = SUBREG_REG (usedreg);
+      rtx subreg = SUBREG_REG (usedreg);
+
+      if (GET_CODE (subreg) == REG)
+       {
+         if (GET_MODE_SIZE (GET_MODE (subreg)) > UNITS_PER_WORD)
+           may_save_copy = 0;
+
+         if (REGNO (subreg) < FIRST_PSEUDO_REGISTER)
+           offset += subreg_regno_offset (REGNO (subreg),
+                                          GET_MODE (subreg),
+                                          SUBREG_BYTE (usedreg),
+                                          GET_MODE (usedreg));
+         else
+           offset += (SUBREG_BYTE (usedreg)
+                     / REGMODE_NATURAL_SIZE (GET_MODE (usedreg)));
+       }
+
+      usedreg = subreg;
     }
+
   if (GET_CODE (usedreg) != REG)
     return 0;
+
   ureg = REGNO (usedreg);
   if (ureg < FIRST_PSEUDO_REGISTER)
     usize = HARD_REGNO_NREGS (ureg, GET_MODE (usedreg));
@@ -1820,20 +1840,29 @@ combine_regs (usedreg, setreg, may_save_copy, insn_number, insn, already_dead)
 
   while (GET_CODE (setreg) == SUBREG)
     {
-      if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (setreg))) > UNITS_PER_WORD)
-       may_save_copy = 0;
-      if (REGNO (SUBREG_REG (setreg)) < FIRST_PSEUDO_REGISTER)
-       offset -= subreg_regno_offset (REGNO (SUBREG_REG (setreg)),
-                                      GET_MODE (SUBREG_REG (setreg)),
-                                      SUBREG_BYTE (setreg),
-                                      GET_MODE (setreg));
-      else
-       offset -= (SUBREG_BYTE (setreg)
-                  / REGMODE_NATURAL_SIZE (GET_MODE (setreg)));
-      setreg = SUBREG_REG (setreg);
+      rtx subreg = SUBREG_REG (setreg);
+
+      if (GET_CODE (subreg) == REG)
+       {
+         if (GET_MODE_SIZE (GET_MODE (subreg)) > UNITS_PER_WORD)
+           may_save_copy = 0;
+
+         if (REGNO (subreg) < FIRST_PSEUDO_REGISTER)
+           offset -= subreg_regno_offset (REGNO (subreg),
+                                          GET_MODE (subreg),
+                                          SUBREG_BYTE (setreg),
+                                          GET_MODE (setreg));
+         else
+           offset -= (SUBREG_BYTE (setreg)
+                     / REGMODE_NATURAL_SIZE (GET_MODE (setreg)));
+       }
+
+      setreg = subreg;
     }
+
   if (GET_CODE (setreg) != REG)
     return 0;
+
   sreg = REGNO (setreg);
   if (sreg < FIRST_PSEUDO_REGISTER)
     ssize = HARD_REGNO_NREGS (sreg, GET_MODE (setreg));
@@ -1954,7 +1983,7 @@ combine_regs (usedreg, setreg, may_save_copy, insn_number, insn, already_dead)
       qty[sqty].freq += REG_FREQ (sreg);
       if (usize < ssize)
        {
-         register int i;
+         int i;
 
          for (i = qty[sqty].first_reg; i >= 0; i = reg_next_in_qty[i])
            reg_offset[i] -= offset;
@@ -1978,7 +2007,7 @@ reg_meets_class_p (reg, class)
      int reg;
      enum reg_class class;
 {
-  register enum reg_class rclass = reg_preferred_class (reg);
+  enum reg_class rclass = reg_preferred_class (reg);
   return (reg_class_subset_p (rclass, class)
          || reg_class_subset_p (class, rclass));
 }
@@ -2039,7 +2068,7 @@ reg_is_born (reg, birth)
      rtx reg;
      int birth;
 {
-  register int regno;
+  int regno;
 
   if (GET_CODE (reg) == SUBREG)
     {
@@ -2077,10 +2106,10 @@ reg_is_born (reg, birth)
 
 static void
 wipe_dead_reg (reg, output_p)
-     register rtx reg;
+     rtx reg;
      int output_p;
 {
-  register int regno = REGNO (reg);
+  int regno = REGNO (reg);
 
   /* If this insn has multiple results,
      and the dead reg is used in one of the results,
@@ -2152,14 +2181,14 @@ find_free_reg (class, mode, qtyno, accept_call_clobbered, just_try_suggested,
      int just_try_suggested;
      int born_index, dead_index;
 {
-  register int i, ins;
+  int i, ins;
 #ifdef HARD_REG_SET
   /* Declare it register if it's a scalar.  */
   register
 #endif
     HARD_REG_SET used, first_used;
 #ifdef ELIMINABLE_REGS
-  static struct {int from, to; } eliminables[] = ELIMINABLE_REGS;
+  static const struct {const int from, to; } eliminables[] = ELIMINABLE_REGS;
 #endif
 
   /* Validate our parameters.  */
@@ -2245,8 +2274,8 @@ find_free_reg (class, mode, qtyno, accept_call_clobbered, just_try_suggested,
              || accept_call_clobbered
              || ! HARD_REGNO_CALL_PART_CLOBBERED (regno, mode)))
        {
-         register int j;
-         register int size1 = HARD_REGNO_NREGS (regno, mode);
+         int j;
+         int size1 = HARD_REGNO_NREGS (regno, mode);
          for (j = 1; j < size1 && ! TEST_HARD_REG_BIT (used, regno + j); j++);
          if (j == size1)
            {
@@ -2303,11 +2332,11 @@ find_free_reg (class, mode, qtyno, accept_call_clobbered, just_try_suggested,
 
 static void
 mark_life (regno, mode, life)
-     register int regno;
+     int regno;
      enum machine_mode mode;
      int life;
 {
-  register int j = HARD_REGNO_NREGS (regno, mode);
+  int j = HARD_REGNO_NREGS (regno, mode);
   if (life)
     while (--j >= 0)
       SET_HARD_REG_BIT (regs_live, regno + j);
@@ -2326,7 +2355,7 @@ post_mark_life (regno, mode, life, birth, death)
      enum machine_mode mode;
      int life, birth, death;
 {
-  register int j = HARD_REGNO_NREGS (regno, mode);
+  int j = HARD_REGNO_NREGS (regno, mode);
 #ifdef HARD_REG_SET
   /* Declare it register if it's a scalar.  */
   register
@@ -2416,8 +2445,6 @@ requires_inout (p)
       case '=':  case '+':  case '?':
       case '#':  case '&':  case '!':
       case '*':  case '%':
-      case '1':  case '2':  case '3':  case '4': case '5':
-      case '6':  case '7':  case '8':  case '9':
       case 'm':  case '<':  case '>':  case 'V':  case 'o':
       case 'E':  case 'F':  case 'G':  case 'H':
       case 's':  case 'i':  case 'n':
@@ -2438,6 +2465,13 @@ requires_inout (p)
        found_zero = 1;
        break;
 
+      case '1':  case '2':  case '3':  case '4': case '5':
+      case '6':  case '7':  case '8':  case '9':
+       /* Skip the balance of the matching constraint.  */
+       while (ISDIGIT (*p))
+         p++;
+       break;
+
       default:
        if (REG_CLASS_FROM_LETTER (c) == NO_REGS)
          break;
@@ -2458,7 +2492,7 @@ void
 dump_local_alloc (file)
      FILE *file;
 {
-  register int i;
+  int i;
   for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
     if (reg_renumber[i] != -1)
       fprintf (file, ";; Register %d in %d.\n", i, reg_renumber[i]);