OSDN Git Service

Changlog libcpp
[pf3gnuchains/gcc-fork.git] / gcc / reload1.c
index 9b81062..d5cd37c 100644 (file)
@@ -1,6 +1,6 @@
 /* Reload pseudo regs into hard regs for insns that require hard regs.
    Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
+   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
    Free Software Foundation, Inc.
 
 This file is part of GCC.
@@ -44,9 +44,10 @@ along with GCC; see the file COPYING3.  If not see
 #include "toplev.h"
 #include "except.h"
 #include "tree.h"
+#include "ira.h"
 #include "df.h"
 #include "target.h"
-#include "dse.h"
+#include "emit-rtl.h"
 
 /* This file contains the reload pass of the compiler, which is
    run after register allocation has been done.  It checks that
@@ -257,6 +258,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;
@@ -314,8 +318,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.  */
@@ -389,7 +394,7 @@ 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);
@@ -443,6 +448,8 @@ static rtx inc_for_reload (rtx, rtx, rtx, int);
 static void add_auto_inc_notes (rtx, rtx);
 #endif
 static void copy_eh_notes (rtx, rtx);
+static void substitute (rtx *, const_rtx, rtx);
+static bool gen_reload_chain_without_interm_reg_p (int, int);
 static int reloads_conflict (int, int);
 static rtx gen_reload (rtx, rtx, int, enum reload_type);
 static rtx emit_insn_if_valid_for_reload (rtx);
@@ -501,6 +508,7 @@ init_reload (void)
   reload_startobj = XOBNEWVAR (&reload_obstack, char, 0);
 
   INIT_REG_SET (&spilled_pseudos);
+  INIT_REG_SET (&changed_allocation_pseudos);
   INIT_REG_SET (&pseudos_counted);
 }
 
@@ -546,11 +554,11 @@ compute_use_by_pseudos (HARD_REG_SET *to, regset from)
 
       if (r < 0)
        {
-         /* reload_combine uses the information from
-            DF_LIVE_IN (BASIC_BLOCK), which might still
-            contain registers that have not actually been allocated
-            since they have an equivalence.  */
-         gcc_assert (reload_completed);
+         /* reload_combine uses the information from DF_LIVE_IN,
+            which might still contain registers that have not
+            actually been allocated since they have an
+            equivalence.  */
+         gcc_assert (ira_conflicts_p || reload_completed);
        }
       else
        add_to_hard_reg_set (to, PSEUDO_REGNO_MODE (regno), r);
@@ -684,6 +692,9 @@ static int something_needs_operands_changed;
 /* 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.
@@ -700,7 +711,7 @@ static int failure;
 int
 reload (rtx first, int global)
 {
-  int i;
+  int i, n;
   rtx insn;
   struct elim_table *ep;
   basic_block bb;
@@ -790,7 +801,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)))
@@ -883,12 +894,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
@@ -978,7 +998,8 @@ 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)))
@@ -1002,7 +1023,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);
              }
          }
 
@@ -1036,7 +1057,12 @@ reload (rtx first, int global)
 
       calculate_needs_all_insns (global);
 
-      CLEAR_REG_SET (&spilled_pseudos);
+      if (! ira_conflicts_p)
+       /* Don't do it for IRA.  We need this info because we don't
+          change live_throughout and dead_or_set for chains when IRA
+          is used.  */
+       CLEAR_REG_SET (&spilled_pseudos);
+
       did_spill = 0;
 
       something_changed = 0;
@@ -1163,6 +1189,7 @@ reload (rtx first, int global)
      regs.  */
  failed:
 
+  CLEAR_REG_SET (&changed_allocation_pseudos);
   CLEAR_REG_SET (&spilled_pseudos);
   reload_in_progress = 0;
 
@@ -1207,6 +1234,48 @@ 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;
+
+         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);
+             if (equiv == reg)
+               equiv = 0;
+           }
+         else if (reg && REG_P (reg) && (int)REGNO (reg) != i)
+           equiv = reg;
+
+         if (equiv)
+           for (use = DF_REG_USE_CHAIN (i); use;
+                use = DF_REF_NEXT_REG (use))
+             if (DEBUG_INSN_P (DF_REF_INSN (use)))
+               {
+                 rtx *loc = DF_REF_LOC (use);
+                 rtx x = *loc;
+
+                 if (x == reg)
+                   *loc = copy_rtx (equiv);
+                 else if (GET_CODE (x) == SUBREG
+                          && SUBREG_REG (x) == reg)
+                   *loc = simplify_gen_subreg (GET_MODE (x), equiv,
+                                               GET_MODE (reg),
+                                               SUBREG_BYTE (x));
+                 else
+                   gcc_unreachable ();
+               }
+       }
     }
 
   /* We must set reload_completed now since the cleanup_subreg_operands call
@@ -1301,9 +1370,9 @@ reload (rtx first, int global)
          }
       }
 
-  /* 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;
@@ -1333,6 +1402,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)
@@ -1573,10 +1644,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)
@@ -1665,6 +1750,10 @@ static int spill_cost[FIRST_PSEUDO_REGISTER];
    only the first hard reg for a multi-reg pseudo.  */
 static int spill_add_cost[FIRST_PSEUDO_REGISTER];
 
+/* Map of hard regno to pseudo regno currently occupying the hard
+   reg.  */
+static int hard_regno_to_pseudo_regno[FIRST_PSEUDO_REGISTER];
+
 /* Update the spill cost arrays, considering that pseudo REG is live.  */
 
 static void
@@ -1675,7 +1764,10 @@ count_pseudo (int reg)
   int nregs;
 
   if (REGNO_REG_SET_P (&pseudos_counted, reg)
-      || REGNO_REG_SET_P (&spilled_pseudos, reg))
+      || REGNO_REG_SET_P (&spilled_pseudos, reg)
+      /* Ignore spilled pseudo-registers which can be here only if IRA
+        is used.  */
+      || (ira_conflicts_p && r < 0))
     return;
 
   SET_REGNO_REG_SET (&pseudos_counted, reg);
@@ -1683,10 +1775,12 @@ count_pseudo (int reg)
   gcc_assert (r >= 0);
 
   spill_add_cost[r] += freq;
-
   nregs = hard_regno_nregs[r][PSEUDO_REGNO_MODE (reg)];
   while (nregs-- > 0)
-    spill_cost[r + nregs] += freq;
+    {
+      hard_regno_to_pseudo_regno[r + nregs] = reg;
+      spill_cost[r + nregs] += freq;
+    }
 }
 
 /* Calculate the SPILL_COST and SPILL_ADD_COST arrays and determine the
@@ -1704,6 +1798,8 @@ order_regs_for_reload (struct insn_chain *chain)
 
   memset (spill_cost, 0, sizeof spill_cost);
   memset (spill_add_cost, 0, sizeof spill_add_cost);
+  for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+    hard_regno_to_pseudo_regno[i] = -1;
 
   /* Count number of uses of each hard reg by pseudo regs allocated to it
      and then order them by decreasing use.  First exclude hard registers
@@ -1746,18 +1842,25 @@ static HARD_REG_SET used_spill_regs_local;
 static void
 count_spilled_pseudo (int spilled, int spilled_nregs, int reg)
 {
+  int freq = REG_FREQ (reg);
   int r = reg_renumber[reg];
   int nregs = hard_regno_nregs[r][PSEUDO_REGNO_MODE (reg)];
 
-  if (REGNO_REG_SET_P (&spilled_pseudos, reg)
+  /* Ignore spilled pseudo-registers which can be here only if IRA is
+     used.  */
+  if ((ira_conflicts_p && r < 0)
+      || REGNO_REG_SET_P (&spilled_pseudos, reg)
       || spilled + spilled_nregs <= r || r + nregs <= spilled)
     return;
 
   SET_REGNO_REG_SET (&spilled_pseudos, reg);
 
-  spill_add_cost[r] -= REG_FREQ (reg);
+  spill_add_cost[r] -= freq;
   while (nregs-- > 0)
-    spill_cost[r + nregs] -= REG_FREQ (reg);
+    {
+      hard_regno_to_pseudo_regno[r + nregs] = -1;
+      spill_cost[r + nregs] -= freq;
+    }
 }
 
 /* Find reload register to use for reload number ORDER.  */
@@ -1769,11 +1872,13 @@ find_reg (struct insn_chain *chain, int order)
   struct reload *rl = rld + rnum;
   int best_cost = INT_MAX;
   int best_reg = -1;
-  unsigned int i, j;
+  unsigned int i, j, n;
   int k;
   HARD_REG_SET not_usable;
   HARD_REG_SET used_by_other_reload;
   reg_set_iterator rsi;
+  static int regno_pseudo_regs[FIRST_PSEUDO_REGISTER];
+  static int best_regno_pseudo_regs[FIRST_PSEUDO_REGISTER];
 
   COPY_HARD_REG_SET (not_usable, bad_spill_regs);
   IOR_HARD_REG_SET (not_usable, bad_spill_regs_global);
@@ -1791,7 +1896,11 @@ find_reg (struct insn_chain *chain, int order)
 
   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
     {
+#ifdef REG_ALLOC_ORDER
+      unsigned int regno = reg_alloc_order[i];
+#else
       unsigned int regno = i;
+#endif
 
       if (! TEST_HARD_REG_BIT (not_usable, regno)
          && ! TEST_HARD_REG_BIT (used_by_other_reload, regno)
@@ -1810,6 +1919,38 @@ find_reg (struct insn_chain *chain, int order)
            }
          if (! ok)
            continue;
+
+         if (ira_conflicts_p)
+           {
+             /* Ask IRA to find a better pseudo-register for
+                spilling.  */
+             for (n = j = 0; j < this_nregs; j++)
+               {
+                 int r = hard_regno_to_pseudo_regno[regno + j];
+
+                 if (r < 0)
+                   continue;
+                 if (n == 0 || regno_pseudo_regs[n - 1] != r)
+                   regno_pseudo_regs[n++] = r;
+               }
+             regno_pseudo_regs[n++] = -1;
+             if (best_reg < 0
+                 || ira_better_spill_reload_regno_p (regno_pseudo_regs,
+                                                     best_regno_pseudo_regs,
+                                                     rl->in, rl->out,
+                                                     chain->insn))
+               {
+                 best_reg = regno;
+                 for (j = 0;; j++)
+                   {
+                     best_regno_pseudo_regs[j] = regno_pseudo_regs[j];
+                     if (regno_pseudo_regs[j] < 0)
+                       break;
+                   }
+               }
+             continue;
+           }
+
          if (rl->in && REG_P (rl->in) && REGNO (rl->in) == regno)
            this_cost--;
          if (rl->out && REG_P (rl->out) && REGNO (rl->out) == regno)
@@ -1857,6 +1998,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;
@@ -2026,7 +2168,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.  */
@@ -2052,7 +2194,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);
@@ -2060,6 +2202,17 @@ alter_reg (int i, int from_reg)
       unsigned int min_align = reg_max_ref_width[i] * BITS_PER_UNIT;
       int adjust = 0;
 
+      if (ira_conflicts_p)
+       {
+         /* Mark the spill for IRA.  */
+         SET_REGNO_REG_SET (&spilled_pseudos, i);
+         if (!dont_share_p)
+           x = ira_reuse_stack_slot (i, inherent_size, total_size);
+       }
+
+      if (x)
+       ;
+
       /* Each pseudo reg has an inherent size which comes from its own mode,
         and a total size which provides room for paradoxical subregs
         which refer to the pseudo reg in wider modes.
@@ -2068,24 +2221,34 @@ alter_reg (int i, int from_reg)
         enough inherent space and enough total space.
         Otherwise, we allocate a new slot, making sure that it has no less
         inherent space, and no less total space, then the previous slot.  */
-      if (from_reg == -1)
+      else if (from_reg == -1 || (!dont_share_p && ira_conflicts_p))
        {
-         alias_set_type alias_set = new_alias_set ();
+         rtx stack_slot;
 
          /* No known place to spill from => no slot to reuse.  */
          x = assign_stack_local (mode, total_size,
                                  min_align > inherent_align
                                  || total_size > inherent_size ? -1 : 0);
+
+         stack_slot = x;
+
+         /* Cancel the big-endian correction done in assign_stack_local.
+            Get the address of the beginning of the slot.  This is so we
+            can do a big-endian correction unconditionally below.  */
          if (BYTES_BIG_ENDIAN)
-           /* Cancel the  big-endian correction done in assign_stack_local.
-              Get the address of the beginning of the slot.
-              This is so we can do a big-endian correction unconditionally
-              below.  */
-           adjust = inherent_size - total_size;
-
-         /* Nothing can alias this slot except this pseudo.  */
-         set_mem_alias_set (x, alias_set);
-         dse_record_singleton_alias_set (alias_set, mode);
+           {
+             adjust = inherent_size - total_size;
+             if (adjust)
+               stack_slot
+                 = adjust_address_nv (x, mode_for_size (total_size
+                                                        * BITS_PER_UNIT,
+                                                        MODE_INT, 1),
+                                      adjust);
+           }
+
+         if (! dont_share_p && ira_conflicts_p)
+           /* Inform IRA about allocation a new stack slot.  */
+           ira_mark_new_stack_slot (stack_slot, i, total_size);
        }
 
       /* Reuse a stack slot if possible.  */
@@ -2095,6 +2258,7 @@ alter_reg (int i, int from_reg)
                   >= inherent_size)
               && MEM_ALIGN (spill_stack_slot[from_reg]) >= min_align)
        x = spill_stack_slot[from_reg];
+
       /* Allocate a bigger slot.  */
       else
        {
@@ -2119,27 +2283,11 @@ alter_reg (int i, int from_reg)
                                  || total_size > inherent_size ? -1 : 0);
          stack_slot = x;
 
-         /* All pseudos mapped to this slot can alias each other.  */
-         if (spill_stack_slot[from_reg])
-           {
-             alias_set_type alias_set 
-               = MEM_ALIAS_SET (spill_stack_slot[from_reg]);
-             set_mem_alias_set (x, alias_set);
-             dse_invalidate_singleton_alias_set (alias_set);
-           }
-         else
-           {
-             alias_set_type alias_set = new_alias_set ();
-             set_mem_alias_set (x, alias_set);
-             dse_record_singleton_alias_set (alias_set, mode);
-           }
-
+         /* Cancel the  big-endian correction done in assign_stack_local.
+            Get the address of the beginning of the slot.  This is so we
+            can do a big-endian correction unconditionally below.  */
          if (BYTES_BIG_ENDIAN)
            {
-             /* Cancel the  big-endian correction done in assign_stack_local.
-                Get the address of the beginning of the slot.
-                This is so we can do a big-endian correction unconditionally
-                below.  */
              adjust = GET_MODE_SIZE (mode) - total_size;
              if (adjust)
                stack_slot
@@ -2162,25 +2310,8 @@ 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;
@@ -2441,7 +2572,7 @@ eliminate_regs_1 (rtx x, enum machine_mode mem_mode, rtx insn,
          /* 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;
 
@@ -2478,7 +2609,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
@@ -2544,7 +2675,7 @@ 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)
@@ -2594,12 +2725,12 @@ eliminate_regs_1 (rtx x, enum machine_mode mem_mode, rtx insn,
              /* 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_rtx, XEXP (x, 1));
+             x = alloc_reg_note (REG_NOTE_KIND (x), new_rtx, XEXP (x, 1));
            }
        }
 
@@ -2722,7 +2853,7 @@ 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_rtx = eliminate_regs_1 (XEXP (x, 0), 0, insn, false);
+      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;
@@ -2956,15 +3087,15 @@ elimination_effects (rtx x, enum machine_mode mem_mode)
 
                if (GET_CODE (src) == PLUS
                    && XEXP (src, 0) == SET_DEST (x)
-                   && GET_CODE (XEXP (src, 1)) == CONST_INT)
+                   && CONST_INT_P (XEXP (src, 1)))
                  ep->offset -= INTVAL (XEXP (src, 1));
                else
                  ep->can_eliminate = 0;
              }
        }
 
-      elimination_effects (SET_DEST (x), 0);
-      elimination_effects (SET_SRC (x), 0);
+      elimination_effects (SET_DEST (x), VOIDmode);
+      elimination_effects (SET_SRC (x), VOIDmode);
       return;
 
     case MEM:
@@ -3062,7 +3193,8 @@ 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));
       return 0;
     }
 
@@ -3091,7 +3223,7 @@ eliminate_regs_in_insn (rtx insn, int replace)
                    rtx prev_insn, prev_set;
 
                    if (GET_CODE (base) == PLUS
-                       && GET_CODE (XEXP (base, 1)) == CONST_INT)
+                       && CONST_INT_P (XEXP (base, 1)))
                      {
                        offset += INTVAL (XEXP (base, 1));
                        base = XEXP (base, 0);
@@ -3166,7 +3298,7 @@ eliminate_regs_in_insn (rtx insn, int replace)
        plus_src = SET_SRC (old_set);
       /* First see if the source is of the form (plus (...) CST).  */
       if (plus_src
-         && GET_CODE (XEXP (plus_src, 1)) == CONST_INT)
+         && CONST_INT_P (XEXP (plus_src, 1)))
        plus_cst_src = plus_src;
       else if (REG_P (SET_SRC (old_set))
               || plus_src)
@@ -3179,7 +3311,7 @@ eliminate_regs_in_insn (rtx insn, int replace)
              if ((REG_NOTE_KIND (links) == REG_EQUAL
                   || REG_NOTE_KIND (links) == REG_EQUIV)
                  && GET_CODE (XEXP (links, 0)) == PLUS
-                 && GET_CODE (XEXP (XEXP (links, 0), 1)) == CONST_INT)
+                 && CONST_INT_P (XEXP (XEXP (links, 0), 1)))
                {
                  plus_cst_src = XEXP (links, 0);
                  break;
@@ -3212,7 +3344,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)),
@@ -3262,7 +3394,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.  */
@@ -3303,7 +3435,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])
@@ -3433,7 +3565,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;
 }
@@ -3491,7 +3623,7 @@ mark_not_eliminable (rtx dest, const_rtx x, void *data ATTRIBUTE_UNUSED)
        && (GET_CODE (x) != SET
            || GET_CODE (SET_SRC (x)) != PLUS
            || XEXP (SET_SRC (x), 0) != dest
-           || GET_CODE (XEXP (SET_SRC (x), 1)) != CONST_INT))
+           || !CONST_INT_P (XEXP (SET_SRC (x), 1))))
       {
        reg_eliminate[i].can_eliminate_previous
          = reg_eliminate[i].can_eliminate = 0;
@@ -3614,9 +3746,10 @@ update_eliminables (HARD_REG_SET *pset)
   struct elim_table *ep;
 
   for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
-    if ((ep->from == HARD_FRAME_POINTER_REGNUM && FRAME_POINTER_REQUIRED)
+    if ((ep->from == HARD_FRAME_POINTER_REGNUM 
+         && targetm.frame_pointer_required ())
 #ifdef ELIMINABLE_REGS
-       || ! CAN_ELIMINATE (ep->from, ep->to)
+       || ! targetm.can_eliminate (ep->from, ep->to)
 #endif
        )
       ep->can_eliminate = 0;
@@ -3722,7 +3855,7 @@ init_elim_table (void)
       ep->from = ep1->from;
       ep->to = ep1->to;
       ep->can_eliminate = ep->can_eliminate_previous
-       = (CAN_ELIMINATE (ep->from, ep->to)
+       = (targetm.can_eliminate (ep->from, ep->to)
           && ! (ep->to == STACK_POINTER_REGNUM
                 && frame_pointer_needed 
                 && (! SUPPORTS_STACK_ALIGNMENT
@@ -3817,22 +3950,28 @@ finish_spills (int global)
       spill_reg_order[i] = -1;
 
   EXECUTE_IF_SET_IN_REG_SET (&spilled_pseudos, FIRST_PSEUDO_REGISTER, i, rsi)
-    {
-      /* Record the current hard register the pseudo is allocated to in
-        pseudo_previous_regs so we avoid reallocating it to the same
-        hard reg in a later pass.  */
-      gcc_assert (reg_renumber[i] >= 0);
-
-      SET_HARD_REG_BIT (pseudo_previous_regs[i], reg_renumber[i]);
-      /* Mark it as no longer having a hard register home.  */
-      reg_renumber[i] = -1;
-      /* We will need to scan everything again.  */
-      something_changed = 1;
-    }
+    if (! ira_conflicts_p || reg_renumber[i] >= 0)
+      {
+       /* Record the current hard register the pseudo is allocated to
+          in pseudo_previous_regs so we avoid reallocating it to the
+          same hard reg in a later pass.  */
+       gcc_assert (reg_renumber[i] >= 0);
+       
+       SET_HARD_REG_BIT (pseudo_previous_regs[i], reg_renumber[i]);
+       /* Mark it as no longer having a hard register home.  */
+       reg_renumber[i] = -1;
+       if (ira_conflicts_p)
+         /* Inform IRA about the change.  */
+         ira_mark_allocation_change (i);
+       /* We will need to scan everything again.  */
+       something_changed = 1;
+      }
 
   /* Retry global register allocation if possible.  */
-  if (global)
+  if (global && ira_conflicts_p)
     {
+      unsigned int n;
+
       memset (pseudo_forbidden_regs, 0, max_regno * sizeof (HARD_REG_SET));
       /* For every insn that needs reloads, set the registers used as spill
         regs in pseudo_forbidden_regs for every pseudo live across the
@@ -3853,24 +3992,24 @@ finish_spills (int global)
            }
        }
 
-      /* Retry allocating the spilled pseudos.  For each reg, merge the
-        various reg sets that indicate which hard regs can't be used,
-        and call retry_global_alloc.
-        We change spill_pseudos here to only contain pseudos that did not
-        get a new hard register.  */
-      for (i = FIRST_PSEUDO_REGISTER; i < (unsigned)max_regno; i++)
+      /* Retry allocating the pseudos spilled in IRA and the
+        reload.  For each reg, merge the various reg sets that
+        indicate which hard regs can't be used, and call
+        ira_reassign_pseudos.  */
+      for (n = 0, i = FIRST_PSEUDO_REGISTER; i < (unsigned) max_regno; i++)
        if (reg_old_renumber[i] != reg_renumber[i])
          {
-           HARD_REG_SET forbidden;
-           COPY_HARD_REG_SET (forbidden, bad_spill_regs_global);
-           IOR_HARD_REG_SET (forbidden, pseudo_forbidden_regs[i]);
-           IOR_HARD_REG_SET (forbidden, pseudo_previous_regs[i]);
-           retry_global_alloc (i, forbidden);
-           if (reg_renumber[i] >= 0)
+           if (reg_renumber[i] < 0)
+             temp_pseudo_reg_arr[n++] = i;
+           else
              CLEAR_REGNO_REG_SET (&spilled_pseudos, i);
          }
+      if (ira_reassign_pseudos (temp_pseudo_reg_arr, n,
+                               bad_spill_regs_global,
+                               pseudo_forbidden_regs, pseudo_previous_regs,
+                               &spilled_pseudos))
+       something_changed = 1;
     }
-
   /* Fix up the register information in the insn chain.
      This involves deleting those of the spilled pseudos which did not get
      a new hard register home from the live_{before,after} sets.  */
@@ -3879,9 +4018,14 @@ finish_spills (int global)
       HARD_REG_SET used_by_pseudos;
       HARD_REG_SET used_by_pseudos2;
 
-      AND_COMPL_REG_SET (&chain->live_throughout, &spilled_pseudos);
-      AND_COMPL_REG_SET (&chain->dead_or_set, &spilled_pseudos);
-
+      if (! ira_conflicts_p)
+       {
+         /* Don't do it for IRA because IRA and the reload still can
+            assign hard registers to the spilled pseudos on next
+            reload iterations.  */
+         AND_COMPL_REG_SET (&chain->live_throughout, &spilled_pseudos);
+         AND_COMPL_REG_SET (&chain->dead_or_set, &spilled_pseudos);
+       }
       /* Mark any unallocated hard regs as available for spills.  That
         makes inheritance work somewhat better.  */
       if (chain->need_reload)
@@ -3890,20 +4034,18 @@ finish_spills (int global)
          REG_SET_TO_HARD_REG_SET (used_by_pseudos2, &chain->dead_or_set);
          IOR_HARD_REG_SET (used_by_pseudos, used_by_pseudos2);
 
-         /* Save the old value for the sanity test below.  */
-         COPY_HARD_REG_SET (used_by_pseudos2, chain->used_spill_regs);
-
          compute_use_by_pseudos (&used_by_pseudos, &chain->live_throughout);
          compute_use_by_pseudos (&used_by_pseudos, &chain->dead_or_set);
+         /* Value of chain->used_spill_regs from previous iteration
+            may be not included in the value calculated here because
+            of possible removing caller-saves insns (see function
+            delete_caller_save_insns.  */
          COMPL_HARD_REG_SET (chain->used_spill_regs, used_by_pseudos);
          AND_HARD_REG_SET (chain->used_spill_regs, used_spill_regs);
-
-         /* Make sure we only enlarge the set.  */
-         gcc_assert (hard_reg_set_subset_p (used_by_pseudos2,
-                                           chain->used_spill_regs));
        }
     }
 
+  CLEAR_REG_SET (&changed_allocation_pseudos);
   /* Let alter_reg modify the reg rtx's for the modified pseudos.  */
   for (i = FIRST_PSEUDO_REGISTER; i < (unsigned)max_regno; i++)
     {
@@ -3911,7 +4053,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)
        {
@@ -3988,26 +4132,17 @@ 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;
-    }
+  if (! may_trap_p (PATTERN (insn)))
+    remove_note (insn, note);
 
   for (i = NEXT_INSN (prev); i != next; i = NEXT_INSN (i))
     if (INSN_P (i) && i != insn && may_trap_p (PATTERN (i)))
-      {
-       trap_count++;
-       add_reg_note (i, REG_EH_REGION, XEXP (note, 0));
-      }
+      add_reg_note (i, REG_EH_REGION, XEXP (note, 0));
 }
 
 /* Reload pseudo-registers into hard regs around each insn as needed.
@@ -4042,6 +4177,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.  */
@@ -4210,31 +4348,30 @@ reload_as_needed (int live_known)
                            continue;
                          if (n == 1)
                            {
-                             n = validate_replace_rtx (reload_reg,
-                                                       gen_rtx_fmt_e (code,
-                                                                      mode,
-                                                                      reload_reg),
-                                                       p);
+                             rtx replace_reg
+                               = gen_rtx_fmt_e (code, mode, reload_reg);
+
+                             validate_replace_rtx_group (reload_reg,
+                                                         replace_reg, p);
+                             n = verify_changes (0);
 
                              /* We must also verify that the constraints
-                                are met after the replacement.  */
-                             extract_insn (p);
+                                are met after the replacement.  Make sure
+                                extract_insn is only called for an insn
+                                where the replacements were found to be
+                                valid so far. */
                              if (n)
-                               n = constrain_operands (1);
-                             else
-                               break;
-
-                             /* If the constraints were not met, then
-                                undo the replacement.  */
-                             if (!n)
                                {
-                                 validate_replace_rtx (gen_rtx_fmt_e (code,
-                                                                      mode,
-                                                                      reload_reg),
-                                                       reload_reg, p);
-                                 break;
+                                 extract_insn (p);
+                                 n = constrain_operands (1);
                                }
 
+                             /* If the constraints were not met, then
+                                undo the replacement, else confirm it.  */
+                             if (!n)
+                               cancel_changes (0);
+                             else
+                               confirm_change_group ();
                            }
                          break;
                        }
@@ -4266,6 +4403,43 @@ reload_as_needed (int live_known)
                      SET_REGNO_REG_SET (&reg_has_output_reload,
                                         REGNO (XEXP (in_reg, 0)));
                    }
+                 else if (code == PRE_INC || code == PRE_DEC
+                          || code == POST_INC || code == POST_DEC)
+                   {
+                     int in_regno = REGNO (XEXP (in_reg, 0));
+
+                     if (reg_last_reload_reg[in_regno] != NULL_RTX)
+                       {
+                         int in_hard_regno;
+                         bool forget_p = true;
+
+                         in_hard_regno = REGNO (reg_last_reload_reg[in_regno]);
+                         if (TEST_HARD_REG_BIT (reg_reloaded_valid,
+                                                in_hard_regno))
+                           {
+                             for (x = old_prev ? NEXT_INSN (old_prev) : insn;
+                                  x != old_next;
+                                  x = NEXT_INSN (x))
+                               if (x == reg_reloaded_insn[in_hard_regno])
+                                 {
+                                   forget_p = false;
+                                   break;
+                                 }
+                           }
+                         /* If for some reasons, we didn't set up
+                            reg_last_reload_reg in this insn,
+                            invalidate inheritance from previous
+                            insns for the incremented/decremented
+                            register.  Such registers will be not in
+                            reg_has_output_reload.  Invalidate it
+                            also if the corresponding element in
+                            reg_reloaded_insn is also
+                            invalidated.  */
+                         if (forget_p)
+                           forget_old_reloads_1 (XEXP (in_reg, 0),
+                                                 NULL_RTX, NULL);
+                       }
+                   }
                }
            }
          /* If a pseudo that got a hard register is auto-incremented,
@@ -4295,8 +4469,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);
        }
     }
 
@@ -4967,6 +5141,126 @@ reloads_unique_chain_p (int r1, int r2)
   return true;
 }
 
+
+/* The recursive function change all occurrences of WHAT in *WHERE
+   onto 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))
+    {
+      *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)
+{
+  bool result;
+  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 = copy_rtx (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);
+      return result;
+    }
+  
+  /* It looks like other cases in gen_reload are not possible for
+     chain reloads or do need an intermediate hard registers.  */
+  return true;
+}
+
 /* Return 1 if the reloads denoted by R1 and R2 cannot share a register.
    Return 0 otherwise.
 
@@ -5016,7 +5310,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
@@ -5811,9 +6106,10 @@ 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))
@@ -6089,6 +6385,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,
@@ -6687,7 +6984,7 @@ emit_input_reload_insns (struct insn_chain *chain, struct reload *rl,
                                rl->when_needed, old, rl->out, j, 0))
     {
       rtx temp = PREV_INSN (insn);
-      while (temp && NOTE_P (temp))
+      while (temp && (NOTE_P (temp) || DEBUG_INSN_P (temp)))
        temp = PREV_INSN (temp);
       if (temp
          && NONJUMP_INSN_P (temp)
@@ -6724,9 +7021,19 @@ emit_input_reload_insns (struct insn_chain *chain, struct reload *rl,
                  && REG_N_SETS (REGNO (old)) == 1)
                {
                  reg_renumber[REGNO (old)] = REGNO (reloadreg);
-                 alter_reg (REGNO (old), -1);
+                 if (ira_conflicts_p)
+                   /* Inform IRA about the change.  */
+                   ira_mark_allocation_change (REGNO (old));
+                 alter_reg (REGNO (old), -1, false);
                }
              special = 1;
+
+             /* Adjust any debug insns between temp and insn.  */
+             while ((temp = NEXT_INSN (temp)) != insn)
+               if (DEBUG_INSN_P (temp))
+                 replace_rtx (PATTERN (temp), old, reloadreg);
+               else
+                 gcc_assert (NOTE_P (temp));
            }
          else
            {
@@ -6832,10 +7139,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.  */
@@ -6851,9 +7165,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)
                {
@@ -6862,13 +7182,17 @@ emit_input_reload_insns (struct insn_chain *chain, struct reload *rl,
                  if (reload_adjust_reg_for_temp (&intermediate, NULL,
                                                  new_class, mode)
                      && reload_adjust_reg_for_icode (&third_reload_reg, NULL,
-                                                     sri2.icode))
+                                                     ((enum insn_code)
+                                                      sri2.icode)))
                    {
                      second_reload_reg = intermediate;
-                     tertiary_icode = sri2.icode;
+                     tertiary_icode = (enum insn_code) sri2.icode;
                    }
                  else
-                   oldequiv = old, real_oldequiv = real_old;
+                   {
+                     oldequiv = old;
+                     real_oldequiv = real_old;
+                   }
                }
              else if (new_t_class != NO_REGS && sri2.icode == CODE_FOR_nothing)
                {
@@ -6880,14 +7204,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;
+               }
            }
        }
 
@@ -8009,9 +8339,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)),
@@ -8157,9 +8489,9 @@ delete_output_reload (rtx insn, int j, int last_reload_reg, rtx new_reload_reg)
                                        reg, 0);
   if (substed)
     n_occurrences += count_occurrences (PATTERN (insn),
-                                       eliminate_regs (substed, 0,
+                                       eliminate_regs (substed, VOIDmode,
                                                        NULL_RTX), 0);
-  for (i1 = reg_equiv_alt_mem_list [REGNO (reg)]; i1; i1 = XEXP (i1, 1))
+  for (i1 = reg_equiv_alt_mem_list[REGNO (reg)]; i1; i1 = XEXP (i1, 1))
     {
       gcc_assert (!rtx_equal_p (XEXP (i1, 0), substed));
       n_occurrences += count_occurrences (PATTERN (insn), XEXP (i1, 0), 0);
@@ -8260,7 +8592,10 @@ delete_output_reload (rtx insn, int j, int last_reload_reg, rtx new_reload_reg)
 
       /* For the debugging info, say the pseudo lives in this reload reg.  */
       reg_renumber[REGNO (reg)] = REGNO (new_reload_reg);
-      alter_reg (REGNO (reg), -1);
+      if (ira_conflicts_p)
+       /* Inform IRA about the change.  */
+       ira_mark_allocation_change (REGNO (reg));
+      alter_reg (REGNO (reg), -1, false);
     }
   else
     {
@@ -8293,8 +8628,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))
@@ -8519,7 +8854,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));