OSDN Git Service

* config/sol2.c (solaris_assemble_visibility): Declare decl, vis
[pf3gnuchains/gcc-fork.git] / gcc / reload1.c
index 2aad6b0..504c9e0 100644 (file)
@@ -1,13 +1,13 @@
 /* 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
+   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
    Free Software Foundation, Inc.
 
 This file is part of GCC.
 
 GCC is free software; you can redistribute it and/or modify it under
 the terms of the GNU General Public License as published by the Free
-Software Foundation; either version 2, or (at your option) any later
+Software Foundation; either version 3, or (at your option) any later
 version.
 
 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
@@ -16,9 +16,8 @@ FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 for more details.
 
 You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING.  If not, write to the Free
-Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
-02110-1301, USA.  */
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
 
 #include "config.h"
 #include "system.h"
@@ -38,14 +37,16 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
 #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 "ira.h"
 #include "target.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
@@ -157,7 +158,7 @@ static HARD_REG_SET reg_reloaded_dead;
 
 /* Indicate whether the register's current value is one that is not
    safe to retain across a call, even for registers that are normally
-   call-saved.  */
+   call-saved.  This is only meaningful for members of reg_reloaded_valid.  */
 static HARD_REG_SET reg_reloaded_call_part_clobbered;
 
 /* Number of spill-regs so far; number of valid elements of spill_regs.  */
@@ -256,6 +257,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;
@@ -313,8 +317,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.  */
@@ -372,6 +377,21 @@ static int first_label_num;
 static char *offsets_known_at;
 static HOST_WIDE_INT (*offsets_at)[NUM_ELIMINABLE_REGS];
 
+/* 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;
@@ -388,13 +408,13 @@ 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 int eliminate_regs_in_insn (rtx, int);
 static void update_eliminable_offsets (void);
-static void mark_not_eliminable (rtx, rtx, void *);
+static void mark_not_eliminable (rtx, const_rtx, void *);
 static void set_initial_elim_offsets (void);
 static bool verify_initial_elim_offsets (void);
 static void set_initial_label_offsets (void);
@@ -407,7 +427,7 @@ static void scan_paradoxical_subregs (rtx);
 static void count_pseudo (int);
 static void order_regs_for_reload (struct insn_chain *);
 static void reload_as_needed (int);
-static void forget_old_reloads_1 (rtx, rtx, void *);
+static void forget_old_reloads_1 (rtx, const_rtx, void *);
 static void forget_marked_reloads (regset);
 static int reload_reg_class_lower (const void *, const void *);
 static void mark_reload_reg_in_use (unsigned int, int, enum reload_type,
@@ -433,21 +453,22 @@ static void emit_output_reload_insns (struct insn_chain *, struct reload *,
                                      int);
 static void do_input_reload (struct insn_chain *, struct reload *, int);
 static void do_output_reload (struct insn_chain *, struct reload *, int);
-static bool inherit_piecemeal_p (int, int);
 static void emit_reload_insns (struct insn_chain *);
-static void delete_output_reload (rtx, int, int);
+static void delete_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);
 #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);
 \f
-/* Initialize the reload pass once per compilation.  */
+/* Initialize the reload pass.  This is called at the beginning of compilation
+   and may be called again if the target is reinitialized.  */
 
 void
 init_reload (void)
@@ -497,9 +518,10 @@ init_reload (void)
 
   /* Initialize obstack for our rtl allocation.  */
   gcc_obstack_init (&reload_obstack);
-  reload_startobj = obstack_alloc (&reload_obstack, 0);
+  reload_startobj = XOBNEWVAR (&reload_obstack, char, 0);
 
   INIT_REG_SET (&spilled_pseudos);
+  INIT_REG_SET (&changed_allocation_pseudos);
   INIT_REG_SET (&pseudos_counted);
 }
 
@@ -514,7 +536,7 @@ new_insn_chain (void)
 
   if (unused_insn_chains == 0)
     {
-      c = obstack_alloc (&reload_obstack, sizeof (struct insn_chain));
+      c = XOBNEW (&reload_obstack, struct insn_chain);
       INIT_REG_SET (&c->live_throughout);
       INIT_REG_SET (&c->dead_or_set);
     }
@@ -542,22 +564,17 @@ compute_use_by_pseudos (HARD_REG_SET *to, regset from)
   EXECUTE_IF_SET_IN_REG_SET (from, FIRST_PSEUDO_REGISTER, regno, rsi)
     {
       int r = reg_renumber[regno];
-      int nregs;
 
       if (r < 0)
        {
-         /* reload_combine uses the information from
-            BASIC_BLOCK->global_live_at_start, 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
-       {
-         nregs = hard_regno_nregs[r][PSEUDO_REGNO_MODE (regno)];
-         while (nregs-- > 0)
-           SET_HARD_REG_BIT (*to, r + nregs);
-       }
+       add_to_hard_reg_set (to, PSEUDO_REGNO_MODE (regno), r);
     }
 }
 
@@ -622,6 +639,61 @@ replace_pseudos_in (rtx *loc, enum machine_mode mem_mode, rtx usage)
        replace_pseudos_in (& XVECEXP (x, i, j), mem_mode, usage);
 }
 
+/* Determine if the current function has an exception receiver block
+   that reaches the exit block via non-exceptional edges  */
+
+static bool
+has_nonexceptional_receiver (void)
+{
+  edge e;
+  edge_iterator ei;
+  basic_block *tos, *worklist, bb;
+
+  /* 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);
+
+  FOR_EACH_BB (bb)
+    bb->flags &= ~BB_REACHABLE;
+
+  /* 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)
+    {
+      bb = *--tos;
+
+      FOR_EACH_EDGE (e, ei, bb->preds)
+       if (!(e->flags & EDGE_ABNORMAL))
+         {
+           basic_block src = e->src;
+
+           if (!(src->flags & BB_REACHABLE))
+             {
+               src->flags |= BB_REACHABLE;
+               *tos++ = src;
+             }
+         }
+    }
+  free (worklist);
+
+  /* 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;
+
+  /* No exceptional block reached exit unexceptionally.  */
+  return false;
+}
+
 \f
 /* Global variables used by reload and its subroutines.  */
 
@@ -629,10 +701,15 @@ replace_pseudos_in (rtx *loc, enum machine_mode mem_mode, rtx usage)
 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.
@@ -649,7 +726,7 @@ static int failure;
 int
 reload (rtx first, int global)
 {
-  int i;
+  int i, n;
   rtx insn;
   struct elim_table *ep;
   basic_block bb;
@@ -659,7 +736,7 @@ reload (rtx first, int global)
 
   failure = 0;
 
-  reload_firstobj = obstack_alloc (&reload_obstack, 0);
+  reload_firstobj = XOBNEWVAR (&reload_obstack, char, 0);
 
   /* Make sure that the last insn in the chain
      is not something that needs reloading.  */
@@ -688,12 +765,17 @@ reload (rtx first, int global)
   for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
     mark_home_live (i);
 
-  /* A function that receives a nonlocal goto must save all call-saved
+  /* A function that has a nonlocal label that can reach the exit
+     block via non-exceptional paths must save all call-saved
      registers.  */
-  if (current_function_has_nonlocal_label)
+  if (cfun->has_nonlocal_label
+      && has_nonexceptional_receiver ())
+    crtl->saves_all_registers = 1;
+
+  if (crtl->saves_all_registers)
     for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
       if (! call_used_regs[i] && ! fixed_regs[i] && ! LOCAL_REGNO (i))
-       regs_ever_live[i] = 1;
+       df_set_regs_ever_live (i, true);
 
   /* Find all the pseudo registers that didn't get hard regs
      but do have known equivalent constants or memory slots.
@@ -734,7 +816,7 @@ reload (rtx first, int global)
          && GET_MODE (insn) != VOIDmode)
        PUT_MODE (insn, VOIDmode);
 
-      if (INSN_P (insn))
+      if (NONDEBUG_INSN_P (insn))
        scan_paradoxical_subregs (PATTERN (insn));
 
       if (set != 0 && REG_P (SET_DEST (set)))
@@ -827,12 +909,21 @@ reload (rtx first, int global)
   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));
 
-  /* Alter each pseudo-reg rtx to contain its hard reg number.
-     Assign stack slots to the pseudos that lack hard regs or equivalents.
+  /* 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.  */
 
-  for (i = LAST_VIRTUAL_REGISTER + 1; i < max_regno; i++)
-    alter_reg (i, -1);
+  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;
+
+  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 = 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
@@ -891,6 +982,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 ();
@@ -922,10 +1014,12 @@ reload (rtx first, int global)
       for (i = FIRST_PSEUDO_REGISTER; i < max_regno; 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)))
+           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))
@@ -946,7 +1040,7 @@ reload (rtx first, int global)
                   the loop.  */
                reg_equiv_memory_loc[i] = 0;
                reg_equiv_init[i] = 0;
-               alter_reg (i, -1);
+               alter_reg (i, -1, true);
              }
          }
 
@@ -954,9 +1048,9 @@ 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 && cfun->stack_alignment_needed)
+      if (starting_frame_size && crtl->stack_alignment_needed)
        {
          /* If we have a stack frame, we must align it now.  The
             stack size may be a part of the offset computation for
@@ -966,7 +1060,7 @@ reload (rtx first, int global)
             stack frame when none is needed should
             STARTING_FRAME_OFFSET not be already aligned to
             STACK_BOUNDARY.  */
-         assign_stack_local (BLKmode, 0, cfun->stack_alignment_needed);
+         assign_stack_local (BLKmode, 0, crtl->stack_alignment_needed);
          if (starting_frame_size != get_frame_size ())
            continue;
        }
@@ -975,23 +1069,28 @@ reload (rtx first, int global)
        {
          save_call_clobbered_regs ();
          /* That might have allocated new insn_chain structures.  */
-         reload_firstobj = obstack_alloc (&reload_obstack, 0);
+         reload_firstobj = XOBNEWVAR (&reload_obstack, char, 0);
        }
 
       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 ())
@@ -1101,13 +1200,13 @@ reload (rtx first, int global)
 
   if (! frame_pointer_needed)
     FOR_EACH_BB (bb)
-      CLEAR_REGNO_REG_SET (bb->il.rtl->global_live_at_start,
-                          HARD_FRAME_POINTER_REGNUM);
+      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;
 
@@ -1152,6 +1251,52 @@ reload (rtx first, int global)
          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))
+               {
+                 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);
+               }
+           }
+       }
     }
 
   /* We must set reload_completed now since the cleanup_subreg_operands call
@@ -1164,29 +1309,14 @@ reload (rtx first, int global)
      notes.  Delete all CLOBBER insns, except those that refer to the return
      value and the special mem:BLK CLOBBERs added to prevent the scheduler
      from misarranging variable-array code, and simplify (subreg (reg))
-     operands.  Also remove all REG_RETVAL and REG_LIBCALL notes since they
-     are no longer useful or accurate.  Strip and regenerate REG_INC notes
-     that may have been moved around.  */
+     operands.  Strip and regenerate REG_INC notes that may have been moved
+     around.  */
 
   for (insn = first; insn; insn = NEXT_INSN (insn))
     if (INSN_P (insn))
       {
        rtx *pnote;
 
-       /* Clean up invalid ASMs so that they don't confuse later passes.
-          See PR 21299.  */
-       if (asm_noperands (PATTERN (insn)) >= 0)
-         {
-           extract_insn (insn);
-           if (!constrain_operands (1))
-             {
-               error_for_asm (insn,
-                              "%<asm%> operand has impossible constraints");
-               delete_insn (insn);
-               continue;
-             }
-         }
-
        if (CALL_P (insn))
          replace_pseudos_in (& CALL_INSN_FUNCTION_USAGE (insn),
                              VOIDmode, CALL_INSN_FUNCTION_USAGE (insn));
@@ -1233,9 +1363,7 @@ reload (rtx first, int global)
          {
            if (REG_NOTE_KIND (*pnote) == REG_DEAD
                || REG_NOTE_KIND (*pnote) == REG_UNUSED
-               || REG_NOTE_KIND (*pnote) == REG_INC
-               || REG_NOTE_KIND (*pnote) == REG_RETVAL
-               || REG_NOTE_KIND (*pnote) == REG_LIBCALL)
+               || REG_NOTE_KIND (*pnote) == REG_INC)
              *pnote = XEXP (*pnote, 1);
            else
              pnote = &XEXP (*pnote, 1);
@@ -1245,19 +1373,33 @@ reload (rtx first, int global)
        add_auto_inc_notes (insn, PATTERN (insn));
 #endif
 
-       /* And simplify (subreg (reg)) if it appears as an operand.  */
+       /* Simplify (subreg (reg)) if it appears as an operand.  */
        cleanup_subreg_operands (insn);
+
+       /* Clean up invalid ASMs so that they don't confuse later passes.
+          See PR 21299.  */
+       if (asm_noperands (PATTERN (insn)) >= 0)
+         {
+           extract_insn (insn);
+           if (!constrain_operands (1))
+             {
+               error_for_asm (insn,
+                              "%<asm%> operand has impossible constraints");
+               delete_insn (insn);
+               continue;
+             }
+         }
       }
 
-  /* If we are doing stack checking, give a warning if this function's
-     frame size is larger than we expect.  */
-  if (flag_stack_check && ! STACK_CHECK_BUILTIN)
+  /* If we are doing generic stack checking, give a warning if this
+     function's frame size is larger than we expect.  */
+  if (flag_stack_check == GENERIC_STACK_CHECK)
     {
       HOST_WIDE_INT size = get_frame_size () + STACK_CHECK_FIXED_FRAME_SIZE;
       static int verbose_warned = 0;
 
       for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
-       if (regs_ever_live[i] && ! fixed_regs[i] && call_used_regs[i])
+       if (df_regs_ever_live_p (i) && ! fixed_regs[i] && call_used_regs[i])
          size += UNITS_PER_WORD;
 
       if (size > STACK_CHECK_MAX_FRAME_SIZE)
@@ -1281,6 +1423,8 @@ reload (rtx first, int global)
   VEC_free (rtx, gc, reg_equiv_memory_loc_vec);
   reg_equiv_memory_loc = 0;
 
+  free (temp_pseudo_reg_arr);
+
   if (offsets_known_at)
     free (offsets_known_at);
   if (offsets_at)
@@ -1321,6 +1465,8 @@ reload (rtx first, int global)
     REGNO_POINTER_ALIGN (HARD_FRAME_POINTER_REGNUM) = BITS_PER_UNIT;
 #endif
 
+  VEC_free (rtx_p, heap, substitute_stack);
+
   return failure;
 }
 
@@ -1399,11 +1545,11 @@ maybe_fix_stack_asms (void)
              switch (c)
                {
                case '=': case '+': case '*': case '%': case '?': case '!':
-               case '0': case '1': case '2': case '3': case '4': case 'm':
-               case '<': case '>': case 'V': case 'o': case '&': case 'E':
-               case 'F': case 's': case 'i': case 'n': case 'X': case 'I':
-               case 'J': case 'K': case 'L': case 'M': case 'N': case 'O':
-               case 'P':
+               case '0': case '1': case '2': case '3': case '4': case '<':
+               case '>': case 'V': case 'o': case '&': case 'E': case 'F':
+               case 's': case 'i': case 'n': case 'X': case 'I': case 'J':
+               case 'K': case 'L': case 'M': case 'N': case 'O': case 'P':
+               case TARGET_MEM_CONSTRAINT:
                  break;
 
                case 'p':
@@ -1448,10 +1594,9 @@ static void
 copy_reloads (struct insn_chain *chain)
 {
   chain->n_reloads = n_reloads;
-  chain->rld = obstack_alloc (&reload_obstack,
-                             n_reloads * sizeof (struct reload));
+  chain->rld = XOBNEWVEC (&reload_obstack, struct reload, n_reloads);
   memcpy (chain->rld, rld, n_reloads * sizeof (struct reload));
-  reload_insn_firstobj = obstack_alloc (&reload_obstack, 0);
+  reload_insn_firstobj = XOBNEWVAR (&reload_obstack, char, 0);
 }
 
 /* Walk the chain of insns, and determine for each whether it needs reloads
@@ -1465,7 +1610,7 @@ calculate_needs_all_insns (int global)
 
   something_needs_elimination = 0;
 
-  reload_insn_firstobj = obstack_alloc (&reload_obstack, 0);
+  reload_insn_firstobj = XOBNEWVAR (&reload_obstack, char, 0);
   for (chain = reload_insn_chain; chain != 0; chain = next)
     {
       rtx insn = chain->insn;
@@ -1479,8 +1624,8 @@ calculate_needs_all_insns (int global)
       chain->need_operand_change = 0;
 
       /* If this is a label, a JUMP_INSN, or has REG_NOTES (which might
-        include REG_LABEL), we need to see what effects this has on the
-        known offsets at labels.  */
+        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))
@@ -1522,10 +1667,24 @@ 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)
@@ -1586,8 +1745,8 @@ reload_reg_class_lower (const void *r1p, const void *r2p)
     return t;
 
   /* Count all solitary classes before non-solitary ones.  */
-  t = ((reg_class_size[(int) rld[r2].class] == 1)
-       - (reg_class_size[(int) rld[r1].class] == 1));
+  t = ((reg_class_size[(int) rld[r2].rclass] == 1)
+       - (reg_class_size[(int) rld[r1].rclass] == 1));
   if (t != 0)
     return t;
 
@@ -1597,7 +1756,7 @@ reload_reg_class_lower (const void *r1p, const void *r2p)
     return t;
 
   /* Consider reloads in order of increasing reg-class number.  */
-  t = (int) rld[r1].class - (int) rld[r2].class;
+  t = (int) rld[r1].rclass - (int) rld[r2].rclass;
   if (t != 0)
     return t;
 
@@ -1614,6 +1773,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
@@ -1624,7 +1787,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);
@@ -1632,10 +1798,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
@@ -1653,6 +1821,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
@@ -1695,18 +1865,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.  */
@@ -1718,15 +1895,17 @@ 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);
-  IOR_COMPL_HARD_REG_SET (not_usable, reg_class_contents[rl->class]);
+  IOR_COMPL_HARD_REG_SET (not_usable, reg_class_contents[rl->rclass]);
 
   CLEAR_HARD_REG_SET (used_by_other_reload);
   for (k = 0; k < order; k++)
@@ -1740,7 +1919,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)
@@ -1759,6 +1942,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)
@@ -1806,6 +2021,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;
@@ -1867,7 +2083,7 @@ find_reload_regs (struct insn_chain *chain)
          {
            if (dump_file)
              fprintf (dump_file, "reload failure for reload %d\n", r);
-           spill_failure (chain->insn, rld[r].class);
+           spill_failure (chain->insn, rld[r].rclass);
            failure = 1;
            return;
          }
@@ -1925,16 +2141,16 @@ delete_caller_save_insns (void)
    INSN should be one of the insns which needed this particular spill reg.  */
 
 static void
-spill_failure (rtx insn, enum reg_class class)
+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 "
                   "reloading %<asm%>",
-                  reg_class_names[class]);
+                  reg_class_names[rclass]);
   else
     {
       error ("unable to find a register to spill in class %qs",
-            reg_class_names[class]);
+            reg_class_names[rclass]);
 
       if (dump_file)
        {
@@ -1975,7 +2191,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.  */
@@ -1989,8 +2205,8 @@ alter_reg (int i, int from_reg)
 
   /* Modify the reg-rtx to contain the new hard reg
      number or else to contain its pseudo reg number.  */
-  REGNO (regno_reg_rtx[i])
-    = reg_renumber[i] >= 0 ? reg_renumber[i] : i;
+  SET_REGNO (regno_reg_rtx[i],
+            reg_renumber[i] >= 0 ? reg_renumber[i] : i);
 
   /* If we have a pseudo that is needed but has no hard reg or equivalent,
      allocate a stack slot for it.  */
@@ -2001,7 +2217,7 @@ alter_reg (int i, int from_reg)
       && (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);
@@ -2009,6 +2225,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.
@@ -2017,21 +2246,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))
        {
+         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, new_alias_set ());
+           {
+             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.  */
@@ -2066,18 +2308,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])
-           set_mem_alias_set (x, MEM_ALIAS_SET (spill_stack_slot[from_reg]));
-         else
-           set_mem_alias_set (x, new_alias_set ());
-
+         /* 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
@@ -2100,45 +2335,38 @@ 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;
     }
 }
 
-/* Mark the slots in regs_ever_live for the hard regs
-   used by pseudo-reg number REGNO.  */
+/* Mark the slots in regs_ever_live for the hard regs used by
+   pseudo-reg number REGNO, accessed in MODE.  */
 
-void
-mark_home_live (int regno)
+static void
+mark_home_live_1 (int regno, enum machine_mode mode)
 {
   int i, lim;
 
   i = reg_renumber[regno];
   if (i < 0)
     return;
-  lim = i + hard_regno_nregs[i][PSEUDO_REGNO_MODE (regno)];
+  lim = end_hard_regno (mode, i);
   while (i < lim)
-    regs_ever_live[i++] = 1;
+    df_set_regs_ever_live(i++, true);
+}
+
+/* Mark the slots in regs_ever_live for the hard regs
+   used by pseudo-reg number REGNO.  */
+
+void
+mark_home_live (int regno)
+{
+  if (reg_renumber[regno] >= 0)
+    mark_home_live_1 (regno, PSEUDO_REGNO_MODE (regno));
 }
 \f
 /* This function handles the tracking of elimination offsets around branches.
@@ -2214,10 +2442,11 @@ set_label_offsets (rtx x, rtx insn, int initial_p)
 
     case INSN:
     case CALL_INSN:
-      /* Any labels mentioned in REG_LABEL notes can be branched to indirectly
-        and hence must have all eliminations at their initial offsets.  */
+      /* Any labels mentioned in REG_LABEL_OPERAND notes can be branched
+        to indirectly and hence must have all eliminations at their
+        initial offsets.  */
       for (tem = REG_NOTES (x); tem; tem = XEXP (tem, 1))
-       if (REG_NOTE_KIND (tem) == REG_LABEL)
+       if (REG_NOTE_KIND (tem) == REG_LABEL_OPERAND)
          set_label_offsets (XEXP (tem, 0), insn, 1);
       return;
 
@@ -2321,7 +2550,7 @@ eliminate_regs_1 (rtx x, enum machine_mode mem_mode, rtx insn,
   enum rtx_code code = GET_CODE (x);
   struct elim_table *ep;
   int regno;
-  rtx new;
+  rtx new_rtx;
   int i, j;
   const char *fmt;
   int copied = 0;
@@ -2333,6 +2562,7 @@ eliminate_regs_1 (rtx x, enum machine_mode mem_mode, rtx insn,
     {
     case CONST_INT:
     case CONST_DOUBLE:
+    case CONST_FIXED:
     case CONST_VECTOR:
     case CONST:
     case SYMBOL_REF:
@@ -2361,13 +2591,13 @@ 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])
        {
-         if (may_use_invariant)
+         if (may_use_invariant || (insn && DEBUG_INSN_P (insn)))
            return eliminate_regs_1 (copy_rtx (reg_equiv_invariant[regno]),
                                     mem_mode, insn, true);
          /* 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);
+         alter_reg (regno, -1, true);
        }
       return x;
 
@@ -2404,7 +2634,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
@@ -2449,15 +2679,15 @@ eliminate_regs_1 (rtx x, enum machine_mode mem_mode, rtx insn,
                     && reg_equiv_constant[REGNO (new0)] != 0)
              new0 = reg_equiv_constant[REGNO (new0)];
 
-           new = 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
               for an addition of 0 if we aren't optimizing.  */
-           if (! mem_mode && GET_CODE (new) != PLUS)
-             return gen_rtx_PLUS (GET_MODE (x), new, const0_rtx);
+           if (! mem_mode && GET_CODE (new_rtx) != PLUS)
+             return gen_rtx_PLUS (GET_MODE (x), new_rtx, const0_rtx);
            else
-             return new;
+             return new_rtx;
          }
       }
       return x;
@@ -2470,15 +2700,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
@@ -2514,18 +2746,18 @@ 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 = eliminate_regs_1 (XEXP (x, 0), mem_mode, insn, true);
-         if (new != XEXP (x, 0))
+         new_rtx = eliminate_regs_1 (XEXP (x, 0), mem_mode, insn, true);
+         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)
                        : NULL_RTX);
 
-             x = gen_rtx_EXPR_LIST (REG_NOTE_KIND (x), new, XEXP (x, 1));
+             x = alloc_reg_note (REG_NOTE_KIND (x), new_rtx, XEXP (x, 1));
            }
        }
 
@@ -2537,10 +2769,10 @@ eliminate_regs_1 (rtx x, enum machine_mode mem_mode, rtx insn,
         strictly needed, but it simplifies the code.  */
       if (XEXP (x, 1))
        {
-         new = eliminate_regs_1 (XEXP (x, 1), mem_mode, insn, true);
-         if (new != XEXP (x, 1))
+         new_rtx = eliminate_regs_1 (XEXP (x, 1), mem_mode, insn, true);
+         if (new_rtx != XEXP (x, 1))
            return
-             gen_rtx_fmt_ee (GET_CODE (x), GET_MODE (x), XEXP (x, 0), new);
+             gen_rtx_fmt_ee (GET_CODE (x), GET_MODE (x), XEXP (x, 0), new_rtx);
        }
       return x;
 
@@ -2562,13 +2794,13 @@ eliminate_regs_1 (rtx x, enum machine_mode mem_mode, rtx insn,
       if (GET_CODE (XEXP (x, 1)) == PLUS
          && XEXP (XEXP (x, 1), 0) == XEXP (x, 0))
        {
-         rtx new = eliminate_regs_1 (XEXP (XEXP (x, 1), 1), mem_mode,
+         rtx new_rtx = eliminate_regs_1 (XEXP (XEXP (x, 1), 1), mem_mode,
                                      insn, true);
 
-         if (new != XEXP (XEXP (x, 1), 1))
+         if (new_rtx != XEXP (XEXP (x, 1), 1))
            return gen_rtx_fmt_ee (code, GET_MODE (x), XEXP (x, 0),
                                   gen_rtx_PLUS (GET_MODE (x),
-                                                XEXP (x, 0), new));
+                                                XEXP (x, 0), new_rtx));
        }
       return x;
 
@@ -2586,9 +2818,9 @@ eliminate_regs_1 (rtx x, enum machine_mode mem_mode, rtx insn,
     case POPCOUNT:
     case PARITY:
     case BSWAP:
-      new = eliminate_regs_1 (XEXP (x, 0), mem_mode, insn, false);
-      if (new != XEXP (x, 0))
-       return gen_rtx_fmt_e (code, GET_MODE (x), new);
+      new_rtx = eliminate_regs_1 (XEXP (x, 0), mem_mode, insn, false);
+      if (new_rtx != XEXP (x, 0))
+       return gen_rtx_fmt_e (code, GET_MODE (x), new_rtx);
       return x;
 
     case SUBREG:
@@ -2604,17 +2836,17 @@ eliminate_regs_1 (rtx x, enum machine_mode mem_mode, rtx insn,
          && reg_equiv_memory_loc != 0
          && reg_equiv_memory_loc[REGNO (SUBREG_REG (x))] != 0)
        {
-         new = SUBREG_REG (x);
+         new_rtx = SUBREG_REG (x);
        }
       else
-       new = eliminate_regs_1 (SUBREG_REG (x), mem_mode, insn, false);
+       new_rtx = eliminate_regs_1 (SUBREG_REG (x), mem_mode, insn, false);
 
-      if (new != SUBREG_REG (x))
+      if (new_rtx != SUBREG_REG (x))
        {
          int x_size = GET_MODE_SIZE (GET_MODE (x));
-         int new_size = GET_MODE_SIZE (GET_MODE (new));
+         int new_size = GET_MODE_SIZE (GET_MODE (new_rtx));
 
-         if (MEM_P (new)
+         if (MEM_P (new_rtx)
              && ((x_size < new_size
 #ifdef WORD_REGISTER_OPERATIONS
                   /* On these machines, combine can create rtl of the form
@@ -2630,9 +2862,9 @@ eliminate_regs_1 (rtx x, enum machine_mode mem_mode, rtx insn,
                   )
                  || x_size == new_size)
              )
-           return adjust_address_nv (new, GET_MODE (x), SUBREG_BYTE (x));
+           return adjust_address_nv (new_rtx, GET_MODE (x), SUBREG_BYTE (x));
          else
-           return gen_rtx_SUBREG (GET_MODE (x), new, SUBREG_BYTE (x));
+           return gen_rtx_SUBREG (GET_MODE (x), new_rtx, SUBREG_BYTE (x));
        }
 
       return x;
@@ -2648,12 +2880,15 @@ eliminate_regs_1 (rtx x, enum machine_mode mem_mode, rtx insn,
 
     case USE:
       /* Handle insn_list USE that a call to a pure function may generate.  */
-      new = eliminate_regs_1 (XEXP (x, 0), 0, insn, false);
-      if (new != XEXP (x, 0))
-       return gen_rtx_USE (GET_MODE (x), new);
+      new_rtx = eliminate_regs_1 (XEXP (x, 0), VOIDmode, insn, false);
+      if (new_rtx != XEXP (x, 0))
+       return gen_rtx_USE (GET_MODE (x), new_rtx);
       return x;
 
     case CLOBBER:
+      gcc_assert (insn && DEBUG_INSN_P (insn));
+      break;
+
     case ASM_OPERANDS:
     case SET:
       gcc_unreachable ();
@@ -2669,21 +2904,21 @@ eliminate_regs_1 (rtx x, enum machine_mode mem_mode, rtx insn,
     {
       if (*fmt == 'e')
        {
-         new = eliminate_regs_1 (XEXP (x, i), mem_mode, insn, false);
-         if (new != XEXP (x, i) && ! copied)
+         new_rtx = eliminate_regs_1 (XEXP (x, i), mem_mode, insn, false);
+         if (new_rtx != XEXP (x, i) && ! copied)
            {
              x = shallow_copy_rtx (x);
              copied = 1;
            }
-         XEXP (x, i) = new;
+         XEXP (x, i) = new_rtx;
        }
       else if (*fmt == 'E')
        {
          int copied_vec = 0;
          for (j = 0; j < XVECLEN (x, i); j++)
            {
-             new = eliminate_regs_1 (XVECEXP (x, i, j), mem_mode, insn, false);
-             if (new != XVECEXP (x, i, j) && ! copied_vec)
+             new_rtx = eliminate_regs_1 (XVECEXP (x, i, j), mem_mode, insn, false);
+             if (new_rtx != XVECEXP (x, i, j) && ! copied_vec)
                {
                  rtvec new_v = gen_rtvec_v (XVECLEN (x, i),
                                             XVEC (x, i)->elem);
@@ -2695,7 +2930,7 @@ eliminate_regs_1 (rtx x, enum machine_mode mem_mode, rtx insn,
                  XVEC (x, i) = new_v;
                  copied_vec = 1;
                }
-             XVECEXP (x, i, j) = new;
+             XVECEXP (x, i, j) = new_rtx;
            }
        }
     }
@@ -2726,6 +2961,7 @@ elimination_effects (rtx x, enum machine_mode mem_mode)
     {
     case CONST_INT:
     case CONST_DOUBLE:
+    case CONST_FIXED:
     case CONST_VECTOR:
     case CONST:
     case SYMBOL_REF:
@@ -2881,15 +3117,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:
@@ -2987,7 +3223,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;
     }
 
@@ -3016,7 +3256,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);
@@ -3091,7 +3331,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)
@@ -3101,9 +3341,10 @@ eliminate_regs_in_insn (rtx insn, int replace)
          rtx links;
          for (links = REG_NOTES (insn); links; links = XEXP (links, 1))
            {
-             if (REG_NOTE_KIND (links) == REG_EQUAL
+             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;
@@ -3136,7 +3377,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)),
@@ -3163,7 +3404,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))
@@ -3186,7 +3427,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.  */
@@ -3227,7 +3468,7 @@ 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);
          if (substed_operand[i] != orig_operand[i])
@@ -3236,14 +3477,13 @@ eliminate_regs_in_insn (rtx insn, int replace)
             this point.  */
          *recog_data.operand_loc[i] = 0;
 
-       /* If an output operand changed from a REG to a MEM and INSN is an
-          insn, write a CLOBBER insn.  */
+         /* If an output operand changed from a REG to a MEM and INSN is an
+            insn, write a CLOBBER insn.  */
          if (recog_data.operand_type[i] != OP_IN
              && REG_P (orig_operand[i])
              && MEM_P (substed_operand[i])
              && replace)
-           emit_insn_after (gen_rtx_CLOBBER (VOIDmode, orig_operand[i]),
-                            insn);
+           emit_insn_after (gen_clobber (orig_operand[i]), insn);
        }
     }
 
@@ -3321,7 +3561,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]];
     }
@@ -3358,7 +3601,7 @@ 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);
 
   return val;
 }
@@ -3398,7 +3641,7 @@ update_eliminable_offsets (void)
    the insns of the function.  */
 
 static void
-mark_not_eliminable (rtx dest, rtx x, void *data ATTRIBUTE_UNUSED)
+mark_not_eliminable (rtx dest, const_rtx x, void *data ATTRIBUTE_UNUSED)
 {
   unsigned int i;
 
@@ -3416,7 +3659,7 @@ mark_not_eliminable (rtx dest, 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;
@@ -3539,9 +3782,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;
@@ -3588,8 +3832,11 @@ update_eliminables (HARD_REG_SET *pset)
   frame_pointer_needed = 1;
   for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
     {
-      if (ep->can_eliminate && ep->from == FRAME_POINTER_REGNUM
-         && ep->to != HARD_FRAME_POINTER_REGNUM)
+      if (ep->can_eliminate
+         && ep->from == FRAME_POINTER_REGNUM
+         && ep->to != HARD_FRAME_POINTER_REGNUM
+         && (! SUPPORTS_STACK_ALIGNMENT
+             || ! crtl->stack_realign_needed))
        frame_pointer_needed = 0;
 
       if (! ep->can_eliminate && ep->can_eliminate_previous)
@@ -3606,7 +3853,23 @@ update_eliminables (HARD_REG_SET *pset)
     SET_HARD_REG_BIT (*pset, HARD_FRAME_POINTER_REGNUM);
 }
 
-/* Initialize the table of registers to eliminate.  */
+/* Return true if X is used as the target register of an elimination.  */
+
+bool
+elimination_target_reg_p (rtx x)
+{
+  struct elim_table *ep;
+
+  for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
+    if (ep->to_rtx == x && ep->can_eliminate)
+      return true;
+
+  return false;
+}
+
+/* Initialize the table of registers to eliminate.
+   Pre-condition: global flag frame_pointer_needed has been set before
+   calling this function.  */
 
 static void
 init_elim_table (void)
@@ -3617,20 +3880,7 @@ init_elim_table (void)
 #endif
 
   if (!reg_eliminate)
-    reg_eliminate = xcalloc (sizeof (struct elim_table), NUM_ELIMINABLE_REGS);
-
-  /* Does this function require a frame pointer?  */
-
-  frame_pointer_needed = (! flag_omit_frame_pointer
-                         /* ?? If EXIT_IGNORE_STACK is set, we will not save
-                            and restore sp for alloca.  So we can't eliminate
-                            the frame pointer in that case.  At some point,
-                            we should improve this by emitting the
-                            sp-adjusting insns for this case.  */
-                         || (current_function_calls_alloca
-                             && EXIT_IGNORE_STACK)
-                         || current_function_accesses_prior_frames
-                         || FRAME_POINTER_REQUIRED);
+    reg_eliminate = XCNEWVEC (struct elim_table, NUM_ELIMINABLE_REGS);
 
   num_eliminable = 0;
 
@@ -3641,8 +3891,11 @@ 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)
-          && ! (ep->to == STACK_POINTER_REGNUM && frame_pointer_needed));
+       = (targetm.can_eliminate (ep->from, ep->to)
+          && ! (ep->to == STACK_POINTER_REGNUM
+                && frame_pointer_needed
+                && (! SUPPORTS_STACK_ALIGNMENT
+                    || ! stack_realign_fp)));
     }
 #else
   reg_eliminate[0].from = reg_eliminate_1[0].from;
@@ -3681,7 +3934,7 @@ spill_hard_reg (unsigned int regno, int cant_eliminate)
   if (cant_eliminate)
     {
       SET_HARD_REG_BIT (bad_spill_regs_global, regno);
-      regs_ever_live[regno] = 1;
+      df_set_regs_ever_live (regno, true);
     }
 
   /* Spill every pseudo reg that was allocated to this reg
@@ -3690,10 +3943,7 @@ spill_hard_reg (unsigned int regno, int cant_eliminate)
   for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
     if (reg_renumber[i] >= 0
        && (unsigned int) reg_renumber[i] <= regno
-       && ((unsigned int) reg_renumber[i]
-           + hard_regno_nregs[(unsigned int) reg_renumber[i]]
-                             [PSEUDO_REGNO_MODE (i)]
-           > regno))
+       && end_hard_regno (PSEUDO_REGNO_MODE (i), reg_renumber[i]) > regno)
       SET_REGNO_REG_SET (&spilled_pseudos, i);
 }
 
@@ -3728,30 +3978,36 @@ finish_spills (int global)
       {
        spill_reg_order[i] = n_spills;
        spill_regs[n_spills++] = i;
-       if (num_eliminable && ! regs_ever_live[i])
+       if (num_eliminable && ! df_regs_ever_live_p (i))
          something_changed = 1;
-       regs_ever_live[i] = 1;
+       df_set_regs_ever_live (i, true);
       }
     else
       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
@@ -3772,24 +4028,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.  */
@@ -3798,9 +4054,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)
@@ -3809,21 +4070,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.  */
-         GO_IF_HARD_REG_SUBSET (used_by_pseudos2, chain->used_spill_regs, ok);
-         gcc_unreachable ();
-       ok:;
        }
     }
 
+  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++)
     {
@@ -3831,7 +4089,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)
        {
@@ -3863,6 +4123,7 @@ scan_paradoxical_subregs (rtx x)
     case SYMBOL_REF:
     case LABEL_REF:
     case CONST_DOUBLE:
+    case CONST_FIXED:
     case CONST_VECTOR: /* shouldn't happen, but just in case.  */
     case CC0:
     case PC:
@@ -3874,8 +4135,11 @@ scan_paradoxical_subregs (rtx x)
       if (REG_P (SUBREG_REG (x))
          && (GET_MODE_SIZE (GET_MODE (x))
              > reg_max_ref_width[REGNO (SUBREG_REG (x))]))
-       reg_max_ref_width[REGNO (SUBREG_REG (x))]
-         = GET_MODE_SIZE (GET_MODE (x));
+       {
+         reg_max_ref_width[REGNO (SUBREG_REG (x))]
+           = GET_MODE_SIZE (GET_MODE (x));
+         mark_home_live_1 (REGNO (SUBREG_REG (x)), GET_MODE (x));
+       }
       return;
 
     default:
@@ -3904,27 +4168,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++;
-       REG_NOTES (i)
-         = gen_rtx_EXPR_LIST (REG_EH_REGION, XEXP (note, 0), REG_NOTES (i));
-      }
+  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.
@@ -3959,6 +4207,9 @@ reload_as_needed (int live_known)
       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.  */
@@ -4034,7 +4285,7 @@ reload_as_needed (int live_known)
              /* 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)
+             if (targetm.small_register_classes_for_mode_p (VOIDmode))
                merge_assigned_reloads (insn);
 
              /* Generate the insns to reload operands into or out of
@@ -4127,39 +4378,36 @@ 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;
                        }
                      if (n == 1)
                        {
-                         REG_NOTES (p)
-                           = gen_rtx_EXPR_LIST (REG_INC, reload_reg,
-                                                REG_NOTES (p));
+                         add_reg_note (p, REG_INC, reload_reg);
                          /* Mark this as having an output reload so that the
                             REG_INC processing code below won't invalidate
                             the reload for inheritance.  */
@@ -4185,6 +4433,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,
@@ -4214,8 +4499,8 @@ 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);
        }
     }
 
@@ -4229,13 +4514,13 @@ 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.  */
 
 static void
-forget_old_reloads_1 (rtx x, rtx ignored ATTRIBUTE_UNUSED,
+forget_old_reloads_1 (rtx x, const_rtx ignored ATTRIBUTE_UNUSED,
                      void *data)
 {
   unsigned int regno;
@@ -4276,7 +4561,6 @@ forget_old_reloads_1 (rtx x, rtx ignored ATTRIBUTE_UNUSED,
              || ! TEST_HARD_REG_BIT (reg_is_output_reload, regno + i))
            {
              CLEAR_HARD_REG_BIT (reg_reloaded_valid, regno + i);
-             CLEAR_HARD_REG_BIT (reg_reloaded_call_part_clobbered, regno + i);
              spill_reg_store[regno + i] = 0;
            }
     }
@@ -4313,7 +4597,6 @@ forget_marked_reloads (regset regs)
              || ! TEST_HARD_REG_BIT (reg_is_output_reload, reg)))
          {
            CLEAR_HARD_REG_BIT (reg_reloaded_valid, reg);
-           CLEAR_HARD_REG_BIT (reg_reloaded_call_part_clobbered, reg);
            spill_reg_store[reg] = 0;
          }
       if (n_reloads == 0
@@ -4514,8 +4797,7 @@ clear_reload_reg_in_use (unsigned int regno, int opnum,
            {
              unsigned int conflict_start = true_regnum (rld[i].reg_rtx);
              unsigned int conflict_end
-               = (conflict_start
-                  + hard_regno_nregs[conflict_start][rld[i].mode]);
+               = end_hard_regno (rld[i].mode, conflict_start);
 
              /* If there is an overlap with the first to-be-freed register,
                 adjust the interval start.  */
@@ -4828,6 +5110,21 @@ reload_reg_reaches_end_p (unsigned int regno, int opnum, enum reload_type type)
       gcc_unreachable ();
     }
 }
+
+/* Like reload_reg_reaches_end_p, but check that the condition holds for
+   every register in the range [REGNO, REGNO + NREGS).  */
+
+static bool
+reload_regs_reach_end_p (unsigned int regno, int nregs,
+                        int opnum, enum reload_type type)
+{
+  int i;
+
+  for (i = 0; i < nregs; i++)
+    if (!reload_reg_reaches_end_p (regno + i, opnum, type))
+      return false;
+  return true;
+}
 \f
 
 /*  Returns whether R1 and R2 are uniquely chained: the value of one
@@ -4874,6 +5171,133 @@ 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, tem, 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.  */
+  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;
+
+  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.
 
@@ -4923,7 +5347,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
@@ -4967,6 +5392,12 @@ static rtx reload_override_in[MAX_RELOADS];
    or -1 if we did not need a register for this reload.  */
 static int reload_spill_index[MAX_RELOADS];
 
+/* Index X is the value of rld[X].reg_rtx, adjusted for the input mode.  */
+static rtx reload_reg_rtx_for_input[MAX_RELOADS];
+
+/* Index X is the value of rld[X].reg_rtx, adjusted for the output mode.  */
+static rtx reload_reg_rtx_for_output[MAX_RELOADS];
+
 /* Subroutine of free_for_value_p, used to check a single register.
    START_REGNO is the starting regno of the full reload register
    (possibly comprising multiple hard registers) that we are considering.  */
@@ -5232,7 +5663,7 @@ free_for_value_p (int regno, enum machine_mode mode, int opnum,
    memory.  */
 
 int
-function_invariant_p (rtx x)
+function_invariant_p (const_rtx x)
 {
   if (CONSTANT_P (x))
     return 1;
@@ -5381,7 +5812,7 @@ allocate_reload_reg (struct insn_chain *chain ATTRIBUTE_UNUSED, int r,
 
       for (count = 0; count < n_spills; count++)
        {
-         int class = (int) rld[r].class;
+         int rclass = (int) rld[r].rclass;
          int regnum;
 
          i++;
@@ -5398,7 +5829,7 @@ allocate_reload_reg (struct insn_chain *chain ATTRIBUTE_UNUSED, int r,
                   && free_for_value_p (regnum, rld[r].mode, rld[r].opnum,
                                        rld[r].when_needed, rld[r].in,
                                        rld[r].out, r, 1)))
-             && TEST_HARD_REG_BIT (reg_class_contents[class], regnum)
+             && TEST_HARD_REG_BIT (reg_class_contents[rclass], regnum)
              && HARD_REGNO_MODE_OK (regnum, rld[r].mode)
              /* Look first for regs to share, then for unshared.  But
                 don't share regs used for inherited reloads; they are
@@ -5428,7 +5859,7 @@ allocate_reload_reg (struct insn_chain *chain ATTRIBUTE_UNUSED, int r,
              while (nr > 1)
                {
                  int regno = regnum + nr - 1;
-                 if (!(TEST_HARD_REG_BIT (reg_class_contents[class], regno)
+                 if (!(TEST_HARD_REG_BIT (reg_class_contents[rclass], regno)
                        && spill_reg_order[regno] >= 0
                        && reload_reg_free_p (regno, rld[r].opnum,
                                              rld[r].when_needed)))
@@ -5541,13 +5972,20 @@ choose_reload_regs (struct insn_chain *chain)
   for (j = 0; j < n_reloads; j++)
     {
       reload_order[j] = j;
-      reload_spill_index[j] = -1;
+      if (rld[j].reg_rtx != NULL_RTX)
+       {
+         gcc_assert (REG_P (rld[j].reg_rtx)
+                     && HARD_REGISTER_P (rld[j].reg_rtx));
+         reload_spill_index[j] = REGNO (rld[j].reg_rtx);
+       }
+      else
+       reload_spill_index[j] = -1;
 
       if (rld[j].nregs > 1)
        {
          max_group_size = MAX (rld[j].nregs, max_group_size);
          group_class
-           = reg_class_superunion[(int) rld[j].class][(int) group_class];
+           = reg_class_superunion[(int) rld[j].rclass][(int) group_class];
        }
 
       save_reload_reg_rtx[j] = rld[j].reg_rtx;
@@ -5693,7 +6131,7 @@ choose_reload_regs (struct insn_chain *chain)
 #endif
                  )
                {
-                 enum reg_class class = rld[r].class, last_class;
+                 enum reg_class rclass = rld[r].rclass, last_class;
                  rtx last_reg = reg_last_reload_reg[regno];
                  enum machine_mode need_mode;
 
@@ -5705,27 +6143,28 @@ choose_reload_regs (struct insn_chain *chain)
                    need_mode = mode;
                  else
                    need_mode
-                     = smallest_mode_for_size (GET_MODE_BITSIZE (mode)
-                                               + byte * BITS_PER_UNIT,
-                                               GET_MODE_CLASS (mode));
+                     = smallest_mode_for_size
+                       (GET_MODE_BITSIZE (mode) + byte * BITS_PER_UNIT,
+                        GET_MODE_CLASS (mode) == MODE_PARTIAL_INT
+                        ? MODE_INT : GET_MODE_CLASS (mode));
 
                  if ((GET_MODE_SIZE (GET_MODE (last_reg))
                       >= GET_MODE_SIZE (need_mode))
                      && 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) class], i)
+                     && (TEST_HARD_REG_BIT (reg_class_contents[(int) rclass], i)
                          /* Even if we can't use this register as a reload
                             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, class)
-                              < MEMORY_MOVE_COST (mode, class, 1))
-                             && (secondary_reload_class (1, class, mode,
+                         || ((REGISTER_MOVE_COST (mode, last_class, rclass)
+                              < MEMORY_MOVE_COST (mode, rclass, 1))
+                             && (secondary_reload_class (1, rclass, mode,
                                                          last_reg)
                                  == NO_REGS)
 #ifdef SECONDARY_MEMORY_NEEDED
-                             && ! SECONDARY_MEMORY_NEEDED (last_class, class,
+                             && ! SECONDARY_MEMORY_NEEDED (last_class, rclass,
                                                            mode)
 #endif
                              ))
@@ -5757,7 +6196,7 @@ choose_reload_regs (struct insn_chain *chain)
 
                          bad_for_class = 0;
                          for (k = 0; k < nr; k++)
-                           bad_for_class |= ! TEST_HARD_REG_BIT (reg_class_contents[(int) rld[r].class],
+                           bad_for_class |= ! TEST_HARD_REG_BIT (reg_class_contents[(int) rld[r].rclass],
                                                                  i+k);
 
                          /* We found a register that contains the
@@ -5839,7 +6278,7 @@ choose_reload_regs (struct insn_chain *chain)
                  || REG_P (rld[r].in)
                  || MEM_P (rld[r].in))
              && (rld[r].nregs == max_group_size
-                 || ! reg_classes_intersect_p (rld[r].class, group_class)))
+                 || ! 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.  */
@@ -5856,7 +6295,7 @@ choose_reload_regs (struct insn_chain *chain)
          if (search_equiv)
            {
              rtx equiv
-               = find_equiv_reg (search_equiv, insn, rld[r].class,
+               = find_equiv_reg (search_equiv, insn, rld[r].rclass,
                                  -1, NULL, 0, rld[r].mode);
              int regno = 0;
 
@@ -5897,7 +6336,7 @@ choose_reload_regs (struct insn_chain *chain)
                    {
                      regs_used |= TEST_HARD_REG_BIT (reload_reg_used_at_all,
                                                      i);
-                     bad_for_class |= ! TEST_HARD_REG_BIT (reg_class_contents[(int) rld[r].class],
+                     bad_for_class |= ! TEST_HARD_REG_BIT (reg_class_contents[(int) rld[r].rclass],
                                                           i);
                    }
 
@@ -5983,6 +6422,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,
@@ -6035,9 +6475,9 @@ choose_reload_regs (struct insn_chain *chain)
                  || rld[s].optional)
                continue;
 
-             if ((rld[s].class != rld[r].class
-                  && reg_classes_intersect_p (rld[r].class,
-                                              rld[s].class))
+             if ((rld[s].rclass != rld[r].rclass
+                  && reg_classes_intersect_p (rld[r].rclass,
+                                              rld[s].rclass))
                  || rld[s].nregs < rld[r].nregs)
                break;
            }
@@ -6231,10 +6671,11 @@ 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.
+/* If the small_register_classes_for_mode_p target hook returns true for
+   some machine modes, 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
@@ -6322,15 +6763,23 @@ merge_assigned_reloads (rtx insn)
                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.  */
+         /* 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++)
@@ -6338,6 +6787,7 @@ merge_assigned_reloads (rtx insn)
                  && 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)
@@ -6442,49 +6892,13 @@ emit_input_reload_insns (struct insn_chain *chain, struct reload *rl,
                         rtx old, int j)
 {
   rtx insn = chain->insn;
-  rtx reloadreg = rl->reg_rtx;
+  rtx reloadreg;
   rtx oldequiv_reg = 0;
   rtx oldequiv = 0;
   int special = 0;
   enum machine_mode mode;
   rtx *where;
 
-  /* Determine the mode to reload in.
-     This is very tricky because we have three to choose from.
-     There is the mode the insn operand wants (rl->inmode).
-     There is the mode of the reload register RELOADREG.
-     There is the intrinsic mode of the operand, which we could find
-     by stripping some SUBREGs.
-     It turns out that RELOADREG's mode is irrelevant:
-     we can change that arbitrarily.
-
-     Consider (SUBREG:SI foo:QI) as an operand that must be SImode;
-     then the reload reg may not support QImode moves, so use SImode.
-     If foo is in memory due to spilling a pseudo reg, this is safe,
-     because the QImode value is in the least significant part of a
-     slot big enough for a SImode.  If foo is some other sort of
-     memory reference, then it is impossible to reload this case,
-     so previous passes had better make sure this never happens.
-
-     Then consider a one-word union which has SImode and one of its
-     members is a float, being fetched as (SUBREG:SF union:SI).
-     We must fetch that as SFmode because we could be loading into
-     a float-only register.  In this case OLD's mode is correct.
-
-     Consider an immediate integer: it has VOIDmode.  Here we need
-     to get a mode from something else.
-
-     In some cases, there is a fourth mode, the operand's
-     containing mode.  If the insn specifies a containing mode for
-     this operand, it overrides all others.
-
-     I am not sure whether the algorithm here is always right,
-     but it does the right things in those cases.  */
-
-  mode = GET_MODE (old);
-  if (mode == VOIDmode)
-    mode = rl->inmode;
-
   /* delete_output_reload is only invoked properly if old contains
      the original pseudo register.  Since this is replaced with a
      hard reg when RELOAD_OVERRIDE_IN is set, see if we can
@@ -6502,6 +6916,9 @@ emit_input_reload_insns (struct insn_chain *chain, struct reload *rl,
   else if (GET_CODE (oldequiv) == SUBREG)
     oldequiv_reg = SUBREG_REG (oldequiv);
 
+  reloadreg = reload_reg_rtx_for_input[j];
+  mode = GET_MODE (reloadreg);
+
   /* If we are reloading from a register that was recently stored in
      with an output-reload, see if we can prove there was
      actually no need to store the old value in it.  */
@@ -6513,16 +6930,11 @@ emit_input_reload_insns (struct insn_chain *chain, struct reload *rl,
       && (dead_or_set_p (insn, spill_reg_stored_to[REGNO (oldequiv)])
          || rtx_equal_p (spill_reg_stored_to[REGNO (oldequiv)],
                          rl->out_reg)))
-    delete_output_reload (insn, j, REGNO (oldequiv));
+    delete_output_reload (insn, j, REGNO (oldequiv), reloadreg);
 
-  /* Encapsulate both RELOADREG and OLDEQUIV into that mode,
-     then load RELOADREG from OLDEQUIV.  Note that we cannot use
-     gen_lowpart_common since it can do the wrong thing when
-     RELOADREG has a multi-word mode.  Note that RELOADREG
-     must always be a REG here.  */
+  /* Encapsulate OLDEQUIV into the reload mode, then load RELOADREG from
+     OLDEQUIV.  */
 
-  if (GET_MODE (reloadreg) != mode)
-    reloadreg = reload_adjust_reg_for_mode (reloadreg, mode);
   while (GET_CODE (oldequiv) == SUBREG && GET_MODE (oldequiv) != mode)
     oldequiv = SUBREG_REG (oldequiv);
   if (GET_MODE (oldequiv) != VOIDmode
@@ -6586,7 +6998,7 @@ emit_input_reload_insns (struct insn_chain *chain, struct reload *rl,
                             spill_reg_stored_to[REGNO (oldequiv)])
              || rtx_equal_p (spill_reg_stored_to[REGNO (oldequiv)],
                              old)))
-       delete_output_reload (insn, j, REGNO (oldequiv));
+       delete_output_reload (insn, j, REGNO (oldequiv), reloadreg);
 
       /* Prevent normal processing of this reload.  */
       special = 1;
@@ -6610,7 +7022,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)
@@ -6646,10 +7058,20 @@ emit_input_reload_insns (struct insn_chain *chain, struct reload *rl,
              if (REG_N_DEATHS (REGNO (old)) == 1
                  && REG_N_SETS (REGNO (old)) == 1)
                {
-                 reg_renumber[REGNO (old)] = REGNO (rl->reg_rtx);
-                 alter_reg (REGNO (old), -1);
+                 reg_renumber[REGNO (old)] = REGNO (reloadreg);
+                 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
            {
@@ -6747,7 +7169,7 @@ 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->class,
+         new_class = targetm.secondary_reload (1, real_oldequiv, rl->rclass,
                                                mode, &sri);
 
          if (new_class == NO_REGS && sri.icode == CODE_FOR_nothing)
@@ -6755,10 +7177,17 @@ emit_input_reload_insns (struct insn_chain *chain, struct reload *rl,
          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.  */
@@ -6774,9 +7203,15 @@ emit_input_reload_insns (struct insn_chain *chain, struct reload *rl,
                  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)
                {
@@ -6785,13 +7220,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)
                {
@@ -6803,14 +7242,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;
+               }
            }
        }
 
@@ -6887,7 +7332,7 @@ emit_input_reload_insns (struct insn_chain *chain, struct reload *rl,
     }
 
   if (flag_non_call_exceptions)
-    copy_eh_notes (insn, get_insns ());
+    copy_reg_eh_region_note_forward (insn, get_insns (), NULL);
 
   /* End this sequence.  */
   *where = get_insns ();
@@ -6905,35 +7350,23 @@ static void
 emit_output_reload_insns (struct insn_chain *chain, struct reload *rl,
                          int j)
 {
-  rtx reloadreg = rl->reg_rtx;
+  rtx reloadreg;
   rtx insn = chain->insn;
   int special = 0;
   rtx old = rl->out;
-  enum machine_mode mode = GET_MODE (old);
+  enum machine_mode mode;
   rtx p;
+  rtx rl_reg_rtx;
 
   if (rl->when_needed == RELOAD_OTHER)
     start_sequence ();
   else
     push_to_sequence (output_reload_insns[rl->opnum]);
 
-  /* Determine the mode to reload in.
-     See comments above (for input reloading).  */
-
-  if (mode == VOIDmode)
-    {
-      /* VOIDmode should never happen for an output.  */
-      if (asm_noperands (PATTERN (insn)) < 0)
-       /* It's the compiler's fault.  */
-       fatal_insn ("VOIDmode on an output", insn);
-      error_for_asm (insn, "output operand is constant in %<asm%>");
-      /* Prevent crash--use something we know is valid.  */
-      mode = word_mode;
-      old = gen_rtx_REG (mode, REGNO (reloadreg));
-    }
+  rl_reg_rtx = reload_reg_rtx_for_output[j];
+  mode = GET_MODE (rl_reg_rtx);
 
-  if (GET_MODE (reloadreg) != mode)
-    reloadreg = reload_adjust_reg_for_mode (reloadreg, mode);
+  reloadreg = rl_reg_rtx;
 
   /* If we need two reload regs, set RELOADREG to the intermediate
      one, since it will be stored into OLD.  We might need a secondary
@@ -6949,7 +7382,7 @@ emit_output_reload_insns (struct insn_chain *chain, struct reload *rl,
          && reg_equiv_mem[REGNO (old)] != 0)
        real_old = reg_equiv_mem[REGNO (old)];
 
-      if (secondary_reload_class (0, rl->class, mode, real_old) != NO_REGS)
+      if (secondary_reload_class (0, rl->rclass, mode, real_old) != NO_REGS)
        {
          rtx second_reloadreg = reloadreg;
          reloadreg = rld[secondary_reload].reg_rtx;
@@ -7057,12 +7490,12 @@ emit_output_reload_insns (struct insn_chain *chain, struct reload *rl,
           reg_has_output_reload will make this do nothing.  */
        note_stores (pat, forget_old_reloads_1, NULL);
 
-       if (reg_mentioned_p (rl->reg_rtx, pat))
+       if (reg_mentioned_p (rl_reg_rtx, pat))
          {
            rtx set = single_set (insn);
            if (reload_spill_index[j] < 0
                && set
-               && SET_SRC (set) == rl->reg_rtx)
+               && SET_SRC (set) == rl_reg_rtx)
              {
                int src = REGNO (SET_SRC (set));
 
@@ -7071,7 +7504,7 @@ emit_output_reload_insns (struct insn_chain *chain, struct reload *rl,
                if (find_regno_note (insn, REG_DEAD, src))
                  SET_HARD_REG_BIT (reg_reloaded_died, src);
              }
-           if (REGNO (rl->reg_rtx) < FIRST_PSEUDO_REGISTER)
+           if (HARD_REGISTER_P (rl_reg_rtx))
              {
                int s = rl->secondary_out_reload;
                set = single_set (p);
@@ -7084,7 +7517,7 @@ emit_output_reload_insns (struct insn_chain *chain, struct reload *rl,
                     made; leave new_spill_reg_store alone.  */
                  ;
                else if (s >= 0
-                        && SET_SRC (set) == rl->reg_rtx
+                        && SET_SRC (set) == rl_reg_rtx
                         && SET_DEST (set) == rld[s].reg_rtx)
                  {
                    /* Usually the next instruction will be the
@@ -7105,7 +7538,7 @@ emit_output_reload_insns (struct insn_chain *chain, struct reload *rl,
                      }
                  }
                else
-                 new_spill_reg_store[REGNO (rl->reg_rtx)] = p;
+                 new_spill_reg_store[REGNO (rl_reg_rtx)] = p;
              }
          }
       }
@@ -7119,7 +7552,7 @@ emit_output_reload_insns (struct insn_chain *chain, struct reload *rl,
     output_reload_insns[rl->opnum] = get_insns ();
 
   if (flag_non_call_exceptions)
-    copy_eh_notes (insn, get_insns ());
+    copy_reg_eh_region_note_forward (insn, get_insns (), NULL);
 
   end_sequence ();
 }
@@ -7132,13 +7565,62 @@ do_input_reload (struct insn_chain *chain, struct reload *rl, int j)
   rtx insn = chain->insn;
   rtx old = (rl->in && MEM_P (rl->in)
             ? rl->in_reg : rl->in);
+  rtx reg_rtx = rl->reg_rtx;
+
+  if (old && reg_rtx)
+    {
+      enum machine_mode mode;
+
+      /* Determine the mode to reload in.
+        This is very tricky because we have three to choose from.
+        There is the mode the insn operand wants (rl->inmode).
+        There is the mode of the reload register RELOADREG.
+        There is the intrinsic mode of the operand, which we could find
+        by stripping some SUBREGs.
+        It turns out that RELOADREG's mode is irrelevant:
+        we can change that arbitrarily.
+
+        Consider (SUBREG:SI foo:QI) as an operand that must be SImode;
+        then the reload reg may not support QImode moves, so use SImode.
+        If foo is in memory due to spilling a pseudo reg, this is safe,
+        because the QImode value is in the least significant part of a
+        slot big enough for a SImode.  If foo is some other sort of
+        memory reference, then it is impossible to reload this case,
+        so previous passes had better make sure this never happens.
+
+        Then consider a one-word union which has SImode and one of its
+        members is a float, being fetched as (SUBREG:SF union:SI).
+        We must fetch that as SFmode because we could be loading into
+        a float-only register.  In this case OLD's mode is correct.
+
+        Consider an immediate integer: it has VOIDmode.  Here we need
+        to get a mode from something else.
+
+        In some cases, there is a fourth mode, the operand's
+        containing mode.  If the insn specifies a containing mode for
+        this operand, it overrides all others.
+
+        I am not sure whether the algorithm here is always right,
+        but it does the right things in those cases.  */
+
+      mode = GET_MODE (old);
+      if (mode == VOIDmode)
+       mode = rl->inmode;
+
+      /* We cannot use gen_lowpart_common since it can do the wrong thing
+        when REG_RTX has a multi-word mode.  Note that REG_RTX must
+        always be a REG here.  */
+      if (GET_MODE (reg_rtx) != mode)
+       reg_rtx = reload_adjust_reg_for_mode (reg_rtx, mode);
+    }
+  reload_reg_rtx_for_input[j] = reg_rtx;
 
   if (old != 0
       /* AUTO_INC reloads need to be handled even if inherited.  We got an
         AUTO_INC reload if reload_out is set but reload_out_reg isn't.  */
       && (! reload_inherited[j] || (rl->out && ! rl->out_reg))
-      && ! rtx_equal_p (rl->reg_rtx, old)
-      && rl->reg_rtx != 0)
+      && ! rtx_equal_p (reg_rtx, old)
+      && reg_rtx != 0)
     emit_input_reload_insns (chain, rld + j, old, j);
 
   /* When inheriting a wider reload, we have a MEM in rl->in,
@@ -7156,29 +7638,22 @@ do_input_reload (struct insn_chain *chain, struct reload *rl, int j)
      actually no need to store the old value in it.  */
 
   if (optimize
-      /* Only attempt this for input reloads; for RELOAD_OTHER we miss
-        that there may be multiple uses of the previous output reload.
-        Restricting to RELOAD_FOR_INPUT is mostly paranoia.  */
-      && rl->when_needed == RELOAD_FOR_INPUT
       && (reload_inherited[j] || reload_override_in[j])
-      && rl->reg_rtx
-      && REG_P (rl->reg_rtx)
-      && spill_reg_store[REGNO (rl->reg_rtx)] != 0
+      && reg_rtx
+      && REG_P (reg_rtx)
+      && spill_reg_store[REGNO (reg_rtx)] != 0
 #if 0
       /* There doesn't seem to be any reason to restrict this to pseudos
         and doing so loses in the case where we are copying from a
         register of the wrong class.  */
-      && (REGNO (spill_reg_stored_to[REGNO (rl->reg_rtx)])
-         >= FIRST_PSEUDO_REGISTER)
+      && !HARD_REGISTER_P (spill_reg_stored_to[REGNO (reg_rtx)])
 #endif
       /* The insn might have already some references to stackslots
         replaced by MEMs, while reload_out_reg still names the
         original pseudo.  */
-      && (dead_or_set_p (insn,
-                        spill_reg_stored_to[REGNO (rl->reg_rtx)])
-         || rtx_equal_p (spill_reg_stored_to[REGNO (rl->reg_rtx)],
-                         rl->out_reg)))
-    delete_output_reload (insn, j, REGNO (rl->reg_rtx));
+      && (dead_or_set_p (insn, spill_reg_stored_to[REGNO (reg_rtx)])
+         || rtx_equal_p (spill_reg_stored_to[REGNO (reg_rtx)], rl->out_reg)))
+    delete_output_reload (insn, j, REGNO (reg_rtx), reg_rtx);
 }
 
 /* Do output reloading for reload RL, which is for the insn described by
@@ -7194,6 +7669,30 @@ do_output_reload (struct insn_chain *chain, struct reload *rl, int j)
      not loaded in this same reload, see if we can eliminate a previous
      store.  */
   rtx pseudo = rl->out_reg;
+  rtx reg_rtx = rl->reg_rtx;
+
+  if (rl->out && reg_rtx)
+    {
+      enum machine_mode mode;
+
+      /* Determine the mode to reload in.
+        See comments above (for input reloading).  */
+      mode = GET_MODE (rl->out);
+      if (mode == VOIDmode)
+       {
+         /* VOIDmode should never happen for an output.  */
+         if (asm_noperands (PATTERN (insn)) < 0)
+           /* It's the compiler's fault.  */
+           fatal_insn ("VOIDmode on an output", insn);
+         error_for_asm (insn, "output operand is constant in %<asm%>");
+         /* Prevent crash--use something we know is valid.  */
+         mode = word_mode;
+         rl->out = gen_rtx_REG (mode, REGNO (reg_rtx));
+       }
+      if (GET_MODE (reg_rtx) != mode)
+       reg_rtx = reload_adjust_reg_for_mode (reg_rtx, mode);
+    }
+  reload_reg_rtx_for_output[j] = reg_rtx;
 
   if (pseudo
       && optimize
@@ -7212,13 +7711,13 @@ do_output_reload (struct insn_chain *chain, struct reload *rl, int j)
          && reg_reloaded_contents[last_regno] == pseudo_no
          && spill_reg_store[last_regno]
          && rtx_equal_p (pseudo, spill_reg_stored_to[last_regno]))
-       delete_output_reload (insn, j, last_regno);
+       delete_output_reload (insn, j, last_regno, reg_rtx);
     }
 
   old = rl->out_reg;
   if (old == 0
-      || rl->reg_rtx == old
-      || rl->reg_rtx == 0)
+      || reg_rtx == 0
+      || rtx_equal_p (old, reg_rtx))
     return;
 
   /* An output operand that dies right away does need a reload,
@@ -7227,7 +7726,7 @@ do_output_reload (struct insn_chain *chain, struct reload *rl, int j)
   if ((REG_P (old) || GET_CODE (old) == SCRATCH)
       && (note = find_reg_note (insn, REG_UNUSED, old)) != 0)
     {
-      XEXP (note, 0) = rl->reg_rtx;
+      XEXP (note, 0) = reg_rtx;
       return;
     }
   /* Likewise for a SUBREG of an operand that dies.  */
@@ -7236,8 +7735,7 @@ do_output_reload (struct insn_chain *chain, struct reload *rl, int j)
           && 0 != (note = find_reg_note (insn, REG_UNUSED,
                                          SUBREG_REG (old))))
     {
-      XEXP (note, 0) = gen_lowpart_common (GET_MODE (old),
-                                          rl->reg_rtx);
+      XEXP (note, 0) = gen_lowpart_common (GET_MODE (old), reg_rtx);
       return;
     }
   else if (GET_CODE (old) == SCRATCH)
@@ -7251,22 +7749,20 @@ do_output_reload (struct insn_chain *chain, struct reload *rl, int j)
   emit_output_reload_insns (chain, rld + j, j);
 }
 
-/* Reload number R reloads from or to a group of hard registers starting at
-   register REGNO.  Return true if it can be treated for inheritance purposes
-   like a group of reloads, each one reloading a single hard register.
-   The caller has already checked that the spill register and REGNO use
-   the same number of registers to store the reload value.  */
+/* A reload copies values of MODE from register SRC to register DEST.
+   Return true if it can be treated for inheritance purposes like a
+   group of reloads, each one reloading a single hard register.  The
+   caller has already checked that (reg:MODE SRC) and (reg:MODE DEST)
+   occupy the same number of hard registers.  */
 
 static bool
-inherit_piecemeal_p (int r ATTRIBUTE_UNUSED, int regno ATTRIBUTE_UNUSED)
+inherit_piecemeal_p (int dest ATTRIBUTE_UNUSED,
+                    int src ATTRIBUTE_UNUSED,
+                    enum machine_mode mode ATTRIBUTE_UNUSED)
 {
 #ifdef CANNOT_CHANGE_MODE_CLASS
-  return (!REG_CANNOT_CHANGE_MODE_P (reload_spill_index[r],
-                                    GET_MODE (rld[r].reg_rtx),
-                                    reg_raw_mode[reload_spill_index[r]])
-         && !REG_CANNOT_CHANGE_MODE_P (regno,
-                                       GET_MODE (rld[r].reg_rtx),
-                                       reg_raw_mode[regno]));
+  return (!REG_CANNOT_CHANGE_MODE_P (dest, mode, reg_raw_mode[dest])
+         && !REG_CANNOT_CHANGE_MODE_P (src, mode, reg_raw_mode[src]));
 #else
   return true;
 #endif
@@ -7308,9 +7804,13 @@ emit_reload_insns (struct insn_chain *chain)
 
   for (j = 0; j < n_reloads; j++)
     {
-      if (rld[j].reg_rtx
-         && REGNO (rld[j].reg_rtx) < FIRST_PSEUDO_REGISTER)
-       new_spill_reg_store[REGNO (rld[j].reg_rtx)] = 0;
+      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);
@@ -7409,104 +7909,108 @@ emit_reload_insns (struct insn_chain *chain)
        {
          int nr = hard_regno_nregs[i][GET_MODE (rld[r].reg_rtx)];
          int k;
-         int part_reaches_end = 0;
-         int all_reaches_end = 1;
 
          /* 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))
-               part_reaches_end = 1;
-             else
-               all_reaches_end = 0;
-           }
+           if (reload_reg_reaches_end_p (i + k, rld[r].opnum,
+                                         rld[r].when_needed))
+             CLEAR_HARD_REG_BIT (reg_reloaded_valid, i + k);
 
-         /* Ignore reloads that don't reach the end of the insn in
-            entirety.  */
-         if (all_reaches_end)
-           {
-             /* First, clear out memory of what used to be in this spill reg.
-                If consecutive registers are used, clear them all.  */
-
-             for (k = 0; k < nr; k++)
-               {
-               CLEAR_HARD_REG_BIT (reg_reloaded_valid, i + k);
-                 CLEAR_HARD_REG_BIT (reg_reloaded_call_part_clobbered, i + k);
-               }
-
-             /* Maybe the spill reg contains a copy of reload_out.  */
-             if (rld[r].out != 0
-                 && (REG_P (rld[r].out)
+         /* 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
+                 || ! rld[r].out_reg
 #endif
-                     || REG_P (rld[r].out_reg)))
+                 || REG_P (rld[r].out_reg)))
+           {
+             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))
                {
                  rtx out = (REG_P (rld[r].out)
                             ? rld[r].out
                             : rld[r].out_reg
                             ? rld[r].out_reg
 /* AUTO_INC */              : XEXP (rld[r].in_reg, 0));
-                 int nregno = REGNO (out);
-                 int nnr = (nregno >= FIRST_PSEUDO_REGISTER ? 1
-                            : hard_regno_nregs[nregno]
-                                              [GET_MODE (rld[r].reg_rtx)]);
+                 int out_regno = REGNO (out);
+                 int out_nregs = (!HARD_REGISTER_NUM_P (out_regno) ? 1
+                                  : hard_regno_nregs[out_regno][mode]);
                  bool piecemeal;
 
-                 spill_reg_store[i] = new_spill_reg_store[i];
-                 spill_reg_stored_to[i] = out;
-                 reg_last_reload_reg[nregno] = rld[r].reg_rtx;
+                 spill_reg_store[regno] = new_spill_reg_store[regno];
+                 spill_reg_stored_to[regno] = out;
+                 reg_last_reload_reg[out_regno] = reg;
 
-                 piecemeal = (nregno < FIRST_PSEUDO_REGISTER
-                              && nr == nnr
-                              && inherit_piecemeal_p (r, nregno));
+                 piecemeal = (HARD_REGISTER_NUM_P (out_regno)
+                              && nregs == out_nregs
+                              && inherit_piecemeal_p (out_regno, regno, mode));
 
-                 /* If NREGNO is a hard register, it may occupy more than
+                 /* If OUT_REGNO is a hard register, it may occupy more than
                     one register.  If it does, say what is in the
                     rest of the registers assuming that both registers
                     agree on how many words the object takes.  If not,
                     invalidate the subsequent registers.  */
 
-                 if (nregno < FIRST_PSEUDO_REGISTER)
-                   for (k = 1; k < nnr; k++)
-                     reg_last_reload_reg[nregno + k]
-                       = (piecemeal
-                          ? regno_reg_rtx[REGNO (rld[r].reg_rtx) + k]
-                          : 0);
+                 if (HARD_REGISTER_NUM_P (out_regno))
+                   for (k = 1; k < out_nregs; k++)
+                     reg_last_reload_reg[out_regno + k]
+                       = (piecemeal ? regno_reg_rtx[regno + k] : 0);
 
                  /* Now do the inverse operation.  */
-                 for (k = 0; k < nr; k++)
+                 for (k = 0; k < nregs; k++)
                    {
-                     CLEAR_HARD_REG_BIT (reg_reloaded_dead, i + k);
-                     reg_reloaded_contents[i + k]
-                       = (nregno >= FIRST_PSEUDO_REGISTER || !piecemeal
-                          ? nregno
-                          : nregno + k);
-                     reg_reloaded_insn[i + k] = insn;
-                     SET_HARD_REG_BIT (reg_reloaded_valid, i + k);
-                     if (HARD_REGNO_CALL_PART_CLOBBERED (i + k, GET_MODE (out)))
-                       SET_HARD_REG_BIT (reg_reloaded_call_part_clobbered, i + k);
+                     CLEAR_HARD_REG_BIT (reg_reloaded_dead, regno + k);
+                     reg_reloaded_contents[regno + k]
+                       = (!HARD_REGISTER_NUM_P (out_regno) || !piecemeal
+                          ? out_regno
+                          : out_regno + k);
+                     reg_reloaded_insn[regno + k] = insn;
+                     SET_HARD_REG_BIT (reg_reloaded_valid, regno + k);
+                     if (HARD_REGNO_CALL_PART_CLOBBERED (regno + k, mode))
+                       SET_HARD_REG_BIT (reg_reloaded_call_part_clobbered,
+                                         regno + k);
+                     else
+                       CLEAR_HARD_REG_BIT (reg_reloaded_call_part_clobbered,
+                                           regno + k);
                    }
                }
-
-             /* Maybe the spill reg contains a copy of reload_in.  Only do
-                something if there will not be an output reload for
-                the register being reloaded.  */
-             else if (rld[r].out_reg == 0
-                      && rld[r].in != 0
-                      && ((REG_P (rld[r].in)
-                           && REGNO (rld[r].in) >= FIRST_PSEUDO_REGISTER
-                           && !REGNO_REG_SET_P (&reg_has_output_reload,
-                                                REGNO (rld[r].in)))
-                          || (REG_P (rld[r].in_reg)
-                              && !REGNO_REG_SET_P (&reg_has_output_reload,
-                                                   REGNO (rld[r].in_reg))))
-                      && ! reg_set_p (rld[r].reg_rtx, PATTERN (insn)))
+           }
+         /* Maybe the spill reg contains a copy of reload_in.  Only do
+            something if there will not be an output reload for
+            the register being reloaded.  */
+         else if (rld[r].out_reg == 0
+                  && rld[r].in != 0
+                  && ((REG_P (rld[r].in)
+                       && !HARD_REGISTER_P (rld[r].in)
+                       && !REGNO_REG_SET_P (&reg_has_output_reload,
+                                            REGNO (rld[r].in)))
+                      || (REG_P (rld[r].in_reg)
+                          && !REGNO_REG_SET_P (&reg_has_output_reload,
+                                               REGNO (rld[r].in_reg))))
+                  && !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))
                {
-                 int nregno;
-                 int nnr;
+                 int in_regno;
+                 int in_nregs;
                  rtx in;
                  bool piecemeal;
 
@@ -7517,24 +8021,21 @@ emit_reload_insns (struct insn_chain *chain)
                    in = rld[r].in_reg;
                  else
                    in = XEXP (rld[r].in_reg, 0);
-                 nregno = REGNO (in);
+                 in_regno = REGNO (in);
 
-                 nnr = (nregno >= FIRST_PSEUDO_REGISTER ? 1
-                        : hard_regno_nregs[nregno]
-                                          [GET_MODE (rld[r].reg_rtx)]);
+                 in_nregs = (!HARD_REGISTER_NUM_P (in_regno) ? 1
+                             : hard_regno_nregs[in_regno][mode]);
 
-                 reg_last_reload_reg[nregno] = rld[r].reg_rtx;
+                 reg_last_reload_reg[in_regno] = reg;
 
-                 piecemeal = (nregno < FIRST_PSEUDO_REGISTER
-                              && nr == nnr
-                              && inherit_piecemeal_p (r, nregno));
+                 piecemeal = (HARD_REGISTER_NUM_P (in_regno)
+                              && nregs == in_nregs
+                              && inherit_piecemeal_p (regno, in_regno, mode));
 
-                 if (nregno < FIRST_PSEUDO_REGISTER)
-                   for (k = 1; k < nnr; k++)
-                     reg_last_reload_reg[nregno + k]
-                       = (piecemeal
-                          ? regno_reg_rtx[REGNO (rld[r].reg_rtx) + k]
-                          : 0);
+                 if (HARD_REGISTER_NUM_P (in_regno))
+                   for (k = 1; k < in_nregs; k++)
+                     reg_last_reload_reg[in_regno + k]
+                       = (piecemeal ? regno_reg_rtx[regno + k] : 0);
 
                  /* Unless we inherited this reload, show we haven't
                     recently done a store.
@@ -7542,33 +8043,26 @@ emit_reload_insns (struct insn_chain *chain)
                     also have to be discarded.  */
                  if (! reload_inherited[r]
                      || (rld[r].out && ! rld[r].out_reg))
-                   spill_reg_store[i] = 0;
+                   spill_reg_store[regno] = 0;
 
-                 for (k = 0; k < nr; k++)
+                 for (k = 0; k < nregs; k++)
                    {
-                     CLEAR_HARD_REG_BIT (reg_reloaded_dead, i + k);
-                     reg_reloaded_contents[i + k]
-                       = (nregno >= FIRST_PSEUDO_REGISTER || !piecemeal
-                          ? nregno
-                          : nregno + k);
-                     reg_reloaded_insn[i + k] = insn;
-                     SET_HARD_REG_BIT (reg_reloaded_valid, i + k);
-                     if (HARD_REGNO_CALL_PART_CLOBBERED (i + k, GET_MODE (in)))
-                       SET_HARD_REG_BIT (reg_reloaded_call_part_clobbered, i + k);
+                     CLEAR_HARD_REG_BIT (reg_reloaded_dead, regno + k);
+                     reg_reloaded_contents[regno + k]
+                       = (!HARD_REGISTER_NUM_P (in_regno) || !piecemeal
+                          ? in_regno
+                          : in_regno + k);
+                     reg_reloaded_insn[regno + k] = insn;
+                     SET_HARD_REG_BIT (reg_reloaded_valid, regno + k);
+                     if (HARD_REGNO_CALL_PART_CLOBBERED (regno + k, mode))
+                       SET_HARD_REG_BIT (reg_reloaded_call_part_clobbered,
+                                         regno + k);
+                     else
+                       CLEAR_HARD_REG_BIT (reg_reloaded_call_part_clobbered,
+                                           regno + k);
                    }
                }
            }
-
-         /* However, if part of the reload reaches the end, then we must
-            invalidate the old info for the part that survives to the end.  */
-         else if (part_reaches_end)
-           {
-             for (k = 0; k < nr; k++)
-               if (reload_reg_reaches_end_p (i + k,
-                                             rld[r].opnum,
-                                             rld[r].when_needed))
-                 CLEAR_HARD_REG_BIT (reg_reloaded_valid, i + k);
-           }
        }
 
       /* The following if-statement was #if 0'd in 1.34 (or before...).
@@ -7581,7 +8075,7 @@ emit_reload_insns (struct insn_chain *chain)
         it thinks only about the original insn.  So invalidate it here.
         Also do the same thing for RELOAD_OTHER constraints where the
         output is discarded.  */
-      if (i < 0 
+      if (i < 0
          && ((rld[r].out != 0
               && (REG_P (rld[r].out)
                   || (MEM_P (rld[r].out)
@@ -7591,7 +8085,8 @@ emit_reload_insns (struct insn_chain *chain)
        {
          rtx out = ((rld[r].out && REG_P (rld[r].out))
                     ? rld[r].out : rld[r].out_reg);
-         int nregno = REGNO (out);
+         int out_regno = REGNO (out);
+         enum machine_mode mode = GET_MODE (out);
 
          /* REG_RTX is now set or clobbered by the main instruction.
             As the comment above explains, forget_old_reloads_1 only
@@ -7609,16 +8104,16 @@ emit_reload_insns (struct insn_chain *chain)
          if (rld[r].reg_rtx && rld[r].reg_rtx != out)
            forget_old_reloads_1 (rld[r].reg_rtx, NULL_RTX, NULL);
 
-         if (nregno >= FIRST_PSEUDO_REGISTER)
+         if (!HARD_REGISTER_NUM_P (out_regno))
            {
              rtx src_reg, store_insn = NULL_RTX;
 
-             reg_last_reload_reg[nregno] = 0;
+             reg_last_reload_reg[out_regno] = 0;
 
              /* If we can find a hard register that is stored, record
                 the storing insn so that we may delete this insn with
                 delete_output_reload.  */
-             src_reg = rld[r].reg_rtx;
+             src_reg = reload_reg_rtx_for_output[r];
 
              /* If this is an optional reload, try to find the source reg
                 from an input reload.  */
@@ -7635,7 +8130,7 @@ emit_reload_insns (struct insn_chain *chain)
                        {
                          if (rld[k].in == src_reg)
                            {
-                             src_reg = rld[k].reg_rtx;
+                             src_reg = reload_reg_rtx_for_input[k];
                              break;
                            }
                        }
@@ -7646,47 +8141,54 @@ emit_reload_insns (struct insn_chain *chain)
              if (src_reg && REG_P (src_reg)
                  && REGNO (src_reg) < FIRST_PSEUDO_REGISTER)
                {
-                 int src_regno = REGNO (src_reg);
-                 int nr = hard_regno_nregs[src_regno][rld[r].mode];
+                 int src_regno, src_nregs, k;
+                 rtx note;
+
+                 gcc_assert (GET_MODE (src_reg) == mode);
+                 src_regno = REGNO (src_reg);
+                 src_nregs = hard_regno_nregs[src_regno][mode];
                  /* The place where to find a death note varies with
                     PRESERVE_DEATH_INFO_REGNO_P .  The condition is not
                     necessarily checked exactly in the code that moves
                     notes, so just check both locations.  */
-                 rtx note = find_regno_note (insn, REG_DEAD, src_regno);
+                 note = find_regno_note (insn, REG_DEAD, src_regno);
                  if (! note && store_insn)
                    note = find_regno_note (store_insn, REG_DEAD, src_regno);
-                 while (nr-- > 0)
+                 for (k = 0; k < src_nregs; k++)
                    {
-                     spill_reg_store[src_regno + nr] = store_insn;
-                     spill_reg_stored_to[src_regno + nr] = out;
-                     reg_reloaded_contents[src_regno + nr] = nregno;
-                     reg_reloaded_insn[src_regno + nr] = store_insn;
-                     CLEAR_HARD_REG_BIT (reg_reloaded_dead, src_regno + nr);
-                     SET_HARD_REG_BIT (reg_reloaded_valid, src_regno + nr);
-                     if (HARD_REGNO_CALL_PART_CLOBBERED (src_regno + nr, 
-                                                         GET_MODE (src_reg)))
-                       SET_HARD_REG_BIT (reg_reloaded_call_part_clobbered, 
-                                         src_regno + nr);
-                     SET_HARD_REG_BIT (reg_is_output_reload, src_regno + nr);
+                     spill_reg_store[src_regno + k] = store_insn;
+                     spill_reg_stored_to[src_regno + k] = out;
+                     reg_reloaded_contents[src_regno + k] = out_regno;
+                     reg_reloaded_insn[src_regno + k] = store_insn;
+                     CLEAR_HARD_REG_BIT (reg_reloaded_dead, src_regno + k);
+                     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,
+                                         src_regno + k);
+                     else
+                       CLEAR_HARD_REG_BIT (reg_reloaded_call_part_clobbered,
+                                           src_regno + k);
+                     SET_HARD_REG_BIT (reg_is_output_reload, src_regno + k);
                      if (note)
                        SET_HARD_REG_BIT (reg_reloaded_died, src_regno);
                      else
                        CLEAR_HARD_REG_BIT (reg_reloaded_died, src_regno);
                    }
-                 reg_last_reload_reg[nregno] = src_reg;
-                 /* We have to set reg_has_output_reload here, or else 
+                 reg_last_reload_reg[out_regno] = src_reg;
+                 /* We have to set reg_has_output_reload here, or else
                     forget_old_reloads_1 will clear reg_last_reload_reg
                     right away.  */
                  SET_REGNO_REG_SET (&reg_has_output_reload,
-                                    nregno);
+                                    out_regno);
                }
            }
          else
            {
-             int num_regs = hard_regno_nregs[nregno][GET_MODE (out)];
+             int k, out_nregs = hard_regno_nregs[out_regno][mode];
 
-             while (num_regs-- > 0)
-               reg_last_reload_reg[nregno + num_regs] = 0;
+             for (k = 0; k < out_nregs; k++)
+               reg_last_reload_reg[out_regno + k] = 0;
            }
        }
     }
@@ -7837,7 +8339,7 @@ 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) add_optab->handlers[(int) GET_MODE (out)].insn_code;
+      code = (int) optab_handler (add_optab, GET_MODE (out))->insn_code;
 
       if (CONSTANT_P (op1) || MEM_P (op1) || GET_CODE (op1) == SUBREG
          || (REG_P (op1)
@@ -7867,6 +8369,7 @@ gen_reload (rtx out, rtx in, int opnum, enum reload_type type)
       /* If that failed, copy the address register to the reload register.
         Then add the constant to the reload register.  */
 
+      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);
@@ -7874,9 +8377,11 @@ gen_reload (rtx out, rtx in, int opnum, enum reload_type type)
 
 #ifdef SECONDARY_MEMORY_NEEDED
   /* If we need a memory location to do the move, do it that way.  */
-  else if ((REG_P (in) || GET_CODE (in) == SUBREG)
+  else if ((REG_P (in)
+            || (GET_CODE (in) == SUBREG && REG_P (SUBREG_REG (in))))
           && reg_or_subregno (in) < FIRST_PSEUDO_REGISTER
-          && (REG_P (out) || GET_CODE (out) == SUBREG)
+          && (REG_P (out)
+              || (GET_CODE (out) == SUBREG && REG_P (SUBREG_REG (out))))
           && reg_or_subregno (out) < FIRST_PSEUDO_REGISTER
           && SECONDARY_MEMORY_NEEDED (REGNO_REG_CLASS (reg_or_subregno (in)),
                                       REGNO_REG_CLASS (reg_or_subregno (out)),
@@ -7939,7 +8444,7 @@ gen_reload (rtx out, rtx in, int opnum, enum reload_type type)
   else if (OBJECT_P (in) || GET_CODE (in) == SUBREG)
     {
       tem = emit_insn (gen_move_insn (out, in));
-      /* IN may contain a LABEL_REF, if so add a REG_LABEL note.  */
+      /* IN may contain a LABEL_REF, if so add a REG_LABEL_OPERAND note.  */
       mark_jump_label (in, tem, 0);
     }
 
@@ -7968,10 +8473,11 @@ gen_reload (rtx out, rtx in, int opnum, enum reload_type type)
    LAST_RELOAD_REG is the hard register number for which we want to delete
    the last output reload.
    J is the reload-number that originally used REG.  The caller has made
-   certain that reload J doesn't use REG any longer for input.  */
+   certain that reload J doesn't use REG any longer for input.
+   NEW_RELOAD_REG is reload register that reload J is using for REG.  */
 
 static void
-delete_output_reload (rtx insn, int j, int last_reload_reg)
+delete_output_reload (rtx insn, int j, int last_reload_reg, rtx new_reload_reg)
 {
   rtx output_reload_insn = spill_reg_store[last_reload_reg];
   rtx reg = spill_reg_stored_to[last_reload_reg];
@@ -8010,16 +8516,7 @@ delete_output_reload (rtx insn, int j, int last_reload_reg)
       if (rtx_equal_p (reg2, reg))
        {
          if (reload_inherited[k] || reload_override_in[k] || k == j)
-           {
-             n_inherited++;
-             reg2 = rld[k].out_reg;
-             if (! reg2)
-               continue;
-             while (GET_CODE (reg2) == SUBREG)
-               reg2 = XEXP (reg2, 0);
-             if (rtx_equal_p (reg2, reg))
-               n_inherited++;
-           }
+           n_inherited++;
          else
            return;
        }
@@ -8030,9 +8527,9 @@ delete_output_reload (rtx insn, int j, int last_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);
@@ -8084,7 +8581,7 @@ delete_output_reload (rtx insn, int j, int last_reload_reg)
   if (rld[j].out != rld[j].in
       && REG_N_DEATHS (REGNO (reg)) == 1
       && REG_N_SETS (REGNO (reg)) == 1
-      && REG_BASIC_BLOCK (REGNO (reg)) >= 0
+      && REG_BASIC_BLOCK (REGNO (reg)) >= NUM_FIXED_BLOCKS
       && find_regno_note (insn, REG_DEAD, REGNO (reg)))
     {
       rtx i2;
@@ -8132,8 +8629,11 @@ delete_output_reload (rtx insn, int j, int last_reload_reg)
        }
 
       /* For the debugging info, say the pseudo lives in this reload reg.  */
-      reg_renumber[REGNO (reg)] = REGNO (rld[j].reg_rtx);
-      alter_reg (REGNO (reg), -1);
+      reg_renumber[REGNO (reg)] = REGNO (new_reload_reg);
+      if (ira_conflicts_p)
+       /* Inform IRA about the change.  */
+       ira_mark_allocation_change (REGNO (reg));
+      alter_reg (REGNO (reg), -1, false);
     }
   else
     {
@@ -8166,8 +8666,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))
@@ -8392,7 +8892,7 @@ inc_for_reload (rtx reloadreg, rtx in, rtx value, int inc_amount)
 
       emit_insn (gen_add2_insn (reloadreg, inc));
       store = emit_insn (gen_move_insn (incloc, reloadreg));
-      if (GET_CODE (inc) == CONST_INT)
+      if (CONST_INT_P (inc))
        emit_insn (gen_add2_insn (reloadreg, GEN_INT (-INTVAL (inc))));
       else
        emit_insn (gen_sub2_insn (reloadreg, inc));
@@ -8411,8 +8911,7 @@ add_auto_inc_notes (rtx insn, rtx x)
 
   if (code == MEM && auto_inc_p (XEXP (x, 0)))
     {
-      REG_NOTES (insn)
-       = gen_rtx_EXPR_LIST (REG_INC, XEXP (XEXP (x, 0), 0), REG_NOTES (insn));
+      add_reg_note (insn, REG_INC, XEXP (XEXP (x, 0), 0));
       return;
     }
 
@@ -8429,23 +8928,6 @@ 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)))
-           REG_NOTES (x)
-             = gen_rtx_EXPR_LIST (REG_EH_REGION, XEXP (eh_note, 0),
-                                  REG_NOTES (x));
-       }
-    }
-}
-
 /* This is used by reload pass, that does emit some instructions after
    abnormal calls moving basic block end, but in fact it wants to emit
    them on the edge.  Looks for abnormal call edges, find backward the
@@ -8503,7 +8985,7 @@ fixup_abnormal_edges (void)
                  next = NEXT_INSN (insn);
                  if (INSN_P (insn))
                    {
-                     delete_insn (insn);
+                     delete_insn (insn);
 
                      /* Sometimes there's still the return value USE.
                         If it's placed after a trapping call (i.e. that
@@ -8521,12 +9003,14 @@ fixup_abnormal_edges (void)
                          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 
+            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
@@ -8541,6 +9025,7 @@ fixup_abnormal_edges (void)
       blocks = sbitmap_alloc (last_basic_block);
       sbitmap_ones (blocks);
       find_many_sub_basic_blocks (blocks);
+      sbitmap_free (blocks);
     }
 
   if (inserted)