OSDN Git Service

* objc/objc-act.c (UTAG_STATICS, UTAG_PROTOCOL_LIST, USERTYPE):
[pf3gnuchains/gcc-fork.git] / gcc / local-alloc.c
index 2637b7e..77607ba 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.  */
@@ -244,7 +245,7 @@ static rtx this_insn;
 struct equivalence
 {
   /* Set when an attempt should be made to replace a register
-     with the associated src entry.  */
+     with the associated src_p entry.  */
 
   char replace;
 
@@ -254,7 +255,7 @@ struct equivalence
 
   rtx replacement;
 
-  rtx src;
+  rtx *src_p;
 
   /* Loop depth is used to recognize equivalences which appear
      to be present within the same loop (or in an inner loop).  */
@@ -335,8 +336,9 @@ alloc_qty (regno, mode, size, birth)
 int
 local_alloc ()
 {
-  int b, i;
+  int i;
   int max_qty;
+  basic_block b;
 
   /* We need to keep track of whether or not we recorded a LABEL_REF so
      that we know if the jump optimizer needs to be rerun.  */
@@ -351,7 +353,8 @@ local_alloc ()
 
   /* Promote REG_EQUAL notes to REG_EQUIV notes and adjust status of affected
      registers.  */
-  update_equiv_regs ();
+  if (optimize)
+    update_equiv_regs ();
 
   /* This sets the maximum number of quantities we can have.  Quantity
      numbers start at zero and we can have one for each pseudo.  */
@@ -392,7 +395,7 @@ local_alloc ()
 
   /* Allocate each block's local registers, block by block.  */
 
-  for (b = 0; b < n_basic_blocks; b++)
+  FOR_EACH_BB (b)
     {
       /* NEXT_QTY indicates which elements of the `qty_...'
         vectors might need to be initialized because they were used
@@ -424,7 +427,7 @@ local_alloc ()
 
       next_qty = 0;
 
-      block_alloc (b);
+      block_alloc (b->index);
     }
 
   free (qty);
@@ -538,6 +541,7 @@ equiv_init_varies_p (x)
     case CONST:
     case CONST_INT:
     case CONST_DOUBLE:
+    case CONST_VECTOR:
     case SYMBOL_REF:
     case LABEL_REF:
       return 0;
@@ -657,10 +661,10 @@ contains_replace_regs (x)
     case LABEL_REF:
     case SYMBOL_REF:
     case CONST_DOUBLE:
+    case CONST_VECTOR:
     case PC:
     case CC0:
     case HIGH:
-    case LO_SUM:
       return 0;
 
     case REG:
@@ -707,6 +711,7 @@ memref_referenced_p (memref, x)
     case LABEL_REF:
     case SYMBOL_REF:
     case CONST_DOUBLE:
+    case CONST_VECTOR:
     case PC:
     case CC0:
     case HIGH:
@@ -778,6 +783,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;
@@ -805,7 +816,7 @@ static void
 update_equiv_regs ()
 {
   rtx insn;
-  int block;
+  basic_block bb;
   int loop_depth;
   regset_head cleared_regs;
   int clear_regnos = 0;
@@ -818,9 +829,8 @@ update_equiv_regs ()
   /* Scan the insns and find which registers have equivalences.  Do this
      in a separate scan of the insns because (due to -fcse-follow-jumps)
      a register can be set below its use.  */
-  for (block = 0; block < n_basic_blocks; block++)
+  FOR_EACH_BB (bb)
     {
-      basic_block bb = BASIC_BLOCK (block);
       loop_depth = bb->loop_depth;
 
       for (insn = bb->head; insn != NEXT_INSN (bb->end); insn = NEXT_INSN (insn))
@@ -929,8 +939,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 */
@@ -996,7 +1005,7 @@ update_equiv_regs ()
                recorded_label_ref = 1;
 
              reg_equiv[regno].replacement = XEXP (note, 0);
-             reg_equiv[regno].src = src;
+             reg_equiv[regno].src_p = &SET_SRC (set);
              reg_equiv[regno].loop_depth = loop_depth;
 
              /* Don't mess with things live during setjmp.  */
@@ -1035,10 +1044,8 @@ update_equiv_regs ()
      within the same loop (or in an inner loop), then move the register
      initialization just before the use, so that they are in the same
      basic block.  */
-  for (block = n_basic_blocks - 1; block >= 0; block--)
+  FOR_EACH_BB_REVERSE (bb)
     {
-      basic_block bb = BASIC_BLOCK (block);
-
       loop_depth = bb->loop_depth;
       for (insn = bb->end; insn != PREV_INSN (bb->head); insn = PREV_INSN (insn))
        {
@@ -1078,7 +1085,7 @@ update_equiv_regs ()
 
                  if (asm_noperands (PATTERN (equiv_insn)) < 0
                      && validate_replace_rtx (regno_reg_rtx[regno],
-                                              reg_equiv[regno].src, insn))
+                                              *(reg_equiv[regno].src_p), insn))
                    {
                      rtx equiv_link;
                      rtx last_link;
@@ -1108,7 +1115,7 @@ update_equiv_regs ()
                      REG_N_REFS (regno) = 0;
                      REG_FREQ (regno) = 0;
                      delete_insn (equiv_insn);
-                     
+
                      reg_equiv[regno].init_insns
                        = XEXP (reg_equiv[regno].init_insns, 1);
                    }
@@ -1130,12 +1137,12 @@ update_equiv_regs ()
 
                      XEXP (reg_equiv[regno].init_insns, 0) = new_insn;
 
-                     REG_BASIC_BLOCK (regno) = block >= 0 ? block : 0;
+                     REG_BASIC_BLOCK (regno) = bb->index;
                      REG_N_CALLS_CROSSED (regno) = 0;
                      REG_LIVE_LENGTH (regno) = 2;
 
-                     if (block >= 0 && insn == BLOCK_HEAD (block))
-                       BLOCK_HEAD (block) = PREV_INSN (insn);
+                     if (insn == bb->head)
+                       bb->head = PREV_INSN (insn);
 
                      /* Remember to clear REGNO from all basic block's live
                         info.  */
@@ -1150,24 +1157,22 @@ update_equiv_regs ()
   /* Clear all dead REGNOs from all basic block's live info.  */
   if (clear_regnos)
     {
-      int j, l;
+      int j;
       if (clear_regnos > 8)
-        {
-         for (l = 0; l < n_basic_blocks; l++)
+       {
+         FOR_EACH_BB (bb)
            {
-             AND_COMPL_REG_SET (BASIC_BLOCK (l)->global_live_at_start,
-                                &cleared_regs);
-             AND_COMPL_REG_SET (BASIC_BLOCK (l)->global_live_at_end,
-                                &cleared_regs);
+             AND_COMPL_REG_SET (bb->global_live_at_start, &cleared_regs);
+             AND_COMPL_REG_SET (bb->global_live_at_end, &cleared_regs);
            }
        }
       else
-        EXECUTE_IF_SET_IN_REG_SET (&cleared_regs, 0, j,
-          {
-           for (l = 0; l < n_basic_blocks; l++)
+       EXECUTE_IF_SET_IN_REG_SET (&cleared_regs, 0, j,
+         {
+           FOR_EACH_BB (bb)
              {
-               CLEAR_REGNO_REG_SET (BASIC_BLOCK (l)->global_live_at_start, j);
-               CLEAR_REGNO_REG_SET (BASIC_BLOCK (l)->global_live_at_end, j);
+               CLEAR_REGNO_REG_SET (bb->global_live_at_start, j);
+               CLEAR_REGNO_REG_SET (bb->global_live_at_end, j);
              }
          });
     }
@@ -1217,7 +1222,7 @@ block_alloc (b)
 {
   int i, q;
   rtx insn;
-  rtx note;
+  rtx note, hard_reg;
   int insn_number = 0;
   int insn_count = 0;
   int max_uid = get_max_uid ();
@@ -1302,7 +1307,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)
@@ -1341,6 +1346,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.
@@ -1583,7 +1600,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.
 
@@ -1789,20 +1806,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));
@@ -1813,20 +1839,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));
@@ -2409,8 +2444,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':
@@ -2431,6 +2464,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;