OSDN Git Service

* g++.dg/cdce3.C: Require c99 runtime.
[pf3gnuchains/gcc-fork.git] / gcc / regclass.c
index b35dc18..b12d416 100644 (file)
@@ -1,13 +1,13 @@
 /* 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.
 
 GCC is free software; you can redistribute it and/or modify it under
 the terms of the GNU General Public License as published by the Free
-Software Foundation; either version 2, or (at your option) any later
+Software Foundation; either version 3, or (at your option) any later
 version.
 
 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
@@ -16,9 +16,8 @@ FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 for more details.
 
 You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING.  If not, write to the Free
-Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
-02110-1301, USA.  */
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
 
 
 /* This file contains two passes of the compiler: reg_scan and reg_class.
@@ -179,7 +178,7 @@ static enum reg_class reg_class_superclasses[N_REG_CLASSES][N_REG_CLASSES];
 
 /* For each reg class, table listing all the classes contained in it.  */
 
-static enum reg_class reg_class_subclasses[N_REG_CLASSES][N_REG_CLASSES];
+enum reg_class reg_class_subclasses[N_REG_CLASSES][N_REG_CLASSES];
 
 /* For each pair of reg classes,
    a largest reg class contained in their union.  */
@@ -212,24 +211,25 @@ bool have_regs_of_mode [MAX_MACHINE_MODE];
 
 /* 1 if class does contain register of given mode.  */
 
-static char contains_reg_of_mode [N_REG_CLASSES] [MAX_MACHINE_MODE];
-
-typedef unsigned short move_table[N_REG_CLASSES];
+char contains_reg_of_mode [N_REG_CLASSES] [MAX_MACHINE_MODE];
 
 /* Maximum cost of moving from a register in one class to a register in
    another class.  Based on REGISTER_MOVE_COST.  */
 
-static move_table *move_cost[MAX_MACHINE_MODE];
+move_table *move_cost[MAX_MACHINE_MODE];
 
 /* Similar, but here we don't have to move if the first index is a subset
    of the second so in that case the cost is zero.  */
 
-static move_table *may_move_in_cost[MAX_MACHINE_MODE];
+move_table *may_move_in_cost[MAX_MACHINE_MODE];
 
 /* Similar, but here we don't have to move if the first index is a superset
    of the second so in that case the cost is zero.  */
 
-static move_table *may_move_out_cost[MAX_MACHINE_MODE];
+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
 
@@ -263,7 +263,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;
@@ -307,20 +307,14 @@ 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.  */
 
-static void
+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;
 
@@ -340,14 +334,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)
@@ -404,6 +398,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.  */
 
@@ -413,6 +459,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.  */
 
@@ -432,6 +485,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++)
@@ -454,6 +508,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++)
@@ -512,6 +567,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);
 
@@ -565,6 +621,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++)
@@ -583,14 +651,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;
 
@@ -612,8 +702,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)
@@ -644,7 +736,7 @@ init_fake_stack_mems (void)
    Only needed if secondary reloads are required for memory moves.  */
 
 int
-memory_move_secondary_cost (enum machine_mode mode, enum reg_class class, int in)
+memory_move_secondary_cost (enum machine_mode mode, enum reg_class rclass, int in)
 {
   enum reg_class altclass;
   int partial_cost = 0;
@@ -653,17 +745,17 @@ memory_move_secondary_cost (enum machine_mode mode, enum reg_class class, int in
   rtx mem ATTRIBUTE_UNUSED = top_of_stack[(int) mode];
 
 
-  altclass = secondary_reload_class (in ? 1 : 0, class, mode, mem);
+  altclass = secondary_reload_class (in ? 1 : 0, rclass, mode, mem);
 
   if (altclass == NO_REGS)
     return 0;
 
   if (in)
-    partial_cost = REGISTER_MOVE_COST (mode, altclass, class);
+    partial_cost = REGISTER_MOVE_COST (mode, altclass, rclass);
   else
-    partial_cost = REGISTER_MOVE_COST (mode, class, altclass);
+    partial_cost = REGISTER_MOVE_COST (mode, rclass, altclass);
 
-  if (class == altclass)
+  if (rclass == altclass)
     /* This isn't simply a copy-to-temporary situation.  Can't guess
        what it is, so MEMORY_MOVE_COST really ought not to be calling
        here in that case.
@@ -930,6 +1022,7 @@ reg_preferred_class (int regno)
 {
   if (reg_pref == 0)
     return GENERAL_REGS;
+
   return (enum reg_class) reg_pref[regno].prefclass;
 }
 
@@ -965,8 +1058,10 @@ regclass_init (void)
   return 1;
 }
 
-struct tree_opt_pass pass_regclass_init =
+struct rtl_opt_pass pass_regclass_init =
 {
+ {
+  RTL_PASS,
   "regclass",                           /* name */
   NULL,                                 /* gate */
   regclass_init,                        /* execute */
@@ -978,8 +1073,8 @@ struct tree_opt_pass pass_regclass_init =
   0,                                    /* properties_provided */
   0,                                    /* properties_destroyed */
   0,                                    /* todo_flags_start */
-  0,                                    /* todo_flags_finish */
-  'k'                                   /* letter */
+  0                                     /* todo_flags_finish */
+ }
 };
 
 
@@ -991,23 +1086,23 @@ dump_regclass (FILE *dump)
   int i;
   for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
     {
-      int /* enum reg_class */ class;
+      int /* enum reg_class */ rclass;
       if (REG_N_REFS (i))
        {
          fprintf (dump, "  Register %i costs:", i);
-         for (class = 0; class < (int) N_REG_CLASSES; class++)
-           if (contains_reg_of_mode [(enum reg_class) class][PSEUDO_REGNO_MODE (i)]
+         for (rclass = 0; rclass < (int) N_REG_CLASSES; rclass++)
+           if (contains_reg_of_mode [(enum reg_class) rclass][PSEUDO_REGNO_MODE (i)]
 #ifdef FORBIDDEN_INC_DEC_CLASSES
                && (!in_inc_dec[i]
-                   || !forbidden_inc_dec_class[(enum reg_class) class])
+                   || !forbidden_inc_dec_class[(enum reg_class) rclass])
 #endif
 #ifdef CANNOT_CHANGE_MODE_CLASS
-               && ! invalid_mode_change_p (i, (enum reg_class) class,
+               && ! invalid_mode_change_p (i, (enum reg_class) rclass,
                                            PSEUDO_REGNO_MODE (i))
 #endif
                )
-           fprintf (dump, " %s:%i", reg_class_names[class],
-                    costs[i].cost[(enum reg_class) class]);
+           fprintf (dump, " %s:%i", reg_class_names[rclass],
+                    costs[i].cost[(enum reg_class) rclass]);
          fprintf (dump, " MEM:%i\n", costs[i].mem_cost);
        }
     }
@@ -1047,8 +1142,9 @@ record_operand_costs (rtx insn, struct costs *op_costs,
        record_address_regs (GET_MODE (recog_data.operand[i]),
                             XEXP (recog_data.operand[i], 0),
                             0, MEM, SCRATCH, frequency * 2);
-      else if (constraints[i][0] == 'p'
-              || EXTRA_ADDRESS_CONSTRAINT (constraints[i][0], constraints[i]))
+      else if (recog_data.alternative_enabled_p[0]
+              && (constraints[i][0] == 'p'
+                  || EXTRA_ADDRESS_CONSTRAINT (constraints[i][0], constraints[i])))
        record_address_regs (VOIDmode, recog_data.operand[i], 0, ADDRESS,
                             SCRATCH, frequency * 2);
     }
@@ -1158,6 +1254,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);
@@ -1187,7 +1284,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;
@@ -1212,7 +1309,7 @@ regclass (rtx f, int nregs)
 
   init_recog ();
 
-  reg_renumber = xmalloc (max_regno * sizeof (short));
+  reg_renumber = XNEWVEC (short, max_regno);
   reg_pref = XCNEWVEC (struct reg_pref, max_regno);
   memset (reg_renumber, -1, max_regno * sizeof (short));
 
@@ -1284,7 +1381,7 @@ regclass (rtx f, int nregs)
          enum reg_class best = ALL_REGS, alt = NO_REGS;
          /* This is an enum reg_class, but we call it an int
             to save lots of casts.  */
-         int class;
+         int rclass;
          struct costs *p = &costs[i];
 
          if (regno_reg_rtx[i] == NULL)
@@ -1295,27 +1392,27 @@ regclass (rtx f, int nregs)
          if (optimize && !REG_N_REFS (i) && !REG_N_SETS (i))
            continue;
 
-         for (class = (int) ALL_REGS - 1; class > 0; class--)
+         for (rclass = (int) ALL_REGS - 1; rclass > 0; rclass--)
            {
              /* Ignore classes that are too small for this operand or
                 invalid for an operand that was auto-incremented.  */
-             if (!contains_reg_of_mode [class][PSEUDO_REGNO_MODE (i)]
+             if (!contains_reg_of_mode [rclass][PSEUDO_REGNO_MODE (i)]
 #ifdef FORBIDDEN_INC_DEC_CLASSES
-                 || (in_inc_dec[i] && forbidden_inc_dec_class[class])
+                 || (in_inc_dec[i] && forbidden_inc_dec_class[rclass])
 #endif
 #ifdef CANNOT_CHANGE_MODE_CLASS
-                 || invalid_mode_change_p (i, (enum reg_class) class,
+                 || invalid_mode_change_p (i, (enum reg_class) rclass,
                                            PSEUDO_REGNO_MODE (i))
 #endif
                  )
                ;
-             else if (p->cost[class] < best_cost)
+             else if (p->cost[rclass] < best_cost)
                {
-                 best_cost = p->cost[class];
-                 best = (enum reg_class) class;
+                 best_cost = p->cost[rclass];
+                 best = (enum reg_class) rclass;
                }
-             else if (p->cost[class] == best_cost)
-               best = reg_class_subunion[(int) best][class];
+             else if (p->cost[rclass] == best_cost)
+               best = reg_class_subunion[(int) best][rclass];
            }
 
          /* If no register class is better than memory, use memory. */
@@ -1330,19 +1427,19 @@ regclass (rtx f, int nregs)
             will be doing it again later.  */
 
          if ((pass == 1  || dump_file) || ! flag_expensive_optimizations)
-           for (class = 0; class < N_REG_CLASSES; class++)
-             if (p->cost[class] < p->mem_cost
-                 && (reg_class_size[(int) reg_class_subunion[(int) alt][class]]
+           for (rclass = 0; rclass < N_REG_CLASSES; rclass++)
+             if (p->cost[rclass] < p->mem_cost
+                 && (reg_class_size[(int) reg_class_subunion[(int) alt][rclass]]
                      > reg_class_size[(int) alt])
 #ifdef FORBIDDEN_INC_DEC_CLASSES
-                 && ! (in_inc_dec[i] && forbidden_inc_dec_class[class])
+                 && ! (in_inc_dec[i] && forbidden_inc_dec_class[rclass])
 #endif
 #ifdef CANNOT_CHANGE_MODE_CLASS
-                 && ! invalid_mode_change_p (i, (enum reg_class) class,
+                 && ! invalid_mode_change_p (i, (enum reg_class) rclass,
                                              PSEUDO_REGNO_MODE (i))
 #endif
                  )
-               alt = reg_class_subunion[(int) alt][class];
+               alt = reg_class_subunion[(int) alt][rclass];
 
          /* If we don't add any classes, nothing to try.  */
          if (alt == best)
@@ -1419,7 +1516,7 @@ record_reg_classes (int n_alts, int n_ops, rtx *ops,
       int alt_cost = 0;
       enum reg_class classes[MAX_RECOG_OPERANDS];
       int allows_mem[MAX_RECOG_OPERANDS];
-      int class;
+      int rclass;
 
       for (i = 0; i < n_ops; i++)
        {
@@ -1519,17 +1616,17 @@ record_reg_classes (int n_alts, int n_ops, rtx *ops,
                  switch (recog_data.operand_type[i])
                    {
                    case OP_INOUT:
-                     for (class = 0; class < N_REG_CLASSES; class++)
-                       pp->cost[class] = (intable[class][op_class]
-                                          + outtable[op_class][class]);
+                     for (rclass = 0; rclass < N_REG_CLASSES; rclass++)
+                       pp->cost[rclass] = (intable[rclass][op_class]
+                                          + outtable[op_class][rclass]);
                      break;
                    case OP_IN:
-                     for (class = 0; class < N_REG_CLASSES; class++)
-                       pp->cost[class] = intable[class][op_class];
+                     for (rclass = 0; rclass < N_REG_CLASSES; rclass++)
+                       pp->cost[rclass] = intable[rclass][op_class];
                      break;
                    case OP_OUT:
-                     for (class = 0; class < N_REG_CLASSES; class++)
-                       pp->cost[class] = outtable[op_class][class];
+                     for (rclass = 0; rclass < N_REG_CLASSES; rclass++)
+                       pp->cost[rclass] = outtable[op_class][rclass];
                      break;
                    }
 
@@ -1604,7 +1701,7 @@ record_reg_classes (int n_alts, int n_ops, rtx *ops,
                    [(int) base_reg_class (VOIDmode, ADDRESS, SCRATCH)];
                  break;
 
-               case 'm':  case 'o':  case 'V':
+               case TARGET_MEM_CONSTRAINT:  case 'o':  case 'V':
                  /* It doesn't seem worth distinguishing between offsettable
                     and non-offsettable addresses here.  */
                  allows_mem[i] = 1;
@@ -1763,17 +1860,17 @@ record_reg_classes (int n_alts, int n_ops, rtx *ops,
                  switch (recog_data.operand_type[i])
                    {
                    case OP_INOUT:
-                     for (class = 0; class < N_REG_CLASSES; class++)
-                       pp->cost[class] = (intable[class][op_class]
-                                          + outtable[op_class][class]);
+                     for (rclass = 0; rclass < N_REG_CLASSES; rclass++)
+                       pp->cost[rclass] = (intable[rclass][op_class]
+                                          + outtable[op_class][rclass]);
                      break;
                    case OP_IN:
-                     for (class = 0; class < N_REG_CLASSES; class++)
-                       pp->cost[class] = intable[class][op_class];
+                     for (rclass = 0; rclass < N_REG_CLASSES; rclass++)
+                       pp->cost[rclass] = intable[rclass][op_class];
                      break;
                    case OP_OUT:
-                     for (class = 0; class < N_REG_CLASSES; class++)
-                       pp->cost[class] = outtable[op_class][class];
+                     for (rclass = 0; rclass < N_REG_CLASSES; rclass++)
+                       pp->cost[rclass] = outtable[op_class][rclass];
                      break;
                    }
 
@@ -1835,6 +1932,9 @@ record_reg_classes (int n_alts, int n_ops, rtx *ops,
       if (alt_fail)
        continue;
 
+      if (!recog_data.alternative_enabled_p[alt])
+       continue;
+
       /* Finally, update the costs with the information we've calculated
         about this alternative.  */
 
@@ -1848,9 +1948,9 @@ record_reg_classes (int n_alts, int n_ops, rtx *ops,
            pp->mem_cost = MIN (pp->mem_cost,
                                (qq->mem_cost + alt_cost) * scale);
 
-           for (class = 0; class < N_REG_CLASSES; class++)
-             pp->cost[class] = MIN (pp->cost[class],
-                                    (qq->cost[class] + alt_cost) * scale);
+           for (rclass = 0; rclass < N_REG_CLASSES; rclass++)
+             pp->cost[rclass] = MIN (pp->cost[rclass],
+                                    (qq->cost[rclass] + alt_cost) * scale);
          }
     }
 
@@ -1860,7 +1960,7 @@ record_reg_classes (int n_alts, int n_ops, rtx *ops,
      we may want to adjust the cost of that register class to -1.
 
      Avoid the adjustment if the source does not die to avoid stressing of
-     register allocator by preferrencing two colliding registers into single
+     register allocator by preferencing two colliding registers into single
      class.
 
      Also avoid the adjustment if a copy between registers of the class
@@ -1877,7 +1977,7 @@ record_reg_classes (int n_alts, int n_ops, rtx *ops,
        {
          unsigned int regno = REGNO (ops[!i]);
          enum machine_mode mode = GET_MODE (ops[!i]);
-         int class;
+         int rclass;
 
          if (regno >= FIRST_PSEUDO_REGISTER && reg_pref != 0
              && reg_pref[regno].prefclass != NO_REGS)
@@ -1890,15 +1990,15 @@ record_reg_classes (int n_alts, int n_ops, rtx *ops,
                op_costs[i].cost[(unsigned char) pref] = -1;
            }
          else if (regno < FIRST_PSEUDO_REGISTER)
-           for (class = 0; class < N_REG_CLASSES; class++)
-             if (TEST_HARD_REG_BIT (reg_class_contents[class], regno)
-                 && reg_class_size[class] == (unsigned) CLASS_MAX_NREGS (class, mode))
+           for (rclass = 0; rclass < N_REG_CLASSES; rclass++)
+             if (TEST_HARD_REG_BIT (reg_class_contents[rclass], regno)
+                 && reg_class_size[rclass] == (unsigned) CLASS_MAX_NREGS (rclass, mode))
                {
-                 if (reg_class_size[class] == 1)
-                   op_costs[i].cost[class] = -1;
-                 else if (in_hard_reg_set_p (reg_class_contents[class],
+                 if (reg_class_size[rclass] == 1)
+                   op_costs[i].cost[rclass] = -1;
+                 else if (in_hard_reg_set_p (reg_class_contents[rclass],
                                             mode, regno))
-                   op_costs[i].cost[class] = -1;
+                   op_costs[i].cost[rclass] = -1;
                }
        }
 }
@@ -1909,7 +2009,7 @@ record_reg_classes (int n_alts, int n_ops, rtx *ops,
    X must not be a pseudo.  */
 
 static int
-copy_cost (rtx x, enum machine_mode mode, enum reg_class class, int to_p,
+copy_cost (rtx x, enum machine_mode mode, enum reg_class rclass, int to_p,
           secondary_reload_info *prev_sri)
 {
   enum reg_class secondary_class = NO_REGS;
@@ -1922,7 +2022,7 @@ copy_cost (rtx x, enum machine_mode mode, enum reg_class class, int to_p,
     return 0;
 
   /* Get the class we will actually use for a reload.  */
-  class = PREFERRED_RELOAD_CLASS (x, class);
+  rclass = PREFERRED_RELOAD_CLASS (x, rclass);
 
   /* If we need a secondary reload for an intermediate, the
      cost is that to load the input into the intermediate register, then
@@ -1930,13 +2030,13 @@ copy_cost (rtx x, enum machine_mode mode, enum reg_class class, int to_p,
 
   sri.prev_sri = prev_sri;
   sri.extra_cost = 0;
-  secondary_class = targetm.secondary_reload (to_p, x, class, mode, &sri);
+  secondary_class = targetm.secondary_reload (to_p, x, rclass, mode, &sri);
 
   if (!move_cost[mode])
     init_move_cost (mode);
 
   if (secondary_class != NO_REGS)
-    return (move_cost[mode][(int) secondary_class][(int) class]
+    return (move_cost[mode][(int) secondary_class][(int) rclass]
            + sri.extra_cost
            + copy_cost (x, mode, secondary_class, to_p, &sri));
 
@@ -1944,12 +2044,12 @@ copy_cost (rtx x, enum machine_mode mode, enum reg_class class, int to_p,
      cost to move between the register classes, and use 2 for everything
      else (constants).  */
 
-  if (MEM_P (x) || class == NO_REGS)
-    return sri.extra_cost + MEMORY_MOVE_COST (mode, class, to_p);
+  if (MEM_P (x) || rclass == NO_REGS)
+    return sri.extra_cost + MEMORY_MOVE_COST (mode, rclass, to_p);
 
   else if (REG_P (x))
     return (sri.extra_cost
-           + move_cost[mode][(int) REGNO_REG_CLASS (REGNO (x))][(int) class]);
+           + move_cost[mode][(int) REGNO_REG_CLASS (REGNO (x))][(int) rclass]);
 
   else
     /* If this is a constant, we may eventually want to call rtx_cost here.  */
@@ -1975,12 +2075,12 @@ record_address_regs (enum machine_mode mode, rtx x, int context,
                     int scale)
 {
   enum rtx_code code = GET_CODE (x);
-  enum reg_class class;
+  enum reg_class rclass;
 
   if (context == 1)
-    class = INDEX_REG_CLASS;
+    rclass = INDEX_REG_CLASS;
   else
-    class = base_reg_class (mode, outer_code, index_code);
+    rclass = base_reg_class (mode, outer_code, index_code);
 
   switch (code)
     {
@@ -2133,12 +2233,12 @@ record_address_regs (enum machine_mode mode, rtx x, int context,
        struct costs *pp = &costs[REGNO (x)];
        int i;
 
-       pp->mem_cost += (MEMORY_MOVE_COST (Pmode, class, 1) * scale) / 2;
+       pp->mem_cost += (MEMORY_MOVE_COST (Pmode, rclass, 1) * scale) / 2;
 
        if (!move_cost[Pmode])
          init_move_cost (Pmode);
        for (i = 0; i < N_REG_CLASSES; i++)
-         pp->cost[i] += (may_move_in_cost[Pmode][i][(int) class] * scale) / 2;
+         pp->cost[i] += (may_move_in_cost[Pmode][i][(int) rclass] * scale) / 2;
       }
       break;
 
@@ -2182,6 +2282,32 @@ auto_inc_dec_reg_p (rtx reg, enum machine_mode mode)
 }
 #endif
 \f
+
+/* Allocate space for reg info.  */
+void
+allocate_reg_info (void)
+{
+  int size = max_reg_num ();
+
+  gcc_assert (! reg_pref && ! reg_renumber);
+  reg_renumber = XNEWVEC (short, size);
+  reg_pref = XCNEWVEC (struct reg_pref, size);
+  memset (reg_renumber, -1, size * sizeof (short));
+}
+
+
+/* Resize reg info. The new elements will be uninitialized.  */
+void
+resize_reg_info (void)
+{
+  int size = max_reg_num ();
+
+  gcc_assert (reg_pref && reg_renumber);
+  reg_renumber = XRESIZEVEC (short, reg_renumber, size);
+  reg_pref = XRESIZEVEC (struct reg_pref, reg_pref, size);
+}
+
+
 /* Free up the space allocated by allocate_reg_info.  */
 void
 free_reg_info (void)
@@ -2199,6 +2325,21 @@ free_reg_info (void)
     }
 }
 
+
+\f
+
+/* Set up preferred and alternate classes for REGNO as PREFCLASS and
+   ALTCLASS.  */
+void
+setup_reg_classes (int regno,
+                  enum reg_class prefclass, enum reg_class altclass)
+{
+  if (reg_pref == NULL)
+    return;
+  reg_pref[regno].prefclass = prefclass;
+  reg_pref[regno].altclass = altclass;
+}
+
 \f
 /* This is the `regscan' pass of the compiler, run just before cse and
    again just before loop.  It finds the first and last use of each
@@ -2228,8 +2369,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)
 {
@@ -2245,6 +2384,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:
@@ -2339,10 +2479,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 ...  */
@@ -2403,15 +2540,18 @@ static htab_t subregs_of_mode;
 static hashval_t
 som_hash (const void *x)
 {
-  const struct subregs_of_mode_node *a = x;
+  const struct subregs_of_mode_node *const a =
+    (const struct subregs_of_mode_node *) x;
   return a->block;
 }
 
 static int
 som_eq (const void *x, const void *y)
 {
-  const struct subregs_of_mode_node *a = x;
-  const struct subregs_of_mode_node *b = y;
+  const struct subregs_of_mode_node *const a =
+    (const struct subregs_of_mode_node *) x;
+  const struct subregs_of_mode_node *const b =
+    (const struct subregs_of_mode_node *) y;
   return a->block == b->block;
 }
 
@@ -2436,7 +2576,7 @@ record_subregs_of_mode (rtx subreg)
   dummy.block = regno & -8;
   slot = htab_find_slot_with_hash (subregs_of_mode, &dummy,
                                   dummy.block, INSERT);
-  node = *slot;
+  node = (struct subregs_of_mode_node *) *slot;
   if (node == NULL)
     {
       node = XCNEW (struct subregs_of_mode_node);
@@ -2508,7 +2648,8 @@ cannot_change_mode_set_regs (HARD_REG_SET *used, enum machine_mode from,
 
   gcc_assert (subregs_of_mode);
   dummy.block = regno & -8;
-  node = htab_find_with_hash (subregs_of_mode, &dummy, dummy.block);
+  node = (struct subregs_of_mode_node *)
+    htab_find_with_hash (subregs_of_mode, &dummy, dummy.block);
   if (node == NULL)
     return;
 
@@ -2526,7 +2667,7 @@ cannot_change_mode_set_regs (HARD_REG_SET *used, enum machine_mode from,
 
 bool
 invalid_mode_change_p (unsigned int regno,
-                      enum reg_class class ATTRIBUTE_UNUSED,
+                      enum reg_class rclass ATTRIBUTE_UNUSED,
                       enum machine_mode from)
 {
   struct subregs_of_mode_node dummy, *node;
@@ -2535,14 +2676,15 @@ invalid_mode_change_p (unsigned int regno,
 
   gcc_assert (subregs_of_mode);
   dummy.block = regno & -8;
-  node = htab_find_with_hash (subregs_of_mode, &dummy, dummy.block);
+  node = (struct subregs_of_mode_node *)
+    htab_find_with_hash (subregs_of_mode, &dummy, dummy.block);
   if (node == NULL)
     return false;
 
   mask = 1 << (regno & 7);
   for (to = VOIDmode; to < NUM_MACHINE_MODES; to++)
     if (node->modes[to] & mask)
-      if (CANNOT_CHANGE_MODE_CLASS (from, to, class))
+      if (CANNOT_CHANGE_MODE_CLASS (from, to, rclass))
        return true;
 
   return false;
@@ -2579,8 +2721,10 @@ gate_subregs_of_mode_init (void)
 #endif
 }
 
-struct tree_opt_pass pass_subregs_of_mode_init =
+struct rtl_opt_pass pass_subregs_of_mode_init =
 {
+ {
+  RTL_PASS,
   "subregs_of_mode_init",               /* name */
   gate_subregs_of_mode_init,            /* gate */
   init_subregs_of_mode,                 /* execute */
@@ -2592,12 +2736,14 @@ struct tree_opt_pass pass_subregs_of_mode_init =
   0,                                    /* properties_provided */
   0,                                    /* properties_destroyed */
   0,                                    /* todo_flags_start */
-  0,                                    /* todo_flags_finish */
-  0                                     /* letter */
+  0                                     /* todo_flags_finish */
+ }
 };
 
-struct tree_opt_pass pass_subregs_of_mode_finish =
+struct rtl_opt_pass pass_subregs_of_mode_finish =
 {
+ {
+  RTL_PASS,
   "subregs_of_mode_finish",               /* name */
   gate_subregs_of_mode_init,            /* gate */
   finish_subregs_of_mode,               /* execute */
@@ -2609,8 +2755,8 @@ struct tree_opt_pass pass_subregs_of_mode_finish =
   0,                                    /* properties_provided */
   0,                                    /* properties_destroyed */
   0,                                    /* todo_flags_start */
-  0,                                    /* todo_flags_finish */
-  0                                     /* letter */
+  0                                     /* todo_flags_finish */
+ }
 };