OSDN Git Service

PR c/13133
[pf3gnuchains/gcc-fork.git] / gcc / reload1.c
index c188aec..22c0342 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 Free Software Foundation, Inc.
+   1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -21,6 +21,8 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 
 #include "config.h"
 #include "system.h"
+#include "coretypes.h"
+#include "tm.h"
 
 #include "machmode.h"
 #include "hard-reg-set.h"
@@ -37,7 +39,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "reload.h"
 #include "recog.h"
 #include "output.h"
-#include "cselib.h"
 #include "real.h"
 #include "toplev.h"
 #include "except.h"
@@ -77,10 +78,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
    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
@@ -139,7 +136,7 @@ static int reg_reloaded_contents[FIRST_PSEUDO_REGISTER];
    when reg_reloaded_valid is set for this register.  */
 static rtx reg_reloaded_insn[FIRST_PSEUDO_REGISTER];
 
-/* Indicate if reg_reloaded_insn / reg_reloaded_contents is valid */
+/* Indicate if reg_reloaded_insn / reg_reloaded_contents is valid */
 static HARD_REG_SET reg_reloaded_valid;
 /* Indicate if the register was dead at the end of the reload.
    This is only valid if reg_reloaded_contents is set and valid.  */
@@ -284,12 +281,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
@@ -302,12 +293,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.  */
-  int can_eliminate;           /* Non-zero if this elimination can be done.  */
+  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
@@ -340,7 +331,7 @@ static const struct elim_table_1
 #define NUM_ELIMINABLE_REGS ARRAY_SIZE (reg_eliminate_1)
 
 /* Record the number of pending eliminations that have an offset not equal
-   to their initial offset.  If non-zero, we use a new copy of each
+   to their initial offset.  If nonzero, we use a new copy of each
    replacement result in any insns encountered.  */
 int num_not_at_initial_offset;
 
@@ -352,116 +343,92 @@ static int num_eliminable_invariants;
 
 /* For each label, we record the offset of each elimination.  If we reach
    a label by more than one path and an offset differs, we cannot do the
-   elimination.  This information is indexed by the number of the label.
-   The first table is an array of flags that records whether we have yet
-   encountered a label and the second table is an array of arrays, one
-   entry in the latter array for each elimination.  */
-
+   elimination.  This information is indexed by the difference of the
+   number of the label and the first label number.  We can't offset the
+   pointer itself as this can cause problems on machines with segmented
+   memory.  The first table is an array of flags that records whether we
+   have yet encountered a label and the second table is an array of arrays,
+   one entry in the latter array for each elimination.  */
+
+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_call_usage      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 PTR, const PTR));
-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 reload_cse_regs_1          PARAMS ((rtx));
-static int reload_cse_noop_set_p       PARAMS ((rtx));
-static int reload_cse_simplify_set     PARAMS ((rtx, rtx));
-static int reload_cse_simplify_operands        PARAMS ((rtx, rtx));
-static void reload_combine             PARAMS ((void));
-static void reload_combine_note_use    PARAMS ((rtx *, rtx));
-static void reload_combine_note_store  PARAMS ((rtx, rtx, void *));
-static void reload_cse_move2add                PARAMS ((rtx));
-static void move2add_note_store                PARAMS ((rtx, rtx, void *));
+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 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 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));
-static HOST_WIDE_INT sext_for_mode     PARAMS ((enum machine_mode,
-                                                HOST_WIDE_INT));
-static void failed_reload              PARAMS ((rtx, int));
-static int set_reload_reg              PARAMS ((int, int));
-static void reload_cse_simplify                PARAMS ((rtx, rtx));
-void fixup_abnormal_edges              PARAMS ((void));
-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;
 
@@ -508,7 +475,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);
@@ -519,14 +486,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);
     }
@@ -546,9 +512,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;
 
@@ -580,10 +544,7 @@ compute_use_by_pseudos (to, from)
    equivalences.  */
 
 static void
-replace_pseudos_in_call_usage (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;
@@ -605,7 +566,7 @@ replace_pseudos_in_call_usage (loc, mem_mode, usage)
       if (x != *loc)
        {
          *loc = x;
-         replace_pseudos_in_call_usage (loc, mem_mode, usage);
+         replace_pseudos_in (loc, mem_mode, usage);
          return;
        }
 
@@ -625,7 +586,7 @@ replace_pseudos_in_call_usage (loc, mem_mode, usage)
     }
   else if (code == MEM)
     {
-      replace_pseudos_in_call_usage (& XEXP (x, 0), GET_MODE (x), usage);
+      replace_pseudos_in (& XEXP (x, 0), GET_MODE (x), usage);
       return;
     }
 
@@ -633,10 +594,10 @@ replace_pseudos_in_call_usage (loc, mem_mode, usage)
   fmt = GET_RTX_FORMAT (code);
   for (i = 0; i < GET_RTX_LENGTH (code); i++, fmt++)
     if (*fmt == 'e')
-      replace_pseudos_in_call_usage (&XEXP (x, i), mem_mode, usage);
+      replace_pseudos_in (&XEXP (x, i), mem_mode, usage);
     else if (*fmt == 'E')
       for (j = 0; j < XVECLEN (x, i); j++)
-       replace_pseudos_in_call_usage (& XVECEXP (x, i, j), mem_mode, usage);
+       replace_pseudos_in (& XVECEXP (x, i, j), mem_mode, usage);
 }
 
 \f
@@ -664,30 +625,23 @@ 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;
   struct elim_table *ep;
   basic_block bb;
 
-  /* The two pointers used to track the true location of the memory used
-     for label offsets.  */
-  char *real_known_ptr = NULL;
-  int (*real_at_ptr)[NUM_ELIMINABLE_REGS];
-
   /* Make sure even insns with volatile mem refs are recognizable.  */
   init_recog ();
 
   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.  */
-  emit_note (NULL, NOTE_INSN_DELETED);
+  emit_note (NOTE_INSN_DELETED);
 
   /* Enable find_equiv_reg to distinguish insns made by reload.  */
   reload_first_uid = get_max_uid ();
@@ -698,8 +652,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.  */
@@ -729,26 +683,22 @@ 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.  */
+     are used for user variables.  These can never be used for spills.  */
 
   num_eliminable_invariants = 0;
   for (insn = first; insn; insn = NEXT_INSN (insn))
@@ -762,12 +712,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);
@@ -817,8 +761,12 @@ reload (first, global)
                      else if (LEGITIMATE_CONSTANT_P (x))
                        reg_equiv_constant[i] = x;
                      else
-                       reg_equiv_memory_loc[i]
-                         = force_const_mem (GET_MODE (SET_DEST (set)), x);
+                       {
+                         reg_equiv_memory_loc[i]
+                           = force_const_mem (GET_MODE (SET_DEST (set)), x);
+                         if (!reg_equiv_memory_loc[i])
+                           continue;
+                       }
                    }
                  else
                    continue;
@@ -852,20 +800,15 @@ reload (first, global)
 
   init_elim_table ();
 
-  num_labels = max_label_num () - get_first_label_num ();
+  first_label_num = get_first_label_num ();
+  num_labels = max_label_num () - first_label_num;
 
   /* Allocate the tables used to store offset information at labels.  */
   /* We used to use alloca here, but the size of what it would try to
      allocate would occasionally cause it to exceed the stack limit and
      cause a core dump.  */
-  real_known_ptr = xmalloc (num_labels);
-  real_at_ptr
-    = (int (*)[NUM_ELIMINABLE_REGS])
-    xmalloc (num_labels * NUM_ELIMINABLE_REGS * sizeof (int));
-
-  offsets_known_at = real_known_ptr - get_first_label_num ();
-  offsets_at
-    = (int (*)[NUM_ELIMINABLE_REGS]) (real_at_ptr - get_first_label_num ());
+  offsets_known_at = xmalloc (num_labels);
+  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.
@@ -997,7 +940,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);
@@ -1023,7 +966,7 @@ reload (first, global)
              did_spill = 1;
 
              /* Regardless of the state of spills, if we previously had
-                a register that we thought we could eliminate, but no can
+                a register that we thought we could eliminate, but now can
                 not eliminate, we must run another pass.
 
                 Consider pseudos which have an entry in reg_equiv_* which
@@ -1193,9 +1136,8 @@ reload (first, global)
        rtx *pnote;
 
        if (GET_CODE (insn) == CALL_INSN)
-         replace_pseudos_in_call_usage (& CALL_INSN_FUNCTION_USAGE (insn),
-                                        VOIDmode,
-                                        CALL_INSN_FUNCTION_USAGE (insn));
+         replace_pseudos_in (& CALL_INSN_FUNCTION_USAGE (insn),
+                             VOIDmode, CALL_INSN_FUNCTION_USAGE (insn));
 
        if ((GET_CODE (PATTERN (insn)) == USE
             /* We mark with QImode USEs introduced by reload itself.  */
@@ -1205,7 +1147,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)))))
@@ -1214,6 +1156,13 @@ reload (first, global)
            continue;
          }
 
+       /* Some CLOBBERs may survive until here and still reference unassigned
+          pseudos with const equivalent, which may in turn cause ICE in later
+          passes if the reference remains in place.  */
+       if (GET_CODE (PATTERN (insn)) == CLOBBER)
+         replace_pseudos_in (& XEXP (PATTERN (insn), 0),
+                             VOIDmode, PATTERN (insn));
+
        pnote = &REG_NOTES (insn);
        while (*pnote != 0)
          {
@@ -1265,10 +1214,10 @@ reload (first, global)
     free (reg_equiv_memory_loc);
   reg_equiv_memory_loc = 0;
 
-  if (real_known_ptr)
-    free (real_known_ptr);
-  if (real_at_ptr)
-    free (real_at_ptr);
+  if (offsets_known_at)
+    free (offsets_known_at);
+  if (offsets_at)
+    free (offsets_at);
 
   free (reg_equiv_mem);
   free (reg_equiv_init);
@@ -1303,7 +1252,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];
@@ -1349,7 +1298,7 @@ maybe_fix_stack_asms ()
 
          for (;;)
            {
-             char c = *p++;
+             char c = *p;
 
              if (c == '\0' || c == ',' || c == '#')
                {
@@ -1357,6 +1306,7 @@ maybe_fix_stack_asms ()
                     class, and reset the class.  */
                  IOR_HARD_REG_SET (allowed, reg_class_contents[cls]);
                  cls = NO_REGS;
+                 p++;
                  if (c == '#')
                    do {
                      c = *p++;
@@ -1387,13 +1337,14 @@ maybe_fix_stack_asms ()
                  break;
 
                default:
-                 if (EXTRA_ADDRESS_CONSTRAINT (c))
+                 if (EXTRA_ADDRESS_CONSTRAINT (c, p))
                    cls = (int) reg_class_subunion[cls]
                      [(int) MODE_BASE_REG_CLASS (VOIDmode)];
                  else
                    cls = (int) reg_class_subunion[cls]
-                     [(int) REG_CLASS_FROM_LETTER (c)];
+                     [(int) REG_CLASS_FROM_CONSTRAINT (c, p)];
                }
+             p += CONSTRAINT_LEN (c, p);
            }
        }
       /* Those of the registers which are clobbered, but allowed by the
@@ -1414,30 +1365,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;
@@ -1497,7 +1445,7 @@ calculate_needs_all_insns (global)
                  && REGNO (SET_SRC (set)) >= FIRST_PSEUDO_REGISTER)
                {
                  delete_insn (insn);
-                 /* Delete it from the reload chain */
+                 /* Delete it from the reload chain */
                  if (chain->prev)
                    chain->prev->next = next;
                  else
@@ -1545,9 +1493,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 PTR r1p;
-     const PTR r2p;
+reload_reg_class_lower (const void *r1p, const void *r2p)
 {
   int r1 = *(const short *) r1p, r2 = *(const short *) r2p;
   int t;
@@ -1589,8 +1535,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];
@@ -1616,8 +1561,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;
@@ -1667,8 +1611,7 @@ 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));
@@ -1687,9 +1630,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;
@@ -1795,8 +1736,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;
 
@@ -1856,7 +1796,7 @@ find_reload_regs (chain)
 }
 
 static void
-select_reload_regs ()
+select_reload_regs (void)
 {
   struct insn_chain *chain;
 
@@ -1869,7 +1809,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;
 
@@ -1901,9 +1841,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)
@@ -1921,8 +1859,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;
@@ -1950,9 +1887,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.  */
@@ -2073,9 +2008,10 @@ alter_reg (i, from_reg)
 
       /* If we have a decl for the original register, set it for the
         memory.  If this is a shared MEM, make a copy.  */
-      if (REGNO_DECL (i))
+      if (REG_EXPR (regno_reg_rtx[i])
+         && TREE_CODE_CLASS (TREE_CODE (REG_EXPR (regno_reg_rtx[i]))) == 'd')
        {
-         rtx decl = DECL_RTL_IF_SET (REGNO_DECL (i));
+         rtx decl = DECL_RTL_IF_SET (REG_EXPR (regno_reg_rtx[i]));
 
          /* We can do this only for the DECLs home pseudo, not for
             any copies of it, since otherwise when the stack slot
@@ -2086,7 +2022,7 @@ alter_reg (i, from_reg)
              if (from_reg != -1 && spill_stack_slot[from_reg] == x)
                x = copy_rtx (x);
 
-             set_mem_expr (x, REGNO_DECL (i));
+             set_mem_attrs_from_reg (x, regno_reg_rtx[i]);
            }
        }
 
@@ -2099,8 +2035,7 @@ 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;
 
@@ -2118,15 +2053,12 @@ mark_home_live (regno)
 
    INSN is the insn that it came from, if any.
 
-   INITIAL_P is non-zero if we are to set the offset to be the initial
+   INITIAL_P is nonzero if we are to set the offset to be the initial
    offset and zero if we are setting the offset of the label to be the
    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;
@@ -2151,13 +2083,13 @@ set_label_offsets (x, insn, initial_p)
         we guessed wrong, we will suppress an elimination that might have
         been possible had we been able to guess correctly.  */
 
-      if (! offsets_known_at[CODE_LABEL_NUMBER (x)])
+      if (! offsets_known_at[CODE_LABEL_NUMBER (x) - first_label_num])
        {
          for (i = 0; i < NUM_ELIMINABLE_REGS; i++)
-           offsets_at[CODE_LABEL_NUMBER (x)][i]
+           offsets_at[CODE_LABEL_NUMBER (x) - first_label_num][i]
              = (initial_p ? reg_eliminate[i].initial_offset
                 : reg_eliminate[i].offset);
-         offsets_known_at[CODE_LABEL_NUMBER (x)] = 1;
+         offsets_known_at[CODE_LABEL_NUMBER (x) - first_label_num] = 1;
        }
 
       /* Otherwise, if this is the definition of a label and it is
@@ -2174,7 +2106,7 @@ set_label_offsets (x, insn, initial_p)
           where the offsets disagree.  */
 
        for (i = 0; i < NUM_ELIMINABLE_REGS; i++)
-         if (offsets_at[CODE_LABEL_NUMBER (x)][i]
+         if (offsets_at[CODE_LABEL_NUMBER (x) - first_label_num][i]
              != (initial_p ? reg_eliminate[i].initial_offset
                  : reg_eliminate[i].offset))
            reg_eliminate[i].can_eliminate = 0;
@@ -2273,7 +2205,7 @@ set_label_offsets (x, insn, initial_p)
    to record the fact that a register is referenced outside a MEM.
 
    If INSN is an insn, it is the insn containing X.  If we replace a REG
-   in a SET_DEST with an equivalent MEM and INSN is non-zero, write a
+   in a SET_DEST with an equivalent MEM and INSN is nonzero, write a
    CLOBBER of the pseudo after INSN so find_equiv_regs will know that
    the REG is being modified.
 
@@ -2289,10 +2221,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;
@@ -2536,6 +2465,10 @@ eliminate_regs (x, mem_mode, insn)
     case ABS:
     case SQRT:
     case FFS:
+    case CLZ:
+    case CTZ:
+    case POPCOUNT:
+    case PARITY:
       new = eliminate_regs (XEXP (x, 0), mem_mode, insn);
       if (new != XEXP (x, 0))
        return gen_rtx_fmt_e (code, GET_MODE (x), new);
@@ -2546,7 +2479,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))
@@ -2573,7 +2506,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
@@ -2629,9 +2562,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;
            }
@@ -2650,10 +2581,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;
                    }
@@ -2673,10 +2601,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;
@@ -2767,6 +2692,10 @@ elimination_effects (x, mem_mode)
     case ABS:
     case SQRT:
     case FFS:
+    case CLZ:
+    case CTZ:
+    case POPCOUNT:
+    case PARITY:
       elimination_effects (XEXP (x, 0), mem_mode);
       return;
 
@@ -2869,8 +2798,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;
@@ -2919,9 +2847,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);
@@ -2929,7 +2855,7 @@ eliminate_regs_in_insn (insn, replace)
   rtx old_set = single_set (insn);
   rtx new_body;
   int val = 0;
-  int i, any_changes;
+  int i;
   rtx substed_operand[MAX_RECOG_OPERANDS];
   rtx orig_operand[MAX_RECOG_OPERANDS];
   struct elim_table *ep;
@@ -2963,7 +2889,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)
                  {
@@ -3046,7 +2972,7 @@ eliminate_regs_in_insn (insn, replace)
       && REGNO (XEXP (SET_SRC (old_set), 0)) < FIRST_PSEUDO_REGISTER)
     {
       rtx reg = XEXP (SET_SRC (old_set), 0);
-      int offset = INTVAL (XEXP (SET_SRC (old_set), 1));
+      HOST_WIDE_INT offset = INTVAL (XEXP (SET_SRC (old_set), 1));
 
       for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
        if (ep->from_rtx == reg && ep->can_eliminate)
@@ -3104,7 +3030,6 @@ eliminate_regs_in_insn (insn, replace)
   /* Eliminate all eliminable registers occurring in operands that
      can be handled by reload.  */
   extract_insn (insn);
-  any_changes = 0;
   for (i = 0; i < recog_data.n_operands; i++)
     {
       orig_operand[i] = recog_data.operand[i];
@@ -3130,7 +3055,7 @@ eliminate_regs_in_insn (insn, replace)
          substed_operand[i] = eliminate_regs (recog_data.operand[i], 0,
                                               replace ? insn : NULL_RTX);
          if (substed_operand[i] != orig_operand[i])
-           val = any_changes = 1;
+           val = 1;
          /* Terminate the search in check_eliminable_occurrences at
             this point.  */
          *recog_data.operand_loc[i] = 0;
@@ -3229,7 +3154,7 @@ eliminate_regs_in_insn (insn, replace)
      insn.  The changes we make were determined by the earlier call to
      elimination_effects.
 
-     We also detect cases where register elimination cannot be done,
+     We also detect cases where register elimination cannot be done,
      namely, if a register would be both changed and referenced outside a MEM
      in the resulting insn since such an insn is often undefined and, even if
      not, we cannot know what meaning will be given to it.  Note that it is
@@ -3268,7 +3193,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;
 
@@ -3296,10 +3221,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;
 
@@ -3331,9 +3253,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;
@@ -3354,7 +3276,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;
 
@@ -3380,10 +3302,10 @@ 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 ((char *) &offsets_known_at[get_first_label_num ()], 0, num_labels);
+  memset (offsets_known_at, 0, num_labels);
 
   for (x = forced_labels; x; x = XEXP (x, 1))
     if (XEXP (x, 0))
@@ -3394,8 +3316,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);
@@ -3404,7 +3325,8 @@ set_offsets_for_label (insn)
   num_not_at_initial_offset = 0;
   for (i = 0, ep = reg_eliminate; i < NUM_ELIMINABLE_REGS; ep++, i++)
     {
-      ep->offset = ep->previous_offset = offsets_at[label_nr][i];
+      ep->offset = ep->previous_offset
+                = offsets_at[label_nr - first_label_num][i];
       if (ep->can_eliminate && ep->offset != ep->initial_offset)
        num_not_at_initial_offset++;
     }
@@ -3417,12 +3339,9 @@ 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)
 {
-#if HARD_FRAME_POINTER_REGNUM != FRAME_POINTER_REGNUM
   int previous_frame_pointer_needed = frame_pointer_needed;
-#endif
   struct elim_table *ep;
 
   for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
@@ -3487,18 +3406,16 @@ update_eliminables (pset)
        }
     }
 
-#if HARD_FRAME_POINTER_REGNUM != FRAME_POINTER_REGNUM
   /* If we didn't need a frame pointer last time, but we do now, spill
      the hard frame pointer.  */
   if (frame_pointer_needed && ! previous_frame_pointer_needed)
     SET_HARD_REG_BIT (*pset, HARD_FRAME_POINTER_REGNUM);
-#endif
 }
 
 /* Initialize the table of registers to eliminate.  */
 
 static void
-init_elim_table ()
+init_elim_table (void)
 {
   struct elim_table *ep;
 #ifdef ELIMINABLE_REGS
@@ -3506,8 +3423,7 @@ 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?  */
 
@@ -3565,9 +3481,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;
 
@@ -3594,8 +3508,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);
 }
@@ -3606,8 +3519,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;
@@ -3657,7 +3569,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.  */
@@ -3756,8 +3668,7 @@ finish_spills (global)
    forbidden from being used for spill registers.  */
 
 static void
-scan_paradoxical_subregs (x)
-     rtx x;
+scan_paradoxical_subregs (rtx x)
 {
   int i;
   const char *fmt;
@@ -3820,8 +3731,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)
@@ -3829,17 +3739,17 @@ 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);
 
   set_initial_elim_offsets ();
 
   for (chain = reload_insn_chain; chain; chain = chain->next)
     {
-      rtx prev;
+      rtx prev = 0;
       rtx insn = chain->insn;
       rtx old_next = NEXT_INSN (insn);
 
@@ -3934,6 +3844,7 @@ reload_as_needed (live_known)
              if (asm_noperands (PATTERN (insn)) >= 0)
                for (p = NEXT_INSN (prev); p != next; p = NEXT_INSN (p))
                  if (p != insn && INSN_P (p)
+                     && GET_CODE (PATTERN (p)) != USE
                      && (recog_memoized (p) < 0
                          || (extract_insn (p), ! constrain_operands (1))))
                    {
@@ -3981,7 +3892,7 @@ reload_as_needed (live_known)
                                            REGNO (rld[i].reg_rtx))
                      /* Make sure it is the inc/dec pseudo, and not
                         some other (e.g. output operand) pseudo.  */
-                     && (reg_reloaded_contents[REGNO (rld[i].reg_rtx)]
+                     && ((unsigned) reg_reloaded_contents[REGNO (rld[i].reg_rtx)]
                          == REGNO (XEXP (in_reg, 0))))
 
                    {
@@ -4048,7 +3959,7 @@ reload_as_needed (live_known)
                                                 REGNO (rld[i].reg_rtx))
                           /* Make sure it is the inc/dec pseudo, and not
                              some other (e.g. output operand) pseudo.  */
-                          && (reg_reloaded_contents[REGNO (rld[i].reg_rtx)]
+                          && ((unsigned) reg_reloaded_contents[REGNO (rld[i].reg_rtx)]
                               == REGNO (XEXP (in_reg, 0))))
                    {
                      SET_HARD_REG_BIT (reg_is_output_reload,
@@ -4098,10 +4009,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;
@@ -4197,11 +4106,8 @@ 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 i;
@@ -4262,11 +4168,8 @@ 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 start_regno, end_regno, r;
@@ -4374,10 +4277,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;
 
@@ -4540,10 +4440,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;
 
@@ -4673,8 +4570,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;
@@ -4752,7 +4648,7 @@ char reload_inherited[MAX_RELOADS];
    if we know it.  Otherwise, this is 0.  */
 rtx reload_inheritance_insn[MAX_RELOADS];
 
-/* If non-zero, this is a place to get the value of the reload,
+/* If nonzero, this is a place to get the value of the reload,
    rather than using reload_in.  */
 rtx reload_override_in[MAX_RELOADS];
 
@@ -4765,14 +4661,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
@@ -4993,7 +4884,7 @@ reload_reg_free_for_value_p (start_regno, regno, opnum, type, value, out,
    determine how many hard regs to test.
 
    Other read-only reloads with the same value do not conflict
-   unless OUT is non-zero and these other reloads have to live while
+   unless OUT is nonzero and these other reloads have to live while
    output reloads live.
    If OUT is CONST0_RTX, this is a special case: it means that the
    test should not be for using register REGNO as reload register, but
@@ -5009,15 +4900,9 @@ 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);
   while (nregs-- > 0)
@@ -5032,8 +4917,7 @@ free_for_value_p (regno, mode, opnum, type, value, out, reloadnum,
    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++)
@@ -5046,9 +4930,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.  */
@@ -5069,8 +4951,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];
@@ -5116,7 +4997,7 @@ set_reload_reg (i, r)
 }
 
 /* Find a spill register to use as a reload register for reload R.
-   LAST_RELOAD is non-zero if this is the last reload for the insn being
+   LAST_RELOAD is nonzero if this is the last reload for the insn being
    processed.
 
    Set rld[R].reg_rtx to the register allocated.
@@ -5125,10 +5006,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;
 
@@ -5249,9 +5128,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;
 
@@ -5259,8 +5136,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);
@@ -5310,8 +5187,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;
@@ -5494,16 +5370,15 @@ choose_reload_regs (chain)
                                                GET_MODE_CLASS (mode));
 
                  if (
-#ifdef CLASS_CANNOT_CHANGE_MODE
-                     (TEST_HARD_REG_BIT
-                      (reg_class_contents[(int) CLASS_CANNOT_CHANGE_MODE], i)
-                      ? ! CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (last_reg),
-                                                      need_mode)
-                      : (GET_MODE_SIZE (GET_MODE (last_reg))
-                         >= GET_MODE_SIZE (need_mode)))
-#else
+#ifdef CANNOT_CHANGE_MODE_CLASS
+                     (!REG_CANNOT_CHANGE_MODE_P (i, GET_MODE (last_reg),
+                                                 need_mode)
+                      &&
+#endif
                      (GET_MODE_SIZE (GET_MODE (last_reg))
                       >= GET_MODE_SIZE (need_mode))
+#ifdef CANNOT_CHANGE_MODE_CLASS
+                     )
 #endif
                      && reg_reloaded_contents[i] == regno
                      && TEST_HARD_REG_BIT (reg_reloaded_valid, i)
@@ -5675,14 +5550,27 @@ choose_reload_regs (chain)
 
              /* If we found a spill reg, reject it unless it is free
                 and of the desired class.  */
-             if (equiv != 0
-                 && ((TEST_HARD_REG_BIT (reload_reg_used_at_all, regno)
+             if (equiv != 0)
+               {
+                 int regs_used = 0;
+                 int bad_for_class = 0;
+                 int max_regno = regno + rld[r].nregs;
+
+                 for (i = regno; i < max_regno; i++)
+                   {
+                     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],
+                                                          i);
+                   }
+
+                 if ((regs_used
                       && ! free_for_value_p (regno, rld[r].mode,
                                              rld[r].opnum, rld[r].when_needed,
                                              rld[r].in, rld[r].out, r, 1))
-                     || ! TEST_HARD_REG_BIT (reg_class_contents[(int) rld[r].class],
-                                             regno)))
-               equiv = 0;
+                     || bad_for_class)
+                   equiv = 0;
+               }
 
              if (equiv != 0 && ! HARD_REGNO_MODE_OK (regno, rld[r].mode))
                equiv = 0;
@@ -5935,7 +5823,7 @@ choose_reload_regs (chain)
     if (reload_override_in[j])
       rld[j].in = reload_override_in[j];
 
-  /* If this reload won't be done because it has been cancelled or is
+  /* If this reload won't be done because it has been canceled or is
      optional and not inherited, clear reload_reg_rtx so other
      routines (such as subst_reloads) don't get confused.  */
   for (j = 0; j < n_reloads; j++)
@@ -5994,8 +5882,7 @@ choose_reload_regs (chain)
    remove_address_replacements.  */
 
 void
-deallocate_reload_reg (r)
-     int r;
+deallocate_reload_reg (int r)
 {
   int regno;
 
@@ -6009,7 +5896,7 @@ deallocate_reload_reg (r)
   reload_spill_index[r] = -1;
 }
 \f
-/* If SMALL_REGISTER_CLASSES is non-zero, we may not have merged two
+/* If SMALL_REGISTER_CLASSES is nonzero, we may not have merged two
    reloads of the same item for fear that we might not have enough reload
    registers. However, normally they will get the same reload register
    and hence actually need not be loaded twice.
@@ -6023,8 +5910,7 @@ deallocate_reload_reg (r)
    prevent redundant code.  */
 
 static void
-merge_assigned_reloads (insn)
-     rtx insn;
+merge_assigned_reloads (rtx insn)
 {
   int i, j;
 
@@ -6119,10 +6005,26 @@ merge_assigned_reloads (insn)
                      || rld[j].when_needed == RELOAD_FOR_INPADDR_ADDRESS)
                  && reg_overlap_mentioned_for_reload_p (rld[j].in,
                                                         rld[i].in))
-               rld[j].when_needed
-                 = ((rld[j].when_needed == RELOAD_FOR_INPUT_ADDRESS
-                     || rld[j].when_needed == RELOAD_FOR_INPADDR_ADDRESS)
-                    ? RELOAD_FOR_OTHER_ADDRESS : RELOAD_OTHER);
+               {
+                 int k;
+
+                 rld[j].when_needed
+                   = ((rld[j].when_needed == RELOAD_FOR_INPUT_ADDRESS
+                       || rld[j].when_needed == RELOAD_FOR_INPADDR_ADDRESS)
+                      ? RELOAD_FOR_OTHER_ADDRESS : RELOAD_OTHER);
+
+                 /* Check to see if we accidentally converted two reloads
+                    that use the same reload register with different inputs
+                    to the same type.  If so, the resulting code won't work,
+                    so abort.  */
+                 if (rld[j].reg_rtx)
+                   for (k = 0; k < j; k++)
+                     if (rld[k].in != 0 && rld[k].reg_rtx != 0
+                         && rld[k].when_needed == rld[j].when_needed
+                         && rtx_equal_p (rld[k].reg_rtx, rld[j].reg_rtx)
+                         && ! rtx_equal_p (rld[k].in, rld[j].in))
+                       abort ();
+               }
        }
     }
 }
@@ -6148,11 +6050,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;
@@ -6244,7 +6143,7 @@ emit_input_reload_insns (chain, rl, old, j)
         or memory.  */
 
       if (oldequiv != 0
-         && ((REGNO_REG_CLASS (regno) != rl->class
+         && (((enum reg_class) REGNO_REG_CLASS (regno) != rl->class
               && (REGISTER_MOVE_COST (mode, REGNO_REG_CLASS (regno),
                                       rl->class)
                   >= MEMORY_MOVE_COST (mode, rl->class, 1)))
@@ -6300,7 +6199,7 @@ emit_input_reload_insns (chain, rl, old, j)
      must always be a REG here.  */
 
   if (GET_MODE (reloadreg) != mode)
-    reloadreg = gen_rtx_REG (mode, REGNO (reloadreg));
+    reloadreg = reload_adjust_reg_for_mode (reloadreg, mode);
   while (GET_CODE (oldequiv) == SUBREG && GET_MODE (oldequiv) != mode)
     oldequiv = SUBREG_REG (oldequiv);
   if (GET_MODE (oldequiv) != VOIDmode
@@ -6549,8 +6448,8 @@ emit_input_reload_insns (chain, rl, old, j)
                        oldequiv = old, real_oldequiv = real_old;
                      else
                        second_reload_reg
-                         = gen_rtx_REG (new_mode,
-                                        REGNO (second_reload_reg));
+                         = reload_adjust_reg_for_mode (second_reload_reg,
+                                                       new_mode);
                    }
                }
            }
@@ -6639,10 +6538,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;
@@ -6672,7 +6569,7 @@ emit_output_reload_insns (chain, rl, j)
     }
 
   if (GET_MODE (reloadreg) != mode)
-    reloadreg = gen_rtx_REG (mode, REGNO (reloadreg));
+    reloadreg = reload_adjust_reg_for_mode (reloadreg, mode);
 
 #ifdef SECONDARY_OUTPUT_RELOAD_CLASS
 
@@ -6713,7 +6610,7 @@ emit_output_reload_insns (chain, rl, j)
                = rld[secondary_reload].secondary_out_icode;
 
              if (GET_MODE (reloadreg) != mode)
-               reloadreg = gen_rtx_REG (mode, REGNO (reloadreg));
+               reloadreg = reload_adjust_reg_for_mode (reloadreg, mode);
 
              if (tertiary_icode != CODE_FOR_nothing)
                {
@@ -6853,12 +6750,8 @@ 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)
 {
-  int expect_occurrences = 1;
   rtx insn = chain->insn;
   rtx old = (rl->in && GET_CODE (rl->in) == MEM
             ? rl->in_reg : rl->in);
@@ -6879,11 +6772,7 @@ do_input_reload (chain, rl, j)
       && GET_CODE (rl->in_reg) == MEM
       && reload_spill_index[j] >= 0
       && TEST_HARD_REG_BIT (reg_reloaded_valid, reload_spill_index[j]))
-    {
-      expect_occurrences
-       = count_occurrences (PATTERN (insn), rl->in, 0) == 1 ? 0 : -1;
-      rl->in = regno_reg_rtx[reg_reloaded_contents[reload_spill_index[j]]];
-    }
+    rl->in = regno_reg_rtx[reg_reloaded_contents[reload_spill_index[j]]];
 
   /* If we are reloading a register that was recently stored in with an
      output-reload, see if we can prove there was
@@ -6916,10 +6805,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;
@@ -6988,8 +6874,7 @@ do_output_reload (chain, rl, j)
 /* 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;
 
@@ -7362,11 +7247,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;
@@ -7532,10 +7413,12 @@ gen_reload (out, in, opnum, type)
 
 #ifdef SECONDARY_MEMORY_NEEDED
   /* If we need a memory location to do the move, do it that way.  */
-  else if (GET_CODE (in) == REG && REGNO (in) < FIRST_PSEUDO_REGISTER
-          && GET_CODE (out) == REG && REGNO (out) < FIRST_PSEUDO_REGISTER
-          && SECONDARY_MEMORY_NEEDED (REGNO_REG_CLASS (REGNO (in)),
-                                      REGNO_REG_CLASS (REGNO (out)),
+  else if ((GET_CODE (in) == REG || GET_CODE (in) == SUBREG)
+          && reg_or_subregno (in) < FIRST_PSEUDO_REGISTER
+          && (GET_CODE (out) == REG || GET_CODE (out) == SUBREG)
+          && reg_or_subregno (out) < FIRST_PSEUDO_REGISTER
+          && SECONDARY_MEMORY_NEEDED (REGNO_REG_CLASS (reg_or_subregno (in)),
+                                      REGNO_REG_CLASS (reg_or_subregno (out)),
                                       GET_MODE (out)))
     {
       /* Get the memory to use and rewrite both registers to its mode.  */
@@ -7584,10 +7467,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];
@@ -7597,6 +7477,11 @@ delete_output_reload (insn, j, last_reload_reg)
   rtx i1;
   rtx substed;
 
+  /* It is possible that this reload has been only used to set another reload
+     we eliminated earlier and thus deleted this instruction too.  */
+  if (INSN_DELETED_P (output_reload_insn))
+    return;
+
   /* Get the raw pseudo-register referred to.  */
 
   while (GET_CODE (reg) == SUBREG)
@@ -7678,7 +7563,7 @@ delete_output_reload (insn, j, last_reload_reg)
 
   /* The caller has already checked that REG dies or is set in INSN.
      It has also checked that we are optimizing, and thus some
-     inaccurancies in the debugging information are acceptable.
+     inaccuracies in the debugging information are acceptable.
      So we could just delete output_reload_insn.  But in some cases
      we can improve the debugging information without sacrificing
      optimization - maybe even improving the code: See if the pseudo
@@ -7749,8 +7634,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;
@@ -7786,8 +7670,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;
@@ -7880,7 +7763,7 @@ delete_address_reloads_1 (dead_insn, x, current_insn)
                  return;
              /* ??? We can't finish the loop here, because dst might be
                 allocated to a pseudo in this block if no reload in this
-                block needs any of the clsses containing DST - see
+                block needs any of the classes containing DST - see
                 spill_hard_reg.  There is no easy way to tell this, so we
                 have to scan till the end of the basic block.  */
            }
@@ -7905,10 +7788,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);
@@ -7922,7 +7802,7 @@ inc_for_reload (reloadreg, in, value, inc_amount)
   rtx real_in = in == value ? XEXP (in, 0) : in;
 
   /* No hard register is equivalent to this register after
-     inc/dec operation.  If REG_LAST_RELOAD_REG were non-zero,
+     inc/dec operation.  If REG_LAST_RELOAD_REG were nonzero,
      we could inc/dec that register as well (maybe even using it for
      the source), but I'm not sure it's worth worrying about.  */
   if (GET_CODE (incloc) == REG)
@@ -7997,1511 +7877,128 @@ inc_for_reload (reloadreg, in, value, inc_amount)
   return store;
 }
 \f
-
-/* See whether a single set SET is a noop.  */
-static int
-reload_cse_noop_set_p (set)
-     rtx set;
-{
-  return rtx_equal_for_cselib_p (SET_DEST (set), SET_SRC (set));
-}
-
-/* Try to simplify INSN.  */
+#ifdef AUTO_INC_DEC
 static void
-reload_cse_simplify (insn, testreg)
-     rtx insn;
-     rtx testreg;
+add_auto_inc_notes (rtx insn, rtx x)
 {
-  rtx body = PATTERN (insn);
-
-  if (GET_CODE (body) == SET)
-    {
-      int count = 0;
-
-      /* Simplify even if we may think it is a no-op.
-         We may think a memory load of a value smaller than WORD_SIZE
-         is redundant because we haven't taken into account possible
-         implicit extension.  reload_cse_simplify_set() will bring
-         this out, so it's safer to simplify before we delete.  */
-      count += reload_cse_simplify_set (body, insn);
-
-      if (!count && reload_cse_noop_set_p (body))
-       {
-         rtx value = SET_DEST (body);
-         if (REG_P (value)
-             && ! REG_FUNCTION_VALUE_P (value))
-           value = 0;
-         delete_insn_and_edges (insn);
-         return;
-       }
+  enum rtx_code code = GET_CODE (x);
+  const char *fmt;
+  int i, j;
 
-      if (count > 0)
-       apply_change_group ();
-      else
-       reload_cse_simplify_operands (insn, testreg);
-    }
-  else if (GET_CODE (body) == PARALLEL)
+  if (code == MEM && auto_inc_p (XEXP (x, 0)))
     {
-      int i;
-      int count = 0;
-      rtx value = NULL_RTX;
-
-      /* If every action in a PARALLEL is a noop, we can delete
-        the entire PARALLEL.  */
-      for (i = XVECLEN (body, 0) - 1; i >= 0; --i)
-       {
-         rtx part = XVECEXP (body, 0, i);
-         if (GET_CODE (part) == SET)
-           {
-             if (! reload_cse_noop_set_p (part))
-               break;
-             if (REG_P (SET_DEST (part))
-                 && REG_FUNCTION_VALUE_P (SET_DEST (part)))
-               {
-                 if (value)
-                   break;
-                 value = SET_DEST (part);
-               }
-           }
-         else if (GET_CODE (part) != CLOBBER)
-           break;
-       }
-
-      if (i < 0)
-       {
-         delete_insn_and_edges (insn);
-         /* We're done with this insn.  */
-         return;
-       }
-
-      /* It's not a no-op, but we can try to simplify it.  */
-      for (i = XVECLEN (body, 0) - 1; i >= 0; --i)
-       if (GET_CODE (XVECEXP (body, 0, i)) == SET)
-         count += reload_cse_simplify_set (XVECEXP (body, 0, i), insn);
-
-      if (count > 0)
-       apply_change_group ();
-      else
-       reload_cse_simplify_operands (insn, testreg);
+      REG_NOTES (insn)
+       = gen_rtx_EXPR_LIST (REG_INC, XEXP (XEXP (x, 0), 0), REG_NOTES (insn));
+      return;
     }
-}
-
-/* Do a very simple CSE pass over the hard registers.
-
-   This function detects no-op moves where we happened to assign two
-   different pseudo-registers to the same hard register, and then
-   copied one to the other.  Reload will generate a useless
-   instruction copying a register to itself.
-
-   This function also detects cases where we load a value from memory
-   into two different registers, and (if memory is more expensive than
-   registers) changes it to simply copy the first register into the
-   second register.
-
-   Another optimization is performed that scans the operands of each
-   instruction to see whether the value is already available in a
-   hard register.  It then replaces the operand with the hard register
-   if possible, much like an optional reload would.  */
-
-static void
-reload_cse_regs_1 (first)
-     rtx first;
-{
-  rtx insn;
-  rtx testreg = gen_rtx_REG (VOIDmode, -1);
 
-  cselib_init ();
-  init_alias_analysis ();
-
-  for (insn = first; insn; insn = NEXT_INSN (insn))
+  /* Scan all the operand sub-expressions.  */
+  fmt = GET_RTX_FORMAT (code);
+  for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
     {
-      if (INSN_P (insn))
-       reload_cse_simplify (insn, testreg);
-
-      cselib_process_insn (insn);
+      if (fmt[i] == 'e')
+       add_auto_inc_notes (insn, XEXP (x, i));
+      else if (fmt[i] == 'E')
+       for (j = XVECLEN (x, i) - 1; j >= 0; j--)
+         add_auto_inc_notes (insn, XVECEXP (x, i, j));
     }
-
-  /* Clean up.  */
-  end_alias_analysis ();
-  cselib_finish ();
 }
-
-/* Call cse / combine like post-reload optimization phases.
-   FIRST is the first instruction.  */
-void
-reload_cse_regs (first)
-     rtx first;
-{
-  reload_cse_regs_1 (first);
-  reload_combine ();
-  reload_cse_move2add (first);
-  if (flag_expensive_optimizations)
-    reload_cse_regs_1 (first);
-}
-
-/* Try to simplify a single SET instruction.  SET is the set pattern.
-   INSN is the instruction it came from.
-   This function only handles one case: if we set a register to a value
-   which is not a register, we try to find that value in some other register
-   and change the set into a register copy.  */
-
-static int
-reload_cse_simplify_set (set, insn)
-     rtx set;
-     rtx insn;
-{
-  int did_change = 0;
-  int dreg;
-  rtx src;
-  enum reg_class dclass;
-  int old_cost;
-  cselib_val *val;
-  struct elt_loc_list *l;
-#ifdef LOAD_EXTEND_OP
-  enum rtx_code extend_op = NIL;
 #endif
 
-  dreg = true_regnum (SET_DEST (set));
-  if (dreg < 0)
-    return 0;
-
-  src = SET_SRC (set);
-  if (side_effects_p (src) || true_regnum (src) >= 0)
-    return 0;
-
-  dclass = REGNO_REG_CLASS (dreg);
-
-#ifdef LOAD_EXTEND_OP
-  /* When replacing a memory with a register, we need to honor assumptions
-     that combine made wrt the contents of sign bits.  We'll do this by
-     generating an extend instruction instead of a reg->reg copy.  Thus
-     the destination must be a register that we can widen.  */
-  if (GET_CODE (src) == MEM
-      && GET_MODE_BITSIZE (GET_MODE (src)) < BITS_PER_WORD
-      && (extend_op = LOAD_EXTEND_OP (GET_MODE (src))) != NIL
-      && GET_CODE (SET_DEST (set)) != REG)
-    return 0;
-#endif
-
-  /* If memory loads are cheaper than register copies, don't change them.  */
-  if (GET_CODE (src) == MEM)
-    old_cost = MEMORY_MOVE_COST (GET_MODE (src), dclass, 1);
-  else if (CONSTANT_P (src))
-    old_cost = rtx_cost (src, SET);
-  else if (GET_CODE (src) == REG)
-    old_cost = REGISTER_MOVE_COST (GET_MODE (src),
-                                  REGNO_REG_CLASS (REGNO (src)), dclass);
-  else
-    /* ???   */
-    old_cost = rtx_cost (src, SET);
-
-  val = cselib_lookup (src, GET_MODE (SET_DEST (set)), 0);
-  if (! val)
-    return 0;
-  for (l = val->locs; l; l = l->next)
+/* Copy EH notes from an insn to its reloads.  */
+static void
+copy_eh_notes (rtx insn, rtx x)
+{
+  rtx eh_note = find_reg_note (insn, REG_EH_REGION, NULL_RTX);
+  if (eh_note)
     {
-      rtx this_rtx = l->loc;
-      int this_cost;
-
-      if (CONSTANT_P (this_rtx) && ! references_value_p (this_rtx, 0))
-       {
-#ifdef LOAD_EXTEND_OP
-         if (extend_op != NIL)
-           {
-             HOST_WIDE_INT this_val;
-
-             /* ??? I'm lazy and don't wish to handle CONST_DOUBLE.  Other
-                constants, such as SYMBOL_REF, cannot be extended.  */
-             if (GET_CODE (this_rtx) != CONST_INT)
-               continue;
-
-             this_val = INTVAL (this_rtx);
-             switch (extend_op)
-               {
-               case ZERO_EXTEND:
-                 this_val &= GET_MODE_MASK (GET_MODE (src));
-                 break;
-               case SIGN_EXTEND:
-                 /* ??? In theory we're already extended.  */
-                 if (this_val == trunc_int_for_mode (this_val, GET_MODE (src)))
-                   break;
-               default:
-                 abort ();
-               }
-             this_rtx = GEN_INT (this_val);
-           }
-#endif
-         this_cost = rtx_cost (this_rtx, SET);
-       }
-      else if (GET_CODE (this_rtx) == REG)
-       {
-#ifdef LOAD_EXTEND_OP
-         if (extend_op != NIL)
-           {
-             this_rtx = gen_rtx_fmt_e (extend_op, word_mode, this_rtx);
-             this_cost = rtx_cost (this_rtx, SET);
-           }
-         else
-#endif
-           this_cost = REGISTER_MOVE_COST (GET_MODE (this_rtx),
-                                           REGNO_REG_CLASS (REGNO (this_rtx)),
-                                           dclass);
-       }
-      else
-       continue;
-
-      /* If equal costs, prefer registers over anything else.  That
-        tends to lead to smaller instructions on some machines.  */
-      if (this_cost < old_cost
-         || (this_cost == old_cost
-             && GET_CODE (this_rtx) == REG
-             && GET_CODE (SET_SRC (set)) != REG))
+      for (; x != 0; x = NEXT_INSN (x))
        {
-#ifdef LOAD_EXTEND_OP
-         if (GET_MODE_BITSIZE (GET_MODE (SET_DEST (set))) < BITS_PER_WORD
-             && extend_op != NIL)
-           {
-             rtx wide_dest = gen_rtx_REG (word_mode, REGNO (SET_DEST (set)));
-             ORIGINAL_REGNO (wide_dest) = ORIGINAL_REGNO (SET_DEST (set));
-             validate_change (insn, &SET_DEST (set), wide_dest, 1);
-           }
-#endif
-
-         validate_change (insn, &SET_SRC (set), copy_rtx (this_rtx), 1);
-         old_cost = this_cost, did_change = 1;
+         if (may_trap_p (PATTERN (x)))
+           REG_NOTES (x)
+             = gen_rtx_EXPR_LIST (REG_EH_REGION, XEXP (eh_note, 0),
+                                  REG_NOTES (x));
        }
     }
-
-  return did_change;
 }
 
-/* Try to replace operands in INSN with equivalent values that are already
-   in registers.  This can be viewed as optional reloading.
-
-   For each non-register operand in the insn, see if any hard regs are
-   known to be equivalent to that operand.  Record the alternatives which
-   can accept these hard registers.  Among all alternatives, select the
-   ones which are better or equal to the one currently matching, where
-   "better" is in terms of '?' and '!' constraints.  Among the remaining
-   alternatives, select the one which replaces most operands with
-   hard registers.  */
+/* This is used by reload pass, that does emit some instructions after
+   abnormal calls moving basic block end, but in fact it wants to emit
+   them on the edge.  Looks for abnormal call edges, find backward the
+   proper call and fix the damage.
 
-static int
-reload_cse_simplify_operands (insn, testreg)
-     rtx insn;
-     rtx testreg;
+   Similar handle instructions throwing exceptions internally.  */
+void
+fixup_abnormal_edges (void)
 {
-  int i, j;
-
-  /* For each operand, all registers that are equivalent to it.  */
-  HARD_REG_SET equiv_regs[MAX_RECOG_OPERANDS];
-
-  const char *constraints[MAX_RECOG_OPERANDS];
-
-  /* Vector recording how bad an alternative is.  */
-  int *alternative_reject;
-  /* Vector recording how many registers can be introduced by choosing
-     this alternative.  */
-  int *alternative_nregs;
-  /* Array of vectors recording, for each operand and each alternative,
-     which hard register to substitute, or -1 if the operand should be
-     left as it is.  */
-  int *op_alt_regno[MAX_RECOG_OPERANDS];
-  /* Array of alternatives, sorted in order of decreasing desirability.  */
-  int *alternative_order;
-
-  extract_insn (insn);
-
-  if (recog_data.n_alternatives == 0 || recog_data.n_operands == 0)
-    return 0;
-
-  /* Figure out which alternative currently matches.  */
-  if (! constrain_operands (1))
-    fatal_insn_not_found (insn);
-
-  alternative_reject = (int *) alloca (recog_data.n_alternatives * sizeof (int));
-  alternative_nregs = (int *) alloca (recog_data.n_alternatives * sizeof (int));
-  alternative_order = (int *) alloca (recog_data.n_alternatives * sizeof (int));
-  memset ((char *) alternative_reject, 0, recog_data.n_alternatives * sizeof (int));
-  memset ((char *) alternative_nregs, 0, recog_data.n_alternatives * sizeof (int));
-
-  /* For each operand, find out which regs are equivalent.  */
-  for (i = 0; i < recog_data.n_operands; i++)
-    {
-      cselib_val *v;
-      struct elt_loc_list *l;
-
-      CLEAR_HARD_REG_SET (equiv_regs[i]);
-
-      /* cselib blows up on CODE_LABELs.  Trying to fix that doesn't seem
-        right, so avoid the problem here.  Likewise if we have a constant
-         and the insn pattern doesn't tell us the mode we need.  */
-      if (GET_CODE (recog_data.operand[i]) == CODE_LABEL
-         || (CONSTANT_P (recog_data.operand[i])
-             && recog_data.operand_mode[i] == VOIDmode))
-       continue;
-
-      v = cselib_lookup (recog_data.operand[i], recog_data.operand_mode[i], 0);
-      if (! v)
-       continue;
-
-      for (l = v->locs; l; l = l->next)
-       if (GET_CODE (l->loc) == REG)
-         SET_HARD_REG_BIT (equiv_regs[i], REGNO (l->loc));
-    }
+  bool inserted = false;
+  basic_block bb;
 
-  for (i = 0; i < recog_data.n_operands; i++)
+  FOR_EACH_BB (bb)
     {
-      enum machine_mode mode;
-      int regno;
-      const char *p;
-
-      op_alt_regno[i] = (int *) alloca (recog_data.n_alternatives * sizeof (int));
-      for (j = 0; j < recog_data.n_alternatives; j++)
-       op_alt_regno[i][j] = -1;
-
-      p = constraints[i] = recog_data.constraints[i];
-      mode = recog_data.operand_mode[i];
+      edge e;
 
-      /* Add the reject values for each alternative given by the constraints
-        for this operand.  */
-      j = 0;
-      while (*p != '\0')
+      /* Look for cases we are interested in - calls or instructions causing
+         exceptions.  */
+      for (e = bb->succ; e; e = e->succ_next)
        {
-         char c = *p++;
-         if (c == ',')
-           j++;
-         else if (c == '?')
-           alternative_reject[j] += 3;
-         else if (c == '!')
-           alternative_reject[j] += 300;
+         if (e->flags & EDGE_ABNORMAL_CALL)
+           break;
+         if ((e->flags & (EDGE_ABNORMAL | EDGE_EH))
+             == (EDGE_ABNORMAL | EDGE_EH))
+           break;
        }
-
-      /* We won't change operands which are already registers.  We
-        also don't want to modify output operands.  */
-      regno = true_regnum (recog_data.operand[i]);
-      if (regno >= 0
-         || constraints[i][0] == '='
-         || constraints[i][0] == '+')
-       continue;
-
-      for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
+      if (e && GET_CODE (bb->end) != CALL_INSN && !can_throw_internal (bb->end))
        {
-         int class = (int) NO_REGS;
-
-         if (! TEST_HARD_REG_BIT (equiv_regs[i], regno))
-           continue;
-
-         REGNO (testreg) = regno;
-         PUT_MODE (testreg, mode);
-
-         /* We found a register equal to this operand.  Now look for all
-            alternatives that can accept this register and have not been
-            assigned a register they can use yet.  */
-         j = 0;
-         p = constraints[i];
-         for (;;)
+         rtx insn = bb->end, stop = NEXT_INSN (bb->end);
+         rtx next;
+         for (e = bb->succ; e; e = e->succ_next)
+           if (e->flags & EDGE_FALLTHRU)
+             break;
+         /* Get past the new insns generated. Allow notes, as the insns may
+            be already deleted.  */
+         while ((GET_CODE (insn) == INSN || GET_CODE (insn) == NOTE)
+                && !can_throw_internal (insn)
+                && insn != bb->head)
+           insn = PREV_INSN (insn);
+         if (GET_CODE (insn) != CALL_INSN && !can_throw_internal (insn))
+           abort ();
+         bb->end = insn;
+         inserted = true;
+         insn = NEXT_INSN (insn);
+         while (insn && insn != stop)
            {
-             char c = *p++;
-
-             switch (c)
+             next = NEXT_INSN (insn);
+             if (INSN_P (insn))
                {
-               case '=':  case '+':  case '?':
-               case '#':  case '&':  case '!':
-               case '*':  case '%':
-               case '0':  case '1':  case '2':  case '3':  case '4':
-               case '5':  case '6':  case '7':  case '8':  case '9':
-               case 'm':  case '<':  case '>':  case 'V':  case 'o':
-               case 'E':  case 'F':  case 'G':  case 'H':
-               case 's':  case 'i':  case 'n':
-               case 'I':  case 'J':  case 'K':  case 'L':
-               case 'M':  case 'N':  case 'O':  case 'P':
-               case 'p': case 'X':
-                 /* These don't say anything we care about.  */
-                 break;
-
-               case 'g': case 'r':
-                 class = reg_class_subunion[(int) class][(int) GENERAL_REGS];
-                 break;
-
-               default:
-                 class
-                   = reg_class_subunion[(int) class][(int) REG_CLASS_FROM_LETTER ((unsigned char) c)];
-                 break;
+                 delete_insn (insn);
 
-               case ',': case '\0':
-                 /* See if REGNO fits this alternative, and set it up as the
-                    replacement register if we don't have one for this
-                    alternative yet and the operand being replaced is not
-                    a cheap CONST_INT.  */
-                 if (op_alt_regno[i][j] == -1
-                     && reg_fits_class_p (testreg, class, 0, mode)
-                     && (GET_CODE (recog_data.operand[i]) != CONST_INT
-                         || (rtx_cost (recog_data.operand[i], SET)
-                             > rtx_cost (testreg, SET))))
+                 /* Sometimes there's still the return value USE.
+                    If it's placed after a trapping call (i.e. that
+                    call is the last insn anyway), we have no fallthru
+                    edge.  Simply delete this use and don't try to insert
+                    on the non-existent edge.  */
+                 if (GET_CODE (PATTERN (insn)) != USE)
                    {
-                     alternative_nregs[j]++;
-                     op_alt_regno[i][j] = regno;
+                     /* We're not deleting it, we're moving it.  */
+                     INSN_DELETED_P (insn) = 0;
+                     PREV_INSN (insn) = NULL_RTX;
+                     NEXT_INSN (insn) = NULL_RTX;
+
+                     insert_insn_on_edge (insn, e);
                    }
-                 j++;
-                 break;
                }
-
-             if (c == '\0')
-               break;
+             insn = next;
            }
        }
     }
-
-  /* Record all alternatives which are better or equal to the currently
-     matching one in the alternative_order array.  */
-  for (i = j = 0; i < recog_data.n_alternatives; i++)
-    if (alternative_reject[i] <= alternative_reject[which_alternative])
-      alternative_order[j++] = i;
-  recog_data.n_alternatives = j;
-
-  /* Sort it.  Given a small number of alternatives, a dumb algorithm
-     won't hurt too much.  */
-  for (i = 0; i < recog_data.n_alternatives - 1; i++)
-    {
-      int best = i;
-      int best_reject = alternative_reject[alternative_order[i]];
-      int best_nregs = alternative_nregs[alternative_order[i]];
-      int tmp;
-
-      for (j = i + 1; j < recog_data.n_alternatives; j++)
-       {
-         int this_reject = alternative_reject[alternative_order[j]];
-         int this_nregs = alternative_nregs[alternative_order[j]];
-
-         if (this_reject < best_reject
-             || (this_reject == best_reject && this_nregs < best_nregs))
-           {
-             best = j;
-             best_reject = this_reject;
-             best_nregs = this_nregs;
-           }
-       }
-
-      tmp = alternative_order[best];
-      alternative_order[best] = alternative_order[i];
-      alternative_order[i] = tmp;
-    }
-
-  /* Substitute the operands as determined by op_alt_regno for the best
-     alternative.  */
-  j = alternative_order[0];
-
-  for (i = 0; i < recog_data.n_operands; i++)
-    {
-      enum machine_mode mode = recog_data.operand_mode[i];
-      if (op_alt_regno[i][j] == -1)
-       continue;
-
-      validate_change (insn, recog_data.operand_loc[i],
-                      gen_rtx_REG (mode, op_alt_regno[i][j]), 1);
-    }
-
-  for (i = recog_data.n_dups - 1; i >= 0; i--)
-    {
-      int op = recog_data.dup_num[i];
-      enum machine_mode mode = recog_data.operand_mode[op];
-
-      if (op_alt_regno[op][j] == -1)
-       continue;
-
-      validate_change (insn, recog_data.dup_loc[i],
-                      gen_rtx_REG (mode, op_alt_regno[op][j]), 1);
-    }
-
-  return apply_change_group ();
-}
-\f
-/* If reload couldn't use reg+reg+offset addressing, try to use reg+reg
-   addressing now.
-   This code might also be useful when reload gave up on reg+reg addresssing
-   because of clashes between the return register and INDEX_REG_CLASS.  */
-
-/* The maximum number of uses of a register we can keep track of to
-   replace them with reg+reg addressing.  */
-#define RELOAD_COMBINE_MAX_USES 6
-
-/* INSN is the insn where a register has ben used, and USEP points to the
-   location of the register within the rtl.  */
-struct reg_use { rtx insn, *usep; };
-
-/* If the register is used in some unknown fashion, USE_INDEX is negative.
-   If it is dead, USE_INDEX is RELOAD_COMBINE_MAX_USES, and STORE_RUID
-   indicates where it becomes live again.
-   Otherwise, USE_INDEX is the index of the last encountered use of the
-   register (which is first among these we have seen since we scan backwards),
-   OFFSET contains the constant offset that is added to the register in
-   all encountered uses, and USE_RUID indicates the first encountered, i.e.
-   last, of these uses.
-   STORE_RUID is always meaningful if we only want to use a value in a
-   register in a different place: it denotes the next insn in the insn
-   stream (i.e. the last ecountered) that sets or clobbers the register.  */
-static struct
-  {
-    struct reg_use reg_use[RELOAD_COMBINE_MAX_USES];
-    int use_index;
-    rtx offset;
-    int store_ruid;
-    int use_ruid;
-  } reg_state[FIRST_PSEUDO_REGISTER];
-
-/* Reverse linear uid.  This is increased in reload_combine while scanning
-   the instructions from last to first.  It is used to set last_label_ruid
-   and the store_ruid / use_ruid fields in reg_state.  */
-static int reload_combine_ruid;
-
-#define LABEL_LIVE(LABEL) \
-  (label_live[CODE_LABEL_NUMBER (LABEL) - min_labelno])
-
-static void
-reload_combine ()
-{
-  rtx insn, set;
-  int first_index_reg = -1;
-  int last_index_reg = 0;
-  int i;
-  basic_block bb;
-  unsigned int r;
-  int last_label_ruid;
-  int min_labelno, n_labels;
-  HARD_REG_SET ever_live_at_start, *label_live;
-
-  /* If reg+reg can be used in offsetable memory addresses, the main chunk of
-     reload has already used it where appropriate, so there is no use in
-     trying to generate it now.  */
-  if (double_reg_address_ok && INDEX_REG_CLASS != NO_REGS)
-    return;
-
-  /* To avoid wasting too much time later searching for an index register,
-     determine the minimum and maximum index register numbers.  */
-  for (r = 0; r < FIRST_PSEUDO_REGISTER; r++)
-    if (TEST_HARD_REG_BIT (reg_class_contents[INDEX_REG_CLASS], r))
-      {
-       if (first_index_reg == -1)
-         first_index_reg = r;
-
-       last_index_reg = r;
-      }
-
-  /* If no index register is available, we can quit now.  */
-  if (first_index_reg == -1)
-    return;
-
-  /* Set up LABEL_LIVE and EVER_LIVE_AT_START.  The register lifetime
-     information is a bit fuzzy immediately after reload, but it's
-     still good enough to determine which registers are live at a jump
-     destination.  */
-  min_labelno = get_first_label_num ();
-  n_labels = max_label_num () - min_labelno;
-  label_live = (HARD_REG_SET *) xmalloc (n_labels * sizeof (HARD_REG_SET));
-  CLEAR_HARD_REG_SET (ever_live_at_start);
-
-  FOR_EACH_BB_REVERSE (bb)
-    {
-      insn = bb->head;
-      if (GET_CODE (insn) == CODE_LABEL)
-       {
-         HARD_REG_SET live;
-
-         REG_SET_TO_HARD_REG_SET (live,
-                                  bb->global_live_at_start);
-         compute_use_by_pseudos (&live,
-                                 bb->global_live_at_start);
-         COPY_HARD_REG_SET (LABEL_LIVE (insn), live);
-         IOR_HARD_REG_SET (ever_live_at_start, live);
-       }
-    }
-
-  /* Initialize last_label_ruid, reload_combine_ruid and reg_state.  */
-  last_label_ruid = reload_combine_ruid = 0;
-  for (r = 0; r < FIRST_PSEUDO_REGISTER; r++)
-    {
-      reg_state[r].store_ruid = reload_combine_ruid;
-      if (fixed_regs[r])
-       reg_state[r].use_index = -1;
-      else
-       reg_state[r].use_index = RELOAD_COMBINE_MAX_USES;
-    }
-
-  for (insn = get_last_insn (); insn; insn = PREV_INSN (insn))
-    {
-      rtx note;
-
-      /* We cannot do our optimization across labels.  Invalidating all the use
-        information we have would be costly, so we just note where the label
-        is and then later disable any optimization that would cross it.  */
-      if (GET_CODE (insn) == CODE_LABEL)
-       last_label_ruid = reload_combine_ruid;
-      else if (GET_CODE (insn) == BARRIER)
-       for (r = 0; r < FIRST_PSEUDO_REGISTER; r++)
-         if (! fixed_regs[r])
-             reg_state[r].use_index = RELOAD_COMBINE_MAX_USES;
-
-      if (! INSN_P (insn))
-       continue;
-
-      reload_combine_ruid++;
-
-      /* Look for (set (REGX) (CONST_INT))
-        (set (REGX) (PLUS (REGX) (REGY)))
-        ...
-        ... (MEM (REGX)) ...
-        and convert it to
-        (set (REGZ) (CONST_INT))
-        ...
-        ... (MEM (PLUS (REGZ) (REGY)))... .
-
-        First, check that we have (set (REGX) (PLUS (REGX) (REGY)))
-        and that we know all uses of REGX before it dies.  */
-      set = single_set (insn);
-      if (set != NULL_RTX
-         && GET_CODE (SET_DEST (set)) == REG
-         && (HARD_REGNO_NREGS (REGNO (SET_DEST (set)),
-                               GET_MODE (SET_DEST (set)))
-             == 1)
-         && GET_CODE (SET_SRC (set)) == PLUS
-         && GET_CODE (XEXP (SET_SRC (set), 1)) == REG
-         && rtx_equal_p (XEXP (SET_SRC (set), 0), SET_DEST (set))
-         && last_label_ruid < reg_state[REGNO (SET_DEST (set))].use_ruid)
-       {
-         rtx reg = SET_DEST (set);
-         rtx plus = SET_SRC (set);
-         rtx base = XEXP (plus, 1);
-         rtx prev = prev_nonnote_insn (insn);
-         rtx prev_set = prev ? single_set (prev) : NULL_RTX;
-         unsigned int regno = REGNO (reg);
-         rtx const_reg = NULL_RTX;
-         rtx reg_sum = NULL_RTX;
-
-         /* Now, we need an index register.
-            We'll set index_reg to this index register, const_reg to the
-            register that is to be loaded with the constant
-            (denoted as REGZ in the substitution illustration above),
-            and reg_sum to the register-register that we want to use to
-            substitute uses of REG (typically in MEMs) with.
-            First check REG and BASE for being index registers;
-            we can use them even if they are not dead.  */
-         if (TEST_HARD_REG_BIT (reg_class_contents[INDEX_REG_CLASS], regno)
-             || TEST_HARD_REG_BIT (reg_class_contents[INDEX_REG_CLASS],
-                                   REGNO (base)))
-           {
-             const_reg = reg;
-             reg_sum = plus;
-           }
-         else
-           {
-             /* Otherwise, look for a free index register.  Since we have
-                checked above that neiter REG nor BASE are index registers,
-                if we find anything at all, it will be different from these
-                two registers.  */
-             for (i = first_index_reg; i <= last_index_reg; i++)
-               {
-                 if (TEST_HARD_REG_BIT (reg_class_contents[INDEX_REG_CLASS],
-                                        i)
-                     && reg_state[i].use_index == RELOAD_COMBINE_MAX_USES
-                     && reg_state[i].store_ruid <= reg_state[regno].use_ruid
-                     && HARD_REGNO_NREGS (i, GET_MODE (reg)) == 1)
-                   {
-                     rtx index_reg = gen_rtx_REG (GET_MODE (reg), i);
-
-                     const_reg = index_reg;
-                     reg_sum = gen_rtx_PLUS (GET_MODE (reg), index_reg, base);
-                     break;
-                   }
-               }
-           }
-
-         /* Check that PREV_SET is indeed (set (REGX) (CONST_INT)) and that
-            (REGY), i.e. BASE, is not clobbered before the last use we'll
-            create.  */
-         if (prev_set != 0
-             && GET_CODE (SET_SRC (prev_set)) == CONST_INT
-             && rtx_equal_p (SET_DEST (prev_set), reg)
-             && reg_state[regno].use_index >= 0
-             && (reg_state[REGNO (base)].store_ruid
-                 <= reg_state[regno].use_ruid)
-             && reg_sum != 0)
-           {
-             int i;
-
-             /* Change destination register and, if necessary, the
-                constant value in PREV, the constant loading instruction.  */
-             validate_change (prev, &SET_DEST (prev_set), const_reg, 1);
-             if (reg_state[regno].offset != const0_rtx)
-               validate_change (prev,
-                                &SET_SRC (prev_set),
-                                GEN_INT (INTVAL (SET_SRC (prev_set))
-                                         + INTVAL (reg_state[regno].offset)),
-                                1);
-
-             /* Now for every use of REG that we have recorded, replace REG
-                with REG_SUM.  */
-             for (i = reg_state[regno].use_index;
-                  i < RELOAD_COMBINE_MAX_USES; i++)
-               validate_change (reg_state[regno].reg_use[i].insn,
-                                reg_state[regno].reg_use[i].usep,
-                                /* Each change must have its own
-                                   replacement.  */
-                                copy_rtx (reg_sum), 1);
-
-             if (apply_change_group ())
-               {
-                 rtx *np;
-
-                 /* Delete the reg-reg addition.  */
-                 delete_insn (insn);
-
-                 if (reg_state[regno].offset != const0_rtx)
-                   /* Previous REG_EQUIV / REG_EQUAL notes for PREV
-                      are now invalid.  */
-                   for (np = &REG_NOTES (prev); *np;)
-                     {
-                       if (REG_NOTE_KIND (*np) == REG_EQUAL
-                           || REG_NOTE_KIND (*np) == REG_EQUIV)
-                         *np = XEXP (*np, 1);
-                       else
-                         np = &XEXP (*np, 1);
-                     }
-
-                 reg_state[regno].use_index = RELOAD_COMBINE_MAX_USES;
-                 reg_state[REGNO (const_reg)].store_ruid
-                   = reload_combine_ruid;
-                 continue;
-               }
-           }
-       }
-
-      note_stores (PATTERN (insn), reload_combine_note_store, NULL);
-
-      if (GET_CODE (insn) == CALL_INSN)
-       {
-         rtx link;
-
-         for (r = 0; r < FIRST_PSEUDO_REGISTER; r++)
-           if (call_used_regs[r])
-             {
-               reg_state[r].use_index = RELOAD_COMBINE_MAX_USES;
-               reg_state[r].store_ruid = reload_combine_ruid;
-             }
-
-         for (link = CALL_INSN_FUNCTION_USAGE (insn); link;
-              link = XEXP (link, 1))
-           {
-             rtx usage_rtx = XEXP (XEXP (link, 0), 0);
-             if (GET_CODE (usage_rtx) == REG)
-               {
-                 unsigned int i;
-                 unsigned int start_reg = REGNO (usage_rtx);
-                 unsigned int num_regs =
-                       HARD_REGNO_NREGS (start_reg, GET_MODE (usage_rtx));
-                 unsigned int end_reg  = start_reg + num_regs - 1;
-                 for (i = start_reg; i <= end_reg; i++)
-                   if (GET_CODE (XEXP (link, 0)) == CLOBBER)
-                     {
-                       reg_state[i].use_index = RELOAD_COMBINE_MAX_USES;
-                       reg_state[i].store_ruid = reload_combine_ruid;
-                     }
-                   else
-                     reg_state[i].use_index = -1;
-                }
-            }
-
-       }
-      else if (GET_CODE (insn) == JUMP_INSN
-              && GET_CODE (PATTERN (insn)) != RETURN)
-       {
-         /* Non-spill registers might be used at the call destination in
-            some unknown fashion, so we have to mark the unknown use.  */
-         HARD_REG_SET *live;
-
-         if ((condjump_p (insn) || condjump_in_parallel_p (insn))
-             && JUMP_LABEL (insn))
-           live = &LABEL_LIVE (JUMP_LABEL (insn));
-         else
-           live = &ever_live_at_start;
-
-         for (i = FIRST_PSEUDO_REGISTER - 1; i >= 0; --i)
-           if (TEST_HARD_REG_BIT (*live, i))
-             reg_state[i].use_index = -1;
-       }
-
-      reload_combine_note_use (&PATTERN (insn), insn);
-      for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
-       {
-         if (REG_NOTE_KIND (note) == REG_INC
-             && GET_CODE (XEXP (note, 0)) == REG)
-           {
-             int regno = REGNO (XEXP (note, 0));
-
-             reg_state[regno].store_ruid = reload_combine_ruid;
-             reg_state[regno].use_index = -1;
-           }
-       }
-    }
-
-  free (label_live);
-}
-
-/* Check if DST is a register or a subreg of a register; if it is,
-   update reg_state[regno].store_ruid and reg_state[regno].use_index
-   accordingly.  Called via note_stores from reload_combine.  */
-
-static void
-reload_combine_note_store (dst, set, data)
-     rtx dst, set;
-     void *data ATTRIBUTE_UNUSED;
-{
-  int regno = 0;
-  int i;
-  enum machine_mode mode = GET_MODE (dst);
-
-  if (GET_CODE (dst) == SUBREG)
-    {
-      regno = subreg_regno_offset (REGNO (SUBREG_REG (dst)),
-                                  GET_MODE (SUBREG_REG (dst)),
-                                  SUBREG_BYTE (dst),
-                                  GET_MODE (dst));
-      dst = SUBREG_REG (dst);
-    }
-  if (GET_CODE (dst) != REG)
-    return;
-  regno += REGNO (dst);
-
-  /* note_stores might have stripped a STRICT_LOW_PART, so we have to be
-     careful with registers / register parts that are not full words.
-
-     Similarly for ZERO_EXTRACT and SIGN_EXTRACT.  */
-  if (GET_CODE (set) != SET
-      || GET_CODE (SET_DEST (set)) == ZERO_EXTRACT
-      || GET_CODE (SET_DEST (set)) == SIGN_EXTRACT
-      || GET_CODE (SET_DEST (set)) == STRICT_LOW_PART)
-    {
-      for (i = HARD_REGNO_NREGS (regno, mode) - 1 + regno; i >= regno; i--)
-       {
-         reg_state[i].use_index = -1;
-         reg_state[i].store_ruid = reload_combine_ruid;
-       }
-    }
-  else
-    {
-      for (i = HARD_REGNO_NREGS (regno, mode) - 1 + regno; i >= regno; i--)
-       {
-         reg_state[i].store_ruid = reload_combine_ruid;
-         reg_state[i].use_index = RELOAD_COMBINE_MAX_USES;
-       }
-    }
-}
-
-/* XP points to a piece of rtl that has to be checked for any uses of
-   registers.
-   *XP is the pattern of INSN, or a part of it.
-   Called from reload_combine, and recursively by itself.  */
-static void
-reload_combine_note_use (xp, insn)
-     rtx *xp, insn;
-{
-  rtx x = *xp;
-  enum rtx_code code = x->code;
-  const char *fmt;
-  int i, j;
-  rtx offset = const0_rtx; /* For the REG case below.  */
-
-  switch (code)
-    {
-    case SET:
-      if (GET_CODE (SET_DEST (x)) == REG)
-       {
-         reload_combine_note_use (&SET_SRC (x), insn);
-         return;
-       }
-      break;
-
-    case USE:
-      /* If this is the USE of a return value, we can't change it.  */
-      if (GET_CODE (XEXP (x, 0)) == REG && REG_FUNCTION_VALUE_P (XEXP (x, 0)))
-       {
-       /* Mark the return register as used in an unknown fashion.  */
-         rtx reg = XEXP (x, 0);
-         int regno = REGNO (reg);
-         int nregs = HARD_REGNO_NREGS (regno, GET_MODE (reg));
-
-         while (--nregs >= 0)
-           reg_state[regno + nregs].use_index = -1;
-         return;
-       }
-      break;
-
-    case CLOBBER:
-      if (GET_CODE (SET_DEST (x)) == REG)
-       {
-         /* No spurious CLOBBERs of pseudo registers may remain.  */
-         if (REGNO (SET_DEST (x)) >= FIRST_PSEUDO_REGISTER)
-           abort ();
-         return;
-       }
-      break;
-
-    case PLUS:
-      /* We are interested in (plus (reg) (const_int)) .  */
-      if (GET_CODE (XEXP (x, 0)) != REG
-         || GET_CODE (XEXP (x, 1)) != CONST_INT)
-       break;
-      offset = XEXP (x, 1);
-      x = XEXP (x, 0);
-      /* Fall through.  */
-    case REG:
-      {
-       int regno = REGNO (x);
-       int use_index;
-       int nregs;
-
-       /* No spurious USEs of pseudo registers may remain.  */
-       if (regno >= FIRST_PSEUDO_REGISTER)
-         abort ();
-
-       nregs = HARD_REGNO_NREGS (regno, GET_MODE (x));
-
-       /* We can't substitute into multi-hard-reg uses.  */
-       if (nregs > 1)
-         {
-           while (--nregs >= 0)
-             reg_state[regno + nregs].use_index = -1;
-           return;
-         }
-
-       /* If this register is already used in some unknown fashion, we
-          can't do anything.
-          If we decrement the index from zero to -1, we can't store more
-          uses, so this register becomes used in an unknown fashion.  */
-       use_index = --reg_state[regno].use_index;
-       if (use_index < 0)
-         return;
-
-       if (use_index != RELOAD_COMBINE_MAX_USES - 1)
-         {
-           /* We have found another use for a register that is already
-              used later.  Check if the offsets match; if not, mark the
-              register as used in an unknown fashion.  */
-           if (! rtx_equal_p (offset, reg_state[regno].offset))
-             {
-               reg_state[regno].use_index = -1;
-               return;
-             }
-         }
-       else
-         {
-           /* This is the first use of this register we have seen since we
-              marked it as dead.  */
-           reg_state[regno].offset = offset;
-           reg_state[regno].use_ruid = reload_combine_ruid;
-         }
-       reg_state[regno].reg_use[use_index].insn = insn;
-       reg_state[regno].reg_use[use_index].usep = xp;
-       return;
-      }
-
-    default:
-      break;
-    }
-
-  /* Recursively process the components of X.  */
-  fmt = GET_RTX_FORMAT (code);
-  for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
-    {
-      if (fmt[i] == 'e')
-       reload_combine_note_use (&XEXP (x, i), insn);
-      else if (fmt[i] == 'E')
-       {
-         for (j = XVECLEN (x, i) - 1; j >= 0; j--)
-           reload_combine_note_use (&XVECEXP (x, i, j), insn);
-       }
-    }
-}
-\f
-/* See if we can reduce the cost of a constant by replacing a move
-   with an add.  We track situations in which a register is set to a
-   constant or to a register plus a constant.  */
-/* We cannot do our optimization across labels.  Invalidating all the
-   information about register contents we have would be costly, so we
-   use move2add_last_label_luid to note where the label is and then
-   later disable any optimization that would cross it.
-   reg_offset[n] / reg_base_reg[n] / reg_mode[n] are only valid if
-   reg_set_luid[n] is greater than last_label_luid[n] .  */
-static int reg_set_luid[FIRST_PSEUDO_REGISTER];
-
-/* If reg_base_reg[n] is negative, register n has been set to
-   reg_offset[n] in mode reg_mode[n] .
-   If reg_base_reg[n] is non-negative, register n has been set to the
-   sum of reg_offset[n] and the value of register reg_base_reg[n]
-   before reg_set_luid[n], calculated in mode reg_mode[n] .  */
-static HOST_WIDE_INT reg_offset[FIRST_PSEUDO_REGISTER];
-static int reg_base_reg[FIRST_PSEUDO_REGISTER];
-static enum machine_mode reg_mode[FIRST_PSEUDO_REGISTER];
-
-/* move2add_luid is linearily increased while scanning the instructions
-   from first to last.  It is used to set reg_set_luid in
-   reload_cse_move2add and move2add_note_store.  */
-static int move2add_luid;
-
-/* move2add_last_label_luid is set whenever a label is found.  Labels
-   invalidate all previously collected reg_offset data.  */
-static int move2add_last_label_luid;
-
-/* Generate a CONST_INT and force it in the range of MODE.  */
-
-static HOST_WIDE_INT
-sext_for_mode (mode, value)
-     enum machine_mode mode;
-     HOST_WIDE_INT value;
-{
-  HOST_WIDE_INT cval = value & GET_MODE_MASK (mode);
-  int width = GET_MODE_BITSIZE (mode);
-
-  /* If MODE is narrower than HOST_WIDE_INT and CVAL is a negative number,
-     sign extend it.  */
-  if (width > 0 && width < HOST_BITS_PER_WIDE_INT
-      && (cval & ((HOST_WIDE_INT) 1 << (width - 1))) != 0)
-    cval |= (HOST_WIDE_INT) -1 << width;
-
-  return cval;
-}
-
-/* ??? We don't know how zero / sign extension is handled, hence we
-   can't go from a narrower to a wider mode.  */
-#define MODES_OK_FOR_MOVE2ADD(OUTMODE, INMODE) \
-  (GET_MODE_SIZE (OUTMODE) == GET_MODE_SIZE (INMODE) \
-   || (GET_MODE_SIZE (OUTMODE) <= GET_MODE_SIZE (INMODE) \
-       && TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (OUTMODE), \
-                                GET_MODE_BITSIZE (INMODE))))
-
-static void
-reload_cse_move2add (first)
-     rtx first;
-{
-  int i;
-  rtx insn;
-
-  for (i = FIRST_PSEUDO_REGISTER - 1; i >= 0; i--)
-    reg_set_luid[i] = 0;
-
-  move2add_last_label_luid = 0;
-  move2add_luid = 2;
-  for (insn = first; insn; insn = NEXT_INSN (insn), move2add_luid++)
-    {
-      rtx pat, note;
-
-      if (GET_CODE (insn) == CODE_LABEL)
-       {
-         move2add_last_label_luid = move2add_luid;
-         /* We're going to increment move2add_luid twice after a
-            label, so that we can use move2add_last_label_luid + 1 as
-            the luid for constants.  */
-         move2add_luid++;
-         continue;
-       }
-      if (! INSN_P (insn))
-       continue;
-      pat = PATTERN (insn);
-      /* For simplicity, we only perform this optimization on
-        straightforward SETs.  */
-      if (GET_CODE (pat) == SET
-         && GET_CODE (SET_DEST (pat)) == REG)
-       {
-         rtx reg = SET_DEST (pat);
-         int regno = REGNO (reg);
-         rtx src = SET_SRC (pat);
-
-         /* Check if we have valid information on the contents of this
-            register in the mode of REG.  */
-         if (reg_set_luid[regno] > move2add_last_label_luid
-             && MODES_OK_FOR_MOVE2ADD (GET_MODE (reg), reg_mode[regno]))
-           {
-             /* Try to transform (set (REGX) (CONST_INT A))
-                                 ...
-                                 (set (REGX) (CONST_INT B))
-                to
-                                 (set (REGX) (CONST_INT A))
-                                 ...
-                                 (set (REGX) (plus (REGX) (CONST_INT B-A)))  */
-
-             if (GET_CODE (src) == CONST_INT && reg_base_reg[regno] < 0)
-               {
-                 int success = 0;
-                 rtx new_src = GEN_INT (sext_for_mode (GET_MODE (reg),
-                                                       INTVAL (src)
-                                                       - reg_offset[regno]));
-                 /* (set (reg) (plus (reg) (const_int 0))) is not canonical;
-                    use (set (reg) (reg)) instead.
-                    We don't delete this insn, nor do we convert it into a
-                    note, to avoid losing register notes or the return
-                    value flag.  jump2 already knowns how to get rid of
-                    no-op moves.  */
-                 if (new_src == const0_rtx)
-                   success = validate_change (insn, &SET_SRC (pat), reg, 0);
-                 else if (rtx_cost (new_src, PLUS) < rtx_cost (src, SET)
-                          && have_add2_insn (reg, new_src))
-                   success = validate_change (insn, &PATTERN (insn),
-                                              gen_add2_insn (reg, new_src), 0);
-                 reg_set_luid[regno] = move2add_luid;
-                 reg_mode[regno] = GET_MODE (reg);
-                 reg_offset[regno] = INTVAL (src);
-                 continue;
-               }
-
-             /* Try to transform (set (REGX) (REGY))
-                                 (set (REGX) (PLUS (REGX) (CONST_INT A)))
-                                 ...
-                                 (set (REGX) (REGY))
-                                 (set (REGX) (PLUS (REGX) (CONST_INT B)))
-                to
-                                 (REGX) (REGY))
-                                 (set (REGX) (PLUS (REGX) (CONST_INT A)))
-                                 ...
-                                 (set (REGX) (plus (REGX) (CONST_INT B-A)))  */
-             else if (GET_CODE (src) == REG
-                      && reg_set_luid[regno] == reg_set_luid[REGNO (src)]
-                      && reg_base_reg[regno] == reg_base_reg[REGNO (src)]
-                      && MODES_OK_FOR_MOVE2ADD (GET_MODE (reg),
-                                                reg_mode[REGNO (src)]))
-               {
-                 rtx next = next_nonnote_insn (insn);
-                 rtx set = NULL_RTX;
-                 if (next)
-                   set = single_set (next);
-                 if (set
-                     && SET_DEST (set) == reg
-                     && GET_CODE (SET_SRC (set)) == PLUS
-                     && XEXP (SET_SRC (set), 0) == reg
-                     && GET_CODE (XEXP (SET_SRC (set), 1)) == CONST_INT)
-                   {
-                     rtx src3 = XEXP (SET_SRC (set), 1);
-                     HOST_WIDE_INT added_offset = INTVAL (src3);
-                     HOST_WIDE_INT base_offset = reg_offset[REGNO (src)];
-                     HOST_WIDE_INT regno_offset = reg_offset[regno];
-                     rtx new_src = GEN_INT (sext_for_mode (GET_MODE (reg),
-                                                           added_offset
-                                                           + base_offset
-                                                           - regno_offset));
-                     int success = 0;
-
-                     if (new_src == const0_rtx)
-                       /* See above why we create (set (reg) (reg)) here.  */
-                       success
-                         = validate_change (next, &SET_SRC (set), reg, 0);
-                     else if ((rtx_cost (new_src, PLUS)
-                               < COSTS_N_INSNS (1) + rtx_cost (src3, SET))
-                              && have_add2_insn (reg, new_src))
-                       success
-                         = validate_change (next, &PATTERN (next),
-                                            gen_add2_insn (reg, new_src), 0);
-                     if (success)
-                       delete_insn (insn);
-                     insn = next;
-                     reg_mode[regno] = GET_MODE (reg);
-                     reg_offset[regno] = sext_for_mode (GET_MODE (reg),
-                                                        added_offset
-                                                        + base_offset);
-                     continue;
-                   }
-               }
-           }
-       }
-
-      for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
-       {
-         if (REG_NOTE_KIND (note) == REG_INC
-             && GET_CODE (XEXP (note, 0)) == REG)
-           {
-             /* Reset the information about this register.  */
-             int regno = REGNO (XEXP (note, 0));
-             if (regno < FIRST_PSEUDO_REGISTER)
-               reg_set_luid[regno] = 0;
-           }
-       }
-      note_stores (PATTERN (insn), move2add_note_store, NULL);
-      /* If this is a CALL_INSN, all call used registers are stored with
-        unknown values.  */
-      if (GET_CODE (insn) == CALL_INSN)
-       {
-         for (i = FIRST_PSEUDO_REGISTER - 1; i >= 0; i--)
-           {
-             if (call_used_regs[i])
-               /* Reset the information about this register.  */
-               reg_set_luid[i] = 0;
-           }
-       }
-    }
-}
-
-/* SET is a SET or CLOBBER that sets DST.
-   Update reg_set_luid, reg_offset and reg_base_reg accordingly.
-   Called from reload_cse_move2add via note_stores.  */
-
-static void
-move2add_note_store (dst, set, data)
-     rtx dst, set;
-     void *data ATTRIBUTE_UNUSED;
-{
-  unsigned int regno = 0;
-  unsigned int i;
-  enum machine_mode mode = GET_MODE (dst);
-
-  if (GET_CODE (dst) == SUBREG)
-    {
-      regno = subreg_regno_offset (REGNO (SUBREG_REG (dst)),
-                                  GET_MODE (SUBREG_REG (dst)),
-                                  SUBREG_BYTE (dst),
-                                  GET_MODE (dst));
-      dst = SUBREG_REG (dst);
-    }
-
-  /* Some targets do argument pushes without adding REG_INC notes.  */
-
-  if (GET_CODE (dst) == MEM)
-    {
-      dst = XEXP (dst, 0);
-      if (GET_CODE (dst) == PRE_INC || GET_CODE (dst) == POST_INC
-         || GET_CODE (dst) == PRE_DEC || GET_CODE (dst) == POST_DEC)
-       reg_set_luid[REGNO (XEXP (dst, 0))] = 0;
-      return;
-    }
-  if (GET_CODE (dst) != REG)
-    return;
-
-  regno += REGNO (dst);
-
-  if (HARD_REGNO_NREGS (regno, mode) == 1 && GET_CODE (set) == SET
-      && GET_CODE (SET_DEST (set)) != ZERO_EXTRACT
-      && GET_CODE (SET_DEST (set)) != SIGN_EXTRACT
-      && GET_CODE (SET_DEST (set)) != STRICT_LOW_PART)
-    {
-      rtx src = SET_SRC (set);
-      rtx base_reg;
-      HOST_WIDE_INT offset;
-      int base_regno;
-      /* This may be different from mode, if SET_DEST (set) is a
-        SUBREG.  */
-      enum machine_mode dst_mode = GET_MODE (dst);
-
-      switch (GET_CODE (src))
-       {
-       case PLUS:
-         if (GET_CODE (XEXP (src, 0)) == REG)
-           {
-             base_reg = XEXP (src, 0);
-
-             if (GET_CODE (XEXP (src, 1)) == CONST_INT)
-               offset = INTVAL (XEXP (src, 1));
-             else if (GET_CODE (XEXP (src, 1)) == REG
-                      && (reg_set_luid[REGNO (XEXP (src, 1))]
-                          > move2add_last_label_luid)
-                      && (MODES_OK_FOR_MOVE2ADD
-                          (dst_mode, reg_mode[REGNO (XEXP (src, 1))])))
-               {
-                 if (reg_base_reg[REGNO (XEXP (src, 1))] < 0)
-                   offset = reg_offset[REGNO (XEXP (src, 1))];
-                 /* Maybe the first register is known to be a
-                    constant.  */
-                 else if (reg_set_luid[REGNO (base_reg)]
-                          > move2add_last_label_luid
-                          && (MODES_OK_FOR_MOVE2ADD
-                              (dst_mode, reg_mode[REGNO (XEXP (src, 1))]))
-                          && reg_base_reg[REGNO (base_reg)] < 0)
-                   {
-                     offset = reg_offset[REGNO (base_reg)];
-                     base_reg = XEXP (src, 1);
-                   }
-                 else
-                   goto invalidate;
-               }
-             else
-               goto invalidate;
-
-             break;
-           }
-
-         goto invalidate;
-
-       case REG:
-         base_reg = src;
-         offset = 0;
-         break;
-
-       case CONST_INT:
-         /* Start tracking the register as a constant.  */
-         reg_base_reg[regno] = -1;
-         reg_offset[regno] = INTVAL (SET_SRC (set));
-         /* We assign the same luid to all registers set to constants.  */
-         reg_set_luid[regno] = move2add_last_label_luid + 1;
-         reg_mode[regno] = mode;
-         return;
-
-       default:
-       invalidate:
-         /* Invalidate the contents of the register.  */
-         reg_set_luid[regno] = 0;
-         return;
-       }
-
-      base_regno = REGNO (base_reg);
-      /* If information about the base register is not valid, set it
-        up as a new base register, pretending its value is known
-        starting from the current insn.  */
-      if (reg_set_luid[base_regno] <= move2add_last_label_luid)
-       {
-         reg_base_reg[base_regno] = base_regno;
-         reg_offset[base_regno] = 0;
-         reg_set_luid[base_regno] = move2add_luid;
-         reg_mode[base_regno] = mode;
-       }
-      else if (! MODES_OK_FOR_MOVE2ADD (dst_mode,
-                                       reg_mode[base_regno]))
-       goto invalidate;
-
-      reg_mode[regno] = mode;
-
-      /* Copy base information from our base register.  */
-      reg_set_luid[regno] = reg_set_luid[base_regno];
-      reg_base_reg[regno] = reg_base_reg[base_regno];
-
-      /* Compute the sum of the offsets or constants.  */
-      reg_offset[regno] = sext_for_mode (dst_mode,
-                                        offset
-                                        + reg_offset[base_regno]);
-    }
-  else
-    {
-      unsigned int endregno = regno + HARD_REGNO_NREGS (regno, mode);
-
-      for (i = regno; i < endregno; i++)
-       /* Reset the information about this register.  */
-       reg_set_luid[i] = 0;
-    }
-}
-
-#ifdef AUTO_INC_DEC
-static void
-add_auto_inc_notes (insn, x)
-     rtx insn;
-     rtx x;
-{
-  enum rtx_code code = GET_CODE (x);
-  const char *fmt;
-  int i, j;
-
-  if (code == MEM && auto_inc_p (XEXP (x, 0)))
-    {
-      REG_NOTES (insn)
-       = gen_rtx_EXPR_LIST (REG_INC, XEXP (XEXP (x, 0), 0), REG_NOTES (insn));
-      return;
-    }
-
-  /* Scan all the operand sub-expressions.  */
-  fmt = GET_RTX_FORMAT (code);
-  for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
-    {
-      if (fmt[i] == 'e')
-       add_auto_inc_notes (insn, XEXP (x, i));
-      else if (fmt[i] == 'E')
-       for (j = XVECLEN (x, i) - 1; j >= 0; j--)
-         add_auto_inc_notes (insn, XVECEXP (x, i, j));
-    }
-}
-#endif
-
-/* Copy EH notes from an insn to its reloads.  */
-static void
-copy_eh_notes (insn, x)
-     rtx insn;
-     rtx x;
-{
-  rtx eh_note = find_reg_note (insn, REG_EH_REGION, NULL_RTX);
-  if (eh_note)
-    {
-      for (; x != 0; x = NEXT_INSN (x))
-       {
-         if (may_trap_p (PATTERN (x)))
-           REG_NOTES (x)
-             = gen_rtx_EXPR_LIST (REG_EH_REGION, XEXP (eh_note, 0),
-                                  REG_NOTES (x));
-       }
-    }
-}
-
-/* This is used by reload pass, that does emit some instructions after
-   abnormal calls moving basic block end, but in fact it wants to emit
-   them on the edge.  Looks for abnormal call edges, find backward the
-   proper call and fix the damage.
-
-   Similar handle instructions throwing exceptions internally.  */
-void
-fixup_abnormal_edges ()
-{
-  bool inserted = false;
-  basic_block bb;
-
-  FOR_EACH_BB (bb)
+  /* We've possibly turned single trapping insn into multiple ones.  */
+  if (flag_non_call_exceptions)
     {
-      edge e;
-
-      /* Look for cases we are interested in - an calls or instructions causing
-         exceptions.  */
-      for (e = bb->succ; e; e = e->succ_next)
-       {
-         if (e->flags & EDGE_ABNORMAL_CALL)
-           break;
-         if ((e->flags & (EDGE_ABNORMAL | EDGE_EH))
-             == (EDGE_ABNORMAL | EDGE_EH))
-           break;
-       }
-      if (e && GET_CODE (bb->end) != CALL_INSN && !can_throw_internal (bb->end))
-       {
-         rtx insn = bb->end, stop = NEXT_INSN (bb->end);
-         rtx next;
-         for (e = bb->succ; e; e = e->succ_next)
-           if (e->flags & EDGE_FALLTHRU)
-             break;
-         /* Get past the new insns generated. Allow notes, as the insns may
-            be already deleted.  */
-         while ((GET_CODE (insn) == INSN || GET_CODE (insn) == NOTE)
-                && !can_throw_internal (insn)
-                && insn != bb->head)
-           insn = PREV_INSN (insn);
-         if (GET_CODE (insn) != CALL_INSN && !can_throw_internal (insn))
-           abort ();
-         bb->end = insn;
-         inserted = true;
-         insn = NEXT_INSN (insn);
-         while (insn && insn != stop)
-           {
-             next = NEXT_INSN (insn);
-             if (INSN_P (insn))
-               {
-                 delete_insn (insn);
-
-                 /* Sometimes there's still the return value USE.
-                    If it's placed after a trapping call (i.e. that
-                    call is the last insn anyway), we have no fallthru
-                    edge.  Simply delete this use and don't try to insert
-                    on the non-existant edge.  */
-                 if (GET_CODE (PATTERN (insn)) != USE)
-                   {
-                     /* We're not deleting it, we're moving it.  */
-                     INSN_DELETED_P (insn) = 0;
-                     PREV_INSN (insn) = NULL_RTX;
-                     NEXT_INSN (insn) = NULL_RTX;
-
-                     insert_insn_on_edge (insn, e);
-                   }
-               }
-             insn = next;
-           }
-       }
+      sbitmap blocks;
+      blocks = sbitmap_alloc (last_basic_block);
+      sbitmap_ones (blocks);
+      find_many_sub_basic_blocks (blocks);
     }
   if (inserted)
     commit_edge_insertions ();