OSDN Git Service

gcc/
[pf3gnuchains/gcc-fork.git] / gcc / reload1.c
index ac1e874..2f02ae3 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, 2008
+   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
    Free Software Foundation, Inc.
 
 This file is part of GCC.
@@ -26,7 +26,7 @@ along with GCC; see the file COPYING3.  If not see
 
 #include "machmode.h"
 #include "hard-reg-set.h"
-#include "rtl.h"
+#include "rtl-error.h"
 #include "tm_p.h"
 #include "obstack.h"
 #include "insn-config.h"
@@ -37,15 +37,13 @@ along with GCC; see the file COPYING3.  If not see
 #include "regs.h"
 #include "addresses.h"
 #include "basic-block.h"
+#include "df.h"
 #include "reload.h"
 #include "recog.h"
 #include "output.h"
-#include "real.h"
-#include "toplev.h"
 #include "except.h"
 #include "tree.h"
 #include "ira.h"
-#include "df.h"
 #include "target.h"
 #include "emit-rtl.h"
 
@@ -83,6 +81,14 @@ along with GCC; see the file COPYING3.  If not see
    fixing up each insn, and generating the new insns to copy values
    into the reload registers.  */
 \f
+struct target_reload default_target_reload;
+#if SWITCHABLE_TARGET
+struct target_reload *this_target_reload = &default_target_reload;
+#endif
+
+#define spill_indirect_levels                  \
+  (this_target_reload->x_spill_indirect_levels)
+
 /* During reload_as_needed, element N contains a REG rtx for the hard reg
    into which reg N has been reloaded (perhaps for a previous insn).  */
 static rtx *reg_last_reload_reg;
@@ -233,22 +239,6 @@ static HARD_REG_SET used_spill_regs;
    a round-robin fashion.  */
 static int last_spill_reg;
 
-/* Nonzero if indirect addressing is supported on the machine; this means
-   that spilling (REG n) does not require reloading it into a register in
-   order to do (MEM (REG n)) or (MEM (PLUS (REG n) (CONST_INT c))).  The
-   value indicates the level of indirect addressing supported, e.g., two
-   means that (MEM (MEM (REG n))) is also valid if (REG n) does not get
-   a hard register.  */
-static char spill_indirect_levels;
-
-/* Nonzero if indirect addressing is supported when the innermost MEM is
-   of the form (MEM (SYMBOL_REF sym)).  It is assumed that the level to
-   which these are valid is the same as spill_indirect_levels, above.  */
-char indirect_symref_ok;
-
-/* Nonzero if an address (plus (reg frame_pointer) (reg ...)) is valid.  */
-char double_reg_address_ok;
-
 /* Record the stack slot for each spilled hard register.  */
 static rtx spill_stack_slot[FIRST_PSEUDO_REGISTER];
 
@@ -277,12 +267,6 @@ int caller_save_needed;
    Required by some machines to handle any generated moves differently.  */
 int reload_in_progress = 0;
 
-/* These arrays record the insn_code of insns that may be needed to
-   perform input and output reloads of special objects.  They provide a
-   place to pass a scratch register.  */
-enum insn_code reload_in_optab[NUM_MACHINE_MODES];
-enum insn_code reload_out_optab[NUM_MACHINE_MODES];
-
 /* This obstack is used for allocation of rtl during register elimination.
    The allocated storage can be freed once find_reloads has processed the
    insn.  */
@@ -318,8 +302,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.  */
@@ -377,6 +362,21 @@ static int first_label_num;
 static char *offsets_known_at;
 static HOST_WIDE_INT (*offsets_at)[NUM_ELIMINABLE_REGS];
 
+/* Stack of addresses where an rtx has been changed.  We can undo the 
+   changes by popping items off the stack and restoring the original
+   value at each location. 
+
+   We use this simplistic undo capability rather than copy_rtx as copy_rtx
+   will not make a deep copy of a normally sharable rtx, such as
+   (const (plus (symbol_ref) (const_int))).  If such an expression appears
+   as R1 in gen_reload_chain_without_interm_reg_p, then a shared
+   rtx expression would be changed.  See PR 42431.  */
+
+typedef rtx *rtx_p;
+DEF_VEC_P(rtx_p);
+DEF_VEC_ALLOC_P(rtx_p,heap);
+static VEC(rtx_p,heap) *substitute_stack;
+
 /* Number of labels in the current function.  */
 
 static int num_labels;
@@ -397,6 +397,7 @@ static void alter_reg (int, int, bool);
 static void set_label_offsets (rtx, rtx, int);
 static void check_eliminable_occurrences (rtx);
 static void elimination_effects (rtx, enum machine_mode);
+static rtx eliminate_regs_1 (rtx, enum machine_mode, rtx, bool, bool);
 static int eliminate_regs_in_insn (rtx, int);
 static void update_eliminable_offsets (void);
 static void mark_not_eliminable (rtx, const_rtx, void *);
@@ -404,8 +405,11 @@ static void set_initial_elim_offsets (void);
 static bool verify_initial_elim_offsets (void);
 static void set_initial_label_offsets (void);
 static void set_offsets_for_label (rtx);
+static void init_eliminable_invariants (rtx, bool);
 static void init_elim_table (void);
+static void free_reg_equiv (void);
 static void update_eliminables (HARD_REG_SET *);
+static void elimination_costs_in_insn (rtx);
 static void spill_hard_reg (unsigned int, int);
 static int finish_spills (int);
 static void scan_paradoxical_subregs (rtx);
@@ -431,7 +435,6 @@ static void failed_reload (rtx, int);
 static int set_reload_reg (int, int);
 static void choose_reload_regs_init (struct insn_chain *, rtx *);
 static void choose_reload_regs (struct insn_chain *);
-static void merge_assigned_reloads (rtx);
 static void emit_input_reload_insns (struct insn_chain *, struct reload *,
                                     rtx, int);
 static void emit_output_reload_insns (struct insn_chain *, struct reload *,
@@ -446,7 +449,6 @@ static rtx inc_for_reload (rtx, rtx, rtx, int);
 #ifdef AUTO_INC_DEC
 static void add_auto_inc_notes (rtx, rtx);
 #endif
-static void copy_eh_notes (rtx, rtx);
 static void substitute (rtx *, const_rtx, rtx);
 static bool gen_reload_chain_without_interm_reg_p (int, int);
 static int reloads_conflict (int, int);
@@ -557,7 +559,7 @@ compute_use_by_pseudos (HARD_REG_SET *to, regset from)
             which might still contain registers that have not
             actually been allocated since they have an
             equivalence.  */
-         gcc_assert ((flag_ira && optimize) || reload_completed);
+         gcc_assert (ira_conflicts_p || reload_completed);
        }
       else
        add_to_hard_reg_set (to, PSEUDO_REGNO_MODE (regno), r);
@@ -586,7 +588,7 @@ replace_pseudos_in (rtx *loc, enum machine_mode mem_mode, rtx usage)
       if (regno < FIRST_PSEUDO_REGISTER)
        return;
 
-      x = eliminate_regs (x, mem_mode, usage);
+      x = eliminate_regs_1 (x, mem_mode, usage, true, false);
       if (x != *loc)
        {
          *loc = x;
@@ -596,6 +598,8 @@ replace_pseudos_in (rtx *loc, enum machine_mode mem_mode, rtx usage)
 
       if (reg_equiv_constant[regno])
        *loc = reg_equiv_constant[regno];
+      else if (reg_equiv_invariant[regno])
+       *loc = reg_equiv_invariant[regno];
       else if (reg_equiv_mem[regno])
        *loc = reg_equiv_mem[regno];
       else if (reg_equiv_address[regno])
@@ -638,7 +642,7 @@ has_nonexceptional_receiver (void)
   /* If we're not optimizing, then just err on the safe side.  */
   if (!optimize)
     return true;
-  
+
   /* First determine which blocks can reach exit via normal paths.  */
   tos = worklist = XNEWVEC (basic_block, n_basic_blocks + 1);
 
@@ -648,7 +652,7 @@ has_nonexceptional_receiver (void)
   /* Place the exit block on our worklist.  */
   EXIT_BLOCK_PTR->flags |= BB_REACHABLE;
   *tos++ = EXIT_BLOCK_PTR;
-  
+
   /* Iterate: find everything reachable from what we've already seen.  */
   while (tos != worklist)
     {
@@ -671,10 +675,8 @@ has_nonexceptional_receiver (void)
   /* Now see if there's a reachable block with an exceptional incoming
      edge.  */
   FOR_EACH_BB (bb)
-    if (bb->flags & BB_REACHABLE)
-      FOR_EACH_EDGE (e, ei, bb->preds)
-       if (e->flags & EDGE_ABNORMAL)
-         return true;
+    if (bb->flags & BB_REACHABLE && bb_has_abnormal_pred (bb))
+      return true;
 
   /* No exceptional block reached exit unexceptionally.  */
   return false;
@@ -683,10 +685,15 @@ has_nonexceptional_receiver (void)
 \f
 /* Global variables used by reload and its subroutines.  */
 
+/* The current basic block while in calculate_elim_costs_all_insns.  */
+static basic_block elim_bb;
+
 /* Set during calculate_needs if an insn needs register elimination.  */
 static int something_needs_elimination;
 /* Set during calculate_needs if an insn needs an operand changed.  */
 static int something_needs_operands_changed;
+/* Set by alter_regs if we spilled a register to the stack.  */
+static bool something_was_spilled;
 
 /* Nonzero means we couldn't get enough spill regs.  */
 static int failure;
@@ -761,22 +768,6 @@ reload (rtx first, int global)
       if (! call_used_regs[i] && ! fixed_regs[i] && ! LOCAL_REGNO (i))
        df_set_regs_ever_live (i, true);
 
-  /* Find all the pseudo registers that didn't get hard regs
-     but do have known equivalent constants or memory slots.
-     These include parameters (known equivalent to parameter slots)
-     and cse'd or loop-moved constant memory addresses.
-
-     Record constant equivalents in reg_equiv_constant
-     so they will be substituted by find_reloads.
-     Record memory equivalents in reg_mem_equiv so they can
-     be substituted eventually by altering the REG-rtx's.  */
-
-  reg_equiv_constant = XCNEWVEC (rtx, max_regno);
-  reg_equiv_invariant = XCNEWVEC (rtx, max_regno);
-  reg_equiv_mem = XCNEWVEC (rtx, max_regno);
-  reg_equiv_alt_mem_list = XCNEWVEC (rtx, max_regno);
-  reg_equiv_address = XCNEWVEC (rtx, max_regno);
-  reg_max_ref_width = XCNEWVEC (unsigned int, max_regno);
   reg_old_renumber = XCNEWVEC (short, max_regno);
   memcpy (reg_old_renumber, reg_renumber, max_regno * sizeof (short));
   pseudo_forbidden_regs = XNEWVEC (HARD_REG_SET, max_regno);
@@ -784,115 +775,9 @@ reload (rtx first, int global)
 
   CLEAR_HARD_REG_SET (bad_spill_regs_global);
 
-  /* Look for REG_EQUIV notes; record what each pseudo is equivalent
-     to.  Also find all paradoxical subregs and find largest such for
-     each pseudo.  */
-
-  num_eliminable_invariants = 0;
-  for (insn = first; insn; insn = NEXT_INSN (insn))
-    {
-      rtx set = single_set (insn);
-
-      /* We may introduce USEs that we want to remove at the end, so
-        we'll mark them with QImode.  Make sure there are no
-        previously-marked insns left by say regmove.  */
-      if (INSN_P (insn) && GET_CODE (PATTERN (insn)) == USE
-         && GET_MODE (insn) != VOIDmode)
-       PUT_MODE (insn, VOIDmode);
-
-      if (INSN_P (insn))
-       scan_paradoxical_subregs (PATTERN (insn));
-
-      if (set != 0 && REG_P (SET_DEST (set)))
-       {
-         rtx note = find_reg_note (insn, REG_EQUIV, NULL_RTX);
-         rtx x;
-
-         if (! note)
-           continue;
-
-         i = REGNO (SET_DEST (set));
-         x = XEXP (note, 0);
-
-         if (i <= LAST_VIRTUAL_REGISTER)
-           continue;
-
-         if (! function_invariant_p (x)
-             || ! flag_pic
-             /* A function invariant is often CONSTANT_P but may
-                include a register.  We promise to only pass
-                CONSTANT_P objects to LEGITIMATE_PIC_OPERAND_P.  */
-             || (CONSTANT_P (x)
-                 && LEGITIMATE_PIC_OPERAND_P (x)))
-           {
-             /* It can happen that a REG_EQUIV note contains a MEM
-                that is not a legitimate memory operand.  As later
-                stages of reload assume that all addresses found
-                in the reg_equiv_* arrays were originally legitimate,
-                we ignore such REG_EQUIV notes.  */
-             if (memory_operand (x, VOIDmode))
-               {
-                 /* Always unshare the equivalence, so we can
-                    substitute into this insn without touching the
-                      equivalence.  */
-                 reg_equiv_memory_loc[i] = copy_rtx (x);
-               }
-             else if (function_invariant_p (x))
-               {
-                 if (GET_CODE (x) == PLUS)
-                   {
-                     /* This is PLUS of frame pointer and a constant,
-                        and might be shared.  Unshare it.  */
-                     reg_equiv_invariant[i] = copy_rtx (x);
-                     num_eliminable_invariants++;
-                   }
-                 else if (x == frame_pointer_rtx || x == arg_pointer_rtx)
-                   {
-                     reg_equiv_invariant[i] = x;
-                     num_eliminable_invariants++;
-                   }
-                 else if (LEGITIMATE_CONSTANT_P (x))
-                   reg_equiv_constant[i] = x;
-                 else
-                   {
-                     reg_equiv_memory_loc[i]
-                       = force_const_mem (GET_MODE (SET_DEST (set)), x);
-                     if (! reg_equiv_memory_loc[i])
-                       reg_equiv_init[i] = NULL_RTX;
-                   }
-               }
-             else
-               {
-                 reg_equiv_init[i] = NULL_RTX;
-                 continue;
-               }
-           }
-         else
-           reg_equiv_init[i] = NULL_RTX;
-       }
-    }
-
-  if (dump_file)
-    for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
-      if (reg_equiv_init[i])
-       {
-         fprintf (dump_file, "init_insns for %u: ", i);
-         print_inline_rtx (dump_file, reg_equiv_init[i], 20);
-         fprintf (dump_file, "\n");
-       }
-
+  init_eliminable_invariants (first, true);
   init_elim_table ();
 
-  first_label_num = get_first_label_num ();
-  num_labels = max_label_num () - first_label_num;
-
-  /* Allocate the tables used to store offset information at labels.  */
-  /* We used to use alloca here, but the size of what it would try to
-     allocate would occasionally cause it to exceed the stack limit and
-     cause a core dump.  */
-  offsets_known_at = XNEWVEC (char, num_labels);
-  offsets_at = (HOST_WIDE_INT (*)[NUM_ELIMINABLE_REGS]) xmalloc (num_labels * NUM_ELIMINABLE_REGS * sizeof (HOST_WIDE_INT));
-
   /* 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.  */
@@ -900,8 +785,8 @@ reload (rtx first, int global)
   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 && optimize)
+
+  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);
@@ -946,7 +831,7 @@ reload (rtx first, int global)
        spill_hard_reg (from, 1);
     }
 
-#if HARD_FRAME_POINTER_REGNUM != FRAME_POINTER_REGNUM
+#if !HARD_FRAME_POINTER_IS_FRAME_POINTER
   if (frame_pointer_needed)
     spill_hard_reg (HARD_FRAME_POINTER_REGNUM, 1);
 #endif
@@ -966,6 +851,7 @@ reload (rtx first, int global)
       HOST_WIDE_INT starting_frame_size;
 
       starting_frame_size = get_frame_size ();
+      something_was_spilled = false;
 
       set_initial_elim_offsets ();
       set_initial_label_offsets ();
@@ -997,10 +883,12 @@ reload (rtx first, int global)
       for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
        if (reg_renumber[i] < 0 && reg_equiv_memory_loc[i])
          {
-           rtx x = eliminate_regs (reg_equiv_memory_loc[i], 0, NULL_RTX);
+           rtx x = eliminate_regs (reg_equiv_memory_loc[i], VOIDmode,
+                                   NULL_RTX);
 
-           if (strict_memory_address_p (GET_MODE (regno_reg_rtx[i]),
-                                        XEXP (x, 0)))
+           if (strict_memory_address_addr_space_p
+                 (GET_MODE (regno_reg_rtx[i]), XEXP (x, 0),
+                  MEM_ADDR_SPACE (x)))
              reg_equiv_mem[i] = x, reg_equiv_address[i] = 0;
            else if (CONSTANT_P (XEXP (x, 0))
                     || (REG_P (XEXP (x, 0))
@@ -1029,7 +917,7 @@ reload (rtx first, int global)
        setup_save_areas ();
 
       /* If we allocated another stack slot, redo elimination bookkeeping.  */
-      if (starting_frame_size != get_frame_size ())
+      if (something_was_spilled || starting_frame_size != get_frame_size ())
        continue;
       if (starting_frame_size && crtl->stack_alignment_needed)
        {
@@ -1055,7 +943,7 @@ reload (rtx first, int global)
 
       calculate_needs_all_insns (global);
 
-      if (! flag_ira || ! optimize)
+      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.  */
@@ -1067,11 +955,11 @@ reload (rtx first, int global)
 
       /* If we allocated any new memory locations, make another pass
         since it might have changed elimination offsets.  */
-      if (starting_frame_size != get_frame_size ())
+      if (something_was_spilled || starting_frame_size != get_frame_size ())
        something_changed = 1;
 
       /* Even if the frame size remained the same, we might still have
-        changed elimination offsets, e.g. if find_reloads called 
+        changed elimination offsets, e.g. if find_reloads called
         force_const_mem requiring the back end to allocate a constant
         pool base register that needs to be saved on the stack.  */
       else if (!verify_initial_elim_offsets ())
@@ -1182,7 +1070,7 @@ reload (rtx first, int global)
   if (! frame_pointer_needed)
     FOR_EACH_BB (bb)
       bitmap_clear_bit (df_get_live_in (bb), HARD_FRAME_POINTER_REGNUM);
-       
+
   /* Come here (with failure set nonzero) if we can't get enough spill
      regs.  */
  failed:
@@ -1232,6 +1120,52 @@ reload (rtx first, int global)
          else if (reg_equiv_mem[i])
            XEXP (reg_equiv_mem[i], 0) = addr;
        }
+
+      /* We don't want complex addressing modes in debug insns
+        if simpler ones will do, so delegitimize equivalences
+        in debug insns.  */
+      if (MAY_HAVE_DEBUG_INSNS && reg_renumber[i] < 0)
+       {
+         rtx reg = regno_reg_rtx[i];
+         rtx equiv = 0;
+         df_ref use, next;
+
+         if (reg_equiv_constant[i])
+           equiv = reg_equiv_constant[i];
+         else if (reg_equiv_invariant[i])
+           equiv = reg_equiv_invariant[i];
+         else if (reg && MEM_P (reg))
+           equiv = targetm.delegitimize_address (reg);
+         else if (reg && REG_P (reg) && (int)REGNO (reg) != i)
+           equiv = reg;
+
+         if (equiv == reg)
+           continue;
+
+         for (use = DF_REG_USE_CHAIN (i); use; use = next)
+           {
+             insn = DF_REF_INSN (use);
+
+             /* Make sure the next ref is for a different instruction,
+                so that we're not affected by the rescan.  */
+             next = DF_REF_NEXT_REG (use);
+             while (next && DF_REF_INSN (next) == insn)
+               next = DF_REF_NEXT_REG (next);
+
+             if (DEBUG_INSN_P (insn))
+               {
+                 if (!equiv)
+                   {
+                     INSN_VAR_LOCATION_LOC (insn) = gen_rtx_UNKNOWN_VAR_LOC ();
+                     df_insn_rescan_debug_internal (insn);
+                   }
+                 else
+                   INSN_VAR_LOCATION_LOC (insn)
+                     = simplify_replace_rtx (INSN_VAR_LOCATION_LOC (insn),
+                                             reg, equiv);
+               }
+           }
+       }
     }
 
   /* We must set reload_completed now since the cleanup_subreg_operands call
@@ -1348,31 +1282,11 @@ reload (rtx first, int global)
        }
     }
 
-  /* Indicate that we no longer have known memory locations or constants.  */
-  if (reg_equiv_constant)
-    free (reg_equiv_constant);
-  if (reg_equiv_invariant)
-    free (reg_equiv_invariant);
-  reg_equiv_constant = 0;
-  reg_equiv_invariant = 0;
-  VEC_free (rtx, gc, reg_equiv_memory_loc_vec);
-  reg_equiv_memory_loc = 0;
-
   free (temp_pseudo_reg_arr);
 
-  if (offsets_known_at)
-    free (offsets_known_at);
-  if (offsets_at)
-    free (offsets_at);
-
-  for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
-    if (reg_equiv_alt_mem_list[i])
-      free_EXPR_LIST_list (&reg_equiv_alt_mem_list[i]);
-  free (reg_equiv_alt_mem_list);
-
-  free (reg_equiv_mem);
+  /* Indicate that we no longer have known memory locations or constants.  */
+  free_reg_equiv ();
   reg_equiv_init = 0;
-  free (reg_equiv_address);
   free (reg_max_ref_width);
   free (reg_old_renumber);
   free (pseudo_previous_regs);
@@ -1400,6 +1314,10 @@ reload (rtx first, int global)
     REGNO_POINTER_ALIGN (HARD_FRAME_POINTER_REGNUM) = BITS_PER_UNIT;
 #endif
 
+  VEC_free (rtx_p, heap, substitute_stack);
+
+  gcc_assert (bitmap_empty_p (&spilled_pseudos));
+
   return failure;
 }
 
@@ -1614,7 +1532,7 @@ calculate_needs_all_insns (int global)
                                       reg_equiv_memory_loc
                                       [REGNO (SET_DEST (set))]))))
                {
-                 if (flag_ira && optimize)
+                 if (ira_conflicts_p)
                    /* Inform IRA about the insn deletion.  */
                    ira_mark_memory_move_deletion (REGNO (SET_DEST (set)),
                                                   REGNO (SET_SRC (set)));
@@ -1663,6 +1581,100 @@ calculate_needs_all_insns (int global)
   *pprev_reload = 0;
 }
 \f
+/* This function is called from the register allocator to set up estimates
+   for the cost of eliminating pseudos which have REG_EQUIV equivalences to
+   an invariant.  The structure is similar to calculate_needs_all_insns.  */
+
+void
+calculate_elim_costs_all_insns (void)
+{
+  int *reg_equiv_init_cost;
+  basic_block bb;
+  int i;
+
+  reg_equiv_init_cost = XCNEWVEC (int, max_regno);
+  init_elim_table ();
+  init_eliminable_invariants (get_insns (), false);
+
+  set_initial_elim_offsets ();
+  set_initial_label_offsets ();
+
+  FOR_EACH_BB (bb)
+    {
+      rtx insn;
+      elim_bb = bb;
+
+      FOR_BB_INSNS (bb, insn)
+       {
+         /* If this is a label, a JUMP_INSN, or has REG_NOTES (which might
+            include REG_LABEL_OPERAND and REG_LABEL_TARGET), we need to see
+            what effects this has on the known offsets at labels.  */
+
+         if (LABEL_P (insn) || JUMP_P (insn)
+             || (INSN_P (insn) && REG_NOTES (insn) != 0))
+           set_label_offsets (insn, insn, 0);
+
+         if (INSN_P (insn))
+           {
+             rtx set = single_set (insn);
+
+             /* Skip insns that only set an equivalence.  */
+             if (set && REG_P (SET_DEST (set))
+                 && reg_renumber[REGNO (SET_DEST (set))] < 0
+                 && (reg_equiv_constant[REGNO (SET_DEST (set))]
+                     || (reg_equiv_invariant[REGNO (SET_DEST (set))])))
+               {
+                 unsigned regno = REGNO (SET_DEST (set));
+                 rtx init = reg_equiv_init[regno];
+                 if (init)
+                   {
+                     rtx t = eliminate_regs_1 (SET_SRC (set), VOIDmode, insn,
+                                               false, true);
+                     int cost = rtx_cost (t, SET,
+                                          optimize_bb_for_speed_p (bb));
+                     int freq = REG_FREQ_FROM_BB (bb);
+
+                     reg_equiv_init_cost[regno] = cost * freq;
+                     continue;
+                   }
+               }
+             /* If needed, eliminate any eliminable registers.  */
+             if (num_eliminable || num_eliminable_invariants)
+               elimination_costs_in_insn (insn);
+
+             if (num_eliminable)
+               update_eliminable_offsets ();
+           }
+       }
+    }
+  for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
+    {
+      if (reg_equiv_invariant[i])
+       {
+         if (reg_equiv_init[i])
+           {
+             int cost = reg_equiv_init_cost[i];
+             if (dump_file)
+               fprintf (dump_file,
+                        "Reg %d has equivalence, initial gains %d\n", i, cost);
+             if (cost != 0)
+               ira_adjust_equiv_reg_cost (i, cost);
+           }
+         else
+           {
+             if (dump_file)
+               fprintf (dump_file,
+                        "Reg %d had equivalence, but can't be eliminated\n",
+                        i);
+             ira_adjust_equiv_reg_cost (i, 0);
+           }
+       }
+    }
+
+  free_reg_equiv ();
+  free (reg_equiv_init_cost);
+}
+\f
 /* Comparison function for qsort to decide which of two reloads
    should be handled first.  *P1 and *P2 are the reload numbers.  */
 
@@ -1723,7 +1735,7 @@ count_pseudo (int reg)
       || REGNO_REG_SET_P (&spilled_pseudos, reg)
       /* Ignore spilled pseudo-registers which can be here only if IRA
         is used.  */
-      || (flag_ira && optimize && r < 0))
+      || (ira_conflicts_p && r < 0))
     return;
 
   SET_REGNO_REG_SET (&pseudos_counted, reg);
@@ -1804,7 +1816,7 @@ count_spilled_pseudo (int spilled, int spilled_nregs, int reg)
 
   /* Ignore spilled pseudo-registers which can be here only if IRA is
      used.  */
-  if ((flag_ira && optimize && r < 0)
+  if ((ira_conflicts_p && r < 0)
       || REGNO_REG_SET_P (&spilled_pseudos, reg)
       || spilled + spilled_nregs <= r || r + nregs <= spilled)
     return;
@@ -1876,7 +1888,7 @@ find_reg (struct insn_chain *chain, int order)
          if (! ok)
            continue;
 
-         if (flag_ira && optimize)
+         if (ira_conflicts_p)
            {
              /* Ask IRA to find a better pseudo-register for
                 spilling.  */
@@ -2077,7 +2089,7 @@ static void
 spill_failure (rtx insn, enum reg_class rclass)
 {
   if (asm_noperands (PATTERN (insn)) >= 0)
-    error_for_asm (insn, "can't find a register in class %qs while "
+    error_for_asm (insn, "can%'t find a register in class %qs while "
                   "reloading %<asm%>",
                   reg_class_names[rclass]);
   else
@@ -2100,7 +2112,7 @@ spill_failure (rtx insn, enum reg_class rclass)
 static void
 delete_dead_insn (rtx insn)
 {
-  rtx prev = prev_real_insn (insn);
+  rtx prev = prev_active_insn (insn);
   rtx prev_dest;
 
   /* If the previous insn sets a register that dies in our insn, delete it
@@ -2158,7 +2170,9 @@ alter_reg (int i, int from_reg, bool dont_share_p)
       unsigned int min_align = reg_max_ref_width[i] * BITS_PER_UNIT;
       int adjust = 0;
 
-      if (flag_ira && optimize)
+      something_was_spilled = true;
+
+      if (ira_conflicts_p)
        {
          /* Mark the spill for IRA.  */
          SET_REGNO_REG_SET (&spilled_pseudos, i);
@@ -2177,7 +2191,7 @@ alter_reg (int i, int from_reg, bool dont_share_p)
         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.  */
-      else if (from_reg == -1 || (!dont_share_p && flag_ira && optimize))
+      else if (from_reg == -1 || (!dont_share_p && ira_conflicts_p))
        {
          rtx stack_slot;
 
@@ -2202,7 +2216,7 @@ alter_reg (int i, int from_reg, bool dont_share_p)
                                       adjust);
            }
 
-         if (! dont_share_p && flag_ira && optimize)
+         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);
        }
@@ -2449,6 +2463,36 @@ set_label_offsets (rtx x, rtx insn, int initial_p)
     }
 }
 \f
+/* Called through for_each_rtx, this function examines every reg that occurs
+   in PX and adjusts the costs for its elimination which are gathered by IRA.
+   DATA is the insn in which PX occurs.  We do not recurse into MEM
+   expressions.  */
+
+static int
+note_reg_elim_costly (rtx *px, void *data)
+{
+  rtx insn = (rtx)data;
+  rtx x = *px;
+
+  if (MEM_P (x))
+    return -1;
+
+  if (REG_P (x)
+      && REGNO (x) >= FIRST_PSEUDO_REGISTER
+      && reg_equiv_init[REGNO (x)]
+      && reg_equiv_invariant[REGNO (x)])
+    {
+      rtx t = reg_equiv_invariant[REGNO (x)];
+      rtx new_rtx = eliminate_regs_1 (t, Pmode, insn, true, true);
+      int cost = rtx_cost (new_rtx, SET, optimize_bb_for_speed_p (elim_bb));
+      int freq = REG_FREQ_FROM_BB (elim_bb);
+
+      if (cost != 0)
+       ira_adjust_equiv_reg_cost (REGNO (x), -cost * freq);
+    }
+  return 0;
+}
+
 /* Scan X and replace any eliminable registers (such as fp) with a
    replacement (such as sp), plus an offset.
 
@@ -2468,6 +2512,9 @@ set_label_offsets (rtx x, rtx insn, int initial_p)
    This means, do not set ref_outside_mem even if the reference
    is outside of MEMs.
 
+   If FOR_COSTS is true, we are being called before reload in order to
+   estimate the costs of keeping registers with an equivalence unallocated.
+
    REG_EQUIV_MEM and REG_EQUIV_ADDRESS contain address that have had
    replacements done assuming all offsets are at their initial values.  If
    they are not, or if REG_EQUIV_ADDRESS is nonzero for a pseudo we
@@ -2476,7 +2523,7 @@ set_label_offsets (rtx x, rtx insn, int initial_p)
 
 static rtx
 eliminate_regs_1 (rtx x, enum machine_mode mem_mode, rtx insn,
-                 bool may_use_invariant)
+                 bool may_use_invariant, bool for_costs)
 {
   enum rtx_code code = GET_CODE (x);
   struct elim_table *ep;
@@ -2522,13 +2569,14 @@ eliminate_regs_1 (rtx x, enum machine_mode mem_mode, rtx insn,
       else if (reg_renumber && reg_renumber[regno] < 0
               && reg_equiv_invariant && reg_equiv_invariant[regno])
        {
-         if (may_use_invariant)
+         if (may_use_invariant || (insn && DEBUG_INSN_P (insn)))
            return eliminate_regs_1 (copy_rtx (reg_equiv_invariant[regno]),
-                                    mem_mode, insn, true);
+                                    mem_mode, insn, true, for_costs);
          /* There exists at least one use of REGNO that cannot be
             eliminated.  Prevent the defining insn from being deleted.  */
          reg_equiv_init[regno] = NULL_RTX;
-         alter_reg (regno, -1, true);
+         if (!for_costs)
+           alter_reg (regno, -1, true);
        }
       return x;
 
@@ -2565,7 +2613,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
@@ -2589,8 +2637,10 @@ eliminate_regs_1 (rtx x, enum machine_mode mem_mode, rtx insn,
         operand of a load-address insn.  */
 
       {
-       rtx new0 = eliminate_regs_1 (XEXP (x, 0), mem_mode, insn, true);
-       rtx new1 = eliminate_regs_1 (XEXP (x, 1), mem_mode, insn, true);
+       rtx new0 = eliminate_regs_1 (XEXP (x, 0), mem_mode, insn, true,
+                                    for_costs);
+       rtx new1 = eliminate_regs_1 (XEXP (x, 1), mem_mode, insn, true,
+                                    for_costs);
 
        if (reg_renumber && (new0 != XEXP (x, 0) || new1 != XEXP (x, 1)))
          {
@@ -2610,7 +2660,7 @@ 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_rtx = form_sum (new0, new1);
+           new_rtx = form_sum (GET_MODE (x), new0, new1);
 
            /* As above, if we are not inside a MEM we do not want to
               turn a PLUS into something else.  We might try to do so here
@@ -2631,15 +2681,17 @@ eliminate_regs_1 (rtx x, enum machine_mode mem_mode, rtx insn,
         We ignore the possibility of overflow here.  */
       if (REG_P (XEXP (x, 0))
          && REGNO (XEXP (x, 0)) < FIRST_PSEUDO_REGISTER
-         && GET_CODE (XEXP (x, 1)) == CONST_INT)
+         && CONST_INT_P (XEXP (x, 1)))
        for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS];
             ep++)
          if (ep->from_rtx == XEXP (x, 0) && ep->can_eliminate)
            {
              if (! mem_mode
-                 /* Refs inside notes don't count for this purpose.  */
+                 /* Refs inside notes or in DEBUG_INSNs don't count for
+                    this purpose.  */
                  && ! (insn != 0 && (GET_CODE (insn) == EXPR_LIST
-                                     || GET_CODE (insn) == INSN_LIST)))
+                                     || GET_CODE (insn) == INSN_LIST
+                                     || DEBUG_INSN_P (insn))))
                ep->ref_outside_mem = 1;
 
              return
@@ -2662,9 +2714,11 @@ eliminate_regs_1 (rtx x, enum machine_mode mem_mode, rtx insn,
     case GE:       case GT:       case GEU:    case GTU:
     case LE:       case LT:       case LEU:    case LTU:
       {
-       rtx new0 = eliminate_regs_1 (XEXP (x, 0), mem_mode, insn, false);
+       rtx new0 = eliminate_regs_1 (XEXP (x, 0), mem_mode, insn, false,
+                                    for_costs);
        rtx new1 = XEXP (x, 1)
-                  ? eliminate_regs_1 (XEXP (x, 1), mem_mode, insn, false) : 0;
+         ? eliminate_regs_1 (XEXP (x, 1), mem_mode, insn, false,
+                             for_costs) : 0;
 
        if (new0 != XEXP (x, 0) || new1 != XEXP (x, 1))
          return gen_rtx_fmt_ee (code, GET_MODE (x), new0, new1);
@@ -2675,7 +2729,8 @@ eliminate_regs_1 (rtx x, enum machine_mode mem_mode, rtx insn,
       /* If we have something in XEXP (x, 0), the usual case, eliminate it.  */
       if (XEXP (x, 0))
        {
-         new_rtx = eliminate_regs_1 (XEXP (x, 0), mem_mode, insn, true);
+         new_rtx = eliminate_regs_1 (XEXP (x, 0), mem_mode, insn, true,
+                                     for_costs);
          if (new_rtx != XEXP (x, 0))
            {
              /* If this is a REG_DEAD note, it is not valid anymore.
@@ -2683,10 +2738,11 @@ eliminate_regs_1 (rtx x, enum machine_mode mem_mode, rtx insn,
                 REG_DEAD note for the stack or frame pointer.  */
              if (REG_NOTE_KIND (x) == REG_DEAD)
                return (XEXP (x, 1)
-                       ? eliminate_regs_1 (XEXP (x, 1), mem_mode, insn, true)
+                       ? eliminate_regs_1 (XEXP (x, 1), mem_mode, insn, true,
+                                           for_costs)
                        : NULL_RTX);
 
-             x = gen_rtx_EXPR_LIST (REG_NOTE_KIND (x), new_rtx, XEXP (x, 1));
+             x = alloc_reg_note (REG_NOTE_KIND (x), new_rtx, XEXP (x, 1));
            }
        }
 
@@ -2698,7 +2754,8 @@ eliminate_regs_1 (rtx x, enum machine_mode mem_mode, rtx insn,
         strictly needed, but it simplifies the code.  */
       if (XEXP (x, 1))
        {
-         new_rtx = eliminate_regs_1 (XEXP (x, 1), mem_mode, insn, true);
+         new_rtx = eliminate_regs_1 (XEXP (x, 1), mem_mode, insn, true,
+                                     for_costs);
          if (new_rtx != XEXP (x, 1))
            return
              gen_rtx_fmt_ee (GET_CODE (x), GET_MODE (x), XEXP (x, 0), new_rtx);
@@ -2724,7 +2781,7 @@ eliminate_regs_1 (rtx x, enum machine_mode mem_mode, rtx insn,
          && XEXP (XEXP (x, 1), 0) == XEXP (x, 0))
        {
          rtx new_rtx = eliminate_regs_1 (XEXP (XEXP (x, 1), 1), mem_mode,
-                                     insn, true);
+                                         insn, true, for_costs);
 
          if (new_rtx != XEXP (XEXP (x, 1), 1))
            return gen_rtx_fmt_ee (code, GET_MODE (x), XEXP (x, 0),
@@ -2747,7 +2804,8 @@ eliminate_regs_1 (rtx x, enum machine_mode mem_mode, rtx insn,
     case POPCOUNT:
     case PARITY:
     case BSWAP:
-      new_rtx = eliminate_regs_1 (XEXP (x, 0), mem_mode, insn, false);
+      new_rtx = eliminate_regs_1 (XEXP (x, 0), mem_mode, insn, false,
+                                 for_costs);
       if (new_rtx != XEXP (x, 0))
        return gen_rtx_fmt_e (code, GET_MODE (x), new_rtx);
       return x;
@@ -2768,7 +2826,8 @@ eliminate_regs_1 (rtx x, enum machine_mode mem_mode, rtx insn,
          new_rtx = SUBREG_REG (x);
        }
       else
-       new_rtx = eliminate_regs_1 (SUBREG_REG (x), mem_mode, insn, false);
+       new_rtx = eliminate_regs_1 (SUBREG_REG (x), mem_mode, insn, false,
+                                   for_costs);
 
       if (new_rtx != SUBREG_REG (x))
        {
@@ -2802,20 +2861,29 @@ eliminate_regs_1 (rtx x, enum machine_mode mem_mode, rtx insn,
       /* Our only special processing is to pass the mode of the MEM to our
         recursive call and copy the flags.  While we are here, handle this
         case more efficiently.  */
-      return
-       replace_equiv_address_nv (x,
-                                 eliminate_regs_1 (XEXP (x, 0), GET_MODE (x),
-                                                   insn, true));
+
+      new_rtx = eliminate_regs_1 (XEXP (x, 0), GET_MODE (x), insn, true,
+                                 for_costs);
+      if (for_costs
+         && memory_address_p (GET_MODE (x), XEXP (x, 0))
+         && !memory_address_p (GET_MODE (x), new_rtx))
+       for_each_rtx (&XEXP (x, 0), note_reg_elim_costly, insn);
+
+      return replace_equiv_address_nv (x, new_rtx);
 
     case USE:
       /* Handle insn_list USE that a call to a pure function may generate.  */
-      new_rtx = eliminate_regs_1 (XEXP (x, 0), 0, insn, false);
+      new_rtx = eliminate_regs_1 (XEXP (x, 0), VOIDmode, insn, false,
+                                 for_costs);
       if (new_rtx != XEXP (x, 0))
        return gen_rtx_USE (GET_MODE (x), new_rtx);
       return x;
 
     case CLOBBER:
     case ASM_OPERANDS:
+      gcc_assert (insn && DEBUG_INSN_P (insn));
+      break;
+
     case SET:
       gcc_unreachable ();
 
@@ -2830,7 +2898,8 @@ eliminate_regs_1 (rtx x, enum machine_mode mem_mode, rtx insn,
     {
       if (*fmt == 'e')
        {
-         new_rtx = eliminate_regs_1 (XEXP (x, i), mem_mode, insn, false);
+         new_rtx = eliminate_regs_1 (XEXP (x, i), mem_mode, insn, false,
+                                     for_costs);
          if (new_rtx != XEXP (x, i) && ! copied)
            {
              x = shallow_copy_rtx (x);
@@ -2843,7 +2912,8 @@ eliminate_regs_1 (rtx x, enum machine_mode mem_mode, rtx insn,
          int copied_vec = 0;
          for (j = 0; j < XVECLEN (x, i); j++)
            {
-             new_rtx = eliminate_regs_1 (XVECEXP (x, i, j), mem_mode, insn, false);
+             new_rtx = eliminate_regs_1 (XVECEXP (x, i, j), mem_mode, insn, false,
+                                         for_costs);
              if (new_rtx != XVECEXP (x, i, j) && ! copied_vec)
                {
                  rtvec new_v = gen_rtvec_v (XVECLEN (x, i),
@@ -2867,7 +2937,7 @@ eliminate_regs_1 (rtx x, enum machine_mode mem_mode, rtx insn,
 rtx
 eliminate_regs (rtx x, enum machine_mode mem_mode, rtx insn)
 {
-  return eliminate_regs_1 (x, mem_mode, insn, false);
+  return eliminate_regs_1 (x, mem_mode, insn, false, false);
 }
 
 /* Scan rtx X for modifications of elimination target registers.  Update
@@ -3043,15 +3113,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:
@@ -3149,7 +3219,11 @@ eliminate_regs_in_insn (rtx insn, int replace)
                  || GET_CODE (PATTERN (insn)) == CLOBBER
                  || GET_CODE (PATTERN (insn)) == ADDR_VEC
                  || GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC
-                 || GET_CODE (PATTERN (insn)) == ASM_INPUT);
+                 || GET_CODE (PATTERN (insn)) == ASM_INPUT
+                 || DEBUG_INSN_P (insn));
+      if (DEBUG_INSN_P (insn))
+       INSN_VAR_LOCATION_LOC (insn)
+         = eliminate_regs (INSN_VAR_LOCATION_LOC (insn), VOIDmode, insn);
       return 0;
     }
 
@@ -3160,7 +3234,7 @@ eliminate_regs_in_insn (rtx insn, int replace)
       for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
        if (ep->from_rtx == SET_DEST (old_set) && ep->can_eliminate)
          {
-#if HARD_FRAME_POINTER_REGNUM != FRAME_POINTER_REGNUM
+#if !HARD_FRAME_POINTER_IS_FRAME_POINTER
            /* If this is setting the frame pointer register to the
               hardware frame pointer register and this is an elimination
               that will be done (tested above), this insn is really
@@ -3178,7 +3252,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);
@@ -3253,7 +3327,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)
@@ -3266,7 +3340,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;
@@ -3326,7 +3400,7 @@ eliminate_regs_in_insn (rtx insn, int replace)
                /* First see if this insn remains valid when we make the
                   change.  If not, try to replace the whole pattern with
                   a simple set (this may help if the original insn was a
-                  PARALLEL that was only recognized as single_set due to 
+                  PARALLEL that was only recognized as single_set due to
                   REG_UNUSED notes).  If this isn't valid either, keep
                   the INSN_CODE the same and let reload fix it up.  */
                if (!validate_change (insn, &SET_SRC (old_set), new_src, 0))
@@ -3349,7 +3423,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.  */
@@ -3381,7 +3455,8 @@ eliminate_regs_in_insn (rtx insn, int replace)
          /* Companion to the above plus substitution, we can allow
             invariants as the source of a plain move.  */
          is_set_src = false;
-         if (old_set && recog_data.operand_loc[i] == &SET_SRC (old_set))
+         if (old_set
+             && recog_data.operand_loc[i] == &SET_SRC (old_set))
            is_set_src = true;
          in_plus = false;
          if (plus_src
@@ -3390,9 +3465,9 @@ eliminate_regs_in_insn (rtx insn, int replace)
            in_plus = true;
 
          substed_operand[i]
-           = eliminate_regs_1 (recog_data.operand[i], 0,
+           = eliminate_regs_1 (recog_data.operand[i], VOIDmode,
                                replace ? insn : NULL_RTX,
-                               is_set_src || in_plus);
+                               is_set_src || in_plus, false);
          if (substed_operand[i] != orig_operand[i])
            val = 1;
          /* Terminate the search in check_eliminable_occurrences at
@@ -3483,7 +3558,10 @@ eliminate_regs_in_insn (rtx insn, int replace)
     {
       /* Restore the old body.  */
       for (i = 0; i < recog_data.n_operands; i++)
-       *recog_data.operand_loc[i] = orig_operand[i];
+       /* Restoring a top-level match_parallel would clobber the new_body
+          we installed in the insn.  */
+       if (recog_data.operand_loc[i] != &PATTERN (insn))
+         *recog_data.operand_loc[i] = orig_operand[i];
       for (i = 0; i < recog_data.n_dups; i++)
        *recog_data.dup_loc[i] = orig_operand[(int) recog_data.dup_num[i]];
     }
@@ -3520,11 +3598,167 @@ eliminate_regs_in_insn (rtx insn, int replace)
      the pre-passes.  */
   if (val && REG_NOTES (insn) != 0)
     REG_NOTES (insn)
-      = eliminate_regs_1 (REG_NOTES (insn), 0, REG_NOTES (insn), true);
+      = eliminate_regs_1 (REG_NOTES (insn), VOIDmode, REG_NOTES (insn), true,
+                         false);
 
   return val;
 }
 
+/* Like eliminate_regs_in_insn, but only estimate costs for the use of the
+   register allocator.  INSN is the instruction we need to examine, we perform
+   eliminations in its operands and record cases where eliminating a reg with
+   an invariant equivalence would add extra cost.  */
+
+static void
+elimination_costs_in_insn (rtx insn)
+{
+  int icode = recog_memoized (insn);
+  rtx old_body = PATTERN (insn);
+  int insn_is_asm = asm_noperands (old_body) >= 0;
+  rtx old_set = single_set (insn);
+  int i;
+  rtx orig_operand[MAX_RECOG_OPERANDS];
+  rtx orig_dup[MAX_RECOG_OPERANDS];
+  struct elim_table *ep;
+  rtx plus_src, plus_cst_src;
+  bool sets_reg_p;
+
+  if (! insn_is_asm && icode < 0)
+    {
+      gcc_assert (GET_CODE (PATTERN (insn)) == USE
+                 || GET_CODE (PATTERN (insn)) == CLOBBER
+                 || GET_CODE (PATTERN (insn)) == ADDR_VEC
+                 || GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC
+                 || GET_CODE (PATTERN (insn)) == ASM_INPUT
+                 || DEBUG_INSN_P (insn));
+      return;
+    }
+
+  if (old_set != 0 && REG_P (SET_DEST (old_set))
+      && REGNO (SET_DEST (old_set)) < FIRST_PSEUDO_REGISTER)
+    {
+      /* Check for setting an eliminable register.  */
+      for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
+       if (ep->from_rtx == SET_DEST (old_set) && ep->can_eliminate)
+         return;
+    }
+
+  /* We allow one special case which happens to work on all machines we
+     currently support: a single set with the source or a REG_EQUAL
+     note being a PLUS of an eliminable register and a constant.  */
+  plus_src = plus_cst_src = 0;
+  sets_reg_p = false;
+  if (old_set && REG_P (SET_DEST (old_set)))
+    {
+      sets_reg_p = true;
+      if (GET_CODE (SET_SRC (old_set)) == PLUS)
+       plus_src = SET_SRC (old_set);
+      /* First see if the source is of the form (plus (...) CST).  */
+      if (plus_src
+         && CONST_INT_P (XEXP (plus_src, 1)))
+       plus_cst_src = plus_src;
+      else if (REG_P (SET_SRC (old_set))
+              || plus_src)
+       {
+         /* Otherwise, see if we have a REG_EQUAL note of the form
+            (plus (...) CST).  */
+         rtx links;
+         for (links = REG_NOTES (insn); links; links = XEXP (links, 1))
+           {
+             if ((REG_NOTE_KIND (links) == REG_EQUAL
+                  || REG_NOTE_KIND (links) == REG_EQUIV)
+                 && GET_CODE (XEXP (links, 0)) == PLUS
+                 && CONST_INT_P (XEXP (XEXP (links, 0), 1)))
+               {
+                 plus_cst_src = XEXP (links, 0);
+                 break;
+               }
+           }
+       }
+    }
+
+  /* Determine the effects of this insn on elimination offsets.  */
+  elimination_effects (old_body, VOIDmode);
+
+  /* Eliminate all eliminable registers occurring in operands that
+     can be handled by reload.  */
+  extract_insn (insn);
+  for (i = 0; i < recog_data.n_dups; i++)
+    orig_dup[i] = *recog_data.dup_loc[i];
+
+  for (i = 0; i < recog_data.n_operands; i++)
+    {
+      orig_operand[i] = recog_data.operand[i];
+
+      /* For an asm statement, every operand is eliminable.  */
+      if (insn_is_asm || insn_data[icode].operand[i].eliminable)
+       {
+         bool is_set_src, in_plus;
+
+         /* Check for setting a register that we know about.  */
+         if (recog_data.operand_type[i] != OP_IN
+             && REG_P (orig_operand[i]))
+           {
+             /* If we are assigning to a register that can be eliminated, it
+                must be as part of a PARALLEL, since the code above handles
+                single SETs.  We must indicate that we can no longer
+                eliminate this reg.  */
+             for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS];
+                  ep++)
+               if (ep->from_rtx == orig_operand[i])
+                 ep->can_eliminate = 0;
+           }
+
+         /* Companion to the above plus substitution, we can allow
+            invariants as the source of a plain move.  */
+         is_set_src = false;
+         if (old_set && recog_data.operand_loc[i] == &SET_SRC (old_set))
+           is_set_src = true;
+         if (is_set_src && !sets_reg_p)
+           note_reg_elim_costly (&SET_SRC (old_set), insn);
+         in_plus = false;
+         if (plus_src && sets_reg_p
+             && (recog_data.operand_loc[i] == &XEXP (plus_src, 0)
+                 || recog_data.operand_loc[i] == &XEXP (plus_src, 1)))
+           in_plus = true;
+
+         eliminate_regs_1 (recog_data.operand[i], VOIDmode,
+                           NULL_RTX,
+                           is_set_src || in_plus, true);
+         /* Terminate the search in check_eliminable_occurrences at
+            this point.  */
+         *recog_data.operand_loc[i] = 0;
+       }
+    }
+
+  for (i = 0; i < recog_data.n_dups; i++)
+    *recog_data.dup_loc[i]
+      = *recog_data.operand_loc[(int) recog_data.dup_num[i]];
+
+  /* If any eliminable remain, they aren't eliminable anymore.  */
+  check_eliminable_occurrences (old_body);
+
+  /* Restore the old body.  */
+  for (i = 0; i < recog_data.n_operands; i++)
+    *recog_data.operand_loc[i] = orig_operand[i];
+  for (i = 0; i < recog_data.n_dups; i++)
+    *recog_data.dup_loc[i] = orig_dup[i];
+
+  /* Update all elimination pairs to reflect the status after the current
+     insn.  The changes we make were determined by the earlier call to
+     elimination_effects.  */
+
+  for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
+    {
+      if (ep->previous_offset != ep->offset && ep->ref_outside_mem)
+       ep->can_eliminate = 0;
+
+      ep->ref_outside_mem = 0;
+    }
+
+  return;
+}
+
 /* Loop through all elimination pairs.
    Recalculate the number not at initial offset.
 
@@ -3578,7 +3812,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;
@@ -3701,9 +3935,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;
@@ -3765,73 +4000,235 @@ update_eliminables (HARD_REG_SET *pset)
        }
     }
 
-  /* If we didn't need a frame pointer last time, but we do now, spill
-     the hard frame pointer.  */
-  if (frame_pointer_needed && ! previous_frame_pointer_needed)
-    SET_HARD_REG_BIT (*pset, HARD_FRAME_POINTER_REGNUM);
-}
+  /* If we didn't need a frame pointer last time, but we do now, spill
+     the hard frame pointer.  */
+  if (frame_pointer_needed && ! previous_frame_pointer_needed)
+    SET_HARD_REG_BIT (*pset, HARD_FRAME_POINTER_REGNUM);
+}
+
+/* Return true if X is used as the target register of an elimination.  */
+
+bool
+elimination_target_reg_p (rtx x)
+{
+  struct elim_table *ep;
+
+  for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
+    if (ep->to_rtx == x && ep->can_eliminate)
+      return true;
+
+  return false;
+}
+
+/* Initialize the table of registers to eliminate.
+   Pre-condition: global flag frame_pointer_needed has been set before
+   calling this function.  */
+
+static void
+init_elim_table (void)
+{
+  struct elim_table *ep;
+#ifdef ELIMINABLE_REGS
+  const struct elim_table_1 *ep1;
+#endif
+
+  if (!reg_eliminate)
+    reg_eliminate = XCNEWVEC (struct elim_table, NUM_ELIMINABLE_REGS);
+
+  num_eliminable = 0;
+
+#ifdef ELIMINABLE_REGS
+  for (ep = reg_eliminate, ep1 = reg_eliminate_1;
+       ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++, ep1++)
+    {
+      ep->from = ep1->from;
+      ep->to = ep1->to;
+      ep->can_eliminate = ep->can_eliminate_previous
+       = (targetm.can_eliminate (ep->from, ep->to)
+          && ! (ep->to == STACK_POINTER_REGNUM
+                && frame_pointer_needed
+                && (! SUPPORTS_STACK_ALIGNMENT
+                    || ! stack_realign_fp)));
+    }
+#else
+  reg_eliminate[0].from = reg_eliminate_1[0].from;
+  reg_eliminate[0].to = reg_eliminate_1[0].to;
+  reg_eliminate[0].can_eliminate = reg_eliminate[0].can_eliminate_previous
+    = ! frame_pointer_needed;
+#endif
+
+  /* Count the number of eliminable registers and build the FROM and TO
+     REG rtx's.  Note that code in gen_rtx_REG will cause, e.g.,
+     gen_rtx_REG (Pmode, STACK_POINTER_REGNUM) to equal stack_pointer_rtx.
+     We depend on this.  */
+  for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
+    {
+      num_eliminable += ep->can_eliminate;
+      ep->from_rtx = gen_rtx_REG (Pmode, ep->from);
+      ep->to_rtx = gen_rtx_REG (Pmode, ep->to);
+    }
+}
+
+/* Find all the pseudo registers that didn't get hard regs
+   but do have known equivalent constants or memory slots.
+   These include parameters (known equivalent to parameter slots)
+   and cse'd or loop-moved constant memory addresses.
+
+   Record constant equivalents in reg_equiv_constant
+   so they will be substituted by find_reloads.
+   Record memory equivalents in reg_mem_equiv so they can
+   be substituted eventually by altering the REG-rtx's.  */
+
+static void
+init_eliminable_invariants (rtx first, bool do_subregs)
+{
+  int i;
+  rtx insn;
+
+  reg_equiv_constant = XCNEWVEC (rtx, max_regno);
+  reg_equiv_invariant = XCNEWVEC (rtx, max_regno);
+  reg_equiv_mem = XCNEWVEC (rtx, max_regno);
+  reg_equiv_alt_mem_list = XCNEWVEC (rtx, max_regno);
+  reg_equiv_address = XCNEWVEC (rtx, max_regno);
+  if (do_subregs)
+    reg_max_ref_width = XCNEWVEC (unsigned int, max_regno);
+  else
+    reg_max_ref_width = NULL;
+
+  num_eliminable_invariants = 0;
+
+  first_label_num = get_first_label_num ();
+  num_labels = max_label_num () - first_label_num;
+
+  /* Allocate the tables used to store offset information at labels.  */
+  offsets_known_at = XNEWVEC (char, num_labels);
+  offsets_at = (HOST_WIDE_INT (*)[NUM_ELIMINABLE_REGS]) xmalloc (num_labels * NUM_ELIMINABLE_REGS * sizeof (HOST_WIDE_INT));
+
+/* Look for REG_EQUIV notes; record what each pseudo is equivalent
+   to.  If DO_SUBREGS is true, also find all paradoxical subregs and
+   find largest such for each pseudo.  FIRST is the head of the insn
+   list.  */
+
+  for (insn = first; insn; insn = NEXT_INSN (insn))
+    {
+      rtx set = single_set (insn);
+
+      /* We may introduce USEs that we want to remove at the end, so
+        we'll mark them with QImode.  Make sure there are no
+        previously-marked insns left by say regmove.  */
+      if (INSN_P (insn) && GET_CODE (PATTERN (insn)) == USE
+         && GET_MODE (insn) != VOIDmode)
+       PUT_MODE (insn, VOIDmode);
+
+      if (do_subregs && NONDEBUG_INSN_P (insn))
+       scan_paradoxical_subregs (PATTERN (insn));
+
+      if (set != 0 && REG_P (SET_DEST (set)))
+       {
+         rtx note = find_reg_note (insn, REG_EQUIV, NULL_RTX);
+         rtx x;
+
+         if (! note)
+           continue;
 
-/* Return true if X is used as the target register of an elimination.  */
+         i = REGNO (SET_DEST (set));
+         x = XEXP (note, 0);
 
-bool
-elimination_target_reg_p (rtx x)
-{
-  struct elim_table *ep;
+         if (i <= LAST_VIRTUAL_REGISTER)
+           continue;
 
-  for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
-    if (ep->to_rtx == x && ep->can_eliminate)
-      return true;
+         /* If flag_pic and we have constant, verify it's legitimate.  */
+         if (!CONSTANT_P (x)
+             || !flag_pic || LEGITIMATE_PIC_OPERAND_P (x))
+           {
+             /* It can happen that a REG_EQUIV note contains a MEM
+                that is not a legitimate memory operand.  As later
+                stages of reload assume that all addresses found
+                in the reg_equiv_* arrays were originally legitimate,
+                we ignore such REG_EQUIV notes.  */
+             if (memory_operand (x, VOIDmode))
+               {
+                 /* Always unshare the equivalence, so we can
+                    substitute into this insn without touching the
+                      equivalence.  */
+                 reg_equiv_memory_loc[i] = copy_rtx (x);
+               }
+             else if (function_invariant_p (x))
+               {
+                 if (GET_CODE (x) == PLUS)
+                   {
+                     /* This is PLUS of frame pointer and a constant,
+                        and might be shared.  Unshare it.  */
+                     reg_equiv_invariant[i] = copy_rtx (x);
+                     num_eliminable_invariants++;
+                   }
+                 else if (x == frame_pointer_rtx || x == arg_pointer_rtx)
+                   {
+                     reg_equiv_invariant[i] = x;
+                     num_eliminable_invariants++;
+                   }
+                 else if (LEGITIMATE_CONSTANT_P (x))
+                   reg_equiv_constant[i] = x;
+                 else
+                   {
+                     reg_equiv_memory_loc[i]
+                       = force_const_mem (GET_MODE (SET_DEST (set)), x);
+                     if (! reg_equiv_memory_loc[i])
+                       reg_equiv_init[i] = NULL_RTX;
+                   }
+               }
+             else
+               {
+                 reg_equiv_init[i] = NULL_RTX;
+                 continue;
+               }
+           }
+         else
+           reg_equiv_init[i] = NULL_RTX;
+       }
+    }
 
-  return false;
+  if (dump_file)
+    for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
+      if (reg_equiv_init[i])
+       {
+         fprintf (dump_file, "init_insns for %u: ", i);
+         print_inline_rtx (dump_file, reg_equiv_init[i], 20);
+         fprintf (dump_file, "\n");
+       }
 }
 
-/* Initialize the table of registers to eliminate.
-   Pre-condition: global flag frame_pointer_needed has been set before
-   calling this function.  */
+/* Indicate that we no longer have known memory locations or constants.
+   Free all data involved in tracking these.  */
 
 static void
-init_elim_table (void)
+free_reg_equiv (void)
 {
-  struct elim_table *ep;
-#ifdef ELIMINABLE_REGS
-  const struct elim_table_1 *ep1;
-#endif
+  int i;
 
-  if (!reg_eliminate)
-    reg_eliminate = XCNEWVEC (struct elim_table, NUM_ELIMINABLE_REGS);
+  if (reg_equiv_constant)
+    free (reg_equiv_constant);
+  if (reg_equiv_invariant)
+    free (reg_equiv_invariant);
+  reg_equiv_constant = 0;
+  reg_equiv_invariant = 0;
+  VEC_free (rtx, gc, reg_equiv_memory_loc_vec);
+  reg_equiv_memory_loc = 0;
 
-  num_eliminable = 0;
+  if (offsets_known_at)
+    free (offsets_known_at);
+  if (offsets_at)
+    free (offsets_at);
+  offsets_at = 0;
+  offsets_known_at = 0;
 
-#ifdef ELIMINABLE_REGS
-  for (ep = reg_eliminate, ep1 = reg_eliminate_1;
-       ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++, ep1++)
-    {
-      ep->from = ep1->from;
-      ep->to = ep1->to;
-      ep->can_eliminate = ep->can_eliminate_previous
-       = (CAN_ELIMINATE (ep->from, ep->to)
-          && ! (ep->to == STACK_POINTER_REGNUM
-                && frame_pointer_needed 
-                && (! SUPPORTS_STACK_ALIGNMENT
-                    || ! stack_realign_fp)));
-    }
-#else
-  reg_eliminate[0].from = reg_eliminate_1[0].from;
-  reg_eliminate[0].to = reg_eliminate_1[0].to;
-  reg_eliminate[0].can_eliminate = reg_eliminate[0].can_eliminate_previous
-    = ! frame_pointer_needed;
-#endif
+  for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+    if (reg_equiv_alt_mem_list[i])
+      free_EXPR_LIST_list (&reg_equiv_alt_mem_list[i]);
+  free (reg_equiv_alt_mem_list);
 
-  /* Count the number of eliminable registers and build the FROM and TO
-     REG rtx's.  Note that code in gen_rtx_REG will cause, e.g.,
-     gen_rtx_REG (Pmode, STACK_POINTER_REGNUM) to equal stack_pointer_rtx.
-     We depend on this.  */
-  for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
-    {
-      num_eliminable += ep->can_eliminate;
-      ep->from_rtx = gen_rtx_REG (Pmode, ep->from);
-      ep->to_rtx = gen_rtx_REG (Pmode, ep->to);
-    }
+  free (reg_equiv_mem);
+  free (reg_equiv_address);
 }
 \f
 /* Kick all pseudos out of hard register REGNO.
@@ -3904,17 +4301,17 @@ finish_spills (int global)
       spill_reg_order[i] = -1;
 
   EXECUTE_IF_SET_IN_REG_SET (&spilled_pseudos, FIRST_PSEUDO_REGISTER, i, rsi)
-    if (! flag_ira || ! optimize || reg_renumber[i] >= 0)
+    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 (flag_ira && optimize)
+       if (ira_conflicts_p)
          /* Inform IRA about the change.  */
          ira_mark_allocation_change (i);
        /* We will need to scan everything again.  */
@@ -3922,8 +4319,10 @@ finish_spills (int global)
       }
 
   /* 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
@@ -3944,49 +4343,23 @@ finish_spills (int global)
            }
        }
 
-      if (! flag_ira || ! optimize)
-       {
-         /* 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;
-         
-       }
+      /* 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])
+         {
+           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
@@ -3996,7 +4369,7 @@ finish_spills (int global)
       HARD_REG_SET used_by_pseudos;
       HARD_REG_SET used_by_pseudos2;
 
-      if (! flag_ira || ! optimize)
+      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
@@ -4110,26 +4483,11 @@ static void
 fixup_eh_region_note (rtx insn, rtx prev, rtx next)
 {
   rtx note = find_reg_note (insn, REG_EH_REGION, NULL_RTX);
-  unsigned int trap_count;
-  rtx i;
-
   if (note == NULL)
     return;
-
-  if (may_trap_p (PATTERN (insn)))
-    trap_count = 1;
-  else
-    {
-      remove_note (insn, note);
-      trap_count = 0;
-    }
-
-  for (i = NEXT_INSN (prev); i != next; i = NEXT_INSN (i))
-    if (INSN_P (i) && i != insn && may_trap_p (PATTERN (i)))
-      {
-       trap_count++;
-       add_reg_note (i, REG_EH_REGION, XEXP (note, 0));
-      }
+  if (!insn_could_throw_p (insn))
+    remove_note (insn, note);
+  copy_reg_eh_region_note_forward (note, NEXT_INSN (prev), next);
 }
 
 /* Reload pseudo-registers into hard regs around each insn as needed.
@@ -4239,12 +4597,6 @@ reload_as_needed (int live_known)
                 Record the choices of reload reg in reload_reg_rtx.  */
              choose_reload_regs (chain);
 
-             /* Merge any reloads that we didn't combine for fear of
-                increasing the number of spill registers needed but now
-                discover can be safely merged.  */
-             if (SMALL_REGISTER_CLASSES)
-               merge_assigned_reloads (insn);
-
              /* Generate the insns to reload operands into or out of
                 their reload regs.  */
              emit_reload_insns (chain);
@@ -4256,7 +4608,7 @@ reload_as_needed (int live_known)
              subst_reloads (insn);
 
              /* Adjust the exception region notes for loads and stores.  */
-             if (flag_non_call_exceptions && !CALL_P (insn))
+             if (cfun->can_throw_non_call_exceptions && !CALL_P (insn))
                fixup_eh_region_note (insn, prev, next);
 
              /* If this was an ASM, make sure that all the reload insns
@@ -4335,31 +4687,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;
                        }
@@ -4391,29 +4742,39 @@ 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))
+                 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)
                        {
+                         int in_hard_regno;
+                         bool forget_p = true;
+
                          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 (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.  */
-                         if (x == old_next)
+                            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);
                        }
@@ -4462,7 +4823,7 @@ reload_as_needed (int live_known)
    unless X is an output reload reg of the current insn.
 
    X may be a hard reg (the reload reg)
-   or it may be a pseudo reg that was reloaded from.  
+   or it may be a pseudo reg that was reloaded from.
 
    When DATA is non-NULL just mark the registers in regset
    to be forgotten later.  */
@@ -5119,9 +5480,8 @@ reloads_unique_chain_p (int r1, int r2)
   return true;
 }
 
-
 /* The recursive function change all occurrences of WHAT in *WHERE
-   onto REPL.  */
+   to REPL.  */
 static void
 substitute (rtx *where, const_rtx what, rtx repl)
 {
@@ -5134,6 +5494,8 @@ substitute (rtx *where, const_rtx what, rtx repl)
 
   if (*where == what || rtx_equal_p (*where, what))
     {
+      /* Record the location of the changed rtx.  */
+      VEC_safe_push (rtx_p, heap, substitute_stack, where);
       *where = repl;
       return;
     }
@@ -5181,7 +5543,9 @@ substitute (rtx *where, const_rtx what, rtx repl)
 static bool
 gen_reload_chain_without_interm_reg_p (int r1, int r2)
 {
-  bool result;
+  /* Assume other cases in gen_reload are not possible for
+     chain reloads or do need an intermediate hard registers.  */
+  bool result = true;
   int regno, n, code;
   rtx out, in, tem, insn;
   rtx last = get_last_insn ();
@@ -5197,7 +5561,7 @@ gen_reload_chain_without_interm_reg_p (int r1, int r2)
   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);
+  in = rld[r1].in;
   substitute (&in, rld[r2].in, gen_rtx_REG (rld[r2].mode, regno));
 
   /* If IN is a paradoxical SUBREG, remove it and try to put the
@@ -5229,14 +5593,18 @@ gen_reload_chain_without_interm_reg_p (int r1, int r2)
             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;
+
+  /* Restore the original value at each changed address within R1.  */
+  while (!VEC_empty (rtx_p, substitute_stack))
+    {
+      rtx *where = VEC_pop (rtx_p, substitute_stack);
+      *where = rld[r2].in;
+    }
+
+  return result;
 }
 
 /* Return 1 if the reloads denoted by R1 and R2 cannot share a register.
@@ -5612,7 +5980,7 @@ function_invariant_p (const_rtx x)
     return 1;
   if (GET_CODE (x) == PLUS
       && (XEXP (x, 0) == frame_pointer_rtx || XEXP (x, 0) == arg_pointer_rtx)
-      && CONSTANT_P (XEXP (x, 1)))
+      && GET_CODE (XEXP (x, 1)) == CONST_INT)
     return 1;
   return 0;
 }
@@ -5657,7 +6025,9 @@ failed_reload (rtx insn, int r)
 static int
 set_reload_reg (int i, int r)
 {
-  int regno;
+  /* regno is 'set but not used' if HARD_REGNO_MODE_OK doesn't use its first
+     parameter.  */
+  int regno ATTRIBUTE_UNUSED;
   rtx reg = spill_reg_rtx[i];
 
   if (reg == 0 || GET_MODE (reg) != rld[r].mode)
@@ -5734,15 +6104,17 @@ allocate_reload_reg (struct insn_chain *chain ATTRIBUTE_UNUSED, int r,
      take any reg in the right class and not in use.
      If we want a consecutive group, here is where we look for it.
 
-     We use two passes so we can first look for reload regs to
+     We use three passes so we can first look for reload regs to
      reuse, which are already in use for other reloads in this insn,
-     and only then use additional registers.
+     and only then use additional registers which are not "bad", then
+     finally any register.
+
      I think that maximizing reuse is needed to make sure we don't
      run out of reload regs.  Suppose we have three reloads, and
      reloads A and B can share regs.  These need two regs.
      Suppose A and B are given different regs.
      That leaves none for C.  */
-  for (pass = 0; pass < 2; pass++)
+  for (pass = 0; pass < 3; pass++)
     {
       /* I is the index in spill_regs.
         We advance it round-robin between insns to use all spill regs
@@ -5782,6 +6154,13 @@ allocate_reload_reg (struct insn_chain *chain ATTRIBUTE_UNUSED, int r,
                                              regnum))))
            {
              int nr = hard_regno_nregs[regnum][rld[r].mode];
+
+             /* During the second pass we want to avoid reload registers
+                which are "bad" for this reload.  */
+             if (pass == 1
+                 && ira_bad_reload_regno (regnum, rld[r].in, rld[r].out))
+               continue;
+
              /* Avoid the problem where spilling a GENERAL_OR_FP_REG
                 (on 68000) got us two FP regs.  If NR is 1,
                 we would reject both of them.  */
@@ -5812,7 +6191,7 @@ allocate_reload_reg (struct insn_chain *chain ATTRIBUTE_UNUSED, int r,
            }
        }
 
-      /* If we found something on pass 1, omit pass 2.  */
+      /* If we found something on the current pass, omit later passes.  */
       if (count < n_spills)
        break;
     }
@@ -6084,9 +6463,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))
@@ -6098,8 +6478,8 @@ choose_reload_regs (struct insn_chain *chain)
                             register, we might use it for reload_override_in,
                             if copying it to the desired class is cheap
                             enough.  */
-                         || ((REGISTER_MOVE_COST (mode, last_class, rclass)
-                              < MEMORY_MOVE_COST (mode, rclass, 1))
+                         || ((register_move_cost (mode, last_class, rclass)
+                              < memory_move_cost (mode, rclass, true))
                              && (secondary_reload_class (1, rclass, mode,
                                                          last_reg)
                                  == NO_REGS)
@@ -6220,17 +6600,6 @@ choose_reload_regs (struct insn_chain *chain)
              && (rld[r].nregs == max_group_size
                  || ! reg_classes_intersect_p (rld[r].rclass, group_class)))
            search_equiv = rld[r].in;
-         /* If this is an output reload from a simple move insn, look
-            if an equivalence for the input is available.  */
-         else if (inheritance && rld[r].in == 0 && rld[r].out != 0)
-           {
-             rtx set = single_set (insn);
-
-             if (set
-                 && rtx_equal_p (rld[r].out, SET_DEST (set))
-                 && CONSTANT_P (SET_SRC (set)))
-               search_equiv = SET_SRC (set);
-           }
 
          if (search_equiv)
            {
@@ -6611,152 +6980,6 @@ deallocate_reload_reg (int r)
   reload_spill_index[r] = -1;
 }
 \f
-/* If SMALL_REGISTER_CLASSES is nonzero, we may not have merged two
-   reloads of the same item for fear that we might not have enough reload
-   registers. However, normally they will get the same reload register
-   and hence actually need not be loaded twice.
-
-   Here we check for the most common case of this phenomenon: when we have
-   a number of reloads for the same object, each of which were allocated
-   the same reload_reg_rtx, that reload_reg_rtx is not used for any other
-   reload, and is not modified in the insn itself.  If we find such,
-   merge all the reloads and set the resulting reload to RELOAD_OTHER.
-   This will not increase the number of spill registers needed and will
-   prevent redundant code.  */
-
-static void
-merge_assigned_reloads (rtx insn)
-{
-  int i, j;
-
-  /* Scan all the reloads looking for ones that only load values and
-     are not already RELOAD_OTHER and ones whose reload_reg_rtx are
-     assigned and not modified by INSN.  */
-
-  for (i = 0; i < n_reloads; i++)
-    {
-      int conflicting_input = 0;
-      int max_input_address_opnum = -1;
-      int min_conflicting_input_opnum = MAX_RECOG_OPERANDS;
-
-      if (rld[i].in == 0 || rld[i].when_needed == RELOAD_OTHER
-         || rld[i].out != 0 || rld[i].reg_rtx == 0
-         || reg_set_p (rld[i].reg_rtx, insn))
-       continue;
-
-      /* Look at all other reloads.  Ensure that the only use of this
-        reload_reg_rtx is in a reload that just loads the same value
-        as we do.  Note that any secondary reloads must be of the identical
-        class since the values, modes, and result registers are the
-        same, so we need not do anything with any secondary reloads.  */
-
-      for (j = 0; j < n_reloads; j++)
-       {
-         if (i == j || rld[j].reg_rtx == 0
-             || ! reg_overlap_mentioned_p (rld[j].reg_rtx,
-                                           rld[i].reg_rtx))
-           continue;
-
-         if (rld[j].when_needed == RELOAD_FOR_INPUT_ADDRESS
-             && rld[j].opnum > max_input_address_opnum)
-           max_input_address_opnum = rld[j].opnum;
-
-         /* If the reload regs aren't exactly the same (e.g, different modes)
-            or if the values are different, we can't merge this reload.
-            But if it is an input reload, we might still merge
-            RELOAD_FOR_INPUT_ADDRESS and RELOAD_FOR_OTHER_ADDRESS reloads.  */
-
-         if (! rtx_equal_p (rld[i].reg_rtx, rld[j].reg_rtx)
-             || rld[j].out != 0 || rld[j].in == 0
-             || ! rtx_equal_p (rld[i].in, rld[j].in))
-           {
-             if (rld[j].when_needed != RELOAD_FOR_INPUT
-                 || ((rld[i].when_needed != RELOAD_FOR_INPUT_ADDRESS
-                      || rld[i].opnum > rld[j].opnum)
-                     && rld[i].when_needed != RELOAD_FOR_OTHER_ADDRESS))
-               break;
-             conflicting_input = 1;
-             if (min_conflicting_input_opnum > rld[j].opnum)
-               min_conflicting_input_opnum = rld[j].opnum;
-           }
-       }
-
-      /* If all is OK, merge the reloads.  Only set this to RELOAD_OTHER if
-        we, in fact, found any matching reloads.  */
-
-      if (j == n_reloads
-         && max_input_address_opnum <= min_conflicting_input_opnum)
-       {
-         gcc_assert (rld[i].when_needed != RELOAD_FOR_OUTPUT);
-
-         for (j = 0; j < n_reloads; j++)
-           if (i != j && rld[j].reg_rtx != 0
-               && rtx_equal_p (rld[i].reg_rtx, rld[j].reg_rtx)
-               && (! conflicting_input
-                   || rld[j].when_needed == RELOAD_FOR_INPUT_ADDRESS
-                   || rld[j].when_needed == RELOAD_FOR_OTHER_ADDRESS))
-             {
-               rld[i].when_needed = RELOAD_OTHER;
-               rld[j].in = 0;
-               reload_spill_index[j] = -1;
-               transfer_replacements (i, j);
-             }
-
-         /* If this is now RELOAD_OTHER, look for any reloads that
-            load parts of this operand and set them to
-            RELOAD_FOR_OTHER_ADDRESS if they were for inputs,
-            RELOAD_OTHER for outputs.  Note that this test is
-            equivalent to looking for reloads for this operand
-            number.
-
-            We must take special care with RELOAD_FOR_OUTPUT_ADDRESS;
-            it may share registers with a RELOAD_FOR_INPUT, so we can
-            not change it to RELOAD_FOR_OTHER_ADDRESS.  We should
-            never need to, since we do not modify RELOAD_FOR_OUTPUT.
-
-            It is possible that the RELOAD_FOR_OPERAND_ADDRESS
-            instruction is assigned the same register as the earlier
-            RELOAD_FOR_OTHER_ADDRESS instruction.  Merging these two
-            instructions will cause the RELOAD_FOR_OTHER_ADDRESS
-            instruction to be deleted later on.  */
-
-         if (rld[i].when_needed == RELOAD_OTHER)
-           for (j = 0; j < n_reloads; j++)
-             if (rld[j].in != 0
-                 && rld[j].when_needed != RELOAD_OTHER
-                 && rld[j].when_needed != RELOAD_FOR_OTHER_ADDRESS
-                 && rld[j].when_needed != RELOAD_FOR_OUTPUT_ADDRESS
-                 && rld[j].when_needed != RELOAD_FOR_OPERAND_ADDRESS
-                 && (! conflicting_input
-                     || rld[j].when_needed == RELOAD_FOR_INPUT_ADDRESS
-                     || rld[j].when_needed == RELOAD_FOR_INPADDR_ADDRESS)
-                 && reg_overlap_mentioned_for_reload_p (rld[j].in,
-                                                        rld[i].in))
-               {
-                 int k;
-
-                 rld[j].when_needed
-                   = ((rld[j].when_needed == RELOAD_FOR_INPUT_ADDRESS
-                       || rld[j].when_needed == RELOAD_FOR_INPADDR_ADDRESS)
-                      ? RELOAD_FOR_OTHER_ADDRESS : RELOAD_OTHER);
-
-                 /* Check to see if we accidentally converted two
-                    reloads that use the same reload register with
-                    different inputs to the same type.  If so, the
-                    resulting code won't work.  */
-                 if (rld[j].reg_rtx)
-                   for (k = 0; k < j; k++)
-                     gcc_assert (rld[k].in == 0 || rld[k].reg_rtx == 0
-                                 || rld[k].when_needed != rld[j].when_needed
-                                 || !rtx_equal_p (rld[k].reg_rtx,
-                                                  rld[j].reg_rtx)
-                                 || rtx_equal_p (rld[k].in,
-                                                 rld[j].in));
-               }
-       }
-    }
-}
-\f
 /* These arrays are filled by emit_reload_insns and its subroutines.  */
 static rtx input_reload_insns[MAX_RECOG_OPERANDS];
 static rtx other_input_address_reload_insns = 0;
@@ -6961,7 +7184,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)
@@ -6998,12 +7221,19 @@ emit_input_reload_insns (struct insn_chain *chain, struct reload *rl,
                  && REG_N_SETS (REGNO (old)) == 1)
                {
                  reg_renumber[REGNO (old)] = REGNO (reloadreg);
-                 if (flag_ira && optimize)
+                 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
            {
@@ -7101,18 +7331,27 @@ emit_input_reload_insns (struct insn_chain *chain, struct reload *rl,
 
          sri.icode = CODE_FOR_nothing;
          sri.prev_sri = NULL;
-         new_class = targetm.secondary_reload (1, real_oldequiv, rl->rclass,
-                                               mode, &sri);
+         new_class
+           = (enum reg_class) targetm.secondary_reload (1, real_oldequiv,
+                                                        rl->rclass, mode,
+                                                        &sri);
 
          if (new_class == NO_REGS && sri.icode == CODE_FOR_nothing)
            second_reload_reg = 0;
          else if (new_class == NO_REGS)
            {
              if (reload_adjust_reg_for_icode (&second_reload_reg,
-                                              third_reload_reg, sri.icode))
-               icode = sri.icode, third_reload_reg = 0;
+                                              third_reload_reg,
+                                              (enum insn_code) sri.icode))
+               {
+                 icode = (enum insn_code) sri.icode;
+                 third_reload_reg = 0;
+               }
              else
-               oldequiv = old, real_oldequiv = real_old;
+               {
+                 oldequiv = old;
+                 real_oldequiv = real_old;
+               }
            }
          else if (sri.icode != CODE_FOR_nothing)
            /* We currently lack a way to express this in reloads.  */
@@ -7121,16 +7360,24 @@ emit_input_reload_insns (struct insn_chain *chain, struct reload *rl,
            {
              sri2.icode = CODE_FOR_nothing;
              sri2.prev_sri = &sri;
-             new_t_class = targetm.secondary_reload (1, real_oldequiv,
-                                                     new_class, mode, &sri);
+             new_t_class
+               = (enum reg_class) targetm.secondary_reload (1, real_oldequiv,
+                                                            new_class, mode,
+                                                            &sri);
              if (new_t_class == NO_REGS && sri2.icode == CODE_FOR_nothing)
                {
                  if (reload_adjust_reg_for_temp (&second_reload_reg,
                                                  third_reload_reg,
                                                  new_class, mode))
-                   third_reload_reg = 0, tertiary_icode = sri2.icode;
+                   {
+                     third_reload_reg = 0;
+                     tertiary_icode = (enum insn_code) sri2.icode;
+                   }
                  else
-                   oldequiv = old, real_oldequiv = real_old;
+                   {
+                     oldequiv = old;
+                     real_oldequiv = real_old;
+                   }
                }
              else if (new_t_class == NO_REGS && sri2.icode != CODE_FOR_nothing)
                {
@@ -7139,13 +7386,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)
                {
@@ -7157,14 +7408,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;
+               }
            }
        }
 
@@ -7232,16 +7489,16 @@ emit_input_reload_insns (struct insn_chain *chain, struct reload *rl,
                  || (reg_equiv_constant
                      [REGNO (SUBREG_REG (oldequiv))] != 0)))
          || (CONSTANT_P (oldequiv)
-             && (PREFERRED_RELOAD_CLASS (oldequiv,
-                                         REGNO_REG_CLASS (REGNO (reloadreg)))
+             && (targetm.preferred_reload_class (oldequiv,
+                                                 REGNO_REG_CLASS (REGNO (reloadreg)))
                  == NO_REGS)))
        real_oldequiv = rl->in;
       gen_reload (reloadreg, real_oldequiv, rl->opnum,
                  rl->when_needed);
     }
 
-  if (flag_non_call_exceptions)
-    copy_eh_notes (insn, get_insns ());
+  if (cfun->can_throw_non_call_exceptions)
+    copy_reg_eh_region_note_forward (insn, get_insns (), NULL);
 
   /* End this sequence.  */
   *where = get_insns ();
@@ -7460,8 +7717,8 @@ emit_output_reload_insns (struct insn_chain *chain, struct reload *rl,
   else
     output_reload_insns[rl->opnum] = get_insns ();
 
-  if (flag_non_call_exceptions)
-    copy_eh_notes (insn, get_insns ());
+  if (cfun->can_throw_non_call_exceptions)
+    copy_reg_eh_region_note_forward (insn, get_insns (), NULL);
 
   end_sequence ();
 }
@@ -8073,7 +8330,7 @@ emit_reload_insns (struct insn_chain *chain)
                      SET_HARD_REG_BIT (reg_reloaded_valid, src_regno + k);
                      if (HARD_REGNO_CALL_PART_CLOBBERED (src_regno + k,
                                                          mode))
-                       SET_HARD_REG_BIT (reg_reloaded_call_part_clobbered, 
+                       SET_HARD_REG_BIT (reg_reloaded_call_part_clobbered,
                                          src_regno + k);
                      else
                        CLEAR_HARD_REG_BIT (reg_reloaded_call_part_clobbered,
@@ -8085,7 +8342,7 @@ emit_reload_insns (struct insn_chain *chain)
                        CLEAR_HARD_REG_BIT (reg_reloaded_died, src_regno);
                    }
                  reg_last_reload_reg[out_regno] = src_reg;
-                 /* We have to set reg_has_output_reload here, or else 
+                 /* We have to set reg_has_output_reload here, or else
                     forget_old_reloads_1 will clear reg_last_reload_reg
                     right away.  */
                  SET_REGNO_REG_SET (&reg_has_output_reload,
@@ -8248,7 +8505,7 @@ gen_reload (rtx out, rtx in, int opnum, enum reload_type type)
         DEFINE_PEEPHOLE should be specified that recognizes the sequence
         we emit below.  */
 
-      code = (int) optab_handler (add_optab, GET_MODE (out))->insn_code;
+      code = (int) optab_handler (add_optab, GET_MODE (out));
 
       if (CONSTANT_P (op1) || MEM_P (op1) || GET_CODE (op1) == SUBREG
          || (REG_P (op1)
@@ -8347,7 +8604,7 @@ gen_reload (rtx out, rtx in, int opnum, enum reload_type type)
          return insn;
        }
 
-      fatal_insn ("Failure trying to reload:", set);
+      fatal_insn ("failure trying to reload:", set);
     }
   /* If IN is a simple operand, use gen_move_insn.  */
   else if (OBJECT_P (in) || GET_CODE (in) == SUBREG)
@@ -8395,6 +8652,8 @@ delete_output_reload (rtx insn, int j, int last_reload_reg, rtx new_reload_reg)
   int n_inherited = 0;
   rtx i1;
   rtx substed;
+  unsigned regno;
+  int nregs;
 
   /* It is possible that this reload has been only used to set another reload
      we eliminated earlier and thus deleted this instruction too.  */
@@ -8436,7 +8695,7 @@ 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))
     {
@@ -8446,6 +8705,12 @@ delete_output_reload (rtx insn, int j, int last_reload_reg, rtx new_reload_reg)
   if (n_occurrences > n_inherited)
     return;
 
+  regno = REGNO (reg);
+  if (regno >= FIRST_PSEUDO_REGISTER)
+    nregs = 1;
+  else
+    nregs = hard_regno_nregs[regno][GET_MODE (reg)];
+
   /* If the pseudo-reg we are reloading is no longer referenced
      anywhere between the store into it and here,
      and we're within the same basic block, then the value can only
@@ -8457,7 +8722,7 @@ delete_output_reload (rtx insn, int j, int last_reload_reg, rtx new_reload_reg)
       if (NOTE_INSN_BASIC_BLOCK_P (i1))
        return;
       if ((NONJUMP_INSN_P (i1) || CALL_P (i1))
-         && reg_mentioned_p (reg, PATTERN (i1)))
+         && refers_to_regno_p (regno, regno + nregs, PATTERN (i1), NULL))
        {
          /* If this is USE in front of INSN, we only have to check that
             there are no more references than accounted for by inheritance.  */
@@ -8539,7 +8804,7 @@ 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);
-      if (flag_ira && optimize)
+      if (ira_conflicts_p)
        /* Inform IRA about the change.  */
        ira_mark_allocation_change (REGNO (reg));
       alter_reg (REGNO (reg), -1, false);
@@ -8575,8 +8840,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))
@@ -8801,7 +9066,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));
@@ -8837,21 +9102,6 @@ add_auto_inc_notes (rtx insn, rtx x)
 }
 #endif
 
-/* Copy EH notes from an insn to its reloads.  */
-static void
-copy_eh_notes (rtx insn, rtx x)
-{
-  rtx eh_note = find_reg_note (insn, REG_EH_REGION, NULL_RTX);
-  if (eh_note)
-    {
-      for (; x != 0; x = NEXT_INSN (x))
-       {
-         if (may_trap_p (PATTERN (x)))
-           add_reg_note (x, REG_EH_REGION, XEXP (eh_note, 0));
-       }
-    }
-}
-
 /* This is used by reload pass, that does emit some instructions after
    abnormal calls moving basic block end, but in fact it wants to emit
    them on the edge.  Looks for abnormal call edges, find backward the
@@ -8900,9 +9150,7 @@ fixup_abnormal_edges (void)
              BB_END (bb) = insn;
              insn = NEXT_INSN (insn);
 
-             FOR_EACH_EDGE (e, ei, bb->succs)
-               if (e->flags & EDGE_FALLTHRU)
-                 break;
+             e = find_fallthru_edge (bb->succs);
 
              while (insn && insn != stop)
                {
@@ -8934,7 +9182,7 @@ fixup_abnormal_edges (void)
            }
 
          /* It may be that we don't find any such trapping insn.  In this
-            case we discovered quite late that the insn that had been 
+            case we discovered quite late that the insn that had been
             marked as can_throw_internal in fact couldn't trap at all.
             So we should in fact delete the EH edges out of the block.  */
          else
@@ -8943,7 +9191,7 @@ fixup_abnormal_edges (void)
     }
 
   /* We've possibly turned single trapping insn into multiple ones.  */
-  if (flag_non_call_exceptions)
+  if (cfun->can_throw_non_call_exceptions)
     {
       sbitmap blocks;
       blocks = sbitmap_alloc (last_basic_block);