OSDN Git Service

* dwarf2out.c (dwarf2out_frame_debug_expr): Consult the
[pf3gnuchains/gcc-fork.git] / gcc / regclass.c
index c80cc6f..911a19a 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, 2006, 2007
+   1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
    Free Software Foundation, Inc.
 
 This file is part of GCC.
@@ -230,6 +230,9 @@ static move_table *may_move_in_cost[MAX_MACHINE_MODE];
 
 static move_table *may_move_out_cost[MAX_MACHINE_MODE];
 
+/* Keep track of the last mode we initialized move costs for.  */
+static int last_mode_for_init_move_cost;
+
 #ifdef FORBIDDEN_INC_DEC_CLASSES
 
 /* These are the classes that regs which are auto-incremented or decremented
@@ -262,7 +265,7 @@ unsigned char hard_regno_nregs[FIRST_PSEUDO_REGISTER][MAX_MACHINE_MODE];
    with moving single words, but probably isn't worth the trouble.  */
 
 void
-reg_set_to_hard_reg_set (HARD_REG_SET *to, bitmap from)
+reg_set_to_hard_reg_set (HARD_REG_SET *to, const_bitmap from)
 {
   unsigned i;
   bitmap_iterator bi;
@@ -306,11 +309,6 @@ init_reg_sets (void)
   memcpy (fixed_regs, initial_fixed_regs, sizeof fixed_regs);
   memcpy (call_used_regs, initial_call_used_regs, sizeof call_used_regs);
   memset (global_regs, 0, sizeof global_regs);
-
-#ifdef REG_ALLOC_ORDER
-  for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
-    inv_reg_alloc_order[reg_alloc_order[i]] = i;
-#endif
 }
 
 /* Initialize may_move_cost and friends for mode M.  */
@@ -319,7 +317,6 @@ static void
 init_move_cost (enum machine_mode m)
 {
   static unsigned short last_move_cost[N_REG_CLASSES][N_REG_CLASSES];
-  static int last_mode = -1;
   bool all_match = true;
   unsigned int i, j;
 
@@ -339,14 +336,14 @@ init_move_cost (enum machine_mode m)
          all_match &= (last_move_cost[i][j] == cost);
          last_move_cost[i][j] = cost;
        }
-  if (all_match && last_mode != -1)
+  if (all_match && last_mode_for_init_move_cost != -1)
     {
-      move_cost[m] = move_cost[last_mode];
-      may_move_in_cost[m] = may_move_in_cost[last_mode];
-      may_move_out_cost[m] = may_move_out_cost[last_mode];
+      move_cost[m] = move_cost[last_mode_for_init_move_cost];
+      may_move_in_cost[m] = may_move_in_cost[last_mode_for_init_move_cost];
+      may_move_out_cost[m] = may_move_out_cost[last_mode_for_init_move_cost];
       return;
     }
-  last_mode = m;
+  last_mode_for_init_move_cost = m;
   move_cost[m] = (move_table *)xmalloc (sizeof (move_table)
                                        * N_REG_CLASSES);
   may_move_in_cost[m] = (move_table *)xmalloc (sizeof (move_table)
@@ -403,6 +400,58 @@ init_move_cost (enum machine_mode m)
        }
 }
 
+/* We need to save copies of some of the register information which
+   can be munged by command-line switches so we can restore it during
+   subsequent back-end reinitialization.  */
+
+static char saved_fixed_regs[FIRST_PSEUDO_REGISTER];
+static char saved_call_used_regs[FIRST_PSEUDO_REGISTER];
+#ifdef CALL_REALLY_USED_REGISTERS
+static char saved_call_really_used_regs[FIRST_PSEUDO_REGISTER];
+#endif
+static const char *saved_reg_names[FIRST_PSEUDO_REGISTER];
+
+/* Save the register information.  */
+
+void
+save_register_info (void)
+{
+  /* Sanity check:  make sure the target macros FIXED_REGISTERS and
+     CALL_USED_REGISTERS had the right number of initializers.  */
+  gcc_assert (sizeof fixed_regs == sizeof saved_fixed_regs);
+  gcc_assert (sizeof call_used_regs == sizeof saved_call_used_regs);
+  memcpy (saved_fixed_regs, fixed_regs, sizeof fixed_regs);
+  memcpy (saved_call_used_regs, call_used_regs, sizeof call_used_regs);
+
+  /* Likewise for call_really_used_regs.  */
+#ifdef CALL_REALLY_USED_REGISTERS
+  gcc_assert (sizeof call_really_used_regs
+             == sizeof saved_call_really_used_regs);
+  memcpy (saved_call_really_used_regs, call_really_used_regs,
+         sizeof call_really_used_regs);
+#endif
+
+  /* And similarly for reg_names.  */
+  gcc_assert (sizeof reg_names == sizeof saved_reg_names);
+  memcpy (saved_reg_names, reg_names, sizeof reg_names);
+}
+
+/* Restore the register information.  */
+
+static void
+restore_register_info (void)
+{
+  memcpy (fixed_regs, saved_fixed_regs, sizeof fixed_regs);
+  memcpy (call_used_regs, saved_call_used_regs, sizeof call_used_regs);
+
+#ifdef CALL_REALLY_USED_REGISTERS
+  memcpy (call_really_used_regs, saved_call_really_used_regs,
+         sizeof call_really_used_regs);
+#endif
+
+  memcpy (reg_names, saved_reg_names, sizeof reg_names);
+}
+
 /* After switches have been processed, which perhaps alter
    `fixed_regs' and `call_used_regs', convert them to HARD_REG_SETs.  */
 
@@ -412,6 +461,13 @@ init_reg_sets_1 (void)
   unsigned int i, j;
   unsigned int /* enum machine_mode */ m;
 
+  restore_register_info ();
+
+#ifdef REG_ALLOC_ORDER
+  for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+    inv_reg_alloc_order[reg_alloc_order[i]] = i;
+#endif
+
   /* This macro allows the fixed or call-used registers
      and the register classes to depend on target flags.  */
 
@@ -431,6 +487,7 @@ init_reg_sets_1 (void)
      reg_class_subunion[I][J] gets the largest-numbered reg-class
      that is contained in the union of classes I and J.  */
 
+  memset (reg_class_subunion, 0, sizeof reg_class_subunion);
   for (i = 0; i < N_REG_CLASSES; i++)
     {
       for (j = 0; j < N_REG_CLASSES; j++)
@@ -453,6 +510,7 @@ init_reg_sets_1 (void)
      reg_class_superunion[I][J] gets the smallest-numbered reg-class
      containing the union of classes I and J.  */
 
+  memset (reg_class_superunion, 0, sizeof reg_class_superunion);
   for (i = 0; i < N_REG_CLASSES; i++)
     {
       for (j = 0; j < N_REG_CLASSES; j++)
@@ -511,6 +569,7 @@ init_reg_sets_1 (void)
   CLEAR_HARD_REG_SET (call_used_reg_set);
   CLEAR_HARD_REG_SET (call_fixed_reg_set);
   CLEAR_HARD_REG_SET (regs_invalidated_by_call);
+  CLEAR_HARD_REG_SET (losing_caller_save_reg_set);
 
   memcpy (call_fixed_regs, fixed_regs, sizeof call_fixed_regs);
 
@@ -564,6 +623,18 @@ init_reg_sets_1 (void)
        SET_HARD_REG_BIT (regs_invalidated_by_call, i);
     }
 
+  /* Preserve global registers if called more than once.  */
+  for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+    {
+      if (global_regs[i])
+       {
+         fixed_regs[i] = call_used_regs[i] = call_fixed_regs[i] = 1;
+         SET_HARD_REG_BIT (fixed_reg_set, i);
+         SET_HARD_REG_BIT (call_used_reg_set, i);
+         SET_HARD_REG_BIT (call_fixed_reg_set, i);
+       }
+    }
+
   memset (have_regs_of_mode, 0, sizeof (have_regs_of_mode));
   memset (contains_reg_of_mode, 0, sizeof (contains_reg_of_mode));
   for (m = 0; m < (unsigned int) MAX_MACHINE_MODE; m++)
@@ -582,14 +653,36 @@ init_reg_sets_1 (void)
             have_regs_of_mode [m] = 1;
          }
      }
+
+  /* Reset move_cost and friends, making sure we only free shared
+     table entries once.  */
+  for (i = 0; i < MAX_MACHINE_MODE; i++)
+    if (move_cost[i])
+      {
+       for (j = 0; j < i && move_cost[i] != move_cost[j]; j++)
+         ;
+       if (i == j)
+         {
+           free (move_cost[i]);
+           free (may_move_in_cost[i]);
+           free (may_move_out_cost[i]);
+         }
+      }
+  memset (move_cost, 0, sizeof move_cost);
+  memset (may_move_in_cost, 0, sizeof may_move_in_cost);
+  memset (may_move_out_cost, 0, sizeof may_move_out_cost);
+  last_mode_for_init_move_cost = -1;
 }
 
 /* Compute the table of register modes.
    These values are used to record death information for individual registers
-   (as opposed to a multi-register mode).  */
+   (as opposed to a multi-register mode).
+   This function might be invoked more than once, if the target has support
+   for changing register usage conventions on a per-function basis.
+*/
 
 void
-init_reg_modes_once (void)
+init_reg_modes_target (void)
 {
   int i, j;
 
@@ -611,8 +704,10 @@ init_reg_modes_once (void)
     }
 }
 
-/* Finish initializing the register sets and
-   initialize the register modes.  */
+/* Finish initializing the register sets and initialize the register modes.
+   This function might be invoked more than once, if the target has support
+   for changing register usage conventions on a per-function basis.
+*/
 
 void
 init_regs (void)
@@ -1157,6 +1252,7 @@ init_reg_autoinc (void)
 #ifdef FORBIDDEN_INC_DEC_CLASSES
   int i;
 
+  memset (forbidden_inc_dec_class, 0, sizeof forbidden_inc_dec_class);
   for (i = 0; i < N_REG_CLASSES; i++)
     {
       rtx r = gen_rtx_raw_REG (VOIDmode, 0);
@@ -1186,7 +1282,7 @@ init_reg_autoinc (void)
                     requires secondary reloads, disallow its class from
                     being used in such addresses.  */
 
-                 if ((secondary_reload_class (1, base_class, m, r)
+                 if ((secondary_reload_class (0, base_class, m, r)
                       || secondary_reload_class (1, base_class, m, r))
                      && ! auto_inc_dec_reg_p (r, m))
                    forbidden_inc_dec_class[i] = 1;
@@ -2227,8 +2323,6 @@ reg_scan (rtx f, unsigned int nregs ATTRIBUTE_UNUSED)
    We should only record information for REGs with numbers
    greater than or equal to MIN_REGNO.  */
 
-extern struct tree_opt_pass *current_pass;
-
 static void
 reg_scan_mark_refs (rtx x, rtx insn)
 {
@@ -2244,6 +2338,7 @@ reg_scan_mark_refs (rtx x, rtx insn)
     case CONST:
     case CONST_INT:
     case CONST_DOUBLE:
+    case CONST_FIXED:
     case CONST_VECTOR:
     case CC0:
     case PC:
@@ -2338,10 +2433,7 @@ reg_scan_mark_refs (rtx x, rtx insn)
                 || (GET_CODE (src) == SUBREG && subreg_lowpart_p (src)))
            src = XEXP (src, 0);
 
-         if (REG_P (src))
-           REG_ATTRS (dest) = REG_ATTRS (src);
-         if (MEM_P (src))
-           set_reg_attrs_from_mem (dest, src);
+         set_reg_attrs_from_value (dest, src);
        }
 
       /* ... fall through ...  */