OSDN Git Service

Fix mips64vr4100-elf build failure.
[pf3gnuchains/gcc-fork.git] / gcc / regclass.c
index 5a4d72f..e7ea926 100644 (file)
@@ -1,5 +1,5 @@
 /* Compute register class preferences for pseudo-registers.
-   Copyright (C) 1987, 1988, 1991 Free Software Foundation, Inc.
+   Copyright (C) 1987, 88, 91-97, 1998 Free Software Foundation, Inc.
 
 This file is part of GNU CC.
 
@@ -15,7 +15,8 @@ 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, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+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.
@@ -23,6 +24,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
    and a function init_reg_sets to initialize the tables.  */
 
 #include "config.h"
+#include "system.h"
 #include "rtl.h"
 #include "hard-reg-set.h"
 #include "flags.h"
@@ -30,13 +32,23 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include "regs.h"
 #include "insn-config.h"
 #include "recog.h"
+#include "reload.h"
+#include "real.h"
+#include "toplev.h"
+#include "output.h"
 
 #ifndef REGISTER_MOVE_COST
 #define REGISTER_MOVE_COST(x, y) 2
 #endif
 
-#ifndef MEMORY_MOVE_COST
-#define MEMORY_MOVE_COST(x) 2
+/* If we have auto-increment or auto-decrement and we can have secondary
+   reloads, we are not allowed to use classes requiring secondary
+   reloads for pseudos auto-incremented since reload can't handle it.  */
+
+#ifdef AUTO_INC_DEC
+#if defined(SECONDARY_INPUT_RELOAD_CLASS) || defined(SECONDARY_OUTPUT_RELOAD_CLASS)
+#define FORBIDDEN_INC_DEC_CLASSES
+#endif
 #endif
 \f
 /* Register tables used by many passes.  */
@@ -67,6 +79,9 @@ char call_used_regs[FIRST_PSEUDO_REGISTER];
 
 HARD_REG_SET call_used_reg_set;
 
+/* HARD_REG_SET of registers we want to avoid caller saving.  */
+HARD_REG_SET losing_caller_save_reg_set;
+
 /* Data for initializing the above.  */
 
 static char initial_call_used_regs[] = CALL_USED_REGISTERS;
@@ -101,7 +116,17 @@ int reg_alloc_order[FIRST_PSEUDO_REGISTER] = REG_ALLOC_ORDER;
 
 /* For each reg class, a HARD_REG_SET saying which registers are in it.  */
 
-HARD_REG_SET reg_class_contents[] = REG_CLASS_CONTENTS;
+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.  */
+
+#define N_REG_INTS  \
+  ((FIRST_PSEUDO_REGISTER + (HOST_BITS_PER_INT - 1)) / HOST_BITS_PER_INT)
+
+static unsigned int_reg_class_contents[N_REG_CLASSES][N_REG_INTS] 
+  = REG_CLASS_CONTENTS;
 
 /* For each reg class, number of regs it contains.  */
 
@@ -129,15 +154,44 @@ enum reg_class reg_class_superunion[N_REG_CLASSES][N_REG_CLASSES];
 
 char *reg_names[] = REGISTER_NAMES;
 
+/* 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
+   it will be a MODE_FLOAT or a MODE_CC mode, whichever is valid for the
+   register.  */
+
+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];
+
+/* 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_cost[N_REG_CLASSES][N_REG_CLASSES];
+
+#ifdef FORBIDDEN_INC_DEC_CLASSES
+
+/* These are the classes that regs which are auto-incremented or decremented
+   cannot be put in.  */
 
-/* Indexed by n, gives number of times (REG n) is set or clobbered.
-   This information remains valid for the rest of the compilation
-   of the current function; it is used to control register allocation.
+static int forbidden_inc_dec_class[N_REG_CLASSES];
 
-   This information applies to both hard registers and pseudo registers,
-   unlike much of the information above.  */
+/* Indexed by n, is non-zero if (REG n) is used in an auto-inc or auto-dec
+   context.  */
 
-short *reg_n_sets;
+static char *in_inc_dec;
+
+#endif /* FORBIDDEN_INC_DEC_CLASSES */
+
+#ifdef HAVE_SECONDARY_RELOADS
+
+/* Sample MEM values for use by memory_move_secondary_cost.  */
+
+static rtx top_of_stack[MAX_MACHINE_MODE];
+
+#endif /* HAVE_SECONDARY_RELOADS */
 
 /* Function called only once to initialize the above data on reg usage.
    Once this is done, various switches may override.  */
@@ -147,13 +201,26 @@ init_reg_sets ()
 {
   register int i, j;
 
+  /* First copy the register information from the initial int form into
+     the regsets.  */
+
+  for (i = 0; i < N_REG_CLASSES; i++)
+    {
+      CLEAR_HARD_REG_SET (reg_class_contents[i]);
+
+      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)))
+         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);
 
   /* Compute number of hard regs in each class.  */
 
-  bzero (reg_class_size, sizeof reg_class_size);
+  bzero ((char *) reg_class_size, 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))
@@ -253,15 +320,18 @@ init_reg_sets ()
          *p = (enum reg_class) i;
        }
     }
+
+  /* Do any additional initialization regsets may need */
+  INIT_ONCE_REG_SET ();
 }
 
 /* After switches have been processed, which perhaps alter
    `fixed_regs' and `call_used_regs', convert them to HARD_REG_SETs.  */
 
-void
+static void
 init_reg_sets_1 ()
 {
-  register int i;
+  register unsigned int i, j;
 
   /* This macro allows the fixed or call-used registers
      to depend on target flags.  */
@@ -270,16 +340,6 @@ init_reg_sets_1 ()
   CONDITIONAL_REGISTER_USAGE;
 #endif
 
-  for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
-    if (global_regs[i])
-      {
-       if (call_used_regs[i] && ! fixed_regs[i])
-         warning ("call-clobbered register used for global register variable");
-       fixed_regs[i] = 1;
-       /* Prevent saving/restoring of this reg.  */
-       call_used_regs[i] = 1;
-      }
-
   /* Initialize "constant" tables.  */
 
   CLEAR_HARD_REG_SET (fixed_reg_set);
@@ -287,19 +347,11 @@ init_reg_sets_1 ()
   CLEAR_HARD_REG_SET (call_fixed_reg_set);
 
   bcopy (fixed_regs, call_fixed_regs, sizeof call_fixed_regs);
-#ifdef STRUCT_VALUE_REGNUM
-  call_fixed_regs[STRUCT_VALUE_REGNUM] = 1;
-#endif
-#ifdef STATIC_CHAIN_REGNUM
-  call_fixed_regs[STATIC_CHAIN_REGNUM] = 1;
-#endif
 
   n_non_fixed_regs = 0;
 
   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
     {
-      if (FUNCTION_VALUE_REGNO_P (i))
-       call_fixed_regs[i] = 1;
       if (fixed_regs[i])
        SET_HARD_REG_BIT (fixed_reg_set, i);
       else
@@ -309,7 +361,186 @@ init_reg_sets_1 ()
        SET_HARD_REG_BIT (call_used_reg_set, i);
       if (call_fixed_regs[i])
        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);
     }
+
+  /* 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++)
+      {
+       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))
+         cost = 0;
+
+       may_move_cost[i][j] = cost;
+      }
+}
+
+/* Compute the table of register modes.
+   These values are used to record death information for individual registers
+   (as opposed to a multi-register mode).  */
+
+static void
+init_reg_modes ()
+{
+  register int i;
+
+  for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+    {
+      reg_raw_mode[i] = choose_hard_reg_mode (i, 1);
+
+      /* If we couldn't find a valid mode, just use the previous mode.
+         ??? One situation in which we need to do this is on the mips where
+        HARD_REGNO_NREGS (fpreg, [SD]Fmode) returns 2.  Ideally we'd like
+        to use DF mode for the even registers and VOIDmode for the odd
+        (for the cpu models where the odd ones are inaccessible).  */
+      if (reg_raw_mode[i] == VOIDmode)
+       reg_raw_mode[i] = i == 0 ? word_mode : reg_raw_mode[i-1];
+    }
+}
+
+/* Finish initializing the register sets and
+   initialize the register modes.  */
+
+void
+init_regs ()
+{
+  /* This finishes what was started by init_reg_sets, but couldn't be done
+     until after register usage was specified.  */
+  init_reg_sets_1 ();
+
+  init_reg_modes ();
+
+#ifdef HAVE_SECONDARY_RELOADS
+  {
+    /* 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);
+  }
+#endif
+}
+
+#ifdef HAVE_SECONDARY_RELOADS
+
+/* Compute extra cost of moving registers to/from memory due to reloads.
+   Only needed if secondary reloads are required for memory moves.  */
+
+int
+memory_move_secondary_cost (mode, class, in)
+     enum machine_mode mode;
+     enum reg_class class;
+     int in;
+{
+  enum reg_class altclass;
+  int partial_cost = 0;
+  /* We need a memory reference to feed to SECONDARY... macros.  */
+  rtx mem = top_of_stack[(int) mode];
+
+  if (in)
+    {
+#ifdef SECONDARY_INPUT_RELOAD_CLASS
+      altclass = SECONDARY_INPUT_RELOAD_CLASS (class, mode, mem);
+#else
+      altclass = NO_REGS;
+#endif
+    }
+  else
+    {
+#ifdef SECONDARY_OUTPUT_RELOAD_CLASS
+      altclass = SECONDARY_OUTPUT_RELOAD_CLASS (class, mode, mem);
+#else
+      altclass = NO_REGS;
+#endif
+    }
+
+  if (altclass == NO_REGS)
+    return 0;
+
+  if (in)
+    partial_cost = REGISTER_MOVE_COST (altclass, class);
+  else
+    partial_cost = REGISTER_MOVE_COST (class, altclass);
+
+  if (class == 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.
+
+       I'm tempted to put in an abort here, but returning this will
+       probably only give poor estimates, which is what we would've
+       had before this code anyways.  */
+    return partial_cost;
+
+  /* Check if the secondary reload register will also need a
+     secondary reload.  */
+  return memory_move_secondary_cost (mode, altclass, in) + partial_cost;
+}
+#endif
+
+/* Return a machine mode that is legitimate for hard reg REGNO and large
+   enough to save nregs.  If we can't find one, return VOIDmode.  */
+
+enum machine_mode
+choose_hard_reg_mode (regno, nregs)
+     int regno;
+     int nregs;
+{
+  enum machine_mode found_mode = VOIDmode, mode;
+
+  /* We first look for the largest integer mode that can be validly
+     held in REGNO.  If none, we look for the largest floating-point mode.
+     If we still didn't find a valid mode, try CCmode.  */
+
+  for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT);
+       mode != VOIDmode;
+       mode = GET_MODE_WIDER_MODE (mode))
+    if (HARD_REGNO_NREGS (regno, mode) == nregs
+       && HARD_REGNO_MODE_OK (regno, mode))
+      found_mode = mode;
+
+  if (found_mode != VOIDmode)
+    return found_mode;
+
+  for (mode = GET_CLASS_NARROWEST_MODE (MODE_FLOAT);
+       mode != VOIDmode;
+       mode = GET_MODE_WIDER_MODE (mode))
+    if (HARD_REGNO_NREGS (regno, mode) == nregs
+       && HARD_REGNO_MODE_OK (regno, mode))
+      found_mode = mode;
+
+  if (found_mode != VOIDmode)
+    return found_mode;
+
+  if (HARD_REGNO_NREGS (regno, CCmode) == nregs
+      && HARD_REGNO_MODE_OK (regno, CCmode))
+    return CCmode;
+
+  /* We can't find a mode valid for this register.  */
+  return VOIDmode;
 }
 
 /* Specify the usage characteristics of the register named NAME.
@@ -326,55 +557,104 @@ fix_register (name, fixed, call_used)
   /* Decode the name and update the primary form of
      the register info.  */
 
-  for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
-    if (reg_names[i][0] && ! strcmp (reg_names[i], name))
-      {
-       fixed_regs[i] = fixed;
-       call_used_regs[i] = call_used;
-       break;
-      }
-
-  if (i == FIRST_PSEUDO_REGISTER)
+  if ((i = decode_reg_name (name)) >= 0)
+    {
+      fixed_regs[i] = fixed;
+      call_used_regs[i] = call_used;
+    }
+  else
     {
       warning ("unknown register name: %s", name);
+    }
+}
+
+/* Mark register number I as global.  */
+
+void
+globalize_reg (i)
+     int i;
+{
+  if (global_regs[i])
+    {
+      warning ("register used for two global register variables");
       return;
     }
+
+  if (call_used_regs[i] && ! fixed_regs[i])
+    warning ("call-clobbered register used for global register variable");
+
+  global_regs[i] = 1;
+
+  /* If already fixed, nothing else to do.  */
+  if (fixed_regs[i])
+    return;
+
+  fixed_regs[i] = call_used_regs[i] = call_fixed_regs[i] = 1;
+  n_non_fixed_regs--;
+
+  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);
 }
 \f
 /* Now the data and code for the `regclass' pass, which happens
    just before local-alloc.  */
 
-/* savings[R].savings[CL] is twice the amount saved by putting register R
-   in class CL.  This data is used within `regclass' and freed
-   when it is finished.  */
+/* The `costs' struct records the cost of using a hard register of each class
+   and of using memory for each pseudo.  We use this data to set up
+   register class preferences.  */
 
-struct savings
+struct costs
 {
-  short savings[N_REG_CLASSES];
-  short memcost;
-  short nrefs;
+  int cost[N_REG_CLASSES];
+  int mem_cost;
 };
 
-static struct savings *savings;
+/* Record the cost of each class for each pseudo.  */
+
+static struct costs *costs;
+
+/* Record the same data by operand number, accumulated for each alternative
+   in an insn.  The contribution to a pseudo is that of the minimum-cost
+   alternative.  */
+
+static struct costs op_costs[MAX_RECOG_OPERANDS];
 
 /* (enum reg_class) prefclass[R] is the preferred class for pseudo number R.
    This is available after `regclass' is run.  */
 
 static char *prefclass;
 
-/* preferred_or_nothing[R] is nonzero if we should put pseudo number R
-   in memory if we can't get its perferred class.
+/* altclass[R] is a register class that we should use for allocating
+   pseudo number R if no register in the preferred class is available.
+   If no register in this class is available, memory is preferred.
+
+   It might appear to be more general to have a bitmask of classes here,
+   but since it is recommended that there be a class corresponding to the
+   union of most major pair of classes, that generality is not required. 
+
    This is available after `regclass' is run.  */
 
-static char *preferred_or_nothing;
+static char *altclass;
 
-/* Record the depth of loops that we are in, 1 for no loops.  */
+/* Record the depth of loops that we are in.  */
 
 static int loop_depth;
 
-void reg_class_record ();
-void record_address_regs ();
+/* Account for the fact that insns within a loop are executed very commonly,
+   but don't keep doing this as loops go too deep.  */
+
+static int loop_cost;
 
+static void record_reg_classes PROTO((int, int, rtx *, enum machine_mode *,
+                                      char **, rtx));
+static int copy_cost           PROTO((rtx, enum machine_mode, 
+                                      enum reg_class, int));
+static void record_address_regs        PROTO((rtx, enum reg_class, int));
+#ifdef FORBIDDEN_INC_DEC_CLASSES
+static int auto_inc_dec_reg_p  PROTO((rtx, enum machine_mode));
+#endif
+static void reg_scan_mark_refs PROTO((rtx, rtx, 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.
@@ -389,12 +669,14 @@ reg_preferred_class (regno)
   return (enum reg_class) prefclass[regno];
 }
 
-int
-reg_preferred_or_nothing (regno)
+enum reg_class
+reg_alternate_class (regno)
+     int regno;
 {
   if (prefclass == 0)
-    return 0;
-  return preferred_or_nothing[regno];
+    return ALL_REGS;
+
+  return (enum reg_class) altclass[regno];
 }
 
 /* This prevents dump_flow_info from losing if called
@@ -418,394 +700,851 @@ regclass (f, nregs)
 {
 #ifdef REGISTER_CONSTRAINTS
   register rtx insn;
-  register int i;
+  register int i, j;
+  struct costs init_cost;
+  rtx set;
+  int pass;
 
   init_recog ();
 
-  /* Zero out our accumulation of the cost of each class for each reg.  */
+  costs = (struct costs *) alloca (nregs * sizeof (struct costs));
 
-  savings = (struct savings *) alloca (nregs * sizeof (struct savings));
-  bzero (savings, nregs * sizeof (struct savings));
+#ifdef FORBIDDEN_INC_DEC_CLASSES
 
-  loop_depth = 1;
+  in_inc_dec = (char *) alloca (nregs);
 
-  /* Scan the instructions and record each time it would
-     save code to put a certain register in a certain class.  */
+  /* Initialize information about which register classes can be used for
+     pseudos that are auto-incremented or auto-decremented.  It would
+     seem better to put this in init_reg_sets, but we need to be able
+     to allocate rtx, which we can't do that early.  */
 
-  for (insn = f; insn; insn = NEXT_INSN (insn))
+  for (i = 0; i < N_REG_CLASSES; i++)
     {
-      if (GET_CODE (insn) == NOTE
-         && NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG)
-       loop_depth++;
-      else if (GET_CODE (insn) == NOTE
-              && NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_END)
-       loop_depth--;
-      else if ((GET_CODE (insn) == INSN
-               && GET_CODE (PATTERN (insn)) != USE
-               && GET_CODE (PATTERN (insn)) != CLOBBER
-               && GET_CODE (PATTERN (insn)) != ASM_INPUT)
-              || (GET_CODE (insn) == JUMP_INSN
-                  && GET_CODE (PATTERN (insn)) != ADDR_VEC
-                  && GET_CODE (PATTERN (insn)) != ADDR_DIFF_VEC)
-              || GET_CODE (insn) == CALL_INSN)
-       {
-         if (GET_CODE (insn) == INSN && asm_noperands (PATTERN (insn)) >= 0)
-           {
-             int noperands = asm_noperands (PATTERN (insn));
-             /* We don't use alloca because alloca would not free
-                any of the space until this function returns.  */
-             rtx *operands = (rtx *) oballoc (noperands * sizeof (rtx));
-             char **constraints
-               = (char **) oballoc (noperands * sizeof (char *));
+      rtx r = gen_rtx_REG (VOIDmode, 0);
+      enum machine_mode m;
 
-             decode_asm_operands (PATTERN (insn), operands, 0, constraints, 0);
+      for (j = 0; j < FIRST_PSEUDO_REGISTER; j++)
+       if (TEST_HARD_REG_BIT (reg_class_contents[i], j))
+         {
+           REGNO (r) = j;
 
-             for (i = noperands - 1; i >= 0; i--)
-               reg_class_record (operands[i], i, constraints);
+           for (m = VOIDmode; (int) m < (int) MAX_MACHINE_MODE;
+                m = (enum machine_mode) ((int) m + 1))
+             if (HARD_REGNO_MODE_OK (j, m))
+               {
+                 PUT_MODE (r, m);
 
-             obfree (operands);
-           }
-         else
-           {
-             int insn_code_number = recog_memoized (insn);
-             rtx set = single_set (insn);
+                 /* If a register is not directly suitable for an
+                    auto-increment or decrement addressing mode and
+                    requires secondary reloads, disallow its class from
+                    being used in such addresses.  */
+
+                 if ((0
+#ifdef SECONDARY_RELOAD_CLASS
+                      || (SECONDARY_RELOAD_CLASS (BASE_REG_CLASS, m, r)
+                          != NO_REGS)
+#else
+#ifdef SECONDARY_INPUT_RELOAD_CLASS
+                      || (SECONDARY_INPUT_RELOAD_CLASS (BASE_REG_CLASS, m, r)
+                          != NO_REGS)
+#endif
+#ifdef SECONDARY_OUTPUT_RELOAD_CLASS
+                      || (SECONDARY_OUTPUT_RELOAD_CLASS (BASE_REG_CLASS, m, r)
+                          != NO_REGS)
+#endif
+#endif
+                      )
+                     && ! auto_inc_dec_reg_p (r, m))
+                   forbidden_inc_dec_class[i] = 1;
+               }
+         }
+    }
+#endif /* FORBIDDEN_INC_DEC_CLASSES */
+
+  init_cost.mem_cost = 10000;
+  for (i = 0; i < N_REG_CLASSES; i++)
+    init_cost.cost[i] = 10000;
 
-             insn_extract (insn);
+  /* Normally we scan the insns once and determine the best class to use for
+     each register.  However, if -fexpensive_optimizations are on, we do so
+     twice, the second time using the tentative best classes to guide the
+     selection.  */
 
-             for (i = insn_n_operands[insn_code_number] - 1; i >= 0; i--)
-               reg_class_record (recog_operand[i], i,
-                                 insn_operand_constraint[insn_code_number]);
+  for (pass = 0; pass <= flag_expensive_optimizations; pass++)
+    {
+      /* Zero out our accumulation of the cost of each class for each reg.  */
+
+      bzero ((char *) costs, nregs * sizeof (struct costs));
+
+#ifdef FORBIDDEN_INC_DEC_CLASSES
+      bzero (in_inc_dec, nregs);
+#endif
 
-             /* If this insn loads a parameter from its stack slot,
-                then it represents a savings, rather than a cost,
-                if the parameter is stored in memory.  Record this fact.  */
-             if (set != 0 && GET_CODE (SET_DEST (set)) == REG
-                 && GET_CODE (SET_SRC (set)) == MEM)
+      loop_depth = 0, loop_cost = 1;
+
+      /* Scan the instructions and record each time it would
+        save code to put a certain register in a certain class.  */
+
+      for (insn = f; insn; insn = NEXT_INSN (insn))
+       {
+         char *constraints[MAX_RECOG_OPERANDS];
+         enum machine_mode modes[MAX_RECOG_OPERANDS];
+         int nalternatives;
+         int noperands;
+
+         /* 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.  */
+
+         if (GET_CODE (insn) == NOTE
+             && NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG)
+           loop_depth++, loop_cost = 1 << (2 * MIN (loop_depth, 5));
+         else if (GET_CODE (insn) == NOTE
+                  && NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_END)
+           loop_depth--, loop_cost = 1 << (2 * MIN (loop_depth, 5));
+
+         else if ((GET_CODE (insn) == INSN
+                   && GET_CODE (PATTERN (insn)) != USE
+                   && GET_CODE (PATTERN (insn)) != CLOBBER
+                   && GET_CODE (PATTERN (insn)) != ASM_INPUT)
+                  || (GET_CODE (insn) == JUMP_INSN
+                      && GET_CODE (PATTERN (insn)) != ADDR_VEC
+                      && GET_CODE (PATTERN (insn)) != ADDR_DIFF_VEC)
+                  || GET_CODE (insn) == CALL_INSN)
+           {
+             if (GET_CODE (insn) == INSN
+                 && (noperands = asm_noperands (PATTERN (insn))) >= 0)
                {
-                 rtx note = find_reg_note (insn, REG_EQUIV, 0);
-                 if (note != 0 && GET_CODE (XEXP (note, 0)) == MEM)
-                   savings[REGNO (SET_DEST (set))].memcost
-                     -= (MEMORY_MOVE_COST (GET_MODE (SET_DEST (set)))
-                         * loop_depth);
+                 decode_asm_operands (PATTERN (insn), recog_operand, NULL_PTR,
+                                      constraints, modes);
+                 nalternatives = (noperands == 0 ? 0
+                                  : n_occurrences (',', constraints[0]) + 1);
                }
-             
-             /* Improve handling of two-address insns such as
-                (set X (ashift CONST Y)) where CONST must be made to match X.
-                Change it into two insns: (set X CONST)  (set X (ashift X Y)).
-                If we left this for reloading, it would probably get three
-                insns because X and Y might go in the same place.
-                This prevents X and Y from receiving the same hard reg.
-
-                We can only do this if the modes of operands 0 and 1 (which
-                might not be the same) are tieable.  */
-
-             if (optimize
-                 && insn_n_operands[insn_code_number] >= 3
-                 && insn_operand_constraint[insn_code_number][1][0] == '0'
-                 && insn_operand_constraint[insn_code_number][1][1] == 0
-                 && CONSTANT_P (recog_operand[1])
-                 && ! rtx_equal_p (recog_operand[0], recog_operand[1])
-                 && ! rtx_equal_p (recog_operand[0], recog_operand[2])
-                 && GET_CODE (recog_operand[0]) == REG
-                 && MODES_TIEABLE_P (GET_MODE (recog_operand[0]),
-                                     insn_operand_mode[insn_code_number][1]))
+             else
                {
-                 rtx previnsn = prev_real_insn (insn);
-                 rtx dest
-                   = gen_lowpart (insn_operand_mode[insn_code_number][1],
-                                  recog_operand[0]);
-                 rtx newinsn
-                   = emit_insn_before (gen_move_insn (dest, recog_operand[1]),
-                                       insn);
+                 int insn_code_number = recog_memoized (insn);
+                 rtx note;
 
-                 /* If this insn was the start of a basic block,
-                    include the new insn in that block.  */
-                 if (previnsn == 0 || GET_CODE (previnsn) == JUMP_INSN)
+                 set = single_set (insn);
+                 insn_extract (insn);
+
+                 nalternatives = insn_n_alternatives[insn_code_number];
+                 noperands = insn_n_operands[insn_code_number];
+
+                 /* If this insn loads a parameter from its stack slot, then
+                    it represents a savings, rather than a cost, if the
+                    parameter is stored in memory.  Record this fact.  */
+
+                 if (set != 0 && GET_CODE (SET_DEST (set)) == REG
+                     && GET_CODE (SET_SRC (set)) == MEM
+                     && (note = find_reg_note (insn, REG_EQUIV,
+                                               NULL_RTX)) != 0
+                     && GET_CODE (XEXP (note, 0)) == MEM)
                    {
-                     int b;
-                     for (b = 0; b < n_basic_blocks; b++)
-                       if (insn == basic_block_head[b])
-                         basic_block_head[b] = newinsn;
+                     costs[REGNO (SET_DEST (set))].mem_cost
+                       -= (MEMORY_MOVE_COST (GET_MODE (SET_DEST (set)),
+                                             GENERAL_REGS, 1)
+                           * loop_cost);
+                     record_address_regs (XEXP (SET_SRC (set), 0),
+                                          BASE_REG_CLASS, loop_cost * 2);
+                     continue;
+                   }
+             
+                 /* Improve handling of two-address insns such as
+                    (set X (ashift CONST Y)) where CONST must be made to
+                    match X. Change it into two insns: (set X CONST)
+                    (set X (ashift X Y)).  If we left this for reloading, it
+                    would probably get three insns because X and Y might go
+                    in the same place. This prevents X and Y from receiving
+                    the same hard reg.
+
+                    We can only do this if the modes of operands 0 and 1
+                    (which might not be the same) are tieable and we only need
+                    do this during our first pass.  */
+
+                 if (pass == 0 && optimize
+                     && noperands >= 3
+                     && insn_operand_constraint[insn_code_number][1][0] == '0'
+                     && insn_operand_constraint[insn_code_number][1][1] == 0
+                     && CONSTANT_P (recog_operand[1])
+                     && ! rtx_equal_p (recog_operand[0], recog_operand[1])
+                     && ! rtx_equal_p (recog_operand[0], recog_operand[2])
+                     && GET_CODE (recog_operand[0]) == REG
+                     && MODES_TIEABLE_P (GET_MODE (recog_operand[0]),
+                                         insn_operand_mode[insn_code_number][1]))
+                   {
+                     rtx previnsn = prev_real_insn (insn);
+                     rtx dest
+                       = gen_lowpart (insn_operand_mode[insn_code_number][1],
+                                      recog_operand[0]);
+                     rtx newinsn
+                       = emit_insn_before (gen_move_insn (dest,
+                                                          recog_operand[1]),
+                                           insn);
+
+                     /* If this insn was the start of a basic block,
+                        include the new insn in that block.
+                        We need not check for code_label here;
+                        while a basic block can start with a code_label,
+                        INSN could not be at the beginning of that block.  */
+                     if (previnsn == 0 || GET_CODE (previnsn) == JUMP_INSN)
+                       {
+                         int b;
+                         for (b = 0; b < n_basic_blocks; b++)
+                           if (insn == basic_block_head[b])
+                             basic_block_head[b] = newinsn;
+                       }
+
+                     /* This makes one more setting of new insns's dest.  */
+                     REG_N_SETS (REGNO (recog_operand[0]))++;
+
+                     *recog_operand_loc[1] = recog_operand[0];
+                     for (i = insn_n_dups[insn_code_number] - 1; i >= 0; i--)
+                       if (recog_dup_num[i] == 1)
+                         *recog_dup_loc[i] = recog_operand[0];
+
+                     insn = PREV_INSN (newinsn);
+                     continue;
                    }
 
-                 /* This makes one more setting of new insns's destination. */
-                 reg_n_sets[REGNO (recog_operand[0])]++;
+                 for (i = 0; i < noperands; i++)
+                   {
+                     constraints[i]
+                       = insn_operand_constraint[insn_code_number][i];
+                     modes[i] = insn_operand_mode[insn_code_number][i];
+                   }
+               }
+
+             /* If we get here, we are set up to record the costs of all the
+                operands for this insn.  Start by initializing the costs.
+                Then handle any address registers.  Finally record the desired
+                classes for any pseudos, doing it twice if some pair of
+                operands are commutative.  */
+            
+             for (i = 0; i < noperands; i++)
+               {
+                 op_costs[i] = init_cost;
+
+                 if (GET_CODE (recog_operand[i]) == SUBREG)
+                   recog_operand[i] = SUBREG_REG (recog_operand[i]);
 
-                 *recog_operand_loc[1] = recog_operand[0];
-                 for (i = insn_n_dups[insn_code_number] - 1; i >= 0; i--)
-                   if (recog_dup_num[i] == 1)
-                     *recog_dup_loc[i] = recog_operand[0];
+                 if (GET_CODE (recog_operand[i]) == MEM)
+                   record_address_regs (XEXP (recog_operand[i], 0),
+                                        BASE_REG_CLASS, loop_cost * 2);
+                 else if (constraints[i][0] == 'p')
+                   record_address_regs (recog_operand[i],
+                                        BASE_REG_CLASS, loop_cost * 2);
                }
+
+             /* Check for commutative in a separate loop so everything will
+                have been initialized.  We must do this even if one operand
+                is a constant--see addsi3 in m68k.md.  */
+             
+             for (i = 0; i < noperands - 1; i++)
+               if (constraints[i][0] == '%')
+                 {
+                   char *xconstraints[MAX_RECOG_OPERANDS];
+                   int j;
+
+                   /* Handle commutative operands by swapping the constraints.
+                      We assume the modes are the same.  */
+
+                   for (j = 0; j < noperands; j++)
+                     xconstraints[j] = constraints[j];
+
+                   xconstraints[i] = constraints[i+1];
+                   xconstraints[i+1] = constraints[i];
+                   record_reg_classes (nalternatives, noperands,
+                                       recog_operand, modes, xconstraints,
+                                       insn);
+                 }
+
+             record_reg_classes (nalternatives, noperands, recog_operand,
+                                 modes, constraints, insn);
+
+             /* Now add the cost for each operand to the total costs for
+                its register.  */
+
+             for (i = 0; i < noperands; i++)
+               if (GET_CODE (recog_operand[i]) == REG
+                   && REGNO (recog_operand[i]) >= FIRST_PSEUDO_REGISTER)
+                 {
+                   int regno = REGNO (recog_operand[i]);
+                   struct costs *p = &costs[regno], *q = &op_costs[i];
+
+                   p->mem_cost += q->mem_cost * loop_cost;
+                   for (j = 0; j < N_REG_CLASSES; j++)
+                     p->cost[j] += q->cost[j] * loop_cost;
+                 }
            }
        }
-    }
 
-  /* Now for each register look at how desirable each class is
-     and find which class is preferred.  Store that in `prefclass[REGNO]'.  */
+      /* Now for each register look at how desirable each class is
+        and find which class is preferred.  Store that in
+        `prefclass[REGNO]'.  Record in `altclass[REGNO]' the largest register
+        class any of whose registers is better than memory.  */
     
-  prefclass = (char *) oballoc (nregs);
-    
-  preferred_or_nothing = (char *) oballoc (nregs);
-
-  for (i = FIRST_PSEUDO_REGISTER; i < nregs; i++)
-    {
-      register int best_savings = 0;
-      enum reg_class best = ALL_REGS;
-
-      /* This is an enum reg_class, but we call it an int
-        to save lots of casts.  */
-      register int class;
-      register struct savings *p = &savings[i];
+      if (pass == 0)
+       {
+         prefclass = (char *) oballoc (nregs);
+         altclass = (char *) oballoc (nregs);
+       }
 
-      for (class = (int) ALL_REGS - 1; class > 0; class--)
+      for (i = FIRST_PSEUDO_REGISTER; i < nregs; i++)
        {
-         if (p->savings[class] > best_savings)
+         register 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];
+
+         for (class = (int) ALL_REGS - 1; class > 0; class--)
            {
-             best_savings = p->savings[class];
-             best = (enum reg_class) class;
-           }
-         else if (p->savings[class] == best_savings)
-           {
-             best = reg_class_subunion[(int)best][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]
+#ifdef FORBIDDEN_INC_DEC_CLASSES
+                 || (in_inc_dec[i] && forbidden_inc_dec_class[class])
+#endif
+                 )
+               ;
+             else if (p->cost[class] < best_cost)
+               {
+                 best_cost = p->cost[class];
+                 best = (enum reg_class) class;
+               }
+             else if (p->cost[class] == best_cost)
+               best = reg_class_subunion[(int)best][class];
            }
-       }
 
-#if 0
-      /* Note that best_savings is twice number of places something
-        is saved.  */
-      if ((best_savings - p->savings[(int) GENERAL_REGS]) * 5 < reg_n_refs[i])
-       prefclass[i] = (int) GENERAL_REGS;
-      else
-       prefclass[i] = (int) best;
-#else
-      /* We cast to (int) because (char) hits bugs in some compilers.  */
-      prefclass[i] = (int) best;
+         /* Record the alternate register class; i.e., a class for which
+            every register in it is better than using memory.  If adding a
+            class would make a smaller class (i.e., no union of just those
+            classes exists), skip that class.  The major unions of classes
+            should be provided as a register class.  Don't do this if we
+            will be doing it again later.  */
+
+         if (pass == 1 || ! 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]]
+                     > reg_class_size[(int) alt])
+#ifdef FORBIDDEN_INC_DEC_CLASSES
+                 && ! (in_inc_dec[i] && forbidden_inc_dec_class[class])
 #endif
-
-      /* reg_n_refs + p->memcost measures the cost of putting in memory.
-        If a GENERAL_REG is no better, don't even try for one.
-        Since savings and memcost are 2 * number of refs,
-        this effectively counts each memory operand not needing reloading
-        as costing 1/2 of a reload insn.  */
-      if (reg_n_refs != 0)
-       preferred_or_nothing[i]
-         = ((best_savings - p->savings[(int) GENERAL_REGS])
-            >= p->nrefs + p->memcost);
+                 )
+               alt = reg_class_subunion[(int) alt][class];
+         
+         /* If we don't add any classes, nothing to try.  */
+         if (alt == best)
+           alt = NO_REGS;
+
+         /* We cast to (int) because (char) hits bugs in some compilers.  */
+         prefclass[i] = (int) best;
+         altclass[i] = (int) alt;
+       }
     }
 #endif /* REGISTER_CONSTRAINTS */
 }
 \f
 #ifdef REGISTER_CONSTRAINTS
 
-/* Scan an operand OP for register class preferences.
-   OPNO is the operand number, and CONSTRAINTS is the constraint
-   vector for the insn.
+/* Record the cost of using memory or registers of various classes for
+   the operands in INSN.
 
-   Record the preferred register classes from the constraint for OP
-   if OP is a register.  If OP is a memory reference, record suitable
-   preferences for registers used in the address.  */
+   N_ALTS is the number of alternatives.
 
-void
-reg_class_record (op, opno, constraints)
-     rtx op;
-     int opno;
+   N_OPS is the number of operands.
+
+   OPS is an array of the operands.
+
+   MODES are the modes of the operands, in case any are VOIDmode.
+
+   CONSTRAINTS are the constraints to use for the operands.  This array
+   is modified by this procedure.
+
+   This procedure works alternative by alternative.  For each alternative
+   we assume that we will be able to allocate all pseudos to their ideal
+   register class and calculate the cost of using that alternative.  Then
+   we compute for each operand that is a pseudo-register, the cost of 
+   having the pseudo allocated to each register class and using it in that
+   alternative.  To this cost is added the cost of the alternative.
+
+   The cost of each class for this insn is its lowest cost among all the
+   alternatives.  */
+
+static void
+record_reg_classes (n_alts, n_ops, ops, modes, constraints, insn)
+     int n_alts;
+     int n_ops;
+     rtx *ops;
+     enum machine_mode *modes;
      char **constraints;
+     rtx insn;
 {
-  char *constraint = constraints[opno];
-  register char *p;
-  register enum reg_class class = NO_REGS;
-  char *next = 0;
-  int memok = 0;
-  int double_cost = 0;
-
-  if (op == 0)
-    return;
+  int alt;
+  enum op_type {OP_READ, OP_WRITE, OP_READ_WRITE} op_types[MAX_RECOG_OPERANDS];
+  int i, j;
+  rtx set;
 
-  while (1)
-    {
-      if (GET_CODE (op) == SUBREG)
-       op = SUBREG_REG (op);
-      else break;
-    }
+  /* By default, each operand is an input operand.  */
 
-  /* Memory reference: scan the address.  */
+  for (i = 0; i < n_ops; i++)
+    op_types[i] = OP_READ;
 
-  if (GET_CODE (op) == MEM)
-    record_address_regs (XEXP (op, 0), 2, 0);
+  /* Process each alternative, each time minimizing an operand's cost with
+     the cost for each operand in that alternative.  */
 
-  if (GET_CODE (op) != REG)
+  for (alt = 0; alt < n_alts; alt++)
     {
-      /* If the constraint says the operand is supposed to BE an address,
-        scan it as one.  */
+      struct costs this_op_costs[MAX_RECOG_OPERANDS];
+      int alt_fail = 0;
+      int alt_cost = 0;
+      enum reg_class classes[MAX_RECOG_OPERANDS];
+      int class;
 
-      if (constraint != 0 && constraint[0] == 'p')
-       record_address_regs (op, 2, 0);
-      return;
-    }
+      for (i = 0; i < n_ops; i++)
+       {
+         char *p = constraints[i];
+         rtx op = ops[i];
+         enum machine_mode mode = modes[i];
+         int allows_mem = 0;
+         int win = 0;
+         char c;
 
-  /* Operand is a register: examine the constraint for specified classes.  */
+         /* If this operand has no constraints at all, we can conclude 
+            nothing about it since anything is valid.  */
 
-  for (p = constraint; *p || next; p++)
-    {
-      enum reg_class new_class = NO_REGS;
+         if (*p == 0)
+           {
+             if (GET_CODE (op) == REG && REGNO (op) >= FIRST_PSEUDO_REGISTER)
+               bzero ((char *) &this_op_costs[i], sizeof this_op_costs[i]);
+
+             continue;
+           }
+
+         if (*p == '%')
+           p++;
+
+         /* If this alternative is only relevant when this operand
+            matches a previous operand, we do different things depending
+            on whether this operand is a pseudo-reg or not.  */
+
+         if (p[0] >= '0' && p[0] <= '0' + i && (p[1] == ',' || p[1] == 0))
+           {
+             j = p[0] - '0';
+             classes[i] = classes[j];
+
+             if (GET_CODE (op) != REG || REGNO (op) < FIRST_PSEUDO_REGISTER)
+               {
+                 /* If this matches the other operand, we have no added
+                    cost and we win.  */
+                 if (rtx_equal_p (ops[j], op))
+                   win = 1;
+
+                 /* If we can put the other operand into a register, add to
+                    the cost of this alternative the cost to copy this
+                    operand to the register used for the other operand.  */
+
+                 else if (classes[j] != NO_REGS)
+                   alt_cost += copy_cost (op, mode, classes[j], 1), win = 1;
+               }
+             else if (GET_CODE (ops[j]) != REG
+                      || REGNO (ops[j]) < FIRST_PSEUDO_REGISTER)
+               {
+                 /* This op is a pseudo but the one it matches is not.  */
+                 
+                 /* If we can't put the other operand into a register, this
+                    alternative can't be used.  */
+
+                 if (classes[j] == NO_REGS)
+                   alt_fail = 1;
+
+                 /* Otherwise, add to the cost of this alternative the cost
+                    to copy the other operand to the register used for this
+                    operand.  */
+
+                 else
+                   alt_cost += copy_cost (ops[j], mode, classes[j], 1);
+               }
+             else
+               {
+                 /* The costs of this operand are the same as that of the
+                    other operand.  However, if we cannot tie them, this
+                    alternative needs to do a copy, which is one
+                    instruction.  */
+
+                 this_op_costs[i] = this_op_costs[j];
+                 if (REGNO (ops[i]) != REGNO (ops[j])
+                     && ! find_reg_note (insn, REG_DEAD, op))
+                   alt_cost += 2;
+
+                 /* This is in place of ordinary cost computation
+                    for this operand, so skip to the end of the
+                    alternative (should be just one character).  */
+                 while (*p && *p++ != ',')
+                   ;
+
+                 constraints[i] = p;
+                 continue;
+               }
+           }
+
+         /* Scan all the constraint letters.  See if the operand matches
+            any of the constraints.  Collect the valid register classes
+            and see if this operand accepts memory.  */
+
+         classes[i] = NO_REGS;
+         while (*p && (c = *p++) != ',')
+           switch (c)
+             {
+             case '=':
+               op_types[i] = OP_WRITE;
+               break;
+
+             case '+':
+               op_types[i] = OP_READ_WRITE;
+               break;
+
+             case '*':
+               /* Ignore the next letter for this pass.  */
+               p++;
+               break;
+
+             case '?':
+               alt_cost += 2;
+             case '%':
+             case '!':  case '#':
+             case '&':
+             case '0':  case '1':  case '2':  case '3':  case '4':
+             case 'p':
+               break;
+
+             case 'm':  case 'o':  case 'V':
+               /* It doesn't seem worth distinguishing between offsettable
+                  and non-offsettable addresses here.  */
+               allows_mem = 1;
+               if (GET_CODE (op) == MEM)
+                 win = 1;
+               break;
+
+             case '<':
+               if (GET_CODE (op) == MEM
+                   && (GET_CODE (XEXP (op, 0)) == PRE_DEC
+                       || GET_CODE (XEXP (op, 0)) == POST_DEC))
+                 win = 1;
+               break;
+
+             case '>':
+               if (GET_CODE (op) == MEM
+                   && (GET_CODE (XEXP (op, 0)) == PRE_INC
+                       || GET_CODE (XEXP (op, 0)) == POST_INC))
+                 win = 1;
+               break;
+
+             case 'E':
+#ifndef REAL_ARITHMETIC
+               /* Match any floating double constant, but only if
+                  we can examine the bits of it reliably.  */
+               if ((HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT
+                    || HOST_BITS_PER_WIDE_INT != BITS_PER_WORD)
+                   && GET_MODE (op) != VOIDmode && ! flag_pretend_float)
+                 break;
+#endif
+               if (GET_CODE (op) == CONST_DOUBLE)
+                 win = 1;
+               break;
+
+             case 'F':
+               if (GET_CODE (op) == CONST_DOUBLE)
+                 win = 1;
+               break;
+
+             case 'G':
+             case 'H':
+               if (GET_CODE (op) == CONST_DOUBLE
+                   && CONST_DOUBLE_OK_FOR_LETTER_P (op, c))
+                 win = 1;
+               break;
+
+             case 's':
+               if (GET_CODE (op) == CONST_INT
+                   || (GET_CODE (op) == CONST_DOUBLE
+                       && GET_MODE (op) == VOIDmode))
+                 break;
+             case 'i':
+               if (CONSTANT_P (op)
+#ifdef LEGITIMATE_PIC_OPERAND_P
+                   && (! flag_pic || LEGITIMATE_PIC_OPERAND_P (op))
+#endif
+                   )
+                 win = 1;
+               break;
+
+             case 'n':
+               if (GET_CODE (op) == CONST_INT
+                   || (GET_CODE (op) == CONST_DOUBLE
+                       && GET_MODE (op) == VOIDmode))
+                 win = 1;
+               break;
+
+             case 'I':
+             case 'J':
+             case 'K':
+             case 'L':
+             case 'M':
+             case 'N':
+             case 'O':
+             case 'P':
+               if (GET_CODE (op) == CONST_INT
+                   && CONST_OK_FOR_LETTER_P (INTVAL (op), c))
+                 win = 1;
+               break;
+
+             case 'X':
+               win = 1;
+               break;
 
-      if (*p == 0)
-       {
-         p = next;
-         next = 0;
-       }
-      switch (*p)
-       {
-       case '=':
-       case '?':
-       case '#':
-       case '&':
-       case '!':
-       case '%':
-       case 'E':
-       case 'F':
-       case 'G':
-       case 'H':
-       case 'i':
-       case 'n':
-       case 's':
-       case 'p':
-       case ',':
-       case 'I':
-       case 'J':
-       case 'K':
-       case 'L':
-       case 'M':
-       case 'N':
-       case 'O':
-       case 'P':
 #ifdef EXTRA_CONSTRAINT
-       case 'Q':
-       case 'R':
-       case 'S':
-       case 'T':
-       case 'U':
+              case 'Q':
+              case 'R':
+              case 'S':
+              case 'T':
+              case 'U':
+               if (EXTRA_CONSTRAINT (op, c))
+                 win = 1;
+               break;
 #endif
-       case 'V':
-       case 'X':
-         break;
-
-       case '+':
-         /* An input-output operand is twice as costly if it loses.  */
-         double_cost = 1;
-         break;
-
-       case 'm':
-       case 'o':
-         memok = 1;
-         break;
-
-         /* * means ignore following letter
-            when choosing register preferences.  */
-       case '*':
-         p++;
-         break;
-
-       case 'g':
-       case 'r':
-         new_class = GENERAL_REGS;
-         break;
-
-       case '0':
-       case '1':
-       case '2':
-       case '3':
-       case '4':
-         /* If constraint says "match another operand",
-            use that operand's constraint to choose preferences.  */
-         if (*p - '0' < opno)
+
+             case 'g':
+               if (GET_CODE (op) == MEM
+                   || (CONSTANT_P (op)
+#ifdef LEGITIMATE_PIC_OPERAND_P
+                       && (! flag_pic || LEGITIMATE_PIC_OPERAND_P (op))
+#endif
+                       ))
+                 win = 1;
+               allows_mem = 1;
+             case 'r':
+               classes[i]
+                 = reg_class_subunion[(int) classes[i]][(int) GENERAL_REGS];
+               break;
+
+             default:
+               classes[i]
+                 = reg_class_subunion[(int) classes[i]]
+                   [(int) REG_CLASS_FROM_LETTER (c)];
+             }
+
+         constraints[i] = p;
+
+         /* 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,
+            since we want to assume that all pseudos get allocated for
+            register preferencing.  If some register class is valid, compute
+            the costs of moving the pseudo into that class.  */
+
+         if (GET_CODE (op) == REG && REGNO (op) >= FIRST_PSEUDO_REGISTER)
            {
-             opno = *p - '0';
-             next = constraints[opno];
+             if (classes[i] == NO_REGS)
+               alt_fail = 1;
+             else
+               {
+                 struct costs *pp = &this_op_costs[i];
+
+                 for (class = 0; class < N_REG_CLASSES; class++)
+                   pp->cost[class] = may_move_cost[class][(int) classes[i]];
+
+                 /* If the alternative actually allows memory, make things
+                    a bit cheaper since we won't need an extra insn to
+                    load it.  */
+
+                 pp->mem_cost = (MEMORY_MOVE_COST (mode, classes[i], 1)
+                                 - allows_mem);
+
+                 /* If we have assigned a class to this register in our
+                    first pass, add a cost to this alternative corresponding
+                    to what we would add if this register were not in the
+                    appropriate class.  */
+
+                 if (prefclass)
+                   alt_cost
+                     += may_move_cost[prefclass[REGNO (op)]][(int) classes[i]];
+               }
            }
-         break;
 
-       default:
-         new_class = REG_CLASS_FROM_LETTER (*p);
-         break;
-       }
+         /* Otherwise, if this alternative wins, either because we
+            have already determined that or if we have a hard register of
+            the proper class, there is no cost for this alternative.  */
 
-      /* If this object can fit into the class requested, compute the subunion
-        of the requested class and classes found so far.  */
-      if (CLASS_MAX_NREGS (new_class, GET_MODE (op))
-         <= reg_class_size[(int) new_class])
-       class = reg_class_subunion[(int) class][(int) new_class];
-    }
+         else if (win
+                  || (GET_CODE (op) == REG
+                      && reg_fits_class_p (op, classes[i], 0, GET_MODE (op))))
+           ;
 
-  {
-    register int i;
-    register struct savings *pp;
-    register enum reg_class class1;
-    int cost = 2 * (1 + double_cost) * loop_depth;
-    pp = &savings[REGNO (op)];
+         /* If registers are valid, the cost of this alternative includes
+            copying the object to and/or from a register.  */
 
-    /* Increment the savings for this reg
-       for each class contained in the one the constraint asks for.  */
+         else if (classes[i] != NO_REGS)
+           {
+             if (op_types[i] != OP_WRITE)
+               alt_cost += copy_cost (op, mode, classes[i], 1);
 
-    if (class != NO_REGS && class != ALL_REGS)
-      {
-       int extracost;
+             if (op_types[i] != OP_READ)
+               alt_cost += copy_cost (op, mode, classes[i], 0);
+           }
 
-       pp->savings[(int) class] += cost;
-       for (i = 0; ; i++)
-         {
-           class1 = reg_class_subclasses[(int)class][i];
-           if (class1 == LIM_REG_CLASSES)
-             break;
-           pp->savings[(int) class1] += cost;
-         }
-       /* If it's slow to move data between this class and GENERAL_REGS,
-          record that fact.  */
-       extracost = (REGISTER_MOVE_COST (class, GENERAL_REGS) - 2) * loop_depth;
-       if (extracost > 0)
+         /* The only other way this alternative can be used is if this is a
+            constant that could be placed into memory.  */
+
+         else if (CONSTANT_P (op) && allows_mem)
+           alt_cost += MEMORY_MOVE_COST (mode, classes[i], 1);
+         else
+           alt_fail = 1;
+       }
+
+      if (alt_fail)
+       continue;
+
+      /* Finally, update the costs with the information we've calculated
+        about this alternative.  */
+
+      for (i = 0; i < n_ops; i++)
+       if (GET_CODE (ops[i]) == REG
+           && REGNO (ops[i]) >= FIRST_PSEUDO_REGISTER)
          {
-           /* Check that this class and GENERAL_REGS don't overlap.
-              REGISTER_MOVE_COST is meaningless if there is overlap.  */
-           HARD_REG_SET temp;
-           COMPL_HARD_REG_SET (temp, reg_class_contents[(int) class]);
-           GO_IF_HARD_REG_SUBSET (reg_class_contents[(int) GENERAL_REGS],
-                                  temp, label1);
-           /* Overlap.  */
-           goto label2;
-
-         label1: /* No overlap.  */
-           /* Charge this extra cost to GENERAL_REGS
-              and all its subclasses (none of which overlap this class).  */
-           extracost = extracost * cost / (2 * loop_depth);
-           pp->savings[(int) GENERAL_REGS] -= extracost;
-           for (i = 0; ; i++)
-             {
-               class1 = reg_class_subclasses[(int)GENERAL_REGS][i];
-               if (class1 == LIM_REG_CLASSES)
-                 break;
-               pp->savings[(int) class1] -= extracost;
-             }
+           struct costs *pp = &op_costs[i], *qq = &this_op_costs[i];
+           int scale = 1 + (op_types[i] == OP_READ_WRITE);
+
+           pp->mem_cost = MIN (pp->mem_cost,
+                               (qq->mem_cost + alt_cost) * scale);
 
-         label2: ;
+           for (class = 0; class < N_REG_CLASSES; class++)
+             pp->cost[class] = MIN (pp->cost[class],
+                                    (qq->cost[class] + alt_cost) * scale);
          }
-      }
+    }
 
-    if (! memok)
-      pp->memcost += (MEMORY_MOVE_COST (GET_MODE (op)) * (1 + double_cost)
-                     - 1) * loop_depth;
-    pp->nrefs += loop_depth;
-  }
+  /* If this insn is a single set copying operand 1 to operand 0
+     and one is a pseudo with the other a hard reg that is in its
+     own register class, set the cost of that register class to -1.  */
+
+  if ((set = single_set (insn)) != 0
+      && ops[0] == SET_DEST (set) && ops[1] == SET_SRC (set)
+      && GET_CODE (ops[0]) == REG && GET_CODE (ops[1]) == REG)
+    for (i = 0; i <= 1; i++)
+      if (REGNO (ops[i]) >= FIRST_PSEUDO_REGISTER)
+       {
+         int regno = REGNO (ops[!i]);
+         enum machine_mode mode = GET_MODE (ops[!i]);
+         int class;
+         int nr;
+
+         if (regno >= FIRST_PSEUDO_REGISTER && prefclass != 0
+             && (reg_class_size[prefclass[regno]]
+                 == CLASS_MAX_NREGS (prefclass[regno], mode)))
+           op_costs[i].cost[prefclass[regno]] = -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] == CLASS_MAX_NREGS (class, mode))
+               {
+                 if (reg_class_size[class] == 1)
+                   op_costs[i].cost[class] = -1;
+                 else
+                   {
+                     for (nr = 0; nr < HARD_REGNO_NREGS(regno, mode); nr++)
+                       {
+                         if (!TEST_HARD_REG_BIT (reg_class_contents[class], regno + nr))
+                           break;
+                       }
+
+                     if (nr == HARD_REGNO_NREGS(regno,mode))
+                       op_costs[i].cost[class] = -1;
+                   }
+               }
+       }
 }
+\f
+/* Compute the cost of loading X into (if TO_P is non-zero) or from (if
+   TO_P is zero) a register of class CLASS in mode MODE.
+
+   X must not be a pseudo.  */
+
+static int
+copy_cost (x, mode, class, to_p)
+     rtx x;
+     enum machine_mode mode;
+     enum reg_class class;
+     int to_p;
+{
+#ifdef HAVE_SECONDARY_RELOADS
+  enum reg_class secondary_class = NO_REGS;
+#endif
 
+  /* If X is a SCRATCH, there is actually nothing to move since we are
+     assuming optimal allocation.  */
+
+  if (GET_CODE (x) == SCRATCH)
+    return 0;
+
+  /* Get the class we will actually use for a reload.  */
+  class = PREFERRED_RELOAD_CLASS (x, class);
+
+#ifdef HAVE_SECONDARY_RELOADS
+  /* If we need a secondary reload (we assume here that we are using 
+     the secondary reload as an intermediate, not a scratch register), the
+     cost is that to load the input into the intermediate register, then
+     to copy them.  We use a special value of TO_P to avoid recursion.  */
+
+#ifdef SECONDARY_INPUT_RELOAD_CLASS
+  if (to_p == 1)
+    secondary_class = SECONDARY_INPUT_RELOAD_CLASS (class, mode, x);
+#endif
+
+#ifdef SECONDARY_OUTPUT_RELOAD_CLASS
+  if (! to_p)
+    secondary_class = SECONDARY_OUTPUT_RELOAD_CLASS (class, mode, x);
+#endif
+
+  if (secondary_class != NO_REGS)
+    return (move_cost[(int) secondary_class][(int) class]
+           + copy_cost (x, mode, secondary_class, 2));
+#endif  /* HAVE_SECONDARY_RELOADS */
+
+  /* For memory, use the memory move cost, for (hard) registers, use the
+     cost to move between the register classes, and use 2 for everything
+     else (constants).  */
+
+  if (GET_CODE (x) == MEM || class == NO_REGS)
+    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];
+
+  else
+    /* If this is a constant, we may eventually want to call rtx_cost here.  */
+    return 2;
+}
+\f
 /* Record the pseudo registers we must reload into hard registers
    in a subexpression of a memory address, X.
-   BCOST is the cost if X is a register and it fails to be in BASE_REG_CLASS.
-   ICOST is the cost if it fails to be in INDEX_REG_CLASS. */
 
-void
-record_address_regs (x, bcost, icost)
+   CLASS is the class that the register needs to be in and is either
+   BASE_REG_CLASS or INDEX_REG_CLASS.
+
+   SCALE is twice the amount to multiply the cost by (it is twice so we
+   can represent half-cost adjustments).  */
+
+static void
+record_address_regs (x, class, scale)
      rtx x;
-     int bcost, icost;
+     enum reg_class class;
+     int scale;
 {
   register enum rtx_code code = GET_CODE (x);
 
@@ -824,66 +1563,104 @@ record_address_regs (x, bcost, icost)
         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.  */
+        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
+        the register is being used as a pointer.  */
+
       {
        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);
-       int icost0 = 0;
-       int icost1 = 0;
-       int suppress1 = 0;
-       int suppress0 = 0;
 
        /* Look inside subregs.  */
-       while (code0 == SUBREG)
+       if (code0 == SUBREG)
          arg0 = SUBREG_REG (arg0), code0 = GET_CODE (arg0);
-       while (code1 == SUBREG)
+       if (code1 == SUBREG)
          arg1 = SUBREG_REG (arg1), code1 = GET_CODE (arg1);
 
-       if (code0 == MULT || code1 == MEM)
-         icost0 = 2;
-       else if (code1 == MULT || code0 == MEM)
-         icost1 = 2;
-       else if (code0 == CONST_INT)
-         suppress0 = 1;
-       else if (code1 == CONST_INT)
-         suppress1 = 1;
-       else if (code0 == REG && code1 == REG)
+       /* If this machine only allows one register per address, it must
+          be in the first operand.  */
+
+       if (MAX_REGS_PER_ADDRESS == 1)
+         record_address_regs (arg0, class, scale);
+
+       /* If index and base registers are the same on this machine, just
+          record registers in any non-constant operands.  We assume here,
+          as well as in the tests below, that all addresses are in 
+          canonical form.  */
+
+       else if (INDEX_REG_CLASS == BASE_REG_CLASS)
          {
-           if (REGNO_POINTER_FLAG (REGNO (arg0)))
-             icost1 = 2;
-           else if (REGNO_POINTER_FLAG (REGNO (arg1)))
-             icost0 = 2;
-           else
-             icost0 = icost1 = 1;
+           record_address_regs (arg0, class, scale);
+           if (! CONSTANT_P (arg1))
+             record_address_regs (arg1, class, scale);
          }
-       else if (code0 == REG)
+
+       /* If the second operand is a constant integer, it doesn't change
+          what class the first operand must be.  */
+
+       else if (code1 == CONST_INT || code1 == CONST_DOUBLE)
+         record_address_regs (arg0, class, scale);
+
+       /* If the second operand is a symbolic constant, the first operand
+          must be an index register.  */
+
+       else if (code1 == SYMBOL_REF || code1 == CONST || code1 == LABEL_REF)
+         record_address_regs (arg0, INDEX_REG_CLASS, scale);
+
+       /* If both operands are registers but one is already a hard register
+          of index or base class, give the other the class that the hard
+          register is not.  */
+
+#ifdef REG_OK_FOR_BASE_P
+       else if (code0 == REG && code1 == REG
+                && REGNO (arg0) < FIRST_PSEUDO_REGISTER
+                && (REG_OK_FOR_BASE_P (arg0) || REG_OK_FOR_INDEX_P (arg0)))
+         record_address_regs (arg1,
+                              REG_OK_FOR_BASE_P (arg0)
+                              ? INDEX_REG_CLASS : BASE_REG_CLASS,
+                              scale);
+       else if (code0 == REG && code1 == REG
+                && REGNO (arg1) < FIRST_PSEUDO_REGISTER
+                && (REG_OK_FOR_BASE_P (arg1) || REG_OK_FOR_INDEX_P (arg1)))
+         record_address_regs (arg0,
+                              REG_OK_FOR_BASE_P (arg1)
+                              ? INDEX_REG_CLASS : BASE_REG_CLASS,
+                              scale);
+#endif
+
+       /* If one operand is known to be a pointer, it must be the base
+          with the other operand the index.  Likewise if the other operand
+          is a MULT.  */
+
+       else if ((code0 == REG && REGNO_POINTER_FLAG (REGNO (arg0)))
+                || code1 == MULT)
          {
-           if (code1 == PLUS
-               && ! REGNO_POINTER_FLAG (REGNO (arg0)))
-             icost0 = 2;
-           else
-             REGNO_POINTER_FLAG (REGNO (arg0)) = 1;
+           record_address_regs (arg0, BASE_REG_CLASS, scale);
+           record_address_regs (arg1, INDEX_REG_CLASS, scale);
          }
-       else if (code1 == REG)
+       else if ((code1 == REG && REGNO_POINTER_FLAG (REGNO (arg1)))
+                || code0 == MULT)
          {
-           if (code0 == PLUS
-               && ! REGNO_POINTER_FLAG (REGNO (arg1)))
-             icost1 = 2;
-           else
-             REGNO_POINTER_FLAG (REGNO (arg1)) = 1;
+           record_address_regs (arg0, INDEX_REG_CLASS, scale);
+           record_address_regs (arg1, BASE_REG_CLASS, scale);
          }
 
-       /* ICOST0 determines whether we are treating operand 0
-          as a base register or as an index register.
-          SUPPRESS0 nonzero means it isn't a register at all.
-          ICOST1 and SUPPRESS1 are likewise for operand 1.  */
+       /* Otherwise, count equal chances that each might be a base
+          or index register.  This case should be rare.  */
 
-       if (! suppress0)
-         record_address_regs (arg0, 2 - icost0, icost0);
-       if (! suppress1)
-         record_address_regs (arg1, 2 - icost1, icost1);
+       else
+         {
+           record_address_regs (arg0, BASE_REG_CLASS, scale / 2);
+           record_address_regs (arg0, INDEX_REG_CLASS, scale / 2);
+           record_address_regs (arg1, BASE_REG_CLASS, scale / 2);
+           record_address_regs (arg1, INDEX_REG_CLASS, scale / 2);
+         }
       }
       break;
 
@@ -893,52 +1670,27 @@ record_address_regs (x, bcost, icost)
     case PRE_DEC:
       /* 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.  */
-      record_address_regs (XEXP (x, 0), 2 * bcost, 2 * icost);
+        if it ends up in the wrong place.  If the operand is a pseudo,
+        show it is being used in an INC_DEC context.  */
+
+#ifdef FORBIDDEN_INC_DEC_CLASSES
+      if (GET_CODE (XEXP (x, 0)) == REG
+         && REGNO (XEXP (x, 0)) >= FIRST_PSEUDO_REGISTER)
+       in_inc_dec[REGNO (XEXP (x, 0))] = 1;
+#endif
+
+      record_address_regs (XEXP (x, 0), class, 2 * scale);
       break;
 
     case REG:
       {
-       register struct savings *pp;
-       register enum reg_class class, class1;
-       pp = &savings[REGNO (x)];
-       pp->nrefs += loop_depth;
-
-       /* We have an address (or part of one) that is just one register.  */
-
-       /* Record BCOST worth of savings for classes contained
-          in BASE_REG_CLASS.  */
-
-       class = BASE_REG_CLASS;
-       if (class != NO_REGS && class != ALL_REGS)
-         {
-           register int i;
-           pp->savings[(int) class] += bcost * loop_depth;
-           for (i = 0; ; i++)
-             {
-               class1 = reg_class_subclasses[(int)class][i];
-               if (class1 == LIM_REG_CLASSES)
-                 break;
-               pp->savings[(int) class1] += bcost * loop_depth;
-             }
-         }
+       register struct costs *pp = &costs[REGNO (x)];
+       register int i;
 
-       /* Record ICOST worth of savings for classes contained
-          in INDEX_REG_CLASS.  */
+       pp->mem_cost += (MEMORY_MOVE_COST (Pmode, class, 1) * scale) / 2;
 
-       class = INDEX_REG_CLASS;
-       if (icost != 0 && class != NO_REGS && class != ALL_REGS)
-         {
-           register int i;
-           pp->savings[(int) class] += icost * loop_depth;
-           for (i = 0; ; i++)
-             {
-               class1 = reg_class_subclasses[(int)class][i];
-               if (class1 == LIM_REG_CLASSES)
-                 break;
-               pp->savings[(int) class1] += icost * loop_depth;
-             }
-         }
+       for (i = 0; i < N_REG_CLASSES; i++)
+         pp->cost[i] += (may_move_cost[i][(int) class] * scale) / 2;
       }
       break;
 
@@ -948,45 +1700,148 @@ record_address_regs (x, bcost, icost)
        register int i;
        for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
          if (fmt[i] == 'e')
-           record_address_regs (XEXP (x, i), bcost, icost);
+           record_address_regs (XEXP (x, i), class, scale);
       }
     }
 }
+\f
+#ifdef FORBIDDEN_INC_DEC_CLASSES
+
+/* Return 1 if REG is valid as an auto-increment memory reference
+   to an object of MODE.  */
+
+static int
+auto_inc_dec_reg_p (reg, mode)
+     rtx reg;
+     enum machine_mode mode;
+{
+#ifdef HAVE_POST_INCREMENT
+  if (memory_address_p (mode, gen_rtx_POST_INC (Pmode, reg)))
+    return 1;
+#endif
+
+#ifdef HAVE_POST_DECREMENT
+  if (memory_address_p (mode, gen_rtx_POST_DEC (Pmode, reg)))
+    return 1;
+#endif
+
+#ifdef HAVE_PRE_INCREMENT
+  if (memory_address_p (mode, gen_rtx_PRE_INC (Pmode, reg)))
+    return 1;
+#endif
+
+#ifdef HAVE_PRE_DECREMENT
+  if (memory_address_p (mode, gen_rtx_PRE_DEC (Pmode, reg)))
+    return 1;
+#endif
+
+  return 0;
+}
+#endif
+
 #endif /* REGISTER_CONSTRAINTS */
 \f
-/* This is the `regscan' pass of the compiler, run just before cse
-   and again just before loop.
+/* 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
+   NEW_P is non zero, initialize all of the registers, otherwise only
+   initialize the new registers allocated.  The same table is kept from
+   function to function, only reallocating it when we need more room.  If
+   RENUMBER_P is non zero, allocate the reg_renumber array also.  */
 
-   It finds the first and last use of each pseudo-register
-   and records them in the vectors regno_first_uid, regno_last_uid
-   and counts the number of sets in the vector reg_n_sets.
+void
+allocate_reg_info (num_regs, new_p, renumber_p)
+     int num_regs;
+     int new_p;
+     int renumber_p;
+{
+  static int regno_allocated = 0;
+  static short *renumber = (short *)0;
+  int i;
+  int size_info;
+  int size_renumber;
+  int min = (new_p) ? 0 : reg_n_max;
 
-   REPEAT is nonzero the second time this is called.  */
+  /* If this message come up, and you want to fix it, then all of the tables
+     like reg_renumber, etc. that use short will have to be found and lengthed
+     to int or HOST_WIDE_INT.  */
+
+  /* Free up all storage allocated */
+  if (num_regs < 0)
+    {
+      if (reg_n_info)
+       {
+         free ((char *)reg_n_info);
+         free ((char *)renumber);
+         reg_n_info = (reg_info *)0;
+         renumber = (short *)0;
+       }
+      regno_allocated = 0;
+      reg_n_max = 0;
+      return;
+    }
+
+  if (num_regs > regno_allocated)
+    {
+      regno_allocated = num_regs + (num_regs / 20);    /* add some slop space */
+      size_info = regno_allocated * sizeof (reg_info);
+      size_renumber = regno_allocated * sizeof (short);
+
+      if (!reg_n_info)
+       {
+         reg_n_info = (reg_info *) xmalloc (size_info);
+         renumber = (short *) xmalloc (size_renumber);
+       }
+
+      else if (new_p)          /* if we're zapping everything, no need to realloc */
+       {
+         free ((char *)reg_n_info);
+         free ((char *)renumber);
+         reg_n_info = (reg_info *) xmalloc (size_info);
+         renumber = (short *) xmalloc (size_renumber);
+       }
 
-/* Indexed by pseudo register number, gives uid of first insn using the reg
-   (as of the time reg_scan is called).  */
+      else
+       {
+         reg_n_info = (reg_info *) xrealloc ((char *)reg_n_info, size_info);
+         renumber = (short *) xrealloc ((char *)renumber, size_renumber);
+       }
+    }
 
-short *regno_first_uid;
+  if (min < num_regs)
+    {
+      bzero ((char *) &reg_n_info[min], (num_regs - min) * sizeof (reg_info));
+      for (i = min; i < num_regs; i++)
+       {
+         REG_BASIC_BLOCK (i) = REG_BLOCK_UNKNOWN;
+         renumber[i] = -1;
+       }
+    }
 
-/* Indexed by pseudo register number, gives uid of last insn using the reg
-   (as of the time reg_scan is called).  */
+  if (renumber_p)
+    reg_renumber = renumber;
 
-short *regno_last_uid;
+  /* Tell the regset code about the new number of registers */
+  MAX_REGNO_REG_SET (num_regs, new_p, renumber_p);
 
-/* Record the number of registers we used when we allocated the above two
-   tables.  If we are called again with more than this, we must re-allocate
-   the tables.  */
+  reg_n_max = num_regs;
+}
 
-static int highest_regno_in_uid_map;
+\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 pseudo-register
+   and records them in the vectors regno_first_uid, regno_last_uid
+   and counts the number of sets in the vector reg_n_sets.
+
+   REPEAT is nonzero the second time this is called.  */
 
 /* Maximum number of parallel sets and clobbers in any insn in this fn.
-   Always at least 3, since the combiner could put that many togetherm
+   Always at least 3, since the combiner could put that many together
    and we want this to remain correct for all the remaining passes.  */
 
 int max_parallel;
 
-void reg_scan_mark_refs ();
-
 void
 reg_scan (f, nregs, repeat)
      rtx f;
@@ -995,22 +1850,7 @@ reg_scan (f, nregs, repeat)
 {
   register rtx insn;
 
-  if (!repeat || nregs > highest_regno_in_uid_map)
-    {
-      /* Leave some spare space in case more regs are allocated.  */
-      highest_regno_in_uid_map = nregs + nregs / 20;
-      regno_first_uid
-       = (short *) oballoc (highest_regno_in_uid_map * sizeof (short));
-      regno_last_uid
-       = (short *) oballoc (highest_regno_in_uid_map * sizeof (short));
-      reg_n_sets
-       = (short *) oballoc (highest_regno_in_uid_map * sizeof (short));
-    }
-
-  bzero (regno_first_uid, highest_regno_in_uid_map * sizeof (short));
-  bzero (regno_last_uid, highest_regno_in_uid_map * sizeof (short));
-  bzero (reg_n_sets, highest_regno_in_uid_map * sizeof (short));
-
+  allocate_reg_info (nregs, TRUE, FALSE);
   max_parallel = 3;
 
   for (insn = f; insn; insn = NEXT_INSN (insn))
@@ -1021,17 +1861,25 @@ reg_scan (f, nregs, repeat)
        if (GET_CODE (PATTERN (insn)) == PARALLEL
            && XVECLEN (PATTERN (insn), 0) > max_parallel)
          max_parallel = XVECLEN (PATTERN (insn), 0);
-       reg_scan_mark_refs (PATTERN (insn), INSN_UID (insn));
+       reg_scan_mark_refs (PATTERN (insn), insn, 0);
+
+       if (REG_NOTES (insn))
+         reg_scan_mark_refs (REG_NOTES (insn), insn, 1);
       }
 }
 
-void
-reg_scan_mark_refs (x, uid)
+/* X is the expression to scan.  INSN is the insn it appears in.
+   NOTE_FLAG is nonzero if X is from INSN's notes rather than its body.  */
+
+static void
+reg_scan_mark_refs (x, insn, note_flag)
      rtx x;
-     int uid;
+     rtx insn;
+     int note_flag;
 {
   register enum rtx_code code = GET_CODE (x);
   register rtx dest;
+  register rtx note;
 
   switch (code)
     {
@@ -1050,12 +1898,26 @@ reg_scan_mark_refs (x, uid)
       {
        register int regno = REGNO (x);
 
-       regno_last_uid[regno] = uid;
-       if (regno_first_uid[regno] == 0)
-         regno_first_uid[regno] = uid;
+       REGNO_LAST_NOTE_UID (regno) = INSN_UID (insn);
+       if (!note_flag)
+         REGNO_LAST_UID (regno) = INSN_UID (insn);
+       if (REGNO_FIRST_UID (regno) == 0)
+         REGNO_FIRST_UID (regno) = INSN_UID (insn);
       }
       break;
 
+    case EXPR_LIST:
+      if (XEXP (x, 0))
+       reg_scan_mark_refs (XEXP (x, 0), insn, note_flag);
+      if (XEXP (x, 1))
+       reg_scan_mark_refs (XEXP (x, 1), insn, note_flag);
+      break;
+
+    case INSN_LIST:
+      if (XEXP (x, 1))
+       reg_scan_mark_refs (XEXP (x, 1), insn, note_flag);
+      break;
+
     case SET:
       /* Count a set of the destination if it is a register.  */
       for (dest = SET_DEST (x);
@@ -1065,9 +1927,56 @@ reg_scan_mark_refs (x, uid)
        ;
 
       if (GET_CODE (dest) == REG)
-       reg_n_sets[REGNO (dest)]++;
-
-      /* ... fall through ... */
+       REG_N_SETS (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
+        a pointer, set the destination to be a pointer as well.
+
+        Likewise if it is setting the destination from an address or from a
+        value equivalent to an address or to the sum of an address and
+        something else.
+                    
+        But don't do any of this if the pseudo corresponds to a user
+        variable since it should have already been set as a pointer based
+        on the type.  */
+
+      if (GET_CODE (SET_DEST (x)) == REG
+         && REGNO (SET_DEST (x)) >= FIRST_PSEUDO_REGISTER
+         /* 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
+            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)))
+         && ((GET_CODE (SET_SRC (x)) == REG
+              && REGNO_POINTER_FLAG (REGNO (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))))
+             || GET_CODE (SET_SRC (x)) == CONST
+             || GET_CODE (SET_SRC (x)) == SYMBOL_REF
+             || GET_CODE (SET_SRC (x)) == LABEL_REF
+             || (GET_CODE (SET_SRC (x)) == HIGH
+                 && (GET_CODE (XEXP (SET_SRC (x), 0)) == CONST
+                     || GET_CODE (XEXP (SET_SRC (x), 0)) == SYMBOL_REF
+                     || GET_CODE (XEXP (SET_SRC (x), 0)) == LABEL_REF))
+             || ((GET_CODE (SET_SRC (x)) == PLUS
+                  || GET_CODE (SET_SRC (x)) == LO_SUM)
+                 && (GET_CODE (XEXP (SET_SRC (x), 1)) == CONST
+                     || GET_CODE (XEXP (SET_SRC (x), 1)) == SYMBOL_REF
+                     || GET_CODE (XEXP (SET_SRC (x), 1)) == LABEL_REF))
+             || ((note = find_reg_note (insn, REG_EQUAL, 0)) != 0
+                 && (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;
+
+      /* ... fall through ...  */
 
     default:
       {
@@ -1076,12 +1985,12 @@ reg_scan_mark_refs (x, uid)
        for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
          {
            if (fmt[i] == 'e')
-             reg_scan_mark_refs (XEXP (x, i), uid);
+             reg_scan_mark_refs (XEXP (x, i), insn, note_flag);
            else if (fmt[i] == 'E' && XVEC (x, i) != 0)
              {
                register int j;
                for (j = XVECLEN (x, i) - 1; j >= 0; j--)
-                 reg_scan_mark_refs (XVECEXP (x, i, j), uid);            
+                 reg_scan_mark_refs (XVECEXP (x, i, j), insn, note_flag);
              }
          }
       }
@@ -1134,3 +2043,17 @@ reg_classes_intersect_p (c1, c2)
   return 0;
 }
 
+/* Release any memory allocated by register sets.  */
+
+void
+regset_release_memory ()
+{
+  if (basic_block_live_at_start)
+    {
+      free_regset_vector (basic_block_live_at_start, n_basic_blocks);
+      basic_block_live_at_start = 0;
+    }
+
+  FREE_REG_SET (regs_live_at_setjmp);
+  bitmap_release_memory ();
+}