OSDN Git Service

* config/m68k/m68k.h (REGISTER_NAMES): Prefix each name with
[pf3gnuchains/gcc-fork.git] / gcc / alias.c
index 02554a9..f0cfe4c 100644 (file)
@@ -1,5 +1,5 @@
 /* Alias analysis for GNU C
-   Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003
+   Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
    Free Software Foundation, Inc.
    Contributed by John Carr (jfc@mit.edu).
 
@@ -157,17 +157,21 @@ static void memory_modified_1 (rtx, rtx, void *);
    current function performs nonlocal memory memory references for the
    purposes of marking the function as a constant function.  */
 
-static GTY((length ("reg_base_value_size"))) rtx *reg_base_value;
+static GTY(()) varray_type reg_base_value;
 static rtx *new_reg_base_value;
-static unsigned int reg_base_value_size; /* size of reg_base_value array */
+
+/* We preserve the copy of old array around to avoid amount of garbage
+   produced.  About 8% of garbage produced were attributed to this
+   array.  */
+static GTY((deletable (""))) varray_type old_reg_base_value;
 
 /* Static hunks of RTL used by the aliasing code; these are initialized
    once per function to avoid unnecessary RTL allocations.  */
 static GTY (()) rtx static_reg_base_value[FIRST_PSEUDO_REGISTER];
 
 #define REG_BASE_VALUE(X) \
-  (REGNO (X) < reg_base_value_size \
-   ? reg_base_value[REGNO (X)] : 0)
+  (reg_base_value && REGNO (X) < VARRAY_SIZE (reg_base_value) \
+   ? VARRAY_RTX (reg_base_value, REGNO (X)) : 0)
 
 /* Vector of known invariant relationships between registers.  Set in
    loop unrolling.  Indexed by register number, if nonzero the value
@@ -178,6 +182,7 @@ static GTY (()) rtx static_reg_base_value[FIRST_PSEUDO_REGISTER];
    Because this array contains only pseudo registers it has no effect
    after reload.  */
 static rtx *alias_invariant;
+unsigned int alias_invariant_size;
 
 /* Vector indexed by N giving the initial (unchanging) value known for
    pseudo-register N.  This array is initialized in
@@ -778,7 +783,7 @@ find_base_value (rtx src)
         The test above is not sufficient because the scheduler may move
         a copy out of an arg reg past the NOTE_INSN_FUNCTION_BEGIN.  */
       if ((regno >= FIRST_PSEUDO_REGISTER || fixed_regs[regno])
-         && regno < reg_base_value_size)
+         && regno < VARRAY_SIZE (reg_base_value))
        {
          /* If we're inside init_alias_analysis, use new_reg_base_value
             to reduce the number of relaxation iterations.  */
@@ -786,8 +791,8 @@ find_base_value (rtx src)
              && REG_N_SETS (regno) == 1)
            return new_reg_base_value[regno];
 
-         if (reg_base_value[regno])
-           return reg_base_value[regno];
+         if (VARRAY_RTX (reg_base_value, regno))
+           return VARRAY_RTX (reg_base_value, regno);
        }
 
       return 0;
@@ -931,13 +936,13 @@ record_set (rtx dest, rtx set, void *data ATTRIBUTE_UNUSED)
 
   regno = REGNO (dest);
 
-  if (regno >= reg_base_value_size)
+  if (regno >= VARRAY_SIZE (reg_base_value))
     abort ();
 
   /* If this spans multiple hard registers, then we must indicate that every
      register has an unusable value.  */
   if (regno < FIRST_PSEUDO_REGISTER)
-    n = HARD_REGNO_NREGS (regno, GET_MODE (dest));
+    n = hard_regno_nregs[regno][GET_MODE (dest)];
   else
     n = 1;
   if (n != 1)
@@ -1030,21 +1035,20 @@ record_set (rtx dest, rtx set, void *data ATTRIBUTE_UNUSED)
 void
 record_base_value (unsigned int regno, rtx val, int invariant)
 {
-  if (regno >= reg_base_value_size)
-    return;
-
-  if (invariant && alias_invariant)
+  if (invariant && alias_invariant && regno < alias_invariant_size)
     alias_invariant[regno] = val;
 
+  if (regno >= VARRAY_SIZE (reg_base_value))
+    VARRAY_GROW (reg_base_value, max_reg_num ());
+
   if (GET_CODE (val) == REG)
     {
-      if (REGNO (val) < reg_base_value_size)
-       reg_base_value[regno] = reg_base_value[REGNO (val)];
-
+      VARRAY_RTX (reg_base_value, regno)
+        = REG_BASE_VALUE (val);
       return;
     }
-
-  reg_base_value[regno] = find_base_value (val);
+  VARRAY_RTX (reg_base_value, regno)
+     = find_base_value (val);
 }
 
 /* Clear alias info for a register.  This is used if an RTL transformation
@@ -1135,9 +1139,6 @@ rtx_equal_for_memref_p (rtx x, rtx y)
   /* Some RTL can be compared without a recursive examination.  */
   switch (code)
     {
-    case VALUE:
-      return CSELIB_VAL_PTR (x) == CSELIB_VAL_PTR (y);
-
     case REG:
       return REGNO (x) == REGNO (y);
 
@@ -1147,6 +1148,7 @@ rtx_equal_for_memref_p (rtx x, rtx y)
     case SYMBOL_REF:
       return XSTR (x, 0) == XSTR (y, 0);
 
+    case VALUE:
     case CONST_INT:
     case CONST_DOUBLE:
       /* There's no need to compare the contents of CONST_DOUBLEs or
@@ -1321,6 +1323,8 @@ find_base_term (rtx x)
 
     case VALUE:
       val = CSELIB_VAL_PTR (x);
+      if (!val)
+       return 0;
       for (l = val->locs; l; l = l->next)
        if ((x = find_base_term (l->loc)) != 0)
          return x;
@@ -1498,14 +1502,17 @@ get_addr (rtx x)
   if (GET_CODE (x) != VALUE)
     return x;
   v = CSELIB_VAL_PTR (x);
-  for (l = v->locs; l; l = l->next)
-    if (CONSTANT_P (l->loc))
-      return l->loc;
-  for (l = v->locs; l; l = l->next)
-    if (GET_CODE (l->loc) != REG && GET_CODE (l->loc) != MEM)
-      return l->loc;
-  if (v->locs)
-    return v->locs->loc;
+  if (v)
+    {
+      for (l = v->locs; l; l = l->next)
+       if (CONSTANT_P (l->loc))
+         return l->loc;
+      for (l = v->locs; l; l = l->next)
+       if (GET_CODE (l->loc) != REG && GET_CODE (l->loc) != MEM)
+         return l->loc;
+      if (v->locs)
+       return v->locs->loc;
+    }
   return x;
 }
 
@@ -1682,8 +1689,8 @@ memrefs_conflict_p (int xsize, rtx x, int ysize, rtx y, HOST_WIDE_INT c)
            unsigned int r_x = REGNO (x), r_y = REGNO (y);
            rtx i_x, i_y;       /* invariant relationships of X and Y */
 
-           i_x = r_x >= reg_base_value_size ? 0 : alias_invariant[r_x];
-           i_y = r_y >= reg_base_value_size ? 0 : alias_invariant[r_y];
+           i_x = r_x >= alias_invariant_size ? 0 : alias_invariant[r_x];
+           i_y = r_y >= alias_invariant_size ? 0 : alias_invariant[r_y];
 
            if (i_x == 0 && i_y == 0)
              break;
@@ -2710,7 +2717,7 @@ memory_modified_in_insn_p (rtx mem, rtx insn)
 void
 init_alias_analysis (void)
 {
-  int maxreg = max_reg_num ();
+  unsigned int maxreg = max_reg_num ();
   int changed, pass;
   int i;
   unsigned int ui;
@@ -2730,17 +2737,31 @@ init_alias_analysis (void)
   /* Overallocate reg_base_value to allow some growth during loop
      optimization.  Loop unrolling can create a large number of
      registers.  */
-  reg_base_value_size = maxreg * 2;
-  reg_base_value = ggc_alloc_cleared (reg_base_value_size * sizeof (rtx));
+  if (old_reg_base_value)
+    {
+      reg_base_value = old_reg_base_value;
+      /* If varray gets large zeroing cost may get important.  */
+      if (VARRAY_SIZE (reg_base_value) > 256
+          && VARRAY_SIZE (reg_base_value) > 4 * maxreg)
+       VARRAY_GROW (reg_base_value, maxreg);
+      VARRAY_CLEAR (reg_base_value);
+      if (VARRAY_SIZE (reg_base_value) < maxreg)
+       VARRAY_GROW (reg_base_value, maxreg);
+    }
+  else
+    {
+      VARRAY_RTX_INIT (reg_base_value, maxreg, "reg_base_value");
+    }
 
-  new_reg_base_value = xmalloc (reg_base_value_size * sizeof (rtx));
-  reg_seen = xmalloc (reg_base_value_size);
+  new_reg_base_value = xmalloc (maxreg * sizeof (rtx));
+  reg_seen = xmalloc (maxreg);
   if (! reload_completed && flag_old_unroll_loops)
     {
       /* ??? Why are we realloc'ing if we're just going to zero it?  */
       alias_invariant = xrealloc (alias_invariant,
-                                 reg_base_value_size * sizeof (rtx));
-      memset (alias_invariant, 0, reg_base_value_size * sizeof (rtx));
+                                 maxreg * sizeof (rtx));
+      memset (alias_invariant, 0, maxreg * sizeof (rtx));
+      alias_invariant_size = maxreg;
     }
 
   /* The basic idea is that each pass through this loop will use the
@@ -2777,10 +2798,10 @@ init_alias_analysis (void)
       copying_arguments = true;
 
       /* Wipe the potential alias information clean for this pass.  */
-      memset (new_reg_base_value, 0, reg_base_value_size * sizeof (rtx));
+      memset (new_reg_base_value, 0, maxreg * sizeof (rtx));
 
       /* Wipe the reg_seen array clean.  */
-      memset (reg_seen, 0, reg_base_value_size);
+      memset (reg_seen, 0, maxreg);
 
       /* Mark all hard registers which may contain an address.
         The stack, frame and argument pointers may contain an address.
@@ -2868,13 +2889,16 @@ init_alias_analysis (void)
        }
 
       /* Now propagate values from new_reg_base_value to reg_base_value.  */
-      for (ui = 0; ui < reg_base_value_size; ui++)
+      if (maxreg != (unsigned int) max_reg_num())
+       abort ();
+      for (ui = 0; ui < maxreg; ui++)
        {
          if (new_reg_base_value[ui]
-             && new_reg_base_value[ui] != reg_base_value[ui]
-             && ! rtx_equal_p (new_reg_base_value[ui], reg_base_value[ui]))
+             && new_reg_base_value[ui] != VARRAY_RTX (reg_base_value, ui)
+             && ! rtx_equal_p (new_reg_base_value[ui],
+                               VARRAY_RTX (reg_base_value, ui)))
            {
-             reg_base_value[ui] = new_reg_base_value[ui];
+             VARRAY_RTX (reg_base_value, ui) = new_reg_base_value[ui];
              changed = 1;
            }
        }
@@ -2882,7 +2906,7 @@ init_alias_analysis (void)
   while (changed && ++pass < MAX_ALIAS_LOOP_PASSES);
 
   /* Fill in the remaining entries.  */
-  for (i = FIRST_PSEUDO_REGISTER; i < maxreg; i++)
+  for (i = FIRST_PSEUDO_REGISTER; i < (int)maxreg; i++)
     if (reg_known_value[i] == 0)
       reg_known_value[i] = regno_reg_rtx[i];
 
@@ -2901,16 +2925,17 @@ init_alias_analysis (void)
     {
       changed = 0;
       pass++;
-      for (ui = 0; ui < reg_base_value_size; ui++)
+      for (ui = 0; ui < maxreg; ui++)
        {
-         rtx base = reg_base_value[ui];
+         rtx base = VARRAY_RTX (reg_base_value, ui);
          if (base && GET_CODE (base) == REG)
            {
              unsigned int base_regno = REGNO (base);
              if (base_regno == ui)             /* register set from itself */
-               reg_base_value[ui] = 0;
+               VARRAY_RTX (reg_base_value, ui) = 0;
              else
-               reg_base_value[ui] = reg_base_value[base_regno];
+               VARRAY_RTX (reg_base_value, ui)
+                 = VARRAY_RTX (reg_base_value, base_regno);
              changed = 1;
            }
        }
@@ -2928,17 +2953,17 @@ init_alias_analysis (void)
 void
 end_alias_analysis (void)
 {
+  old_reg_base_value = reg_base_value;
   free (reg_known_value + FIRST_PSEUDO_REGISTER);
   reg_known_value = 0;
   reg_known_value_size = 0;
   free (reg_known_equiv_p + FIRST_PSEUDO_REGISTER);
   reg_known_equiv_p = 0;
-  reg_base_value = 0;
-  reg_base_value_size = 0;
   if (alias_invariant)
     {
       free (alias_invariant);
       alias_invariant = 0;
+      alias_invariant_size = 0;
     }
 }