match.pd: Implement simple complex operations cancelling.
[gcc.git] / gcc / reload1.c
index 7852566190411d77fe628ffe954b586090c7f573..7d5bad51d88ad5b165179e56762dd7580f9cfee4 100644 (file)
@@ -1,7 +1,5 @@
 /* Reload pseudo regs into hard regs for insns that require hard regs.
-   Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
-   2011 Free Software Foundation, Inc.
+   Copyright (C) 1987-2014 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -32,21 +30,32 @@ along with GCC; see the file COPYING3.  If not see
 #include "insn-config.h"
 #include "ggc.h"
 #include "flags.h"
+#include "hashtab.h"
+#include "hash-set.h"
+#include "vec.h"
+#include "input.h"
 #include "function.h"
 #include "expr.h"
+#include "insn-codes.h"
 #include "optabs.h"
 #include "regs.h"
 #include "addresses.h"
+#include "predict.h"
+#include "dominance.h"
+#include "cfg.h"
+#include "cfgrtl.h"
+#include "cfgbuild.h"
 #include "basic-block.h"
 #include "df.h"
 #include "reload.h"
 #include "recog.h"
-#include "output.h"
 #include "except.h"
 #include "tree.h"
 #include "ira.h"
 #include "target.h"
 #include "emit-rtl.h"
+#include "dumpfile.h"
+#include "rtl-iter.h"
 
 /* This file contains the reload pass of the compiler, which is
    run after register allocation has been done.  It checks that
@@ -117,7 +126,7 @@ static int reg_reloaded_contents[FIRST_PSEUDO_REGISTER];
 /* During reload_as_needed, element N contains the insn for which
    hard register N was last used.   Its contents are significant only
    when reg_reloaded_valid is set for this register.  */
-static rtx reg_reloaded_insn[FIRST_PSEUDO_REGISTER];
+static rtx_insn *reg_reloaded_insn[FIRST_PSEUDO_REGISTER];
 
 /* Indicate if reg_reloaded_insn / reg_reloaded_contents is valid.  */
 static HARD_REG_SET reg_reloaded_valid;
@@ -142,7 +151,7 @@ static rtx spill_reg_rtx[FIRST_PSEUDO_REGISTER];
 /* In parallel with spill_regs, contains nonzero for a spill reg
    that was stored after the last time it was used.
    The precise value is the insn generated to do the store.  */
-static rtx spill_reg_store[FIRST_PSEUDO_REGISTER];
+static rtx_insn *spill_reg_store[FIRST_PSEUDO_REGISTER];
 
 /* This is the register that was stored with spill_reg_store.  This is a
    copy of reload_out / reload_out_reg when the value was stored; if
@@ -328,7 +337,7 @@ static int first_label_num;
 static char *offsets_known_at;
 static HOST_WIDE_INT (*offsets_at)[NUM_ELIMINABLE_REGS];
 
-VEC(reg_equivs_t,gc) *reg_equivs;
+vec<reg_equivs_t, va_gc> *reg_equivs;
 
 /* Stack of addresses where an rtx has been changed.  We can undo the 
    changes by popping items off the stack and restoring the original
@@ -341,15 +350,13 @@ VEC(reg_equivs_t,gc) *reg_equivs;
    rtx expression would be changed.  See PR 42431.  */
 
 typedef rtx *rtx_p;
-DEF_VEC_P(rtx_p);
-DEF_VEC_ALLOC_P(rtx_p,heap);
-static VEC(rtx_p,heap) *substitute_stack;
+static vec<rtx_p> substitute_stack;
 
 /* Number of labels in the current function.  */
 
 static int num_labels;
 \f
-static void replace_pseudos_in (rtx *, enum machine_mode, rtx);
+static void replace_pseudos_in (rtx *, machine_mode, rtx);
 static void maybe_fix_stack_asms (void);
 static void copy_reloads (struct insn_chain *);
 static void calculate_needs_all_insns (int);
@@ -358,26 +365,27 @@ 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 spill_failure (rtx_insn *, enum reg_class);
 static void count_spilled_pseudo (int, int, int);
-static void delete_dead_insn (rtx);
+static void delete_dead_insn (rtx_insn *);
 static void alter_reg (int, int, bool);
-static void set_label_offsets (rtx, rtx, int);
+static void set_label_offsets (rtx, rtx_insn *, int);
 static void check_eliminable_occurrences (rtx);
-static void elimination_effects (rtx, enum machine_mode);
-static rtx eliminate_regs_1 (rtx, enum machine_mode, rtx, bool, bool);
-static int eliminate_regs_in_insn (rtx, int);
+static void elimination_effects (rtx, machine_mode);
+static rtx eliminate_regs_1 (rtx, machine_mode, rtx, bool, bool);
+static int eliminate_regs_in_insn (rtx_insn *, int);
 static void update_eliminable_offsets (void);
 static void mark_not_eliminable (rtx, const_rtx, void *);
 static void set_initial_elim_offsets (void);
 static bool verify_initial_elim_offsets (void);
 static void set_initial_label_offsets (void);
-static void set_offsets_for_label (rtx);
-static void init_eliminable_invariants (rtx, bool);
+static void set_offsets_for_label (rtx_insn *);
+static void init_eliminable_invariants (rtx_insn *, bool);
 static void init_elim_table (void);
 static void free_reg_equiv (void);
 static void update_eliminables (HARD_REG_SET *);
-static void elimination_costs_in_insn (rtx);
+static bool update_eliminables_and_spill (void);
+static void elimination_costs_in_insn (rtx_insn *);
 static void spill_hard_reg (unsigned int, int);
 static int finish_spills (int);
 static void scan_paradoxical_subregs (rtx);
@@ -388,17 +396,17 @@ static void forget_old_reloads_1 (rtx, const_rtx, void *);
 static void forget_marked_reloads (regset);
 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);
+                                   machine_mode);
 static void clear_reload_reg_in_use (unsigned int, int, enum reload_type,
-                                    enum machine_mode);
+                                    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,
+static int free_for_value_p (int, machine_mode, int, enum reload_type,
                             rtx, rtx, int, int);
 static int allocate_reload_reg (struct insn_chain *, int, int);
 static int conflicts_with_override (rtx);
-static void failed_reload (rtx, int);
+static void failed_reload (rtx_insn *, 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 *);
@@ -409,18 +417,18 @@ static void emit_output_reload_insns (struct insn_chain *, struct reload *,
 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, rtx);
-static void delete_address_reloads (rtx, rtx);
-static void delete_address_reloads_1 (rtx, rtx, rtx);
+static void delete_output_reload (rtx_insn *, int, int, rtx);
+static void delete_address_reloads (rtx_insn *, rtx_insn *);
+static void delete_address_reloads_1 (rtx_insn *, rtx, rtx_insn *);
 static void inc_for_reload (rtx, rtx, rtx, int);
 #ifdef AUTO_INC_DEC
-static void add_auto_inc_notes (rtx, rtx);
+static void add_auto_inc_notes (rtx_insn *, rtx);
 #endif
 static void substitute (rtx *, const_rtx, rtx);
 static bool gen_reload_chain_without_interm_reg_p (int, int);
 static int reloads_conflict (int, int);
-static rtx gen_reload (rtx, rtx, int, enum reload_type);
-static rtx emit_insn_if_valid_for_reload (rtx);
+static rtx_insn *gen_reload (rtx, rtx, int, enum reload_type);
+static rtx_insn *emit_insn_if_valid_for_reload (rtx);
 \f
 /* Initialize the reload pass.  This is called at the beginning of compilation
    and may be called again if the target is reinitialized.  */
@@ -439,7 +447,7 @@ init_reload (void)
                   gen_rtx_PLUS (Pmode,
                                 gen_rtx_REG (Pmode,
                                              LAST_VIRTUAL_REGISTER + 1),
-                                GEN_INT (4)));
+                                gen_int_mode (4, Pmode)));
   spill_indirect_levels = 0;
 
   while (memory_address_p (QImode, tem))
@@ -462,7 +470,7 @@ init_reload (void)
                          gen_rtx_REG (Pmode, i));
 
       /* This way, we make sure that reg+reg is an offsettable address.  */
-      tem = plus_constant (tem, 4);
+      tem = plus_constant (Pmode, tem, 4);
 
       if (memory_address_p (QImode, tem))
        {
@@ -472,8 +480,11 @@ init_reload (void)
     }
 
   /* Initialize obstack for our rtl allocation.  */
-  gcc_obstack_init (&reload_obstack);
-  reload_startobj = XOBNEWVAR (&reload_obstack, char, 0);
+  if (reload_startobj == NULL)
+    {
+      gcc_obstack_init (&reload_obstack);
+      reload_startobj = XOBNEWVAR (&reload_obstack, char, 0);
+    }
 
   INIT_REG_SET (&spilled_pseudos);
   INIT_REG_SET (&changed_allocation_pseudos);
@@ -537,7 +548,7 @@ compute_use_by_pseudos (HARD_REG_SET *to, regset from)
    equivalences.  */
 
 static void
-replace_pseudos_in (rtx *loc, enum machine_mode mem_mode, rtx usage)
+replace_pseudos_in (rtx *loc, machine_mode mem_mode, rtx usage)
 {
   rtx x = *loc;
   enum rtx_code code;
@@ -611,14 +622,14 @@ has_nonexceptional_receiver (void)
     return true;
 
   /* First determine which blocks can reach exit via normal paths.  */
-  tos = worklist = XNEWVEC (basic_block, n_basic_blocks + 1);
+  tos = worklist = XNEWVEC (basic_block, n_basic_blocks_for_fn (cfun) + 1);
 
-  FOR_EACH_BB (bb)
+  FOR_EACH_BB_FN (bb, cfun)
     bb->flags &= ~BB_REACHABLE;
 
   /* Place the exit block on our worklist.  */
-  EXIT_BLOCK_PTR->flags |= BB_REACHABLE;
-  *tos++ = EXIT_BLOCK_PTR;
+  EXIT_BLOCK_PTR_FOR_FN (cfun)->flags |= BB_REACHABLE;
+  *tos++ = EXIT_BLOCK_PTR_FOR_FN (cfun);
 
   /* Iterate: find everything reachable from what we've already seen.  */
   while (tos != worklist)
@@ -641,7 +652,7 @@ has_nonexceptional_receiver (void)
 
   /* Now see if there's a reachable block with an exceptional incoming
      edge.  */
-  FOR_EACH_BB (bb)
+  FOR_EACH_BB_FN (bb, cfun)
     if (bb->flags & BB_REACHABLE && bb_has_abnormal_pred (bb))
       return true;
 
@@ -656,17 +667,15 @@ has_nonexceptional_receiver (void)
 void
 grow_reg_equivs (void)
 {
-  int old_size = VEC_length (reg_equivs_t, reg_equivs);
+  int old_size = vec_safe_length (reg_equivs);
   int max_regno = max_reg_num ();
   int i;
+  reg_equivs_t ze;
 
-  VEC_reserve (reg_equivs_t, gc, reg_equivs, max_regno);
+  memset (&ze, 0, sizeof (reg_equivs_t));
+  vec_safe_reserve (reg_equivs, max_regno);
   for (i = old_size; i < max_regno; i++)
-    {
-      VEC_quick_insert (reg_equivs_t, reg_equivs, i, 0);
-      memset (VEC_index (reg_equivs_t, reg_equivs, i), 0, sizeof (reg_equivs_t));
-    }
-    
+    reg_equivs->quick_insert (i, ze);
 }
 
 \f
@@ -688,6 +697,65 @@ static int failure;
 /* Temporary array of pseudo-register number.  */
 static int *temp_pseudo_reg_arr;
 
+/* If a pseudo has no hard reg, delete the insns that made the equivalence.
+   If that insn didn't set the register (i.e., it copied the register to
+   memory), just delete that insn instead of the equivalencing insn plus
+   anything now dead.  If we call delete_dead_insn on that insn, we may
+   delete the insn that actually sets the register if the register dies
+   there and that is incorrect.  */
+static void
+remove_init_insns ()
+{
+  for (int i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
+    {
+      if (reg_renumber[i] < 0 && reg_equiv_init (i) != 0)
+       {
+         rtx list;
+         for (list = reg_equiv_init (i); list; list = XEXP (list, 1))
+           {
+             rtx_insn *equiv_insn = as_a <rtx_insn *> (XEXP (list, 0));
+
+             /* If we already deleted the insn or if it may trap, we can't
+                delete it.  The latter case shouldn't happen, but can
+                if an insn has a variable address, gets a REG_EH_REGION
+                note added to it, and then gets converted into a load
+                from a constant address.  */
+             if (NOTE_P (equiv_insn)
+                 || can_throw_internal (equiv_insn))
+               ;
+             else if (reg_set_p (regno_reg_rtx[i], PATTERN (equiv_insn)))
+               delete_dead_insn (equiv_insn);
+             else
+               SET_INSN_DELETED (equiv_insn);
+           }
+       }
+    }
+}
+
+/* Return true if remove_init_insns will delete INSN.  */
+static bool
+will_delete_init_insn_p (rtx_insn *insn)
+{
+  rtx set = single_set (insn);
+  if (!set || !REG_P (SET_DEST (set)))
+    return false;
+  unsigned regno = REGNO (SET_DEST (set));
+
+  if (can_throw_internal (insn))
+    return false;
+
+  if (regno < FIRST_PSEUDO_REGISTER || reg_renumber[regno] >= 0)
+    return false;
+
+  for (rtx list = reg_equiv_init (regno); list; list = XEXP (list, 1))
+    {
+      rtx equiv_insn = XEXP (list, 0);
+      if (equiv_insn == insn)
+       return true;
+    }
+  return false;
+}
+
 /* Main entry point for the reload pass.
 
    FIRST is the first insn of the function being compiled.
@@ -703,10 +771,10 @@ static int *temp_pseudo_reg_arr;
    return value is FALSE.  */
 
 bool
-reload (rtx first, int global)
+reload (rtx_insn *first, int global)
 {
   int i, n;
-  rtx insn;
+  rtx_insn *insn;
   struct elim_table *ep;
   basic_block bb;
   bool inserted;
@@ -768,7 +836,6 @@ reload (rtx first, int global)
      be substituted eventually by altering the REG-rtx's.  */
 
   grow_reg_equivs ();
-  reg_max_ref_width = XCNEWVEC (unsigned int, max_regno);
   reg_old_renumber = XCNEWVEC (short, max_regno);
   memcpy (reg_old_renumber, reg_renumber, max_regno * sizeof (short));
   pseudo_forbidden_regs = XNEWVEC (HARD_REG_SET, max_regno);
@@ -917,9 +984,6 @@ reload (rtx first, int global)
       if (caller_save_needed)
        setup_save_areas ();
 
-      /* If we allocated another stack slot, redo elimination bookkeeping.  */
-      if (something_was_spilled || starting_frame_size != get_frame_size ())
-       continue;
       if (starting_frame_size && crtl->stack_alignment_needed)
        {
          /* If we have a stack frame, we must align it now.  The
@@ -931,8 +995,12 @@ reload (rtx first, int global)
             STARTING_FRAME_OFFSET not be already aligned to
             STACK_BOUNDARY.  */
          assign_stack_local (BLKmode, 0, crtl->stack_alignment_needed);
-         if (starting_frame_size != get_frame_size ())
-           continue;
+       }
+      /* If we allocated another stack slot, redo elimination bookkeeping.  */
+      if (something_was_spilled || starting_frame_size != get_frame_size ())
+       {
+         update_eliminables_and_spill ();
+         continue;
        }
 
       if (caller_save_needed)
@@ -966,30 +1034,11 @@ reload (rtx first, int global)
       else if (!verify_initial_elim_offsets ())
        something_changed = 1;
 
-      {
-       HARD_REG_SET to_spill;
-       CLEAR_HARD_REG_SET (to_spill);
-       update_eliminables (&to_spill);
-       AND_COMPL_HARD_REG_SET (used_spill_regs, to_spill);
-
-       for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
-         if (TEST_HARD_REG_BIT (to_spill, i))
-           {
-             spill_hard_reg (i, 1);
-             did_spill = 1;
-
-             /* Regardless of the state of spills, if we previously had
-                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
-                reference an eliminable register.  We must make another pass
-                to update reg_equiv_* so that we do not substitute in the
-                old value from when we thought the elimination could be
-                performed.  */
-             something_changed = 1;
-           }
-      }
+      if (update_eliminables_and_spill ())
+       {
+         did_spill = 1;
+         something_changed = 1;
+       }
 
       select_reload_regs ();
       if (failure)
@@ -1014,37 +1063,7 @@ reload (rtx first, int global)
       if (ep->can_eliminate)
        mark_elimination (ep->from, ep->to);
 
-  /* If a pseudo has no hard reg, delete the insns that made the equivalence.
-     If that insn didn't set the register (i.e., it copied the register to
-     memory), just delete that insn instead of the equivalencing insn plus
-     anything now dead.  If we call delete_dead_insn on that insn, we may
-     delete the insn that actually sets the register if the register dies
-     there and that is incorrect.  */
-
-  for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
-    {
-      if (reg_renumber[i] < 0 && reg_equiv_init (i) != 0)
-       {
-         rtx list;
-         for (list = reg_equiv_init (i); list; list = XEXP (list, 1))
-           {
-             rtx equiv_insn = XEXP (list, 0);
-
-             /* If we already deleted the insn or if it may trap, we can't
-                delete it.  The latter case shouldn't happen, but can
-                if an insn has a variable address, gets a REG_EH_REGION
-                note added to it, and then gets converted into a load
-                from a constant address.  */
-             if (NOTE_P (equiv_insn)
-                 || can_throw_internal (equiv_insn))
-               ;
-             else if (reg_set_p (regno_reg_rtx[i], PATTERN (equiv_insn)))
-               delete_dead_insn (equiv_insn);
-             else
-               SET_INSN_DELETED (equiv_insn);
-           }
-       }
-    }
+  remove_init_insns ();
 
   /* Use the reload registers where necessary
      by generating move instructions to move the must-be-register
@@ -1069,7 +1088,7 @@ reload (rtx first, int global)
      pseudo.  */
 
   if (! frame_pointer_needed)
-    FOR_EACH_BB (bb)
+    FOR_EACH_BB_FN (bb, cfun)
       bitmap_clear_bit (df_get_live_in (bb), HARD_FRAME_POINTER_REGNUM);
 
   /* Come here (with failure set nonzero) if we can't get enough spill
@@ -1112,10 +1131,7 @@ reload (rtx first, int global)
              if (reg_equiv_memory_loc (i))
                MEM_COPY_ATTRIBUTES (reg, reg_equiv_memory_loc (i));
              else
-               {
-                 MEM_IN_STRUCT_P (reg) = MEM_SCALAR_P (reg) = 0;
-                 MEM_ATTRS (reg) = 0;
-               }
+               MEM_ATTRS (reg) = 0;
              MEM_NOTRAP_P (reg) = 1;
            }
          else if (reg_equiv_mem (i))
@@ -1251,7 +1267,7 @@ reload (rtx first, int global)
        if (asm_noperands (PATTERN (insn)) >= 0)
          {
            extract_insn (insn);
-           if (!constrain_operands (1))
+           if (!constrain_operands (1, get_enabled_alternatives (insn)))
              {
                error_for_asm (insn,
                               "%<asm%> operand has impossible constraints");
@@ -1307,8 +1323,8 @@ reload (rtx first, int global)
   if (cfun->can_throw_non_call_exceptions)
     {
       sbitmap blocks;
-      blocks = sbitmap_alloc (last_basic_block);
-      sbitmap_ones (blocks);
+      blocks = sbitmap_alloc (last_basic_block_for_fn (cfun));
+      bitmap_ones (blocks);
       find_many_sub_basic_blocks (blocks);
       sbitmap_free (blocks);
     }
@@ -1329,7 +1345,7 @@ reload (rtx first, int global)
     REGNO_POINTER_ALIGN (HARD_FRAME_POINTER_REGNUM) = BITS_PER_UNIT;
 #endif
 
-  VEC_free (rtx_p, heap, substitute_stack);
+  substitute_stack.release ();
 
   gcc_assert (bitmap_empty_p (&spilled_pseudos));
 
@@ -1350,7 +1366,7 @@ maybe_fix_stack_asms (void)
 {
 #ifdef STACK_REGS
   const char *constraints[MAX_RECOG_OPERANDS];
-  enum machine_mode operand_mode[MAX_RECOG_OPERANDS];
+  machine_mode operand_mode[MAX_RECOG_OPERANDS];
   struct insn_chain *chain;
 
   for (chain = reload_insn_chain; chain != 0; chain = chain->next)
@@ -1412,33 +1428,20 @@ maybe_fix_stack_asms (void)
 
              switch (c)
                {
-               case '=': case '+': case '*': case '%': case '?': case '!':
-               case '0': case '1': case '2': case '3': case '4': case '<':
-               case '>': case 'V': case 'o': case '&': case 'E': case 'F':
-               case 's': case 'i': case 'n': case 'X': case 'I': case 'J':
-               case 'K': case 'L': case 'M': case 'N': case 'O': case 'P':
-               case TARGET_MEM_CONSTRAINT:
-                 break;
-
-               case 'p':
-                 cls = (int) reg_class_subunion[cls]
-                     [(int) base_reg_class (VOIDmode, ADDR_SPACE_GENERIC,
-                                            ADDRESS, SCRATCH)];
-                 break;
-
                case 'g':
-               case 'r':
                  cls = (int) reg_class_subunion[cls][(int) GENERAL_REGS];
                  break;
 
                default:
-                 if (EXTRA_ADDRESS_CONSTRAINT (c, p))
+                 enum constraint_num cn = lookup_constraint (p);
+                 if (insn_extra_address_constraint (cn))
                    cls = (int) reg_class_subunion[cls]
                      [(int) base_reg_class (VOIDmode, ADDR_SPACE_GENERIC,
                                             ADDRESS, SCRATCH)];
                  else
                    cls = (int) reg_class_subunion[cls]
-                     [(int) REG_CLASS_FROM_CONSTRAINT (c, p)];
+                     [reg_class_for_constraint (cn)];
+                 break;
                }
              p += CONSTRAINT_LEN (c, p);
            }
@@ -1483,7 +1486,7 @@ calculate_needs_all_insns (int global)
   reload_insn_firstobj = XOBNEWVAR (&reload_obstack, char, 0);
   for (chain = reload_insn_chain; chain != 0; chain = next)
     {
-      rtx insn = chain->insn;
+      rtx_insn *insn = chain->insn;
 
       next = chain->next;
 
@@ -1497,7 +1500,7 @@ calculate_needs_all_insns (int global)
         include REG_LABEL_OPERAND and REG_LABEL_TARGET), we need to see
         what effects this has on the known offsets at labels.  */
 
-      if (LABEL_P (insn) || JUMP_P (insn)
+      if (LABEL_P (insn) || JUMP_P (insn) || JUMP_TABLE_DATA_P (insn)
          || (INSN_P (insn) && REG_NOTES (insn) != 0))
        set_label_offsets (insn, insn, 0);
 
@@ -1508,14 +1511,9 @@ calculate_needs_all_insns (int global)
          rtx old_notes = REG_NOTES (insn);
          int did_elimination = 0;
          int operands_changed = 0;
-         rtx set = single_set (insn);
 
          /* Skip insns that only set an equivalence.  */
-         if (set && REG_P (SET_DEST (set))
-             && reg_renumber[REGNO (SET_DEST (set))] < 0
-             && (reg_equiv_constant (REGNO (SET_DEST (set)))
-                 || (reg_equiv_invariant (REGNO (SET_DEST (set)))))
-                     && reg_equiv_init (REGNO (SET_DEST (set))))
+         if (will_delete_init_insn_p (insn))
            continue;
 
          /* If needed, eliminate any eliminable registers.  */
@@ -1616,9 +1614,9 @@ calculate_elim_costs_all_insns (void)
   set_initial_elim_offsets ();
   set_initial_label_offsets ();
 
-  FOR_EACH_BB (bb)
+  FOR_EACH_BB_FN (bb, cfun)
     {
-      rtx insn;
+      rtx_insn *insn;
       elim_bb = bb;
 
       FOR_BB_INSNS (bb, insn)
@@ -1627,7 +1625,7 @@ calculate_elim_costs_all_insns (void)
             include REG_LABEL_OPERAND and REG_LABEL_TARGET), we need to see
             what effects this has on the known offsets at labels.  */
 
-         if (LABEL_P (insn) || JUMP_P (insn)
+         if (LABEL_P (insn) || JUMP_P (insn) || JUMP_TABLE_DATA_P (insn)
              || (INSN_P (insn) && REG_NOTES (insn) != 0))
            set_label_offsets (insn, insn, 0);
 
@@ -1688,6 +1686,10 @@ calculate_elim_costs_all_insns (void)
     }
 
   free (reg_equiv_init_cost);
+  free (offsets_known_at);
+  free (offsets_at);
+  offsets_at = NULL;
+  offsets_known_at = NULL;
 }
 \f
 /* Comparison function for qsort to decide which of two reloads
@@ -1746,11 +1748,12 @@ count_pseudo (int reg)
   int r = reg_renumber[reg];
   int nregs;
 
+  /* Ignore spilled pseudo-registers which can be here only if IRA is used.  */
+  if (ira_conflicts_p && r < 0)
+    return;
+
   if (REGNO_REG_SET_P (&pseudos_counted, reg)
-      || REGNO_REG_SET_P (&spilled_pseudos, reg)
-      /* Ignore spilled pseudo-registers which can be here only if IRA
-        is used.  */
-      || (ira_conflicts_p && r < 0))
+      || REGNO_REG_SET_P (&spilled_pseudos, reg))
     return;
 
   SET_REGNO_REG_SET (&pseudos_counted, reg);
@@ -1827,12 +1830,17 @@ count_spilled_pseudo (int spilled, int spilled_nregs, int reg)
 {
   int freq = REG_FREQ (reg);
   int r = reg_renumber[reg];
-  int nregs = hard_regno_nregs[r][PSEUDO_REGNO_MODE (reg)];
+  int nregs;
+
+  /* Ignore spilled pseudo-registers which can be here only if IRA is used.  */
+  if (ira_conflicts_p && r < 0)
+    return;
 
-  /* Ignore spilled pseudo-registers which can be here only if IRA is
-     used.  */
-  if ((ira_conflicts_p && r < 0)
-      || REGNO_REG_SET_P (&spilled_pseudos, reg)
+  gcc_assert (r >= 0);
+
+  nregs = hard_regno_nregs[r][PSEUDO_REGNO_MODE (reg)];
+
+  if (REGNO_REG_SET_P (&spilled_pseudos, reg)
       || spilled + spilled_nregs <= r || r + nregs <= spilled)
     return;
 
@@ -2078,7 +2086,7 @@ delete_caller_save_insns (void)
       while (c != 0 && c->is_caller_save_insn)
        {
          struct insn_chain *next = c->next;
-         rtx insn = c->insn;
+         rtx_insn *insn = c->insn;
 
          if (c == reload_insn_chain)
            reload_insn_chain = next;
@@ -2101,7 +2109,7 @@ delete_caller_save_insns (void)
    INSN should be one of the insns which needed this particular spill reg.  */
 
 static void
-spill_failure (rtx insn, enum reg_class rclass)
+spill_failure (rtx_insn *insn, enum reg_class rclass)
 {
   if (asm_noperands (PATTERN (insn)) >= 0)
     error_for_asm (insn, "can%'t find a register in class %qs while "
@@ -2125,9 +2133,9 @@ spill_failure (rtx insn, enum reg_class rclass)
    data that is dead in INSN.  */
 
 static void
-delete_dead_insn (rtx insn)
+delete_dead_insn (rtx_insn *insn)
 {
-  rtx prev = prev_active_insn (insn);
+  rtx_insn *prev = prev_active_insn (insn);
   rtx prev_dest;
 
   /* If the previous insn sets a register that dies in our insn make
@@ -2137,7 +2145,8 @@ delete_dead_insn (rtx insn)
      block local equivalences.  Instead of trying to figure out the exact
      circumstances where we can delete the potentially dead insns, just
      let DCE do the job.  */
-  if (prev && GET_CODE (PATTERN (prev)) == SET
+  if (prev && BLOCK_FOR_INSN (prev) == BLOCK_FOR_INSN (insn)
+      && GET_CODE (PATTERN (prev)) == SET
       && (prev_dest = SET_DEST (PATTERN (prev)), REG_P (prev_dest))
       && reg_mentioned_p (prev_dest, PATTERN (insn))
       && find_regno_note (insn, REG_DEAD, REGNO (prev_dest))
@@ -2184,7 +2193,7 @@ alter_reg (int i, int from_reg, bool dont_share_p)
       && reg_equiv_memory_loc (i) == 0)
     {
       rtx x = NULL_RTX;
-      enum machine_mode mode = GET_MODE (regno_reg_rtx[i]);
+      machine_mode mode = GET_MODE (regno_reg_rtx[i]);
       unsigned int inherent_size = PSEUDO_REGNO_BYTES (i);
       unsigned int inherent_align = GET_MODE_ALIGNMENT (mode);
       unsigned int total_size = MAX (inherent_size, reg_max_ref_width[i]);
@@ -2313,7 +2322,7 @@ alter_reg (int i, int from_reg, bool dont_share_p)
    pseudo-reg number REGNO, accessed in MODE.  */
 
 static void
-mark_home_live_1 (int regno, enum machine_mode mode)
+mark_home_live_1 (int regno, machine_mode mode)
 {
   int i, lim;
 
@@ -2322,7 +2331,7 @@ mark_home_live_1 (int regno, enum machine_mode mode)
     return;
   lim = end_hard_regno (mode, i);
   while (i < lim)
-    df_set_regs_ever_live(i++, true);
+    df_set_regs_ever_live (i++, true);
 }
 
 /* Mark the slots in regs_ever_live for the hard regs
@@ -2346,7 +2355,7 @@ mark_home_live (int regno)
    current offset.  */
 
 static void
-set_label_offsets (rtx x, rtx insn, int initial_p)
+set_label_offsets (rtx x, rtx_insn *insn, int initial_p)
 {
   enum rtx_code code = GET_CODE (x);
   rtx tem;
@@ -2359,7 +2368,7 @@ set_label_offsets (rtx x, rtx insn, int initial_p)
       if (LABEL_REF_NONLOCAL_P (x))
        return;
 
-      x = XEXP (x, 0);
+      x = LABEL_REF_LABEL (x);
 
       /* ... fall through ...  */
 
@@ -2401,6 +2410,10 @@ set_label_offsets (rtx x, rtx insn, int initial_p)
 
       return;
 
+    case JUMP_TABLE_DATA:
+      set_label_offsets (PATTERN (insn), insn, initial_p);
+      return;
+
     case JUMP_INSN:
       set_label_offsets (PATTERN (insn), insn, initial_p);
 
@@ -2457,13 +2470,13 @@ set_label_offsets (rtx x, rtx insn, int initial_p)
        case IF_THEN_ELSE:
          tem = XEXP (SET_SRC (x), 1);
          if (GET_CODE (tem) == LABEL_REF)
-           set_label_offsets (XEXP (tem, 0), insn, initial_p);
+           set_label_offsets (LABEL_REF_LABEL (tem), insn, initial_p);
          else if (GET_CODE (tem) != PC && GET_CODE (tem) != RETURN)
            break;
 
          tem = XEXP (SET_SRC (x), 2);
          if (GET_CODE (tem) == LABEL_REF)
-           set_label_offsets (XEXP (tem, 0), insn, initial_p);
+           set_label_offsets (LABEL_REF_LABEL (tem), insn, initial_p);
          else if (GET_CODE (tem) != PC && GET_CODE (tem) != RETURN)
            break;
          return;
@@ -2484,34 +2497,33 @@ set_label_offsets (rtx x, rtx insn, int initial_p)
     }
 }
 \f
-/* Called through for_each_rtx, this function examines every reg that occurs
-   in PX and adjusts the costs for its elimination which are gathered by IRA.
-   DATA is the insn in which PX occurs.  We do not recurse into MEM
-   expressions.  */
+/* This function examines every reg that occurs in X and adjusts the
+   costs for its elimination which are gathered by IRA.  INSN is the
+   insn in which X occurs.  We do not recurse into MEM expressions.  */
 
-static int
-note_reg_elim_costly (rtx *px, void *data)
+static void
+note_reg_elim_costly (const_rtx x, rtx insn)
 {
-  rtx insn = (rtx)data;
-  rtx x = *px;
-
-  if (MEM_P (x))
-    return -1;
-
-  if (REG_P (x)
-      && REGNO (x) >= FIRST_PSEUDO_REGISTER
-      && reg_equiv_init (REGNO (x))
-      && reg_equiv_invariant (REGNO (x)))
-    {
-      rtx t = reg_equiv_invariant (REGNO (x));
-      rtx new_rtx = eliminate_regs_1 (t, Pmode, insn, true, true);
-      int cost = set_src_cost (new_rtx, optimize_bb_for_speed_p (elim_bb));
-      int freq = REG_FREQ_FROM_BB (elim_bb);
+  subrtx_iterator::array_type array;
+  FOR_EACH_SUBRTX (iter, array, x, NONCONST)
+    {
+      const_rtx x = *iter;
+      if (MEM_P (x))
+       iter.skip_subrtxes ();
+      else if (REG_P (x)
+              && REGNO (x) >= FIRST_PSEUDO_REGISTER
+              && reg_equiv_init (REGNO (x))
+              && reg_equiv_invariant (REGNO (x)))
+       {
+         rtx t = reg_equiv_invariant (REGNO (x));
+         rtx new_rtx = eliminate_regs_1 (t, Pmode, insn, true, true);
+         int cost = set_src_cost (new_rtx, optimize_bb_for_speed_p (elim_bb));
+         int freq = REG_FREQ_FROM_BB (elim_bb);
 
-      if (cost != 0)
-       ira_adjust_equiv_reg_cost (REGNO (x), -cost * freq);
+         if (cost != 0)
+           ira_adjust_equiv_reg_cost (REGNO (x), -cost * freq);
+       }
     }
-  return 0;
 }
 
 /* Scan X and replace any eliminable registers (such as fp) with a
@@ -2543,7 +2555,7 @@ note_reg_elim_costly (rtx *px, void *data)
    the proper thing.  */
 
 static rtx
-eliminate_regs_1 (rtx x, enum machine_mode mem_mode, rtx insn,
+eliminate_regs_1 (rtx x, machine_mode mem_mode, rtx insn,
                  bool may_use_invariant, bool for_costs)
 {
   enum rtx_code code = GET_CODE (x);
@@ -2559,10 +2571,7 @@ eliminate_regs_1 (rtx x, enum machine_mode mem_mode, rtx insn,
 
   switch (code)
     {
-    case CONST_INT:
-    case CONST_DOUBLE:
-    case CONST_FIXED:
-    case CONST_VECTOR:
+    CASE_CONST_ANY:
     case CONST:
     case SYMBOL_REF:
     case CODE_LABEL:
@@ -2584,7 +2593,7 @@ eliminate_regs_1 (rtx x, enum machine_mode mem_mode, rtx insn,
          for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS];
               ep++)
            if (ep->from_rtx == x && ep->can_eliminate)
-             return plus_constant (ep->to_rtx, ep->previous_offset);
+             return plus_constant (Pmode, ep->to_rtx, ep->previous_offset);
 
        }
       else if (reg_renumber && reg_renumber[regno] < 0
@@ -2640,7 +2649,7 @@ eliminate_regs_1 (rtx x, enum machine_mode mem_mode, rtx insn,
                  return ep->to_rtx;
                else
                  return gen_rtx_PLUS (Pmode, ep->to_rtx,
-                                      plus_constant (XEXP (x, 1),
+                                      plus_constant (Pmode, XEXP (x, 1),
                                                      ep->previous_offset));
              }
 
@@ -2717,7 +2726,8 @@ eliminate_regs_1 (rtx x, enum machine_mode mem_mode, rtx insn,
                ep->ref_outside_mem = 1;
 
              return
-               plus_constant (gen_rtx_MULT (Pmode, ep->to_rtx, XEXP (x, 1)),
+               plus_constant (Pmode,
+                              gen_rtx_MULT (Pmode, ep->to_rtx, XEXP (x, 1)),
                               ep->previous_offset * INTVAL (XEXP (x, 1)));
            }
 
@@ -2771,6 +2781,7 @@ eliminate_regs_1 (rtx x, enum machine_mode mem_mode, rtx insn,
       /* ... fall through ...  */
 
     case INSN_LIST:
+    case INT_LIST:
       /* Now do eliminations in the rest of the chain.  If this was
         an EXPR_LIST, this might result in allocating more memory than is
         strictly needed, but it simplifies the code.  */
@@ -2887,7 +2898,7 @@ eliminate_regs_1 (rtx x, enum machine_mode mem_mode, rtx insn,
       if (for_costs
          && memory_address_p (GET_MODE (x), XEXP (x, 0))
          && !memory_address_p (GET_MODE (x), new_rtx))
-       for_each_rtx (&XEXP (x, 0), note_reg_elim_costly, insn);
+       note_reg_elim_costly (XEXP (x, 0), insn);
 
       return replace_equiv_address_nv (x, new_rtx);
 
@@ -2955,8 +2966,13 @@ eliminate_regs_1 (rtx x, enum machine_mode mem_mode, rtx insn,
 }
 
 rtx
-eliminate_regs (rtx x, enum machine_mode mem_mode, rtx insn)
+eliminate_regs (rtx x, machine_mode mem_mode, rtx insn)
 {
+  if (reg_eliminate == NULL)
+    {
+      gcc_assert (targetm.no_register_allocation);
+      return x;
+    }
   return eliminate_regs_1 (x, mem_mode, insn, false, false);
 }
 
@@ -2965,7 +2981,7 @@ eliminate_regs (rtx x, enum machine_mode mem_mode, rtx insn)
    the mode of an enclosing MEM rtx, or VOIDmode if not within a MEM.  */
 
 static void
-elimination_effects (rtx x, enum machine_mode mem_mode)
+elimination_effects (rtx x, machine_mode mem_mode)
 {
   enum rtx_code code = GET_CODE (x);
   struct elim_table *ep;
@@ -2975,10 +2991,7 @@ elimination_effects (rtx x, enum machine_mode mem_mode)
 
   switch (code)
     {
-    case CONST_INT:
-    case CONST_DOUBLE:
-    case CONST_FIXED:
-    case CONST_VECTOR:
+    CASE_CONST_ANY:
     case CONST:
     case SYMBOL_REF:
     case CODE_LABEL:
@@ -3008,7 +3021,7 @@ elimination_effects (rtx x, enum machine_mode mem_mode)
 
        }
       else if (reg_renumber[regno] < 0
-              && reg_equivs != 0
+              && reg_equivs
               && reg_equiv_constant (regno)
               && ! function_invariant_p (reg_equiv_constant (regno)))
        elimination_effects (reg_equiv_constant (regno), mem_mode);
@@ -3079,7 +3092,7 @@ elimination_effects (rtx x, enum machine_mode mem_mode)
       if (REG_P (SUBREG_REG (x))
          && (GET_MODE_SIZE (GET_MODE (x))
              <= GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))))
-         && reg_equivs != 0
+         && reg_equivs
          && reg_equiv_memory_loc (REGNO (SUBREG_REG (x))) != 0)
        return;
 
@@ -3220,7 +3233,7 @@ check_eliminable_occurrences (rtx x)
    is returned.  Otherwise, 1 is returned.  */
 
 static int
-eliminate_regs_in_insn (rtx insn, int replace)
+eliminate_regs_in_insn (rtx_insn *insn, int replace)
 {
   int icode = recog_memoized (insn);
   rtx old_body = PATTERN (insn);
@@ -3236,12 +3249,10 @@ eliminate_regs_in_insn (rtx insn, int replace)
 
   if (! insn_is_asm && icode < 0)
     {
-      gcc_assert (GET_CODE (PATTERN (insn)) == USE
+      gcc_assert (DEBUG_INSN_P (insn)
+                 || GET_CODE (PATTERN (insn)) == USE
                  || GET_CODE (PATTERN (insn)) == CLOBBER
-                 || GET_CODE (PATTERN (insn)) == ADDR_VEC
-                 || GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC
-                 || GET_CODE (PATTERN (insn)) == ASM_INPUT
-                 || DEBUG_INSN_P (insn));
+                 || GET_CODE (PATTERN (insn)) == ASM_INPUT);
       if (DEBUG_INSN_P (insn))
        INSN_VAR_LOCATION_LOC (insn)
          = eliminate_regs (INSN_VAR_LOCATION_LOC (insn), VOIDmode, insn);
@@ -3265,12 +3276,13 @@ eliminate_regs_in_insn (rtx insn, int replace)
                && ep->to == HARD_FRAME_POINTER_REGNUM)
              {
                rtx base = SET_SRC (old_set);
-               rtx base_insn = insn;
+               rtx_insn *base_insn = insn;
                HOST_WIDE_INT offset = 0;
 
                while (base != ep->to_rtx)
                  {
-                   rtx prev_insn, prev_set;
+                   rtx_insn *prev_insn;
+                   rtx prev_set;
 
                    if (GET_CODE (base) == PLUS
                        && CONST_INT_P (XEXP (base, 1)))
@@ -3291,8 +3303,8 @@ eliminate_regs_in_insn (rtx insn, int replace)
 
                if (base == ep->to_rtx)
                  {
-                   rtx src
-                     = plus_constant (ep->to_rtx, offset - ep->offset);
+                   rtx src = plus_constant (Pmode, ep->to_rtx,
+                                            offset - ep->offset);
 
                    new_body = old_body;
                    if (! replace)
@@ -3406,7 +3418,8 @@ eliminate_regs_in_insn (rtx insn, int replace)
               had a PLUS before.  */
            if (offset == 0 || plus_src)
              {
-               rtx new_src = plus_constant (to_rtx, offset);
+               rtx new_src = plus_constant (GET_MODE (to_rtx),
+                                            to_rtx, offset);
 
                new_body = old_body;
                if (! replace)
@@ -3631,7 +3644,7 @@ eliminate_regs_in_insn (rtx insn, int replace)
    an invariant equivalence would add extra cost.  */
 
 static void
-elimination_costs_in_insn (rtx insn)
+elimination_costs_in_insn (rtx_insn *insn)
 {
   int icode = recog_memoized (insn);
   rtx old_body = PATTERN (insn);
@@ -3646,12 +3659,10 @@ elimination_costs_in_insn (rtx insn)
 
   if (! insn_is_asm && icode < 0)
     {
-      gcc_assert (GET_CODE (PATTERN (insn)) == USE
+      gcc_assert (DEBUG_INSN_P (insn)
+                 || GET_CODE (PATTERN (insn)) == USE
                  || GET_CODE (PATTERN (insn)) == CLOBBER
-                 || GET_CODE (PATTERN (insn)) == ADDR_VEC
-                 || GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC
-                 || GET_CODE (PATTERN (insn)) == ASM_INPUT
-                 || DEBUG_INSN_P (insn));
+                 || GET_CODE (PATTERN (insn)) == ASM_INPUT);
       return;
     }
 
@@ -3736,7 +3747,7 @@ elimination_costs_in_insn (rtx insn)
          if (old_set && recog_data.operand_loc[i] == &SET_SRC (old_set))
            is_set_src = true;
          if (is_set_src && !sets_reg_p)
-           note_reg_elim_costly (&SET_SRC (old_set), insn);
+           note_reg_elim_costly (SET_SRC (old_set), insn);
          in_plus = false;
          if (plus_src && sets_reg_p
              && (recog_data.operand_loc[i] == &XEXP (plus_src, 0)
@@ -3900,7 +3911,7 @@ set_initial_elim_offsets (void)
 static void
 set_initial_eh_label_offset (rtx label)
 {
-  set_label_offsets (label, NULL_RTX, 1);
+  set_label_offsets (label, NULL, 1);
 }
 
 /* Initialize the known label offsets.
@@ -3913,16 +3924,15 @@ set_initial_eh_label_offset (rtx label)
 static void
 set_initial_label_offsets (void)
 {
-  rtx x;
   memset (offsets_known_at, 0, num_labels);
 
-  for (x = forced_labels; x; x = XEXP (x, 1))
-    if (XEXP (x, 0))
-      set_label_offsets (XEXP (x, 0), NULL_RTX, 1);
+  for (rtx_insn_list *x = forced_labels; x; x = x->next ())
+    if (x->insn ())
+      set_label_offsets (x->insn (), NULL, 1);
 
-  for (x = nonlocal_goto_handler_labels; x; x = XEXP (x, 1))
-    if (XEXP (x, 0))
-      set_label_offsets (XEXP (x, 0), NULL_RTX, 1);
+  for (rtx_insn_list *x = nonlocal_goto_handler_labels; x; x = x->next ())
+    if (x->insn ())
+      set_label_offsets (x->insn (), NULL, 1);
 
   for_each_eh_label (set_initial_eh_label_offset);
 }
@@ -3931,7 +3941,7 @@ set_initial_label_offsets (void)
    by INSN.  */
 
 static void
-set_offsets_for_label (rtx insn)
+set_offsets_for_label (rtx_insn *insn)
 {
   unsigned int i;
   int label_nr = CODE_LABEL_NUMBER (insn);
@@ -4031,6 +4041,38 @@ update_eliminables (HARD_REG_SET *pset)
     SET_HARD_REG_BIT (*pset, HARD_FRAME_POINTER_REGNUM);
 }
 
+/* Call update_eliminables an spill any registers we can't eliminate anymore.
+   Return true iff a register was spilled.  */
+
+static bool
+update_eliminables_and_spill (void)
+{
+  int i;
+  bool did_spill = false;
+  HARD_REG_SET to_spill;
+  CLEAR_HARD_REG_SET (to_spill);
+  update_eliminables (&to_spill);
+  AND_COMPL_HARD_REG_SET (used_spill_regs, to_spill);
+
+  for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+    if (TEST_HARD_REG_BIT (to_spill, i))
+      {
+       spill_hard_reg (i, 1);
+       did_spill = true;
+
+       /* Regardless of the state of spills, if we previously had
+          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
+          reference an eliminable register.  We must make another pass
+          to update reg_equiv_* so that we do not substitute in the
+          old value from when we thought the elimination could be
+          performed.  */
+      }
+  return did_spill;
+}
+
 /* Return true if X is used as the target register of an elimination.  */
 
 bool
@@ -4105,10 +4147,10 @@ init_elim_table (void)
    be substituted eventually by altering the REG-rtx's.  */
 
 static void
-init_eliminable_invariants (rtx first, bool do_subregs)
+init_eliminable_invariants (rtx_insn *first, bool do_subregs)
 {
   int i;
-  rtx insn;
+  rtx_insn *insn;
 
   grow_reg_equivs ();
   if (do_subregs)
@@ -4176,7 +4218,7 @@ init_eliminable_invariants (rtx first, bool do_subregs)
                }
              else if (function_invariant_p (x))
                {
-                 enum machine_mode mode;
+                 machine_mode mode;
 
                  mode = GET_MODE (SET_DEST (set));
                  if (GET_CODE (x) == PLUS)
@@ -4229,7 +4271,6 @@ free_reg_equiv (void)
 {
   int i;
 
-
   free (offsets_known_at);
   free (offsets_at);
   offsets_at = 0;
@@ -4238,9 +4279,7 @@ free_reg_equiv (void)
   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
     if (reg_equiv_alt_mem_list (i))
       free_EXPR_LIST_list (&reg_equiv_alt_mem_list (i));
-  VEC_free (reg_equivs_t, gc, reg_equivs);
-  reg_equivs = NULL;
-
+  vec_free (reg_equivs);
 }
 \f
 /* Kick all pseudos out of hard register REGNO.
@@ -4445,13 +4484,10 @@ scan_paradoxical_subregs (rtx x)
   switch (code)
     {
     case REG:
-    case CONST_INT:
     case CONST:
     case SYMBOL_REF:
     case LABEL_REF:
-    case CONST_DOUBLE:
-    case CONST_FIXED:
-    case CONST_VECTOR: /* shouldn't happen, but just in case.  */
+    CASE_CONST_ANY:
     case CC0:
     case PC:
     case USE:
@@ -4526,7 +4562,7 @@ strip_paradoxical_subreg (rtx *op_ptr, rtx *other_ptr)
    annotate all that may trap.  */
 
 static void
-fixup_eh_region_note (rtx insn, rtx prev, rtx next)
+fixup_eh_region_note (rtx_insn *insn, rtx_insn *prev, rtx_insn *next)
 {
   rtx note = find_reg_note (insn, REG_EH_REGION, NULL_RTX);
   if (note == NULL)
@@ -4552,7 +4588,7 @@ reload_as_needed (int live_known)
 #if defined (AUTO_INC_DEC)
   int i;
 #endif
-  rtx x, marker;
+  rtx_note *marker;
 
   memset (spill_reg_rtx, 0, sizeof spill_reg_rtx);
   memset (spill_reg_store, 0, sizeof spill_reg_store);
@@ -4569,13 +4605,16 @@ reload_as_needed (int live_known)
 
   for (chain = reload_insn_chain; chain; chain = chain->next)
     {
-      rtx prev = 0;
-      rtx insn = chain->insn;
-      rtx old_next = NEXT_INSN (insn);
+      rtx_insn *prev = 0;
+      rtx_insn *insn = chain->insn;
+      rtx_insn *old_next = NEXT_INSN (insn);
 #ifdef AUTO_INC_DEC
-      rtx old_prev = PREV_INSN (insn);
+      rtx_insn *old_prev = PREV_INSN (insn);
 #endif
 
+      if (will_delete_init_insn_p (insn))
+       continue;
+
       /* If we pass a label, copy the offsets from the label information
         into the current offsets of each elimination.  */
       if (LABEL_P (insn))
@@ -4636,8 +4675,7 @@ reload_as_needed (int live_known)
 
          if (n_reloads > 0)
            {
-             rtx next = NEXT_INSN (insn);
-             rtx p;
+             rtx_insn *next = NEXT_INSN (insn);
 
              /* ??? PREV can get deleted by reload inheritance.
                 Work around this by emitting a marker note.  */
@@ -4668,7 +4706,7 @@ reload_as_needed (int live_known)
                fixup_eh_region_note (insn, prev, next);
 
              /* Adjust the location of REG_ARGS_SIZE.  */
-             p = find_reg_note (insn, REG_ARGS_SIZE, NULL_RTX);
+             rtx p = find_reg_note (insn, REG_ARGS_SIZE, NULL_RTX);
              if (p)
                {
                  remove_note (insn, p);
@@ -4680,11 +4718,15 @@ reload_as_needed (int live_known)
                 we have generated are valid.  If not, give an error
                 and delete them.  */
              if (asm_noperands (PATTERN (insn)) >= 0)
-               for (p = NEXT_INSN (prev); p != next; p = NEXT_INSN (p))
+               for (rtx_insn *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))))
+                         || (extract_insn (p),
+                             !(constrain_operands (1,
+                                 get_enabled_alternatives (p))))))
                    {
                      error_for_asm (insn,
                                     "%<asm%> operand requires "
@@ -4707,7 +4749,7 @@ reload_as_needed (int live_known)
 
          /* There may have been CLOBBER insns placed after INSN.  So scan
             between INSN and NEXT and use them to forget old reloads.  */
-         for (x = NEXT_INSN (insn); x != old_next; x = NEXT_INSN (x))
+         for (rtx_insn *x = NEXT_INSN (insn); x != old_next; x = NEXT_INSN (x))
            if (NONJUMP_INSN_P (x) && GET_CODE (PATTERN (x)) == CLOBBER)
              note_stores (PATTERN (x), forget_old_reloads_1, NULL);
 
@@ -4737,9 +4779,9 @@ reload_as_needed (int live_known)
 
                    {
                      rtx reload_reg = rld[i].reg_rtx;
-                     enum machine_mode mode = GET_MODE (reload_reg);
+                     machine_mode mode = GET_MODE (reload_reg);
                      int n = 0;
-                     rtx p;
+                     rtx_insn *p;
 
                      for (p = PREV_INSN (old_next); p != prev; p = PREV_INSN (p))
                        {
@@ -4767,7 +4809,8 @@ reload_as_needed (int live_known)
                              if (n)
                                {
                                  extract_insn (p);
-                                 n = constrain_operands (1);
+                                 n = constrain_operands (1,
+                                   get_enabled_alternatives (p));
                                }
 
                              /* If the constraints were not met, then
@@ -4821,7 +4864,8 @@ reload_as_needed (int live_known)
                          if (TEST_HARD_REG_BIT (reg_reloaded_valid,
                                                 in_hard_regno))
                            {
-                             for (x = old_prev ? NEXT_INSN (old_prev) : insn;
+                             for (rtx_insn *x = (old_prev ?
+                                                 NEXT_INSN (old_prev) : insn);
                                   x != old_next;
                                   x = NEXT_INSN (x))
                                if (x == reg_reloaded_insn[in_hard_regno])
@@ -4849,7 +4893,7 @@ reload_as_needed (int live_known)
          /* If a pseudo that got a hard register is auto-incremented,
             we must purge records of copying it into pseudos without
             hard registers.  */
-         for (x = REG_NOTES (insn); x; x = XEXP (x, 1))
+         for (rtx x = REG_NOTES (insn); x; x = XEXP (x, 1))
            if (REG_NOTE_KIND (x) == REG_INC)
              {
                /* See if this pseudo reg was reloaded in this insn.
@@ -5031,7 +5075,7 @@ static HARD_REG_SET reg_used_in_insn;
 
 static void
 mark_reload_reg_in_use (unsigned int regno, int opnum, enum reload_type type,
-                       enum machine_mode mode)
+                       machine_mode mode)
 {
   switch (type)
     {
@@ -5087,7 +5131,7 @@ mark_reload_reg_in_use (unsigned int regno, int opnum, enum reload_type type,
 
 static void
 clear_reload_reg_in_use (unsigned int regno, int opnum,
-                        enum reload_type type, enum machine_mode mode)
+                        enum reload_type type, machine_mode mode)
 {
   unsigned int nregs = hard_regno_nregs[regno][mode];
   unsigned int start_regno, end_regno, r;
@@ -5423,6 +5467,13 @@ reload_reg_reaches_end_p (unsigned int regno, int reloadnum)
        if (TEST_HARD_REG_BIT (reload_reg_used_in_input[i], regno))
          return 0;
 
+      /* Reload register of reload with type RELOAD_FOR_INPADDR_ADDRESS
+        could be killed if the register is also used by reload with type
+        RELOAD_FOR_INPUT_ADDRESS, so check it.  */
+      if (type == RELOAD_FOR_INPADDR_ADDRESS
+         && TEST_HARD_REG_BIT (reload_reg_used_in_input_addr[opnum], regno))
+       return 0;
+
       for (i = opnum + 1; i < reload_n_operands; i++)
        if (TEST_HARD_REG_BIT (reload_reg_used_in_input_addr[i], regno)
            || TEST_HARD_REG_BIT (reload_reg_used_in_inpaddr_addr[i], regno))
@@ -5497,6 +5548,13 @@ reload_reg_reaches_end_p (unsigned int regno, int reloadnum)
            || TEST_HARD_REG_BIT (reload_reg_used_in_outaddr_addr[i], regno))
          return 0;
 
+      /* Reload register of reload with type RELOAD_FOR_OUTADDR_ADDRESS
+        could be killed if the register is also used by reload with type
+        RELOAD_FOR_OUTPUT_ADDRESS, so check it.  */
+      if (type == RELOAD_FOR_OUTADDR_ADDRESS
+         && TEST_HARD_REG_BIT (reload_reg_used_in_outaddr_addr[opnum], regno))
+       return 0;
+
       return 1;
 
     default:
@@ -5505,15 +5563,15 @@ reload_reg_reaches_end_p (unsigned int regno, int reloadnum)
 }
 
 /* Like reload_reg_reaches_end_p, but check that the condition holds for
-   every register in the range [REGNO, REGNO + NREGS).  */
+   every register in REG.  */
 
 static bool
-reload_regs_reach_end_p (unsigned int regno, int nregs, int reloadnum)
+reload_reg_rtx_reaches_end_p (rtx reg, int reloadnum)
 {
-  int i;
+  unsigned int i;
 
-  for (i = 0; i < nregs; i++)
-    if (!reload_reg_reaches_end_p (regno + i, reloadnum))
+  for (i = REGNO (reg); i < END_REGNO (reg); i++)
+    if (!reload_reg_reaches_end_p (i, reloadnum))
       return false;
   return true;
 }
@@ -5552,6 +5610,14 @@ reloads_unique_chain_p (int r1, int r2)
            || reg_mentioned_p (rld[r2].in, rld[r1].in)))
     return false;
 
+  /* The following loop assumes that r1 is the reload that feeds r2.  */
+  if (r1 > r2)
+    {
+      int tmp = r2;
+      r2 = r1;
+      r1 = tmp;
+    }
+
   for (i = 0; i < n_reloads; i ++)
     /* Look for input reloads that aren't our two */
     if (i != r1 && i != r2 && rld[i].in)
@@ -5578,7 +5644,7 @@ substitute (rtx *where, const_rtx what, rtx repl)
   if (*where == what || rtx_equal_p (*where, what))
     {
       /* Record the location of the changed rtx.  */
-      VEC_safe_push (rtx_p, heap, substitute_stack, where);
+      substitute_stack.safe_push (where);
       *where = repl;
       return;
     }
@@ -5630,8 +5696,9 @@ gen_reload_chain_without_interm_reg_p (int r1, int r2)
      chain reloads or do need an intermediate hard registers.  */
   bool result = true;
   int regno, n, code;
-  rtx out, in, insn;
-  rtx last = get_last_insn ();
+  rtx out, in;
+  rtx_insn *insn;
+  rtx_insn *last = get_last_insn ();
 
   /* Make r2 a component of r1.  */
   if (reg_mentioned_p (rld[r1].in, rld[r2].in))
@@ -5670,16 +5737,16 @@ gen_reload_chain_without_interm_reg_p (int r1, int r2)
          /* We want constrain operands to treat this insn strictly in
             its validity determination, i.e., the way it would after
             reload has completed.  */
-         result = constrain_operands (1);
+         result = constrain_operands (1, get_enabled_alternatives (insn));
        }
 
       delete_insns_since (last);
     }
 
   /* Restore the original value at each changed address within R1.  */
-  while (!VEC_empty (rtx_p, substitute_stack))
+  while (!substitute_stack.is_empty ())
     {
-      rtx *where = VEC_pop (rtx_p, substitute_stack);
+      rtx *where = substitute_stack.pop ();
       *where = rld[r2].in;
     }
 
@@ -5770,7 +5837,7 @@ static char reload_inherited[MAX_RELOADS];
 
 /* For an inherited reload, this is the insn the reload was inherited from,
    if we know it.  Otherwise, this is 0.  */
-static rtx reload_inheritance_insn[MAX_RELOADS];
+static rtx_insn *reload_inheritance_insn[MAX_RELOADS];
 
 /* If nonzero, this is a place to get the value of the reload,
    rather than using reload_in.  */
@@ -6030,7 +6097,7 @@ reload_reg_free_for_value_p (int start_regno, int regno, int opnum,
    register.  */
 
 static int
-free_for_value_p (int regno, enum machine_mode mode, int opnum,
+free_for_value_p (int regno, machine_mode mode, int opnum,
                  enum reload_type type, rtx value, rtx out, int reloadnum,
                  int ignore_address_reloads)
 {
@@ -6081,7 +6148,7 @@ conflicts_with_override (rtx x)
 /* Give an error message saying we failed to find a reload for INSN,
    and clear out reload R.  */
 static void
-failed_reload (rtx insn, int r)
+failed_reload (rtx_insn *insn, int r)
 {
   if (asm_noperands (PATTERN (insn)) < 0)
     /* It's the compiler's fault.  */
@@ -6119,7 +6186,7 @@ set_reload_reg (int i, int r)
      This used to be one `if', but Sequent compiler can't handle that.  */
   if (HARD_REGNO_MODE_OK (regno, rld[r].mode))
     {
-      enum machine_mode test_mode = VOIDmode;
+      machine_mode test_mode = VOIDmode;
       if (rld[r].in)
        test_mode = GET_MODE (rld[r].in);
       /* If rld[r].in has VOIDmode, it means we will load it
@@ -6341,6 +6408,51 @@ choose_reload_regs_init (struct insn_chain *chain, rtx *save_reload_reg_rtx)
                              rld[i].when_needed, rld[i].mode);
 }
 
+#ifdef SECONDARY_MEMORY_NEEDED
+/* If X is not a subreg, return it unmodified.  If it is a subreg,
+   look up whether we made a replacement for the SUBREG_REG.  Return
+   either the replacement or the SUBREG_REG.  */
+
+static rtx
+replaced_subreg (rtx x)
+{
+  if (GET_CODE (x) == SUBREG)
+    return find_replacement (&SUBREG_REG (x));
+  return x;
+}
+#endif
+
+/* Compute the offset to pass to subreg_regno_offset, for a pseudo of
+   mode OUTERMODE that is available in a hard reg of mode INNERMODE.
+   SUBREG is non-NULL if the pseudo is a subreg whose reg is a pseudo,
+   otherwise it is NULL.  */
+
+static int
+compute_reload_subreg_offset (machine_mode outermode,
+                             rtx subreg,
+                             machine_mode innermode)
+{
+  int outer_offset;
+  machine_mode middlemode;
+
+  if (!subreg)
+    return subreg_lowpart_offset (outermode, innermode);
+
+  outer_offset = SUBREG_BYTE (subreg);
+  middlemode = GET_MODE (SUBREG_REG (subreg));
+
+  /* If SUBREG is paradoxical then return the normal lowpart offset
+     for OUTERMODE and INNERMODE.  Our caller has already checked
+     that OUTERMODE fits in INNERMODE.  */
+  if (outer_offset == 0
+      && GET_MODE_SIZE (outermode) > GET_MODE_SIZE (middlemode))
+    return subreg_lowpart_offset (outermode, innermode);
+
+  /* SUBREG is normal, but may not be lowpart; return OUTER_OFFSET
+     plus the normal lowpart offset for MIDDLEMODE and INNERMODE.  */
+  return outer_offset + subreg_lowpart_offset (middlemode, innermode);
+}
+
 /* Assign hard reg targets for the pseudo-registers we must reload
    into hard regs for this insn.
    Also output the instructions to copy them in and out of the hard regs.
@@ -6351,7 +6463,7 @@ choose_reload_regs_init (struct insn_chain *chain, rtx *save_reload_reg_rtx)
 static void
 choose_reload_regs (struct insn_chain *chain)
 {
-  rtx insn = chain->insn;
+  rtx_insn *insn = chain->insn;
   int i, j;
   unsigned int max_group_size = 1;
   enum reg_class group_class = NO_REGS;
@@ -6477,7 +6589,8 @@ choose_reload_regs (struct insn_chain *chain)
            {
              int byte = 0;
              int regno = -1;
-             enum machine_mode mode = VOIDmode;
+             machine_mode mode = VOIDmode;
+             rtx subreg = NULL_RTX;
 
              if (rld[r].in == 0)
                ;
@@ -6498,7 +6611,10 @@ choose_reload_regs (struct insn_chain *chain)
                  if (regno < FIRST_PSEUDO_REGISTER)
                    regno = subreg_regno (rld[r].in_reg);
                  else
-                   byte = SUBREG_BYTE (rld[r].in_reg);
+                   {
+                     subreg = rld[r].in_reg;
+                     byte = SUBREG_BYTE (subreg);
+                   }
                  mode = GET_MODE (rld[r].in_reg);
                }
 #ifdef AUTO_INC_DEC
@@ -6536,6 +6652,9 @@ choose_reload_regs (struct insn_chain *chain)
                  rtx last_reg = reg_last_reload_reg[regno];
 
                  i = REGNO (last_reg);
+                 byte = compute_reload_subreg_offset (mode,
+                                                      subreg,
+                                                      GET_MODE (last_reg));
                  i += subreg_regno_offset (i, GET_MODE (last_reg), byte, mode);
                  last_class = REGNO_REG_CLASS (i);
 
@@ -6808,7 +6927,7 @@ choose_reload_regs (struct insn_chain *chain)
                     We must clear it, since otherwise emit_reload_insns
                     might delete the store.  */
                  if (! TEST_HARD_REG_BIT (reg_reloaded_valid, regno))
-                   spill_reg_store[regno] = NULL_RTX;
+                   spill_reg_store[regno] = NULL;
                  /* If any of the hard registers in EQUIV are spill
                     registers, mark them as in use for this insn.  */
                  for (k = 0; k < nr; k++)
@@ -6932,6 +7051,9 @@ choose_reload_regs (struct insn_chain *chain)
        {
          int r = reload_order[j];
          rtx check_reg;
+#ifdef SECONDARY_MEMORY_NEEDED
+         rtx tem;
+#endif
          if (reload_inherited[r] && rld[r].reg_rtx)
            check_reg = rld[r].reg_rtx;
          else if (reload_override_in[r]
@@ -6965,8 +7087,28 @@ choose_reload_regs (struct insn_chain *chain)
             removal of one reload might allow us to inherit another one.  */
          else if (rld[r].in
                   && rld[r].out != rld[r].in
-                  && remove_address_replacements (rld[r].in) && pass)
-           pass = 2;
+                  && remove_address_replacements (rld[r].in))
+           {
+             if (pass)
+               pass = 2;
+           }
+#ifdef SECONDARY_MEMORY_NEEDED
+         /* If we needed a memory location for the reload, we also have to
+            remove its related reloads.  */
+         else if (rld[r].in
+                  && rld[r].out != rld[r].in
+                  && (tem = replaced_subreg (rld[r].in), REG_P (tem))             
+                  && REGNO (tem) < FIRST_PSEUDO_REGISTER
+                  && SECONDARY_MEMORY_NEEDED (REGNO_REG_CLASS (REGNO (tem)),
+                                              rld[r].rclass, rld[r].inmode)
+                  && remove_address_replacements
+                     (get_secondary_mem (tem, rld[r].inmode, rld[r].opnum,
+                                         rld[r].when_needed)))
+           {
+             if (pass)
+               pass = 2;
+           }
+#endif
        }
     }
 
@@ -7046,20 +7188,22 @@ deallocate_reload_reg (int r)
 }
 \f
 /* These arrays are filled by emit_reload_insns and its subroutines.  */
-static rtx input_reload_insns[MAX_RECOG_OPERANDS];
-static rtx other_input_address_reload_insns = 0;
-static rtx other_input_reload_insns = 0;
-static rtx input_address_reload_insns[MAX_RECOG_OPERANDS];
-static rtx inpaddr_address_reload_insns[MAX_RECOG_OPERANDS];
-static rtx output_reload_insns[MAX_RECOG_OPERANDS];
-static rtx output_address_reload_insns[MAX_RECOG_OPERANDS];
-static rtx outaddr_address_reload_insns[MAX_RECOG_OPERANDS];
-static rtx operand_reload_insns = 0;
-static rtx other_operand_reload_insns = 0;
-static rtx other_output_reload_insns[MAX_RECOG_OPERANDS];
-
-/* Values to be put in spill_reg_store are put here first.  */
-static rtx new_spill_reg_store[FIRST_PSEUDO_REGISTER];
+static rtx_insn *input_reload_insns[MAX_RECOG_OPERANDS];
+static rtx_insn *other_input_address_reload_insns = 0;
+static rtx_insn *other_input_reload_insns = 0;
+static rtx_insn *input_address_reload_insns[MAX_RECOG_OPERANDS];
+static rtx_insn *inpaddr_address_reload_insns[MAX_RECOG_OPERANDS];
+static rtx_insn *output_reload_insns[MAX_RECOG_OPERANDS];
+static rtx_insn *output_address_reload_insns[MAX_RECOG_OPERANDS];
+static rtx_insn *outaddr_address_reload_insns[MAX_RECOG_OPERANDS];
+static rtx_insn *operand_reload_insns = 0;
+static rtx_insn *other_operand_reload_insns = 0;
+static rtx_insn *other_output_reload_insns[MAX_RECOG_OPERANDS];
+
+/* Values to be put in spill_reg_store are put here first.  Instructions
+   must only be placed here if the associated reload register reaches
+   the end of the instruction's reload sequence.  */
+static rtx_insn *new_spill_reg_store[FIRST_PSEUDO_REGISTER];
 static HARD_REG_SET reg_reloaded_died;
 
 /* Check if *RELOAD_REG is suitable as an intermediate or scratch register
@@ -7069,7 +7213,7 @@ static HARD_REG_SET reg_reloaded_died;
 static bool
 reload_adjust_reg_for_temp (rtx *reload_reg, rtx alt_reload_reg,
                            enum reg_class new_class,
-                           enum machine_mode new_mode)
+                           machine_mode new_mode)
 
 {
   rtx reg;
@@ -7105,7 +7249,7 @@ reload_adjust_reg_for_icode (rtx *reload_reg, rtx alt_reload_reg,
 
 {
   enum reg_class new_class = scratch_reload_class (icode);
-  enum machine_mode new_mode = insn_data[(int) icode].operand[2].mode;
+  machine_mode new_mode = insn_data[(int) icode].operand[2].mode;
 
   return reload_adjust_reg_for_temp (reload_reg, alt_reload_reg,
                                     new_class, new_mode);
@@ -7118,20 +7262,23 @@ static void
 emit_input_reload_insns (struct insn_chain *chain, struct reload *rl,
                         rtx old, int j)
 {
-  rtx insn = chain->insn;
+  rtx_insn *insn = chain->insn;
   rtx reloadreg;
   rtx oldequiv_reg = 0;
   rtx oldequiv = 0;
   int special = 0;
-  enum machine_mode mode;
-  rtx *where;
+  machine_mode mode;
+  rtx_insn **where;
 
   /* delete_output_reload is only invoked properly if old contains
      the original pseudo register.  Since this is replaced with a
      hard reg when RELOAD_OVERRIDE_IN is set, see if we can
-     find the pseudo in RELOAD_IN_REG.  */
+     find the pseudo in RELOAD_IN_REG.  This is also used to
+     determine whether a secondary reload is needed.  */
   if (reload_override_in[j]
-      && REG_P (rl->in_reg))
+      && (REG_P (rl->in_reg)
+         || (GET_CODE (rl->in_reg) == SUBREG
+             && REG_P (SUBREG_REG (rl->in_reg)))))
     {
       oldequiv = old;
       old = rl->in_reg;
@@ -7219,9 +7366,7 @@ emit_input_reload_insns (struct insn_chain *chain, struct reload *rl,
 
       /* Prevent normal processing of this reload.  */
       special = 1;
-      /* Output a special code sequence for this case, and forget about
-        spill reg information.  */
-      new_spill_reg_store[REGNO (reloadreg)] = NULL;
+      /* Output a special code sequence for this case.  */
       inc_for_reload (reloadreg, oldequiv, rl->out, rl->inc);
     }
 
@@ -7238,7 +7383,7 @@ emit_input_reload_insns (struct insn_chain *chain, struct reload *rl,
           && free_for_value_p (REGNO (reloadreg), rl->mode, rl->opnum,
                                rl->when_needed, old, rl->out, j, 0))
     {
-      rtx temp = PREV_INSN (insn);
+      rtx_insn *temp = PREV_INSN (insn);
       while (temp && (NOTE_P (temp) || DEBUG_INSN_P (temp)))
        temp = PREV_INSN (temp);
       if (temp
@@ -7255,9 +7400,18 @@ emit_input_reload_insns (struct insn_chain *chain, struct reload *rl,
          /* Store into the reload register instead of the pseudo.  */
          SET_DEST (PATTERN (temp)) = reloadreg;
 
-         /* Verify that resulting insn is valid.  */
+         /* Verify that resulting insn is valid. 
+
+            Note that we have replaced the destination of TEMP with
+            RELOADREG.  If TEMP references RELOADREG within an
+            autoincrement addressing mode, then the resulting insn
+            is ill-formed and we must reject this optimization.  */
          extract_insn (temp);
-         if (constrain_operands (1))
+         if (constrain_operands (1, get_enabled_alternatives (temp))
+#ifdef AUTO_INC_DEC
+             && ! find_reg_note (temp, REG_INC, reloadreg)
+#endif
+             )
            {
              /* If the previous insn is an output reload, the source is
                 a reload register, and its spill_reg_store entry will
@@ -7570,11 +7724,11 @@ emit_output_reload_insns (struct insn_chain *chain, struct reload *rl,
                          int j)
 {
   rtx reloadreg;
-  rtx insn = chain->insn;
+  rtx_insn *insn = chain->insn;
   int special = 0;
   rtx old = rl->out;
-  enum machine_mode mode;
-  rtx p;
+  machine_mode mode;
+  rtx_insn *p;
   rtx rl_reg_rtx;
 
   if (rl->when_needed == RELOAD_OTHER)
@@ -7737,19 +7891,19 @@ emit_output_reload_insns (struct insn_chain *chain, struct reload *rl,
                       that it is, setting new_spill_reg_store to
                       that insn will allow an extra optimization.  */
                    rtx s_reg = rld[s].reg_rtx;
-                   rtx next = NEXT_INSN (p);
+                   rtx_insn *next = NEXT_INSN (p);
                    rld[s].out = rl->out;
                    rld[s].out_reg = rl->out_reg;
                    set = single_set (next);
                    if (set && SET_SRC (set) == s_reg
-                       && ! new_spill_reg_store[REGNO (s_reg)])
+                       && reload_reg_rtx_reaches_end_p (s_reg, s))
                      {
                        SET_HARD_REG_BIT (reg_is_output_reload,
                                          REGNO (s_reg));
                        new_spill_reg_store[REGNO (s_reg)] = next;
                      }
                  }
-               else
+               else if (reload_reg_rtx_reaches_end_p (rl_reg_rtx, j))
                  new_spill_reg_store[REGNO (rl_reg_rtx)] = p;
              }
          }
@@ -7774,14 +7928,14 @@ emit_output_reload_insns (struct insn_chain *chain, struct reload *rl,
 static void
 do_input_reload (struct insn_chain *chain, struct reload *rl, int j)
 {
-  rtx insn = chain->insn;
+  rtx_insn *insn = chain->insn;
   rtx old = (rl->in && MEM_P (rl->in)
             ? rl->in_reg : rl->in);
   rtx reg_rtx = rl->reg_rtx;
 
   if (old && reg_rtx)
     {
-      enum machine_mode mode;
+      machine_mode mode;
 
       /* Determine the mode to reload in.
         This is very tricky because we have three to choose from.
@@ -7876,7 +8030,7 @@ static void
 do_output_reload (struct insn_chain *chain, struct reload *rl, int j)
 {
   rtx note, old;
-  rtx insn = chain->insn;
+  rtx_insn *insn = chain->insn;
   /* If this is an output reload that stores something that is
      not loaded in this same reload, see if we can eliminate a previous
      store.  */
@@ -7885,7 +8039,7 @@ do_output_reload (struct insn_chain *chain, struct reload *rl, int j)
 
   if (rl->out && reg_rtx)
     {
-      enum machine_mode mode;
+      machine_mode mode;
 
       /* Determine the mode to reload in.
         See comments above (for input reloading).  */
@@ -7970,7 +8124,7 @@ do_output_reload (struct insn_chain *chain, struct reload *rl, int j)
 static bool
 inherit_piecemeal_p (int dest ATTRIBUTE_UNUSED,
                     int src ATTRIBUTE_UNUSED,
-                    enum machine_mode mode ATTRIBUTE_UNUSED)
+                    machine_mode mode ATTRIBUTE_UNUSED)
 {
 #ifdef CANNOT_CHANGE_MODE_CLASS
   return (!REG_CANNOT_CHANGE_MODE_P (dest, mode, reg_raw_mode[dest])
@@ -7985,7 +8139,7 @@ inherit_piecemeal_p (int dest ATTRIBUTE_UNUSED,
 static void
 emit_reload_insns (struct insn_chain *chain)
 {
-  rtx insn = chain->insn;
+  rtx_insn *insn = chain->insn;
 
   int j;
 
@@ -8009,6 +8163,15 @@ emit_reload_insns (struct insn_chain *chain)
       debug_reload_to_stream (dump_file);
     }
 
+  for (j = 0; j < n_reloads; j++)
+    if (rld[j].reg_rtx && HARD_REGISTER_P (rld[j].reg_rtx))
+      {
+       unsigned int i;
+
+       for (i = REGNO (rld[j].reg_rtx); i < END_REGNO (rld[j].reg_rtx); i++)
+         new_spill_reg_store[i] = 0;
+      }
+
   /* Now output the instructions to copy the data into and out of the
      reload registers.  Do these in the order that the reloads were reported,
      since reloads of base and index registers precede reloads of operands
@@ -8016,14 +8179,6 @@ emit_reload_insns (struct insn_chain *chain)
 
   for (j = 0; j < n_reloads; j++)
     {
-      if (rld[j].reg_rtx && HARD_REGISTER_P (rld[j].reg_rtx))
-       {
-         unsigned int i;
-
-         for (i = REGNO (rld[j].reg_rtx); i < END_REGNO (rld[j].reg_rtx); i++)
-           new_spill_reg_store[i] = 0;
-       }
-
       do_input_reload (chain, rld + j, j);
       do_output_reload (chain, rld + j, j);
     }
@@ -8149,15 +8304,13 @@ emit_reload_insns (struct insn_chain *chain)
                         && GET_CODE (rld[r].out) != PRE_MODIFY))))
            {
              rtx reg;
-             enum machine_mode mode;
-             int regno, nregs;
 
              reg = reload_reg_rtx_for_output[r];
-             mode = GET_MODE (reg);
-             regno = REGNO (reg);
-             nregs = hard_regno_nregs[regno][mode];
-             if (reload_regs_reach_end_p (regno, nregs, r))
+             if (reload_reg_rtx_reaches_end_p (reg, r))
                {
+                 machine_mode mode = GET_MODE (reg);
+                 int regno = REGNO (reg);
+                 int nregs = hard_regno_nregs[regno][mode];
                  rtx out = (REG_P (rld[r].out)
                             ? rld[r].out
                             : rld[r].out_reg
@@ -8221,20 +8374,21 @@ emit_reload_insns (struct insn_chain *chain)
                   && !reg_set_p (reload_reg_rtx_for_input[r], PATTERN (insn)))
            {
              rtx reg;
-             enum machine_mode mode;
-             int regno, nregs;
 
              reg = reload_reg_rtx_for_input[r];
-             mode = GET_MODE (reg);
-             regno = REGNO (reg);
-             nregs = hard_regno_nregs[regno][mode];
-             if (reload_regs_reach_end_p (regno, nregs, r))
+             if (reload_reg_rtx_reaches_end_p (reg, r))
                {
+                 machine_mode mode;
+                 int regno;
+                 int nregs;
                  int in_regno;
                  int in_nregs;
                  rtx in;
                  bool piecemeal;
 
+                 mode = GET_MODE (reg);
+                 regno = REGNO (reg);
+                 nregs = hard_regno_nregs[regno][mode];
                  if (REG_P (rld[r].in)
                      && REGNO (rld[r].in) >= FIRST_PSEUDO_REGISTER)
                    in = rld[r].in;
@@ -8307,7 +8461,7 @@ emit_reload_insns (struct insn_chain *chain)
          rtx out = ((rld[r].out && REG_P (rld[r].out))
                     ? rld[r].out : rld[r].out_reg);
          int out_regno = REGNO (out);
-         enum machine_mode mode = GET_MODE (out);
+         machine_mode mode = GET_MODE (out);
 
          /* REG_RTX is now set or clobbered by the main instruction.
             As the comment above explains, forget_old_reloads_1 only
@@ -8327,7 +8481,8 @@ emit_reload_insns (struct insn_chain *chain)
 
          if (!HARD_REGISTER_NUM_P (out_regno))
            {
-             rtx src_reg, store_insn = NULL_RTX;
+             rtx src_reg;
+             rtx_insn *store_insn = NULL;
 
              reg_last_reload_reg[out_regno] = 0;
 
@@ -8336,10 +8491,17 @@ emit_reload_insns (struct insn_chain *chain)
                 delete_output_reload.  */
              src_reg = reload_reg_rtx_for_output[r];
 
-             /* If this is an optional reload, try to find the source reg
-                from an input reload.  */
-             if (! src_reg)
+             if (src_reg)
                {
+                 if (reload_reg_rtx_reaches_end_p (src_reg, r))
+                   store_insn = new_spill_reg_store[REGNO (src_reg)];
+                 else
+                   src_reg = NULL_RTX;
+               }
+             else
+               {
+                 /* If this is an optional reload, try to find the
+                    source reg from an input reload.  */
                  rtx set = single_set (insn);
                  if (set && SET_DEST (set) == rld[r].out)
                    {
@@ -8357,8 +8519,6 @@ emit_reload_insns (struct insn_chain *chain)
                        }
                    }
                }
-             else
-               store_insn = new_spill_reg_store[REGNO (src_reg)];
              if (src_reg && REG_P (src_reg)
                  && REGNO (src_reg) < FIRST_PSEUDO_REGISTER)
                {
@@ -8419,13 +8579,13 @@ emit_reload_insns (struct insn_chain *chain)
 /* Go through the motions to emit INSN and test if it is strictly valid.
    Return the emitted insn if valid, else return NULL.  */
 
-static rtx
-emit_insn_if_valid_for_reload (rtx insn)
+static rtx_insn *
+emit_insn_if_valid_for_reload (rtx pat)
 {
-  rtx last = get_last_insn ();
+  rtx_insn *last = get_last_insn ();
   int code;
 
-  insn = emit_insn (insn);
+  rtx_insn *insn = emit_insn (pat);
   code = recog_memoized (insn);
 
   if (code >= 0)
@@ -8434,7 +8594,7 @@ emit_insn_if_valid_for_reload (rtx insn)
       /* We want constrain operands to treat this insn strictly in its
         validity determination, i.e., the way it would after reload has
         completed.  */
-      if (constrain_operands (1))
+      if (constrain_operands (1, get_enabled_alternatives (insn)))
        return insn;
     }
 
@@ -8448,11 +8608,14 @@ emit_insn_if_valid_for_reload (rtx insn)
 
    Returns first insn emitted.  */
 
-static rtx
+static rtx_insn *
 gen_reload (rtx out, rtx in, int opnum, enum reload_type type)
 {
-  rtx last = get_last_insn ();
-  rtx tem;
+  rtx_insn *last = get_last_insn ();
+  rtx_insn *tem;
+#ifdef SECONDARY_MEMORY_NEEDED
+  rtx tem1, tem2;
+#endif
 
   /* If IN is a paradoxical SUBREG, remove it and try to put the
      opposite SUBREG on OUT.  Likewise for a paradoxical SUBREG on OUT.  */
@@ -8513,7 +8676,8 @@ gen_reload (rtx out, rtx in, int opnum, enum reload_type type)
         `extract_insn' and it is simpler to emit and then delete the insn if
         not valid than to dummy things up.  */
 
-      rtx op0, op1, tem, insn;
+      rtx op0, op1, tem;
+      rtx_insn *insn;
       enum insn_code code;
 
       op0 = find_replacement (&XEXP (in, 0));
@@ -8589,14 +8753,12 @@ gen_reload (rtx out, rtx in, int opnum, enum reload_type type)
 
 #ifdef SECONDARY_MEMORY_NEEDED
   /* If we need a memory location to do the move, do it that way.  */
-  else if ((REG_P (in)
-            || (GET_CODE (in) == SUBREG && REG_P (SUBREG_REG (in))))
-          && reg_or_subregno (in) < FIRST_PSEUDO_REGISTER
-          && (REG_P (out)
-              || (GET_CODE (out) == SUBREG && REG_P (SUBREG_REG (out))))
-          && reg_or_subregno (out) < FIRST_PSEUDO_REGISTER
-          && SECONDARY_MEMORY_NEEDED (REGNO_REG_CLASS (reg_or_subregno (in)),
-                                      REGNO_REG_CLASS (reg_or_subregno (out)),
+  else if ((tem1 = replaced_subreg (in), tem2 = replaced_subreg (out),
+           (REG_P (tem1) && REG_P (tem2)))
+          && REGNO (tem1) < FIRST_PSEUDO_REGISTER
+          && REGNO (tem2) < FIRST_PSEUDO_REGISTER
+          && SECONDARY_MEMORY_NEEDED (REGNO_REG_CLASS (REGNO (tem1)),
+                                      REGNO_REG_CLASS (REGNO (tem2)),
                                       GET_MODE (out)))
     {
       /* Get the memory to use and rewrite both registers to its mode.  */
@@ -8617,7 +8779,7 @@ gen_reload (rtx out, rtx in, int opnum, enum reload_type type)
       rtx insn;
       rtx op1;
       rtx out_moded;
-      rtx set;
+      rtx_insn *set;
 
       op1 = find_replacement (&XEXP (in, 0));
       if (op1 != XEXP (in, 0))
@@ -8647,7 +8809,7 @@ gen_reload (rtx out, rtx in, int opnum, enum reload_type type)
       if (insn)
        {
          set_unique_reg_note (insn, REG_EQUIV, in);
-         return insn;
+         return as_a <rtx_insn *> (insn);
        }
 
       fatal_insn ("failure trying to reload:", set);
@@ -8689,21 +8851,21 @@ gen_reload (rtx out, rtx in, int opnum, enum reload_type type)
    NEW_RELOAD_REG is reload register that reload J is using for REG.  */
 
 static void
-delete_output_reload (rtx insn, int j, int last_reload_reg, rtx new_reload_reg)
+delete_output_reload (rtx_insn *insn, int j, int last_reload_reg,
+                     rtx new_reload_reg)
 {
-  rtx output_reload_insn = spill_reg_store[last_reload_reg];
+  rtx_insn *output_reload_insn = spill_reg_store[last_reload_reg];
   rtx reg = spill_reg_stored_to[last_reload_reg];
   int k;
   int n_occurrences;
   int n_inherited = 0;
-  rtx i1;
   rtx substed;
   unsigned regno;
   int nregs;
 
   /* 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))
+  if (output_reload_insn->deleted ())
     return;
 
   /* Get the raw pseudo-register referred to.  */
@@ -8743,7 +8905,7 @@ delete_output_reload (rtx insn, int j, int last_reload_reg, rtx new_reload_reg)
     n_occurrences += count_occurrences (PATTERN (insn),
                                        eliminate_regs (substed, VOIDmode,
                                                        NULL_RTX), 0);
-  for (i1 = reg_equiv_alt_mem_list (REGNO (reg)); i1; i1 = XEXP (i1, 1))
+  for (rtx i1 = reg_equiv_alt_mem_list (REGNO (reg)); i1; i1 = XEXP (i1, 1))
     {
       gcc_assert (!rtx_equal_p (XEXP (i1, 0), substed));
       n_occurrences += count_occurrences (PATTERN (insn), XEXP (i1, 0), 0);
@@ -8762,7 +8924,7 @@ delete_output_reload (rtx insn, int j, int last_reload_reg, rtx new_reload_reg)
      and we're within the same basic block, then the value can only
      pass through the reload reg and end up here.
      Otherwise, give up--return.  */
-  for (i1 = NEXT_INSN (output_reload_insn);
+  for (rtx_insn *i1 = NEXT_INSN (output_reload_insn);
        i1 != insn; i1 = NEXT_INSN (i1))
     {
       if (NOTE_INSN_BASIC_BLOCK_P (i1))
@@ -8804,7 +8966,7 @@ delete_output_reload (rtx insn, int j, int last_reload_reg, rtx new_reload_reg)
       && REG_BASIC_BLOCK (REGNO (reg)) >= NUM_FIXED_BLOCKS
       && find_regno_note (insn, REG_DEAD, REGNO (reg)))
     {
-      rtx i2;
+      rtx_insn *i2;
 
       /* We know that it was used only between here and the beginning of
         the current basic block.  (We also know that the last use before
@@ -8818,8 +8980,7 @@ delete_output_reload (rtx insn, int j, int last_reload_reg, rtx new_reload_reg)
             since if they are the only uses, they are dead.  */
          if (set != 0 && SET_DEST (set) == reg)
            continue;
-         if (LABEL_P (i2)
-             || JUMP_P (i2))
+         if (LABEL_P (i2) || JUMP_P (i2))
            break;
          if ((NONJUMP_INSN_P (i2) || CALL_P (i2))
              && reg_mentioned_p (reg, PATTERN (i2)))
@@ -8843,8 +9004,7 @@ delete_output_reload (rtx insn, int j, int last_reload_reg, rtx new_reload_reg)
              delete_address_reloads (i2, insn);
              delete_insn (i2);
            }
-         if (LABEL_P (i2)
-             || JUMP_P (i2))
+         if (LABEL_P (i2) || JUMP_P (i2))
            break;
        }
 
@@ -8866,10 +9026,11 @@ delete_output_reload (rtx insn, int j, int last_reload_reg, rtx new_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 (rtx dead_insn, rtx current_insn)
+delete_address_reloads (rtx_insn *dead_insn, rtx_insn *current_insn)
 {
   rtx set = single_set (dead_insn);
-  rtx set2, dst, prev, next;
+  rtx set2, dst;
+  rtx_insn *prev, *next;
   if (set)
     {
       rtx dst = SET_DEST (set);
@@ -8902,9 +9063,10 @@ delete_address_reloads (rtx dead_insn, rtx current_insn)
 
 /* Subfunction of delete_address_reloads: process registers found in X.  */
 static void
-delete_address_reloads_1 (rtx dead_insn, rtx x, rtx current_insn)
+delete_address_reloads_1 (rtx_insn *dead_insn, rtx x, rtx_insn *current_insn)
 {
-  rtx prev, set, dst, i2;
+  rtx_insn *prev, *i2;
+  rtx set, dst;
   int i, j;
   enum rtx_code code = GET_CODE (x);
 
@@ -9025,9 +9187,9 @@ inc_for_reload (rtx reloadreg, rtx in, rtx value, int inc_amount)
   /* Nonzero if increment after copying.  */
   int post = (GET_CODE (value) == POST_DEC || GET_CODE (value) == POST_INC
              || GET_CODE (value) == POST_MODIFY);
-  rtx last;
+  rtx_insn *last;
   rtx inc;
-  rtx add_insn;
+  rtx_insn *add_insn;
   int code;
   rtx real_in = in == value ? incloc : in;
 
@@ -9069,7 +9231,7 @@ inc_for_reload (rtx reloadreg, rtx in, rtx value, int inc_amount)
       if (code >= 0)
        {
          extract_insn (add_insn);
-         if (constrain_operands (1))
+         if (constrain_operands (1, get_enabled_alternatives (add_insn)))
            {
              /* If this is a pre-increment and we have incremented the value
                 where it lives, copy the incremented value to RELOADREG to
@@ -9109,7 +9271,9 @@ inc_for_reload (rtx reloadreg, rtx in, rtx value, int inc_amount)
       emit_insn (gen_add2_insn (reloadreg, inc));
       emit_insn (gen_move_insn (incloc, reloadreg));
       if (CONST_INT_P (inc))
-       emit_insn (gen_add2_insn (reloadreg, GEN_INT (-INTVAL (inc))));
+       emit_insn (gen_add2_insn (reloadreg,
+                                 gen_int_mode (-INTVAL (inc),
+                                               GET_MODE (reloadreg))));
       else
        emit_insn (gen_sub2_insn (reloadreg, inc));
     }
@@ -9117,7 +9281,7 @@ inc_for_reload (rtx reloadreg, rtx in, rtx value, int inc_amount)
 \f
 #ifdef AUTO_INC_DEC
 static void
-add_auto_inc_notes (rtx insn, rtx x)
+add_auto_inc_notes (rtx_insn *insn, rtx x)
 {
   enum rtx_code code = GET_CODE (x);
   const char *fmt;