OSDN Git Service

* gcc.dg/vect/vect-105.c: Prevent compiler from hoisting abort
[pf3gnuchains/gcc-fork.git] / gcc / reload1.c
index 51d3f4c..bbffad0 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
    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;
@@ -389,7 +393,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 +447,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);
@@ -498,9 +504,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);
 }
 
@@ -515,7 +522,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);
     }
@@ -546,11 +553,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 ((flag_ira && ira_conflicts_p) || reload_completed);
        }
       else
        add_to_hard_reg_set (to, PSEUDO_REGNO_MODE (regno), r);
@@ -633,7 +640,7 @@ has_nonexceptional_receiver (void)
     return true;
   
   /* First determine which blocks can reach exit via normal paths.  */
-  tos = worklist = xmalloc (sizeof (basic_block) * (n_basic_blocks + 1));
+  tos = worklist = XNEWVEC (basic_block, n_basic_blocks + 1);
 
   FOR_EACH_BB (bb)
     bb->flags &= ~BB_REACHABLE;
@@ -684,6 +691,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 +710,7 @@ static int failure;
 int
 reload (rtx first, int global)
 {
-  int i;
+  int i, n;
   rtx insn;
   struct elim_table *ep;
   basic_block bb;
@@ -710,7 +720,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.  */
@@ -883,12 +893,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 (flag_ira && 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
@@ -1002,7 +1021,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);
              }
          }
 
@@ -1031,12 +1050,17 @@ 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 (! flag_ira || ! 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 +1187,7 @@ reload (rtx first, int global)
      regs.  */
  failed:
 
+  CLEAR_REG_SET (&changed_allocation_pseudos);
   CLEAR_REG_SET (&spilled_pseudos);
   reload_in_progress = 0;
 
@@ -1219,9 +1244,8 @@ 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))
@@ -1274,9 +1298,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);
@@ -1304,9 +1326,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;
@@ -1336,6 +1358,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)
@@ -1503,10 +1527,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
@@ -1520,7 +1543,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;
@@ -1577,10 +1600,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 (flag_ira && 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)
@@ -1641,8 +1678,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;
 
@@ -1652,7 +1689,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;
 
@@ -1669,6 +1706,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
@@ -1679,7 +1720,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.  */
+      || (flag_ira && ira_conflicts_p && r < 0))
     return;
 
   SET_REGNO_REG_SET (&pseudos_counted, reg);
@@ -1687,10 +1731,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
@@ -1708,6 +1754,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
@@ -1750,18 +1798,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 ((flag_ira && 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.  */
@@ -1773,15 +1828,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++)
@@ -1795,7 +1852,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)
@@ -1814,6 +1875,38 @@ find_reg (struct insn_chain *chain, int order)
            }
          if (! ok)
            continue;
+
+         if (flag_ira && 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)
@@ -1861,6 +1954,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;
@@ -1922,7 +2016,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;
          }
@@ -1980,16 +2074,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)
        {
@@ -2030,7 +2124,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.  */
@@ -2056,7 +2150,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);
@@ -2064,6 +2158,17 @@ alter_reg (int i, int from_reg)
       unsigned int min_align = reg_max_ref_width[i] * BITS_PER_UNIT;
       int adjust = 0;
 
+      if (flag_ira && 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.
@@ -2072,24 +2177,35 @@ 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 && flag_ira && 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 && flag_ira && 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.  */
@@ -2099,6 +2215,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
        {
@@ -2123,27 +2240,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
@@ -2166,25 +2267,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;
@@ -2398,7 +2482,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;
@@ -2445,7 +2529,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;
 
@@ -2527,15 +2611,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 (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;
@@ -2592,18 +2676,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 = gen_rtx_EXPR_LIST (REG_NOTE_KIND (x), new_rtx, XEXP (x, 1));
            }
        }
 
@@ -2615,10 +2699,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;
 
@@ -2640,13 +2724,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;
 
@@ -2664,9 +2748,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:
@@ -2682,17 +2766,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
@@ -2708,9 +2792,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;
@@ -2726,9 +2810,9 @@ 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), 0, insn, false);
+      if (new_rtx != XEXP (x, 0))
+       return gen_rtx_USE (GET_MODE (x), new_rtx);
       return x;
 
     case CLOBBER:
@@ -2747,21 +2831,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);
@@ -2773,7 +2857,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;
            }
        }
     }
@@ -3216,7 +3300,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)),
@@ -3316,14 +3400,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);
        }
     }
 
@@ -3668,8 +3751,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)
@@ -3700,7 +3786,9 @@ elimination_target_reg_p (rtx x)
   return false;
 }
 
-/* Initialize the table of registers to eliminate.  */
+/* 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)
@@ -3711,20 +3799,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.  */
-                         || (cfun->calls_alloca
-                             && EXIT_IGNORE_STACK)
-                         || crtl->accesses_prior_frames
-                         || FRAME_POINTER_REQUIRED);
+    reg_eliminate = XCNEWVEC (struct elim_table, NUM_ELIMINABLE_REGS);
 
   num_eliminable = 0;
 
@@ -3736,7 +3811,10 @@ init_elim_table (void)
       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));
+          && ! (ep->to == STACK_POINTER_REGNUM
+                && frame_pointer_needed 
+                && (! SUPPORTS_STACK_ALIGNMENT
+                    || ! stack_realign_fp)));
     }
 #else
   reg_eliminate[0].from = reg_eliminate_1[0].from;
@@ -3827,18 +3905,22 @@ 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 (! flag_ira || ! 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 (flag_ira && 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)
@@ -3863,24 +3945,50 @@ 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++)
-       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)
-             CLEAR_REGNO_REG_SET (&spilled_pseudos, i);
-         }
+      if (! flag_ira || ! ira_conflicts_p)
+       {
+         /* 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++)
+           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)
+                 CLEAR_REGNO_REG_SET (&spilled_pseudos, i);
+             }
+       }
+      else
+       {
+         /* 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.  */
+         unsigned int n;
+
+         for (n = 0, i = FIRST_PSEUDO_REGISTER; i < (unsigned) max_regno; i++)
+           if (reg_old_renumber[i] != reg_renumber[i])
+             {
+               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.  */
@@ -3889,9 +3997,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 (! flag_ira || ! 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)
@@ -3900,20 +4013,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++)
     {
@@ -3921,7 +4032,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)
        {
@@ -4016,8 +4129,7 @@ fixup_eh_region_note (rtx insn, rtx prev, rtx next)
     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));
+       add_reg_note (i, REG_EH_REGION, XEXP (note, 0));
       }
 }
 
@@ -4053,6 +4165,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.  */
@@ -4251,9 +4366,7 @@ reload_as_needed (int live_known)
                        }
                      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.  */
@@ -4279,6 +4392,33 @@ 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_hard_regno;
+                     int in_regno = REGNO (XEXP (in_reg, 0));
+
+                     if (reg_last_reload_reg[in_regno] != NULL_RTX)
+                       {
+                         in_hard_regno = REGNO (reg_last_reload_reg[in_regno]);
+                         gcc_assert (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])
+                             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.  */
+                         if (x == old_next)
+                           forget_old_reloads_1 (XEXP (in_reg, 0),
+                                                 NULL_RTX, NULL);
+                       }
+                   }
                }
            }
          /* If a pseudo that got a hard register is auto-incremented,
@@ -4308,8 +4448,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);
        }
     }
 
@@ -4980,6 +5120,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.
 
@@ -5029,7 +5289,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
@@ -5493,7 +5754,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++;
@@ -5510,7 +5771,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
@@ -5540,7 +5801,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)))
@@ -5666,7 +5927,7 @@ choose_reload_regs (struct insn_chain *chain)
        {
          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;
@@ -5812,7 +6073,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;
 
@@ -5824,27 +6085,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
                              ))
@@ -5876,7 +6138,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
@@ -5958,7 +6220,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.  */
@@ -5975,7 +6237,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;
 
@@ -6016,7 +6278,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);
                    }
 
@@ -6102,6 +6364,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,
@@ -6154,9 +6417,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;
            }
@@ -6737,7 +7000,10 @@ 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 (flag_ira && ira_conflicts_p)
+                   /* Inform IRA about the change.  */
+                   ira_mark_allocation_change (REGNO (old));
+                 alter_reg (REGNO (old), -1, false);
                }
              special = 1;
            }
@@ -6837,7 +7103,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)
@@ -7027,7 +7293,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;
@@ -8022,9 +8288,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)),
@@ -8172,7 +8440,7 @@ delete_output_reload (rtx insn, int j, int last_reload_reg, rtx new_reload_reg)
     n_occurrences += count_occurrences (PATTERN (insn),
                                        eliminate_regs (substed, 0,
                                                        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);
@@ -8273,7 +8541,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 (flag_ira && ira_conflicts_p)
+       /* Inform IRA about the change.  */
+       ira_mark_allocation_change (REGNO (reg));
+      alter_reg (REGNO (reg), -1, false);
     }
   else
     {
@@ -8551,8 +8822,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;
     }
 
@@ -8579,9 +8849,7 @@ copy_eh_notes (rtx insn, rtx x)
       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));
+           add_reg_note (x, REG_EH_REGION, XEXP (eh_note, 0));
        }
     }
 }