OSDN Git Service

* gcc.c-torture/execute/ieee/ieee.exp: Change sh-*-* to sh*-*-*.
[pf3gnuchains/gcc-fork.git] / gcc / regclass.c
index 4439857..826da24 100644 (file)
@@ -1,23 +1,23 @@
 /* Compute register class preferences for pseudo-registers.
    Copyright (C) 1987, 1988, 1991, 1992, 1993, 1994, 1995, 1996
-   1997, 1998, 1999, 2000 Free Software Foundation, Inc.
+   1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
 
-This file is part of GNU CC.
+This file is part of GCC.
 
-GNU CC 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 version.
+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
+version.
 
-GNU CC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+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 GNU CC; see the file COPYING.  If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.  */
+along with GCC; see the file COPYING.  If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.  */
 
 
 /* This file contains two passes of the compiler: reg_scan and reg_class.
@@ -27,6 +27,7 @@ Boston, MA 02111-1307, USA.  */
 #include "config.h"
 #include "system.h"
 #include "rtl.h"
+#include "expr.h"
 #include "tm_p.h"
 #include "hard-reg-set.h"
 #include "flags.h"
@@ -42,7 +43,7 @@ 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    PARAMS ((void));
@@ -73,7 +74,7 @@ HARD_REG_SET fixed_reg_set;
 
 /* Data for initializing the above.  */
 
-static char initial_fixed_regs[] = FIXED_REGISTERS;
+static const char initial_fixed_regs[] = FIXED_REGISTERS;
 
 /* Indexed by hard register number, contains 1 for registers
    that are fixed use or are clobbered by function calls.
@@ -92,7 +93,16 @@ HARD_REG_SET losing_caller_save_reg_set;
 
 /* Data for initializing the above.  */
 
-static char initial_call_used_regs[] = CALL_USED_REGISTERS;
+static const char initial_call_used_regs[] = CALL_USED_REGISTERS;
+
+/* This is much like call_used_regs, except it doesn't have to
+   be a superset of FIXED_REGISTERS. This vector indicates
+   what is really call clobbered, and is used when defining 
+   regs_invalidated_by_call.  */
+
+#ifdef CALL_REALLY_USED_REGISTERS
+char call_really_used_regs[] = CALL_REALLY_USED_REGISTERS;
+#endif
   
 /* Indexed by hard register number, contains 1 for registers that are
    fixed use or call used registers that cannot hold quantities across
@@ -115,7 +125,16 @@ int n_non_fixed_regs;
    and are also considered fixed.  */
 
 char global_regs[FIRST_PSEUDO_REGISTER];
-  
+
+/* Contains 1 for registers that are set or clobbered by calls.  */
+/* ??? Ideally, this would be just call_used_regs plus global_regs, but
+   for someone's bright idea to have call_used_regs strictly include
+   fixed_regs.  Which leaves us guessing as to the set of fixed_regs
+   that are actually preserved.  We know for sure that those associated
+   with the local stack frame are safe, but scant others.  */
+
+HARD_REG_SET regs_invalidated_by_call;
+
 /* Table of register numbers in the order in which to try to use them.  */
 #ifdef REG_ALLOC_ORDER
 int reg_alloc_order[FIRST_PSEUDO_REGISTER] = REG_ALLOC_ORDER;
@@ -130,10 +149,11 @@ HARD_REG_SET reg_class_contents[N_REG_CLASSES];
 
 /* The same information, but as an array of unsigned ints.  We copy from
    these unsigned ints to the table above.  We do this so the tm.h files
-   do not have to be aware of the wordsize for machines with <= 64 regs.  */
+   do not have to be aware of the wordsize for machines with <= 64 regs.
+   Note that we hard-code 32 here, not HOST_BITS_PER_INT.  */
 
 #define N_REG_INTS  \
-  ((FIRST_PSEUDO_REGISTER + (HOST_BITS_PER_INT - 1)) / HOST_BITS_PER_INT)
+  ((FIRST_PSEUDO_REGISTER + (32 - 1)) / 32)
 
 static unsigned int_reg_class_contents[N_REG_CLASSES][N_REG_INTS] 
   = REG_CLASS_CONTENTS;
@@ -174,20 +194,24 @@ const char * reg_names[] = REGISTER_NAMES;
 
 enum machine_mode reg_raw_mode[FIRST_PSEUDO_REGISTER];
 
+/* 1 if class does contain register of given mode.  */
+
+static 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 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
 
@@ -241,7 +265,7 @@ struct reg_info_data {
 static struct reg_info_data *reg_info_head;
 
 /* No more global register variables may be declared; true once
-   regclass has been initialized. */
+   regclass has been initialized.  */
 
 static int no_global_reg_vars = 0;
 
@@ -252,7 +276,7 @@ static int no_global_reg_vars = 0;
 void
 init_reg_sets ()
 {
-  register int i, j;
+  int i, j;
 
   /* First copy the register information from the initial int form into
      the regsets.  */
@@ -261,15 +285,16 @@ init_reg_sets ()
     {
       CLEAR_HARD_REG_SET (reg_class_contents[i]);
 
+      /* Note that we hard-code 32 here, not HOST_BITS_PER_INT.  */
       for (j = 0; j < FIRST_PSEUDO_REGISTER; j++)
-       if (int_reg_class_contents[i][j / HOST_BITS_PER_INT]
-           & ((unsigned) 1 << (j % HOST_BITS_PER_INT)))
+       if (int_reg_class_contents[i][j / 32]
+           & ((unsigned) 1 << (j % 32)))
          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 ();
@@ -286,7 +311,9 @@ init_reg_sets ()
 static void
 init_reg_sets_1 ()
 {
-  register unsigned int i, j;
+  unsigned int i, j;
+  unsigned int /* enum machine_mode */ m;
+  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.  */
@@ -297,7 +324,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))
@@ -315,7 +342,7 @@ init_reg_sets_1 ()
          register              /* Declare it register if it's a scalar.  */
 #endif
            HARD_REG_SET c;
-         register int k;
+         int k;
 
          COPY_HARD_REG_SET (c, reg_class_contents[i]);
          IOR_HARD_REG_SET (c, reg_class_contents[j]);
@@ -349,7 +376,7 @@ init_reg_sets_1 ()
          register              /* Declare it register if it's a scalar.  */
 #endif
            HARD_REG_SET c;
-         register int k;
+         int k;
 
          COPY_HARD_REG_SET (c, reg_class_contents[i]);
          IOR_HARD_REG_SET (c, reg_class_contents[j]);
@@ -403,8 +430,9 @@ init_reg_sets_1 ()
   CLEAR_HARD_REG_SET (fixed_reg_set);
   CLEAR_HARD_REG_SET (call_used_reg_set);
   CLEAR_HARD_REG_SET (call_fixed_reg_set);
+  CLEAR_HARD_REG_SET (regs_invalidated_by_call);
 
-  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;
 
@@ -421,43 +449,109 @@ init_reg_sets_1 ()
        SET_HARD_REG_BIT (call_fixed_reg_set, i);
       if (CLASS_LIKELY_SPILLED_P (REGNO_REG_CLASS (i)))
        SET_HARD_REG_BIT (losing_caller_save_reg_set, i);
+
+      /* There are a couple of fixed registers that we know are safe to
+        exclude from being clobbered by calls:
+
+        The frame pointer is always preserved across calls.  The arg pointer
+        is if it is fixed.  The stack pointer usually is, unless
+        RETURN_POPS_ARGS, in which case an explicit CLOBBER will be present.
+        If we are generating PIC code, the PIC offset table register is
+        preserved across calls, though the target can override that.  */
+        
+      if (i == STACK_POINTER_REGNUM || i == FRAME_POINTER_REGNUM)
+       ;
+#if HARD_FRAME_POINTER_REGNUM != FRAME_POINTER_REGNUM
+      else if (i == HARD_FRAME_POINTER_REGNUM)
+       ;
+#endif
+#if ARG_POINTER_REGNUM != FRAME_POINTER_REGNUM
+      else if (i == ARG_POINTER_REGNUM && fixed_regs[i])
+       ;
+#endif
+#ifndef PIC_OFFSET_TABLE_REG_CALL_CLOBBERED
+      else if (i == PIC_OFFSET_TABLE_REGNUM && flag_pic)
+       ;
+#endif
+      else if (0
+#ifdef CALL_REALLY_USED_REGISTERS
+              || call_really_used_regs[i]
+#else
+              || call_used_regs[i]
+#endif
+              || global_regs[i])
+       SET_HARD_REG_BIT (regs_invalidated_by_call, 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 < (unsigned int) MAX_MACHINE_MODE; m++)
+    for (i = 0; i < N_REG_CLASSES; i++)
+      if (CLASS_MAX_NREGS (i, m) <= reg_class_size[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 < (unsigned int) 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;
-
-       if (reg_class_subset_p (j, i))
-         may_move_out_cost[i][j] = 0;
-       else
-         may_move_out_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 = 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;
+             }
       }
 
 #ifdef CLASS_CANNOT_CHANGE_MODE
@@ -484,7 +578,7 @@ init_reg_sets_1 ()
 static void
 init_reg_modes ()
 {
-  register int i;
+  int i;
 
   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
     {
@@ -539,7 +633,7 @@ memory_move_secondary_cost (mode, class, in)
   enum reg_class altclass;
   int partial_cost = 0;
   /* We need a memory reference to feed to SECONDARY... macros.  */
-  /* mem may be unused even if the SECONDARY_ macros are defined. */
+  /* mem may be unused even if the SECONDARY_ macros are defined.  */
   rtx mem ATTRIBUTE_UNUSED = top_of_stack[(int) mode];
 
 
@@ -564,9 +658,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
@@ -592,6 +686,7 @@ choose_hard_reg_mode (regno, nregs)
      unsigned int regno ATTRIBUTE_UNUSED;
      unsigned int nregs;
 {
+  unsigned int /* enum machine_mode */ m;
   enum machine_mode found_mode = VOIDmode, mode;
 
   /* We first look for the largest integer mode that can be validly
@@ -618,9 +713,14 @@ 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 (m = (unsigned int) CCmode; m < (unsigned int) NUM_MACHINE_MODES; ++m)
+    {
+      mode = (enum machine_mode) m;
+      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;
@@ -662,6 +762,10 @@ fix_register (name, fixed, call_used)
        {
          fixed_regs[i] = fixed;
          call_used_regs[i] = call_used;
+#ifdef CALL_REALLY_USED_REGISTERS
+         if (fixed == 0)
+           call_really_used_regs[i] = call_used;
+#endif
        }
     }
   else
@@ -744,14 +848,13 @@ static struct costs init_cost;
 
 static struct reg_pref *reg_pref;
 
-/* Allocated buffers for reg_pref. */
+/* Allocated buffers for reg_pref.  */
 
 static struct reg_pref *reg_pref_buffer;
 
-/* Account for the fact that insns within a loop are executed very commonly,
-   but don't keep doing this as loops go too deep.  */
+/* Frequency of executions of current insn.  */
 
-static int loop_cost;
+static int frequency;
 
 static rtx scan_one_insn       PARAMS ((rtx, int));
 static void record_operand_costs PARAMS ((rtx, struct costs *, struct reg_pref *));
@@ -805,7 +908,7 @@ regclass_init ()
      before regclass is run.  */
   reg_pref = NULL;
 
-  /* No more global register variables may be declared. */
+  /* No more global register variables may be declared.  */
   no_global_reg_vars = 1;
 }
 \f
@@ -818,13 +921,23 @@ dump_regclass (dump)
   int i;
   for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
     {
-      enum reg_class class;
+      int /* enum reg_class */ class;
       if (REG_N_REFS (i))
        {
          fprintf (dump, "  Register %i costs:", i);
-         for (class = 0; class < N_REG_CLASSES; class++)
-           fprintf (dump, " %s:%i", reg_class_names[(int) class],
-                    costs[i].cost[class]);
+         for (class = 0; class < (int) N_REG_CLASSES; class++)
+           if (contains_reg_of_mode [(enum reg_class) class][PSEUDO_REGNO_MODE (i)]
+#ifdef FORBIDDEN_INC_DEC_CLASSES
+               && (!in_inc_dec[i]
+                   || !forbidden_inc_dec_class[(enum reg_class) class])
+#endif
+#ifdef CLASS_CANNOT_CHANGE_MODE
+               && (!REGNO_REG_SET_P (reg_changes_mode, i)
+                    || class_can_change_mode [(enum reg_class) class])
+#endif
+               )
+           fprintf (dump, " %s:%i", reg_class_names[class],
+                    costs[i].cost[(enum reg_class) class]);
          fprintf (dump, " MEM:%i\n", costs[i].mem_cost);
        }
     }
@@ -872,10 +985,10 @@ record_operand_costs (insn, op_costs, reg_pref)
 
       if (GET_CODE (recog_data.operand[i]) == MEM)
        record_address_regs (XEXP (recog_data.operand[i], 0),
-                            BASE_REG_CLASS, loop_cost * 2);
+                            BASE_REG_CLASS, frequency * 2);
       else if (constraints[i][0] == 'p')
        record_address_regs (recog_data.operand[i],
-                            BASE_REG_CLASS, loop_cost * 2);
+                            BASE_REG_CLASS, frequency * 2);
     }
 
   /* Check for commutative in a separate loop so everything will
@@ -951,9 +1064,9 @@ scan_one_insn (insn, pass)
       costs[REGNO (SET_DEST (set))].mem_cost
        -= (MEMORY_MOVE_COST (GET_MODE (SET_DEST (set)),
                              GENERAL_REGS, 1)
-           * loop_cost);
+           * frequency);
       record_address_regs (XEXP (SET_SRC (set), 0),
-                          BASE_REG_CLASS, loop_cost * 2);
+                          BASE_REG_CLASS, frequency * 2);
       return insn;
     }
 
@@ -1002,11 +1115,19 @@ scan_one_insn (insn, pass)
 
       /* This makes one more setting of new insns's dest.  */
       REG_N_SETS (REGNO (recog_data.operand[0]))++;
+      REG_N_REFS (REGNO (recog_data.operand[0]))++;
+      REG_FREQ (REGNO (recog_data.operand[0])) += frequency;
 
       *recog_data.operand_loc[1] = recog_data.operand[0];
+      REG_N_REFS (REGNO (recog_data.operand[0]))++;
+      REG_FREQ (REGNO (recog_data.operand[0])) += frequency;
       for (i = recog_data.n_dups - 1; i >= 0; i--)
        if (recog_data.dup_num[i] == 1)
-         *recog_data.dup_loc[i] = recog_data.operand[0];
+         {
+           *recog_data.dup_loc[i] = recog_data.operand[0];
+           REG_N_REFS (REGNO (recog_data.operand[0]))++;
+           REG_FREQ (REGNO (recog_data.operand[0])) += frequency;
+         }
 
       return PREV_INSN (newinsn);
     }
@@ -1023,9 +1144,9 @@ scan_one_insn (insn, pass)
        int regno = REGNO (recog_data.operand[i]);
        struct costs *p = &costs[regno], *q = &op_costs[i];
 
-       p->mem_cost += q->mem_cost * loop_cost;
+       p->mem_cost += q->mem_cost * frequency;
        for (j = 0; j < N_REG_CLASSES; j++)
-         p->cost[j] += q->cost[j] * loop_cost;
+         p->cost[j] += q->cost[j] * frequency;
       }
 
   return insn;
@@ -1042,8 +1163,8 @@ regclass (f, nregs, dump)
      int nregs;
      FILE *dump;
 {
-  register rtx insn;
-  register int i;
+  rtx insn;
+  int i;
   int pass;
 
   init_recog ();
@@ -1067,7 +1188,7 @@ regclass (f, nregs, dump)
     {
       rtx r = gen_rtx_REG (VOIDmode, 0);
       enum machine_mode m;
-      register int j;
+      int j;
 
       for (j = 0; j < FIRST_PSEUDO_REGISTER; j++)
        if (TEST_HARD_REG_BIT (reg_class_contents[i], j))
@@ -1120,10 +1241,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
@@ -1131,7 +1252,7 @@ regclass (f, nregs, dump)
 
       if (!optimize)
        {
-         loop_cost = 1;
+         frequency = REG_FREQ_MAX;
          for (insn = f; insn; insn = NEXT_INSN (insn))
            insn = scan_one_insn (insn, pass);
        }
@@ -1144,10 +1265,7 @@ regclass (f, nregs, dump)
               times more than insns outside a loop.  This is much more
               aggressive than the assumptions made elsewhere and is being
               tried as an experiment.  */
-           if (optimize_size)
-             loop_cost = 1;
-           else
-             loop_cost = 1 << (2 * MIN (bb->loop_depth, 5));
+           frequency = REG_FREQ_FROM_BB (bb);
            for (insn = bb->head; ; insn = NEXT_INSN (insn))
              {
                insn = scan_one_insn (insn, pass);
@@ -1171,12 +1289,12 @@ regclass (f, nregs, dump)
        }
       for (i = FIRST_PSEUDO_REGISTER; i < nregs; i++)
        {
-         register int best_cost = (1 << (HOST_BITS_PER_INT - 2)) - 1;
+         int best_cost = (1 << (HOST_BITS_PER_INT - 2)) - 1;
          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.  */
-         register int class;
-         register struct costs *p = &costs[i];
+         int class;
+         struct costs *p = &costs[i];
 
          /* In non-optimizing compilation REG_N_REFS is not initialized
             yet.  */
@@ -1186,9 +1304,8 @@ regclass (f, nregs, dump)
          for (class = (int) ALL_REGS - 1; class > 0; class--)
            {
              /* Ignore classes that are too small for this operand or
-                invalid for a operand that was auto-incremented.  */
-             if (CLASS_MAX_NREGS (class, PSEUDO_REGNO_MODE (i))
-                 > reg_class_size[class]
+                invalid for an operand that was auto-incremented.  */
+             if (!contains_reg_of_mode [class][PSEUDO_REGNO_MODE (i)]
 #ifdef FORBIDDEN_INC_DEC_CLASSES
                  || (in_inc_dec[i] && forbidden_inc_dec_class[class])
 #endif
@@ -1335,7 +1452,7 @@ record_reg_classes (n_alts, n_ops, ops, modes,
          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;
            }
@@ -1401,10 +1518,10 @@ record_reg_classes (n_alts, n_ops, ops, modes,
                  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
@@ -1426,7 +1543,8 @@ record_reg_classes (n_alts, n_ops, ops, modes,
 
                  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])
@@ -1559,17 +1677,6 @@ record_reg_classes (n_alts, n_ops, ops, modes,
                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)
@@ -1585,9 +1692,15 @@ record_reg_classes (n_alts, n_ops, ops, modes,
                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;
@@ -1618,10 +1731,10 @@ record_reg_classes (n_alts, n_ops, ops, modes,
                  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
@@ -1643,7 +1756,8 @@ record_reg_classes (n_alts, n_ops, ops, modes,
 
                  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]]);
                }
            }
@@ -1732,7 +1846,7 @@ record_reg_classes (n_alts, n_ops, ops, modes,
 
              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)
@@ -1800,7 +1914,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 */
 
@@ -1812,11 +1926,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
@@ -1834,7 +1948,7 @@ record_address_regs (x, class, scale)
      enum reg_class class;
      int scale;
 {
-  register enum rtx_code code = GET_CODE (x);
+  enum rtx_code code = GET_CODE (x);
 
   switch (code)
     {
@@ -1850,10 +1964,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
@@ -1862,8 +1976,8 @@ record_address_regs (x, class, scale)
       {
        rtx arg0 = XEXP (x, 0);
        rtx arg1 = XEXP (x, 1);
-       register enum rtx_code code0 = GET_CODE (arg0);
-       register enum rtx_code code1 = GET_CODE (arg1);
+       enum rtx_code code0 = GET_CODE (arg0);
+       enum rtx_code code1 = GET_CODE (arg1);
 
        /* Look inside subregs.  */
        if (code0 == SUBREG)
@@ -1926,13 +2040,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);
@@ -1983,20 +2097,20 @@ record_address_regs (x, class, scale)
 
     case REG:
       {
-       register struct costs *pp = &costs[REGNO (x)];
-       register int i;
+       struct costs *pp = &costs[REGNO (x)];
+       int i;
 
        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;
 
     default:
       {
-       register const char *fmt = GET_RTX_FORMAT (code);
-       register int i;
+       const char *fmt = GET_RTX_FORMAT (code);
+       int i;
        for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
          if (fmt[i] == 'e')
            record_address_regs (XEXP (x, i), class, scale);
@@ -2125,7 +2239,7 @@ allocate_reg_info (num_regs, new_p, renumber_p)
          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],
+           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++)
@@ -2187,20 +2301,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;
      unsigned int nregs;
      int repeat ATTRIBUTE_UNUSED;
 {
-  register rtx insn;
+  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
@@ -2215,6 +2337,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
@@ -2228,7 +2352,7 @@ reg_scan_update (first, last, old_max_regno)
      rtx last;
      unsigned int old_max_regno;
 {
-  register rtx insn;
+  rtx insn;
 
   allocate_reg_info (max_reg_num (), FALSE, FALSE);
 
@@ -2259,9 +2383,9 @@ reg_scan_mark_refs (x, insn, note_flag, min_regno)
      int note_flag;
      unsigned int min_regno;
 {
-  register enum rtx_code code;
-  register rtx dest;
-  register rtx note;
+  enum rtx_code code;
+  rtx dest;
+  rtx note;
 
   code = GET_CODE (x);
   switch (code)
@@ -2312,9 +2436,17 @@ 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))++;
+       {
+         REG_N_SETS (REGNO (dest))++;
+         REG_N_REFS (REGNO (dest))++;
+       }
 
       /* If this is setting a pseudo from another pseudo or the sum of a
         pseudo and a constant integer and the other pseudo is known to be
@@ -2334,18 +2466,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
@@ -2362,21 +2494,39 @@ 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;
+
+      /* If this is setting a register from a register or from a simple
+        conversion of a register, propagate REG_DECL.  */
+      if (GET_CODE (dest) == REG)
+       {
+         rtx src = SET_SRC (x);
+
+         while (GET_CODE (src) == SIGN_EXTEND
+                || GET_CODE (src) == ZERO_EXTEND
+                || GET_CODE (src) == TRUNCATE
+                || (GET_CODE (src) == SUBREG && subreg_lowpart_p (src)))
+           src = XEXP (src, 0);
+
+         if (GET_CODE (src) == REG && REGNO_DECL (REGNO (src)) == 0)
+           REGNO_DECL (REGNO (src)) = REGNO_DECL (REGNO (dest));
+         else if (GET_CODE (src) == REG && REGNO_DECL (REGNO (dest)) == 0)
+           REGNO_DECL (REGNO (dest)) = REGNO_DECL (REGNO (src));
+       }
 
       /* ... fall through ...  */
 
     default:
       {
-       register const char *fmt = GET_RTX_FORMAT (code);
-       register int i;
+       const char *fmt = GET_RTX_FORMAT (code);
+       int i;
        for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
          {
            if (fmt[i] == 'e')
              reg_scan_mark_refs (XEXP (x, i), insn, note_flag, min_regno);
            else if (fmt[i] == 'E' && XVEC (x, i) != 0)
              {
-               register int j;
+               int j;
                for (j = XVECLEN (x, i) - 1; j >= 0; j--)
                  reg_scan_mark_refs (XVECEXP (x, i, j), insn, note_flag, min_regno);
              }
@@ -2390,8 +2540,8 @@ reg_scan_mark_refs (x, insn, note_flag, min_regno)
 
 int
 reg_class_subset_p (c1, c2)
-     register enum reg_class c1;
-     register enum reg_class c2;
+     enum reg_class c1;
+     enum reg_class c2;
 {
   if (c1 == c2) return 1;
 
@@ -2408,8 +2558,8 @@ reg_class_subset_p (c1, c2)
 
 int
 reg_classes_intersect_p (c1, c2)
-     register enum reg_class c1;
-     register enum reg_class c2;
+     enum reg_class c1;
+     enum reg_class c2;
 {
 #ifdef HARD_REG_SET
   register