OSDN Git Service

PR c++/15463
[pf3gnuchains/gcc-fork.git] / gcc / reload1.c
index 2e64167..c848ce6 100644 (file)
@@ -1,6 +1,6 @@
 /* Reload pseudo regs into hard regs for insns that require hard regs.
    Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+   1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -77,14 +77,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
    reload needs, spilling, assigning reload registers to use for
    fixing up each insn, and generating the new insns to copy values
    into the reload registers.  */
-
-#ifndef REGISTER_MOVE_COST
-#define REGISTER_MOVE_COST(m, x, y) 2
-#endif
-
-#ifndef LOCAL_REGNO
-#define LOCAL_REGNO(REGNO)  0
-#endif
 \f
 /* During reload_as_needed, element N contains a REG rtx for the hard reg
    into which reg N has been reloaded (perhaps for a previous insn).  */
@@ -146,6 +138,11 @@ static HARD_REG_SET reg_reloaded_valid;
    This is only valid if reg_reloaded_contents is set and valid.  */
 static HARD_REG_SET reg_reloaded_dead;
 
+/* Indicate whether the register's current value is one that is not
+   safe to retain across a call, even for registers that are normally
+   call-saved.  */
+static HARD_REG_SET reg_reloaded_call_part_clobbered;
+
 /* Number of spill-regs so far; number of valid elements of spill_regs.  */
 static int n_spills;
 
@@ -285,12 +282,6 @@ static char *reload_insn_firstobj;
    examine.  */
 struct insn_chain *reload_insn_chain;
 
-#ifdef TREE_CODE
-extern tree current_function_decl;
-#else
-extern union tree_node *current_function_decl;
-#endif
-
 /* List of all insns needing reloads.  */
 static struct insn_chain *insns_need_reload;
 \f
@@ -303,12 +294,12 @@ struct elim_table
 {
   int from;                    /* Register number to be eliminated.  */
   int to;                      /* Register number used as replacement.  */
-  int initial_offset;          /* Initial difference between values.  */
+  HOST_WIDE_INT initial_offset;        /* Initial difference between values.  */
   int can_eliminate;           /* Nonzero if this elimination can be done.  */
   int can_eliminate_previous;  /* Value of CAN_ELIMINATE in previous scan over
                                   insns made by reload.  */
-  int offset;                  /* Current offset between the two regs.  */
-  int previous_offset;         /* Offset at end of previous insn.  */
+  HOST_WIDE_INT offset;                /* Current offset between the two regs.  */
+  HOST_WIDE_INT previous_offset;/* Offset at end of previous insn.  */
   int ref_outside_mem;         /* "to" has been referenced outside a MEM.  */
   rtx from_rtx;                        /* REG rtx for the register to be eliminated.
                                   We cannot simply compare the number since
@@ -362,93 +353,85 @@ static int num_eliminable_invariants;
 
 static int first_label_num;
 static char *offsets_known_at;
-static int (*offsets_at)[NUM_ELIMINABLE_REGS];
+static HOST_WIDE_INT (*offsets_at)[NUM_ELIMINABLE_REGS];
 
 /* Number of labels in the current function.  */
 
 static int num_labels;
 \f
-static void replace_pseudos_in PARAMS ((rtx *, enum machine_mode, rtx));
-static void maybe_fix_stack_asms       PARAMS ((void));
-static void copy_reloads               PARAMS ((struct insn_chain *));
-static void calculate_needs_all_insns  PARAMS ((int));
-static int find_reg                    PARAMS ((struct insn_chain *, int));
-static void find_reload_regs           PARAMS ((struct insn_chain *));
-static void select_reload_regs         PARAMS ((void));
-static void delete_caller_save_insns   PARAMS ((void));
-
-static void spill_failure              PARAMS ((rtx, enum reg_class));
-static void count_spilled_pseudo       PARAMS ((int, int, int));
-static void delete_dead_insn           PARAMS ((rtx));
-static void alter_reg                  PARAMS ((int, int));
-static void set_label_offsets          PARAMS ((rtx, rtx, int));
-static void check_eliminable_occurrences       PARAMS ((rtx));
-static void elimination_effects                PARAMS ((rtx, enum machine_mode));
-static int eliminate_regs_in_insn      PARAMS ((rtx, int));
-static void update_eliminable_offsets  PARAMS ((void));
-static void mark_not_eliminable                PARAMS ((rtx, rtx, void *));
-static void set_initial_elim_offsets   PARAMS ((void));
-static void verify_initial_elim_offsets        PARAMS ((void));
-static void set_initial_label_offsets  PARAMS ((void));
-static void set_offsets_for_label      PARAMS ((rtx));
-static void init_elim_table            PARAMS ((void));
-static void update_eliminables         PARAMS ((HARD_REG_SET *));
-static void spill_hard_reg             PARAMS ((unsigned int, int));
-static int finish_spills               PARAMS ((int));
-static void ior_hard_reg_set           PARAMS ((HARD_REG_SET *, HARD_REG_SET *));
-static void scan_paradoxical_subregs   PARAMS ((rtx));
-static void count_pseudo               PARAMS ((int));
-static void order_regs_for_reload      PARAMS ((struct insn_chain *));
-static void reload_as_needed           PARAMS ((int));
-static void forget_old_reloads_1       PARAMS ((rtx, rtx, void *));
-static int reload_reg_class_lower      PARAMS ((const void *, const void *));
-static void mark_reload_reg_in_use     PARAMS ((unsigned int, int,
-                                                enum reload_type,
-                                                enum machine_mode));
-static void clear_reload_reg_in_use    PARAMS ((unsigned int, int,
-                                                enum reload_type,
-                                                enum machine_mode));
-static int reload_reg_free_p           PARAMS ((unsigned int, int,
-                                                enum reload_type));
-static int reload_reg_free_for_value_p PARAMS ((int, int, int,
-                                                enum reload_type,
-                                                rtx, rtx, int, int));
-static int free_for_value_p            PARAMS ((int, enum machine_mode, int,
-                                                enum reload_type, rtx, rtx,
-                                                int, int));
-static int reload_reg_reaches_end_p    PARAMS ((unsigned int, int,
-                                                enum reload_type));
-static int allocate_reload_reg         PARAMS ((struct insn_chain *, int,
-                                                int));
-static int conflicts_with_override     PARAMS ((rtx));
-static void failed_reload              PARAMS ((rtx, int));
-static int set_reload_reg              PARAMS ((int, int));
-static void choose_reload_regs_init    PARAMS ((struct insn_chain *, rtx *));
-static void choose_reload_regs         PARAMS ((struct insn_chain *));
-static void merge_assigned_reloads     PARAMS ((rtx));
-static void emit_input_reload_insns    PARAMS ((struct insn_chain *,
-                                                struct reload *, rtx, int));
-static void emit_output_reload_insns   PARAMS ((struct insn_chain *,
-                                                struct reload *, int));
-static void do_input_reload            PARAMS ((struct insn_chain *,
-                                                struct reload *, int));
-static void do_output_reload           PARAMS ((struct insn_chain *,
-                                                struct reload *, int));
-static void emit_reload_insns          PARAMS ((struct insn_chain *));
-static void delete_output_reload       PARAMS ((rtx, int, int));
-static void delete_address_reloads     PARAMS ((rtx, rtx));
-static void delete_address_reloads_1   PARAMS ((rtx, rtx, rtx));
-static rtx inc_for_reload              PARAMS ((rtx, rtx, rtx, int));
+static void replace_pseudos_in (rtx *, enum machine_mode, rtx);
+static void maybe_fix_stack_asms (void);
+static void copy_reloads (struct insn_chain *);
+static void calculate_needs_all_insns (int);
+static int find_reg (struct insn_chain *, int);
+static void find_reload_regs (struct insn_chain *);
+static void select_reload_regs (void);
+static void delete_caller_save_insns (void);
+
+static void spill_failure (rtx, enum reg_class);
+static void count_spilled_pseudo (int, int, int);
+static void delete_dead_insn (rtx);
+static void alter_reg (int, int);
+static void set_label_offsets (rtx, rtx, int);
+static void check_eliminable_occurrences (rtx);
+static void elimination_effects (rtx, enum machine_mode);
+static int eliminate_regs_in_insn (rtx, int);
+static void update_eliminable_offsets (void);
+static void mark_not_eliminable (rtx, rtx, void *);
+static void set_initial_elim_offsets (void);
+static void verify_initial_elim_offsets (void);
+static void set_initial_label_offsets (void);
+static void set_offsets_for_label (rtx);
+static void init_elim_table (void);
+static void update_eliminables (HARD_REG_SET *);
+static void spill_hard_reg (unsigned int, int);
+static int finish_spills (int);
+static void ior_hard_reg_set (HARD_REG_SET *, HARD_REG_SET *);
+static void scan_paradoxical_subregs (rtx);
+static void count_pseudo (int);
+static void order_regs_for_reload (struct insn_chain *);
+static void reload_as_needed (int);
+static void forget_old_reloads_1 (rtx, rtx, void *);
+static int reload_reg_class_lower (const void *, const void *);
+static void mark_reload_reg_in_use (unsigned int, int, enum reload_type,
+                                   enum machine_mode);
+static void clear_reload_reg_in_use (unsigned int, int, enum reload_type,
+                                    enum machine_mode);
+static int reload_reg_free_p (unsigned int, int, enum reload_type);
+static int reload_reg_free_for_value_p (int, int, int, enum reload_type,
+                                       rtx, rtx, int, int);
+static int free_for_value_p (int, enum machine_mode, int, enum reload_type,
+                            rtx, rtx, int, int);
+static int function_invariant_p (rtx);
+static int reload_reg_reaches_end_p (unsigned int, int, enum reload_type);
+static int allocate_reload_reg (struct insn_chain *, int, int);
+static int conflicts_with_override (rtx);
+static void failed_reload (rtx, int);
+static int set_reload_reg (int, int);
+static void choose_reload_regs_init (struct insn_chain *, rtx *);
+static void choose_reload_regs (struct insn_chain *);
+static void merge_assigned_reloads (rtx);
+static void emit_input_reload_insns (struct insn_chain *, struct reload *,
+                                    rtx, int);
+static void emit_output_reload_insns (struct insn_chain *, struct reload *,
+                                     int);
+static void do_input_reload (struct insn_chain *, struct reload *, int);
+static void do_output_reload (struct insn_chain *, struct reload *, int);
+static bool inherit_piecemeal_p (int, int);
+static void emit_reload_insns (struct insn_chain *);
+static void delete_output_reload (rtx, int, int);
+static void delete_address_reloads (rtx, rtx);
+static void delete_address_reloads_1 (rtx, rtx, rtx);
+static rtx inc_for_reload (rtx, rtx, rtx, int);
 #ifdef AUTO_INC_DEC
-static void add_auto_inc_notes         PARAMS ((rtx, rtx));
+static void add_auto_inc_notes (rtx, rtx);
 #endif
-static void copy_eh_notes              PARAMS ((rtx, rtx));
-extern void dump_needs                 PARAMS ((struct insn_chain *));
+static void copy_eh_notes (rtx, rtx);
 \f
 /* Initialize the reload pass once per compilation.  */
 
 void
-init_reload ()
+init_reload (void)
 {
   int i;
 
@@ -495,7 +478,7 @@ init_reload ()
 
   /* Initialize obstack for our rtl allocation.  */
   gcc_obstack_init (&reload_obstack);
-  reload_startobj = (char *) obstack_alloc (&reload_obstack, 0);
+  reload_startobj = obstack_alloc (&reload_obstack, 0);
 
   INIT_REG_SET (&spilled_pseudos);
   INIT_REG_SET (&pseudos_counted);
@@ -506,14 +489,13 @@ static struct insn_chain *unused_insn_chains = 0;
 
 /* Allocate an empty insn_chain structure.  */
 struct insn_chain *
-new_insn_chain ()
+new_insn_chain (void)
 {
   struct insn_chain *c;
 
   if (unused_insn_chains == 0)
     {
-      c = (struct insn_chain *)
-       obstack_alloc (&reload_obstack, sizeof (struct insn_chain));
+      c = obstack_alloc (&reload_obstack, sizeof (struct insn_chain));
       INIT_REG_SET (&c->live_throughout);
       INIT_REG_SET (&c->dead_or_set);
     }
@@ -533,9 +515,7 @@ new_insn_chain ()
    allocated to pseudos in regset FROM.  */
 
 void
-compute_use_by_pseudos (to, from)
-     HARD_REG_SET *to;
-     regset from;
+compute_use_by_pseudos (HARD_REG_SET *to, regset from)
 {
   unsigned int regno;
 
@@ -556,7 +536,7 @@ compute_use_by_pseudos (to, from)
         }
        else
         {
-          nregs = HARD_REGNO_NREGS (r, PSEUDO_REGNO_MODE (regno));
+          nregs = hard_regno_nregs[r][PSEUDO_REGNO_MODE (regno)];
           while (nregs-- > 0)
             SET_HARD_REG_BIT (*to, r + nregs);
         }
@@ -567,10 +547,7 @@ compute_use_by_pseudos (to, from)
    equivalences.  */
 
 static void
-replace_pseudos_in (loc, mem_mode, usage)
-     rtx *loc;
-     enum machine_mode mem_mode;
-     rtx usage;
+replace_pseudos_in (rtx *loc, enum machine_mode mem_mode, rtx usage)
 {
   rtx x = *loc;
   enum rtx_code code;
@@ -651,9 +628,7 @@ static int failure;
    and we must not do any more for this function.  */
 
 int
-reload (first, global)
-     rtx first;
-     int global;
+reload (rtx first, int global)
 {
   int i;
   rtx insn;
@@ -665,7 +640,7 @@ reload (first, global)
 
   failure = 0;
 
-  reload_firstobj = (char *) obstack_alloc (&reload_obstack, 0);
+  reload_firstobj = obstack_alloc (&reload_obstack, 0);
 
   /* Make sure that the last insn in the chain
      is not something that needs reloading.  */
@@ -680,8 +655,8 @@ reload (first, global)
 #endif
 
   /* We don't have a stack slot for any spill reg yet.  */
-  memset ((char *) spill_stack_slot, 0, sizeof spill_stack_slot);
-  memset ((char *) spill_stack_slot_width, 0, sizeof spill_stack_slot_width);
+  memset (spill_stack_slot, 0, sizeof spill_stack_slot);
+  memset (spill_stack_slot_width, 0, sizeof spill_stack_slot_width);
 
   /* Initialize the save area information for caller-save, in case some
      are needed.  */
@@ -701,6 +676,17 @@ reload (first, global)
       if (! call_used_regs[i] && ! fixed_regs[i] && ! LOCAL_REGNO (i))
        regs_ever_live[i] = 1;
 
+#ifdef NON_SAVING_SETJMP
+  /* A function that calls setjmp should save and restore all the
+     call-saved registers on a system where longjmp clobbers them.  */
+  if (NON_SAVING_SETJMP && current_function_calls_setjmp)
+    {
+      for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+       if (! call_used_regs[i])
+         regs_ever_live[i] = 1;
+    }
+#endif
+
   /* Find all the pseudo registers that didn't get hard regs
      but do have known equivalent constants or memory slots.
      These include parameters (known equivalent to parameter slots)
@@ -711,26 +697,21 @@ reload (first, global)
      Record memory equivalents in reg_mem_equiv so they can
      be substituted eventually by altering the REG-rtx's.  */
 
-  reg_equiv_constant = (rtx *) xcalloc (max_regno, sizeof (rtx));
-  reg_equiv_mem = (rtx *) xcalloc (max_regno, sizeof (rtx));
-  reg_equiv_init = (rtx *) xcalloc (max_regno, sizeof (rtx));
-  reg_equiv_address = (rtx *) xcalloc (max_regno, sizeof (rtx));
-  reg_max_ref_width = (unsigned int *) xcalloc (max_regno, sizeof (int));
-  reg_old_renumber = (short *) xcalloc (max_regno, sizeof (short));
+  reg_equiv_constant = xcalloc (max_regno, sizeof (rtx));
+  reg_equiv_mem = xcalloc (max_regno, sizeof (rtx));
+  reg_equiv_init = xcalloc (max_regno, sizeof (rtx));
+  reg_equiv_address = xcalloc (max_regno, sizeof (rtx));
+  reg_max_ref_width = xcalloc (max_regno, sizeof (int));
+  reg_old_renumber = xcalloc (max_regno, sizeof (short));
   memcpy (reg_old_renumber, reg_renumber, max_regno * sizeof (short));
-  pseudo_forbidden_regs
-    = (HARD_REG_SET *) xmalloc (max_regno * sizeof (HARD_REG_SET));
-  pseudo_previous_regs
-    = (HARD_REG_SET *) xcalloc (max_regno, sizeof (HARD_REG_SET));
+  pseudo_forbidden_regs = xmalloc (max_regno * sizeof (HARD_REG_SET));
+  pseudo_previous_regs = xcalloc (max_regno, sizeof (HARD_REG_SET));
 
   CLEAR_HARD_REG_SET (bad_spill_regs_global);
 
-  /* Look for REG_EQUIV notes; record what each pseudo is equivalent to.
-     Also find all paradoxical subregs and find largest such for each pseudo.
-     On machines with small register classes, record hard registers that
-     are used for user variables.  These can never be used for spills.
-     Also look for a "constant" REG_SETJMP.  This means that all
-     caller-saved registers must be marked live.  */
+  /* Look for REG_EQUIV notes; record what each pseudo is equivalent
+     to.  Also find all paradoxical subregs and find largest such for
+     each pseudo.  */
 
   num_eliminable_invariants = 0;
   for (insn = first; insn; insn = NEXT_INSN (insn))
@@ -744,12 +725,6 @@ reload (first, global)
          && GET_MODE (insn) != VOIDmode)
        PUT_MODE (insn, VOIDmode);
 
-      if (GET_CODE (insn) == CALL_INSN
-         && find_reg_note (insn, REG_SETJMP, NULL))
-       for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
-         if (! call_used_regs[i])
-           regs_ever_live[i] = 1;
-
       if (set != 0 && GET_CODE (SET_DEST (set)) == REG)
        {
          rtx note = find_reg_note (insn, REG_EQUIV, NULL_RTX);
@@ -846,9 +821,7 @@ reload (first, global)
      allocate would occasionally cause it to exceed the stack limit and
      cause a core dump.  */
   offsets_known_at = xmalloc (num_labels);
-  offsets_at
-    = (int (*)[NUM_ELIMINABLE_REGS])
-    xmalloc (num_labels * NUM_ELIMINABLE_REGS * sizeof (int));
+  offsets_at = xmalloc (num_labels * NUM_ELIMINABLE_REGS * sizeof (HOST_WIDE_INT));
 
   /* Alter each pseudo-reg rtx to contain its hard reg number.
      Assign stack slots to the pseudos that lack hard regs or equivalents.
@@ -878,9 +851,22 @@ reload (first, global)
 
   /* Spill any hard regs that we know we can't eliminate.  */
   CLEAR_HARD_REG_SET (used_spill_regs);
-  for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
-    if (! ep->can_eliminate)
-      spill_hard_reg (ep->from, 1);
+  /* There can be multiple ways to eliminate a register;
+     they should be listed adjacently.
+     Elimination for any register fails only if all possible ways fail.  */
+  for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; )
+    {
+      int from = ep->from;
+      int can_eliminate = 0;
+      do
+       {
+          can_eliminate |= ep->can_eliminate;
+          ep++;
+       }
+      while (ep < &reg_eliminate[NUM_ELIMINABLE_REGS] && ep->from == from);
+      if (! can_eliminate)
+       spill_hard_reg (from, 1);
+    }
 
 #if HARD_FRAME_POINTER_REGNUM != FRAME_POINTER_REGNUM
   if (frame_pointer_needed)
@@ -980,7 +966,7 @@ reload (first, global)
        {
          save_call_clobbered_regs ();
          /* That might have allocated new insn_chain structures.  */
-         reload_firstobj = (char *) obstack_alloc (&reload_obstack, 0);
+         reload_firstobj = obstack_alloc (&reload_obstack, 0);
        }
 
       calculate_needs_all_insns (global);
@@ -1187,7 +1173,7 @@ reload (first, global)
                && (GET_CODE (XEXP (PATTERN (insn), 0)) != MEM
                    || GET_MODE (XEXP (PATTERN (insn), 0)) != BLKmode
                    || (GET_CODE (XEXP (XEXP (PATTERN (insn), 0), 0)) != SCRATCH
-                       && XEXP (XEXP (PATTERN (insn), 0), 0) 
+                       && XEXP (XEXP (PATTERN (insn), 0), 0)
                                != stack_pointer_rtx))
                && (GET_CODE (XEXP (PATTERN (insn), 0)) != REG
                    || ! REG_FUNCTION_VALUE_P (XEXP (PATTERN (insn), 0)))))
@@ -1281,6 +1267,14 @@ reload (first, global)
      by this, so unshare everything here.  */
   unshare_all_rtl_again (first);
 
+#ifdef STACK_BOUNDARY
+  /* init_emit has set the alignment of the hard frame pointer
+     to STACK_BOUNDARY.  It is very likely no longer valid if
+     the hard frame pointer was used for register allocation.  */
+  if (!frame_pointer_needed)
+    REGNO_POINTER_ALIGN (HARD_FRAME_POINTER_REGNUM) = BITS_PER_UNIT;
+#endif
+
   return failure;
 }
 
@@ -1292,7 +1286,7 @@ reload (first, global)
    The whole thing is rather sick, I'm afraid.  */
 
 static void
-maybe_fix_stack_asms ()
+maybe_fix_stack_asms (void)
 {
 #ifdef STACK_REGS
   const char *constraints[MAX_RECOG_OPERANDS];
@@ -1405,30 +1399,27 @@ maybe_fix_stack_asms ()
 /* Copy the global variables n_reloads and rld into the corresponding elts
    of CHAIN.  */
 static void
-copy_reloads (chain)
-     struct insn_chain *chain;
+copy_reloads (struct insn_chain *chain)
 {
   chain->n_reloads = n_reloads;
-  chain->rld
-    = (struct reload *) obstack_alloc (&reload_obstack,
-                                      n_reloads * sizeof (struct reload));
+  chain->rld = obstack_alloc (&reload_obstack,
+                             n_reloads * sizeof (struct reload));
   memcpy (chain->rld, rld, n_reloads * sizeof (struct reload));
-  reload_insn_firstobj = (char *) obstack_alloc (&reload_obstack, 0);
+  reload_insn_firstobj = obstack_alloc (&reload_obstack, 0);
 }
 
 /* Walk the chain of insns, and determine for each whether it needs reloads
    and/or eliminations.  Build the corresponding insns_need_reload list, and
    set something_needs_elimination as appropriate.  */
 static void
-calculate_needs_all_insns (global)
-     int global;
+calculate_needs_all_insns (int global)
 {
   struct insn_chain **pprev_reload = &insns_need_reload;
   struct insn_chain *chain, *next = 0;
 
   something_needs_elimination = 0;
 
-  reload_insn_firstobj = (char *) obstack_alloc (&reload_obstack, 0);
+  reload_insn_firstobj = obstack_alloc (&reload_obstack, 0);
   for (chain = reload_insn_chain; chain != 0; chain = next)
     {
       rtx insn = chain->insn;
@@ -1536,9 +1527,7 @@ calculate_needs_all_insns (global)
    should be handled first.  *P1 and *P2 are the reload numbers.  */
 
 static int
-reload_reg_class_lower (r1p, r2p)
-     const void *r1p;
-     const void *r2p;
+reload_reg_class_lower (const void *r1p, const void *r2p)
 {
   int r1 = *(const short *) r1p, r2 = *(const short *) r2p;
   int t;
@@ -1580,8 +1569,7 @@ static int spill_add_cost[FIRST_PSEUDO_REGISTER];
 /* Update the spill cost arrays, considering that pseudo REG is live.  */
 
 static void
-count_pseudo (reg)
-     int reg;
+count_pseudo (int reg)
 {
   int freq = REG_FREQ (reg);
   int r = reg_renumber[reg];
@@ -1598,7 +1586,7 @@ count_pseudo (reg)
 
   spill_add_cost[r] += freq;
 
-  nregs = HARD_REGNO_NREGS (r, PSEUDO_REGNO_MODE (reg));
+  nregs = hard_regno_nregs[r][PSEUDO_REGNO_MODE (reg)];
   while (nregs-- > 0)
     spill_cost[r + nregs] += freq;
 }
@@ -1607,8 +1595,7 @@ count_pseudo (reg)
    contents of BAD_SPILL_REGS for the insn described by CHAIN.  */
 
 static void
-order_regs_for_reload (chain)
-     struct insn_chain *chain;
+order_regs_for_reload (struct insn_chain *chain)
 {
   int i;
   HARD_REG_SET used_by_pseudos;
@@ -1658,11 +1645,10 @@ static HARD_REG_SET used_spill_regs_local;
    update SPILL_COST/SPILL_ADD_COST.  */
 
 static void
-count_spilled_pseudo (spilled, spilled_nregs, reg)
-     int spilled, spilled_nregs, reg;
+count_spilled_pseudo (int spilled, int spilled_nregs, int reg)
 {
   int r = reg_renumber[reg];
-  int nregs = HARD_REGNO_NREGS (r, PSEUDO_REGNO_MODE (reg));
+  int nregs = hard_regno_nregs[r][PSEUDO_REGNO_MODE (reg)];
 
   if (REGNO_REG_SET_P (&spilled_pseudos, reg)
       || spilled + spilled_nregs <= r || r + nregs <= spilled)
@@ -1678,9 +1664,7 @@ count_spilled_pseudo (spilled, spilled_nregs, reg)
 /* Find reload register to use for reload number ORDER.  */
 
 static int
-find_reg (chain, order)
-     struct insn_chain *chain;
-     int order;
+find_reg (struct insn_chain *chain, int order)
 {
   int rnum = reload_order[order];
   struct reload *rl = rld + rnum;
@@ -1715,7 +1699,7 @@ find_reg (chain, order)
        {
          int this_cost = spill_cost[regno];
          int ok = 1;
-         unsigned int this_nregs = HARD_REGNO_NREGS (regno, rl->mode);
+         unsigned int this_nregs = hard_regno_nregs[regno][rl->mode];
 
          for (j = 1; j < this_nregs; j++)
            {
@@ -1751,10 +1735,10 @@ find_reg (chain, order)
   if (best_reg == -1)
     return 0;
 
-  if (rtl_dump_file)
-    fprintf (rtl_dump_file, "Using reg %d for reload %d\n", best_reg, rnum);
+  if (dump_file)
+    fprintf (dump_file, "Using reg %d for reload %d\n", best_reg, rnum);
 
-  rl->nregs = HARD_REGNO_NREGS (best_reg, rl->mode);
+  rl->nregs = hard_regno_nregs[best_reg][rl->mode];
   rl->regno = best_reg;
 
   EXECUTE_IF_SET_IN_REG_SET
@@ -1786,8 +1770,7 @@ find_reg (chain, order)
    for a smaller class even though it belongs to that class.  */
 
 static void
-find_reload_regs (chain)
-     struct insn_chain *chain;
+find_reload_regs (struct insn_chain *chain)
 {
   int i;
 
@@ -1803,7 +1786,7 @@ find_reload_regs (chain)
          int regno = REGNO (chain->rld[i].reg_rtx);
          chain->rld[i].regno = regno;
          chain->rld[i].nregs
-           = HARD_REGNO_NREGS (regno, GET_MODE (chain->rld[i].reg_rtx));
+           = hard_regno_nregs[regno][GET_MODE (chain->rld[i].reg_rtx)];
        }
       else
        chain->rld[i].regno = -1;
@@ -1815,8 +1798,8 @@ find_reload_regs (chain)
 
   CLEAR_HARD_REG_SET (used_spill_regs_local);
 
-  if (rtl_dump_file)
-    fprintf (rtl_dump_file, "Spilling for insn %d.\n", INSN_UID (chain->insn));
+  if (dump_file)
+    fprintf (dump_file, "Spilling for insn %d.\n", INSN_UID (chain->insn));
 
   qsort (reload_order, n_reloads, sizeof (short), reload_reg_class_lower);
 
@@ -1847,7 +1830,7 @@ find_reload_regs (chain)
 }
 
 static void
-select_reload_regs ()
+select_reload_regs (void)
 {
   struct insn_chain *chain;
 
@@ -1860,7 +1843,7 @@ select_reload_regs ()
 /* Delete all insns that were inserted by emit_caller_save_insns during
    this iteration.  */
 static void
-delete_caller_save_insns ()
+delete_caller_save_insns (void)
 {
   struct insn_chain *c = reload_insn_chain;
 
@@ -1892,9 +1875,7 @@ delete_caller_save_insns ()
    INSN should be one of the insns which needed this particular spill reg.  */
 
 static void
-spill_failure (insn, class)
-     rtx insn;
-     enum reg_class class;
+spill_failure (rtx insn, enum reg_class class)
 {
   static const char *const reg_class_names[] = REG_CLASS_NAMES;
   if (asm_noperands (PATTERN (insn)) >= 0)
@@ -1912,8 +1893,7 @@ spill_failure (insn, class)
    data that is dead in INSN.  */
 
 static void
-delete_dead_insn (insn)
-     rtx insn;
+delete_dead_insn (rtx insn)
 {
   rtx prev = prev_real_insn (insn);
   rtx prev_dest;
@@ -1941,9 +1921,7 @@ delete_dead_insn (insn)
    can share one stack slot.  */
 
 static void
-alter_reg (i, from_reg)
-     int i;
-     int from_reg;
+alter_reg (int i, int from_reg)
 {
   /* When outputting an inline function, this can happen
      for a reg that isn't actually used.  */
@@ -2091,15 +2069,14 @@ alter_reg (i, from_reg)
    used by pseudo-reg number REGNO.  */
 
 void
-mark_home_live (regno)
-     int regno;
+mark_home_live (int regno)
 {
   int i, lim;
 
   i = reg_renumber[regno];
   if (i < 0)
     return;
-  lim = i + HARD_REGNO_NREGS (i, PSEUDO_REGNO_MODE (regno));
+  lim = i + hard_regno_nregs[i][PSEUDO_REGNO_MODE (regno)];
   while (i < lim)
     regs_ever_live[i++] = 1;
 }
@@ -2115,10 +2092,7 @@ mark_home_live (regno)
    current offset.  */
 
 static void
-set_label_offsets (x, insn, initial_p)
-     rtx x;
-     rtx insn;
-     int initial_p;
+set_label_offsets (rtx x, rtx insn, int initial_p)
 {
   enum rtx_code code = GET_CODE (x);
   rtx tem;
@@ -2281,10 +2255,7 @@ set_label_offsets (x, insn, initial_p)
    the proper thing.  */
 
 rtx
-eliminate_regs (x, mem_mode, insn)
-     rtx x;
-     enum machine_mode mem_mode;
-     rtx insn;
+eliminate_regs (rtx x, enum machine_mode mem_mode, rtx insn)
 {
   enum rtx_code code = GET_CODE (x);
   struct elim_table *ep;
@@ -2350,7 +2321,7 @@ eliminate_regs (x, mem_mode, insn)
        and require special code to handle code a reloaded PLUS operand.
 
        Also consider backends where the flags register is clobbered by a
-       MINUS, but we can emit a PLUS that does not clobber flags (ia32,
+       MINUS, but we can emit a PLUS that does not clobber flags (IA-32,
        lea instruction comes to mind).  If we try to reload a MINUS, we
        may kill the flags register that was holding a useful value.
 
@@ -2542,7 +2513,7 @@ eliminate_regs (x, mem_mode, insn)
         Convert (subreg (mem)) to (mem) if not paradoxical.
         Also, if we have a non-paradoxical (subreg (pseudo)) and the
         pseudo didn't get a hard reg, we must replace this with the
-        eliminated version of the memory location because push_reloads
+        eliminated version of the memory location because push_reload
         may do the replacement in certain circumstances.  */
       if (GET_CODE (SUBREG_REG (x)) == REG
          && (GET_MODE_SIZE (GET_MODE (x))
@@ -2569,7 +2540,7 @@ eliminate_regs (x, mem_mode, insn)
                      happen to the entire word.  Moreover, it will use the
                      (reg:m2 R) later, expecting all bits to be preserved.
                      So if the number of words is the same, preserve the
-                     subreg so that push_reloads can see it.  */
+                     subreg so that push_reload can see it.  */
                   && ! ((x_size - 1) / UNITS_PER_WORD
                         == (new_size -1 ) / UNITS_PER_WORD)
 #endif
@@ -2625,9 +2596,7 @@ eliminate_regs (x, mem_mode, insn)
          if (new != XEXP (x, i) && ! copied)
            {
              rtx new_x = rtx_alloc (code);
-             memcpy (new_x, x,
-                     (sizeof (*new_x) - sizeof (new_x->fld)
-                      + sizeof (new_x->fld[0]) * GET_RTX_LENGTH (code)));
+             memcpy (new_x, x, RTX_SIZE (code));
              x = new_x;
              copied = 1;
            }
@@ -2646,10 +2615,7 @@ eliminate_regs (x, mem_mode, insn)
                  if (! copied)
                    {
                      rtx new_x = rtx_alloc (code);
-                     memcpy (new_x, x,
-                             (sizeof (*new_x) - sizeof (new_x->fld)
-                              + (sizeof (new_x->fld[0])
-                                 * GET_RTX_LENGTH (code))));
+                     memcpy (new_x, x, RTX_SIZE (code));
                      x = new_x;
                      copied = 1;
                    }
@@ -2669,10 +2635,7 @@ eliminate_regs (x, mem_mode, insn)
    the mode of an enclosing MEM rtx, or VOIDmode if not within a MEM.  */
 
 static void
-elimination_effects (x, mem_mode)
-     rtx x;
-     enum machine_mode mem_mode;
-
+elimination_effects (rtx x, enum machine_mode mem_mode)
 {
   enum rtx_code code = GET_CODE (x);
   struct elim_table *ep;
@@ -2869,8 +2832,7 @@ elimination_effects (x, mem_mode)
    eliminable.  */
 
 static void
-check_eliminable_occurrences (x)
-     rtx x;
+check_eliminable_occurrences (rtx x)
 {
   const char *fmt;
   int i;
@@ -2886,7 +2848,7 @@ check_eliminable_occurrences (x)
       struct elim_table *ep;
 
       for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
-       if (ep->from_rtx == x && ep->can_eliminate)
+       if (ep->from_rtx == x)
          ep->can_eliminate = 0;
       return;
     }
@@ -2919,9 +2881,7 @@ check_eliminable_occurrences (x)
    is returned.  Otherwise, 1 is returned.  */
 
 static int
-eliminate_regs_in_insn (insn, replace)
-     rtx insn;
-     int replace;
+eliminate_regs_in_insn (rtx insn, int replace)
 {
   int icode = recog_memoized (insn);
   rtx old_body = PATTERN (insn);
@@ -2933,6 +2893,7 @@ eliminate_regs_in_insn (insn, replace)
   rtx substed_operand[MAX_RECOG_OPERANDS];
   rtx orig_operand[MAX_RECOG_OPERANDS];
   struct elim_table *ep;
+  rtx plus_src;
 
   if (! insn_is_asm && icode < 0)
     {
@@ -2963,7 +2924,7 @@ eliminate_regs_in_insn (insn, replace)
              {
                rtx base = SET_SRC (old_set);
                rtx base_insn = insn;
-               int offset = 0;
+               HOST_WIDE_INT offset = 0;
 
                while (base != ep->to_rtx)
                  {
@@ -3036,17 +2997,40 @@ eliminate_regs_in_insn (insn, replace)
     }
 
   /* We allow one special case which happens to work on all machines we
-     currently support: a single set with the source being a PLUS of an
-     eliminable register and a constant.  */
-  if (old_set
-      && GET_CODE (SET_DEST (old_set)) == REG
-      && GET_CODE (SET_SRC (old_set)) == PLUS
-      && GET_CODE (XEXP (SET_SRC (old_set), 0)) == REG
-      && GET_CODE (XEXP (SET_SRC (old_set), 1)) == CONST_INT
-      && REGNO (XEXP (SET_SRC (old_set), 0)) < FIRST_PSEUDO_REGISTER)
+     currently support: a single set with the source or a REG_EQUAL
+     note being a PLUS of an eliminable register and a constant.  */
+  plus_src = 0;
+  if (old_set && GET_CODE (SET_DEST (old_set)) == REG)
+    {
+      /* First see if the source is of the form (plus (reg) CST).  */
+      if (GET_CODE (SET_SRC (old_set)) == PLUS
+         && GET_CODE (XEXP (SET_SRC (old_set), 0)) == REG
+         && GET_CODE (XEXP (SET_SRC (old_set), 1)) == CONST_INT
+         && REGNO (XEXP (SET_SRC (old_set), 0)) < FIRST_PSEUDO_REGISTER)
+       plus_src = SET_SRC (old_set);
+      else if (GET_CODE (SET_SRC (old_set)) == REG)
+       {
+         /* Otherwise, see if we have a REG_EQUAL note of the form
+            (plus (reg) CST).  */
+         rtx links;
+         for (links = REG_NOTES (insn); links; links = XEXP (links, 1))
+           {
+             if (REG_NOTE_KIND (links) == REG_EQUAL
+                 && GET_CODE (XEXP (links, 0)) == PLUS
+                 && GET_CODE (XEXP (XEXP (links, 0), 0)) == REG
+                 && GET_CODE (XEXP (XEXP (links, 0), 1)) == CONST_INT
+                 && REGNO (XEXP (XEXP (links, 0), 0)) < FIRST_PSEUDO_REGISTER)
+               {
+                 plus_src = XEXP (links, 0);
+                 break;
+               }
+           }
+       }
+    }
+  if (plus_src)
     {
-      rtx reg = XEXP (SET_SRC (old_set), 0);
-      int offset = INTVAL (XEXP (SET_SRC (old_set), 1));
+      rtx reg = XEXP (plus_src, 0);
+      HOST_WIDE_INT offset = INTVAL (XEXP (plus_src, 1));
 
       for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
        if (ep->from_rtx == reg && ep->can_eliminate)
@@ -3076,7 +3060,12 @@ eliminate_regs_in_insn (insn, replace)
                if (INSN_CODE (insn) < 0)
                  abort ();
              }
-           else
+           /* If we have a nonzero offset, and the source is already
+              a simple REG, the following transformation would
+              increase the cost of the insn by replacing a simple REG
+              with (plus (reg sp) CST).  So try only when plus_src
+              comes from old_set proper, not REG_NOTES.  */
+           else if (SET_SRC (old_set) == plus_src)
              {
                new_body = old_body;
                if (! replace)
@@ -3091,6 +3080,9 @@ eliminate_regs_in_insn (insn, replace)
                XEXP (SET_SRC (old_set), 0) = ep->to_rtx;
                XEXP (SET_SRC (old_set), 1) = GEN_INT (offset);
              }
+           else
+             break;
+
            val = 1;
            /* This can't have an effect on elimination offsets, so skip right
               to the end.  */
@@ -3122,7 +3114,7 @@ eliminate_regs_in_insn (insn, replace)
                 eliminate this reg.  */
              for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS];
                   ep++)
-               if (ep->from_rtx == orig_operand[i] && ep->can_eliminate)
+               if (ep->from_rtx == orig_operand[i])
                  ep->can_eliminate = 0;
            }
 
@@ -3267,7 +3259,7 @@ eliminate_regs_in_insn (insn, replace)
    grow downward) for each elimination pair.  */
 
 static void
-update_eliminable_offsets ()
+update_eliminable_offsets (void)
 {
   struct elim_table *ep;
 
@@ -3295,10 +3287,7 @@ update_eliminable_offsets ()
    the insns of the function.  */
 
 static void
-mark_not_eliminable (dest, x, data)
-     rtx dest;
-     rtx x;
-     void *data ATTRIBUTE_UNUSED;
+mark_not_eliminable (rtx dest, rtx x, void *data ATTRIBUTE_UNUSED)
 {
   unsigned int i;
 
@@ -3330,9 +3319,9 @@ mark_not_eliminable (dest, x, data)
    cause incorrect code to be generated if we did not check for it.  */
 
 static void
-verify_initial_elim_offsets ()
+verify_initial_elim_offsets (void)
 {
-  int t;
+  HOST_WIDE_INT t;
 
 #ifdef ELIMINABLE_REGS
   struct elim_table *ep;
@@ -3353,7 +3342,7 @@ verify_initial_elim_offsets ()
 /* Reset all offsets on eliminable registers to their initial values.  */
 
 static void
-set_initial_elim_offsets ()
+set_initial_elim_offsets (void)
 {
   struct elim_table *ep = reg_eliminate;
 
@@ -3379,7 +3368,7 @@ set_initial_elim_offsets ()
    For all other labels, show that we don't know the offsets.  */
 
 static void
-set_initial_label_offsets ()
+set_initial_label_offsets (void)
 {
   rtx x;
   memset (offsets_known_at, 0, num_labels);
@@ -3393,8 +3382,7 @@ set_initial_label_offsets ()
    by INSN.  */
 
 static void
-set_offsets_for_label (insn)
-     rtx insn;
+set_offsets_for_label (rtx insn)
 {
   unsigned int i;
   int label_nr = CODE_LABEL_NUMBER (insn);
@@ -3417,8 +3405,7 @@ set_offsets_for_label (insn)
    since they can't have changed.  */
 
 static void
-update_eliminables (pset)
-     HARD_REG_SET *pset;
+update_eliminables (HARD_REG_SET *pset)
 {
   int previous_frame_pointer_needed = frame_pointer_needed;
   struct elim_table *ep;
@@ -3494,7 +3481,7 @@ update_eliminables (pset)
 /* Initialize the table of registers to eliminate.  */
 
 static void
-init_elim_table ()
+init_elim_table (void)
 {
   struct elim_table *ep;
 #ifdef ELIMINABLE_REGS
@@ -3502,13 +3489,11 @@ init_elim_table ()
 #endif
 
   if (!reg_eliminate)
-    reg_eliminate = (struct elim_table *)
-      xcalloc (sizeof (struct elim_table), NUM_ELIMINABLE_REGS);
+    reg_eliminate = xcalloc (sizeof (struct elim_table), NUM_ELIMINABLE_REGS);
 
   /* Does this function require a frame pointer?  */
 
   frame_pointer_needed = (! flag_omit_frame_pointer
-#ifdef EXIT_IGNORE_STACK
                          /* ?? If EXIT_IGNORE_STACK is set, we will not save
                             and restore sp for alloca.  So we can't eliminate
                             the frame pointer in that case.  At some point,
@@ -3516,7 +3501,6 @@ init_elim_table ()
                             sp-adjusting insns for this case.  */
                          || (current_function_calls_alloca
                              && EXIT_IGNORE_STACK)
-#endif
                          || FRAME_POINTER_REQUIRED);
 
   num_eliminable = 0;
@@ -3539,8 +3523,8 @@ init_elim_table ()
 #endif
 
   /* Count the number of eliminable registers and build the FROM and TO
-     REG rtx's.  Note that code in gen_rtx will cause, e.g.,
-     gen_rtx (REG, Pmode, STACK_POINTER_REGNUM) to equal stack_pointer_rtx.
+     REG rtx's.  Note that code in gen_rtx_REG will cause, e.g.,
+     gen_rtx_REG (Pmode, STACK_POINTER_REGNUM) to equal stack_pointer_rtx.
      We depend on this.  */
   for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
     {
@@ -3561,9 +3545,7 @@ init_elim_table ()
    Return nonzero if any pseudos needed to be kicked out.  */
 
 static void
-spill_hard_reg (regno, cant_eliminate)
-     unsigned int regno;
-     int cant_eliminate;
+spill_hard_reg (unsigned int regno, int cant_eliminate)
 {
   int i;
 
@@ -3580,8 +3562,8 @@ spill_hard_reg (regno, cant_eliminate)
     if (reg_renumber[i] >= 0
        && (unsigned int) reg_renumber[i] <= regno
        && ((unsigned int) reg_renumber[i]
-           + HARD_REGNO_NREGS ((unsigned int) reg_renumber[i],
-                               PSEUDO_REGNO_MODE (i))
+           + hard_regno_nregs[(unsigned int) reg_renumber[i]]
+                             [PSEUDO_REGNO_MODE (i)]
            > regno))
       SET_REGNO_REG_SET (&spilled_pseudos, i);
 }
@@ -3590,8 +3572,7 @@ spill_hard_reg (regno, cant_eliminate)
    from within EXECUTE_IF_SET_IN_REG_SET.  Hence this awkwardness.  */
 
 static void
-ior_hard_reg_set (set1, set2)
-     HARD_REG_SET *set1, *set2;
+ior_hard_reg_set (HARD_REG_SET *set1, HARD_REG_SET *set2)
 {
   IOR_HARD_REG_SET (*set1, *set2);
 }
@@ -3602,8 +3583,7 @@ ior_hard_reg_set (set1, set2)
    spill_regs array for use by choose_reload_regs.  */
 
 static int
-finish_spills (global)
-     int global;
+finish_spills (int global)
 {
   struct insn_chain *chain;
   int something_changed = 0;
@@ -3653,7 +3633,7 @@ finish_spills (global)
   /* Retry global register allocation if possible.  */
   if (global)
     {
-      memset ((char *) pseudo_forbidden_regs, 0, max_regno * sizeof (HARD_REG_SET));
+      memset (pseudo_forbidden_regs, 0, max_regno * sizeof (HARD_REG_SET));
       /* For every insn that needs reloads, set the registers used as spill
         regs in pseudo_forbidden_regs for every pseudo live across the
         insn.  */
@@ -3734,12 +3714,12 @@ finish_spills (global)
 
       alter_reg (i, reg_old_renumber[i]);
       reg_old_renumber[i] = regno;
-      if (rtl_dump_file)
+      if (dump_file)
        {
          if (regno == -1)
-           fprintf (rtl_dump_file, " Register %d now on stack.\n\n", i);
+           fprintf (dump_file, " Register %d now on stack.\n\n", i);
          else
-           fprintf (rtl_dump_file, " Register %d now in %d.\n\n",
+           fprintf (dump_file, " Register %d now in %d.\n\n",
                     i, reg_renumber[i]);
        }
     }
@@ -3747,13 +3727,10 @@ finish_spills (global)
   return something_changed;
 }
 \f
-/* Find all paradoxical subregs within X and update reg_max_ref_width.
-   Also mark any hard registers used to store user variables as
-   forbidden from being used for spill registers.  */
+/* Find all paradoxical subregs within X and update reg_max_ref_width.  */
 
 static void
-scan_paradoxical_subregs (x)
-     rtx x;
+scan_paradoxical_subregs (rtx x)
 {
   int i;
   const char *fmt;
@@ -3762,13 +3739,6 @@ scan_paradoxical_subregs (x)
   switch (code)
     {
     case REG:
-#if 0
-      if (SMALL_REGISTER_CLASSES && REGNO (x) < FIRST_PSEUDO_REGISTER
-         && REG_USERVAR_P (x))
-       SET_HARD_REG_BIT (bad_spill_regs_global, REGNO (x));
-#endif
-      return;
-
     case CONST_INT:
     case CONST:
     case SYMBOL_REF:
@@ -3816,8 +3786,7 @@ scan_paradoxical_subregs (x)
    as the insns are scanned.  */
 
 static void
-reload_as_needed (live_known)
-     int live_known;
+reload_as_needed (int live_known)
 {
   struct insn_chain *chain;
 #if defined (AUTO_INC_DEC)
@@ -3825,11 +3794,12 @@ reload_as_needed (live_known)
 #endif
   rtx x;
 
-  memset ((char *) spill_reg_rtx, 0, sizeof spill_reg_rtx);
-  memset ((char *) spill_reg_store, 0, sizeof spill_reg_store);
-  reg_last_reload_reg = (rtx *) xcalloc (max_regno, sizeof (rtx));
-  reg_has_output_reload = (char *) xmalloc (max_regno);
+  memset (spill_reg_rtx, 0, sizeof spill_reg_rtx);
+  memset (spill_reg_store, 0, sizeof spill_reg_store);
+  reg_last_reload_reg = xcalloc (max_regno, sizeof (rtx));
+  reg_has_output_reload = xmalloc (max_regno);
   CLEAR_HARD_REG_SET (reg_reloaded_valid);
+  CLEAR_HARD_REG_SET (reg_reloaded_call_part_clobbered);
 
   set_initial_elim_offsets ();
 
@@ -3999,8 +3969,9 @@ reload_as_needed (live_known)
                          if (n == 1)
                            {
                              n = validate_replace_rtx (reload_reg,
-                                                       gen_rtx (code, mode,
-                                                                reload_reg),
+                                                       gen_rtx_fmt_e (code,
+                                                                      mode,
+                                                                      reload_reg),
                                                        p);
 
                              /* We must also verify that the constraints
@@ -4015,8 +3986,9 @@ reload_as_needed (live_known)
                                 undo the replacement.  */
                              if (!n)
                                {
-                                 validate_replace_rtx (gen_rtx (code, mode,
-                                                                reload_reg),
+                                 validate_replace_rtx (gen_rtx_fmt_e (code,
+                                                                      mode,
+                                                                      reload_reg),
                                                        reload_reg, p);
                                  break;
                                }
@@ -4077,9 +4049,13 @@ reload_as_needed (live_known)
        CLEAR_HARD_REG_SET (reg_reloaded_valid);
 
       /* Don't assume a reload reg is still good after a call insn
-        if it is a call-used reg.  */
+        if it is a call-used reg, or if it contains a value that will
+         be partially clobbered by the call.  */
       else if (GET_CODE (insn) == CALL_INSN)
+       {
        AND_COMPL_HARD_REG_SET (reg_reloaded_valid, call_used_reg_set);
+       AND_COMPL_HARD_REG_SET (reg_reloaded_valid, reg_reloaded_call_part_clobbered);
+       }
     }
 
   /* Clean up.  */
@@ -4095,10 +4071,8 @@ reload_as_needed (live_known)
    or it may be a pseudo reg that was reloaded from.  */
 
 static void
-forget_old_reloads_1 (x, ignored, data)
-     rtx x;
-     rtx ignored ATTRIBUTE_UNUSED;
-     void *data ATTRIBUTE_UNUSED;
+forget_old_reloads_1 (rtx x, rtx ignored ATTRIBUTE_UNUSED,
+                     void *data ATTRIBUTE_UNUSED)
 {
   unsigned int regno;
   unsigned int nr;
@@ -4124,7 +4098,7 @@ forget_old_reloads_1 (x, ignored, data)
     {
       unsigned int i;
 
-      nr = HARD_REGNO_NREGS (regno, GET_MODE (x));
+      nr = hard_regno_nregs[regno][GET_MODE (x)];
       /* Storing into a spilled-reg invalidates its contents.
         This can happen if a block-local pseudo is allocated to that reg
         and it wasn't spilled because this block's total need is 0.
@@ -4136,6 +4110,7 @@ forget_old_reloads_1 (x, ignored, data)
            || ! TEST_HARD_REG_BIT (reg_is_output_reload, regno + i))
          {
            CLEAR_HARD_REG_BIT (reg_reloaded_valid, regno + i);
+           CLEAR_HARD_REG_BIT (reg_reloaded_call_part_clobbered, regno + i);
            spill_reg_store[regno + i] = 0;
          }
     }
@@ -4194,13 +4169,10 @@ static HARD_REG_SET reg_used_in_insn;
    actually used.  */
 
 static void
-mark_reload_reg_in_use (regno, opnum, type, mode)
-     unsigned int regno;
-     int opnum;
-     enum reload_type type;
-     enum machine_mode mode;
+mark_reload_reg_in_use (unsigned int regno, int opnum, enum reload_type type,
+                       enum machine_mode mode)
 {
-  unsigned int nregs = HARD_REGNO_NREGS (regno, mode);
+  unsigned int nregs = hard_regno_nregs[regno][mode];
   unsigned int i;
 
   for (i = regno; i < nregs + regno; i++)
@@ -4259,13 +4231,10 @@ mark_reload_reg_in_use (regno, opnum, type, mode)
 /* Similarly, but show REGNO is no longer in use for a reload.  */
 
 static void
-clear_reload_reg_in_use (regno, opnum, type, mode)
-     unsigned int regno;
-     int opnum;
-     enum reload_type type;
-     enum machine_mode mode;
+clear_reload_reg_in_use (unsigned int regno, int opnum,
+                        enum reload_type type, enum machine_mode mode)
 {
-  unsigned int nregs = HARD_REGNO_NREGS (regno, mode);
+  unsigned int nregs = hard_regno_nregs[regno][mode];
   unsigned int start_regno, end_regno, r;
   int i;
   /* A complication is that for some reload types, inheritance might
@@ -4349,7 +4318,7 @@ clear_reload_reg_in_use (regno, opnum, type, mode)
              unsigned int conflict_start = true_regnum (rld[i].reg_rtx);
              unsigned int conflict_end
                = (conflict_start
-                  + HARD_REGNO_NREGS (conflict_start, rld[i].mode));
+                  + hard_regno_nregs[conflict_start][rld[i].mode]);
 
              /* If there is an overlap with the first to-be-freed register,
                 adjust the interval start.  */
@@ -4371,10 +4340,7 @@ clear_reload_reg_in_use (regno, opnum, type, mode)
    specified by OPNUM and TYPE.  */
 
 static int
-reload_reg_free_p (regno, opnum, type)
-     unsigned int regno;
-     int opnum;
-     enum reload_type type;
+reload_reg_free_p (unsigned int regno, int opnum, enum reload_type type)
 {
   int i;
 
@@ -4389,6 +4355,7 @@ reload_reg_free_p (regno, opnum, type)
       /* In use for anything means we can't use it for RELOAD_OTHER.  */
       if (TEST_HARD_REG_BIT (reload_reg_used_in_other_addr, regno)
          || TEST_HARD_REG_BIT (reload_reg_used_in_op_addr, regno)
+         || TEST_HARD_REG_BIT (reload_reg_used_in_op_addr_reload, regno)
          || TEST_HARD_REG_BIT (reload_reg_used_in_insn, regno))
        return 0;
 
@@ -4537,10 +4504,7 @@ reload_reg_free_p (regno, opnum, type)
    in case the reg has already been marked in use.  */
 
 static int
-reload_reg_reaches_end_p (regno, opnum, type)
-     unsigned int regno;
-     int opnum;
-     enum reload_type type;
+reload_reg_reaches_end_p (unsigned int regno, int opnum, enum reload_type type)
 {
   int i;
 
@@ -4570,6 +4534,7 @@ reload_reg_reaches_end_p (regno, opnum, type)
          return 0;
 
       return (! TEST_HARD_REG_BIT (reload_reg_used_in_op_addr, regno)
+             && ! TEST_HARD_REG_BIT (reload_reg_used_in_op_addr_reload, regno)
              && ! TEST_HARD_REG_BIT (reload_reg_used_in_insn, regno)
              && ! TEST_HARD_REG_BIT (reload_reg_used, regno));
 
@@ -4670,8 +4635,7 @@ reload_reg_reaches_end_p (regno, opnum, type)
    This function uses the same algorithm as reload_reg_free_p above.  */
 
 int
-reloads_conflict (r1, r2)
-     int r1, r2;
+reloads_conflict (int r1, int r2)
 {
   enum reload_type r1_type = rld[r1].when_needed;
   enum reload_type r2_type = rld[r2].when_needed;
@@ -4762,14 +4726,9 @@ int reload_spill_index[MAX_RELOADS];
    (possibly comprising multiple hard registers) that we are considering.  */
 
 static int
-reload_reg_free_for_value_p (start_regno, regno, opnum, type, value, out,
-                            reloadnum, ignore_address_reloads)
-     int start_regno, regno;
-     int opnum;
-     enum reload_type type;
-     rtx value, out;
-     int reloadnum;
-     int ignore_address_reloads;
+reload_reg_free_for_value_p (int start_regno, int regno, int opnum,
+                            enum reload_type type, rtx value, rtx out,
+                            int reloadnum, int ignore_address_reloads)
 {
   int time1;
   /* Set if we see an input reload that must not share its reload register
@@ -4854,7 +4813,7 @@ reload_reg_free_for_value_p (start_regno, regno, opnum, type, value, out,
       rtx reg = rld[i].reg_rtx;
       if (reg && GET_CODE (reg) == REG
          && ((unsigned) regno - true_regnum (reg)
-             <= HARD_REGNO_NREGS (REGNO (reg), GET_MODE (reg)) - (unsigned) 1)
+             <= hard_regno_nregs[REGNO (reg)][GET_MODE (reg)] - (unsigned) 1)
          && i != reloadnum)
        {
          rtx other_input = rld[i].in;
@@ -5006,17 +4965,11 @@ reload_reg_free_for_value_p (start_regno, regno, opnum, type, value, out,
    register.  */
 
 static int
-free_for_value_p (regno, mode, opnum, type, value, out, reloadnum,
-                 ignore_address_reloads)
-     int regno;
-     enum machine_mode mode;
-     int opnum;
-     enum reload_type type;
-     rtx value, out;
-     int reloadnum;
-     int ignore_address_reloads;
+free_for_value_p (int regno, enum machine_mode mode, int opnum,
+                 enum reload_type type, rtx value, rtx out, int reloadnum,
+                 int ignore_address_reloads)
 {
-  int nregs = HARD_REGNO_NREGS (regno, mode);
+  int nregs = hard_regno_nregs[regno][mode];
   while (nregs-- > 0)
     if (! reload_reg_free_for_value_p (regno, regno + nregs, opnum, type,
                                       value, out, reloadnum,
@@ -5025,12 +4978,32 @@ free_for_value_p (regno, mode, opnum, type, value, out, reloadnum,
   return 1;
 }
 
+/* Return nonzero if the rtx X is invariant over the current function.  */
+/* ??? Actually, the places where we use this expect exactly what
+ * is tested here, and not everything that is function invariant.  In
+ * particular, the frame pointer and arg pointer are special cased;
+ * pic_offset_table_rtx is not, and this will cause aborts when we
+ *             go to spill these things to memory.  */
+
+static int
+function_invariant_p (rtx x)
+{
+  if (CONSTANT_P (x))
+    return 1;
+  if (x == frame_pointer_rtx || x == arg_pointer_rtx)
+    return 1;
+  if (GET_CODE (x) == PLUS
+      && (XEXP (x, 0) == frame_pointer_rtx || XEXP (x, 0) == arg_pointer_rtx)
+      && CONSTANT_P (XEXP (x, 1)))
+    return 1;
+  return 0;
+}
+
 /* Determine whether the reload reg X overlaps any rtx'es used for
    overriding inheritance.  Return nonzero if so.  */
 
 static int
-conflicts_with_override (x)
-     rtx x;
+conflicts_with_override (rtx x)
 {
   int i;
   for (i = 0; i < n_reloads; i++)
@@ -5043,9 +5016,7 @@ conflicts_with_override (x)
 /* Give an error message saying we failed to find a reload for INSN,
    and clear out reload R.  */
 static void
-failed_reload (insn, r)
-     rtx insn;
-     int r;
+failed_reload (rtx insn, int r)
 {
   if (asm_noperands (PATTERN (insn)) < 0)
     /* It's the compiler's fault.  */
@@ -5066,8 +5037,7 @@ failed_reload (insn, r)
    for reload R.  If it's valid, get an rtx for it.  Return nonzero if
    successful.  */
 static int
-set_reload_reg (i, r)
-     int i, r;
+set_reload_reg (int i, int r)
 {
   int regno;
   rtx reg = spill_reg_rtx[i];
@@ -5122,10 +5092,8 @@ set_reload_reg (i, r)
    we didn't change anything.  */
 
 static int
-allocate_reload_reg (chain, r, last_reload)
-     struct insn_chain *chain ATTRIBUTE_UNUSED;
-     int r;
-     int last_reload;
+allocate_reload_reg (struct insn_chain *chain ATTRIBUTE_UNUSED, int r,
+                    int last_reload)
 {
   int i, pass, count;
 
@@ -5195,7 +5163,7 @@ allocate_reload_reg (chain, r, last_reload)
                      && ! TEST_HARD_REG_BIT (reload_reg_used_for_inherit,
                                              regnum))))
            {
-             int nr = HARD_REGNO_NREGS (regnum, rld[r].mode);
+             int nr = hard_regno_nregs[regnum][rld[r].mode];
              /* Avoid the problem where spilling a GENERAL_OR_FP_REG
                 (on 68000) got us two FP regs.  If NR is 1,
                 we would reject both of them.  */
@@ -5246,9 +5214,7 @@ allocate_reload_reg (chain, r, last_reload)
    is the array we use to restore the reg_rtx field for every reload.  */
 
 static void
-choose_reload_regs_init (chain, save_reload_reg_rtx)
-     struct insn_chain *chain;
-     rtx *save_reload_reg_rtx;
+choose_reload_regs_init (struct insn_chain *chain, rtx *save_reload_reg_rtx)
 {
   int i;
 
@@ -5256,8 +5222,8 @@ choose_reload_regs_init (chain, save_reload_reg_rtx)
     rld[i].reg_rtx = save_reload_reg_rtx[i];
 
   memset (reload_inherited, 0, MAX_RELOADS);
-  memset ((char *) reload_inheritance_insn, 0, MAX_RELOADS * sizeof (rtx));
-  memset ((char *) reload_override_in, 0, MAX_RELOADS * sizeof (rtx));
+  memset (reload_inheritance_insn, 0, MAX_RELOADS * sizeof (rtx));
+  memset (reload_override_in, 0, MAX_RELOADS * sizeof (rtx));
 
   CLEAR_HARD_REG_SET (reload_reg_used);
   CLEAR_HARD_REG_SET (reload_reg_used_at_all);
@@ -5307,8 +5273,7 @@ choose_reload_regs_init (chain, save_reload_reg_rtx)
    finding a reload reg in the proper class.  */
 
 static void
-choose_reload_regs (chain)
-     struct insn_chain *chain;
+choose_reload_regs (struct insn_chain *chain)
 {
   rtx insn = chain->insn;
   int i, j;
@@ -5531,7 +5496,7 @@ choose_reload_regs (chain)
                    {
                      /* If a group is needed, verify that all the subsequent
                         registers still have their values intact.  */
-                     int nr = HARD_REGNO_NREGS (i, rld[r].mode);
+                     int nr = hard_regno_nregs[i][rld[r].mode];
                      int k;
 
                      for (k = 1; k < nr; k++)
@@ -5681,7 +5646,7 @@ choose_reload_regs (chain)
                    {
                      regs_used |= TEST_HARD_REG_BIT (reload_reg_used_at_all,
                                                      i);
-                     bad_for_class |= ! TEST_HARD_REG_BIT (reg_class_contents[(int) rld[r].class], 
+                     bad_for_class |= ! TEST_HARD_REG_BIT (reg_class_contents[(int) rld[r].class],
                                                           i);
                    }
 
@@ -5764,7 +5729,7 @@ choose_reload_regs (chain)
                  && (regno != HARD_FRAME_POINTER_REGNUM
                      || !frame_pointer_needed))
                {
-                 int nr = HARD_REGNO_NREGS (regno, rld[r].mode);
+                 int nr = hard_regno_nregs[regno][rld[r].mode];
                  int k;
                  rld[r].reg_rtx = equiv;
                  reload_inherited[r] = 1;
@@ -5979,14 +5944,14 @@ choose_reload_regs (chain)
          int nr = 1;
 
          if (nregno < FIRST_PSEUDO_REGISTER)
-           nr = HARD_REGNO_NREGS (nregno, rld[r].mode);
+           nr = hard_regno_nregs[nregno][rld[r].mode];
 
          while (--nr >= 0)
            reg_has_output_reload[nregno + nr] = 1;
 
          if (i >= 0)
            {
-             nr = HARD_REGNO_NREGS (i, rld[r].mode);
+             nr = hard_regno_nregs[i][rld[r].mode];
              while (--nr >= 0)
                SET_HARD_REG_BIT (reg_is_output_reload, i + nr);
            }
@@ -6003,8 +5968,7 @@ choose_reload_regs (chain)
    remove_address_replacements.  */
 
 void
-deallocate_reload_reg (r)
-     int r;
+deallocate_reload_reg (int r)
 {
   int regno;
 
@@ -6032,8 +5996,7 @@ deallocate_reload_reg (r)
    prevent redundant code.  */
 
 static void
-merge_assigned_reloads (insn)
-     rtx insn;
+merge_assigned_reloads (rtx insn)
 {
   int i, j;
 
@@ -6173,11 +6136,8 @@ static HARD_REG_SET reg_reloaded_died;
    has the number J.  OLD contains the value to be used as input.  */
 
 static void
-emit_input_reload_insns (chain, rl, old, j)
-     struct insn_chain *chain;
-     struct reload *rl;
-     rtx old;
-     int j;
+emit_input_reload_insns (struct insn_chain *chain, struct reload *rl,
+                        rtx old, int j)
 {
   rtx insn = chain->insn;
   rtx reloadreg = rl->reg_rtx;
@@ -6664,10 +6624,8 @@ emit_input_reload_insns (chain, rl, old, j)
 /* Generate insns to for the output reload RL, which is for the insn described
    by CHAIN and has the number J.  */
 static void
-emit_output_reload_insns (chain, rl, j)
-     struct insn_chain *chain;
-     struct reload *rl;
-     int j;
+emit_output_reload_insns (struct insn_chain *chain, struct reload *rl,
+                         int j)
 {
   rtx reloadreg = rl->reg_rtx;
   rtx insn = chain->insn;
@@ -6878,10 +6836,7 @@ emit_output_reload_insns (chain, rl, j)
 /* Do input reloading for reload RL, which is for the insn described by CHAIN
    and has the number J.  */
 static void
-do_input_reload (chain, rl, j)
-     struct insn_chain *chain;
-     struct reload *rl;
-     int j;
+do_input_reload (struct insn_chain *chain, struct reload *rl, int j)
 {
   rtx insn = chain->insn;
   rtx old = (rl->in && GET_CODE (rl->in) == MEM
@@ -6936,10 +6891,7 @@ do_input_reload (chain, rl, j)
    ??? At some point we need to support handling output reloads of
    JUMP_INSNs or insns that set cc0.  */
 static void
-do_output_reload (chain, rl, j)
-     struct insn_chain *chain;
-     struct reload *rl;
-     int j;
+do_output_reload (struct insn_chain *chain, struct reload *rl, int j)
 {
   rtx note, old;
   rtx insn = chain->insn;
@@ -7005,11 +6957,31 @@ do_output_reload (chain, rl, j)
   emit_output_reload_insns (chain, rld + j, j);
 }
 
+/* Reload number R reloads from or to a group of hard registers starting at
+   register REGNO.  Return true if it can be treated for inheritance purposes
+   like a group of reloads, each one reloading a single hard register.
+   The caller has already checked that the spill register and REGNO use
+   the same number of registers to store the reload value.  */
+
+static bool
+inherit_piecemeal_p (int r ATTRIBUTE_UNUSED, int regno ATTRIBUTE_UNUSED)
+{
+#ifdef CANNOT_CHANGE_MODE_CLASS
+  return (!REG_CANNOT_CHANGE_MODE_P (reload_spill_index[r],
+                                    GET_MODE (rld[r].reg_rtx),
+                                    reg_raw_mode[reload_spill_index[r]])
+         && !REG_CANNOT_CHANGE_MODE_P (regno,
+                                       GET_MODE (rld[r].reg_rtx),
+                                       reg_raw_mode[regno]));
+#else
+  return true;
+#endif
+}
+
 /* Output insns to reload values in and out of the chosen reload regs.  */
 
 static void
-emit_reload_insns (chain)
-     struct insn_chain *chain;
+emit_reload_insns (struct insn_chain *chain)
 {
   rtx insn = chain->insn;
 
@@ -7029,10 +7001,10 @@ emit_reload_insns (chain)
   other_operand_reload_insns = 0;
 
   /* Dump reloads into the dump file.  */
-  if (rtl_dump_file)
+  if (dump_file)
     {
-      fprintf (rtl_dump_file, "\nReloads for insn # %d\n", INSN_UID (insn));
-      debug_reload_to_stream (rtl_dump_file);
+      fprintf (dump_file, "\nReloads for insn # %d\n", INSN_UID (insn));
+      debug_reload_to_stream (dump_file);
     }
 
   /* Now output the instructions to copy the data into and out of the
@@ -7074,25 +7046,25 @@ emit_reload_insns (chain)
      reloads for the operand.  The RELOAD_OTHER output reloads are
      output in descending order by reload number.  */
 
-  emit_insn_before (other_input_address_reload_insns, insn);
-  emit_insn_before (other_input_reload_insns, insn);
+  emit_insn_before_sameloc (other_input_address_reload_insns, insn);
+  emit_insn_before_sameloc (other_input_reload_insns, insn);
 
   for (j = 0; j < reload_n_operands; j++)
     {
-      emit_insn_before (inpaddr_address_reload_insns[j], insn);
-      emit_insn_before (input_address_reload_insns[j], insn);
-      emit_insn_before (input_reload_insns[j], insn);
+      emit_insn_before_sameloc (inpaddr_address_reload_insns[j], insn);
+      emit_insn_before_sameloc (input_address_reload_insns[j], insn);
+      emit_insn_before_sameloc (input_reload_insns[j], insn);
     }
 
-  emit_insn_before (other_operand_reload_insns, insn);
-  emit_insn_before (operand_reload_insns, insn);
+  emit_insn_before_sameloc (other_operand_reload_insns, insn);
+  emit_insn_before_sameloc (operand_reload_insns, insn);
 
   for (j = 0; j < reload_n_operands; j++)
     {
-      rtx x = emit_insn_after (outaddr_address_reload_insns[j], insn);
-      x = emit_insn_after (output_address_reload_insns[j], x);
-      x = emit_insn_after (output_reload_insns[j], x);
-      emit_insn_after (other_output_reload_insns[j], x);
+      rtx x = emit_insn_after_sameloc (outaddr_address_reload_insns[j], insn);
+      x = emit_insn_after_sameloc (output_address_reload_insns[j], x);
+      x = emit_insn_after_sameloc (output_reload_insns[j], x);
+      emit_insn_after_sameloc (other_output_reload_insns[j], x);
     }
 
   /* For all the spill regs newly reloaded in this instruction,
@@ -7141,7 +7113,7 @@ emit_reload_insns (chain)
 
       if (i >= 0 && rld[r].reg_rtx != 0)
        {
-         int nr = HARD_REGNO_NREGS (i, GET_MODE (rld[r].reg_rtx));
+         int nr = hard_regno_nregs[i][GET_MODE (rld[r].reg_rtx)];
          int k;
          int part_reaches_end = 0;
          int all_reaches_end = 1;
@@ -7165,7 +7137,10 @@ emit_reload_insns (chain)
                 If consecutive registers are used, clear them all.  */
 
              for (k = 0; k < nr; k++)
+               {
                CLEAR_HARD_REG_BIT (reg_reloaded_valid, i + k);
+                 CLEAR_HARD_REG_BIT (reg_reloaded_call_part_clobbered, i + k);
+               }
 
              /* Maybe the spill reg contains a copy of reload_out.  */
              if (rld[r].out != 0
@@ -7182,13 +7157,18 @@ emit_reload_insns (chain)
 /* AUTO_INC */              : XEXP (rld[r].in_reg, 0));
                  int nregno = REGNO (out);
                  int nnr = (nregno >= FIRST_PSEUDO_REGISTER ? 1
-                            : HARD_REGNO_NREGS (nregno,
-                                                GET_MODE (rld[r].reg_rtx)));
+                            : hard_regno_nregs[nregno]
+                                              [GET_MODE (rld[r].reg_rtx)]);
+                 bool piecemeal;
 
                  spill_reg_store[i] = new_spill_reg_store[i];
                  spill_reg_stored_to[i] = out;
                  reg_last_reload_reg[nregno] = rld[r].reg_rtx;
 
+                 piecemeal = (nregno < FIRST_PSEUDO_REGISTER
+                              && nr == nnr
+                              && inherit_piecemeal_p (r, nregno));
+
                  /* If NREGNO is a hard register, it may occupy more than
                     one register.  If it does, say what is in the
                     rest of the registers assuming that both registers
@@ -7198,7 +7178,7 @@ emit_reload_insns (chain)
                  if (nregno < FIRST_PSEUDO_REGISTER)
                    for (k = 1; k < nnr; k++)
                      reg_last_reload_reg[nregno + k]
-                       = (nr == nnr
+                       = (piecemeal
                           ? regno_reg_rtx[REGNO (rld[r].reg_rtx) + k]
                           : 0);
 
@@ -7207,11 +7187,13 @@ emit_reload_insns (chain)
                    {
                      CLEAR_HARD_REG_BIT (reg_reloaded_dead, i + k);
                      reg_reloaded_contents[i + k]
-                       = (nregno >= FIRST_PSEUDO_REGISTER || nr != nnr
+                       = (nregno >= FIRST_PSEUDO_REGISTER || !piecemeal
                           ? nregno
                           : nregno + k);
                      reg_reloaded_insn[i + k] = insn;
                      SET_HARD_REG_BIT (reg_reloaded_valid, i + k);
+                     if (HARD_REGNO_CALL_PART_CLOBBERED (i + k, GET_MODE (out)))
+                       SET_HARD_REG_BIT (reg_reloaded_call_part_clobbered, i + k);
                    }
                }
 
@@ -7229,25 +7211,32 @@ emit_reload_insns (chain)
                {
                  int nregno;
                  int nnr;
+                 rtx in;
+                 bool piecemeal;
 
                  if (GET_CODE (rld[r].in) == REG
                      && REGNO (rld[r].in) >= FIRST_PSEUDO_REGISTER)
-                   nregno = REGNO (rld[r].in);
+                   in = rld[r].in;
                  else if (GET_CODE (rld[r].in_reg) == REG)
-                   nregno = REGNO (rld[r].in_reg);
+                   in = rld[r].in_reg;
                  else
-                   nregno = REGNO (XEXP (rld[r].in_reg, 0));
+                   in = XEXP (rld[r].in_reg, 0);
+                 nregno = REGNO (in);
 
                  nnr = (nregno >= FIRST_PSEUDO_REGISTER ? 1
-                        : HARD_REGNO_NREGS (nregno,
-                                            GET_MODE (rld[r].reg_rtx)));
+                        : hard_regno_nregs[nregno]
+                                          [GET_MODE (rld[r].reg_rtx)]);
 
                  reg_last_reload_reg[nregno] = rld[r].reg_rtx;
 
+                 piecemeal = (nregno < FIRST_PSEUDO_REGISTER
+                              && nr == nnr
+                              && inherit_piecemeal_p (r, nregno));
+
                  if (nregno < FIRST_PSEUDO_REGISTER)
                    for (k = 1; k < nnr; k++)
                      reg_last_reload_reg[nregno + k]
-                       = (nr == nnr
+                       = (piecemeal
                           ? regno_reg_rtx[REGNO (rld[r].reg_rtx) + k]
                           : 0);
 
@@ -7263,11 +7252,13 @@ emit_reload_insns (chain)
                    {
                      CLEAR_HARD_REG_BIT (reg_reloaded_dead, i + k);
                      reg_reloaded_contents[i + k]
-                       = (nregno >= FIRST_PSEUDO_REGISTER || nr != nnr
+                       = (nregno >= FIRST_PSEUDO_REGISTER || !piecemeal
                           ? nregno
                           : nregno + k);
                      reg_reloaded_insn[i + k] = insn;
                      SET_HARD_REG_BIT (reg_reloaded_valid, i + k);
+                     if (HARD_REGNO_CALL_PART_CLOBBERED (i + k, GET_MODE (in)))
+                       SET_HARD_REG_BIT (reg_reloaded_call_part_clobbered, i + k);
                    }
                }
            }
@@ -7338,7 +7329,7 @@ emit_reload_insns (chain)
                  && REGNO (src_reg) < FIRST_PSEUDO_REGISTER)
                {
                  int src_regno = REGNO (src_reg);
-                 int nr = HARD_REGNO_NREGS (src_regno, rld[r].mode);
+                 int nr = hard_regno_nregs[src_regno][rld[r].mode];
                  /* The place where to find a death note varies with
                     PRESERVE_DEATH_INFO_REGNO_P .  The condition is not
                     necessarily checked exactly in the code that moves
@@ -7354,6 +7345,10 @@ emit_reload_insns (chain)
                      reg_reloaded_insn[src_regno + nr] = store_insn;
                      CLEAR_HARD_REG_BIT (reg_reloaded_dead, src_regno + nr);
                      SET_HARD_REG_BIT (reg_reloaded_valid, src_regno + nr);
+                     if (HARD_REGNO_CALL_PART_CLOBBERED (src_regno + nr, 
+                                                         GET_MODE (src_reg)))
+                       SET_HARD_REG_BIT (reg_reloaded_call_part_clobbered, 
+                                         src_regno + nr);
                      SET_HARD_REG_BIT (reg_is_output_reload, src_regno + nr);
                      if (note)
                        SET_HARD_REG_BIT (reg_reloaded_died, src_regno);
@@ -7361,11 +7356,15 @@ emit_reload_insns (chain)
                        CLEAR_HARD_REG_BIT (reg_reloaded_died, src_regno);
                    }
                  reg_last_reload_reg[nregno] = src_reg;
+                 /* We have to set reg_has_output_reload here, or else 
+                    forget_old_reloads_1 will clear reg_last_reload_reg
+                    right away.  */
+                 reg_has_output_reload[nregno] = 1;
                }
            }
          else
            {
-             int num_regs = HARD_REGNO_NREGS (nregno, GET_MODE (rld[r].out));
+             int num_regs = hard_regno_nregs[nregno][GET_MODE (rld[r].out)];
 
              while (num_regs-- > 0)
                reg_last_reload_reg[nregno + num_regs] = 0;
@@ -7382,11 +7381,7 @@ emit_reload_insns (chain)
    Returns first insn emitted.  */
 
 rtx
-gen_reload (out, in, opnum, type)
-     rtx out;
-     rtx in;
-     int opnum;
-     enum reload_type type;
+gen_reload (rtx out, rtx in, int opnum, enum reload_type type)
 {
   rtx last = get_last_insn ();
   rtx tem;
@@ -7575,7 +7570,7 @@ gen_reload (out, in, opnum, type)
 #endif
 
   /* If IN is a simple operand, use gen_move_insn.  */
-  else if (GET_RTX_CLASS (GET_CODE (in)) == 'o' || GET_CODE (in) == SUBREG)
+  else if (OBJECT_P (in) || GET_CODE (in) == SUBREG)
     emit_insn (gen_move_insn (out, in));
 
 #ifdef HAVE_reload_load_address
@@ -7606,10 +7601,7 @@ gen_reload (out, in, opnum, type)
    certain that reload J doesn't use REG any longer for input.  */
 
 static void
-delete_output_reload (insn, j, last_reload_reg)
-     rtx insn;
-     int j;
-     int last_reload_reg;
+delete_output_reload (rtx insn, int j, int last_reload_reg)
 {
   rtx output_reload_insn = spill_reg_store[last_reload_reg];
   rtx reg = spill_reg_stored_to[last_reload_reg];
@@ -7697,7 +7689,7 @@ delete_output_reload (insn, j, last_reload_reg)
     }
 
   /* We will be deleting the insn.  Remove the spill reg information.  */
-  for (k = HARD_REGNO_NREGS (last_reload_reg, GET_MODE (reg)); k-- > 0; )
+  for (k = hard_regno_nregs[last_reload_reg][GET_MODE (reg)]; k-- > 0; )
     {
       spill_reg_store[last_reload_reg + k] = 0;
       spill_reg_stored_to[last_reload_reg + k] = 0;
@@ -7776,8 +7768,7 @@ delete_output_reload (insn, j, last_reload_reg)
    reload registers used in DEAD_INSN that are not used till CURRENT_INSN.
    CURRENT_INSN is being reloaded, so we have to check its reloads too.  */
 static void
-delete_address_reloads (dead_insn, current_insn)
-     rtx dead_insn, current_insn;
+delete_address_reloads (rtx dead_insn, rtx current_insn)
 {
   rtx set = single_set (dead_insn);
   rtx set2, dst, prev, next;
@@ -7813,8 +7804,7 @@ delete_address_reloads (dead_insn, current_insn)
 
 /* Subfunction of delete_address_reloads: process registers found in X.  */
 static void
-delete_address_reloads_1 (dead_insn, x, current_insn)
-     rtx dead_insn, x, current_insn;
+delete_address_reloads_1 (rtx dead_insn, rtx x, rtx current_insn)
 {
   rtx prev, set, dst, i2;
   int i, j;
@@ -7847,7 +7837,7 @@ delete_address_reloads_1 (dead_insn, x, current_insn)
       code = GET_CODE (prev);
       if (code == CODE_LABEL || code == JUMP_INSN)
        return;
-      if (GET_RTX_CLASS (code) != 'i')
+      if (!INSN_P (prev))
        continue;
       if (reg_set_p (x, PATTERN (prev)))
        break;
@@ -7932,10 +7922,7 @@ delete_address_reloads_1 (dead_insn, x, current_insn)
    Return the instruction that stores into RELOADREG.  */
 
 static rtx
-inc_for_reload (reloadreg, in, value, inc_amount)
-     rtx reloadreg;
-     rtx in, value;
-     int inc_amount;
+inc_for_reload (rtx reloadreg, rtx in, rtx value, int inc_amount)
 {
   /* REG or MEM to be copied and incremented.  */
   rtx incloc = XEXP (value, 0);
@@ -8026,9 +8013,7 @@ inc_for_reload (reloadreg, in, value, inc_amount)
 \f
 #ifdef AUTO_INC_DEC
 static void
-add_auto_inc_notes (insn, x)
-     rtx insn;
-     rtx x;
+add_auto_inc_notes (rtx insn, rtx x)
 {
   enum rtx_code code = GET_CODE (x);
   const char *fmt;
@@ -8056,9 +8041,7 @@ add_auto_inc_notes (insn, x)
 
 /* Copy EH notes from an insn to its reloads.  */
 static void
-copy_eh_notes (insn, x)
-     rtx insn;
-     rtx x;
+copy_eh_notes (rtx insn, rtx x)
 {
   rtx eh_note = find_reg_note (insn, REG_EH_REGION, NULL_RTX);
   if (eh_note)
@@ -8080,7 +8063,7 @@ copy_eh_notes (insn, x)
 
    Similar handle instructions throwing exceptions internally.  */
 void
-fixup_abnormal_edges ()
+fixup_abnormal_edges (void)
 {
   bool inserted = false;
   basic_block bb;
@@ -8099,9 +8082,10 @@ fixup_abnormal_edges ()
              == (EDGE_ABNORMAL | EDGE_EH))
            break;
        }
-      if (e && GET_CODE (bb->end) != CALL_INSN && !can_throw_internal (bb->end))
+      if (e && GET_CODE (BB_END (bb)) != CALL_INSN
+         && !can_throw_internal (BB_END (bb)))
        {
-         rtx insn = bb->end, stop = NEXT_INSN (bb->end);
+         rtx insn = BB_END (bb), stop = NEXT_INSN (BB_END (bb));
          rtx next;
          for (e = bb->succ; e; e = e->succ_next)
            if (e->flags & EDGE_FALLTHRU)
@@ -8110,11 +8094,11 @@ fixup_abnormal_edges ()
             be already deleted.  */
          while ((GET_CODE (insn) == INSN || GET_CODE (insn) == NOTE)
                 && !can_throw_internal (insn)
-                && insn != bb->head)
+                && insn != BB_HEAD (bb))
            insn = PREV_INSN (insn);
          if (GET_CODE (insn) != CALL_INSN && !can_throw_internal (insn))
            abort ();
-         bb->end = insn;
+         BB_END (bb) = insn;
          inserted = true;
          insn = NEXT_INSN (insn);
          while (insn && insn != stop)