OSDN Git Service

Use C fixincludes for UnixWare 7.
[pf3gnuchains/gcc-fork.git] / gcc / regclass.c
index d1bcf30..3b07c13 100644 (file)
@@ -1,5 +1,6 @@
 /* Compute register class preferences for pseudo-registers.
-   Copyright (C) 1987, 88, 91-98, 1999, 2000 Free Software Foundation, Inc.
+   Copyright (C) 1987, 1988, 1991, 1992, 1993, 1994, 1995, 1996
+   1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
 
 This file is part of GNU CC.
 
@@ -41,11 +42,11 @@ Boston, MA 02111-1307, USA.  */
 #include "ggc.h"
 
 #ifndef REGISTER_MOVE_COST
-#define REGISTER_MOVE_COST(x, y) 2
+#define REGISTER_MOVE_COST(m, x, y) 2
 #endif
 
-static void init_reg_sets_1    PROTO((void));
-static void init_reg_modes     PROTO((void));
+static void init_reg_sets_1    PARAMS ((void));
+static void init_reg_modes     PARAMS ((void));
 
 /* If we have auto-increment or auto-decrement and we can have secondary
    reloads, we are not allowed to use classes requiring secondary
@@ -139,7 +140,7 @@ static unsigned int_reg_class_contents[N_REG_CLASSES][N_REG_INTS]
 
 /* For each reg class, number of regs it contains.  */
 
-int reg_class_size[N_REG_CLASSES];
+unsigned int reg_class_size[N_REG_CLASSES];
 
 /* For each reg class, table listing all the containing classes.  */
 
@@ -159,9 +160,12 @@ enum reg_class reg_class_subunion[N_REG_CLASSES][N_REG_CLASSES];
 
 enum reg_class reg_class_superunion[N_REG_CLASSES][N_REG_CLASSES];
 
-/* Array containing all of the register names */
+/* Array containing all of the register names.  Unless
+   DEBUG_REGISTER_NAMES is defined, use the copy in print-rtl.c.  */
 
-const char *reg_names[] = REGISTER_NAMES;
+#ifdef DEBUG_REGISTER_NAMES
+const char * reg_names[] = REGISTER_NAMES;
+#endif
 
 /* For each hard register, the widest mode object that it can contain.
    This will be a MODE_INT mode if the register can hold integers.  Otherwise
@@ -173,17 +177,17 @@ enum machine_mode reg_raw_mode[FIRST_PSEUDO_REGISTER];
 /* Maximum cost of moving from a register in one class to a register in
    another class.  Based on REGISTER_MOVE_COST.  */
 
-static int move_cost[N_REG_CLASSES][N_REG_CLASSES];
+static int move_cost[MAX_MACHINE_MODE][N_REG_CLASSES][N_REG_CLASSES];
 
 /* 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 int may_move_in_cost[N_REG_CLASSES][N_REG_CLASSES];
+static int may_move_in_cost[MAX_MACHINE_MODE][N_REG_CLASSES][N_REG_CLASSES];
 
 /* 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 int may_move_out_cost[N_REG_CLASSES][N_REG_CLASSES];
+static int may_move_out_cost[MAX_MACHINE_MODE][N_REG_CLASSES][N_REG_CLASSES];
 
 #ifdef FORBIDDEN_INC_DEC_CLASSES
 
@@ -199,6 +203,21 @@ static char *in_inc_dec;
 
 #endif /* FORBIDDEN_INC_DEC_CLASSES */
 
+#ifdef CLASS_CANNOT_CHANGE_MODE
+
+/* These are the classes containing only registers that can be used in
+   a SUBREG expression that changes the mode of the register in some
+   way that is illegal.  */
+
+static int class_can_change_mode[N_REG_CLASSES];
+
+/* Registers, including pseudos, which change modes in some way that
+   is illegal.  */
+
+static regset reg_changes_mode;
+
+#endif /* CLASS_CANNOT_CHANGE_MODE */
+
 #ifdef HAVE_SECONDARY_RELOADS
 
 /* Sample MEM values for use by memory_move_secondary_cost.  */
@@ -248,9 +267,9 @@ init_reg_sets ()
          SET_HARD_REG_BIT (reg_class_contents[i], j);
     }
 
-  bcopy (initial_fixed_regs, fixed_regs, sizeof fixed_regs);
-  bcopy (initial_call_used_regs, call_used_regs, sizeof call_used_regs);
-  bzero (global_regs, sizeof global_regs);
+  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);
 
   /* Do any additional initialization regsets may need */
   INIT_ONCE_REG_SET ();
@@ -268,6 +287,9 @@ static void
 init_reg_sets_1 ()
 {
   register unsigned int i, j;
+  register unsigned int /* enum machine_mode */ m;
+  char contains_reg_of_mode [N_REG_CLASSES] [MAX_MACHINE_MODE];
+  char allocatable_regs_of_mode [MAX_MACHINE_MODE];
 
   /* This macro allows the fixed or call-used registers
      and the register classes to depend on target flags.  */
@@ -278,7 +300,7 @@ init_reg_sets_1 ()
 
   /* Compute number of hard regs in each class.  */
 
-  bzero ((char *) reg_class_size, sizeof reg_class_size);
+  memset ((char *) reg_class_size, 0, sizeof reg_class_size);
   for (i = 0; i < N_REG_CLASSES; i++)
     for (j = 0; j < FIRST_PSEUDO_REGISTER; j++)
       if (TEST_HARD_REG_BIT (reg_class_contents[i], j))
@@ -385,7 +407,7 @@ init_reg_sets_1 ()
   CLEAR_HARD_REG_SET (call_used_reg_set);
   CLEAR_HARD_REG_SET (call_fixed_reg_set);
 
-  bcopy (fixed_regs, call_fixed_regs, sizeof call_fixed_regs);
+  memcpy (call_fixed_regs, fixed_regs, sizeof call_fixed_regs);
 
   n_non_fixed_regs = 0;
 
@@ -403,43 +425,91 @@ init_reg_sets_1 ()
       if (CLASS_LIKELY_SPILLED_P (REGNO_REG_CLASS (i)))
        SET_HARD_REG_BIT (losing_caller_save_reg_set, i);
     }
+  memset (contains_reg_of_mode, 0, sizeof (contains_reg_of_mode));
+  memset (allocatable_regs_of_mode, 0, sizeof (allocatable_regs_of_mode));
+  for (m = 0; m < MAX_MACHINE_MODE; m++)
+    for (i = 0; i < N_REG_CLASSES; i++)
+      for (j = 0; j < FIRST_PSEUDO_REGISTER; j++)
+       if (!fixed_regs [j] && TEST_HARD_REG_BIT (reg_class_contents[i], j)
+           && HARD_REGNO_MODE_OK (j, m))
+          {
+            contains_reg_of_mode [i][m] = 1;
+            allocatable_regs_of_mode [m] = 1;
+            break;
+          }
 
   /* Initialize the move cost table.  Find every subset of each class
      and take the maximum cost of moving any subset to any other.  */
 
-  for (i = 0; i < N_REG_CLASSES; i++)
-    for (j = 0; j < N_REG_CLASSES; j++)
+  for (m = 0; m < MAX_MACHINE_MODE; m++)
+    if (allocatable_regs_of_mode [m])
       {
-       int cost = i == j ? 2 : REGISTER_MOVE_COST (i, j);
-       enum reg_class *p1, *p2;
-
-       for (p2 = &reg_class_subclasses[j][0]; *p2 != LIM_REG_CLASSES; p2++)
-         if (*p2 != i)
-           cost = MAX (cost, REGISTER_MOVE_COST (i, *p2));
-
-       for (p1 = &reg_class_subclasses[i][0]; *p1 != LIM_REG_CLASSES; p1++)
-         {
-           if (*p1 != j)
-             cost = MAX (cost, REGISTER_MOVE_COST (*p1, j));
-
-           for (p2 = &reg_class_subclasses[j][0];
-                *p2 != LIM_REG_CLASSES; p2++)
-             if (*p1 != *p2)
-               cost = MAX (cost, REGISTER_MOVE_COST (*p1, *p2));
-         }
-
-       move_cost[i][j] = cost;
-
-       if (reg_class_subset_p (i, j))
-         may_move_in_cost[i][j] = 0;
-       else
-         may_move_in_cost[i][j] = cost;
+       for (i = 0; i < N_REG_CLASSES; i++)
+         if (contains_reg_of_mode [i][m])
+           for (j = 0; j < N_REG_CLASSES; j++)
+             {
+               int cost;
+               enum reg_class *p1, *p2;
+
+               if (!contains_reg_of_mode [j][m])
+                 {
+                   move_cost[m][i][j] = 65536;
+                   may_move_in_cost[m][i][j] = 65536;
+                   may_move_out_cost[m][i][j] = 65536;
+                 }
+               else
+                 {
+                   cost = i == j ? 2 : REGISTER_MOVE_COST (m, i, j);
+
+                   for (p2 = &reg_class_subclasses[j][0];
+                        *p2 != LIM_REG_CLASSES;
+                        p2++)
+                     if (*p2 != i && contains_reg_of_mode [*p2][m])
+                       cost = MAX (cost, move_cost [m][i][*p2]);
+
+                   for (p1 = &reg_class_subclasses[i][0];
+                        *p1 != LIM_REG_CLASSES;
+                        p1++)
+                     if (*p1 != j && contains_reg_of_mode [*p1][m])
+                       cost = MAX (cost, move_cost [m][*p1][j]);
+
+                   move_cost[m][i][j] = cost;
+
+                   if (reg_class_subset_p (i, j))
+                     may_move_in_cost[m][i][j] = 0;
+                   else
+                     may_move_in_cost[m][i][j] = cost;
+
+                   if (reg_class_subset_p (j, i))
+                     may_move_out_cost[m][i][j] = 0;
+                   else
+                     may_move_out_cost[m][i][j] = cost;
+                 }
+             }
+         else
+           for (j = 0; j < N_REG_CLASSES; j++)
+             {
+               move_cost[m][i][j] = 65536;
+               may_move_in_cost[m][i][j] = 65536;
+               may_move_out_cost[m][i][j] = 65536;
+             }
+      }
 
-       if (reg_class_subset_p (j, i))
-         may_move_out_cost[i][j] = 0;
-       else
-         may_move_out_cost[i][j] = cost;
+#ifdef CLASS_CANNOT_CHANGE_MODE
+  {
+    HARD_REG_SET c;
+    COMPL_HARD_REG_SET (c, reg_class_contents[CLASS_CANNOT_CHANGE_MODE]);
+      
+    for (i = 0; i < N_REG_CLASSES; i++)
+      {
+       GO_IF_HARD_REG_SUBSET (reg_class_contents[i], c, ok_class);
+       class_can_change_mode [i] = 0;
+       continue;
+      ok_class:
+       class_can_change_mode [i] = 1;
       }
+    }
+#endif /* CLASS_CANNOT_CHANGE_MODE */
 }
 
 /* Compute the table of register modes.
@@ -482,6 +552,7 @@ init_regs ()
     /* Make some fake stack-frame MEM references for use in
        memory_move_secondary_cost.  */
     int i;
+
     for (i = 0; i < MAX_MACHINE_MODE; i++)
       top_of_stack[i] = gen_rtx_MEM (i, stack_pointer_rtx);
     ggc_add_rtx_root (top_of_stack, MAX_MACHINE_MODE);
@@ -528,9 +599,9 @@ memory_move_secondary_cost (mode, class, in)
     return 0;
 
   if (in)
-    partial_cost = REGISTER_MOVE_COST (altclass, class);
+    partial_cost = REGISTER_MOVE_COST (mode, altclass, class);
   else
-    partial_cost = REGISTER_MOVE_COST (class, altclass);
+    partial_cost = REGISTER_MOVE_COST (mode, class, altclass);
 
   if (class == altclass)
     /* This isn't simply a copy-to-temporary situation.  Can't guess
@@ -553,8 +624,8 @@ memory_move_secondary_cost (mode, class, in)
 
 enum machine_mode
 choose_hard_reg_mode (regno, nregs)
-     int regno;
-     int nregs;
+     unsigned int regno ATTRIBUTE_UNUSED;
+     unsigned int nregs;
 {
   enum machine_mode found_mode = VOIDmode, mode;
 
@@ -582,9 +653,11 @@ choose_hard_reg_mode (regno, nregs)
   if (found_mode != VOIDmode)
     return found_mode;
 
-  if (HARD_REGNO_NREGS (regno, CCmode) == nregs
-      && HARD_REGNO_MODE_OK (regno, CCmode))
-    return CCmode;
+  /* Iterate over all of the CCmodes.  */
+  for (mode = CCmode; mode < NUM_MACHINE_MODES; ++mode)
+    if (HARD_REGNO_NREGS (regno, mode) == nregs
+        && HARD_REGNO_MODE_OK (regno, mode))
+    return mode;
 
   /* We can't find a mode valid for this register.  */
   return VOIDmode;
@@ -717,19 +790,19 @@ static struct reg_pref *reg_pref_buffer;
 
 static int loop_cost;
 
-static rtx scan_one_insn       PROTO((rtx, int));
-static void record_operand_costs PROTO((rtx, struct costs *, struct reg_pref *));
-static void dump_regclass      PROTO((FILE *));
-static void record_reg_classes PROTO((int, int, rtx *, enum machine_mode *,
-                                      char *, const char **, rtx,
+static rtx scan_one_insn       PARAMS ((rtx, int));
+static void record_operand_costs PARAMS ((rtx, struct costs *, struct reg_pref *));
+static void dump_regclass      PARAMS ((FILE *));
+static void record_reg_classes PARAMS ((int, int, rtx *, enum machine_mode *,
+                                      const char **, rtx,
                                       struct costs *, struct reg_pref *));
-static int copy_cost           PROTO((rtx, enum machine_mode, 
+static int copy_cost           PARAMS ((rtx, enum machine_mode, 
                                       enum reg_class, int));
-static void record_address_regs        PROTO((rtx, enum reg_class, int));
+static void record_address_regs        PARAMS ((rtx, enum reg_class, int));
 #ifdef FORBIDDEN_INC_DEC_CLASSES
-static int auto_inc_dec_reg_p  PROTO((rtx, enum machine_mode));
+static int auto_inc_dec_reg_p  PARAMS ((rtx, enum machine_mode));
 #endif
-static void reg_scan_mark_refs PROTO((rtx, rtx, int, int));
+static void reg_scan_mark_refs PARAMS ((rtx, rtx, int, unsigned int));
 
 /* Return the reg_class in which pseudo reg number REGNO is best allocated.
    This function is sometimes called before the info has been computed.
@@ -805,7 +878,6 @@ record_operand_costs (insn, op_costs, reg_pref)
 {
   const char *constraints[MAX_RECOG_OPERANDS];
   enum machine_mode modes[MAX_RECOG_OPERANDS];
-  char subreg_changes_size[MAX_RECOG_OPERANDS];
   int i;
 
   for (i = 0; i < recog_data.n_operands; i++)
@@ -813,7 +885,6 @@ record_operand_costs (insn, op_costs, reg_pref)
       constraints[i] = recog_data.constraints[i];
       modes[i] = recog_data.operand_mode[i];
     }
-  memset (subreg_changes_size, 0, sizeof (subreg_changes_size));
 
   /* If we get here, we are set up to record the costs of all the
      operands for this insn.  Start by initializing the costs.
@@ -828,8 +899,11 @@ record_operand_costs (insn, op_costs, reg_pref)
       if (GET_CODE (recog_data.operand[i]) == SUBREG)
        {
          rtx inner = SUBREG_REG (recog_data.operand[i]);
-         if (GET_MODE_SIZE (modes[i]) != GET_MODE_SIZE (GET_MODE (inner)))
-           subreg_changes_size[i] = 1;
+#ifdef CLASS_CANNOT_CHANGE_MODE
+         if (GET_CODE (inner) == REG
+             && CLASS_CANNOT_CHANGE_MODE_P (modes[i], GET_MODE (inner)))
+           SET_REGNO_REG_SET (reg_changes_mode, REGNO (inner));
+#endif
          recog_data.operand[i] = inner;
        }
 
@@ -860,12 +934,12 @@ record_operand_costs (insn, op_costs, reg_pref)
        xconstraints[i] = constraints[i+1];
        xconstraints[i+1] = constraints[i];
        record_reg_classes (recog_data.n_alternatives, recog_data.n_operands,
-                           recog_data.operand, modes, subreg_changes_size,
+                           recog_data.operand, modes, 
                            xconstraints, insn, op_costs, reg_pref);
       }
 
   record_reg_classes (recog_data.n_alternatives, recog_data.n_operands,
-                     recog_data.operand, modes, subreg_changes_size,
+                     recog_data.operand, modes, 
                      constraints, insn, op_costs, reg_pref);
 }
 \f
@@ -1013,6 +1087,10 @@ regclass (f, nregs, dump)
 
   costs = (struct costs *) xmalloc (nregs * sizeof (struct costs));
 
+#ifdef CLASS_CANNOT_CHANGE_MODE
+  reg_changes_mode = BITMAP_XMALLOC();
+#endif  
+
 #ifdef FORBIDDEN_INC_DEC_CLASSES
 
   in_inc_dec = (char *) xmalloc (nregs);
@@ -1079,10 +1157,10 @@ regclass (f, nregs, dump)
         fprintf (dump, "\n\nPass %i\n\n",pass);
       /* Zero out our accumulation of the cost of each class for each reg.  */
 
-      bzero ((char *) costs, nregs * sizeof (struct costs));
+      memset ((char *) costs, 0, nregs * sizeof (struct costs));
 
 #ifdef FORBIDDEN_INC_DEC_CLASSES
-      bzero (in_inc_dec, nregs);
+      memset (in_inc_dec, 0, nregs);
 #endif
 
       /* Scan the instructions and record each time it would
@@ -1102,11 +1180,7 @@ regclass (f, nregs, dump)
            /* Show that an insn inside a loop is likely to be executed three
               times more than insns outside a loop.  This is much more
               aggressive than the assumptions made elsewhere and is being
-              tried as an experiment. 
-
-              Note that a block's loop depth starts at zero, not one!  We
-              must not subract one from the loop depth as that could give
-              a negative shift count below.  */
+              tried as an experiment.  */
            if (optimize_size)
              loop_cost = 1;
            else
@@ -1155,6 +1229,10 @@ regclass (f, nregs, dump)
 #ifdef FORBIDDEN_INC_DEC_CLASSES
                  || (in_inc_dec[i] && forbidden_inc_dec_class[class])
 #endif
+#ifdef CLASS_CANNOT_CHANGE_MODE
+                 || (REGNO_REG_SET_P (reg_changes_mode, i)
+                     && ! class_can_change_mode [class])
+#endif
                  )
                ;
              else if (p->cost[class] < best_cost)
@@ -1181,6 +1259,10 @@ regclass (f, nregs, dump)
 #ifdef FORBIDDEN_INC_DEC_CLASSES
                  && ! (in_inc_dec[i] && forbidden_inc_dec_class[class])
 #endif
+#ifdef CLASS_CANNOT_CHANGE_MODE
+                 && ! (REGNO_REG_SET_P (reg_changes_mode, i)
+                       && ! class_can_change_mode [class])
+#endif
                  )
                alt = reg_class_subunion[(int) alt][class];
          
@@ -1213,6 +1295,9 @@ regclass (f, nregs, dump)
 #ifdef FORBIDDEN_INC_DEC_CLASSES
   free (in_inc_dec);
 #endif
+#ifdef CLASS_CANNOT_CHANGE_MODE
+  BITMAP_XFREE (reg_changes_mode);
+#endif
   free (costs);
 }
 \f
@@ -1241,13 +1326,12 @@ regclass (f, nregs, dump)
    alternatives.  */
 
 static void
-record_reg_classes (n_alts, n_ops, ops, modes, subreg_changes_size,
+record_reg_classes (n_alts, n_ops, ops, modes,
                    constraints, insn, op_costs, reg_pref)
      int n_alts;
      int n_ops;
      rtx *ops;
      enum machine_mode *modes;
-     char *subreg_changes_size ATTRIBUTE_UNUSED;
      const char **constraints;
      rtx insn;
      struct costs *op_costs;
@@ -1288,7 +1372,7 @@ record_reg_classes (n_alts, n_ops, ops, modes, subreg_changes_size,
          if (*p == 0)
            {
              if (GET_CODE (op) == REG && REGNO (op) >= FIRST_PSEUDO_REGISTER)
-               bzero ((char *) &this_op_costs[i], sizeof this_op_costs[i]);
+               memset ((char *) &this_op_costs[i], 0, sizeof this_op_costs[i]);
 
              continue;
            }
@@ -1354,10 +1438,10 @@ record_reg_classes (n_alts, n_ops, ops, modes, subreg_changes_size,
                  for (class = 0; class < N_REG_CLASSES; class++)
                    pp->cost[class]
                      = ((recog_data.operand_type[i] != OP_OUT
-                         ? may_move_in_cost[class][(int) classes[i]]
+                         ? may_move_in_cost[mode][class][(int) classes[i]]
                          : 0)
                         + (recog_data.operand_type[i] != OP_IN
-                           ? may_move_out_cost[(int) classes[i]][class]
+                           ? may_move_out_cost[mode][(int) classes[i]][class]
                            : 0));
                  
                  /* If the alternative actually allows memory, make things
@@ -1379,7 +1463,8 @@ record_reg_classes (n_alts, n_ops, ops, modes, subreg_changes_size,
 
                  if (reg_pref)
                    alt_cost
-                     += (may_move_in_cost[(unsigned char) reg_pref[REGNO (op)].prefclass]
+                     += (may_move_in_cost[mode]
+                         [(unsigned char) reg_pref[REGNO (op)].prefclass]
                          [(int) classes[i]]);
 
                  if (REGNO (ops[i]) != REGNO (ops[j])
@@ -1512,17 +1597,6 @@ record_reg_classes (n_alts, n_ops, ops, modes, subreg_changes_size,
                win = 1;
                break;
 
-#ifdef EXTRA_CONSTRAINT
-              case 'Q':
-              case 'R':
-              case 'S':
-              case 'T':
-              case 'U':
-               if (EXTRA_CONSTRAINT (op, c))
-                 win = 1;
-               break;
-#endif
-
              case 'g':
                if (GET_CODE (op) == MEM
                    || (CONSTANT_P (op)
@@ -1538,23 +1612,19 @@ record_reg_classes (n_alts, n_ops, ops, modes, subreg_changes_size,
                break;
 
              default:
-               classes[i]
-                 = reg_class_subunion[(int) classes[i]]
-                   [(int) REG_CLASS_FROM_LETTER (c)];
+               if (REG_CLASS_FROM_LETTER (c) != NO_REGS)
+                 classes[i]
+                   = reg_class_subunion[(int) classes[i]]
+                     [(int) REG_CLASS_FROM_LETTER (c)];
+#ifdef EXTRA_CONSTRAINT
+               else if (EXTRA_CONSTRAINT (op, c))
+                 win = 1;
+#endif
+               break;
              }
 
          constraints[i] = p;
 
-#ifdef CLASS_CANNOT_CHANGE_SIZE
-         /* If we noted a subreg earlier, and the selected class is a 
-            subclass of CLASS_CANNOT_CHANGE_SIZE, zap it.  */
-         if (subreg_changes_size[i]
-             && (reg_class_subunion[(int) CLASS_CANNOT_CHANGE_SIZE]
-                                   [(int) classes[i]]
-                 == CLASS_CANNOT_CHANGE_SIZE))
-           classes[i] = NO_REGS;
-#endif
-
          /* How we account for this operand now depends on whether it is  a
             pseudo register or not.  If it is, we first check if any
             register classes are valid.  If not, we ignore this alternative,
@@ -1566,13 +1636,13 @@ record_reg_classes (n_alts, n_ops, ops, modes, subreg_changes_size,
            {
              if (classes[i] == NO_REGS)
                {
-                   /* We must always fail if the operand is a REG, but
-                      we did not find a suitable class.
-
-                      Otherwise we may perform an uninitialized read
-                      from this_op_costs after the `continue' statement
-                      below.  */
-                   alt_fail = 1;
+                 /* We must always fail if the operand is a REG, but
+                    we did not find a suitable class.
+                    
+                    Otherwise we may perform an uninitialized read
+                    from this_op_costs after the `continue' statement
+                    below.  */
+                 alt_fail = 1;
                }
              else
                {
@@ -1581,10 +1651,10 @@ record_reg_classes (n_alts, n_ops, ops, modes, subreg_changes_size,
                  for (class = 0; class < N_REG_CLASSES; class++)
                    pp->cost[class]
                      = ((recog_data.operand_type[i] != OP_OUT
-                         ? may_move_in_cost[class][(int) classes[i]]
+                         ? may_move_in_cost[mode][class][(int) classes[i]]
                          : 0)
                         + (recog_data.operand_type[i] != OP_IN
-                           ? may_move_out_cost[(int) classes[i]][class]
+                           ? may_move_out_cost[mode][(int) classes[i]][class]
                            : 0));
 
                  /* If the alternative actually allows memory, make things
@@ -1606,7 +1676,8 @@ record_reg_classes (n_alts, n_ops, ops, modes, subreg_changes_size,
 
                  if (reg_pref)
                    alt_cost
-                     += (may_move_in_cost[(unsigned char) reg_pref[REGNO (op)].prefclass]
+                     += (may_move_in_cost[mode]
+                         [(unsigned char) reg_pref[REGNO (op)].prefclass]
                          [(int) classes[i]]);
                }
            }
@@ -1684,10 +1755,10 @@ record_reg_classes (n_alts, n_ops, ops, modes, subreg_changes_size,
     for (i = 0; i <= 1; i++)
       if (REGNO (ops[i]) >= FIRST_PSEUDO_REGISTER)
        {
-         int regno = REGNO (ops[!i]);
+         unsigned int regno = REGNO (ops[!i]);
          enum machine_mode mode = GET_MODE (ops[!i]);
          int class;
-         int nr;
+         unsigned int nr;
 
          if (regno >= FIRST_PSEUDO_REGISTER && reg_pref != 0)
            {
@@ -1695,7 +1766,7 @@ record_reg_classes (n_alts, n_ops, ops, modes, subreg_changes_size,
 
              if ((reg_class_size[(unsigned char) pref]
                   == CLASS_MAX_NREGS (pref, mode))
-                 && REGISTER_MOVE_COST (pref, pref) < 10 * 2)
+                 && REGISTER_MOVE_COST (mode, pref, pref) < 10 * 2)
                op_costs[i].cost[(unsigned char) pref] = -1;
            }
          else if (regno < FIRST_PSEUDO_REGISTER)
@@ -1707,13 +1778,14 @@ record_reg_classes (n_alts, n_ops, ops, modes, subreg_changes_size,
                    op_costs[i].cost[class] = -1;
                  else
                    {
-                     for (nr = 0; nr < HARD_REGNO_NREGS(regno, mode); nr++)
+                     for (nr = 0; nr < HARD_REGNO_NREGS (regno, mode); nr++)
                        {
-                         if (!TEST_HARD_REG_BIT (reg_class_contents[class], regno + nr))
+                         if (! TEST_HARD_REG_BIT (reg_class_contents[class],
+                                                  regno + nr))
                            break;
                        }
 
-                     if (nr == HARD_REGNO_NREGS(regno,mode))
+                     if (nr == HARD_REGNO_NREGS (regno,mode))
                        op_costs[i].cost[class] = -1;
                    }
                }
@@ -1728,9 +1800,9 @@ record_reg_classes (n_alts, n_ops, ops, modes, subreg_changes_size,
 static int
 copy_cost (x, mode, class, to_p)
      rtx x;
-     enum machine_mode mode;
+     enum machine_mode mode ATTRIBUTE_UNUSED;
      enum reg_class class;
-     int to_p;
+     int to_p ATTRIBUTE_UNUSED;
 {
 #ifdef HAVE_SECONDARY_RELOADS
   enum reg_class secondary_class = NO_REGS;
@@ -1762,7 +1834,7 @@ copy_cost (x, mode, class, to_p)
 #endif
 
   if (secondary_class != NO_REGS)
-    return (move_cost[(int) secondary_class][(int) class]
+    return (move_cost[mode][(int) secondary_class][(int) class]
            + copy_cost (x, mode, secondary_class, 2));
 #endif  /* HAVE_SECONDARY_RELOADS */
 
@@ -1774,11 +1846,11 @@ copy_cost (x, mode, class, to_p)
     return MEMORY_MOVE_COST (mode, class, to_p);
 
   else if (GET_CODE (x) == REG)
-    return move_cost[(int) REGNO_REG_CLASS (REGNO (x))][(int) class];
+    return move_cost[mode][(int) REGNO_REG_CLASS (REGNO (x))][(int) class];
 
   else
     /* If this is a constant, we may eventually want to call rtx_cost here.  */
-    return 2;
+    return COSTS_N_INSNS (1);
 }
 \f
 /* Record the pseudo registers we must reload into hard registers
@@ -1812,10 +1884,10 @@ record_address_regs (x, class, scale)
       /* When we have an address that is a sum,
         we must determine whether registers are "base" or "index" regs.
         If there is a sum of two registers, we must choose one to be
-        the "base".  Luckily, we can use the REGNO_POINTER_FLAG
-        to make a good choice most of the time.  We only need to do this
-        on machines that can have two registers in an address and where
-        the base and index register classes are different.
+        the "base".  Luckily, we can use the REG_POINTER to make a good
+        choice most of the time.  We only need to do this on machines
+        that can have two registers in an address and where the base
+        and index register classes are different.
 
         ??? This code used to set REGNO_POINTER_FLAG in some cases, but
         that seems bogus since it should only be set when we are sure
@@ -1888,13 +1960,13 @@ record_address_regs (x, class, scale)
           with the other operand the index.  Likewise if the other operand
           is a MULT.  */
 
-       else if ((code0 == REG && REGNO_POINTER_FLAG (REGNO (arg0)))
+       else if ((code0 == REG && REG_POINTER (arg0))
                 || code1 == MULT)
          {
            record_address_regs (arg0, BASE_REG_CLASS, scale);
            record_address_regs (arg1, INDEX_REG_CLASS, scale);
          }
-       else if ((code1 == REG && REGNO_POINTER_FLAG (REGNO (arg1)))
+       else if ((code1 == REG && REG_POINTER (arg1))
                 || code0 == MULT)
          {
            record_address_regs (arg0, INDEX_REG_CLASS, scale);
@@ -1914,6 +1986,17 @@ record_address_regs (x, class, scale)
       }
       break;
 
+      /* Double the importance of a pseudo register that is incremented
+        or decremented, since it would take two extra insns
+        if it ends up in the wrong place.  */
+    case POST_MODIFY:
+    case PRE_MODIFY:
+      record_address_regs (XEXP (x, 0), BASE_REG_CLASS, 2 * scale);
+      if (REG_P (XEXP (XEXP (x, 1), 1)))
+       record_address_regs (XEXP (XEXP (x, 1), 1),
+                            INDEX_REG_CLASS, 2 * scale);
+      break;
+
     case POST_INC:
     case PRE_INC:
     case POST_DEC:
@@ -1940,7 +2023,7 @@ record_address_regs (x, class, scale)
        pp->mem_cost += (MEMORY_MOVE_COST (Pmode, class, 1) * scale) / 2;
 
        for (i = 0; i < N_REG_CLASSES; i++)
-         pp->cost[i] += (may_move_in_cost[i][(int) class] * scale) / 2;
+         pp->cost[i] += (may_move_in_cost[Pmode][i][(int) class] * scale) / 2;
       }
       break;
 
@@ -1985,8 +2068,9 @@ auto_inc_dec_reg_p (reg, mode)
 }
 #endif
 \f
-static short *renumber = (short *)0;
-static size_t regno_allocated = 0;
+static short *renumber;
+static size_t regno_allocated;
+static unsigned int reg_n_max;
 
 /* Allocate enough space to hold NUM_REGS registers for the tables used for
    reg_scan and flow_analysis that are indexed by the register number.  If
@@ -2005,7 +2089,6 @@ allocate_reg_info (num_regs, new_p, renumber_p)
   size_t size_renumber;
   size_t min = (new_p) ? 0 : reg_n_max;
   struct reg_info_data *reg_data;
-  struct reg_info_data *reg_next;
 
   if (num_regs > regno_allocated)
     {
@@ -2058,34 +2141,34 @@ allocate_reg_info (num_regs, new_p, renumber_p)
     {
       /* Loop through each of the segments allocated for the actual
         reg_info pages, and set up the pointers, zero the pages, etc.  */
-      for (reg_data = reg_info_head; reg_data; reg_data = reg_next)
+      for (reg_data = reg_info_head; 
+          reg_data && reg_data->max_index >= min;
+          reg_data = reg_data->next)
        {
          size_t min_index = reg_data->min_index;
          size_t max_index = reg_data->max_index;
+         size_t max = MIN (max_index, num_regs);
+         size_t local_min = min - min_index;
+         size_t i;
 
-         reg_next = reg_data->next;
-         if (min <= max_index)
-           {
-             size_t max = max_index;
-             size_t local_min = min - min_index;
-             size_t i;
-
-             if (min < min_index)
-               local_min = 0;
-             if (!reg_data->used_p)    /* page just allocated with calloc */
-               reg_data->used_p = 1;   /* no need to zero */
-             else
-               bzero ((char *) &reg_data->data[local_min],
-                      sizeof (reg_info) * (max - min_index - local_min + 1));
+         if (reg_data->min_index > num_regs)
+           continue;
 
-             for (i = min_index+local_min; i <= max; i++)
-               {
-                 VARRAY_REG (reg_n_info, i) = &reg_data->data[i-min_index];
-                 REG_BASIC_BLOCK (i) = REG_BLOCK_UNKNOWN;
-                 renumber[i] = -1;
-                 reg_pref_buffer[i].prefclass = (char) NO_REGS;
-                 reg_pref_buffer[i].altclass = (char) NO_REGS;
-               }
+         if (min < min_index)
+           local_min = 0;
+         if (!reg_data->used_p)        /* page just allocated with calloc */
+           reg_data->used_p = 1;       /* no need to zero */
+         else
+           memset ((char *) &reg_data->data[local_min], 0,
+                  sizeof (reg_info) * (max - min_index - local_min + 1));
+
+         for (i = min_index+local_min; i <= max; i++)
+           {
+             VARRAY_REG (reg_n_info, i) = &reg_data->data[i-min_index];
+             REG_BASIC_BLOCK (i) = REG_BLOCK_UNKNOWN;
+             renumber[i] = -1;
+             reg_pref_buffer[i].prefclass = (char) NO_REGS;
+             reg_pref_buffer[i].altclass = (char) NO_REGS;
            }
        }
     }
@@ -2138,20 +2221,28 @@ free_reg_info ()
 
 /* Maximum number of parallel sets and clobbers in any insn in this fn.
    Always at least 3, since the combiner could put that many together
-   and we want this to remain correct for all the remaining passes.  */
+   and we want this to remain correct for all the remaining passes.
+   This corresponds to the maximum number of times note_stores will call
+   a function for any insn.  */
 
 int max_parallel;
 
+/* Used as a temporary to record the largest number of registers in 
+   PARALLEL in a SET_DEST.  This is added to max_parallel.  */
+
+static int max_set_parallel;
+
 void
 reg_scan (f, nregs, repeat)
      rtx f;
-     int nregs;
+     unsigned int nregs;
      int repeat ATTRIBUTE_UNUSED;
 {
   register rtx insn;
 
   allocate_reg_info (nregs, TRUE, FALSE);
   max_parallel = 3;
+  max_set_parallel = 0;
 
   for (insn = f; insn; insn = NEXT_INSN (insn))
     if (GET_CODE (insn) == INSN
@@ -2166,6 +2257,8 @@ reg_scan (f, nregs, repeat)
        if (REG_NOTES (insn))
          reg_scan_mark_refs (REG_NOTES (insn), insn, 1, 0);
       }
+
+  max_parallel += max_set_parallel;
 }
 
 /* Update 'regscan' information by looking at the insns
@@ -2174,10 +2267,10 @@ reg_scan (f, nregs, repeat)
    such a REG.  We only update information for those.  */
 
 void
-reg_scan_update(first, last, old_max_regno)
+reg_scan_update (first, last, old_max_regno)
      rtx first;
      rtx last;
-     int old_max_regno;
+     unsigned int old_max_regno;
 {
   register rtx insn;
 
@@ -2208,7 +2301,7 @@ reg_scan_mark_refs (x, insn, note_flag, min_regno)
      rtx x;
      rtx insn;
      int note_flag;
-     int min_regno;
+     unsigned int min_regno;
 {
   register enum rtx_code code;
   register rtx dest;
@@ -2230,7 +2323,7 @@ reg_scan_mark_refs (x, insn, note_flag, min_regno)
 
     case REG:
       {
-       register int regno = REGNO (x);
+       unsigned int regno = REGNO (x);
 
        if (regno >= min_regno)
          {
@@ -2263,6 +2356,11 @@ reg_scan_mark_refs (x, insn, note_flag, min_regno)
           dest = XEXP (dest, 0))
        ;
 
+      /* For a PARALLEL, record the number of things (less the usual one for a
+        SET) that are set.  */
+      if (GET_CODE (dest) == PARALLEL)
+       max_set_parallel = MAX (max_set_parallel, XVECLEN (dest, 0) - 1);
+
       if (GET_CODE (dest) == REG
          && REGNO (dest) >= min_regno)
        REG_N_SETS (REGNO (dest))++;
@@ -2285,18 +2383,18 @@ reg_scan_mark_refs (x, insn, note_flag, 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 presense of global
-            optimizations).  So only set REGNO_POINTER_FLAG on the destination
+            optimizations).  So only set REG_POINTER on the destination
             pseudo if this is the only set of that pseudo.  */
          && REG_N_SETS (REGNO (SET_DEST (x))) == 1
          && ! REG_USERVAR_P (SET_DEST (x))
-         && ! REGNO_POINTER_FLAG (REGNO (SET_DEST (x)))
+         && ! REG_POINTER (SET_DEST (x))
          && ((GET_CODE (SET_SRC (x)) == REG
-              && REGNO_POINTER_FLAG (REGNO (SET_SRC (x))))
+              && REG_POINTER (SET_SRC (x)))
              || ((GET_CODE (SET_SRC (x)) == PLUS
                   || GET_CODE (SET_SRC (x)) == LO_SUM)
                  && GET_CODE (XEXP (SET_SRC (x), 1)) == CONST_INT
                  && GET_CODE (XEXP (SET_SRC (x), 0)) == REG
-                 && REGNO_POINTER_FLAG (REGNO (XEXP (SET_SRC (x), 0))))
+                 && REG_POINTER (XEXP (SET_SRC (x), 0)))
              || GET_CODE (SET_SRC (x)) == CONST
              || GET_CODE (SET_SRC (x)) == SYMBOL_REF
              || GET_CODE (SET_SRC (x)) == LABEL_REF
@@ -2313,7 +2411,7 @@ reg_scan_mark_refs (x, insn, note_flag, min_regno)
                  && (GET_CODE (XEXP (note, 0)) == CONST
                      || GET_CODE (XEXP (note, 0)) == SYMBOL_REF
                      || GET_CODE (XEXP (note, 0)) == LABEL_REF))))
-       REGNO_POINTER_FLAG (REGNO (SET_DEST (x))) = 1;
+       REG_POINTER (SET_DEST (x)) = 1;
 
       /* ... fall through ...  */