OSDN Git Service

* params.def (PARAM_INLINE_UNIT_GROWTH): Set to 30.
[pf3gnuchains/gcc-fork.git] / gcc / regclass.c
index 8a0bab1..0a1114d 100644 (file)
@@ -1,6 +1,6 @@
 /* Compute register class preferences for pseudo-registers.
    Copyright (C) 1987, 1988, 1991, 1992, 1993, 1994, 1995, 1996
-   1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
+   1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
    Free Software Foundation, Inc.
 
 This file is part of GCC.
@@ -859,7 +859,7 @@ static void record_address_regs (enum machine_mode, rtx, int, enum rtx_code,
 #ifdef FORBIDDEN_INC_DEC_CLASSES
 static int auto_inc_dec_reg_p (rtx, enum machine_mode);
 #endif
-static void reg_scan_mark_refs (rtx, rtx, int);
+static void reg_scan_mark_refs (rtx, rtx, int, unsigned int);
 
 /* Wrapper around REGNO_OK_FOR_INDEX_P, to allow pseudo registers.  */
 
@@ -2177,9 +2177,8 @@ allocate_reg_info (size_t num_regs, int new_p, int renumber_p)
       if (!reg_n_info)
        {
          reg_n_info = VEC_alloc (reg_info_p, heap, regno_allocated);
-         VEC_safe_grow (reg_info_p, heap, reg_n_info, regno_allocated);
-         memset (VEC_address (reg_info_p, reg_n_info), 0,
-                 sizeof (reg_info_p) * regno_allocated);
+         VEC_safe_grow_cleared (reg_info_p, heap, reg_n_info,
+                                regno_allocated);
          renumber = xmalloc (size_renumber);
          reg_pref_buffer = XNEWVEC (struct reg_pref, regno_allocated);
        }
@@ -2188,11 +2187,8 @@ allocate_reg_info (size_t num_regs, int new_p, int renumber_p)
          size_t old_length = VEC_length (reg_info_p, reg_n_info);
          if (old_length < regno_allocated)
            {
-             reg_info_p *addr;
-             VEC_safe_grow (reg_info_p, heap, reg_n_info, regno_allocated);
-             addr = VEC_address (reg_info_p, reg_n_info);
-             memset (&addr[old_length], 0,
-                     sizeof (reg_info_p) * (regno_allocated - old_length));
+             VEC_safe_grow_cleared (reg_info_p, heap, reg_n_info,
+                                    regno_allocated);
            }
          else if (regno_allocated < old_length)
            {
@@ -2296,6 +2292,14 @@ free_reg_info (void)
   regno_allocated = 0;
   reg_n_max = 0;
 }
+
+/* Clear the information stored for REGNO.  */
+void
+clear_reg_info_regno (unsigned int regno)
+{
+  if (regno < regno_allocated)
+    memset (VEC_index (reg_info_p, reg_n_info, regno), 0, sizeof (reg_info));
+}
 \f
 /* This is the `regscan' pass of the compiler, run just before cse
    and again just before loop.
@@ -2337,10 +2341,10 @@ reg_scan (rtx f, unsigned int nregs)
        if (GET_CODE (pat) == PARALLEL
            && XVECLEN (pat, 0) > max_parallel)
          max_parallel = XVECLEN (pat, 0);
-       reg_scan_mark_refs (pat, insn, 0);
+       reg_scan_mark_refs (pat, insn, 0, 0);
 
        if (REG_NOTES (insn))
-         reg_scan_mark_refs (REG_NOTES (insn), insn, 1);
+         reg_scan_mark_refs (REG_NOTES (insn), insn, 1, 0);
       }
 
   max_parallel += max_set_parallel;
@@ -2348,11 +2352,39 @@ reg_scan (rtx f, unsigned int nregs)
   timevar_pop (TV_REG_SCAN);
 }
 
+/* Update 'regscan' information by looking at the insns
+   from FIRST to LAST.  Some new REGs have been created,
+   and any REG with number greater than OLD_MAX_REGNO is
+   such a REG.  We only update information for those.  */
+
+void
+reg_scan_update (rtx first, rtx last, unsigned int old_max_regno)
+{
+  rtx insn;
+
+  allocate_reg_info (max_reg_num (), FALSE, FALSE);
+
+  for (insn = first; insn != last; insn = NEXT_INSN (insn))
+    if (INSN_P (insn))
+      {
+       rtx pat = PATTERN (insn);
+       if (GET_CODE (pat) == PARALLEL
+           && XVECLEN (pat, 0) > max_parallel)
+         max_parallel = XVECLEN (pat, 0);
+       reg_scan_mark_refs (pat, insn, 0, old_max_regno);
+
+       if (REG_NOTES (insn))
+         reg_scan_mark_refs (REG_NOTES (insn), insn, 1, old_max_regno);
+      }
+}
+
 /* X is the expression to scan.  INSN is the insn it appears in.
-   NOTE_FLAG is nonzero if X is from INSN's notes rather than its body.  */
+   NOTE_FLAG is nonzero if X is from INSN's notes rather than its body.
+   We should only record information for REGs with numbers
+   greater than or equal to MIN_REGNO.  */
 
 static void
-reg_scan_mark_refs (rtx x, rtx insn, int note_flag)
+reg_scan_mark_refs (rtx x, rtx insn, int note_flag, unsigned int min_regno)
 {
   enum rtx_code code;
   rtx dest;
@@ -2379,35 +2411,43 @@ reg_scan_mark_refs (rtx x, rtx insn, int note_flag)
       {
        unsigned int regno = REGNO (x);
 
-       if (!note_flag)
-         REGNO_LAST_UID (regno) = INSN_UID (insn);
-       if (REGNO_FIRST_UID (regno) == 0)
-         REGNO_FIRST_UID (regno) = INSN_UID (insn);
+       if (regno >= min_regno)
+         {
+           if (!note_flag)
+             REGNO_LAST_UID (regno) = INSN_UID (insn);
+           if (REGNO_FIRST_UID (regno) == 0)
+             REGNO_FIRST_UID (regno) = INSN_UID (insn);
+           /* If we are called by reg_scan_update() (indicated by min_regno
+              being set), we also need to update the reference count.  */
+           if (min_regno)
+             REG_N_REFS (regno)++;
+         }
       }
       break;
 
     case EXPR_LIST:
       if (XEXP (x, 0))
-       reg_scan_mark_refs (XEXP (x, 0), insn, note_flag);
+       reg_scan_mark_refs (XEXP (x, 0), insn, note_flag, min_regno);
       if (XEXP (x, 1))
-       reg_scan_mark_refs (XEXP (x, 1), insn, note_flag);
+       reg_scan_mark_refs (XEXP (x, 1), insn, note_flag, min_regno);
       break;
 
     case INSN_LIST:
       if (XEXP (x, 1))
-       reg_scan_mark_refs (XEXP (x, 1), insn, note_flag);
+       reg_scan_mark_refs (XEXP (x, 1), insn, note_flag, min_regno);
       break;
 
     case CLOBBER:
       {
        rtx reg = XEXP (x, 0);
-       if (REG_P (reg))
+       if (REG_P (reg)
+           && REGNO (reg) >= min_regno)
          {
            REG_N_SETS (REGNO (reg))++;
            REG_N_REFS (REGNO (reg))++;
          }
        else if (MEM_P (reg))
-         reg_scan_mark_refs (XEXP (reg, 0), insn, note_flag);
+         reg_scan_mark_refs (XEXP (reg, 0), insn, note_flag, min_regno);
       }
       break;
 
@@ -2424,7 +2464,8 @@ reg_scan_mark_refs (rtx x, rtx insn, int note_flag)
       if (GET_CODE (dest) == PARALLEL)
        max_set_parallel = MAX (max_set_parallel, XVECLEN (dest, 0) - 1);
 
-      if (REG_P (dest))
+      if (REG_P (dest)
+         && REGNO (dest) >= min_regno)
        {
          REG_N_SETS (REGNO (dest))++;
          REG_N_REFS (REGNO (dest))++;
@@ -2444,6 +2485,7 @@ reg_scan_mark_refs (rtx x, rtx insn, int note_flag)
 
       if (REG_P (SET_DEST (x))
          && REGNO (SET_DEST (x)) >= FIRST_PSEUDO_REGISTER
+         && REGNO (SET_DEST (x)) >= min_regno
          /* If the destination pseudo is set more than once, then other
             sets might not be to a pointer value (consider access to a
             union in two threads of control in the presence of global
@@ -2504,12 +2546,12 @@ reg_scan_mark_refs (rtx x, rtx insn, int note_flag)
        for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
          {
            if (fmt[i] == 'e')
-             reg_scan_mark_refs (XEXP (x, i), insn, note_flag);
+             reg_scan_mark_refs (XEXP (x, i), insn, note_flag, min_regno);
            else if (fmt[i] == 'E' && XVEC (x, i) != 0)
              {
                int j;
                for (j = XVECLEN (x, i) - 1; j >= 0; j--)
-                 reg_scan_mark_refs (XVECEXP (x, i, j), insn, note_flag);
+                 reg_scan_mark_refs (XVECEXP (x, i, j), insn, note_flag, min_regno);
              }
          }
       }