OSDN Git Service

2003-07-30 Chris Demetriou <cgd@broadcom.com>
[pf3gnuchains/gcc-fork.git] / gcc / regclass.c
index 20c7d3b..ec636d7 100644 (file)
@@ -1,6 +1,6 @@
 /* Compute register class preferences for pseudo-registers.
    Copyright (C) 1987, 1988, 1991, 1992, 1993, 1994, 1995, 1996
-   1997, 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+   1997, 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -26,6 +26,8 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 
 #include "config.h"
 #include "system.h"
+#include "coretypes.h"
+#include "tm.h"
 #include "hard-reg-set.h"
 #include "rtl.h"
 #include "expr.h"
@@ -41,13 +43,11 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "toplev.h"
 #include "output.h"
 #include "ggc.h"
+#include "timevar.h"
 
-#ifndef REGISTER_MOVE_COST
-#define REGISTER_MOVE_COST(m, x, y) 2
-#endif
-
-static void init_reg_sets_1    PARAMS ((void));
-static void init_reg_modes     PARAMS ((void));
+static void init_reg_sets_1 (void);
+static void init_reg_modes (void);
+static void init_reg_autoinc (void);
 
 /* If we have auto-increment or auto-decrement and we can have secondary
    reloads, we are not allowed to use classes requiring secondary
@@ -228,9 +228,9 @@ static char *in_inc_dec;
 #endif /* FORBIDDEN_INC_DEC_CLASSES */
 
 #ifdef CANNOT_CHANGE_MODE_CLASS
-/* All registers that have been subreged.  Indexed by mode, where each
-   entry is a regset of registers.  */
-regset_head subregs_of_mode [NUM_MACHINE_MODES];
+/* All registers that have been subreged.  Indexed by regno * MAX_MACHINE_MODE
+   + mode.  */
+bitmap_head subregs_of_mode;
 #endif
 
 /* Sample MEM values for use by memory_move_secondary_cost.  */
@@ -261,7 +261,7 @@ static int no_global_reg_vars = 0;
    Once this is done, various switches may override.  */
 
 void
-init_reg_sets ()
+init_reg_sets (void)
 {
   int i, j;
 
@@ -296,7 +296,7 @@ init_reg_sets ()
    `fixed_regs' and `call_used_regs', convert them to HARD_REG_SETs.  */
 
 static void
-init_reg_sets_1 ()
+init_reg_sets_1 (void)
 {
   unsigned int i, j;
   unsigned int /* enum machine_mode */ m;
@@ -311,7 +311,7 @@ init_reg_sets_1 ()
 
   /* Compute number of hard regs in each class.  */
 
-  memset ((char *) reg_class_size, 0, sizeof reg_class_size);
+  memset (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))
@@ -340,7 +340,7 @@ init_reg_sets_1 ()
              continue;
 
            subclass1:
-             /* keep the largest subclass */           /* SPEE 900308 */
+             /* Keep the largest subclass.  */         /* SPEE 900308 */
              GO_IF_HARD_REG_SUBSET (reg_class_contents[k],
                                     reg_class_contents[(int) reg_class_subunion[i][j]],
                                     subclass2);
@@ -457,7 +457,7 @@ init_reg_sets_1 ()
        ;
 #endif
 #ifndef PIC_OFFSET_TABLE_REG_CALL_CLOBBERED
-      else if (i == PIC_OFFSET_TABLE_REGNUM && fixed_regs[i])
+      else if (i == (unsigned) PIC_OFFSET_TABLE_REGNUM && fixed_regs[i])
        ;
 #endif
       else if (0
@@ -547,13 +547,13 @@ init_reg_sets_1 ()
    (as opposed to a multi-register mode).  */
 
 static void
-init_reg_modes ()
+init_reg_modes (void)
 {
   int i;
 
   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
     {
-      reg_raw_mode[i] = choose_hard_reg_mode (i, 1);
+      reg_raw_mode[i] = choose_hard_reg_mode (i, 1, false);
 
       /* 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
@@ -569,20 +569,22 @@ init_reg_modes ()
    initialize the register modes.  */
 
 void
-init_regs ()
+init_regs (void)
 {
   /* 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 ();
+
+  init_reg_autoinc ();
 }
 
 /* Initialize some fake stack-frame MEM references for use in
    memory_move_secondary_cost.  */
 
 void
-init_fake_stack_mems ()
+init_fake_stack_mems (void)
 {
 #ifdef HAVE_SECONDARY_RELOADS
   {
@@ -600,10 +602,7 @@ init_fake_stack_mems ()
    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;
+memory_move_secondary_cost (enum machine_mode mode, enum reg_class class, int in)
 {
   enum reg_class altclass;
   int partial_cost = 0;
@@ -654,12 +653,12 @@ memory_move_secondary_cost (mode, class, in)
 #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.  */
+   enough to save nregs.  If we can't find one, return VOIDmode.
+   If CALL_SAVED is true, only consider modes that are call saved.  */
 
 enum machine_mode
-choose_hard_reg_mode (regno, nregs)
-     unsigned int regno ATTRIBUTE_UNUSED;
-     unsigned int nregs;
+choose_hard_reg_mode (unsigned int regno ATTRIBUTE_UNUSED,
+                     unsigned int nregs, bool call_saved)
 {
   unsigned int /* enum machine_mode */ m;
   enum machine_mode found_mode = VOIDmode, mode;
@@ -672,7 +671,8 @@ choose_hard_reg_mode (regno, nregs)
        mode != VOIDmode;
        mode = GET_MODE_WIDER_MODE (mode))
     if ((unsigned) HARD_REGNO_NREGS (regno, mode) == nregs
-       && HARD_REGNO_MODE_OK (regno, mode))
+       && HARD_REGNO_MODE_OK (regno, mode)
+       && (! call_saved || ! HARD_REGNO_CALL_PART_CLOBBERED (regno, mode)))
       found_mode = mode;
 
   if (found_mode != VOIDmode)
@@ -682,7 +682,8 @@ choose_hard_reg_mode (regno, nregs)
        mode != VOIDmode;
        mode = GET_MODE_WIDER_MODE (mode))
     if ((unsigned) HARD_REGNO_NREGS (regno, mode) == nregs
-       && HARD_REGNO_MODE_OK (regno, mode))
+       && HARD_REGNO_MODE_OK (regno, mode)
+       && (! call_saved || ! HARD_REGNO_CALL_PART_CLOBBERED (regno, mode)))
       found_mode = mode;
 
   if (found_mode != VOIDmode)
@@ -692,7 +693,8 @@ choose_hard_reg_mode (regno, nregs)
        mode != VOIDmode;
        mode = GET_MODE_WIDER_MODE (mode))
     if ((unsigned) HARD_REGNO_NREGS (regno, mode) == nregs
-       && HARD_REGNO_MODE_OK (regno, mode))
+       && HARD_REGNO_MODE_OK (regno, mode)
+       && (! call_saved || ! HARD_REGNO_CALL_PART_CLOBBERED (regno, mode)))
       found_mode = mode;
 
   if (found_mode != VOIDmode)
@@ -702,7 +704,8 @@ choose_hard_reg_mode (regno, nregs)
        mode != VOIDmode;
        mode = GET_MODE_WIDER_MODE (mode))
     if ((unsigned) HARD_REGNO_NREGS (regno, mode) == nregs
-       && HARD_REGNO_MODE_OK (regno, mode))
+       && HARD_REGNO_MODE_OK (regno, mode)
+       && (! call_saved || ! HARD_REGNO_CALL_PART_CLOBBERED (regno, mode)))
       found_mode = mode;
 
   if (found_mode != VOIDmode)
@@ -713,7 +716,8 @@ choose_hard_reg_mode (regno, nregs)
     {
       mode = (enum machine_mode) m;
       if ((unsigned) HARD_REGNO_NREGS (regno, mode) == nregs
-         && HARD_REGNO_MODE_OK (regno, mode))
+         && HARD_REGNO_MODE_OK (regno, mode)
+         && (! call_saved || ! HARD_REGNO_CALL_PART_CLOBBERED (regno, mode)))
        return mode;
     }
 
@@ -726,9 +730,7 @@ choose_hard_reg_mode (regno, nregs)
    call-used register if CALL_USED.  */
 
 void
-fix_register (name, fixed, call_used)
-     const char *name;
-     int fixed, call_used;
+fix_register (const char *name, int fixed, int call_used)
 {
   int i;
 
@@ -772,8 +774,7 @@ fix_register (name, fixed, call_used)
 /* Mark register number I as global.  */
 
 void
-globalize_reg (i)
-     int i;
+globalize_reg (int i)
 {
   if (fixed_regs[i] == 0 && no_global_reg_vars)
     error ("global register variable follows a function definition");
@@ -815,7 +816,7 @@ struct costs
   int mem_cost;
 };
 
-/* Structure used to record preferrences of given pseudo.  */
+/* Structure used to record preferences of given pseudo.  */
 struct reg_pref
 {
   /* (enum reg_class) prefclass is the preferred class.  */
@@ -839,7 +840,7 @@ static struct costs *costs;
 
 static struct costs init_cost;
 
-/* Record preferrences of each pseudo.
+/* Record preferences of each pseudo.
    This is available after `regclass' is run.  */
 
 static struct reg_pref *reg_pref;
@@ -852,27 +853,25 @@ static struct reg_pref *reg_pref_buffer;
 
 static int frequency;
 
-static rtx scan_one_insn       PARAMS ((rtx, int));
-static void record_operand_costs PARAMS ((rtx, struct costs *, struct reg_pref *));
-static void dump_regclass      PARAMS ((FILE *));
-static void record_reg_classes PARAMS ((int, int, rtx *, enum machine_mode *,
-                                      const char **, rtx,
-                                      struct costs *, struct reg_pref *));
-static int copy_cost           PARAMS ((rtx, enum machine_mode,
-                                      enum reg_class, int));
-static void record_address_regs        PARAMS ((rtx, enum reg_class, int));
+static rtx scan_one_insn (rtx, int);
+static void record_operand_costs (rtx, struct costs *, struct reg_pref *);
+static void dump_regclass (FILE *);
+static void record_reg_classes (int, int, rtx *, enum machine_mode *,
+                               const char **, rtx, struct costs *,
+                               struct reg_pref *);
+static int copy_cost (rtx, enum machine_mode, enum reg_class, int);
+static void record_address_regs (rtx, enum reg_class, int);
 #ifdef FORBIDDEN_INC_DEC_CLASSES
-static int auto_inc_dec_reg_p  PARAMS ((rtx, enum machine_mode));
+static int auto_inc_dec_reg_p (rtx, enum machine_mode);
 #endif
-static void reg_scan_mark_refs PARAMS ((rtx, rtx, int, unsigned int));
+static void reg_scan_mark_refs (rtx, rtx, int, unsigned int);
 
 /* Return the reg_class in which pseudo reg number REGNO is best allocated.
    This function is sometimes called before the info has been computed.
    When that happens, just return GENERAL_REGS, which is innocuous.  */
 
 enum reg_class
-reg_preferred_class (regno)
-     int regno;
+reg_preferred_class (int regno)
 {
   if (reg_pref == 0)
     return GENERAL_REGS;
@@ -880,8 +879,7 @@ reg_preferred_class (regno)
 }
 
 enum reg_class
-reg_alternate_class (regno)
-     int regno;
+reg_alternate_class (int regno)
 {
   if (reg_pref == 0)
     return ALL_REGS;
@@ -892,7 +890,7 @@ reg_alternate_class (regno)
 /* Initialize some global data for this pass.  */
 
 void
-regclass_init ()
+regclass_init (void)
 {
   int i;
 
@@ -910,8 +908,7 @@ regclass_init ()
 \f
 /* Dump register costs.  */
 static void
-dump_regclass (dump)
-     FILE *dump;
+dump_regclass (FILE *dump)
 {
   static const char *const reg_class_names[] = REG_CLASS_NAMES;
   int i;
@@ -943,10 +940,8 @@ dump_regclass (dump)
 /* Calculate the costs of insn operands.  */
 
 static void
-record_operand_costs (insn, op_costs, reg_pref)
-     rtx insn;
-     struct costs *op_costs;
-     struct reg_pref *reg_pref;
+record_operand_costs (rtx insn, struct costs *op_costs,
+                     struct reg_pref *reg_pref)
 {
   const char *constraints[MAX_RECOG_OPERANDS];
   enum machine_mode modes[MAX_RECOG_OPERANDS];
@@ -975,7 +970,7 @@ record_operand_costs (insn, op_costs, reg_pref)
        record_address_regs (XEXP (recog_data.operand[i], 0),
                             MODE_BASE_REG_CLASS (modes[i]), frequency * 2);
       else if (constraints[i][0] == 'p'
-              || EXTRA_ADDRESS_CONSTRAINT (constraints[i][0]))
+              || EXTRA_ADDRESS_CONSTRAINT (constraints[i][0], constraints[i]))
        record_address_regs (recog_data.operand[i],
                             MODE_BASE_REG_CLASS (modes[i]), frequency * 2);
     }
@@ -1016,9 +1011,7 @@ record_operand_costs (insn, op_costs, reg_pref)
    there.  */
 
 static rtx
-scan_one_insn (insn, pass)
-     rtx insn;
-     int pass;
+scan_one_insn (rtx insn, int pass)
 {
   enum rtx_code code = GET_CODE (insn);
   enum rtx_code pat_code;
@@ -1141,37 +1134,18 @@ scan_one_insn (insn, pass)
   return insn;
 }
 
-/* This is a pass of the compiler that scans all instructions
-   and calculates the preferred class for each pseudo-register.
-   This information can be accessed later by calling `reg_preferred_class'.
-   This pass comes just before local register allocation.  */
+/* Initialize information about which register classes can be used for
+   pseudos that are auto-incremented or auto-decremented.  */
 
-void
-regclass (f, nregs, dump)
-     rtx f;
-     int nregs;
-     FILE *dump;
+static void
+init_reg_autoinc (void)
 {
-  rtx insn;
-  int i;
-  int pass;
-
-  init_recog ();
-
-  costs = (struct costs *) xmalloc (nregs * sizeof (struct costs));
-
 #ifdef FORBIDDEN_INC_DEC_CLASSES
-
-  in_inc_dec = (char *) xmalloc (nregs);
-
-  /* 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.  */
+  int i;
 
   for (i = 0; i < N_REG_CLASSES; i++)
     {
-      rtx r = gen_rtx_REG (VOIDmode, 0);
+      rtx r = gen_rtx_raw_REG (VOIDmode, 0);
       enum machine_mode m;
       int j;
 
@@ -1212,6 +1186,29 @@ regclass (f, nregs, dump)
          }
     }
 #endif /* FORBIDDEN_INC_DEC_CLASSES */
+}
+
+/* This is a pass of the compiler that scans all instructions
+   and calculates the preferred class for each pseudo-register.
+   This information can be accessed later by calling `reg_preferred_class'.
+   This pass comes just before local register allocation.  */
+
+void
+regclass (rtx f, int nregs, FILE *dump)
+{
+  rtx insn;
+  int i;
+  int pass;
+
+  init_recog ();
+
+  costs = xmalloc (nregs * sizeof (struct costs));
+
+#ifdef FORBIDDEN_INC_DEC_CLASSES
+
+  in_inc_dec = xmalloc (nregs);
+
+#endif /* FORBIDDEN_INC_DEC_CLASSES */
 
   /* 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
@@ -1226,7 +1223,7 @@ 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.  */
 
-      memset ((char *) costs, 0, nregs * sizeof (struct costs));
+      memset (costs, 0, nregs * sizeof (struct costs));
 
 #ifdef FORBIDDEN_INC_DEC_CLASSES
       memset (in_inc_dec, 0, nregs);
@@ -1386,16 +1383,10 @@ regclass (f, nregs, dump)
    alternatives.  */
 
 static void
-record_reg_classes (n_alts, n_ops, ops, modes,
-                   constraints, insn, op_costs, reg_pref)
-     int n_alts;
-     int n_ops;
-     rtx *ops;
-     enum machine_mode *modes;
-     const char **constraints;
-     rtx insn;
-     struct costs *op_costs;
-     struct reg_pref *reg_pref;
+record_reg_classes (int n_alts, int n_ops, rtx *ops,
+                   enum machine_mode *modes, const char **constraints,
+                   rtx insn, struct costs *op_costs,
+                   struct reg_pref *reg_pref)
 {
   int alt;
   int i, j;
@@ -1432,7 +1423,7 @@ record_reg_classes (n_alts, n_ops, ops, modes,
          if (*p == 0)
            {
              if (GET_CODE (op) == REG && REGNO (op) >= FIRST_PSEUDO_REGISTER)
-               memset ((char *) &this_op_costs[i], 0, sizeof this_op_costs[i]);
+               memset (&this_op_costs[i], 0, sizeof this_op_costs[i]);
 
              continue;
            }
@@ -1546,154 +1537,161 @@ record_reg_classes (n_alts, n_ops, ops, modes,
             any of the constraints.  Collect the valid register classes
             and see if this operand accepts memory.  */
 
-         while (*p && (c = *p++) != ',')
-           switch (c)
-             {
-             case '*':
-               /* Ignore the next letter for this pass.  */
-               p++;
-               break;
-
-             case '?':
-               alt_cost += 2;
-             case '!':  case '#':  case '&':
-             case '0':  case '1':  case '2':  case '3':  case '4':
-             case '5':  case '6':  case '7':  case '8':  case '9':
-               break;
+         while ((c = *p))
+           {
+             switch (c)
+               {
+               case ',':
+                 break;
+               case '*':
+                 /* Ignore the next letter for this pass.  */
+                 c = *++p;
+                 break;
 
-             case 'p':
-               allows_addr = 1;
-               win = address_operand (op, GET_MODE (op));
-               /* We know this operand is an address, so we want it to be
-                  allocated to a register that can be the base of an
-                  address, ie BASE_REG_CLASS.  */
-               classes[i]
-                 = reg_class_subunion[(int) classes[i]]
-                   [(int) MODE_BASE_REG_CLASS (VOIDmode)];
-               break;
+               case '?':
+                 alt_cost += 2;
+               case '!':  case '#':  case '&':
+               case '0':  case '1':  case '2':  case '3':  case '4':
+               case '5':  case '6':  case '7':  case '8':  case '9':
+                 break;
 
-             case 'm':  case 'o':  case 'V':
-               /* It doesn't seem worth distinguishing between offsettable
-                  and non-offsettable addresses here.  */
-               allows_mem[i] = 1;
-               if (GET_CODE (op) == MEM)
-                 win = 1;
-               break;
+               case 'p':
+                 allows_addr = 1;
+                 win = address_operand (op, GET_MODE (op));
+                 /* We know this operand is an address, so we want it to be
+                    allocated to a register that can be the base of an
+                    address, ie BASE_REG_CLASS.  */
+                 classes[i]
+                   = reg_class_subunion[(int) classes[i]]
+                     [(int) MODE_BASE_REG_CLASS (VOIDmode)];
+                 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 'm':  case 'o':  case 'V':
+                 /* It doesn't seem worth distinguishing between offsettable
+                    and non-offsettable addresses here.  */
+                 allows_mem[i] = 1;
+                 if (GET_CODE (op) == MEM)
+                   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 '<':
+                 if (GET_CODE (op) == MEM
+                     && (GET_CODE (XEXP (op, 0)) == PRE_DEC
+                         || GET_CODE (XEXP (op, 0)) == POST_DEC))
+                   win = 1;
+                 break;
 
-             case 'E':
-             case 'F':
-               if (GET_CODE (op) == CONST_DOUBLE
-                   || (GET_CODE (op) == CONST_VECTOR
-                       && (GET_MODE_CLASS (GET_MODE (op))
-                           == MODE_VECTOR_FLOAT)))
-                 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 'G':
-             case 'H':
-               if (GET_CODE (op) == CONST_DOUBLE
-                   && CONST_DOUBLE_OK_FOR_LETTER_P (op, c))
-                 win = 1;
-               break;
+               case 'E':
+               case 'F':
+                 if (GET_CODE (op) == CONST_DOUBLE
+                     || (GET_CODE (op) == CONST_VECTOR
+                         && (GET_MODE_CLASS (GET_MODE (op))
+                             == MODE_VECTOR_FLOAT)))
+                   win = 1;
+                 break;
 
-             case 's':
-               if (GET_CODE (op) == CONST_INT
-                   || (GET_CODE (op) == CONST_DOUBLE
-                       && GET_MODE (op) == VOIDmode))
+               case 'G':
+               case 'H':
+                 if (GET_CODE (op) == CONST_DOUBLE
+                     && CONST_DOUBLE_OK_FOR_CONSTRAINT_P (op, c, p))
+                   win = 1;
                  break;
-             case 'i':
-               if (CONSTANT_P (op)
+
+               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))
+                     && (! flag_pic || LEGITIMATE_PIC_OPERAND_P (op))
 #endif
-                   )
-                 win = 1;
-               break;
+                     )
+                   win = 1;
+                 break;
 
-             case 'n':
-               if (GET_CODE (op) == CONST_INT
-                   || (GET_CODE (op) == CONST_DOUBLE
-                       && GET_MODE (op) == VOIDmode))
-                 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 'I':
+               case 'J':
+               case 'K':
+               case 'L':
+               case 'M':
+               case 'N':
+               case 'O':
+               case 'P':
+                 if (GET_CODE (op) == CONST_INT
+                     && CONST_OK_FOR_CONSTRAINT_P (INTVAL (op), c, p))
+                   win = 1;
+                 break;
 
-             case 'X':
-               win = 1;
-               break;
+               case 'X':
+                 win = 1;
+                 break;
 
-             case 'g':
-               if (GET_CODE (op) == MEM
-                   || (CONSTANT_P (op)
+               case 'g':
+                 if (GET_CODE (op) == MEM
+                     || (CONSTANT_P (op)
 #ifdef LEGITIMATE_PIC_OPERAND_P
-                       && (! flag_pic || LEGITIMATE_PIC_OPERAND_P (op))
+                         && (! flag_pic || LEGITIMATE_PIC_OPERAND_P (op))
 #endif
-                       ))
-                 win = 1;
-               allows_mem[i] = 1;
-             case 'r':
-               classes[i]
-                 = reg_class_subunion[(int) classes[i]][(int) GENERAL_REGS];
-               break;
-
-             default:
-               if (REG_CLASS_FROM_LETTER (c) != NO_REGS)
+                         ))
+                   win = 1;
+                 allows_mem[i] = 1;
+               case 'r':
                  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;
+                   = reg_class_subunion[(int) classes[i]][(int) GENERAL_REGS];
+                 break;
 
-               if (EXTRA_MEMORY_CONSTRAINT (c))
-                 {
-                   /* Every MEM can be reloaded to fit.  */
-                   allows_mem[i] = 1;
-                   if (GET_CODE (op) == MEM)
-                     win = 1;
-                 }
-               if (EXTRA_ADDRESS_CONSTRAINT (op))
-                 {
-                   /* Every address can be reloaded to fit.  */
-                   allows_addr = 1;
-                   if (address_operand (op, GET_MODE (op)))
-                     win = 1;
-                   /* We know this operand is an address, so we want it to be
-                      allocated to a register that can be the base of an
-                      address, ie BASE_REG_CLASS.  */
+               default:
+                 if (REG_CLASS_FROM_CONSTRAINT (c, p) != NO_REGS)
                    classes[i]
                      = reg_class_subunion[(int) classes[i]]
-                       [(int) MODE_BASE_REG_CLASS (VOIDmode)];
-                 }
+                       [(int) REG_CLASS_FROM_CONSTRAINT (c, p)];
+#ifdef EXTRA_CONSTRAINT_STR
+                 else if (EXTRA_CONSTRAINT_STR (op, c, p))
+                   win = 1;
+
+                 if (EXTRA_MEMORY_CONSTRAINT (c, p))
+                   {
+                     /* Every MEM can be reloaded to fit.  */
+                     allows_mem[i] = 1;
+                     if (GET_CODE (op) == MEM)
+                       win = 1;
+                   }
+                 if (EXTRA_ADDRESS_CONSTRAINT (c, p))
+                   {
+                     /* Every address can be reloaded to fit.  */
+                     allows_addr = 1;
+                     if (address_operand (op, GET_MODE (op)))
+                       win = 1;
+                     /* We know this operand is an address, so we want it to
+                        be allocated to a register that can be the base of an
+                        address, ie BASE_REG_CLASS.  */
+                     classes[i]
+                       = reg_class_subunion[(int) classes[i]]
+                         [(int) MODE_BASE_REG_CLASS (VOIDmode)];
+                   }
 #endif
+                 break;
+               }
+             p += CONSTRAINT_LEN (c, p);
+             if (c == ',')
                break;
-             }
+           }
 
          constraints[i] = p;
 
@@ -1812,7 +1810,7 @@ record_reg_classes (n_alts, n_ops, ops, modes,
      we may want to adjust the cost of that register class to -1.
 
      Avoid the adjustment if the source does not die to avoid stressing of
-     register allocator by preferrencing two coliding registers into single
+     register allocator by preferrencing two colliding registers into single
      class.
 
      Also avoid the adjustment if a copy between registers of the class
@@ -1870,11 +1868,8 @@ record_reg_classes (n_alts, n_ops, ops, modes,
    X must not be a pseudo.  */
 
 static int
-copy_cost (x, mode, class, to_p)
-     rtx x;
-     enum machine_mode mode ATTRIBUTE_UNUSED;
-     enum reg_class class;
-     int to_p ATTRIBUTE_UNUSED;
+copy_cost (rtx x, enum machine_mode mode ATTRIBUTE_UNUSED,
+          enum reg_class class, int to_p ATTRIBUTE_UNUSED)
 {
 #ifdef HAVE_SECONDARY_RELOADS
   enum reg_class secondary_class = NO_REGS;
@@ -1935,10 +1930,7 @@ copy_cost (x, mode, class, to_p)
    can represent half-cost adjustments).  */
 
 static void
-record_address_regs (x, class, scale)
-     rtx x;
-     enum reg_class class;
-     int scale;
+record_address_regs (rtx x, enum reg_class class, int scale)
 {
   enum rtx_code code = GET_CODE (x);
 
@@ -2119,9 +2111,7 @@ record_address_regs (x, class, scale)
    to an object of MODE.  */
 
 static int
-auto_inc_dec_reg_p (reg, mode)
-     rtx reg;
-     enum machine_mode mode;
+auto_inc_dec_reg_p (rtx reg, enum machine_mode mode)
 {
   if (HAVE_POST_INCREMENT
       && memory_address_p (mode, gen_rtx_POST_INC (Pmode, reg)))
@@ -2155,10 +2145,7 @@ static unsigned int reg_n_max;
    RENUMBER_P is nonzero, allocate the reg_renumber array also.  */
 
 void
-allocate_reg_info (num_regs, new_p, renumber_p)
-     size_t num_regs;
-     int new_p;
-     int renumber_p;
+allocate_reg_info (size_t num_regs, int new_p, int renumber_p)
 {
   size_t size_info;
   size_t size_renumber;
@@ -2169,42 +2156,42 @@ allocate_reg_info (num_regs, new_p, renumber_p)
     {
       size_t old_allocated = regno_allocated;
 
-      regno_allocated = num_regs + (num_regs / 20);    /* add some slop space */
+      regno_allocated = num_regs + (num_regs / 20);    /* Add some slop space.  */
       size_renumber = regno_allocated * sizeof (short);
 
       if (!reg_n_info)
        {
          VARRAY_REG_INIT (reg_n_info, regno_allocated, "reg_n_info");
-         renumber = (short *) xmalloc (size_renumber);
-         reg_pref_buffer = (struct reg_pref *) xmalloc (regno_allocated
-                                             * sizeof (struct reg_pref));
+         renumber = xmalloc (size_renumber);
+         reg_pref_buffer = xmalloc (regno_allocated
+                                    * sizeof (struct reg_pref));
        }
 
       else
        {
          VARRAY_GROW (reg_n_info, regno_allocated);
 
-         if (new_p)            /* if we're zapping everything, no need to realloc */
+         if (new_p)            /* If we're zapping everything, no need to realloc.  */
            {
              free ((char *) renumber);
              free ((char *) reg_pref);
-             renumber = (short *) xmalloc (size_renumber);
-             reg_pref_buffer = (struct reg_pref *) xmalloc (regno_allocated
-                                                 * sizeof (struct reg_pref));
+             renumber = xmalloc (size_renumber);
+             reg_pref_buffer = xmalloc (regno_allocated
+                                        * sizeof (struct reg_pref));
            }
 
          else
            {
-             renumber = (short *) xrealloc ((char *) renumber, size_renumber);
-             reg_pref_buffer = (struct reg_pref *) xrealloc ((char *) reg_pref_buffer,
-                                                  regno_allocated
-                                                  * sizeof (struct reg_pref));
+             renumber = xrealloc (renumber, size_renumber);
+             reg_pref_buffer = xrealloc (reg_pref_buffer,
+                                         regno_allocated
+                                         * sizeof (struct reg_pref));
            }
        }
 
       size_info = (regno_allocated - old_allocated) * sizeof (reg_info)
        + sizeof (struct reg_info_data) - sizeof (reg_info);
-      reg_data = (struct reg_info_data *) xcalloc (size_info, 1);
+      reg_data = xcalloc (size_info, 1);
       reg_data->min_index = old_allocated;
       reg_data->max_index = regno_allocated - 1;
       reg_data->next = reg_info_head;
@@ -2234,8 +2221,8 @@ 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
-           memset ((char *) &reg_data->data[local_min], 0,
-                  sizeof (reg_info) * (max - min_index - local_min + 1));
+           memset (&reg_data->data[local_min], 0,
+                   sizeof (reg_info) * (max - min_index - local_min + 1));
 
          for (i = min_index+local_min; i <= max; i++)
            {
@@ -2262,7 +2249,7 @@ allocate_reg_info (num_regs, new_p, renumber_p)
 
 /* Free up the space allocated by allocate_reg_info.  */
 void
-free_reg_info ()
+free_reg_info (void)
 {
   if (reg_n_info)
     {
@@ -2308,10 +2295,7 @@ int max_parallel;
 static int max_set_parallel;
 
 void
-reg_scan (f, nregs, repeat)
-     rtx f;
-     unsigned int nregs;
-     int repeat ATTRIBUTE_UNUSED;
+reg_scan (rtx f, unsigned int nregs, int repeat ATTRIBUTE_UNUSED)
 {
   rtx insn;
 
@@ -2319,6 +2303,8 @@ reg_scan (f, nregs, repeat)
   max_parallel = 3;
   max_set_parallel = 0;
 
+  timevar_push (TV_REG_SCAN);
+
   for (insn = f; insn; insn = NEXT_INSN (insn))
     if (GET_CODE (insn) == INSN
        || GET_CODE (insn) == CALL_INSN
@@ -2334,6 +2320,8 @@ reg_scan (f, nregs, repeat)
       }
 
   max_parallel += max_set_parallel;
+
+  timevar_pop (TV_REG_SCAN);
 }
 
 /* Update 'regscan' information by looking at the insns
@@ -2342,10 +2330,7 @@ reg_scan (f, nregs, repeat)
    such a REG.  We only update information for those.  */
 
 void
-reg_scan_update (first, last, old_max_regno)
-     rtx first;
-     rtx last;
-     unsigned int old_max_regno;
+reg_scan_update (rtx first, rtx last, unsigned int old_max_regno)
 {
   rtx insn;
 
@@ -2372,11 +2357,7 @@ reg_scan_update (first, last, old_max_regno)
    greater than or equal to MIN_REGNO.  */
 
 static void
-reg_scan_mark_refs (x, insn, note_flag, min_regno)
-     rtx x;
-     rtx insn;
-     int note_flag;
-     unsigned int min_regno;
+reg_scan_mark_refs (rtx x, rtx insn, int note_flag, unsigned int min_regno)
 {
   enum rtx_code code;
   rtx dest;
@@ -2479,7 +2460,7 @@ reg_scan_mark_refs (x, insn, note_flag, min_regno)
          && REGNO (SET_DEST (x)) >= 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
+            union in two threads of control in the presence of global
             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
@@ -2511,7 +2492,7 @@ reg_scan_mark_refs (x, insn, note_flag, min_regno)
        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.  */
+        conversion of a register, propagate REG_EXPR.  */
       if (GET_CODE (dest) == REG)
        {
          rtx src = SET_SRC (x);
@@ -2522,10 +2503,10 @@ reg_scan_mark_refs (x, insn, note_flag, min_regno)
                 || (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));
+         if (!REG_ATTRS (dest) && REG_P (src))
+           REG_ATTRS (dest) = REG_ATTRS (src);
+         if (!REG_ATTRS (dest) && GET_CODE (src) == MEM)
+           set_reg_attrs_from_mem (dest, src);
        }
 
       /* ... fall through ...  */
@@ -2553,9 +2534,7 @@ reg_scan_mark_refs (x, insn, note_flag, min_regno)
    is also in C2.  */
 
 int
-reg_class_subset_p (c1, c2)
-     enum reg_class c1;
-     enum reg_class c2;
+reg_class_subset_p (enum reg_class c1, enum reg_class c2)
 {
   if (c1 == c2) return 1;
 
@@ -2571,9 +2550,7 @@ reg_class_subset_p (c1, c2)
 /* Return nonzero if there is a register that is in both C1 and C2.  */
 
 int
-reg_classes_intersect_p (c1, c2)
-     enum reg_class c1;
-     enum reg_class c2;
+reg_classes_intersect_p (enum reg_class c1, enum reg_class c2)
 {
 #ifdef HARD_REG_SET
   register
@@ -2598,7 +2575,7 @@ reg_classes_intersect_p (c1, c2)
 /* Release any memory allocated by register sets.  */
 
 void
-regset_release_memory ()
+regset_release_memory (void)
 {
   bitmap_release_memory ();
 }
@@ -2608,39 +2585,42 @@ regset_release_memory ()
    their mode from FROM to any mode in which REGNO was encountered.  */
 
 void
-cannot_change_mode_set_regs (used, from, regno)
-     HARD_REG_SET *used;
-     enum machine_mode from;
-     unsigned int regno;
+cannot_change_mode_set_regs (HARD_REG_SET *used, enum machine_mode from,
+                            unsigned int regno)
 {
   enum machine_mode to;
-  enum reg_class class;
+  int n, i;
+  int start = regno * MAX_MACHINE_MODE;
 
-  for (to = VOIDmode; to < MAX_MACHINE_MODE; ++to)
-    if (REGNO_REG_SET_P (&subregs_of_mode[to], regno))
-      {
-        class = CANNOT_CHANGE_MODE_CLASS (from, to);
-        if (class != NO_REGS)
-          IOR_HARD_REG_SET (*used, reg_class_contents [(int) class]);
-      }
+  EXECUTE_IF_SET_IN_BITMAP (&subregs_of_mode, start, n,
+    if (n >= MAX_MACHINE_MODE + start)
+      return;
+    to = n - start;
+    for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+      if (! TEST_HARD_REG_BIT (*used, i)
+         && REG_CANNOT_CHANGE_MODE_P (i, from, to))
+       SET_HARD_REG_BIT (*used, i);
+  );
 }
 
 /* Return 1 if REGNO has had an invalid mode change in CLASS from FROM
    mode.  */
 
 bool
-invalid_mode_change_p (regno, class, from_mode)
-     unsigned int regno;
-      enum reg_class class;
-     enum machine_mode from_mode;
+invalid_mode_change_p (unsigned int regno, enum reg_class class,
+                      enum machine_mode from_mode)
 {
   enum machine_mode to_mode;
-
-  for (to_mode = 0; to_mode < NUM_MACHINE_MODES; ++to_mode)
-    if (REGNO_REG_SET_P (&subregs_of_mode[(int) to_mode], regno)
-       && reg_classes_intersect_p 
-            (class, CANNOT_CHANGE_MODE_CLASS (from_mode, to_mode)))
+  int n;
+  int start = regno * MAX_MACHINE_MODE;
+
+  EXECUTE_IF_SET_IN_BITMAP (&subregs_of_mode, start, n,
+    if (n >= MAX_MACHINE_MODE + start)
+      return 0;
+    to_mode = n - start;
+    if (CANNOT_CHANGE_MODE_CLASS (from_mode, to_mode, class))
       return 1;
+  );
   return 0;
 }
 #endif /* CANNOT_CHANGE_MODE_CLASS */