OSDN Git Service

Fix an unwinding bug for functions with dynamic stack frames.
[pf3gnuchains/gcc-fork.git] / gcc / reload1.c
index 3ee0fc3..bbb75c8 100644 (file)
@@ -1,7 +1,7 @@
 /* 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
-   Free Software Foundation, Inc.
+   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
+   2011, 2012 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -26,10 +26,11 @@ along with GCC; see the file COPYING3.  If not see
 
 #include "machmode.h"
 #include "hard-reg-set.h"
-#include "rtl.h"
+#include "rtl-error.h"
 #include "tm_p.h"
 #include "obstack.h"
 #include "insn-config.h"
+#include "ggc.h"
 #include "flags.h"
 #include "function.h"
 #include "expr.h"
@@ -37,16 +38,15 @@ along with GCC; see the file COPYING3.  If not see
 #include "regs.h"
 #include "addresses.h"
 #include "basic-block.h"
+#include "df.h"
 #include "reload.h"
 #include "recog.h"
 #include "output.h"
-#include "real.h"
-#include "toplev.h"
 #include "except.h"
 #include "tree.h"
-#include "df.h"
+#include "ira.h"
 #include "target.h"
-#include "dse.h"
+#include "emit-rtl.h"
 
 /* This file contains the reload pass of the compiler, which is
    run after register allocation has been done.  It checks that
@@ -82,6 +82,14 @@ along with GCC; see the file COPYING3.  If not see
    fixing up each insn, and generating the new insns to copy values
    into the reload registers.  */
 \f
+struct target_reload default_target_reload;
+#if SWITCHABLE_TARGET
+struct target_reload *this_target_reload = &default_target_reload;
+#endif
+
+#define spill_indirect_levels                  \
+  (this_target_reload->x_spill_indirect_levels)
+
 /* During reload_as_needed, element N contains a REG rtx for the hard reg
    into which reg N has been reloaded (perhaps for a previous insn).  */
 static rtx *reg_last_reload_reg;
@@ -94,48 +102,9 @@ static regset_head reg_has_output_reload;
    in the current insn.  */
 static HARD_REG_SET reg_is_output_reload;
 
-/* Element N is the constant value to which pseudo reg N is equivalent,
-   or zero if pseudo reg N is not equivalent to a constant.
-   find_reloads looks at this in order to replace pseudo reg N
-   with the constant it stands for.  */
-rtx *reg_equiv_constant;
-
-/* Element N is an invariant value to which pseudo reg N is equivalent.
-   eliminate_regs_in_insn uses this to replace pseudos in particular
-   contexts.  */
-rtx *reg_equiv_invariant;
-
-/* Element N is a memory location to which pseudo reg N is equivalent,
-   prior to any register elimination (such as frame pointer to stack
-   pointer).  Depending on whether or not it is a valid address, this value
-   is transferred to either reg_equiv_address or reg_equiv_mem.  */
-rtx *reg_equiv_memory_loc;
-
-/* We allocate reg_equiv_memory_loc inside a varray so that the garbage
-   collector can keep track of what is inside.  */
-VEC(rtx,gc) *reg_equiv_memory_loc_vec;
-
-/* Element N is the address of stack slot to which pseudo reg N is equivalent.
-   This is used when the address is not valid as a memory address
-   (because its displacement is too big for the machine.)  */
-rtx *reg_equiv_address;
-
-/* Element N is the memory slot to which pseudo reg N is equivalent,
-   or zero if pseudo reg N is not equivalent to a memory slot.  */
-rtx *reg_equiv_mem;
-
-/* Element N is an EXPR_LIST of REG_EQUIVs containing MEMs with
-   alternate representations of the location of pseudo reg N.  */
-rtx *reg_equiv_alt_mem_list;
-
 /* Widest width in which each pseudo reg is referred to (via subreg).  */
 static unsigned int *reg_max_ref_width;
 
-/* Element N is the list of insns that initialized reg N from its equivalent
-   constant or memory slot.  */
-rtx *reg_equiv_init;
-int reg_equiv_init_size;
-
 /* Vector to remember old contents of reg_renumber before spilling.  */
 static short *reg_old_renumber;
 
@@ -232,22 +201,6 @@ static HARD_REG_SET used_spill_regs;
    a round-robin fashion.  */
 static int last_spill_reg;
 
-/* Nonzero if indirect addressing is supported on the machine; this means
-   that spilling (REG n) does not require reloading it into a register in
-   order to do (MEM (REG n)) or (MEM (PLUS (REG n) (CONST_INT c))).  The
-   value indicates the level of indirect addressing supported, e.g., two
-   means that (MEM (MEM (REG n))) is also valid if (REG n) does not get
-   a hard register.  */
-static char spill_indirect_levels;
-
-/* Nonzero if indirect addressing is supported when the innermost MEM is
-   of the form (MEM (SYMBOL_REF sym)).  It is assumed that the level to
-   which these are valid is the same as spill_indirect_levels, above.  */
-char indirect_symref_ok;
-
-/* Nonzero if an address (plus (reg frame_pointer) (reg ...)) is valid.  */
-char double_reg_address_ok;
-
 /* Record the stack slot for each spilled hard register.  */
 static rtx spill_stack_slot[FIRST_PSEUDO_REGISTER];
 
@@ -257,6 +210,9 @@ static unsigned int spill_stack_slot_width[FIRST_PSEUDO_REGISTER];
 /* Record which pseudos needed to be spilled.  */
 static regset_head spilled_pseudos;
 
+/* Record which pseudos changed their allocation in finish_spills.  */
+static regset_head changed_allocation_pseudos;
+
 /* Used for communication between order_regs_for_reload and count_pseudo.
    Used to avoid counting one pseudo twice.  */
 static regset_head pseudos_counted;
@@ -273,12 +229,6 @@ int caller_save_needed;
    Required by some machines to handle any generated moves differently.  */
 int reload_in_progress = 0;
 
-/* These arrays record the insn_code of insns that may be needed to
-   perform input and output reloads of special objects.  They provide a
-   place to pass a scratch register.  */
-enum insn_code reload_in_optab[NUM_MACHINE_MODES];
-enum insn_code reload_out_optab[NUM_MACHINE_MODES];
-
 /* This obstack is used for allocation of rtl during register elimination.
    The allocated storage can be freed once find_reloads has processed the
    insn.  */
@@ -300,6 +250,10 @@ static char *reload_insn_firstobj;
    examine.  */
 struct insn_chain *reload_insn_chain;
 
+/* TRUE if we potentially left dead insns in the insn stream and want to
+   run DCE immediately after reload, FALSE otherwise.  */
+static bool need_dce;
+
 /* List of all insns needing reloads.  */
 static struct insn_chain *insns_need_reload;
 \f
@@ -314,8 +268,9 @@ struct elim_table
   int to;                      /* Register number used as replacement.  */
   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 can_eliminate_previous;  /* Value returned by TARGET_CAN_ELIMINATE
+                                  target hook in previous scan over insns
+                                  made by reload.  */
   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.  */
@@ -373,6 +328,23 @@ 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;
+
+/* Stack of addresses where an rtx has been changed.  We can undo the 
+   changes by popping items off the stack and restoring the original
+   value at each location. 
+
+   We use this simplistic undo capability rather than copy_rtx as copy_rtx
+   will not make a deep copy of a normally sharable rtx, such as
+   (const (plus (symbol_ref) (const_int))).  If such an expression appears
+   as R1 in gen_reload_chain_without_interm_reg_p, then a shared
+   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;
+
 /* Number of labels in the current function.  */
 
 static int num_labels;
@@ -389,10 +361,11 @@ 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 alter_reg (int, int, bool);
 static void set_label_offsets (rtx, rtx, 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 update_eliminable_offsets (void);
 static void mark_not_eliminable (rtx, const_rtx, void *);
@@ -400,8 +373,11 @@ 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 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 void spill_hard_reg (unsigned int, int);
 static int finish_spills (int);
 static void scan_paradoxical_subregs (rtx);
@@ -420,14 +396,12 @@ 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 *,
@@ -438,11 +412,12 @@ 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 rtx inc_for_reload (rtx, rtx, rtx, int);
+static void inc_for_reload (rtx, rtx, rtx, int);
 #ifdef AUTO_INC_DEC
 static void add_auto_inc_notes (rtx, rtx);
 #endif
-static void copy_eh_notes (rtx, rtx);
+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);
@@ -501,6 +476,7 @@ init_reload (void)
   reload_startobj = XOBNEWVAR (&reload_obstack, char, 0);
 
   INIT_REG_SET (&spilled_pseudos);
+  INIT_REG_SET (&changed_allocation_pseudos);
   INIT_REG_SET (&pseudos_counted);
 }
 
@@ -546,11 +522,11 @@ compute_use_by_pseudos (HARD_REG_SET *to, regset from)
 
       if (r < 0)
        {
-         /* reload_combine uses the information from
-            DF_LIVE_IN (BASIC_BLOCK), which might still
-            contain registers that have not actually been allocated
-            since they have an equivalence.  */
-         gcc_assert (reload_completed);
+         /* reload_combine uses the information from DF_LIVE_IN,
+            which might still contain registers that have not
+            actually been allocated since they have an
+            equivalence.  */
+         gcc_assert (ira_conflicts_p || reload_completed);
        }
       else
        add_to_hard_reg_set (to, PSEUDO_REGNO_MODE (regno), r);
@@ -579,7 +555,7 @@ replace_pseudos_in (rtx *loc, enum machine_mode mem_mode, rtx usage)
       if (regno < FIRST_PSEUDO_REGISTER)
        return;
 
-      x = eliminate_regs (x, mem_mode, usage);
+      x = eliminate_regs_1 (x, mem_mode, usage, true, false);
       if (x != *loc)
        {
          *loc = x;
@@ -587,12 +563,14 @@ replace_pseudos_in (rtx *loc, enum machine_mode mem_mode, rtx usage)
          return;
        }
 
-      if (reg_equiv_constant[regno])
-       *loc = reg_equiv_constant[regno];
-      else if (reg_equiv_mem[regno])
-       *loc = reg_equiv_mem[regno];
-      else if (reg_equiv_address[regno])
-       *loc = gen_rtx_MEM (GET_MODE (x), reg_equiv_address[regno]);
+      if (reg_equiv_constant (regno))
+       *loc = reg_equiv_constant (regno);
+      else if (reg_equiv_invariant (regno))
+       *loc = reg_equiv_invariant (regno);
+      else if (reg_equiv_mem (regno))
+       *loc = reg_equiv_mem (regno);
+      else if (reg_equiv_address (regno))
+       *loc = gen_rtx_MEM (GET_MODE (x), reg_equiv_address (regno));
       else
        {
          gcc_assert (!REG_P (regno_reg_rtx[regno])
@@ -631,7 +609,7 @@ has_nonexceptional_receiver (void)
   /* If we're not optimizing, then just err on the safe side.  */
   if (!optimize)
     return true;
-  
+
   /* First determine which blocks can reach exit via normal paths.  */
   tos = worklist = XNEWVEC (basic_block, n_basic_blocks + 1);
 
@@ -641,7 +619,7 @@ has_nonexceptional_receiver (void)
   /* Place the exit block on our worklist.  */
   EXIT_BLOCK_PTR->flags |= BB_REACHABLE;
   *tos++ = EXIT_BLOCK_PTR;
-  
+
   /* Iterate: find everything reachable from what we've already seen.  */
   while (tos != worklist)
     {
@@ -664,26 +642,52 @@ has_nonexceptional_receiver (void)
   /* Now see if there's a reachable block with an exceptional incoming
      edge.  */
   FOR_EACH_BB (bb)
-    if (bb->flags & BB_REACHABLE)
-      FOR_EACH_EDGE (e, ei, bb->preds)
-       if (e->flags & EDGE_ABNORMAL)
-         return true;
+    if (bb->flags & BB_REACHABLE && bb_has_abnormal_pred (bb))
+      return true;
 
   /* No exceptional block reached exit unexceptionally.  */
   return false;
 }
 
+/* Grow (or allocate) the REG_EQUIVS array from its current size (which may be
+   zero elements) to MAX_REG_NUM elements.
+
+   Initialize all new fields to NULL and update REG_EQUIVS_SIZE.  */
+void
+grow_reg_equivs (void)
+{
+  int old_size = VEC_length (reg_equivs_t, reg_equivs);
+  int max_regno = max_reg_num ();
+  int i;
+
+  VEC_reserve (reg_equivs_t, gc, 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));
+    }
+    
+}
+
 \f
 /* Global variables used by reload and its subroutines.  */
 
+/* The current basic block while in calculate_elim_costs_all_insns.  */
+static basic_block elim_bb;
+
 /* Set during calculate_needs if an insn needs register elimination.  */
 static int something_needs_elimination;
 /* Set during calculate_needs if an insn needs an operand changed.  */
 static int something_needs_operands_changed;
+/* Set by alter_regs if we spilled a register to the stack.  */
+static bool something_was_spilled;
 
 /* Nonzero means we couldn't get enough spill regs.  */
 static int failure;
 
+/* Temporary array of pseudo-register number.  */
+static int *temp_pseudo_reg_arr;
+
 /* Main entry point for the reload pass.
 
    FIRST is the first insn of the function being compiled.
@@ -694,16 +698,18 @@ static int failure;
    If GLOBAL is zero, we do not have enough information to do that,
    so any pseudo reg that is spilled must go to the stack.
 
-   Return value is nonzero if reload failed
-   and we must not do any more for this function.  */
+   Return value is TRUE if reload likely left dead insns in the
+   stream and a DCE pass should be run to elimiante them.  Else the
+   return value is FALSE.  */
 
-int
+bool
 reload (rtx first, int global)
 {
-  int i;
+  int i, n;
   rtx insn;
   struct elim_table *ep;
   basic_block bb;
+  bool inserted;
 
   /* Make sure even insns with volatile mem refs are recognizable.  */
   init_recog ();
@@ -761,12 +767,7 @@ reload (rtx first, int global)
      Record memory equivalents in reg_mem_equiv so they can
      be substituted eventually by altering the REG-rtx's.  */
 
-  reg_equiv_constant = XCNEWVEC (rtx, max_regno);
-  reg_equiv_invariant = XCNEWVEC (rtx, max_regno);
-  reg_equiv_mem = XCNEWVEC (rtx, max_regno);
-  reg_equiv_alt_mem_list = XCNEWVEC (rtx, max_regno);
-  reg_equiv_address = XCNEWVEC (rtx, max_regno);
-  reg_max_ref_width = XCNEWVEC (unsigned int, max_regno);
+  grow_reg_equivs ();
   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);
@@ -774,121 +775,24 @@ reload (rtx first, int global)
 
   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.  */
-
-  num_eliminable_invariants = 0;
-  for (insn = first; insn; insn = NEXT_INSN (insn))
-    {
-      rtx set = single_set (insn);
-
-      /* We may introduce USEs that we want to remove at the end, so
-        we'll mark them with QImode.  Make sure there are no
-        previously-marked insns left by say regmove.  */
-      if (INSN_P (insn) && GET_CODE (PATTERN (insn)) == USE
-         && GET_MODE (insn) != VOIDmode)
-       PUT_MODE (insn, VOIDmode);
-
-      if (INSN_P (insn))
-       scan_paradoxical_subregs (PATTERN (insn));
-
-      if (set != 0 && REG_P (SET_DEST (set)))
-       {
-         rtx note = find_reg_note (insn, REG_EQUIV, NULL_RTX);
-         rtx x;
-
-         if (! note)
-           continue;
-
-         i = REGNO (SET_DEST (set));
-         x = XEXP (note, 0);
-
-         if (i <= LAST_VIRTUAL_REGISTER)
-           continue;
-
-         if (! function_invariant_p (x)
-             || ! flag_pic
-             /* A function invariant is often CONSTANT_P but may
-                include a register.  We promise to only pass
-                CONSTANT_P objects to LEGITIMATE_PIC_OPERAND_P.  */
-             || (CONSTANT_P (x)
-                 && LEGITIMATE_PIC_OPERAND_P (x)))
-           {
-             /* It can happen that a REG_EQUIV note contains a MEM
-                that is not a legitimate memory operand.  As later
-                stages of reload assume that all addresses found
-                in the reg_equiv_* arrays were originally legitimate,
-                we ignore such REG_EQUIV notes.  */
-             if (memory_operand (x, VOIDmode))
-               {
-                 /* Always unshare the equivalence, so we can
-                    substitute into this insn without touching the
-                      equivalence.  */
-                 reg_equiv_memory_loc[i] = copy_rtx (x);
-               }
-             else if (function_invariant_p (x))
-               {
-                 if (GET_CODE (x) == PLUS)
-                   {
-                     /* This is PLUS of frame pointer and a constant,
-                        and might be shared.  Unshare it.  */
-                     reg_equiv_invariant[i] = copy_rtx (x);
-                     num_eliminable_invariants++;
-                   }
-                 else if (x == frame_pointer_rtx || x == arg_pointer_rtx)
-                   {
-                     reg_equiv_invariant[i] = x;
-                     num_eliminable_invariants++;
-                   }
-                 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);
-                     if (! reg_equiv_memory_loc[i])
-                       reg_equiv_init[i] = NULL_RTX;
-                   }
-               }
-             else
-               {
-                 reg_equiv_init[i] = NULL_RTX;
-                 continue;
-               }
-           }
-         else
-           reg_equiv_init[i] = NULL_RTX;
-       }
-    }
-
-  if (dump_file)
-    for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
-      if (reg_equiv_init[i])
-       {
-         fprintf (dump_file, "init_insns for %u: ", i);
-         print_inline_rtx (dump_file, reg_equiv_init[i], 20);
-         fprintf (dump_file, "\n");
-       }
-
+  init_eliminable_invariants (first, true);
   init_elim_table ();
 
-  first_label_num = get_first_label_num ();
-  num_labels = max_label_num () - first_label_num;
+  /* Alter each pseudo-reg rtx to contain its hard reg number.  Assign
+     stack slots to the pseudos that lack hard regs or equivalents.
+     Do not touch virtual registers.  */
 
-  /* 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.  */
-  offsets_known_at = XNEWVEC (char, num_labels);
-  offsets_at = (HOST_WIDE_INT (*)[NUM_ELIMINABLE_REGS]) xmalloc (num_labels * NUM_ELIMINABLE_REGS * sizeof (HOST_WIDE_INT));
+  temp_pseudo_reg_arr = XNEWVEC (int, max_regno - LAST_VIRTUAL_REGISTER - 1);
+  for (n = 0, i = LAST_VIRTUAL_REGISTER + 1; i < max_regno; i++)
+    temp_pseudo_reg_arr[n++] = i;
 
-  /* Alter each pseudo-reg rtx to contain its hard reg number.
-     Assign stack slots to the pseudos that lack hard regs or equivalents.
-     Do not touch virtual registers.  */
+  if (ira_conflicts_p)
+    /* Ask IRA to order pseudo-registers for better stack slot
+       sharing.  */
+    ira_sort_regnos_for_alter_reg (temp_pseudo_reg_arr, n, reg_max_ref_width);
 
-  for (i = LAST_VIRTUAL_REGISTER + 1; i < max_regno; i++)
-    alter_reg (i, -1);
+  for (i = 0; i < n; i++)
+    alter_reg (temp_pseudo_reg_arr[i], -1, false);
 
   /* If we have some registers we think can be eliminated, scan all insns to
      see if there is an insn that sets one of these registers to something
@@ -927,7 +831,7 @@ reload (rtx first, int global)
        spill_hard_reg (from, 1);
     }
 
-#if HARD_FRAME_POINTER_REGNUM != FRAME_POINTER_REGNUM
+#if !HARD_FRAME_POINTER_IS_FRAME_POINTER
   if (frame_pointer_needed)
     spill_hard_reg (HARD_FRAME_POINTER_REGNUM, 1);
 #endif
@@ -947,6 +851,7 @@ reload (rtx first, int global)
       HOST_WIDE_INT starting_frame_size;
 
       starting_frame_size = get_frame_size ();
+      something_was_spilled = false;
 
       set_initial_elim_offsets ();
       set_initial_label_offsets ();
@@ -976,13 +881,15 @@ reload (rtx first, int global)
         so this problem goes away.  But that's very hairy.  */
 
       for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
-       if (reg_renumber[i] < 0 && reg_equiv_memory_loc[i])
+       if (reg_renumber[i] < 0 && reg_equiv_memory_loc (i))
          {
-           rtx x = eliminate_regs (reg_equiv_memory_loc[i], 0, NULL_RTX);
+           rtx x = eliminate_regs (reg_equiv_memory_loc (i), VOIDmode,
+                                   NULL_RTX);
 
-           if (strict_memory_address_p (GET_MODE (regno_reg_rtx[i]),
-                                        XEXP (x, 0)))
-             reg_equiv_mem[i] = x, reg_equiv_address[i] = 0;
+           if (strict_memory_address_addr_space_p
+                 (GET_MODE (regno_reg_rtx[i]), XEXP (x, 0),
+                  MEM_ADDR_SPACE (x)))
+             reg_equiv_mem (i) = x, reg_equiv_address (i) = 0;
            else if (CONSTANT_P (XEXP (x, 0))
                     || (REG_P (XEXP (x, 0))
                         && REGNO (XEXP (x, 0)) < FIRST_PSEUDO_REGISTER)
@@ -991,7 +898,7 @@ reload (rtx first, int global)
                         && (REGNO (XEXP (XEXP (x, 0), 0))
                             < FIRST_PSEUDO_REGISTER)
                         && CONSTANT_P (XEXP (XEXP (x, 0), 1))))
-             reg_equiv_address[i] = XEXP (x, 0), reg_equiv_mem[i] = 0;
+             reg_equiv_address (i) = XEXP (x, 0), reg_equiv_mem (i) = 0;
            else
              {
                /* Make a new stack slot.  Then indicate that something
@@ -1000,9 +907,9 @@ reload (rtx first, int global)
                   below might change some offset.  reg_equiv_{mem,address}
                   will be set up for this pseudo on the next pass around
                   the loop.  */
-               reg_equiv_memory_loc[i] = 0;
-               reg_equiv_init[i] = 0;
-               alter_reg (i, -1);
+               reg_equiv_memory_loc (i) = 0;
+               reg_equiv_init (i) = 0;
+               alter_reg (i, -1, true);
              }
          }
 
@@ -1010,7 +917,7 @@ reload (rtx first, int global)
        setup_save_areas ();
 
       /* If we allocated another stack slot, redo elimination bookkeeping.  */
-      if (starting_frame_size != get_frame_size ())
+      if (something_was_spilled || starting_frame_size != get_frame_size ())
        continue;
       if (starting_frame_size && crtl->stack_alignment_needed)
        {
@@ -1036,18 +943,23 @@ reload (rtx first, int global)
 
       calculate_needs_all_insns (global);
 
-      CLEAR_REG_SET (&spilled_pseudos);
+      if (! ira_conflicts_p)
+       /* Don't do it for IRA.  We need this info because we don't
+          change live_throughout and dead_or_set for chains when IRA
+          is used.  */
+       CLEAR_REG_SET (&spilled_pseudos);
+
       did_spill = 0;
 
       something_changed = 0;
 
       /* If we allocated any new memory locations, make another pass
         since it might have changed elimination offsets.  */
-      if (starting_frame_size != get_frame_size ())
+      if (something_was_spilled || starting_frame_size != get_frame_size ())
        something_changed = 1;
 
       /* Even if the frame size remained the same, we might still have
-        changed elimination offsets, e.g. if find_reloads called 
+        changed elimination offsets, e.g. if find_reloads called
         force_const_mem requiring the back end to allocate a constant
         pool base register that needs to be saved on the stack.  */
       else if (!verify_initial_elim_offsets ())
@@ -1110,10 +1022,10 @@ reload (rtx first, int global)
 
   for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
     {
-      if (reg_renumber[i] < 0 && reg_equiv_init[i] != 0)
+      if (reg_renumber[i] < 0 && reg_equiv_init (i) != 0)
        {
          rtx list;
-         for (list = reg_equiv_init[i]; list; list = XEXP (list, 1))
+         for (list = reg_equiv_init (i); list; list = XEXP (list, 1))
            {
              rtx equiv_insn = XEXP (list, 0);
 
@@ -1158,11 +1070,12 @@ reload (rtx first, int global)
   if (! frame_pointer_needed)
     FOR_EACH_BB (bb)
       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
      regs.  */
  failed:
 
+  CLEAR_REG_SET (&changed_allocation_pseudos);
   CLEAR_REG_SET (&spilled_pseudos);
   reload_in_progress = 0;
 
@@ -1180,11 +1093,11 @@ reload (rtx first, int global)
     {
       rtx addr = 0;
 
-      if (reg_equiv_mem[i])
-       addr = XEXP (reg_equiv_mem[i], 0);
+      if (reg_equiv_mem (i))
+       addr = XEXP (reg_equiv_mem (i), 0);
 
-      if (reg_equiv_address[i])
-       addr = reg_equiv_address[i];
+      if (reg_equiv_address (i))
+       addr = reg_equiv_address (i);
 
       if (addr)
        {
@@ -1195,17 +1108,60 @@ reload (rtx first, int global)
              REG_USERVAR_P (reg) = 0;
              PUT_CODE (reg, MEM);
              XEXP (reg, 0) = addr;
-             if (reg_equiv_memory_loc[i])
-               MEM_COPY_ATTRIBUTES (reg, reg_equiv_memory_loc[i]);
+             if (reg_equiv_memory_loc (i))
+               MEM_COPY_ATTRIBUTES (reg, reg_equiv_memory_loc (i));
              else
+               MEM_ATTRS (reg) = 0;
+             MEM_NOTRAP_P (reg) = 1;
+           }
+         else if (reg_equiv_mem (i))
+           XEXP (reg_equiv_mem (i), 0) = addr;
+       }
+
+      /* We don't want complex addressing modes in debug insns
+        if simpler ones will do, so delegitimize equivalences
+        in debug insns.  */
+      if (MAY_HAVE_DEBUG_INSNS && reg_renumber[i] < 0)
+       {
+         rtx reg = regno_reg_rtx[i];
+         rtx equiv = 0;
+         df_ref use, next;
+
+         if (reg_equiv_constant (i))
+           equiv = reg_equiv_constant (i);
+         else if (reg_equiv_invariant (i))
+           equiv = reg_equiv_invariant (i);
+         else if (reg && MEM_P (reg))
+           equiv = targetm.delegitimize_address (reg);
+         else if (reg && REG_P (reg) && (int)REGNO (reg) != i)
+           equiv = reg;
+
+         if (equiv == reg)
+           continue;
+
+         for (use = DF_REG_USE_CHAIN (i); use; use = next)
+           {
+             insn = DF_REF_INSN (use);
+
+             /* Make sure the next ref is for a different instruction,
+                so that we're not affected by the rescan.  */
+             next = DF_REF_NEXT_REG (use);
+             while (next && DF_REF_INSN (next) == insn)
+               next = DF_REF_NEXT_REG (next);
+
+             if (DEBUG_INSN_P (insn))
                {
-                 MEM_IN_STRUCT_P (reg) = MEM_SCALAR_P (reg) = 0;
-                 MEM_ATTRS (reg) = 0;
+                 if (!equiv)
+                   {
+                     INSN_VAR_LOCATION_LOC (insn) = gen_rtx_UNKNOWN_VAR_LOC ();
+                     df_insn_rescan_debug_internal (insn);
+                   }
+                 else
+                   INSN_VAR_LOCATION_LOC (insn)
+                     = simplify_replace_rtx (INSN_VAR_LOCATION_LOC (insn),
+                                             reg, equiv);
                }
-             MEM_NOTRAP_P (reg) = 1;
            }
-         else if (reg_equiv_mem[i])
-           XEXP (reg_equiv_mem[i], 0) = addr;
        }
     }
 
@@ -1323,29 +1279,11 @@ reload (rtx first, int global)
        }
     }
 
-  /* Indicate that we no longer have known memory locations or constants.  */
-  if (reg_equiv_constant)
-    free (reg_equiv_constant);
-  if (reg_equiv_invariant)
-    free (reg_equiv_invariant);
-  reg_equiv_constant = 0;
-  reg_equiv_invariant = 0;
-  VEC_free (rtx, gc, reg_equiv_memory_loc_vec);
-  reg_equiv_memory_loc = 0;
-
-  if (offsets_known_at)
-    free (offsets_known_at);
-  if (offsets_at)
-    free (offsets_at);
+  free (temp_pseudo_reg_arr);
 
-  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]);
-  free (reg_equiv_alt_mem_list);
+  /* Indicate that we no longer have known memory locations or constants.  */
+  free_reg_equiv ();
 
-  free (reg_equiv_mem);
-  reg_equiv_init = 0;
-  free (reg_equiv_address);
   free (reg_max_ref_width);
   free (reg_old_renumber);
   free (pseudo_previous_regs);
@@ -1358,7 +1296,21 @@ reload (rtx first, int global)
   /* Free all the insn_chain structures at once.  */
   obstack_free (&reload_obstack, reload_startobj);
   unused_insn_chains = 0;
-  fixup_abnormal_edges ();
+
+  inserted = fixup_abnormal_edges ();
+
+  /* We've possibly turned single trapping insn into multiple ones.  */
+  if (cfun->can_throw_non_call_exceptions)
+    {
+      sbitmap blocks;
+      blocks = sbitmap_alloc (last_basic_block);
+      sbitmap_ones (blocks);
+      find_many_sub_basic_blocks (blocks);
+      sbitmap_free (blocks);
+    }
+
+  if (inserted)
+    commit_edge_insertions ();
 
   /* Replacing pseudos with their memory equivalents might have
      created shared rtx.  Subsequent passes would get confused
@@ -1373,7 +1325,13 @@ reload (rtx first, int global)
     REGNO_POINTER_ALIGN (HARD_FRAME_POINTER_REGNUM) = BITS_PER_UNIT;
 #endif
 
-  return failure;
+  VEC_free (rtx_p, heap, substitute_stack);
+
+  gcc_assert (bitmap_empty_p (&spilled_pseudos));
+
+  reload_completed = !failure;
+
+  return need_dce;
 }
 
 /* Yet another special case.  Unfortunately, reg-stack forces people to
@@ -1460,7 +1418,8 @@ maybe_fix_stack_asms (void)
 
                case 'p':
                  cls = (int) reg_class_subunion[cls]
-                     [(int) base_reg_class (VOIDmode, ADDRESS, SCRATCH)];
+                     [(int) base_reg_class (VOIDmode, ADDR_SPACE_GENERIC,
+                                            ADDRESS, SCRATCH)];
                  break;
 
                case 'g':
@@ -1471,7 +1430,8 @@ maybe_fix_stack_asms (void)
                default:
                  if (EXTRA_ADDRESS_CONSTRAINT (c, p))
                    cls = (int) reg_class_subunion[cls]
-                     [(int) base_reg_class (VOIDmode, ADDRESS, SCRATCH)];
+                     [(int) base_reg_class (VOIDmode, ADDR_SPACE_GENERIC,
+                                            ADDRESS, SCRATCH)];
                  else
                    cls = (int) reg_class_subunion[cls]
                      [(int) REG_CLASS_FROM_CONSTRAINT (c, p)];
@@ -1549,9 +1509,9 @@ calculate_needs_all_insns (int global)
          /* 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))])
+             && (reg_equiv_constant (REGNO (SET_DEST (set)))
+                 || (reg_equiv_invariant (REGNO (SET_DEST (set)))))
+                     && reg_equiv_init (REGNO (SET_DEST (set))))
            continue;
 
          /* If needed, eliminate any eliminable registers.  */
@@ -1573,10 +1533,22 @@ calculate_needs_all_insns (int global)
            {
              rtx set = single_set (insn);
              if (set
-                 && SET_SRC (set) == SET_DEST (set)
-                 && REG_P (SET_SRC (set))
-                 && REGNO (SET_SRC (set)) >= FIRST_PSEUDO_REGISTER)
+                 &&
+                 ((SET_SRC (set) == SET_DEST (set)
+                   && REG_P (SET_SRC (set))
+                   && REGNO (SET_SRC (set)) >= FIRST_PSEUDO_REGISTER)
+                  || (REG_P (SET_SRC (set)) && REG_P (SET_DEST (set))
+                      && reg_renumber[REGNO (SET_SRC (set))] < 0
+                      && reg_renumber[REGNO (SET_DEST (set))] < 0
+                      && reg_equiv_memory_loc (REGNO (SET_SRC (set))) != NULL
+                      && reg_equiv_memory_loc (REGNO (SET_DEST (set))) != NULL
+                      && rtx_equal_p (reg_equiv_memory_loc (REGNO (SET_SRC (set))),
+                                      reg_equiv_memory_loc (REGNO (SET_DEST (set)))))))
                {
+                 if (ira_conflicts_p)
+                   /* Inform IRA about the insn deletion.  */
+                   ira_mark_memory_move_deletion (REGNO (SET_DEST (set)),
+                                                  REGNO (SET_SRC (set)));
                  delete_insn (insn);
                  /* Delete it from the reload chain.  */
                  if (chain->prev)
@@ -1622,6 +1594,102 @@ calculate_needs_all_insns (int global)
   *pprev_reload = 0;
 }
 \f
+/* This function is called from the register allocator to set up estimates
+   for the cost of eliminating pseudos which have REG_EQUIV equivalences to
+   an invariant.  The structure is similar to calculate_needs_all_insns.  */
+
+void
+calculate_elim_costs_all_insns (void)
+{
+  int *reg_equiv_init_cost;
+  basic_block bb;
+  int i;
+
+  reg_equiv_init_cost = XCNEWVEC (int, max_regno);
+  init_elim_table ();
+  init_eliminable_invariants (get_insns (), false);
+
+  set_initial_elim_offsets ();
+  set_initial_label_offsets ();
+
+  FOR_EACH_BB (bb)
+    {
+      rtx insn;
+      elim_bb = bb;
+
+      FOR_BB_INSNS (bb, insn)
+       {
+         /* If this is a label, a JUMP_INSN, or has REG_NOTES (which might
+            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)
+             || (INSN_P (insn) && REG_NOTES (insn) != 0))
+           set_label_offsets (insn, insn, 0);
+
+         if (INSN_P (insn))
+           {
+             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)))))
+               {
+                 unsigned regno = REGNO (SET_DEST (set));
+                 rtx init = reg_equiv_init (regno);
+                 if (init)
+                   {
+                     rtx t = eliminate_regs_1 (SET_SRC (set), VOIDmode, insn,
+                                               false, true);
+                     int cost = set_src_cost (t, optimize_bb_for_speed_p (bb));
+                     int freq = REG_FREQ_FROM_BB (bb);
+
+                     reg_equiv_init_cost[regno] = cost * freq;
+                     continue;
+                   }
+               }
+             /* If needed, eliminate any eliminable registers.  */
+             if (num_eliminable || num_eliminable_invariants)
+               elimination_costs_in_insn (insn);
+
+             if (num_eliminable)
+               update_eliminable_offsets ();
+           }
+       }
+    }
+  for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
+    {
+      if (reg_equiv_invariant (i))
+       {
+         if (reg_equiv_init (i))
+           {
+             int cost = reg_equiv_init_cost[i];
+             if (dump_file)
+               fprintf (dump_file,
+                        "Reg %d has equivalence, initial gains %d\n", i, cost);
+             if (cost != 0)
+               ira_adjust_equiv_reg_cost (i, cost);
+           }
+         else
+           {
+             if (dump_file)
+               fprintf (dump_file,
+                        "Reg %d had equivalence, but can't be eliminated\n",
+                        i);
+             ira_adjust_equiv_reg_cost (i, 0);
+           }
+       }
+    }
+
+  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
    should be handled first.  *P1 and *P2 are the reload numbers.  */
 
@@ -1665,6 +1733,10 @@ static int spill_cost[FIRST_PSEUDO_REGISTER];
    only the first hard reg for a multi-reg pseudo.  */
 static int spill_add_cost[FIRST_PSEUDO_REGISTER];
 
+/* Map of hard regno to pseudo regno currently occupying the hard
+   reg.  */
+static int hard_regno_to_pseudo_regno[FIRST_PSEUDO_REGISTER];
+
 /* Update the spill cost arrays, considering that pseudo REG is live.  */
 
 static void
@@ -1675,7 +1747,10 @@ count_pseudo (int reg)
   int nregs;
 
   if (REGNO_REG_SET_P (&pseudos_counted, reg)
-      || REGNO_REG_SET_P (&spilled_pseudos, 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))
     return;
 
   SET_REGNO_REG_SET (&pseudos_counted, reg);
@@ -1683,10 +1758,12 @@ count_pseudo (int reg)
   gcc_assert (r >= 0);
 
   spill_add_cost[r] += freq;
-
   nregs = hard_regno_nregs[r][PSEUDO_REGNO_MODE (reg)];
   while (nregs-- > 0)
-    spill_cost[r + nregs] += freq;
+    {
+      hard_regno_to_pseudo_regno[r + nregs] = reg;
+      spill_cost[r + nregs] += freq;
+    }
 }
 
 /* Calculate the SPILL_COST and SPILL_ADD_COST arrays and determine the
@@ -1704,6 +1781,8 @@ order_regs_for_reload (struct insn_chain *chain)
 
   memset (spill_cost, 0, sizeof spill_cost);
   memset (spill_add_cost, 0, sizeof spill_add_cost);
+  for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+    hard_regno_to_pseudo_regno[i] = -1;
 
   /* Count number of uses of each hard reg by pseudo regs allocated to it
      and then order them by decreasing use.  First exclude hard registers
@@ -1746,18 +1825,25 @@ static HARD_REG_SET used_spill_regs_local;
 static void
 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)];
 
-  if (REGNO_REG_SET_P (&spilled_pseudos, reg)
+  /* 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)
       || spilled + spilled_nregs <= r || r + nregs <= spilled)
     return;
 
   SET_REGNO_REG_SET (&spilled_pseudos, reg);
 
-  spill_add_cost[r] -= REG_FREQ (reg);
+  spill_add_cost[r] -= freq;
   while (nregs-- > 0)
-    spill_cost[r + nregs] -= REG_FREQ (reg);
+    {
+      hard_regno_to_pseudo_regno[r + nregs] = -1;
+      spill_cost[r + nregs] -= freq;
+    }
 }
 
 /* Find reload register to use for reload number ORDER.  */
@@ -1769,11 +1855,13 @@ find_reg (struct insn_chain *chain, int order)
   struct reload *rl = rld + rnum;
   int best_cost = INT_MAX;
   int best_reg = -1;
-  unsigned int i, j;
+  unsigned int i, j, n;
   int k;
   HARD_REG_SET not_usable;
   HARD_REG_SET used_by_other_reload;
   reg_set_iterator rsi;
+  static int regno_pseudo_regs[FIRST_PSEUDO_REGISTER];
+  static int best_regno_pseudo_regs[FIRST_PSEUDO_REGISTER];
 
   COPY_HARD_REG_SET (not_usable, bad_spill_regs);
   IOR_HARD_REG_SET (not_usable, bad_spill_regs_global);
@@ -1791,7 +1879,11 @@ find_reg (struct insn_chain *chain, int order)
 
   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
     {
+#ifdef REG_ALLOC_ORDER
+      unsigned int regno = reg_alloc_order[i];
+#else
       unsigned int regno = i;
+#endif
 
       if (! TEST_HARD_REG_BIT (not_usable, regno)
          && ! TEST_HARD_REG_BIT (used_by_other_reload, regno)
@@ -1810,6 +1902,38 @@ find_reg (struct insn_chain *chain, int order)
            }
          if (! ok)
            continue;
+
+         if (ira_conflicts_p)
+           {
+             /* Ask IRA to find a better pseudo-register for
+                spilling.  */
+             for (n = j = 0; j < this_nregs; j++)
+               {
+                 int r = hard_regno_to_pseudo_regno[regno + j];
+
+                 if (r < 0)
+                   continue;
+                 if (n == 0 || regno_pseudo_regs[n - 1] != r)
+                   regno_pseudo_regs[n++] = r;
+               }
+             regno_pseudo_regs[n++] = -1;
+             if (best_reg < 0
+                 || ira_better_spill_reload_regno_p (regno_pseudo_regs,
+                                                     best_regno_pseudo_regs,
+                                                     rl->in, rl->out,
+                                                     chain->insn))
+               {
+                 best_reg = regno;
+                 for (j = 0;; j++)
+                   {
+                     best_regno_pseudo_regs[j] = regno_pseudo_regs[j];
+                     if (regno_pseudo_regs[j] < 0)
+                       break;
+                   }
+               }
+             continue;
+           }
+
          if (rl->in && REG_P (rl->in) && REGNO (rl->in) == regno)
            this_cost--;
          if (rl->out && REG_P (rl->out) && REGNO (rl->out) == regno)
@@ -1857,6 +1981,7 @@ find_reg (struct insn_chain *chain, int order)
     {
       gcc_assert (spill_cost[best_reg + i] == 0);
       gcc_assert (spill_add_cost[best_reg + i] == 0);
+      gcc_assert (hard_regno_to_pseudo_regno[best_reg + i] == -1);
       SET_HARD_REG_BIT (used_spill_regs_local, best_reg + i);
     }
   return 1;
@@ -1979,7 +2104,7 @@ static void
 spill_failure (rtx insn, enum reg_class rclass)
 {
   if (asm_noperands (PATTERN (insn)) >= 0)
-    error_for_asm (insn, "can't find a register in class %qs while "
+    error_for_asm (insn, "can%'t find a register in class %qs while "
                   "reloading %<asm%>",
                   reg_class_names[rclass]);
   else
@@ -2002,17 +2127,22 @@ spill_failure (rtx insn, enum reg_class rclass)
 static void
 delete_dead_insn (rtx insn)
 {
-  rtx prev = prev_real_insn (insn);
+  rtx prev = prev_active_insn (insn);
   rtx prev_dest;
 
-  /* If the previous insn sets a register that dies in our insn, delete it
-     too.  */
+  /* If the previous insn sets a register that dies in our insn make
+     a note that we want to run DCE immediately after reload.
+
+     We used to delete the previous insn & recurse, but that's wrong for
+     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
       && (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))
       && ! side_effects_p (SET_SRC (PATTERN (prev))))
-    delete_dead_insn (prev);
+    need_dce = 1;
 
   SET_INSN_DELETED (insn);
 }
@@ -2026,7 +2156,7 @@ delete_dead_insn (rtx insn)
    can share one stack slot.  */
 
 static void
-alter_reg (int i, int from_reg)
+alter_reg (int i, int from_reg, bool dont_share_p)
 {
   /* When outputting an inline function, this can happen
      for a reg that isn't actually used.  */
@@ -2048,11 +2178,12 @@ alter_reg (int i, int from_reg)
 
   if (reg_renumber[i] < 0
       && REG_N_REFS (i) > 0
-      && reg_equiv_constant[i] == 0
-      && (reg_equiv_invariant[i] == 0 || reg_equiv_init[i] == 0)
-      && reg_equiv_memory_loc[i] == 0)
+      && reg_equiv_constant (i) == 0
+      && (reg_equiv_invariant (i) == 0
+         || reg_equiv_init (i) == 0)
+      && reg_equiv_memory_loc (i) == 0)
     {
-      rtx x;
+      rtx x = NULL_RTX;
       enum 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);
@@ -2060,6 +2191,19 @@ alter_reg (int i, int from_reg)
       unsigned int min_align = reg_max_ref_width[i] * BITS_PER_UNIT;
       int adjust = 0;
 
+      something_was_spilled = true;
+
+      if (ira_conflicts_p)
+       {
+         /* Mark the spill for IRA.  */
+         SET_REGNO_REG_SET (&spilled_pseudos, i);
+         if (!dont_share_p)
+           x = ira_reuse_stack_slot (i, inherent_size, total_size);
+       }
+
+      if (x)
+       ;
+
       /* Each pseudo reg has an inherent size which comes from its own mode,
         and a total size which provides room for paradoxical subregs
         which refer to the pseudo reg in wider modes.
@@ -2068,24 +2212,34 @@ alter_reg (int i, int from_reg)
         enough inherent space and enough total space.
         Otherwise, we allocate a new slot, making sure that it has no less
         inherent space, and no less total space, then the previous slot.  */
-      if (from_reg == -1)
+      else if (from_reg == -1 || (!dont_share_p && ira_conflicts_p))
        {
-         alias_set_type alias_set = new_alias_set ();
+         rtx stack_slot;
 
          /* No known place to spill from => no slot to reuse.  */
          x = assign_stack_local (mode, total_size,
                                  min_align > inherent_align
                                  || total_size > inherent_size ? -1 : 0);
+
+         stack_slot = x;
+
+         /* Cancel the big-endian correction done in assign_stack_local.
+            Get the address of the beginning of the slot.  This is so we
+            can do a big-endian correction unconditionally below.  */
          if (BYTES_BIG_ENDIAN)
-           /* Cancel the  big-endian correction done in assign_stack_local.
-              Get the address of the beginning of the slot.
-              This is so we can do a big-endian correction unconditionally
-              below.  */
-           adjust = inherent_size - total_size;
-
-         /* Nothing can alias this slot except this pseudo.  */
-         set_mem_alias_set (x, alias_set);
-         dse_record_singleton_alias_set (alias_set, mode);
+           {
+             adjust = inherent_size - total_size;
+             if (adjust)
+               stack_slot
+                 = adjust_address_nv (x, mode_for_size (total_size
+                                                        * BITS_PER_UNIT,
+                                                        MODE_INT, 1),
+                                      adjust);
+           }
+
+         if (! dont_share_p && ira_conflicts_p)
+           /* Inform IRA about allocation a new stack slot.  */
+           ira_mark_new_stack_slot (stack_slot, i, total_size);
        }
 
       /* Reuse a stack slot if possible.  */
@@ -2095,6 +2249,7 @@ alter_reg (int i, int from_reg)
                   >= inherent_size)
               && MEM_ALIGN (spill_stack_slot[from_reg]) >= min_align)
        x = spill_stack_slot[from_reg];
+
       /* Allocate a bigger slot.  */
       else
        {
@@ -2119,27 +2274,11 @@ alter_reg (int i, int from_reg)
                                  || total_size > inherent_size ? -1 : 0);
          stack_slot = x;
 
-         /* All pseudos mapped to this slot can alias each other.  */
-         if (spill_stack_slot[from_reg])
-           {
-             alias_set_type alias_set 
-               = MEM_ALIAS_SET (spill_stack_slot[from_reg]);
-             set_mem_alias_set (x, alias_set);
-             dse_invalidate_singleton_alias_set (alias_set);
-           }
-         else
-           {
-             alias_set_type alias_set = new_alias_set ();
-             set_mem_alias_set (x, alias_set);
-             dse_record_singleton_alias_set (alias_set, mode);
-           }
-
+         /* Cancel the  big-endian correction done in assign_stack_local.
+            Get the address of the beginning of the slot.  This is so we
+            can do a big-endian correction unconditionally below.  */
          if (BYTES_BIG_ENDIAN)
            {
-             /* Cancel the  big-endian correction done in assign_stack_local.
-                Get the address of the beginning of the slot.
-                This is so we can do a big-endian correction unconditionally
-                below.  */
              adjust = GET_MODE_SIZE (mode) - total_size;
              if (adjust)
                stack_slot
@@ -2162,28 +2301,11 @@ alter_reg (int i, int from_reg)
         wrong mode, make a new stack slot.  */
       x = adjust_address_nv (x, GET_MODE (regno_reg_rtx[i]), adjust);
 
-      /* If we have a decl for the original register, set it for the
-        memory.  If this is a shared MEM, make a copy.  */
-      if (REG_EXPR (regno_reg_rtx[i])
-         && DECL_P (REG_EXPR (regno_reg_rtx[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
-            is reused, nonoverlapping_memrefs_p might think they
-            cannot overlap.  */
-         if (decl && REG_P (decl) && REGNO (decl) == (unsigned) i)
-           {
-             if (from_reg != -1 && spill_stack_slot[from_reg] == x)
-               x = copy_rtx (x);
-
-             set_mem_attrs_from_reg (x, regno_reg_rtx[i]);
-           }
-       }
+      /* Set all of the memory attributes as appropriate for a spill.  */
+      set_mem_attrs_for_spill (x);
 
       /* Save the stack slot for later.  */
-      reg_equiv_memory_loc[i] = x;
+      reg_equiv_memory_loc (i) = x;
     }
 }
 
@@ -2362,6 +2484,36 @@ 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.  */
+
+static int
+note_reg_elim_costly (rtx *px, void *data)
+{
+  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);
+
+      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
    replacement (such as sp), plus an offset.
 
@@ -2381,6 +2533,9 @@ set_label_offsets (rtx x, rtx insn, int initial_p)
    This means, do not set ref_outside_mem even if the reference
    is outside of MEMs.
 
+   If FOR_COSTS is true, we are being called before reload in order to
+   estimate the costs of keeping registers with an equivalence unallocated.
+
    REG_EQUIV_MEM and REG_EQUIV_ADDRESS contain address that have had
    replacements done assuming all offsets are at their initial values.  If
    they are not, or if REG_EQUIV_ADDRESS is nonzero for a pseudo we
@@ -2389,7 +2544,7 @@ set_label_offsets (rtx x, rtx insn, int initial_p)
 
 static rtx
 eliminate_regs_1 (rtx x, enum machine_mode mem_mode, rtx insn,
-                 bool may_use_invariant)
+                 bool may_use_invariant, bool for_costs)
 {
   enum rtx_code code = GET_CODE (x);
   struct elim_table *ep;
@@ -2433,15 +2588,17 @@ eliminate_regs_1 (rtx x, enum machine_mode mem_mode, rtx insn,
 
        }
       else if (reg_renumber && reg_renumber[regno] < 0
-              && reg_equiv_invariant && reg_equiv_invariant[regno])
+              && reg_equivs
+              && reg_equiv_invariant (regno))
        {
-         if (may_use_invariant)
-           return eliminate_regs_1 (copy_rtx (reg_equiv_invariant[regno]),
-                                    mem_mode, insn, true);
+         if (may_use_invariant || (insn && DEBUG_INSN_P (insn)))
+           return eliminate_regs_1 (copy_rtx (reg_equiv_invariant (regno)),
+                                    mem_mode, insn, true, for_costs);
          /* There exists at least one use of REGNO that cannot be
             eliminated.  Prevent the defining insn from being deleted.  */
-         reg_equiv_init[regno] = NULL_RTX;
-         alter_reg (regno, -1);
+         reg_equiv_init (regno) = NULL_RTX;
+         if (!for_costs)
+           alter_reg (regno, -1, true);
        }
       return x;
 
@@ -2478,7 +2635,7 @@ eliminate_regs_1 (rtx x, enum machine_mode mem_mode, rtx insn,
                   We special-case the commonest situation in
                   eliminate_regs_in_insn, so just replace a PLUS with a
                   PLUS here, unless inside a MEM.  */
-               if (mem_mode != 0 && GET_CODE (XEXP (x, 1)) == CONST_INT
+               if (mem_mode != 0 && CONST_INT_P (XEXP (x, 1))
                    && INTVAL (XEXP (x, 1)) == - ep->previous_offset)
                  return ep->to_rtx;
                else
@@ -2502,8 +2659,10 @@ eliminate_regs_1 (rtx x, enum machine_mode mem_mode, rtx insn,
         operand of a load-address insn.  */
 
       {
-       rtx new0 = eliminate_regs_1 (XEXP (x, 0), mem_mode, insn, true);
-       rtx new1 = eliminate_regs_1 (XEXP (x, 1), mem_mode, insn, true);
+       rtx new0 = eliminate_regs_1 (XEXP (x, 0), mem_mode, insn, true,
+                                    for_costs);
+       rtx new1 = eliminate_regs_1 (XEXP (x, 1), mem_mode, insn, true,
+                                    for_costs);
 
        if (reg_renumber && (new0 != XEXP (x, 0) || new1 != XEXP (x, 1)))
          {
@@ -2514,16 +2673,16 @@ eliminate_regs_1 (rtx x, enum machine_mode mem_mode, rtx insn,
            if (GET_CODE (new0) == PLUS && REG_P (new1)
                && REGNO (new1) >= FIRST_PSEUDO_REGISTER
                && reg_renumber[REGNO (new1)] < 0
-               && reg_equiv_constant != 0
-               && reg_equiv_constant[REGNO (new1)] != 0)
-             new1 = reg_equiv_constant[REGNO (new1)];
+               && reg_equivs
+               && reg_equiv_constant (REGNO (new1)) != 0)
+             new1 = reg_equiv_constant (REGNO (new1));
            else if (GET_CODE (new1) == PLUS && REG_P (new0)
                     && REGNO (new0) >= FIRST_PSEUDO_REGISTER
                     && reg_renumber[REGNO (new0)] < 0
-                    && reg_equiv_constant[REGNO (new0)] != 0)
-             new0 = reg_equiv_constant[REGNO (new0)];
+                    && reg_equiv_constant (REGNO (new0)) != 0)
+             new0 = reg_equiv_constant (REGNO (new0));
 
-           new_rtx = form_sum (new0, new1);
+           new_rtx = form_sum (GET_MODE (x), new0, new1);
 
            /* As above, if we are not inside a MEM we do not want to
               turn a PLUS into something else.  We might try to do so here
@@ -2544,15 +2703,17 @@ eliminate_regs_1 (rtx x, enum machine_mode mem_mode, rtx insn,
         We ignore the possibility of overflow here.  */
       if (REG_P (XEXP (x, 0))
          && REGNO (XEXP (x, 0)) < FIRST_PSEUDO_REGISTER
-         && GET_CODE (XEXP (x, 1)) == CONST_INT)
+         && CONST_INT_P (XEXP (x, 1)))
        for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS];
             ep++)
          if (ep->from_rtx == XEXP (x, 0) && ep->can_eliminate)
            {
              if (! mem_mode
-                 /* Refs inside notes don't count for this purpose.  */
+                 /* Refs inside notes or in DEBUG_INSNs don't count for
+                    this purpose.  */
                  && ! (insn != 0 && (GET_CODE (insn) == EXPR_LIST
-                                     || GET_CODE (insn) == INSN_LIST)))
+                                     || GET_CODE (insn) == INSN_LIST
+                                     || DEBUG_INSN_P (insn))))
                ep->ref_outside_mem = 1;
 
              return
@@ -2575,9 +2736,11 @@ eliminate_regs_1 (rtx x, enum machine_mode mem_mode, rtx insn,
     case GE:       case GT:       case GEU:    case GTU:
     case LE:       case LT:       case LEU:    case LTU:
       {
-       rtx new0 = eliminate_regs_1 (XEXP (x, 0), mem_mode, insn, false);
+       rtx new0 = eliminate_regs_1 (XEXP (x, 0), mem_mode, insn, false,
+                                    for_costs);
        rtx new1 = XEXP (x, 1)
-                  ? eliminate_regs_1 (XEXP (x, 1), mem_mode, insn, false) : 0;
+         ? eliminate_regs_1 (XEXP (x, 1), mem_mode, insn, false,
+                             for_costs) : 0;
 
        if (new0 != XEXP (x, 0) || new1 != XEXP (x, 1))
          return gen_rtx_fmt_ee (code, GET_MODE (x), new0, new1);
@@ -2588,18 +2751,20 @@ eliminate_regs_1 (rtx x, enum machine_mode mem_mode, rtx insn,
       /* If we have something in XEXP (x, 0), the usual case, eliminate it.  */
       if (XEXP (x, 0))
        {
-         new_rtx = eliminate_regs_1 (XEXP (x, 0), mem_mode, insn, true);
+         new_rtx = eliminate_regs_1 (XEXP (x, 0), mem_mode, insn, true,
+                                     for_costs);
          if (new_rtx != XEXP (x, 0))
            {
              /* If this is a REG_DEAD note, it is not valid anymore.
                 Using the eliminated version could result in creating a
                 REG_DEAD note for the stack or frame pointer.  */
-             if (GET_MODE (x) == REG_DEAD)
+             if (REG_NOTE_KIND (x) == REG_DEAD)
                return (XEXP (x, 1)
-                       ? eliminate_regs_1 (XEXP (x, 1), mem_mode, insn, true)
+                       ? eliminate_regs_1 (XEXP (x, 1), mem_mode, insn, true,
+                                           for_costs)
                        : NULL_RTX);
 
-             x = gen_rtx_EXPR_LIST (REG_NOTE_KIND (x), new_rtx, XEXP (x, 1));
+             x = alloc_reg_note (REG_NOTE_KIND (x), new_rtx, XEXP (x, 1));
            }
        }
 
@@ -2611,7 +2776,8 @@ eliminate_regs_1 (rtx x, enum machine_mode mem_mode, rtx insn,
         strictly needed, but it simplifies the code.  */
       if (XEXP (x, 1))
        {
-         new_rtx = eliminate_regs_1 (XEXP (x, 1), mem_mode, insn, true);
+         new_rtx = eliminate_regs_1 (XEXP (x, 1), mem_mode, insn, true,
+                                     for_costs);
          if (new_rtx != XEXP (x, 1))
            return
              gen_rtx_fmt_ee (GET_CODE (x), GET_MODE (x), XEXP (x, 0), new_rtx);
@@ -2637,7 +2803,7 @@ eliminate_regs_1 (rtx x, enum machine_mode mem_mode, rtx insn,
          && XEXP (XEXP (x, 1), 0) == XEXP (x, 0))
        {
          rtx new_rtx = eliminate_regs_1 (XEXP (XEXP (x, 1), 1), mem_mode,
-                                     insn, true);
+                                         insn, true, for_costs);
 
          if (new_rtx != XEXP (XEXP (x, 1), 1))
            return gen_rtx_fmt_ee (code, GET_MODE (x), XEXP (x, 0),
@@ -2660,7 +2826,8 @@ eliminate_regs_1 (rtx x, enum machine_mode mem_mode, rtx insn,
     case POPCOUNT:
     case PARITY:
     case BSWAP:
-      new_rtx = eliminate_regs_1 (XEXP (x, 0), mem_mode, insn, false);
+      new_rtx = eliminate_regs_1 (XEXP (x, 0), mem_mode, insn, false,
+                                 for_costs);
       if (new_rtx != XEXP (x, 0))
        return gen_rtx_fmt_e (code, GET_MODE (x), new_rtx);
       return x;
@@ -2673,15 +2840,14 @@ eliminate_regs_1 (rtx x, enum machine_mode mem_mode, rtx insn,
         eliminated version of the memory location because push_reload
         may do the replacement in certain circumstances.  */
       if (REG_P (SUBREG_REG (x))
-         && (GET_MODE_SIZE (GET_MODE (x))
-             <= GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))))
-         && reg_equiv_memory_loc != 0
-         && reg_equiv_memory_loc[REGNO (SUBREG_REG (x))] != 0)
+         && !paradoxical_subreg_p (x)
+         && reg_equivs
+         && reg_equiv_memory_loc (REGNO (SUBREG_REG (x))) != 0)
        {
          new_rtx = SUBREG_REG (x);
        }
       else
-       new_rtx = eliminate_regs_1 (SUBREG_REG (x), mem_mode, insn, false);
+       new_rtx = eliminate_regs_1 (SUBREG_REG (x), mem_mode, insn, false, for_costs);
 
       if (new_rtx != SUBREG_REG (x))
        {
@@ -2715,20 +2881,29 @@ eliminate_regs_1 (rtx x, enum machine_mode mem_mode, rtx insn,
       /* Our only special processing is to pass the mode of the MEM to our
         recursive call and copy the flags.  While we are here, handle this
         case more efficiently.  */
-      return
-       replace_equiv_address_nv (x,
-                                 eliminate_regs_1 (XEXP (x, 0), GET_MODE (x),
-                                                   insn, true));
+
+      new_rtx = eliminate_regs_1 (XEXP (x, 0), GET_MODE (x), insn, true,
+                                 for_costs);
+      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);
+
+      return replace_equiv_address_nv (x, new_rtx);
 
     case USE:
       /* Handle insn_list USE that a call to a pure function may generate.  */
-      new_rtx = eliminate_regs_1 (XEXP (x, 0), 0, insn, false);
+      new_rtx = eliminate_regs_1 (XEXP (x, 0), VOIDmode, insn, false,
+                                 for_costs);
       if (new_rtx != XEXP (x, 0))
        return gen_rtx_USE (GET_MODE (x), new_rtx);
       return x;
 
     case CLOBBER:
     case ASM_OPERANDS:
+      gcc_assert (insn && DEBUG_INSN_P (insn));
+      break;
+
     case SET:
       gcc_unreachable ();
 
@@ -2743,7 +2918,8 @@ eliminate_regs_1 (rtx x, enum machine_mode mem_mode, rtx insn,
     {
       if (*fmt == 'e')
        {
-         new_rtx = eliminate_regs_1 (XEXP (x, i), mem_mode, insn, false);
+         new_rtx = eliminate_regs_1 (XEXP (x, i), mem_mode, insn, false,
+                                     for_costs);
          if (new_rtx != XEXP (x, i) && ! copied)
            {
              x = shallow_copy_rtx (x);
@@ -2756,7 +2932,8 @@ eliminate_regs_1 (rtx x, enum machine_mode mem_mode, rtx insn,
          int copied_vec = 0;
          for (j = 0; j < XVECLEN (x, i); j++)
            {
-             new_rtx = eliminate_regs_1 (XVECEXP (x, i, j), mem_mode, insn, false);
+             new_rtx = eliminate_regs_1 (XVECEXP (x, i, j), mem_mode, insn, false,
+                                         for_costs);
              if (new_rtx != XVECEXP (x, i, j) && ! copied_vec)
                {
                  rtvec new_v = gen_rtvec_v (XVECLEN (x, i),
@@ -2780,7 +2957,7 @@ eliminate_regs_1 (rtx x, enum machine_mode mem_mode, rtx insn,
 rtx
 eliminate_regs (rtx x, enum machine_mode mem_mode, rtx insn)
 {
-  return eliminate_regs_1 (x, mem_mode, insn, false);
+  return eliminate_regs_1 (x, mem_mode, insn, false, false);
 }
 
 /* Scan rtx X for modifications of elimination target registers.  Update
@@ -2830,10 +3007,11 @@ elimination_effects (rtx x, enum machine_mode mem_mode)
              }
 
        }
-      else if (reg_renumber[regno] < 0 && reg_equiv_constant
-              && reg_equiv_constant[regno]
-              && ! function_invariant_p (reg_equiv_constant[regno]))
-       elimination_effects (reg_equiv_constant[regno], mem_mode);
+      else if (reg_renumber[regno] < 0
+              && reg_equivs != 0
+              && reg_equiv_constant (regno)
+              && ! function_invariant_p (reg_equiv_constant (regno)))
+       elimination_effects (reg_equiv_constant (regno), mem_mode);
       return;
 
     case PRE_INC:
@@ -2901,8 +3079,8 @@ 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_equiv_memory_loc != 0
-         && reg_equiv_memory_loc[REGNO (SUBREG_REG (x))] != 0)
+         && reg_equivs != 0
+         && reg_equiv_memory_loc (REGNO (SUBREG_REG (x))) != 0)
        return;
 
       elimination_effects (SUBREG_REG (x), mem_mode);
@@ -2956,15 +3134,15 @@ elimination_effects (rtx x, enum machine_mode mem_mode)
 
                if (GET_CODE (src) == PLUS
                    && XEXP (src, 0) == SET_DEST (x)
-                   && GET_CODE (XEXP (src, 1)) == CONST_INT)
+                   && CONST_INT_P (XEXP (src, 1)))
                  ep->offset -= INTVAL (XEXP (src, 1));
                else
                  ep->can_eliminate = 0;
              }
        }
 
-      elimination_effects (SET_DEST (x), 0);
-      elimination_effects (SET_SRC (x), 0);
+      elimination_effects (SET_DEST (x), VOIDmode);
+      elimination_effects (SET_SRC (x), VOIDmode);
       return;
 
     case MEM:
@@ -3062,7 +3240,11 @@ eliminate_regs_in_insn (rtx insn, int replace)
                  || GET_CODE (PATTERN (insn)) == CLOBBER
                  || GET_CODE (PATTERN (insn)) == ADDR_VEC
                  || GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC
-                 || GET_CODE (PATTERN (insn)) == ASM_INPUT);
+                 || GET_CODE (PATTERN (insn)) == ASM_INPUT
+                 || DEBUG_INSN_P (insn));
+      if (DEBUG_INSN_P (insn))
+       INSN_VAR_LOCATION_LOC (insn)
+         = eliminate_regs (INSN_VAR_LOCATION_LOC (insn), VOIDmode, insn);
       return 0;
     }
 
@@ -3073,7 +3255,7 @@ eliminate_regs_in_insn (rtx insn, int replace)
       for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
        if (ep->from_rtx == SET_DEST (old_set) && ep->can_eliminate)
          {
-#if HARD_FRAME_POINTER_REGNUM != FRAME_POINTER_REGNUM
+#if !HARD_FRAME_POINTER_IS_FRAME_POINTER
            /* If this is setting the frame pointer register to the
               hardware frame pointer register and this is an elimination
               that will be done (tested above), this insn is really
@@ -3091,7 +3273,7 @@ eliminate_regs_in_insn (rtx insn, int replace)
                    rtx prev_insn, prev_set;
 
                    if (GET_CODE (base) == PLUS
-                       && GET_CODE (XEXP (base, 1)) == CONST_INT)
+                       && CONST_INT_P (XEXP (base, 1)))
                      {
                        offset += INTVAL (XEXP (base, 1));
                        base = XEXP (base, 0);
@@ -3166,7 +3348,7 @@ eliminate_regs_in_insn (rtx insn, int replace)
        plus_src = SET_SRC (old_set);
       /* First see if the source is of the form (plus (...) CST).  */
       if (plus_src
-         && GET_CODE (XEXP (plus_src, 1)) == CONST_INT)
+         && CONST_INT_P (XEXP (plus_src, 1)))
        plus_cst_src = plus_src;
       else if (REG_P (SET_SRC (old_set))
               || plus_src)
@@ -3179,7 +3361,7 @@ eliminate_regs_in_insn (rtx insn, int replace)
              if ((REG_NOTE_KIND (links) == REG_EQUAL
                   || REG_NOTE_KIND (links) == REG_EQUIV)
                  && GET_CODE (XEXP (links, 0)) == PLUS
-                 && GET_CODE (XEXP (XEXP (links, 0), 1)) == CONST_INT)
+                 && CONST_INT_P (XEXP (XEXP (links, 0), 1)))
                {
                  plus_cst_src = XEXP (links, 0);
                  break;
@@ -3212,7 +3394,7 @@ eliminate_regs_in_insn (rtx insn, int replace)
          {
            rtx to_rtx = ep->to_rtx;
            offset += ep->offset;
-           offset = trunc_int_for_mode (offset, GET_MODE (reg));
+           offset = trunc_int_for_mode (offset, GET_MODE (plus_cst_src));
 
            if (GET_CODE (XEXP (plus_cst_src, 0)) == SUBREG)
              to_rtx = gen_lowpart (GET_MODE (XEXP (plus_cst_src, 0)),
@@ -3239,7 +3421,7 @@ eliminate_regs_in_insn (rtx insn, int replace)
                /* First see if this insn remains valid when we make the
                   change.  If not, try to replace the whole pattern with
                   a simple set (this may help if the original insn was a
-                  PARALLEL that was only recognized as single_set due to 
+                  PARALLEL that was only recognized as single_set due to
                   REG_UNUSED notes).  If this isn't valid either, keep
                   the INSN_CODE the same and let reload fix it up.  */
                if (!validate_change (insn, &SET_SRC (old_set), new_src, 0))
@@ -3262,7 +3444,7 @@ eliminate_regs_in_insn (rtx insn, int replace)
     }
 
   /* Determine the effects of this insn on elimination offsets.  */
-  elimination_effects (old_body, 0);
+  elimination_effects (old_body, VOIDmode);
 
   /* Eliminate all eliminable registers occurring in operands that
      can be handled by reload.  */
@@ -3294,7 +3476,8 @@ eliminate_regs_in_insn (rtx insn, int replace)
          /* Companion to the above plus substitution, we can allow
             invariants as the source of a plain move.  */
          is_set_src = false;
-         if (old_set && recog_data.operand_loc[i] == &SET_SRC (old_set))
+         if (old_set
+             && recog_data.operand_loc[i] == &SET_SRC (old_set))
            is_set_src = true;
          in_plus = false;
          if (plus_src
@@ -3303,9 +3486,9 @@ eliminate_regs_in_insn (rtx insn, int replace)
            in_plus = true;
 
          substed_operand[i]
-           = eliminate_regs_1 (recog_data.operand[i], 0,
+           = eliminate_regs_1 (recog_data.operand[i], VOIDmode,
                                replace ? insn : NULL_RTX,
-                               is_set_src || in_plus);
+                               is_set_src || in_plus, false);
          if (substed_operand[i] != orig_operand[i])
            val = 1;
          /* Terminate the search in check_eliminable_occurrences at
@@ -3396,7 +3579,10 @@ eliminate_regs_in_insn (rtx insn, int replace)
     {
       /* Restore the old body.  */
       for (i = 0; i < recog_data.n_operands; i++)
-       *recog_data.operand_loc[i] = orig_operand[i];
+       /* Restoring a top-level match_parallel would clobber the new_body
+          we installed in the insn.  */
+       if (recog_data.operand_loc[i] != &PATTERN (insn))
+         *recog_data.operand_loc[i] = orig_operand[i];
       for (i = 0; i < recog_data.n_dups; i++)
        *recog_data.dup_loc[i] = orig_operand[(int) recog_data.dup_num[i]];
     }
@@ -3433,11 +3619,167 @@ eliminate_regs_in_insn (rtx insn, int replace)
      the pre-passes.  */
   if (val && REG_NOTES (insn) != 0)
     REG_NOTES (insn)
-      = eliminate_regs_1 (REG_NOTES (insn), 0, REG_NOTES (insn), true);
+      = eliminate_regs_1 (REG_NOTES (insn), VOIDmode, REG_NOTES (insn), true,
+                         false);
 
   return val;
 }
 
+/* Like eliminate_regs_in_insn, but only estimate costs for the use of the
+   register allocator.  INSN is the instruction we need to examine, we perform
+   eliminations in its operands and record cases where eliminating a reg with
+   an invariant equivalence would add extra cost.  */
+
+static void
+elimination_costs_in_insn (rtx insn)
+{
+  int icode = recog_memoized (insn);
+  rtx old_body = PATTERN (insn);
+  int insn_is_asm = asm_noperands (old_body) >= 0;
+  rtx old_set = single_set (insn);
+  int i;
+  rtx orig_operand[MAX_RECOG_OPERANDS];
+  rtx orig_dup[MAX_RECOG_OPERANDS];
+  struct elim_table *ep;
+  rtx plus_src, plus_cst_src;
+  bool sets_reg_p;
+
+  if (! insn_is_asm && icode < 0)
+    {
+      gcc_assert (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));
+      return;
+    }
+
+  if (old_set != 0 && REG_P (SET_DEST (old_set))
+      && REGNO (SET_DEST (old_set)) < FIRST_PSEUDO_REGISTER)
+    {
+      /* Check for setting an eliminable register.  */
+      for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
+       if (ep->from_rtx == SET_DEST (old_set) && ep->can_eliminate)
+         return;
+    }
+
+  /* We allow one special case which happens to work on all machines we
+     currently support: a single set with the source or a REG_EQUAL
+     note being a PLUS of an eliminable register and a constant.  */
+  plus_src = plus_cst_src = 0;
+  sets_reg_p = false;
+  if (old_set && REG_P (SET_DEST (old_set)))
+    {
+      sets_reg_p = true;
+      if (GET_CODE (SET_SRC (old_set)) == PLUS)
+       plus_src = SET_SRC (old_set);
+      /* First see if the source is of the form (plus (...) CST).  */
+      if (plus_src
+         && CONST_INT_P (XEXP (plus_src, 1)))
+       plus_cst_src = plus_src;
+      else if (REG_P (SET_SRC (old_set))
+              || plus_src)
+       {
+         /* Otherwise, see if we have a REG_EQUAL note of the form
+            (plus (...) CST).  */
+         rtx links;
+         for (links = REG_NOTES (insn); links; links = XEXP (links, 1))
+           {
+             if ((REG_NOTE_KIND (links) == REG_EQUAL
+                  || REG_NOTE_KIND (links) == REG_EQUIV)
+                 && GET_CODE (XEXP (links, 0)) == PLUS
+                 && CONST_INT_P (XEXP (XEXP (links, 0), 1)))
+               {
+                 plus_cst_src = XEXP (links, 0);
+                 break;
+               }
+           }
+       }
+    }
+
+  /* Determine the effects of this insn on elimination offsets.  */
+  elimination_effects (old_body, VOIDmode);
+
+  /* Eliminate all eliminable registers occurring in operands that
+     can be handled by reload.  */
+  extract_insn (insn);
+  for (i = 0; i < recog_data.n_dups; i++)
+    orig_dup[i] = *recog_data.dup_loc[i];
+
+  for (i = 0; i < recog_data.n_operands; i++)
+    {
+      orig_operand[i] = recog_data.operand[i];
+
+      /* For an asm statement, every operand is eliminable.  */
+      if (insn_is_asm || insn_data[icode].operand[i].eliminable)
+       {
+         bool is_set_src, in_plus;
+
+         /* Check for setting a register that we know about.  */
+         if (recog_data.operand_type[i] != OP_IN
+             && REG_P (orig_operand[i]))
+           {
+             /* If we are assigning to a register that can be eliminated, it
+                must be as part of a PARALLEL, since the code above handles
+                single SETs.  We must indicate that we can no longer
+                eliminate this reg.  */
+             for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS];
+                  ep++)
+               if (ep->from_rtx == orig_operand[i])
+                 ep->can_eliminate = 0;
+           }
+
+         /* Companion to the above plus substitution, we can allow
+            invariants as the source of a plain move.  */
+         is_set_src = false;
+         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);
+         in_plus = false;
+         if (plus_src && sets_reg_p
+             && (recog_data.operand_loc[i] == &XEXP (plus_src, 0)
+                 || recog_data.operand_loc[i] == &XEXP (plus_src, 1)))
+           in_plus = true;
+
+         eliminate_regs_1 (recog_data.operand[i], VOIDmode,
+                           NULL_RTX,
+                           is_set_src || in_plus, true);
+         /* Terminate the search in check_eliminable_occurrences at
+            this point.  */
+         *recog_data.operand_loc[i] = 0;
+       }
+    }
+
+  for (i = 0; i < recog_data.n_dups; i++)
+    *recog_data.dup_loc[i]
+      = *recog_data.operand_loc[(int) recog_data.dup_num[i]];
+
+  /* If any eliminable remain, they aren't eliminable anymore.  */
+  check_eliminable_occurrences (old_body);
+
+  /* Restore the old body.  */
+  for (i = 0; i < recog_data.n_operands; i++)
+    *recog_data.operand_loc[i] = orig_operand[i];
+  for (i = 0; i < recog_data.n_dups; i++)
+    *recog_data.dup_loc[i] = orig_dup[i];
+
+  /* Update all elimination pairs to reflect the status after the current
+     insn.  The changes we make were determined by the earlier call to
+     elimination_effects.  */
+
+  for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
+    {
+      if (ep->previous_offset != ep->offset && ep->ref_outside_mem)
+       ep->can_eliminate = 0;
+
+      ep->ref_outside_mem = 0;
+    }
+
+  return;
+}
+
 /* Loop through all elimination pairs.
    Recalculate the number not at initial offset.
 
@@ -3491,7 +3833,7 @@ mark_not_eliminable (rtx dest, const_rtx x, void *data ATTRIBUTE_UNUSED)
        && (GET_CODE (x) != SET
            || GET_CODE (SET_SRC (x)) != PLUS
            || XEXP (SET_SRC (x), 0) != dest
-           || GET_CODE (XEXP (SET_SRC (x), 1)) != CONST_INT))
+           || !CONST_INT_P (XEXP (SET_SRC (x), 1))))
       {
        reg_eliminate[i].can_eliminate_previous
          = reg_eliminate[i].can_eliminate = 0;
@@ -3578,6 +3920,10 @@ set_initial_label_offsets (void)
     if (XEXP (x, 0))
       set_label_offsets (XEXP (x, 0), NULL_RTX, 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_each_eh_label (set_initial_eh_label_offset);
 }
 
@@ -3614,9 +3960,10 @@ update_eliminables (HARD_REG_SET *pset)
   struct elim_table *ep;
 
   for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
-    if ((ep->from == HARD_FRAME_POINTER_REGNUM && FRAME_POINTER_REQUIRED)
+    if ((ep->from == HARD_FRAME_POINTER_REGNUM
+         && targetm.frame_pointer_required ())
 #ifdef ELIMINABLE_REGS
-       || ! CAN_ELIMINATE (ep->from, ep->to)
+       || ! targetm.can_eliminate (ep->from, ep->to)
 #endif
        )
       ep->can_eliminate = 0;
@@ -3722,9 +4069,9 @@ init_elim_table (void)
       ep->from = ep1->from;
       ep->to = ep1->to;
       ep->can_eliminate = ep->can_eliminate_previous
-       = (CAN_ELIMINATE (ep->from, ep->to)
+       = (targetm.can_eliminate (ep->from, ep->to)
           && ! (ep->to == STACK_POINTER_REGNUM
-                && frame_pointer_needed 
+                && frame_pointer_needed
                 && (! SUPPORTS_STACK_ALIGNMENT
                     || ! stack_realign_fp)));
     }
@@ -3746,6 +4093,155 @@ init_elim_table (void)
       ep->to_rtx = gen_rtx_REG (Pmode, ep->to);
     }
 }
+
+/* Find all the pseudo registers that didn't get hard regs
+   but do have known equivalent constants or memory slots.
+   These include parameters (known equivalent to parameter slots)
+   and cse'd or loop-moved constant memory addresses.
+
+   Record constant equivalents in reg_equiv_constant
+   so they will be substituted by find_reloads.
+   Record memory equivalents in reg_mem_equiv so they can
+   be substituted eventually by altering the REG-rtx's.  */
+
+static void
+init_eliminable_invariants (rtx first, bool do_subregs)
+{
+  int i;
+  rtx insn;
+
+  grow_reg_equivs ();
+  if (do_subregs)
+    reg_max_ref_width = XCNEWVEC (unsigned int, max_regno);
+  else
+    reg_max_ref_width = NULL;
+
+  num_eliminable_invariants = 0;
+
+  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.  */
+  offsets_known_at = XNEWVEC (char, num_labels);
+  offsets_at = (HOST_WIDE_INT (*)[NUM_ELIMINABLE_REGS]) xmalloc (num_labels * NUM_ELIMINABLE_REGS * sizeof (HOST_WIDE_INT));
+
+/* Look for REG_EQUIV notes; record what each pseudo is equivalent
+   to.  If DO_SUBREGS is true, also find all paradoxical subregs and
+   find largest such for each pseudo.  FIRST is the head of the insn
+   list.  */
+
+  for (insn = first; insn; insn = NEXT_INSN (insn))
+    {
+      rtx set = single_set (insn);
+
+      /* We may introduce USEs that we want to remove at the end, so
+        we'll mark them with QImode.  Make sure there are no
+        previously-marked insns left by say regmove.  */
+      if (INSN_P (insn) && GET_CODE (PATTERN (insn)) == USE
+         && GET_MODE (insn) != VOIDmode)
+       PUT_MODE (insn, VOIDmode);
+
+      if (do_subregs && NONDEBUG_INSN_P (insn))
+       scan_paradoxical_subregs (PATTERN (insn));
+
+      if (set != 0 && REG_P (SET_DEST (set)))
+       {
+         rtx note = find_reg_note (insn, REG_EQUIV, NULL_RTX);
+         rtx x;
+
+         if (! note)
+           continue;
+
+         i = REGNO (SET_DEST (set));
+         x = XEXP (note, 0);
+
+         if (i <= LAST_VIRTUAL_REGISTER)
+           continue;
+
+         /* If flag_pic and we have constant, verify it's legitimate.  */
+         if (!CONSTANT_P (x)
+             || !flag_pic || LEGITIMATE_PIC_OPERAND_P (x))
+           {
+             /* It can happen that a REG_EQUIV note contains a MEM
+                that is not a legitimate memory operand.  As later
+                stages of reload assume that all addresses found
+                in the reg_equiv_* arrays were originally legitimate,
+                we ignore such REG_EQUIV notes.  */
+             if (memory_operand (x, VOIDmode))
+               {
+                 /* Always unshare the equivalence, so we can
+                    substitute into this insn without touching the
+                      equivalence.  */
+                 reg_equiv_memory_loc (i) = copy_rtx (x);
+               }
+             else if (function_invariant_p (x))
+               {
+                 enum machine_mode mode;
+
+                 mode = GET_MODE (SET_DEST (set));
+                 if (GET_CODE (x) == PLUS)
+                   {
+                     /* This is PLUS of frame pointer and a constant,
+                        and might be shared.  Unshare it.  */
+                     reg_equiv_invariant (i) = copy_rtx (x);
+                     num_eliminable_invariants++;
+                   }
+                 else if (x == frame_pointer_rtx || x == arg_pointer_rtx)
+                   {
+                     reg_equiv_invariant (i) = x;
+                     num_eliminable_invariants++;
+                   }
+                 else if (targetm.legitimate_constant_p (mode, x))
+                   reg_equiv_constant (i) = x;
+                 else
+                   {
+                     reg_equiv_memory_loc (i) = force_const_mem (mode, x);
+                     if (! reg_equiv_memory_loc (i))
+                       reg_equiv_init (i) = NULL_RTX;
+                   }
+               }
+             else
+               {
+                 reg_equiv_init (i) = NULL_RTX;
+                 continue;
+               }
+           }
+         else
+           reg_equiv_init (i) = NULL_RTX;
+       }
+    }
+
+  if (dump_file)
+    for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
+      if (reg_equiv_init (i))
+       {
+         fprintf (dump_file, "init_insns for %u: ", i);
+         print_inline_rtx (dump_file, reg_equiv_init (i), 20);
+         fprintf (dump_file, "\n");
+       }
+}
+
+/* Indicate that we no longer have known memory locations or constants.
+   Free all data involved in tracking these.  */
+
+static void
+free_reg_equiv (void)
+{
+  int i;
+
+
+  free (offsets_known_at);
+  free (offsets_at);
+  offsets_at = 0;
+  offsets_known_at = 0;
+
+  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;
+
+}
 \f
 /* Kick all pseudos out of hard register REGNO.
 
@@ -3817,22 +4313,28 @@ finish_spills (int global)
       spill_reg_order[i] = -1;
 
   EXECUTE_IF_SET_IN_REG_SET (&spilled_pseudos, FIRST_PSEUDO_REGISTER, i, rsi)
-    {
-      /* Record the current hard register the pseudo is allocated to in
-        pseudo_previous_regs so we avoid reallocating it to the same
-        hard reg in a later pass.  */
-      gcc_assert (reg_renumber[i] >= 0);
-
-      SET_HARD_REG_BIT (pseudo_previous_regs[i], reg_renumber[i]);
-      /* Mark it as no longer having a hard register home.  */
-      reg_renumber[i] = -1;
-      /* We will need to scan everything again.  */
-      something_changed = 1;
-    }
+    if (! ira_conflicts_p || reg_renumber[i] >= 0)
+      {
+       /* Record the current hard register the pseudo is allocated to
+          in pseudo_previous_regs so we avoid reallocating it to the
+          same hard reg in a later pass.  */
+       gcc_assert (reg_renumber[i] >= 0);
+
+       SET_HARD_REG_BIT (pseudo_previous_regs[i], reg_renumber[i]);
+       /* Mark it as no longer having a hard register home.  */
+       reg_renumber[i] = -1;
+       if (ira_conflicts_p)
+         /* Inform IRA about the change.  */
+         ira_mark_allocation_change (i);
+       /* We will need to scan everything again.  */
+       something_changed = 1;
+      }
 
   /* Retry global register allocation if possible.  */
-  if (global)
+  if (global && ira_conflicts_p)
     {
+      unsigned int n;
+
       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
@@ -3853,24 +4355,24 @@ finish_spills (int global)
            }
        }
 
-      /* Retry allocating the spilled pseudos.  For each reg, merge the
-        various reg sets that indicate which hard regs can't be used,
-        and call retry_global_alloc.
-        We change spill_pseudos here to only contain pseudos that did not
-        get a new hard register.  */
-      for (i = FIRST_PSEUDO_REGISTER; i < (unsigned)max_regno; i++)
+      /* Retry allocating the pseudos spilled in IRA and the
+        reload.  For each reg, merge the various reg sets that
+        indicate which hard regs can't be used, and call
+        ira_reassign_pseudos.  */
+      for (n = 0, i = FIRST_PSEUDO_REGISTER; i < (unsigned) max_regno; i++)
        if (reg_old_renumber[i] != reg_renumber[i])
          {
-           HARD_REG_SET forbidden;
-           COPY_HARD_REG_SET (forbidden, bad_spill_regs_global);
-           IOR_HARD_REG_SET (forbidden, pseudo_forbidden_regs[i]);
-           IOR_HARD_REG_SET (forbidden, pseudo_previous_regs[i]);
-           retry_global_alloc (i, forbidden);
-           if (reg_renumber[i] >= 0)
+           if (reg_renumber[i] < 0)
+             temp_pseudo_reg_arr[n++] = i;
+           else
              CLEAR_REGNO_REG_SET (&spilled_pseudos, i);
          }
+      if (ira_reassign_pseudos (temp_pseudo_reg_arr, n,
+                               bad_spill_regs_global,
+                               pseudo_forbidden_regs, pseudo_previous_regs,
+                               &spilled_pseudos))
+       something_changed = 1;
     }
-
   /* Fix up the register information in the insn chain.
      This involves deleting those of the spilled pseudos which did not get
      a new hard register home from the live_{before,after} sets.  */
@@ -3879,9 +4381,14 @@ finish_spills (int global)
       HARD_REG_SET used_by_pseudos;
       HARD_REG_SET used_by_pseudos2;
 
-      AND_COMPL_REG_SET (&chain->live_throughout, &spilled_pseudos);
-      AND_COMPL_REG_SET (&chain->dead_or_set, &spilled_pseudos);
-
+      if (! ira_conflicts_p)
+       {
+         /* Don't do it for IRA because IRA and the reload still can
+            assign hard registers to the spilled pseudos on next
+            reload iterations.  */
+         AND_COMPL_REG_SET (&chain->live_throughout, &spilled_pseudos);
+         AND_COMPL_REG_SET (&chain->dead_or_set, &spilled_pseudos);
+       }
       /* Mark any unallocated hard regs as available for spills.  That
         makes inheritance work somewhat better.  */
       if (chain->need_reload)
@@ -3890,20 +4397,18 @@ finish_spills (int global)
          REG_SET_TO_HARD_REG_SET (used_by_pseudos2, &chain->dead_or_set);
          IOR_HARD_REG_SET (used_by_pseudos, used_by_pseudos2);
 
-         /* Save the old value for the sanity test below.  */
-         COPY_HARD_REG_SET (used_by_pseudos2, chain->used_spill_regs);
-
          compute_use_by_pseudos (&used_by_pseudos, &chain->live_throughout);
          compute_use_by_pseudos (&used_by_pseudos, &chain->dead_or_set);
+         /* Value of chain->used_spill_regs from previous iteration
+            may be not included in the value calculated here because
+            of possible removing caller-saves insns (see function
+            delete_caller_save_insns.  */
          COMPL_HARD_REG_SET (chain->used_spill_regs, used_by_pseudos);
          AND_HARD_REG_SET (chain->used_spill_regs, used_spill_regs);
-
-         /* Make sure we only enlarge the set.  */
-         gcc_assert (hard_reg_set_subset_p (used_by_pseudos2,
-                                           chain->used_spill_regs));
        }
     }
 
+  CLEAR_REG_SET (&changed_allocation_pseudos);
   /* Let alter_reg modify the reg rtx's for the modified pseudos.  */
   for (i = FIRST_PSEUDO_REGISTER; i < (unsigned)max_regno; i++)
     {
@@ -3911,7 +4416,9 @@ finish_spills (int global)
       if (reg_old_renumber[i] == regno)
        continue;
 
-      alter_reg (i, reg_old_renumber[i]);
+      SET_REGNO_REG_SET (&changed_allocation_pseudos, i);
+
+      alter_reg (i, reg_old_renumber[i], false);
       reg_old_renumber[i] = regno;
       if (dump_file)
        {
@@ -3979,6 +4486,40 @@ scan_paradoxical_subregs (rtx x)
        }
     }
 }
+
+/* *OP_PTR and *OTHER_PTR are two operands to a conceptual reload.
+   If *OP_PTR is a paradoxical subreg, try to remove that subreg
+   and apply the corresponding narrowing subreg to *OTHER_PTR.
+   Return true if the operands were changed, false otherwise.  */
+
+static bool
+strip_paradoxical_subreg (rtx *op_ptr, rtx *other_ptr)
+{
+  rtx op, inner, other, tem;
+
+  op = *op_ptr;
+  if (!paradoxical_subreg_p (op))
+    return false;
+  inner = SUBREG_REG (op);
+
+  other = *other_ptr;
+  tem = gen_lowpart_common (GET_MODE (inner), other);
+  if (!tem)
+    return false;
+
+  /* If the lowpart operation turned a hard register into a subreg,
+     rather than simplifying it to another hard register, then the
+     mode change cannot be properly represented.  For example, OTHER
+     might be valid in its current mode, but not in the new one.  */
+  if (GET_CODE (tem) == SUBREG
+      && REG_P (other)
+      && HARD_REGISTER_P (other))
+    return false;
+
+  *op_ptr = inner;
+  *other_ptr = tem;
+  return true;
+}
 \f
 /* A subroutine of reload_as_needed.  If INSN has a REG_EH_REGION note,
    examine all of the reload insns between PREV and NEXT exclusive, and
@@ -3988,26 +4529,11 @@ static void
 fixup_eh_region_note (rtx insn, rtx prev, rtx next)
 {
   rtx note = find_reg_note (insn, REG_EH_REGION, NULL_RTX);
-  unsigned int trap_count;
-  rtx i;
-
   if (note == NULL)
     return;
-
-  if (may_trap_p (PATTERN (insn)))
-    trap_count = 1;
-  else
-    {
-      remove_note (insn, note);
-      trap_count = 0;
-    }
-
-  for (i = NEXT_INSN (prev); i != next; i = NEXT_INSN (i))
-    if (INSN_P (i) && i != insn && may_trap_p (PATTERN (i)))
-      {
-       trap_count++;
-       add_reg_note (i, REG_EH_REGION, XEXP (note, 0));
-      }
+  if (!insn_could_throw_p (insn))
+    remove_note (insn, note);
+  copy_reg_eh_region_note_forward (note, NEXT_INSN (prev), next);
 }
 
 /* Reload pseudo-registers into hard regs around each insn as needed.
@@ -4026,7 +4552,7 @@ reload_as_needed (int live_known)
 #if defined (AUTO_INC_DEC)
   int i;
 #endif
-  rtx x;
+  rtx x, marker;
 
   memset (spill_reg_rtx, 0, sizeof spill_reg_rtx);
   memset (spill_reg_store, 0, sizeof spill_reg_store);
@@ -4037,11 +4563,18 @@ reload_as_needed (int live_known)
 
   set_initial_elim_offsets ();
 
+  /* Generate a marker insn that we will move around.  */
+  marker = emit_note (NOTE_INSN_DELETED);
+  unlink_insn_chain (marker, marker);
+
   for (chain = reload_insn_chain; chain; chain = chain->next)
     {
       rtx prev = 0;
       rtx insn = chain->insn;
       rtx old_next = NEXT_INSN (insn);
+#ifdef AUTO_INC_DEC
+      rtx old_prev = PREV_INSN (insn);
+#endif
 
       /* If we pass a label, copy the offsets from the label information
         into the current offsets of each elimination.  */
@@ -4106,7 +4639,10 @@ reload_as_needed (int live_known)
              rtx next = NEXT_INSN (insn);
              rtx p;
 
+             /* ??? PREV can get deleted by reload inheritance.
+                Work around this by emitting a marker note.  */
              prev = PREV_INSN (insn);
+             reorder_insns_nobb (marker, marker, prev);
 
              /* Now compute which reload regs to reload them into.  Perhaps
                 reusing reload regs from previous insns, or else output
@@ -4114,12 +4650,6 @@ reload_as_needed (int live_known)
                 Record the choices of reload reg in reload_reg_rtx.  */
              choose_reload_regs (chain);
 
-             /* Merge any reloads that we didn't combine for fear of
-                increasing the number of spill registers needed but now
-                discover can be safely merged.  */
-             if (SMALL_REGISTER_CLASSES)
-               merge_assigned_reloads (insn);
-
              /* Generate the insns to reload operands into or out of
                 their reload regs.  */
              emit_reload_insns (chain);
@@ -4130,10 +4660,22 @@ reload_as_needed (int live_known)
                 and that we moved the structure into).  */
              subst_reloads (insn);
 
+             prev = PREV_INSN (marker);
+             unlink_insn_chain (marker, marker);
+
              /* Adjust the exception region notes for loads and stores.  */
-             if (flag_non_call_exceptions && !CALL_P (insn))
+             if (cfun->can_throw_non_call_exceptions && !CALL_P (insn))
                fixup_eh_region_note (insn, prev, next);
 
+             /* Adjust the location of REG_ARGS_SIZE.  */
+             p = find_reg_note (insn, REG_ARGS_SIZE, NULL_RTX);
+             if (p)
+               {
+                 remove_note (insn, p);
+                 fixup_args_size_notes (prev, PREV_INSN (next),
+                                        INTVAL (XEXP (p, 0)));
+               }
+
              /* If this was an ASM, make sure that all the reload insns
                 we have generated are valid.  If not, give an error
                 and delete them.  */
@@ -4210,31 +4752,30 @@ reload_as_needed (int live_known)
                            continue;
                          if (n == 1)
                            {
-                             n = validate_replace_rtx (reload_reg,
-                                                       gen_rtx_fmt_e (code,
-                                                                      mode,
-                                                                      reload_reg),
-                                                       p);
+                             rtx replace_reg
+                               = gen_rtx_fmt_e (code, mode, reload_reg);
+
+                             validate_replace_rtx_group (reload_reg,
+                                                         replace_reg, p);
+                             n = verify_changes (0);
 
                              /* We must also verify that the constraints
-                                are met after the replacement.  */
-                             extract_insn (p);
+                                are met after the replacement.  Make sure
+                                extract_insn is only called for an insn
+                                where the replacements were found to be
+                                valid so far. */
                              if (n)
-                               n = constrain_operands (1);
-                             else
-                               break;
-
-                             /* If the constraints were not met, then
-                                undo the replacement.  */
-                             if (!n)
                                {
-                                 validate_replace_rtx (gen_rtx_fmt_e (code,
-                                                                      mode,
-                                                                      reload_reg),
-                                                       reload_reg, p);
-                                 break;
+                                 extract_insn (p);
+                                 n = constrain_operands (1);
                                }
 
+                             /* If the constraints were not met, then
+                                undo the replacement, else confirm it.  */
+                             if (!n)
+                               cancel_changes (0);
+                             else
+                               confirm_change_group ();
                            }
                          break;
                        }
@@ -4266,6 +4807,43 @@ reload_as_needed (int live_known)
                      SET_REGNO_REG_SET (&reg_has_output_reload,
                                         REGNO (XEXP (in_reg, 0)));
                    }
+                 else if (code == PRE_INC || code == PRE_DEC
+                          || code == POST_INC || code == POST_DEC)
+                   {
+                     int in_regno = REGNO (XEXP (in_reg, 0));
+
+                     if (reg_last_reload_reg[in_regno] != NULL_RTX)
+                       {
+                         int in_hard_regno;
+                         bool forget_p = true;
+
+                         in_hard_regno = REGNO (reg_last_reload_reg[in_regno]);
+                         if (TEST_HARD_REG_BIT (reg_reloaded_valid,
+                                                in_hard_regno))
+                           {
+                             for (x = old_prev ? NEXT_INSN (old_prev) : insn;
+                                  x != old_next;
+                                  x = NEXT_INSN (x))
+                               if (x == reg_reloaded_insn[in_hard_regno])
+                                 {
+                                   forget_p = false;
+                                   break;
+                                 }
+                           }
+                         /* If for some reasons, we didn't set up
+                            reg_last_reload_reg in this insn,
+                            invalidate inheritance from previous
+                            insns for the incremented/decremented
+                            register.  Such registers will be not in
+                            reg_has_output_reload.  Invalidate it
+                            also if the corresponding element in
+                            reg_reloaded_insn is also
+                            invalidated.  */
+                         if (forget_p)
+                           forget_old_reloads_1 (XEXP (in_reg, 0),
+                                                 NULL_RTX, NULL);
+                       }
+                   }
                }
            }
          /* If a pseudo that got a hard register is auto-incremented,
@@ -4295,8 +4873,15 @@ reload_as_needed (int live_known)
          be partially clobbered by the call.  */
       else if (CALL_P (insn))
        {
-       AND_COMPL_HARD_REG_SET (reg_reloaded_valid, call_used_reg_set);
-       AND_COMPL_HARD_REG_SET (reg_reloaded_valid, reg_reloaded_call_part_clobbered);
+         AND_COMPL_HARD_REG_SET (reg_reloaded_valid, call_used_reg_set);
+         AND_COMPL_HARD_REG_SET (reg_reloaded_valid, reg_reloaded_call_part_clobbered);
+
+         /* If this is a call to a setjmp-type function, we must not
+            reuse any reload reg contents across the call; that will
+            just be clobbered by other uses of the register in later
+            code, before the longjmp.  */
+         if (find_reg_note (insn, REG_SETJMP, NULL_RTX))
+           CLEAR_HARD_REG_SET (reg_reloaded_valid);
        }
     }
 
@@ -4310,7 +4895,7 @@ reload_as_needed (int live_known)
    unless X is an output reload reg of the current insn.
 
    X may be a hard reg (the reload reg)
-   or it may be a pseudo reg that was reloaded from.  
+   or it may be a pseudo reg that was reloaded from.
 
    When DATA is non-NULL just mark the registers in regset
    to be forgotten later.  */
@@ -4448,60 +5033,54 @@ static void
 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;
-
-  for (i = regno; i < nregs + regno; i++)
-    {
-      switch (type)
-       {
-       case RELOAD_OTHER:
-         SET_HARD_REG_BIT (reload_reg_used, i);
-         break;
-
-       case RELOAD_FOR_INPUT_ADDRESS:
-         SET_HARD_REG_BIT (reload_reg_used_in_input_addr[opnum], i);
-         break;
+  switch (type)
+    {
+    case RELOAD_OTHER:
+      add_to_hard_reg_set (&reload_reg_used, mode, regno);
+      break;
 
-       case RELOAD_FOR_INPADDR_ADDRESS:
-         SET_HARD_REG_BIT (reload_reg_used_in_inpaddr_addr[opnum], i);
-         break;
+    case RELOAD_FOR_INPUT_ADDRESS:
+      add_to_hard_reg_set (&reload_reg_used_in_input_addr[opnum], mode, regno);
+      break;
 
-       case RELOAD_FOR_OUTPUT_ADDRESS:
-         SET_HARD_REG_BIT (reload_reg_used_in_output_addr[opnum], i);
-         break;
+    case RELOAD_FOR_INPADDR_ADDRESS:
+      add_to_hard_reg_set (&reload_reg_used_in_inpaddr_addr[opnum], mode, regno);
+      break;
 
-       case RELOAD_FOR_OUTADDR_ADDRESS:
-         SET_HARD_REG_BIT (reload_reg_used_in_outaddr_addr[opnum], i);
-         break;
+    case RELOAD_FOR_OUTPUT_ADDRESS:
+      add_to_hard_reg_set (&reload_reg_used_in_output_addr[opnum], mode, regno);
+      break;
 
-       case RELOAD_FOR_OPERAND_ADDRESS:
-         SET_HARD_REG_BIT (reload_reg_used_in_op_addr, i);
-         break;
+    case RELOAD_FOR_OUTADDR_ADDRESS:
+      add_to_hard_reg_set (&reload_reg_used_in_outaddr_addr[opnum], mode, regno);
+      break;
 
-       case RELOAD_FOR_OPADDR_ADDR:
-         SET_HARD_REG_BIT (reload_reg_used_in_op_addr_reload, i);
-         break;
+    case RELOAD_FOR_OPERAND_ADDRESS:
+      add_to_hard_reg_set (&reload_reg_used_in_op_addr, mode, regno);
+      break;
 
-       case RELOAD_FOR_OTHER_ADDRESS:
-         SET_HARD_REG_BIT (reload_reg_used_in_other_addr, i);
-         break;
+    case RELOAD_FOR_OPADDR_ADDR:
+      add_to_hard_reg_set (&reload_reg_used_in_op_addr_reload, mode, regno);
+      break;
 
-       case RELOAD_FOR_INPUT:
-         SET_HARD_REG_BIT (reload_reg_used_in_input[opnum], i);
-         break;
+    case RELOAD_FOR_OTHER_ADDRESS:
+      add_to_hard_reg_set (&reload_reg_used_in_other_addr, mode, regno);
+      break;
 
-       case RELOAD_FOR_OUTPUT:
-         SET_HARD_REG_BIT (reload_reg_used_in_output[opnum], i);
-         break;
+    case RELOAD_FOR_INPUT:
+      add_to_hard_reg_set (&reload_reg_used_in_input[opnum], mode, regno);
+      break;
 
-       case RELOAD_FOR_INSN:
-         SET_HARD_REG_BIT (reload_reg_used_in_insn, i);
-         break;
-       }
+    case RELOAD_FOR_OUTPUT:
+      add_to_hard_reg_set (&reload_reg_used_in_output[opnum], mode, regno);
+      break;
 
-      SET_HARD_REG_BIT (reload_reg_used_at_all, i);
+    case RELOAD_FOR_INSN:
+      add_to_hard_reg_set (&reload_reg_used_in_insn,  mode, regno);
+      break;
     }
+
+  add_to_hard_reg_set (&reload_reg_used_at_all, mode, regno);
 }
 
 /* Similarly, but show REGNO is no longer in use for a reload.  */
@@ -4772,19 +5351,37 @@ reload_reg_free_p (unsigned int regno, int opnum, enum reload_type type)
     }
 }
 
-/* Return 1 if the value in reload reg REGNO, as used by a reload
-   needed for the part of the insn specified by OPNUM and TYPE,
-   is still available in REGNO at the end of the insn.
+/* Return 1 if the value in reload reg REGNO, as used by the reload with
+   the number RELOADNUM, is still available in REGNO at the end of the insn.
 
    We can assume that the reload reg was already tested for availability
    at the time it is needed, and we should not check this again,
    in case the reg has already been marked in use.  */
 
 static int
-reload_reg_reaches_end_p (unsigned int regno, int opnum, enum reload_type type)
+reload_reg_reaches_end_p (unsigned int regno, int reloadnum)
 {
+  int opnum = rld[reloadnum].opnum;
+  enum reload_type type = rld[reloadnum].when_needed;
   int i;
 
+  /* See if there is a reload with the same type for this operand, using
+     the same register. This case is not handled by the code below.  */
+  for (i = reloadnum + 1; i < n_reloads; i++)
+    {
+      rtx reg;
+      int nregs;
+
+      if (rld[i].opnum != opnum || rld[i].when_needed != type)
+       continue;
+      reg = rld[i].reg_rtx;
+      if (reg == NULL_RTX)
+       continue;
+      nregs = hard_regno_nregs[REGNO (reg)][GET_MODE (reg)];
+      if (regno >= REGNO (reg) && regno < REGNO (reg) + nregs)
+       return 0;
+    }
+  
   switch (type)
     {
     case RELOAD_OTHER:
@@ -4908,16 +5505,15 @@ reload_reg_reaches_end_p (unsigned int regno, int opnum, enum reload_type type)
 }
 
 /* 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 opnum, enum reload_type type)
+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, opnum, type))
+  for (i = REGNO (reg); i < END_REGNO (reg); i++)
+    if (!reload_reg_reaches_end_p (i, reloadnum))
       return false;
   return true;
 }
@@ -4967,6 +5563,129 @@ reloads_unique_chain_p (int r1, int r2)
   return true;
 }
 
+/* The recursive function change all occurrences of WHAT in *WHERE
+   to REPL.  */
+static void
+substitute (rtx *where, const_rtx what, rtx repl)
+{
+  const char *fmt;
+  int i;
+  enum rtx_code code;
+
+  if (*where == 0)
+    return;
+
+  if (*where == what || rtx_equal_p (*where, what))
+    {
+      /* Record the location of the changed rtx.  */
+      VEC_safe_push (rtx_p, heap, substitute_stack, where);
+      *where = repl;
+      return;
+    }
+
+  code = GET_CODE (*where);
+  fmt = GET_RTX_FORMAT (code);
+  for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
+    {
+      if (fmt[i] == 'E')
+       {
+         int j;
+
+         for (j = XVECLEN (*where, i) - 1; j >= 0; j--)
+           substitute (&XVECEXP (*where, i, j), what, repl);
+       }
+      else if (fmt[i] == 'e')
+       substitute (&XEXP (*where, i), what, repl);
+    }
+}
+
+/* The function returns TRUE if chain of reload R1 and R2 (in any
+   order) can be evaluated without usage of intermediate register for
+   the reload containing another reload.  It is important to see
+   gen_reload to understand what the function is trying to do.  As an
+   example, let us have reload chain
+
+      r2: const
+      r1: <something> + const
+
+   and reload R2 got reload reg HR.  The function returns true if
+   there is a correct insn HR = HR + <something>.  Otherwise,
+   gen_reload will use intermediate register (and this is the reload
+   reg for R1) to reload <something>.
+
+   We need this function to find a conflict for chain reloads.  In our
+   example, if HR = HR + <something> is incorrect insn, then we cannot
+   use HR as a reload register for R2.  If we do use it then we get a
+   wrong code:
+
+      HR = const
+      HR = <something>
+      HR = HR + HR
+
+*/
+static bool
+gen_reload_chain_without_interm_reg_p (int r1, int r2)
+{
+  /* Assume other cases in gen_reload are not possible for
+     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 ();
+
+  /* Make r2 a component of r1.  */
+  if (reg_mentioned_p (rld[r1].in, rld[r2].in))
+    {
+      n = r1;
+      r1 = r2;
+      r2 = n;
+    }
+  gcc_assert (reg_mentioned_p (rld[r2].in, rld[r1].in));
+  regno = rld[r1].regno >= 0 ? rld[r1].regno : rld[r2].regno;
+  gcc_assert (regno >= 0);
+  out = gen_rtx_REG (rld[r1].mode, regno);
+  in = rld[r1].in;
+  substitute (&in, rld[r2].in, gen_rtx_REG (rld[r2].mode, regno));
+
+  /* If IN is a paradoxical SUBREG, remove it and try to put the
+     opposite SUBREG on OUT.  Likewise for a paradoxical SUBREG on OUT.  */
+  strip_paradoxical_subreg (&in, &out);
+
+  if (GET_CODE (in) == PLUS
+      && (REG_P (XEXP (in, 0))
+         || GET_CODE (XEXP (in, 0)) == SUBREG
+         || MEM_P (XEXP (in, 0)))
+      && (REG_P (XEXP (in, 1))
+         || GET_CODE (XEXP (in, 1)) == SUBREG
+         || CONSTANT_P (XEXP (in, 1))
+         || MEM_P (XEXP (in, 1))))
+    {
+      insn = emit_insn (gen_rtx_SET (VOIDmode, out, in));
+      code = recog_memoized (insn);
+      result = false;
+
+      if (code >= 0)
+       {
+         extract_insn (insn);
+         /* 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);
+       }
+
+      delete_insns_since (last);
+    }
+
+  /* Restore the original value at each changed address within R1.  */
+  while (!VEC_empty (rtx_p, substitute_stack))
+    {
+      rtx *where = VEC_pop (rtx_p, substitute_stack);
+      *where = rld[r2].in;
+    }
+
+  return result;
+}
+
 /* Return 1 if the reloads denoted by R1 and R2 cannot share a register.
    Return 0 otherwise.
 
@@ -5016,7 +5735,8 @@ reloads_conflict (int r1, int r2)
     case RELOAD_FOR_OPERAND_ADDRESS:
       return (r2_type == RELOAD_FOR_INPUT || r2_type == RELOAD_FOR_INSN
              || (r2_type == RELOAD_FOR_OPERAND_ADDRESS
-                 && !reloads_unique_chain_p (r1, r2)));
+                 && (!reloads_unique_chain_p (r1, r2)
+                     || !gen_reload_chain_without_interm_reg_p (r1, r2))));
 
     case RELOAD_FOR_OPADDR_ADDR:
       return (r2_type == RELOAD_FOR_INPUT
@@ -5339,7 +6059,7 @@ function_invariant_p (const_rtx x)
     return 1;
   if (GET_CODE (x) == PLUS
       && (XEXP (x, 0) == frame_pointer_rtx || XEXP (x, 0) == arg_pointer_rtx)
-      && CONSTANT_P (XEXP (x, 1)))
+      && GET_CODE (XEXP (x, 1)) == CONST_INT)
     return 1;
   return 0;
 }
@@ -5384,7 +6104,9 @@ failed_reload (rtx insn, int r)
 static int
 set_reload_reg (int i, int r)
 {
-  int regno;
+  /* regno is 'set but not used' if HARD_REGNO_MODE_OK doesn't use its first
+     parameter.  */
+  int regno ATTRIBUTE_UNUSED;
   rtx reg = spill_reg_rtx[i];
 
   if (reg == 0 || GET_MODE (reg) != rld[r].mode)
@@ -5461,15 +6183,17 @@ allocate_reload_reg (struct insn_chain *chain ATTRIBUTE_UNUSED, int r,
      take any reg in the right class and not in use.
      If we want a consecutive group, here is where we look for it.
 
-     We use two passes so we can first look for reload regs to
+     We use three passes so we can first look for reload regs to
      reuse, which are already in use for other reloads in this insn,
-     and only then use additional registers.
+     and only then use additional registers which are not "bad", then
+     finally any register.
+
      I think that maximizing reuse is needed to make sure we don't
      run out of reload regs.  Suppose we have three reloads, and
      reloads A and B can share regs.  These need two regs.
      Suppose A and B are given different regs.
      That leaves none for C.  */
-  for (pass = 0; pass < 2; pass++)
+  for (pass = 0; pass < 3; pass++)
     {
       /* I is the index in spill_regs.
         We advance it round-robin between insns to use all spill regs
@@ -5509,6 +6233,13 @@ allocate_reload_reg (struct insn_chain *chain ATTRIBUTE_UNUSED, int r,
                                              regnum))))
            {
              int nr = hard_regno_nregs[regnum][rld[r].mode];
+
+             /* During the second pass we want to avoid reload registers
+                which are "bad" for this reload.  */
+             if (pass == 1
+                 && ira_bad_reload_regno (regnum, rld[r].in, rld[r].out))
+               continue;
+
              /* Avoid the problem where spilling a GENERAL_OR_FP_REG
                 (on 68000) got us two FP regs.  If NR is 1,
                 we would reject both of them.  */
@@ -5539,7 +6270,7 @@ allocate_reload_reg (struct insn_chain *chain ATTRIBUTE_UNUSED, int r,
            }
        }
 
-      /* If we found something on pass 1, omit pass 2.  */
+      /* If we found something on the current pass, omit later passes.  */
       if (count < n_spills)
        break;
     }
@@ -5790,6 +6521,8 @@ choose_reload_regs (struct insn_chain *chain)
 
              if (regno >= 0
                  && reg_last_reload_reg[regno] != 0
+                 && (GET_MODE_SIZE (GET_MODE (reg_last_reload_reg[regno]))
+                     >= GET_MODE_SIZE (mode) + byte)
 #ifdef CANNOT_CHANGE_MODE_CLASS
                  /* Verify that the register it's in can be used in
                     mode MODE.  */
@@ -5801,23 +6534,12 @@ choose_reload_regs (struct insn_chain *chain)
                {
                  enum reg_class rclass = rld[r].rclass, last_class;
                  rtx last_reg = reg_last_reload_reg[regno];
-                 enum machine_mode need_mode;
 
                  i = REGNO (last_reg);
                  i += subreg_regno_offset (i, GET_MODE (last_reg), byte, mode);
                  last_class = REGNO_REG_CLASS (i);
 
-                 if (byte == 0)
-                   need_mode = mode;
-                 else
-                   need_mode
-                     = smallest_mode_for_size (GET_MODE_BITSIZE (mode)
-                                               + byte * BITS_PER_UNIT,
-                                               GET_MODE_CLASS (mode));
-
-                 if ((GET_MODE_SIZE (GET_MODE (last_reg))
-                      >= GET_MODE_SIZE (need_mode))
-                     && reg_reloaded_contents[i] == regno
+                 if (reg_reloaded_contents[i] == regno
                      && TEST_HARD_REG_BIT (reg_reloaded_valid, i)
                      && HARD_REGNO_MODE_OK (i, rld[r].mode)
                      && (TEST_HARD_REG_BIT (reg_class_contents[(int) rclass], i)
@@ -5825,8 +6547,8 @@ choose_reload_regs (struct insn_chain *chain)
                             register, we might use it for reload_override_in,
                             if copying it to the desired class is cheap
                             enough.  */
-                         || ((REGISTER_MOVE_COST (mode, last_class, rclass)
-                              < MEMORY_MOVE_COST (mode, rclass, 1))
+                         || ((register_move_cost (mode, last_class, rclass)
+                              < memory_move_cost (mode, rclass, true))
                              && (secondary_reload_class (1, rclass, mode,
                                                          last_reg)
                                  == NO_REGS)
@@ -5947,17 +6669,6 @@ choose_reload_regs (struct insn_chain *chain)
              && (rld[r].nregs == max_group_size
                  || ! reg_classes_intersect_p (rld[r].rclass, group_class)))
            search_equiv = rld[r].in;
-         /* If this is an output reload from a simple move insn, look
-            if an equivalence for the input is available.  */
-         else if (inheritance && rld[r].in == 0 && rld[r].out != 0)
-           {
-             rtx set = single_set (insn);
-
-             if (set
-                 && rtx_equal_p (rld[r].out, SET_DEST (set))
-                 && CONSTANT_P (SET_SRC (set)))
-               search_equiv = SET_SRC (set);
-           }
 
          if (search_equiv)
            {
@@ -6089,6 +6800,7 @@ choose_reload_regs (struct insn_chain *chain)
                  int nr = hard_regno_nregs[regno][rld[r].mode];
                  int k;
                  rld[r].reg_rtx = equiv;
+                 reload_spill_index[r] = regno;
                  reload_inherited[r] = 1;
 
                  /* If reg_reloaded_valid is not set for this register,
@@ -6306,11 +7018,7 @@ choose_reload_regs (struct insn_chain *chain)
                               nregno + nr);
 
          if (i >= 0)
-           {
-             nr = hard_regno_nregs[i][rld[r].mode];
-             while (--nr >= 0)
-               SET_HARD_REG_BIT (reg_is_output_reload, i + nr);
-           }
+           add_to_hard_reg_set (&reg_is_output_reload, rld[r].mode, i);
 
          gcc_assert (rld[r].when_needed == RELOAD_OTHER
                      || rld[r].when_needed == RELOAD_FOR_OUTPUT
@@ -6337,152 +7045,6 @@ deallocate_reload_reg (int r)
   reload_spill_index[r] = -1;
 }
 \f
-/* 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.
-
-   Here we check for the most common case of this phenomenon: when we have
-   a number of reloads for the same object, each of which were allocated
-   the same reload_reg_rtx, that reload_reg_rtx is not used for any other
-   reload, and is not modified in the insn itself.  If we find such,
-   merge all the reloads and set the resulting reload to RELOAD_OTHER.
-   This will not increase the number of spill registers needed and will
-   prevent redundant code.  */
-
-static void
-merge_assigned_reloads (rtx insn)
-{
-  int i, j;
-
-  /* Scan all the reloads looking for ones that only load values and
-     are not already RELOAD_OTHER and ones whose reload_reg_rtx are
-     assigned and not modified by INSN.  */
-
-  for (i = 0; i < n_reloads; i++)
-    {
-      int conflicting_input = 0;
-      int max_input_address_opnum = -1;
-      int min_conflicting_input_opnum = MAX_RECOG_OPERANDS;
-
-      if (rld[i].in == 0 || rld[i].when_needed == RELOAD_OTHER
-         || rld[i].out != 0 || rld[i].reg_rtx == 0
-         || reg_set_p (rld[i].reg_rtx, insn))
-       continue;
-
-      /* Look at all other reloads.  Ensure that the only use of this
-        reload_reg_rtx is in a reload that just loads the same value
-        as we do.  Note that any secondary reloads must be of the identical
-        class since the values, modes, and result registers are the
-        same, so we need not do anything with any secondary reloads.  */
-
-      for (j = 0; j < n_reloads; j++)
-       {
-         if (i == j || rld[j].reg_rtx == 0
-             || ! reg_overlap_mentioned_p (rld[j].reg_rtx,
-                                           rld[i].reg_rtx))
-           continue;
-
-         if (rld[j].when_needed == RELOAD_FOR_INPUT_ADDRESS
-             && rld[j].opnum > max_input_address_opnum)
-           max_input_address_opnum = rld[j].opnum;
-
-         /* If the reload regs aren't exactly the same (e.g, different modes)
-            or if the values are different, we can't merge this reload.
-            But if it is an input reload, we might still merge
-            RELOAD_FOR_INPUT_ADDRESS and RELOAD_FOR_OTHER_ADDRESS reloads.  */
-
-         if (! rtx_equal_p (rld[i].reg_rtx, rld[j].reg_rtx)
-             || rld[j].out != 0 || rld[j].in == 0
-             || ! rtx_equal_p (rld[i].in, rld[j].in))
-           {
-             if (rld[j].when_needed != RELOAD_FOR_INPUT
-                 || ((rld[i].when_needed != RELOAD_FOR_INPUT_ADDRESS
-                      || rld[i].opnum > rld[j].opnum)
-                     && rld[i].when_needed != RELOAD_FOR_OTHER_ADDRESS))
-               break;
-             conflicting_input = 1;
-             if (min_conflicting_input_opnum > rld[j].opnum)
-               min_conflicting_input_opnum = rld[j].opnum;
-           }
-       }
-
-      /* If all is OK, merge the reloads.  Only set this to RELOAD_OTHER if
-        we, in fact, found any matching reloads.  */
-
-      if (j == n_reloads
-         && max_input_address_opnum <= min_conflicting_input_opnum)
-       {
-         gcc_assert (rld[i].when_needed != RELOAD_FOR_OUTPUT);
-
-         for (j = 0; j < n_reloads; j++)
-           if (i != j && rld[j].reg_rtx != 0
-               && rtx_equal_p (rld[i].reg_rtx, rld[j].reg_rtx)
-               && (! conflicting_input
-                   || rld[j].when_needed == RELOAD_FOR_INPUT_ADDRESS
-                   || rld[j].when_needed == RELOAD_FOR_OTHER_ADDRESS))
-             {
-               rld[i].when_needed = RELOAD_OTHER;
-               rld[j].in = 0;
-               reload_spill_index[j] = -1;
-               transfer_replacements (i, j);
-             }
-
-         /* If this is now RELOAD_OTHER, look for any reloads that
-            load parts of this operand and set them to
-            RELOAD_FOR_OTHER_ADDRESS if they were for inputs,
-            RELOAD_OTHER for outputs.  Note that this test is
-            equivalent to looking for reloads for this operand
-            number.
-
-            We must take special care with RELOAD_FOR_OUTPUT_ADDRESS;
-            it may share registers with a RELOAD_FOR_INPUT, so we can
-            not change it to RELOAD_FOR_OTHER_ADDRESS.  We should
-            never need to, since we do not modify RELOAD_FOR_OUTPUT.
-
-            It is possible that the RELOAD_FOR_OPERAND_ADDRESS
-            instruction is assigned the same register as the earlier
-            RELOAD_FOR_OTHER_ADDRESS instruction.  Merging these two
-            instructions will cause the RELOAD_FOR_OTHER_ADDRESS
-            instruction to be deleted later on.  */
-
-         if (rld[i].when_needed == RELOAD_OTHER)
-           for (j = 0; j < n_reloads; j++)
-             if (rld[j].in != 0
-                 && rld[j].when_needed != RELOAD_OTHER
-                 && rld[j].when_needed != RELOAD_FOR_OTHER_ADDRESS
-                 && rld[j].when_needed != RELOAD_FOR_OUTPUT_ADDRESS
-                 && rld[j].when_needed != RELOAD_FOR_OPERAND_ADDRESS
-                 && (! conflicting_input
-                     || rld[j].when_needed == RELOAD_FOR_INPUT_ADDRESS
-                     || rld[j].when_needed == RELOAD_FOR_INPADDR_ADDRESS)
-                 && reg_overlap_mentioned_for_reload_p (rld[j].in,
-                                                        rld[i].in))
-               {
-                 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.  */
-                 if (rld[j].reg_rtx)
-                   for (k = 0; k < j; k++)
-                     gcc_assert (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));
-               }
-       }
-    }
-}
-\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;
@@ -6496,7 +7058,9 @@ 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.  */
+/* 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 new_spill_reg_store[FIRST_PSEUDO_REGISTER];
 static HARD_REG_SET reg_reloaded_died;
 
@@ -6655,22 +7219,10 @@ emit_input_reload_insns (struct insn_chain *chain, struct reload *rl,
 
       old = XEXP (rl->in_reg, 0);
 
-      if (optimize && REG_P (oldequiv)
-         && REGNO (oldequiv) < FIRST_PSEUDO_REGISTER
-         && spill_reg_store[REGNO (oldequiv)]
-         && REG_P (old)
-         && (dead_or_set_p (insn,
-                            spill_reg_stored_to[REGNO (oldequiv)])
-             || rtx_equal_p (spill_reg_stored_to[REGNO (oldequiv)],
-                             old)))
-       delete_output_reload (insn, j, REGNO (oldequiv), reloadreg);
-
       /* Prevent normal processing of this reload.  */
       special = 1;
       /* Output a special code sequence for this case.  */
-      new_spill_reg_store[REGNO (reloadreg)]
-       = inc_for_reload (reloadreg, oldequiv, rl->out,
-                         rl->inc);
+      inc_for_reload (reloadreg, oldequiv, rl->out, rl->inc);
     }
 
   /* If we are reloading a pseudo-register that was set by the previous
@@ -6687,7 +7239,7 @@ emit_input_reload_insns (struct insn_chain *chain, struct reload *rl,
                                rl->when_needed, old, rl->out, j, 0))
     {
       rtx temp = PREV_INSN (insn);
-      while (temp && NOTE_P (temp))
+      while (temp && (NOTE_P (temp) || DEBUG_INSN_P (temp)))
        temp = PREV_INSN (temp);
       if (temp
          && NONJUMP_INSN_P (temp)
@@ -6724,9 +7276,19 @@ emit_input_reload_insns (struct insn_chain *chain, struct reload *rl,
                  && REG_N_SETS (REGNO (old)) == 1)
                {
                  reg_renumber[REGNO (old)] = REGNO (reloadreg);
-                 alter_reg (REGNO (old), -1);
+                 if (ira_conflicts_p)
+                   /* Inform IRA about the change.  */
+                   ira_mark_allocation_change (REGNO (old));
+                 alter_reg (REGNO (old), -1, false);
                }
              special = 1;
+
+             /* Adjust any debug insns between temp and insn.  */
+             while ((temp = NEXT_INSN (temp)) != insn)
+               if (DEBUG_INSN_P (temp))
+                 replace_rtx (PATTERN (temp), old, reloadreg);
+               else
+                 gcc_assert (NOTE_P (temp));
            }
          else
            {
@@ -6777,15 +7339,15 @@ emit_input_reload_insns (struct insn_chain *chain, struct reload *rl,
        tmp = SUBREG_REG (tmp);
       if (REG_P (tmp)
          && REGNO (tmp) >= FIRST_PSEUDO_REGISTER
-         && (reg_equiv_memory_loc[REGNO (tmp)] != 0
-             || reg_equiv_constant[REGNO (tmp)] != 0))
+         && (reg_equiv_memory_loc (REGNO (tmp)) != 0
+             || reg_equiv_constant (REGNO (tmp)) != 0))
        {
-         if (! reg_equiv_mem[REGNO (tmp)]
+         if (! reg_equiv_mem (REGNO (tmp))
              || num_not_at_initial_offset
              || GET_CODE (oldequiv) == SUBREG)
            real_oldequiv = rl->in;
          else
-           real_oldequiv = reg_equiv_mem[REGNO (tmp)];
+           real_oldequiv = reg_equiv_mem (REGNO (tmp));
        }
 
       tmp = old;
@@ -6793,15 +7355,15 @@ emit_input_reload_insns (struct insn_chain *chain, struct reload *rl,
        tmp = SUBREG_REG (tmp);
       if (REG_P (tmp)
          && REGNO (tmp) >= FIRST_PSEUDO_REGISTER
-         && (reg_equiv_memory_loc[REGNO (tmp)] != 0
-             || reg_equiv_constant[REGNO (tmp)] != 0))
+         && (reg_equiv_memory_loc (REGNO (tmp)) != 0
+             || reg_equiv_constant (REGNO (tmp)) != 0))
        {
-         if (! reg_equiv_mem[REGNO (tmp)]
+         if (! reg_equiv_mem (REGNO (tmp))
              || num_not_at_initial_offset
              || GET_CODE (old) == SUBREG)
            real_old = rl->in;
          else
-           real_old = reg_equiv_mem[REGNO (tmp)];
+           real_old = reg_equiv_mem (REGNO (tmp));
        }
 
       second_reload_reg = rld[secondary_reload].reg_rtx;
@@ -6824,18 +7386,27 @@ emit_input_reload_insns (struct insn_chain *chain, struct reload *rl,
 
          sri.icode = CODE_FOR_nothing;
          sri.prev_sri = NULL;
-         new_class = targetm.secondary_reload (1, real_oldequiv, rl->rclass,
-                                               mode, &sri);
+         new_class
+           = (enum reg_class) targetm.secondary_reload (1, real_oldequiv,
+                                                        rl->rclass, mode,
+                                                        &sri);
 
          if (new_class == NO_REGS && sri.icode == CODE_FOR_nothing)
            second_reload_reg = 0;
          else if (new_class == NO_REGS)
            {
              if (reload_adjust_reg_for_icode (&second_reload_reg,
-                                              third_reload_reg, sri.icode))
-               icode = sri.icode, third_reload_reg = 0;
+                                              third_reload_reg,
+                                              (enum insn_code) sri.icode))
+               {
+                 icode = (enum insn_code) sri.icode;
+                 third_reload_reg = 0;
+               }
              else
-               oldequiv = old, real_oldequiv = real_old;
+               {
+                 oldequiv = old;
+                 real_oldequiv = real_old;
+               }
            }
          else if (sri.icode != CODE_FOR_nothing)
            /* We currently lack a way to express this in reloads.  */
@@ -6844,16 +7415,24 @@ emit_input_reload_insns (struct insn_chain *chain, struct reload *rl,
            {
              sri2.icode = CODE_FOR_nothing;
              sri2.prev_sri = &sri;
-             new_t_class = targetm.secondary_reload (1, real_oldequiv,
-                                                     new_class, mode, &sri);
+             new_t_class
+               = (enum reg_class) targetm.secondary_reload (1, real_oldequiv,
+                                                            new_class, mode,
+                                                            &sri);
              if (new_t_class == NO_REGS && sri2.icode == CODE_FOR_nothing)
                {
                  if (reload_adjust_reg_for_temp (&second_reload_reg,
                                                  third_reload_reg,
                                                  new_class, mode))
-                   third_reload_reg = 0, tertiary_icode = sri2.icode;
+                   {
+                     third_reload_reg = 0;
+                     tertiary_icode = (enum insn_code) sri2.icode;
+                   }
                  else
-                   oldequiv = old, real_oldequiv = real_old;
+                   {
+                     oldequiv = old;
+                     real_oldequiv = real_old;
+                   }
                }
              else if (new_t_class == NO_REGS && sri2.icode != CODE_FOR_nothing)
                {
@@ -6862,13 +7441,17 @@ emit_input_reload_insns (struct insn_chain *chain, struct reload *rl,
                  if (reload_adjust_reg_for_temp (&intermediate, NULL,
                                                  new_class, mode)
                      && reload_adjust_reg_for_icode (&third_reload_reg, NULL,
-                                                     sri2.icode))
+                                                     ((enum insn_code)
+                                                      sri2.icode)))
                    {
                      second_reload_reg = intermediate;
-                     tertiary_icode = sri2.icode;
+                     tertiary_icode = (enum insn_code) sri2.icode;
                    }
                  else
-                   oldequiv = old, real_oldequiv = real_old;
+                   {
+                     oldequiv = old;
+                     real_oldequiv = real_old;
+                   }
                }
              else if (new_t_class != NO_REGS && sri2.icode == CODE_FOR_nothing)
                {
@@ -6880,14 +7463,20 @@ emit_input_reload_insns (struct insn_chain *chain, struct reload *rl,
                                                      new_t_class, mode))
                    {
                      second_reload_reg = intermediate;
-                     tertiary_icode = sri2.icode;
+                     tertiary_icode = (enum insn_code) sri2.icode;
                    }
                  else
-                   oldequiv = old, real_oldequiv = real_old;
+                   {
+                     oldequiv = old;
+                     real_oldequiv = real_old;
+                   }
                }
              else
-               /* This could be handled more intelligently too.  */
-               oldequiv = old, real_oldequiv = real_old;
+               {
+                 /* This could be handled more intelligently too.  */
+                 oldequiv = old;
+                 real_oldequiv = real_old;
+               }
            }
        }
 
@@ -6944,27 +7533,25 @@ emit_input_reload_insns (struct insn_chain *chain, struct reload *rl,
 
       if ((REG_P (oldequiv)
           && REGNO (oldequiv) >= FIRST_PSEUDO_REGISTER
-          && (reg_equiv_memory_loc[REGNO (oldequiv)] != 0
-              || reg_equiv_constant[REGNO (oldequiv)] != 0))
+          && (reg_equiv_memory_loc (REGNO (oldequiv)) != 0
+              || reg_equiv_constant (REGNO (oldequiv)) != 0))
          || (GET_CODE (oldequiv) == SUBREG
              && REG_P (SUBREG_REG (oldequiv))
              && (REGNO (SUBREG_REG (oldequiv))
                  >= FIRST_PSEUDO_REGISTER)
-             && ((reg_equiv_memory_loc
-                  [REGNO (SUBREG_REG (oldequiv))] != 0)
-                 || (reg_equiv_constant
-                     [REGNO (SUBREG_REG (oldequiv))] != 0)))
+             && ((reg_equiv_memory_loc (REGNO (SUBREG_REG (oldequiv))) != 0)
+                 || (reg_equiv_constant (REGNO (SUBREG_REG (oldequiv))) != 0)))
          || (CONSTANT_P (oldequiv)
-             && (PREFERRED_RELOAD_CLASS (oldequiv,
-                                         REGNO_REG_CLASS (REGNO (reloadreg)))
+             && (targetm.preferred_reload_class (oldequiv,
+                                                 REGNO_REG_CLASS (REGNO (reloadreg)))
                  == NO_REGS)))
        real_oldequiv = rl->in;
       gen_reload (reloadreg, real_oldequiv, rl->opnum,
                  rl->when_needed);
     }
 
-  if (flag_non_call_exceptions)
-    copy_eh_notes (insn, get_insns ());
+  if (cfun->can_throw_non_call_exceptions)
+    copy_reg_eh_region_note_forward (insn, get_insns (), NULL);
 
   /* End this sequence.  */
   *where = get_insns ();
@@ -7011,8 +7598,8 @@ emit_output_reload_insns (struct insn_chain *chain, struct reload *rl,
       int tertiary_reload = rld[secondary_reload].secondary_out_reload;
 
       if (REG_P (old) && REGNO (old) >= FIRST_PSEUDO_REGISTER
-         && reg_equiv_mem[REGNO (old)] != 0)
-       real_old = reg_equiv_mem[REGNO (old)];
+         && reg_equiv_mem (REGNO (old)) != 0)
+       real_old = reg_equiv_mem (REGNO (old));
 
       if (secondary_reload_class (0, rl->rclass, mode, real_old) != NO_REGS)
        {
@@ -7048,7 +7635,6 @@ emit_output_reload_insns (struct insn_chain *chain, struct reload *rl,
              if (tertiary_icode != CODE_FOR_nothing)
                {
                  rtx third_reloadreg = rld[tertiary_reload].reg_rtx;
-                 rtx tem;
 
                  /* Copy primary reload reg to secondary reload reg.
                     (Note that these have been swapped above, then
@@ -7057,13 +7643,7 @@ emit_output_reload_insns (struct insn_chain *chain, struct reload *rl,
                  /* If REAL_OLD is a paradoxical SUBREG, remove it
                     and try to put the opposite SUBREG on
                     RELOADREG.  */
-                 if (GET_CODE (real_old) == SUBREG
-                     && (GET_MODE_SIZE (GET_MODE (real_old))
-                         > GET_MODE_SIZE (GET_MODE (SUBREG_REG (real_old))))
-                     && 0 != (tem = gen_lowpart_common
-                              (GET_MODE (SUBREG_REG (real_old)),
-                               reloadreg)))
-                   real_old = SUBREG_REG (real_old), reloadreg = tem;
+                 strip_paradoxical_subreg (&real_old, &reloadreg);
 
                  gen_reload (reloadreg, second_reloadreg,
                              rl->opnum, rl->when_needed);
@@ -7162,14 +7742,14 @@ emit_output_reload_insns (struct insn_chain *chain, struct reload *rl,
                    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;
              }
          }
@@ -7183,8 +7763,8 @@ emit_output_reload_insns (struct insn_chain *chain, struct reload *rl,
   else
     output_reload_insns[rl->opnum] = get_insns ();
 
-  if (flag_non_call_exceptions)
-    copy_eh_notes (insn, get_insns ());
+  if (cfun->can_throw_non_call_exceptions)
+    copy_reg_eh_region_note_forward (insn, get_insns (), NULL);
 
   end_sequence ();
 }
@@ -7429,6 +8009,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
@@ -7436,14 +8025,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);
     }
@@ -7545,29 +8126,37 @@ emit_reload_insns (struct insn_chain *chain)
          /* For a multi register reload, we need to check if all or part
             of the value lives to the end.  */
          for (k = 0; k < nr; k++)
-           if (reload_reg_reaches_end_p (i + k, rld[r].opnum,
-                                         rld[r].when_needed))
+           if (reload_reg_reaches_end_p (i + k, r))
              CLEAR_HARD_REG_BIT (reg_reloaded_valid, i + k);
 
          /* Maybe the spill reg contains a copy of reload_out.  */
          if (rld[r].out != 0
              && (REG_P (rld[r].out)
-#ifdef AUTO_INC_DEC
-                 || ! rld[r].out_reg
-#endif
-                 || REG_P (rld[r].out_reg)))
+                 || (rld[r].out_reg
+                     ? REG_P (rld[r].out_reg)
+                     /* The reload value is an auto-modification of
+                        some kind.  For PRE_INC, POST_INC, PRE_DEC
+                        and POST_DEC, we record an equivalence
+                        between the reload register and the operand
+                        on the optimistic assumption that we can make
+                        the equivalence hold.  reload_as_needed must
+                        then either make it hold or invalidate the
+                        equivalence.
+
+                        PRE_MODIFY and POST_MODIFY addresses are reloaded
+                        somewhat differently, and allowing them here leads
+                        to problems.  */
+                     : (GET_CODE (rld[r].out) != POST_MODIFY
+                        && 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, rld[r].opnum,
-                                          rld[r].when_needed))
+             if (reload_reg_rtx_reaches_end_p (reg, r))
                {
+                 enum 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
@@ -7631,21 +8220,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, rld[r].opnum,
-                                          rld[r].when_needed))
+             if (reload_reg_rtx_reaches_end_p (reg, r))
                {
+                 enum 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;
@@ -7747,10 +8336,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)
                    {
@@ -7768,8 +8364,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)
                {
@@ -7796,7 +8390,7 @@ emit_reload_insns (struct insn_chain *chain)
                      SET_HARD_REG_BIT (reg_reloaded_valid, src_regno + k);
                      if (HARD_REGNO_CALL_PART_CLOBBERED (src_regno + k,
                                                          mode))
-                       SET_HARD_REG_BIT (reg_reloaded_call_part_clobbered, 
+                       SET_HARD_REG_BIT (reg_reloaded_call_part_clobbered,
                                          src_regno + k);
                      else
                        CLEAR_HARD_REG_BIT (reg_reloaded_call_part_clobbered,
@@ -7808,7 +8402,7 @@ emit_reload_insns (struct insn_chain *chain)
                        CLEAR_HARD_REG_BIT (reg_reloaded_died, src_regno);
                    }
                  reg_last_reload_reg[out_regno] = src_reg;
-                 /* We have to set reg_has_output_reload here, or else 
+                 /* We have to set reg_has_output_reload here, or else
                     forget_old_reloads_1 will clear reg_last_reload_reg
                     right away.  */
                  SET_REGNO_REG_SET (&reg_has_output_reload,
@@ -7867,16 +8461,8 @@ gen_reload (rtx out, rtx in, int opnum, enum reload_type type)
 
   /* If IN is a paradoxical SUBREG, remove it and try to put the
      opposite SUBREG on OUT.  Likewise for a paradoxical SUBREG on OUT.  */
-  if (GET_CODE (in) == SUBREG
-      && (GET_MODE_SIZE (GET_MODE (in))
-         > GET_MODE_SIZE (GET_MODE (SUBREG_REG (in))))
-      && (tem = gen_lowpart_common (GET_MODE (SUBREG_REG (in)), out)) != 0)
-    in = SUBREG_REG (in), out = tem;
-  else if (GET_CODE (out) == SUBREG
-          && (GET_MODE_SIZE (GET_MODE (out))
-              > GET_MODE_SIZE (GET_MODE (SUBREG_REG (out))))
-          && (tem = gen_lowpart_common (GET_MODE (SUBREG_REG (out)), in)) != 0)
-    out = SUBREG_REG (out), in = tem;
+  if (!strip_paradoxical_subreg (&in, &out))
+    strip_paradoxical_subreg (&out, &in);
 
   /* How to do this reload can get quite tricky.  Normally, we are being
      asked to reload a simple operand, such as a MEM, a constant, or a pseudo
@@ -7933,7 +8519,7 @@ gen_reload (rtx out, rtx in, int opnum, enum reload_type type)
         not valid than to dummy things up.  */
 
       rtx op0, op1, tem, insn;
-      int code;
+      enum insn_code code;
 
       op0 = find_replacement (&XEXP (in, 0));
       op1 = find_replacement (&XEXP (in, 1));
@@ -7971,14 +8557,13 @@ gen_reload (rtx out, rtx in, int opnum, enum reload_type type)
         DEFINE_PEEPHOLE should be specified that recognizes the sequence
         we emit below.  */
 
-      code = (int) optab_handler (add_optab, GET_MODE (out))->insn_code;
+      code = optab_handler (add_optab, GET_MODE (out));
 
       if (CONSTANT_P (op1) || MEM_P (op1) || GET_CODE (op1) == SUBREG
          || (REG_P (op1)
              && REGNO (op1) >= FIRST_PSEUDO_REGISTER)
          || (code != CODE_FOR_nothing
-             && ! ((*insn_data[code].operand[2].predicate)
-                   (op1, insn_data[code].operand[2].mode))))
+             && !insn_operand_matches (code, 2, op1)))
        tem = op0, op0 = op1, op1 = tem;
 
       gen_reload (out, op0, opnum, type);
@@ -7994,7 +8579,7 @@ gen_reload (rtx out, rtx in, int opnum, enum reload_type type)
       if (insn)
        {
          /* Add a REG_EQUIV note so that find_equiv_reg can find it.  */
-         set_unique_reg_note (insn, REG_EQUIV, in);
+         set_dst_reg_note (insn, REG_EQUIV, in, out);
          return insn;
        }
 
@@ -8004,7 +8589,7 @@ gen_reload (rtx out, rtx in, int opnum, enum reload_type type)
       gcc_assert (!reg_overlap_mentioned_p (out, op0));
       gen_reload (out, op1, opnum, type);
       insn = emit_insn (gen_add2_insn (out, op0));
-      set_unique_reg_note (insn, REG_EQUIV, in);
+      set_dst_reg_note (insn, REG_EQUIV, in, out);
     }
 
 #ifdef SECONDARY_MEMORY_NEEDED
@@ -8023,10 +8608,10 @@ gen_reload (rtx out, rtx in, int opnum, enum reload_type type)
       rtx loc = get_secondary_mem (in, GET_MODE (out), opnum, type);
 
       if (GET_MODE (loc) != GET_MODE (out))
-       out = gen_rtx_REG (GET_MODE (loc), REGNO (out));
+       out = gen_rtx_REG (GET_MODE (loc), reg_or_subregno (out));
 
       if (GET_MODE (loc) != GET_MODE (in))
-       in = gen_rtx_REG (GET_MODE (loc), REGNO (in));
+       in = gen_rtx_REG (GET_MODE (loc), reg_or_subregno (in));
 
       gen_reload (loc, in, opnum, type);
       gen_reload (out, loc, opnum, type);
@@ -8070,7 +8655,7 @@ gen_reload (rtx out, rtx in, int opnum, enum reload_type type)
          return insn;
        }
 
-      fatal_insn ("Failure trying to reload:", set);
+      fatal_insn ("failure trying to reload:", set);
     }
   /* If IN is a simple operand, use gen_move_insn.  */
   else if (OBJECT_P (in) || GET_CODE (in) == SUBREG)
@@ -8118,6 +8703,8 @@ delete_output_reload (rtx insn, int j, int last_reload_reg, rtx new_reload_reg)
   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.  */
@@ -8128,7 +8715,7 @@ delete_output_reload (rtx insn, int j, int last_reload_reg, rtx new_reload_reg)
 
   while (GET_CODE (reg) == SUBREG)
     reg = SUBREG_REG (reg);
-  substed = reg_equiv_memory_loc[REGNO (reg)];
+  substed = reg_equiv_memory_loc (REGNO (reg));
 
   /* This is unsafe if the operand occurs more often in the current
      insn than it is inherited.  */
@@ -8159,9 +8746,9 @@ delete_output_reload (rtx insn, int j, int last_reload_reg, rtx new_reload_reg)
                                        reg, 0);
   if (substed)
     n_occurrences += count_occurrences (PATTERN (insn),
-                                       eliminate_regs (substed, 0,
+                                       eliminate_regs (substed, VOIDmode,
                                                        NULL_RTX), 0);
-  for (i1 = reg_equiv_alt_mem_list [REGNO (reg)]; i1; i1 = XEXP (i1, 1))
+  for (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);
@@ -8169,6 +8756,12 @@ delete_output_reload (rtx insn, int j, int last_reload_reg, rtx new_reload_reg)
   if (n_occurrences > n_inherited)
     return;
 
+  regno = REGNO (reg);
+  if (regno >= FIRST_PSEUDO_REGISTER)
+    nregs = 1;
+  else
+    nregs = hard_regno_nregs[regno][GET_MODE (reg)];
+
   /* If the pseudo-reg we are reloading is no longer referenced
      anywhere between the store into it and here,
      and we're within the same basic block, then the value can only
@@ -8180,7 +8773,7 @@ delete_output_reload (rtx insn, int j, int last_reload_reg, rtx new_reload_reg)
       if (NOTE_INSN_BASIC_BLOCK_P (i1))
        return;
       if ((NONJUMP_INSN_P (i1) || CALL_P (i1))
-         && reg_mentioned_p (reg, PATTERN (i1)))
+         && refers_to_regno_p (regno, regno + nregs, PATTERN (i1), NULL))
        {
          /* If this is USE in front of INSN, we only have to check that
             there are no more references than accounted for by inheritance.  */
@@ -8262,7 +8855,10 @@ delete_output_reload (rtx insn, int j, int last_reload_reg, rtx new_reload_reg)
 
       /* For the debugging info, say the pseudo lives in this reload reg.  */
       reg_renumber[REGNO (reg)] = REGNO (new_reload_reg);
-      alter_reg (REGNO (reg), -1);
+      if (ira_conflicts_p)
+       /* Inform IRA about the change.  */
+       ira_mark_allocation_change (REGNO (reg));
+      alter_reg (REGNO (reg), -1, false);
     }
   else
     {
@@ -8295,8 +8891,8 @@ delete_address_reloads (rtx dead_insn, rtx current_insn)
   set2 = single_set (prev);
   if (! set || ! set2
       || GET_CODE (SET_SRC (set)) != PLUS || GET_CODE (SET_SRC (set2)) != PLUS
-      || GET_CODE (XEXP (SET_SRC (set), 1)) != CONST_INT
-      || GET_CODE (XEXP (SET_SRC (set2), 1)) != CONST_INT)
+      || !CONST_INT_P (XEXP (SET_SRC (set), 1))
+      || !CONST_INT_P (XEXP (SET_SRC (set2), 1)))
     return;
   dst = SET_DEST (set);
   if (! rtx_equal_p (dst, SET_DEST (set2))
@@ -8424,11 +9020,9 @@ delete_address_reloads_1 (rtx dead_insn, rtx x, rtx current_insn)
    IN is either identical to VALUE, or some cheaper place to reload from.
 
    INC_AMOUNT is the number to increment or decrement by (always positive).
-   This cannot be deduced from VALUE.
+   This cannot be deduced from VALUE.  */
 
-   Return the instruction that stores into RELOADREG.  */
-
-static rtx
+static void
 inc_for_reload (rtx reloadreg, rtx in, rtx value, int inc_amount)
 {
   /* REG or MEM to be copied and incremented.  */
@@ -8440,7 +9034,6 @@ inc_for_reload (rtx reloadreg, rtx in, rtx value, int inc_amount)
   rtx inc;
   rtx add_insn;
   int code;
-  rtx store;
   rtx real_in = in == value ? incloc : in;
 
   /* No hard register is equivalent to this register after
@@ -8489,8 +9082,7 @@ inc_for_reload (rtx reloadreg, rtx in, rtx value, int inc_amount)
 
              if (! post)
                emit_insn (gen_move_insn (reloadreg, incloc));
-
-             return add_insn;
+             return;
            }
        }
       delete_insns_since (last);
@@ -8506,7 +9098,7 @@ inc_for_reload (rtx reloadreg, rtx in, rtx value, int inc_amount)
       if (in != reloadreg)
        emit_insn (gen_move_insn (reloadreg, real_in));
       emit_insn (gen_add2_insn (reloadreg, inc));
-      store = emit_insn (gen_move_insn (incloc, reloadreg));
+      emit_insn (gen_move_insn (incloc, reloadreg));
     }
   else
     {
@@ -8520,14 +9112,12 @@ inc_for_reload (rtx reloadreg, rtx in, rtx value, int inc_amount)
         the original value.  */
 
       emit_insn (gen_add2_insn (reloadreg, inc));
-      store = emit_insn (gen_move_insn (incloc, reloadreg));
-      if (GET_CODE (inc) == CONST_INT)
+      emit_insn (gen_move_insn (incloc, reloadreg));
+      if (CONST_INT_P (inc))
        emit_insn (gen_add2_insn (reloadreg, GEN_INT (-INTVAL (inc))));
       else
        emit_insn (gen_sub2_insn (reloadreg, inc));
     }
-
-  return store;
 }
 \f
 #ifdef AUTO_INC_DEC
@@ -8556,129 +9146,3 @@ add_auto_inc_notes (rtx insn, rtx x)
     }
 }
 #endif
-
-/* 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)
-    {
-      for (; x != 0; x = NEXT_INSN (x))
-       {
-         if (may_trap_p (PATTERN (x)))
-           add_reg_note (x, REG_EH_REGION, XEXP (eh_note, 0));
-       }
-    }
-}
-
-/* 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 (void)
-{
-  bool inserted = false;
-  basic_block bb;
-
-  FOR_EACH_BB (bb)
-    {
-      edge e;
-      edge_iterator ei;
-
-      /* Look for cases we are interested in - calls or instructions causing
-         exceptions.  */
-      FOR_EACH_EDGE (e, ei, bb->succs)
-       {
-         if (e->flags & EDGE_ABNORMAL_CALL)
-           break;
-         if ((e->flags & (EDGE_ABNORMAL | EDGE_EH))
-             == (EDGE_ABNORMAL | EDGE_EH))
-           break;
-       }
-      if (e && !CALL_P (BB_END (bb))
-         && !can_throw_internal (BB_END (bb)))
-       {
-         rtx insn;
-
-         /* Get past the new insns generated.  Allow notes, as the insns
-            may be already deleted.  */
-         insn = BB_END (bb);
-         while ((NONJUMP_INSN_P (insn) || NOTE_P (insn))
-                && !can_throw_internal (insn)
-                && insn != BB_HEAD (bb))
-           insn = PREV_INSN (insn);
-
-         if (CALL_P (insn) || can_throw_internal (insn))
-           {
-             rtx stop, next;
-
-             stop = NEXT_INSN (BB_END (bb));
-             BB_END (bb) = insn;
-             insn = NEXT_INSN (insn);
-
-             FOR_EACH_EDGE (e, ei, bb->succs)
-               if (e->flags & EDGE_FALLTHRU)
-                 break;
-
-             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-existent 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);
-                         inserted = true;
-                       }
-                   }
-                 else if (!BARRIER_P (insn))
-                   set_block_for_insn (insn, NULL);
-                 insn = next;
-               }
-           }
-
-         /* It may be that we don't find any such trapping insn.  In this
-            case we discovered quite late that the insn that had been 
-            marked as can_throw_internal in fact couldn't trap at all.
-            So we should in fact delete the EH edges out of the block.  */
-         else
-           purge_dead_edges (bb);
-       }
-    }
-
-  /* We've possibly turned single trapping insn into multiple ones.  */
-  if (flag_non_call_exceptions)
-    {
-      sbitmap blocks;
-      blocks = sbitmap_alloc (last_basic_block);
-      sbitmap_ones (blocks);
-      find_many_sub_basic_blocks (blocks);
-      sbitmap_free (blocks);
-    }
-
-  if (inserted)
-    commit_edge_insertions ();
-
-#ifdef ENABLE_CHECKING
-  /* Verify that we didn't turn one trapping insn into many, and that
-     we found and corrected all of the problems wrt fixups on the
-     fallthru edge.  */
-  verify_flow_info ();
-#endif
-}