OSDN Git Service

2005-06-15 Andrew Pinski <pinskia@physics.uc.edu>
[pf3gnuchains/gcc-fork.git] / gcc / reload1.c
index ea01b68..3176dca 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 Free Software Foundation, Inc.
+   1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -120,7 +120,8 @@ static unsigned int *reg_max_ref_width;
 
 /* Element N is the list of insns that initialized reg N from its equivalent
    constant or memory slot.  */
-static rtx *reg_equiv_init;
+rtx *reg_equiv_init;
+int reg_equiv_init_size;
 
 /* Vector to remember old contents of reg_renumber before spilling.  */
 static short *reg_old_renumber;
@@ -268,15 +269,15 @@ 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.  */
-struct obstack reload_obstack;
+static struct obstack reload_obstack;
 
 /* Points to the beginning of the reload_obstack.  All insn_chain structures
    are allocated first.  */
-char *reload_startobj;
+static char *reload_startobj;
 
 /* The point after all insn_chain structures.  Used to quickly deallocate
    memory allocated in copy_reloads during calculate_needs_all_insns.  */
-char *reload_firstobj;
+static char *reload_firstobj;
 
 /* This points before all local rtl generated by register elimination.
    Used to quickly free all memory after processing one insn.  */
@@ -383,14 +384,13 @@ static int eliminate_regs_in_insn (rtx, int);
 static void update_eliminable_offsets (void);
 static void mark_not_eliminable (rtx, rtx, void *);
 static void set_initial_elim_offsets (void);
-static void verify_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_elim_table (void);
 static void update_eliminables (HARD_REG_SET *);
 static void spill_hard_reg (unsigned int, int);
 static int finish_spills (int);
-static void ior_hard_reg_set (HARD_REG_SET *, HARD_REG_SET *);
 static void scan_paradoxical_subregs (rtx);
 static void count_pseudo (int);
 static void order_regs_for_reload (struct insn_chain *);
@@ -406,7 +406,6 @@ static int reload_reg_free_for_value_p (int, int, int, enum reload_type,
                                        rtx, rtx, int, int);
 static int free_for_value_p (int, enum machine_mode, int, enum reload_type,
                             rtx, rtx, int, int);
-static int function_invariant_p (rtx);
 static int reload_reg_reaches_end_p (unsigned int, int, enum reload_type);
 static int allocate_reload_reg (struct insn_chain *, int, int);
 static int conflicts_with_override (rtx);
@@ -431,6 +430,8 @@ static rtx inc_for_reload (rtx, rtx, rtx, int);
 static void add_auto_inc_notes (rtx, rtx);
 #endif
 static void copy_eh_notes (rtx, rtx);
+static int reloads_conflict (int, int);
+static rtx gen_reload (rtx, rtx, int, enum reload_type);
 \f
 /* Initialize the reload pass once per compilation.  */
 
@@ -523,29 +524,28 @@ void
 compute_use_by_pseudos (HARD_REG_SET *to, regset from)
 {
   unsigned int regno;
+  reg_set_iterator rsi;
 
-  EXECUTE_IF_SET_IN_REG_SET
-    (from, FIRST_PSEUDO_REGISTER, regno,
-     {
-       int r = reg_renumber[regno];
-       int nregs;
-
-       if (r < 0)
-        {
-          /* reload_combine uses the information from
-             BASIC_BLOCK->global_live_at_start, which might still
-             contain registers that have not actually been allocated
-             since they have an equivalence.  */
-          if (! reload_completed)
-            abort ();
-        }
-       else
-        {
-          nregs = hard_regno_nregs[r][PSEUDO_REGNO_MODE (regno)];
-          while (nregs-- > 0)
-            SET_HARD_REG_BIT (*to, r + nregs);
-        }
-     });
+  EXECUTE_IF_SET_IN_REG_SET (from, FIRST_PSEUDO_REGISTER, regno, rsi)
+    {
+      int r = reg_renumber[regno];
+      int nregs;
+
+      if (r < 0)
+       {
+         /* reload_combine uses the information from
+            BASIC_BLOCK->global_live_at_start, which might still
+            contain registers that have not actually been allocated
+            since they have an equivalence.  */
+         gcc_assert (reload_completed);
+       }
+      else
+       {
+         nregs = hard_regno_nregs[r][PSEUDO_REGNO_MODE (regno)];
+         while (nregs-- > 0)
+           SET_HARD_REG_BIT (*to, r + nregs);
+       }
+    }
 }
 
 /* Replace all pseudos found in LOC with their corresponding
@@ -584,11 +584,12 @@ replace_pseudos_in (rtx *loc, enum machine_mode mem_mode, rtx usage)
        *loc = reg_equiv_mem[regno];
       else if (reg_equiv_address[regno])
        *loc = gen_rtx_MEM (GET_MODE (x), reg_equiv_address[regno]);
-      else if (!REG_P (regno_reg_rtx[regno])
-              || REGNO (regno_reg_rtx[regno]) != regno)
-       *loc = regno_reg_rtx[regno];
       else
-       abort ();
+       {
+         gcc_assert (!REG_P (regno_reg_rtx[regno])
+                     || REGNO (regno_reg_rtx[regno]) != regno);
+         *loc = regno_reg_rtx[regno];
+       }
 
       return;
     }
@@ -614,7 +615,7 @@ replace_pseudos_in (rtx *loc, enum machine_mode mem_mode, rtx usage)
 /* 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.  */
-int something_needs_operands_changed;
+static int something_needs_operands_changed;
 
 /* Nonzero means we couldn't get enough spill regs.  */
 static int failure;
@@ -681,17 +682,6 @@ reload (rtx first, int global)
       if (! call_used_regs[i] && ! fixed_regs[i] && ! LOCAL_REGNO (i))
        regs_ever_live[i] = 1;
 
-#ifdef NON_SAVING_SETJMP
-  /* A function that calls setjmp should save and restore all the
-     call-saved registers on a system where longjmp clobbers them.  */
-  if (NON_SAVING_SETJMP && current_function_calls_setjmp)
-    {
-      for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
-       if (! call_used_regs[i])
-         regs_ever_live[i] = 1;
-    }
-#endif
-
   /* 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)
@@ -704,7 +694,6 @@ reload (rtx first, int global)
 
   reg_equiv_constant = xcalloc (max_regno, sizeof (rtx));
   reg_equiv_mem = xcalloc (max_regno, sizeof (rtx));
-  reg_equiv_init = xcalloc (max_regno, sizeof (rtx));
   reg_equiv_address = xcalloc (max_regno, sizeof (rtx));
   reg_max_ref_width = xcalloc (max_regno, sizeof (int));
   reg_old_renumber = xcalloc (max_regno, sizeof (short));
@@ -730,92 +719,88 @@ reload (rtx first, int global)
          && 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);
-         if (note
-#ifdef LEGITIMATE_PIC_OPERAND_P
-             && (! function_invariant_p (XEXP (note, 0))
-                 || ! 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 (XEXP (note, 0))
-                     && LEGITIMATE_PIC_OPERAND_P (XEXP (note, 0))))
-#endif
-             )
+         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)))
            {
-             rtx x = XEXP (note, 0);
-             i = REGNO (SET_DEST (set));
-             if (i > LAST_VIRTUAL_REGISTER)
+             /* 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))
                {
-                 /* 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))
+                 if (GET_CODE (x) == PLUS)
                    {
-                     /* Always unshare the equivalence, so we can
-                        substitute into this insn without touching the
-                        equivalence.  */
-                     reg_equiv_memory_loc[i] = copy_rtx (x);
+                     /* This is PLUS of frame pointer and a constant,
+                        and might be shared.  Unshare it.  */
+                     reg_equiv_constant[i] = copy_rtx (x);
+                     num_eliminable_invariants++;
                    }
-                 else if (function_invariant_p (x))
+                 else if (x == frame_pointer_rtx
+                          || x == arg_pointer_rtx)
                    {
-                     if (GET_CODE (x) == PLUS)
-                       {
-                         /* This is PLUS of frame pointer and a constant,
-                            and might be shared.  Unshare it.  */
-                         reg_equiv_constant[i] = copy_rtx (x);
-                         num_eliminable_invariants++;
-                       }
-                     else if (x == frame_pointer_rtx
-                              || x == arg_pointer_rtx)
-                       {
-                         reg_equiv_constant[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])
-                           continue;
-                       }
+                     reg_equiv_constant[i] = x;
+                     num_eliminable_invariants++;
                    }
+                 else if (LEGITIMATE_CONSTANT_P (x))
+                   reg_equiv_constant[i] = x;
                  else
-                   continue;
-
-                 /* If this register is being made equivalent to a MEM
-                    and the MEM is not SET_SRC, the equivalencing insn
-                    is one with the MEM as a SET_DEST and it occurs later.
-                    So don't mark this insn now.  */
-                 if (GET_CODE (x) != MEM
-                     || rtx_equal_p (SET_SRC (set), x))
-                   reg_equiv_init[i]
-                     = gen_rtx_INSN_LIST (VOIDmode, insn, reg_equiv_init[i]);
+                   {
+                     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 this insn is setting a MEM from a register equivalent to it,
-        this is the equivalencing insn.  */
-      else if (set && GET_CODE (SET_DEST (set)) == MEM
-              && REG_P (SET_SRC (set))
-              && reg_equiv_memory_loc[REGNO (SET_SRC (set))]
-              && rtx_equal_p (SET_DEST (set),
-                              reg_equiv_memory_loc[REGNO (SET_SRC (set))]))
-       reg_equiv_init[REGNO (SET_SRC (set))]
-         = gen_rtx_INSN_LIST (VOIDmode, insn,
-                              reg_equiv_init[REGNO (SET_SRC (set))]);
-
-      if (INSN_P (insn))
-       scan_paradoxical_subregs (PATTERN (insn));
     }
 
+  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_elim_table ();
 
   first_label_num = get_first_label_num ();
@@ -842,8 +827,7 @@ reload (rtx first, int global)
      main reload loop in the most common case where register elimination
      cannot be done.  */
   for (insn = first; insn && num_eliminable; insn = NEXT_INSN (insn))
-    if (GET_CODE (insn) == INSN || GET_CODE (insn) == JUMP_INSN
-       || GET_CODE (insn) == CALL_INSN)
+    if (INSN_P (insn))
       note_stores (PATTERN (insn), mark_not_eliminable, NULL);
 
   maybe_fix_stack_asms ();
@@ -986,6 +970,13 @@ reload (rtx first, int global)
       if (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 
+        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 ())
+       something_changed = 1;
+
       {
        HARD_REG_SET to_spill;
        CLEAR_HARD_REG_SET (to_spill);
@@ -1053,17 +1044,13 @@ reload (rtx first, int global)
                 if an insn has a variable address, gets a REG_EH_REGION
                 note added to it, and then gets converted into an load
                 from a constant address.  */
-             if (GET_CODE (equiv_insn) == NOTE
+             if (NOTE_P (equiv_insn)
                  || can_throw_internal (equiv_insn))
                ;
              else if (reg_set_p (regno_reg_rtx[i], PATTERN (equiv_insn)))
                delete_dead_insn (equiv_insn);
              else
-               {
-                 PUT_CODE (equiv_insn, NOTE);
-                 NOTE_SOURCE_FILE (equiv_insn) = 0;
-                 NOTE_LINE_NUMBER (equiv_insn) = NOTE_INSN_DELETED;
-               }
+               SET_INSN_DELETED (equiv_insn);
            }
        }
     }
@@ -1079,11 +1066,9 @@ reload (rtx first, int global)
 
       reload_as_needed (global);
 
-      if (old_frame_size != get_frame_size ())
-       abort ();
+      gcc_assert (old_frame_size == get_frame_size ());
 
-      if (num_eliminable)
-       verify_initial_elim_offsets ();
+      gcc_assert (verify_initial_elim_offsets ());
     }
 
   /* If we were able to eliminate the frame pointer, show that it is no
@@ -1097,8 +1082,8 @@ reload (rtx first, int global)
       CLEAR_REGNO_REG_SET (bb->global_live_at_start,
                           HARD_FRAME_POINTER_REGNUM);
 
-  /* Come here (with failure set nonzero) if we can't get enough spill regs
-     and we decide not to abort about it.  */
+  /* Come here (with failure set nonzero) if we can't get enough spill
+     regs.  */
  failed:
 
   CLEAR_REG_SET (&spilled_pseudos);
@@ -1137,8 +1122,7 @@ reload (rtx first, int global)
                MEM_COPY_ATTRIBUTES (reg, reg_equiv_memory_loc[i]);
              else
                {
-                 RTX_UNCHANGING_P (reg) = MEM_IN_STRUCT_P (reg)
-                   = MEM_SCALAR_P (reg) = 0;
+                 MEM_IN_STRUCT_P (reg) = MEM_SCALAR_P (reg) = 0;
                  MEM_ATTRS (reg) = 0;
                }
            }
@@ -1166,7 +1150,7 @@ reload (rtx first, int global)
       {
        rtx *pnote;
 
-       if (GET_CODE (insn) == CALL_INSN)
+       if (CALL_P (insn))
          replace_pseudos_in (& CALL_INSN_FUNCTION_USAGE (insn),
                              VOIDmode, CALL_INSN_FUNCTION_USAGE (insn));
 
@@ -1175,7 +1159,7 @@ reload (rtx first, int global)
             && (GET_MODE (insn) == QImode
                 || find_reg_note (insn, REG_EQUAL, NULL_RTX)))
            || (GET_CODE (PATTERN (insn)) == CLOBBER
-               && (GET_CODE (XEXP (PATTERN (insn), 0)) != MEM
+               && (!MEM_P (XEXP (PATTERN (insn), 0))
                    || GET_MODE (XEXP (PATTERN (insn), 0)) != BLKmode
                    || (GET_CODE (XEXP (XEXP (PATTERN (insn), 0), 0)) != SCRATCH
                        && XEXP (XEXP (PATTERN (insn), 0), 0)
@@ -1194,6 +1178,19 @@ reload (rtx first, int global)
          replace_pseudos_in (& XEXP (PATTERN (insn), 0),
                              VOIDmode, PATTERN (insn));
 
+       /* Discard obvious no-ops, even without -O.  This optimization
+          is fast and doesn't interfere with debugging.  */
+       if (NONJUMP_INSN_P (insn)
+           && GET_CODE (PATTERN (insn)) == SET
+           && REG_P (SET_SRC (PATTERN (insn)))
+           && REG_P (SET_DEST (PATTERN (insn)))
+           && (REGNO (SET_SRC (PATTERN (insn)))
+               == REGNO (SET_DEST (PATTERN (insn)))))
+         {
+           delete_insn (insn);
+           continue;
+         }
+
        pnote = &REG_NOTES (insn);
        while (*pnote != 0)
          {
@@ -1228,10 +1225,10 @@ reload (rtx first, int global)
 
       if (size > STACK_CHECK_MAX_FRAME_SIZE)
        {
-         warning ("frame size too large for reliable stack checking");
+         warning (0, "frame size too large for reliable stack checking");
          if (! verbose_warned)
            {
-             warning ("try reducing the number of local variables");
+             warning (0, "try reducing the number of local variables");
              verbose_warned = 1;
            }
        }
@@ -1250,7 +1247,7 @@ reload (rtx first, int global)
     free (offsets_at);
 
   free (reg_equiv_mem);
-  free (reg_equiv_init);
+  reg_equiv_init = 0;
   free (reg_equiv_address);
   free (reg_max_ref_width);
   free (reg_old_renumber);
@@ -1440,7 +1437,7 @@ calculate_needs_all_insns (int global)
         include REG_LABEL), we need to see what effects this has on the
         known offsets at labels.  */
 
-      if (GET_CODE (insn) == CODE_LABEL || GET_CODE (insn) == JUMP_INSN
+      if (LABEL_P (insn) || JUMP_P (insn)
          || (INSN_P (insn) && REG_NOTES (insn) != 0))
        set_label_offsets (insn, insn, 0);
 
@@ -1585,8 +1582,7 @@ count_pseudo (int reg)
 
   SET_REGNO_REG_SET (&pseudos_counted, reg);
 
-  if (r < 0)
-    abort ();
+  gcc_assert (r >= 0);
 
   spill_add_cost[r] += freq;
 
@@ -1601,9 +1597,10 @@ count_pseudo (int reg)
 static void
 order_regs_for_reload (struct insn_chain *chain)
 {
-  int i;
+  unsigned i;
   HARD_REG_SET used_by_pseudos;
   HARD_REG_SET used_by_pseudos2;
+  reg_set_iterator rsi;
 
   COPY_HARD_REG_SET (bad_spill_regs, fixed_reg_set);
 
@@ -1624,15 +1621,15 @@ order_regs_for_reload (struct insn_chain *chain)
   CLEAR_REG_SET (&pseudos_counted);
 
   EXECUTE_IF_SET_IN_REG_SET
-    (&chain->live_throughout, FIRST_PSEUDO_REGISTER, i,
-     {
-       count_pseudo (i);
-     });
+    (&chain->live_throughout, FIRST_PSEUDO_REGISTER, i, rsi)
+    {
+      count_pseudo (i);
+    }
   EXECUTE_IF_SET_IN_REG_SET
-    (&chain->dead_or_set, FIRST_PSEUDO_REGISTER, i,
-     {
-       count_pseudo (i);
-     });
+    (&chain->dead_or_set, FIRST_PSEUDO_REGISTER, i, rsi)
+    {
+      count_pseudo (i);
+    }
   CLEAR_REG_SET (&pseudos_counted);
 }
 \f
@@ -1678,6 +1675,7 @@ find_reg (struct insn_chain *chain, int order)
   int k;
   HARD_REG_SET not_usable;
   HARD_REG_SET used_by_other_reload;
+  reg_set_iterator rsi;
 
   COPY_HARD_REG_SET (not_usable, bad_spill_regs);
   IOR_HARD_REG_SET (not_usable, bad_spill_regs_global);
@@ -1746,22 +1744,21 @@ find_reg (struct insn_chain *chain, int order)
   rl->regno = best_reg;
 
   EXECUTE_IF_SET_IN_REG_SET
-    (&chain->live_throughout, FIRST_PSEUDO_REGISTER, j,
-     {
-       count_spilled_pseudo (best_reg, rl->nregs, j);
-     });
+    (&chain->live_throughout, FIRST_PSEUDO_REGISTER, j, rsi)
+    {
+      count_spilled_pseudo (best_reg, rl->nregs, j);
+    }
 
   EXECUTE_IF_SET_IN_REG_SET
-    (&chain->dead_or_set, FIRST_PSEUDO_REGISTER, j,
-     {
-       count_spilled_pseudo (best_reg, rl->nregs, j);
-     });
+    (&chain->dead_or_set, FIRST_PSEUDO_REGISTER, j, rsi)
+    {
+      count_spilled_pseudo (best_reg, rl->nregs, j);
+    }
 
   for (i = 0; i < rl->nregs; i++)
     {
-      if (spill_cost[best_reg + i] != 0
-         || spill_add_cost[best_reg + i] != 0)
-       abort ();
+      gcc_assert (spill_cost[best_reg + i] == 0);
+      gcc_assert (spill_add_cost[best_reg + i] == 0);
       SET_HARD_REG_BIT (used_spill_regs_local, best_reg + i);
     }
   return 1;
@@ -1881,13 +1878,13 @@ delete_caller_save_insns (void)
 static void
 spill_failure (rtx insn, enum reg_class class)
 {
-  static const char *const reg_class_names[] = REG_CLASS_NAMES;
   if (asm_noperands (PATTERN (insn)) >= 0)
-    error_for_asm (insn, "can't find a register in class `%s' while reloading `asm'",
+    error_for_asm (insn, "can't find a register in class %qs while "
+                  "reloading %<asm%>",
                   reg_class_names[class]);
   else
     {
-      error ("unable to find a register to spill in class `%s'",
+      error ("unable to find a register to spill in class %qs",
             reg_class_names[class]);
       fatal_insn ("this is the insn:", insn);
     }
@@ -1911,9 +1908,7 @@ delete_dead_insn (rtx insn)
       && ! side_effects_p (SET_SRC (PATTERN (prev))))
     delete_dead_insn (prev);
 
-  PUT_CODE (insn, NOTE);
-  NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
-  NOTE_SOURCE_FILE (insn) = 0;
+  SET_INSN_DELETED (insn);
 }
 
 /* Modify the home of pseudo-reg I.
@@ -1975,8 +1970,6 @@ alter_reg (int i, int from_reg)
               below.  */
            adjust = inherent_size - total_size;
 
-         RTX_UNCHANGING_P (x) = RTX_UNCHANGING_P (regno_reg_rtx[i]);
-
          /* Nothing can alias this slot except this pseudo.  */
          set_mem_alias_set (x, new_alias_set ());
        }
@@ -2047,7 +2040,7 @@ alter_reg (int i, int from_reg)
       /* If we have a decl for the original register, set it for the
         memory.  If this is a shared MEM, make a copy.  */
       if (REG_EXPR (regno_reg_rtx[i])
-         && TREE_CODE_CLASS (TREE_CODE (REG_EXPR (regno_reg_rtx[i]))) == 'd')
+         && DECL_P (REG_EXPR (regno_reg_rtx[i])))
        {
          rtx decl = DECL_RTL_IF_SET (REG_EXPR (regno_reg_rtx[i]));
 
@@ -2136,7 +2129,7 @@ set_label_offsets (rtx x, rtx insn, int initial_p)
 
       else if (x == insn
               && (tem = prev_nonnote_insn (insn)) != 0
-              && GET_CODE (tem) == BARRIER)
+              && BARRIER_P (tem))
        set_offsets_for_label (insn);
       else
        /* If neither of the above cases is true, compare each offset
@@ -2200,7 +2193,7 @@ set_label_offsets (rtx x, rtx insn, int initial_p)
          return;
 
        case LABEL_REF:
-         set_label_offsets (XEXP (SET_SRC (x), 0), insn, initial_p);
+         set_label_offsets (SET_SRC (x), insn, initial_p);
          return;
 
        case IF_THEN_ELSE:
@@ -2288,15 +2281,6 @@ eliminate_regs (rtx x, enum machine_mode mem_mode, rtx insn)
     case RETURN:
       return x;
 
-    case ADDRESSOF:
-      /* This is only for the benefit of the debugging backends, which call
-        eliminate_regs on DECL_RTL; any ADDRESSOFs in the actual insns are
-        removed after CSE.  */
-      new = eliminate_regs (XEXP (x, 0), 0, insn);
-      if (GET_CODE (new) == MEM)
-       return XEXP (new, 0);
-      return x;
-
     case REG:
       regno = REGNO (x);
 
@@ -2535,7 +2519,7 @@ eliminate_regs (rtx x, enum machine_mode mem_mode, rtx insn)
          int x_size = GET_MODE_SIZE (GET_MODE (x));
          int new_size = GET_MODE_SIZE (GET_MODE (new));
 
-         if (GET_CODE (new) == MEM
+         if (MEM_P (new)
              && ((x_size < new_size
 #ifdef WORD_REGISTER_OPERATIONS
                   /* On these machines, combine can create rtl of the form
@@ -2559,12 +2543,6 @@ eliminate_regs (rtx x, enum machine_mode mem_mode, rtx insn)
       return x;
 
     case MEM:
-      /* This is only for the benefit of the debugging backends, which call
-        eliminate_regs on DECL_RTL; any ADDRESSOFs in the actual insns are
-        removed after CSE.  */
-      if (GET_CODE (XEXP (x, 0)) == ADDRESSOF)
-       return eliminate_regs (XEXP (XEXP (x, 0), 0), 0, 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.  */
@@ -2583,7 +2561,7 @@ eliminate_regs (rtx x, enum machine_mode mem_mode, rtx insn)
     case CLOBBER:
     case ASM_OPERANDS:
     case SET:
-      abort ();
+      gcc_unreachable ();
 
     default:
       break;
@@ -2663,9 +2641,6 @@ elimination_effects (rtx x, enum machine_mode mem_mode)
     case RETURN:
       return;
 
-    case ADDRESSOF:
-      abort ();
-
     case REG:
       regno = REGNO (x);
 
@@ -2808,9 +2783,6 @@ elimination_effects (rtx x, enum machine_mode mem_mode)
       return;
 
     case MEM:
-      if (GET_CODE (XEXP (x, 0)) == ADDRESSOF)
-       abort ();
-
       /* Our only special processing is to pass the mode of the MEM to our
         recursive call.  */
       elimination_effects (XEXP (x, 0), GET_MODE (x));
@@ -2901,13 +2873,12 @@ eliminate_regs_in_insn (rtx insn, int replace)
 
   if (! insn_is_asm && icode < 0)
     {
-      if (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)
-       return 0;
-      abort ();
+      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);
+      return 0;
     }
 
   if (old_set != 0 && REG_P (SET_DEST (old_set))
@@ -3061,8 +3032,7 @@ eliminate_regs_in_insn (rtx insn, int replace)
                    PATTERN (insn) = gen_rtx_PARALLEL (VOIDmode, vec);
                    add_clobbers (PATTERN (insn), INSN_CODE (insn));
                  }
-               if (INSN_CODE (insn) < 0)
-                 abort ();
+               gcc_assert (INSN_CODE (insn) >= 0);
              }
            /* If we have a nonzero offset, and the source is already
               a simple REG, the following transformation would
@@ -3134,7 +3104,7 @@ eliminate_regs_in_insn (rtx insn, int replace)
           insn, write a CLOBBER insn.  */
          if (recog_data.operand_type[i] != OP_IN
              && REG_P (orig_operand[i])
-             && GET_CODE (substed_operand[i]) == MEM
+             && MEM_P (substed_operand[i])
              && replace)
            emit_insn_after (gen_rtx_CLOBBER (VOIDmode, orig_operand[i]),
                             insn);
@@ -3195,9 +3165,9 @@ eliminate_regs_in_insn (rtx insn, int replace)
                 the MEM in recog_data.operand to the one in the insn.
                 If they are not equal, then rerecognize the insn.  */
              || (old_set != 0
-                 && ((GET_CODE (SET_SRC (old_set)) == MEM
+                 && ((MEM_P (SET_SRC (old_set))
                       && SET_SRC (old_set) != recog_data.operand[1])
-                     || (GET_CODE (SET_DEST (old_set)) == MEM
+                     || (MEM_P (SET_DEST (old_set))
                          && SET_DEST (old_set) != recog_data.operand[0])))
              /* If this was an add insn before, rerecognize.  */
              || GET_CODE (SET_SRC (old_set)) == PLUS))
@@ -3322,25 +3292,32 @@ mark_not_eliminable (rtx dest, rtx x, void *data ATTRIBUTE_UNUSED)
    where something illegal happened during reload_as_needed that could
    cause incorrect code to be generated if we did not check for it.  */
 
-static void
+static bool
 verify_initial_elim_offsets (void)
 {
   HOST_WIDE_INT t;
 
+  if (!num_eliminable)
+    return true;
+
 #ifdef ELIMINABLE_REGS
-  struct elim_table *ep;
+  {
+   struct elim_table *ep;
 
-  for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
-    {
-      INITIAL_ELIMINATION_OFFSET (ep->from, ep->to, t);
-      if (t != ep->initial_offset)
-       abort ();
-    }
+   for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
+     {
+       INITIAL_ELIMINATION_OFFSET (ep->from, ep->to, t);
+       if (t != ep->initial_offset)
+        return false;
+     }
+  }
 #else
   INITIAL_FRAME_POINTER_OFFSET (t);
   if (t != reg_eliminate[0].initial_offset)
-    abort ();
+    return false;
 #endif
+
+  return true;
 }
 
 /* Reset all offsets on eliminable registers to their initial values.  */
@@ -3364,6 +3341,14 @@ set_initial_elim_offsets (void)
   num_not_at_initial_offset = 0;
 }
 
+/* Subroutine of set_initial_label_offsets called via for_each_eh_label.  */
+
+static void
+set_initial_eh_label_offset (rtx label)
+{
+  set_label_offsets (label, NULL_RTX, 1);
+}
+
 /* Initialize the known label offsets.
    Set a known offset for each forced label to be at the initial offset
    of each elimination.  We do this because we assume that all
@@ -3380,6 +3365,8 @@ set_initial_label_offsets (void)
   for (x = forced_labels; x; x = XEXP (x, 1))
     if (XEXP (x, 0))
       set_label_offsets (XEXP (x, 0), NULL_RTX, 1);
+
+  for_each_eh_label (set_initial_eh_label_offset);
 }
 
 /* Set all elimination offsets to the known values for the code label given
@@ -3572,15 +3559,6 @@ spill_hard_reg (unsigned int regno, int cant_eliminate)
       SET_REGNO_REG_SET (&spilled_pseudos, i);
 }
 
-/* I'm getting weird preprocessor errors if I use IOR_HARD_REG_SET
-   from within EXECUTE_IF_SET_IN_REG_SET.  Hence this awkwardness.  */
-
-static void
-ior_hard_reg_set (HARD_REG_SET *set1, HARD_REG_SET *set2)
-{
-  IOR_HARD_REG_SET (*set1, *set2);
-}
-
 /* After find_reload_regs has been run for all insn that need reloads,
    and/or spill_hard_regs was called, this function is used to actually
    spill pseudo registers and try to reallocate them.  It also sets up the
@@ -3591,7 +3569,8 @@ finish_spills (int global)
 {
   struct insn_chain *chain;
   int something_changed = 0;
-  int i;
+  unsigned i;
+  reg_set_iterator rsi;
 
   /* Build the spill_regs array for the function.  */
   /* If there are some registers still to eliminate and one of the spill regs
@@ -3618,21 +3597,19 @@ finish_spills (int global)
     else
       spill_reg_order[i] = -1;
 
-  EXECUTE_IF_SET_IN_REG_SET
-    (&spilled_pseudos, FIRST_PSEUDO_REGISTER, i,
-     {
-       /* 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.  */
-       if (reg_renumber[i] < 0)
-        abort ();
-
-       SET_HARD_REG_BIT (pseudo_previous_regs[i], reg_renumber[i]);
-       /* Mark it as no longer having a hard register home.  */
-       reg_renumber[i] = -1;
-       /* We will need to scan everything again.  */
-       something_changed = 1;
-     });
+  EXECUTE_IF_SET_IN_REG_SET (&spilled_pseudos, FIRST_PSEUDO_REGISTER, i, rsi)
+    {
+      /* Record the current hard register the pseudo is allocated to in
+        pseudo_previous_regs so we avoid reallocating it to the same
+        hard reg in a later pass.  */
+      gcc_assert (reg_renumber[i] >= 0);
+
+      SET_HARD_REG_BIT (pseudo_previous_regs[i], reg_renumber[i]);
+      /* Mark it as no longer having a hard register home.  */
+      reg_renumber[i] = -1;
+      /* We will need to scan everything again.  */
+      something_changed = 1;
+    }
 
   /* Retry global register allocation if possible.  */
   if (global)
@@ -3644,17 +3621,17 @@ finish_spills (int global)
       for (chain = insns_need_reload; chain; chain = chain->next_need_reload)
        {
          EXECUTE_IF_SET_IN_REG_SET
-           (&chain->live_throughout, FIRST_PSEUDO_REGISTER, i,
-            {
-              ior_hard_reg_set (pseudo_forbidden_regs + i,
-                                &chain->used_spill_regs);
-            });
+           (&chain->live_throughout, FIRST_PSEUDO_REGISTER, i, rsi)
+           {
+             IOR_HARD_REG_SET (pseudo_forbidden_regs[i],
+                               chain->used_spill_regs);
+           }
          EXECUTE_IF_SET_IN_REG_SET
-           (&chain->dead_or_set, FIRST_PSEUDO_REGISTER, i,
-            {
-              ior_hard_reg_set (pseudo_forbidden_regs + i,
-                                &chain->used_spill_regs);
-            });
+           (&chain->dead_or_set, FIRST_PSEUDO_REGISTER, i, rsi)
+           {
+             IOR_HARD_REG_SET (pseudo_forbidden_regs[i],
+                               chain->used_spill_regs);
+           }
        }
 
       /* Retry allocating the spilled pseudos.  For each reg, merge the
@@ -3662,7 +3639,7 @@ finish_spills (int global)
         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 < max_regno; i++)
+      for (i = FIRST_PSEUDO_REGISTER; i < (unsigned)max_regno; i++)
        if (reg_old_renumber[i] != reg_renumber[i])
          {
            HARD_REG_SET forbidden;
@@ -3704,13 +3681,13 @@ finish_spills (int global)
 
          /* Make sure we only enlarge the set.  */
          GO_IF_HARD_REG_SUBSET (used_by_pseudos2, chain->used_spill_regs, ok);
-         abort ();
+         gcc_unreachable ();
        ok:;
        }
     }
 
   /* Let alter_reg modify the reg rtx's for the modified pseudos.  */
-  for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
+  for (i = FIRST_PSEUDO_REGISTER; i < (unsigned)max_regno; i++)
     {
       int regno = reg_renumber[i];
       if (reg_old_renumber[i] == regno)
@@ -3815,7 +3792,7 @@ reload_as_needed (int live_known)
 
       /* If we pass a label, copy the offsets from the label information
         into the current offsets of each elimination.  */
-      if (GET_CODE (insn) == CODE_LABEL)
+      if (LABEL_P (insn))
        set_offsets_for_label (insn);
 
       else if (INSN_P (insn))
@@ -3827,7 +3804,7 @@ reload_as_needed (int live_known)
 
          if ((GET_CODE (PATTERN (insn)) == USE
               || GET_CODE (PATTERN (insn)) == CLOBBER)
-             && GET_CODE (XEXP (PATTERN (insn), 0)) == MEM)
+             && MEM_P (XEXP (PATTERN (insn), 0)))
            XEXP (XEXP (PATTERN (insn), 0), 0)
              = eliminate_regs (XEXP (XEXP (PATTERN (insn), 0), 0),
                                GET_MODE (XEXP (PATTERN (insn), 0)),
@@ -3838,7 +3815,7 @@ reload_as_needed (int live_known)
          if ((num_eliminable || num_eliminable_invariants) && chain->need_elim)
            {
              eliminate_regs_in_insn (insn, 1);
-             if (GET_CODE (insn) == NOTE)
+             if (NOTE_P (insn))
                {
                  update_eliminable_offsets ();
                  continue;
@@ -3909,7 +3886,8 @@ reload_as_needed (int live_known)
                          || (extract_insn (p), ! constrain_operands (1))))
                    {
                      error_for_asm (insn,
-                                    "`asm' operand requires impossible reload");
+                                    "%<asm%> operand requires "
+                                    "impossible reload");
                      delete_insn (p);
                    }
            }
@@ -3928,7 +3906,7 @@ reload_as_needed (int live_known)
          /* There may have been CLOBBER insns placed after INSN.  So scan
             between INSN and NEXT and use them to forget old reloads.  */
          for (x = NEXT_INSN (insn); x != old_next; x = NEXT_INSN (x))
-           if (GET_CODE (x) == INSN && GET_CODE (PATTERN (x)) == CLOBBER)
+           if (NONJUMP_INSN_P (x) && GET_CODE (PATTERN (x)) == CLOBBER)
              note_stores (PATTERN (x), forget_old_reloads_1, NULL);
 
 #ifdef AUTO_INC_DEC
@@ -4049,13 +4027,13 @@ reload_as_needed (int live_known)
 #endif
        }
       /* A reload reg's contents are unknown after a label.  */
-      if (GET_CODE (insn) == CODE_LABEL)
+      if (LABEL_P (insn))
        CLEAR_HARD_REG_SET (reg_reloaded_valid);
 
       /* Don't assume a reload reg is still good after a call insn
         if it is a call-used reg, or if it contains a value that will
          be partially clobbered by the call.  */
-      else if (GET_CODE (insn) == CALL_INSN)
+      else if (CALL_P (insn))
        {
        AND_COMPL_HARD_REG_SET (reg_reloaded_valid, call_used_reg_set);
        AND_COMPL_HARD_REG_SET (reg_reloaded_valid, reg_reloaded_call_part_clobbered);
@@ -4082,7 +4060,7 @@ forget_old_reloads_1 (rtx x, rtx ignored ATTRIBUTE_UNUSED,
   unsigned int nr;
 
   /* note_stores does give us subregs of hard regs,
-     subreg_regno_offset will abort if it is not a hard reg.  */
+     subreg_regno_offset requires a hard reg.  */
   while (GET_CODE (x) == SUBREG)
     {
       /* We ignore the subreg offset when calculating the regno,
@@ -4299,7 +4277,7 @@ clear_reload_reg_in_use (unsigned int regno, int opnum,
       used_in_set = &reload_reg_used_in_insn;
       break;
     default:
-      abort ();
+      gcc_unreachable ();
     }
   /* We resolve conflicts with remaining reloads of the same type by
      excluding the intervals of reload registers by them from the
@@ -4495,8 +4473,10 @@ reload_reg_free_p (unsigned int regno, int opnum, enum reload_type type)
 
     case RELOAD_FOR_OTHER_ADDRESS:
       return ! TEST_HARD_REG_BIT (reload_reg_used_in_other_addr, regno);
+
+    default:
+      gcc_unreachable ();
     }
-  abort ();
 }
 
 /* Return 1 if the value in reload reg REGNO, as used by a reload
@@ -4628,9 +4608,10 @@ reload_reg_reaches_end_p (unsigned int regno, int opnum, enum reload_type type)
          return 0;
 
       return 1;
-    }
 
-  abort ();
+    default:
+      gcc_unreachable ();
+    }
 }
 \f
 /* Return 1 if the reloads denoted by R1 and R2 cannot share a register.
@@ -4638,7 +4619,7 @@ reload_reg_reaches_end_p (unsigned int regno, int opnum, enum reload_type type)
 
    This function uses the same algorithm as reload_reg_free_p above.  */
 
-int
+static int
 reloads_conflict (int r1, int r2)
 {
   enum reload_type r1_type = rld[r1].when_needed;
@@ -4705,25 +4686,25 @@ reloads_conflict (int r1, int r2)
       return 1;
 
     default:
-      abort ();
+      gcc_unreachable ();
     }
 }
 \f
 /* Indexed by reload number, 1 if incoming value
    inherited from previous insns.  */
-char reload_inherited[MAX_RELOADS];
+static char reload_inherited[MAX_RELOADS];
 
 /* For an inherited reload, this is the insn the reload was inherited from,
    if we know it.  Otherwise, this is 0.  */
-rtx reload_inheritance_insn[MAX_RELOADS];
+static rtx reload_inheritance_insn[MAX_RELOADS];
 
 /* If nonzero, this is a place to get the value of the reload,
    rather than using reload_in.  */
-rtx reload_override_in[MAX_RELOADS];
+static rtx reload_override_in[MAX_RELOADS];
 
 /* For each reload, the hard register number of the register used,
    or -1 if we did not need a register for this reload.  */
-int reload_spill_index[MAX_RELOADS];
+static int reload_spill_index[MAX_RELOADS];
 
 /* Subroutine of free_for_value_p, used to check a single register.
    START_REGNO is the starting regno of the full reload register
@@ -4983,13 +4964,13 @@ free_for_value_p (int regno, enum machine_mode mode, int opnum,
 }
 
 /* Return nonzero if the rtx X is invariant over the current function.  */
-/* ??? Actually, the places where we use this expect exactly what
* is tested here, and not everything that is function invariant.  In
* particular, the frame pointer and arg pointer are special cased;
- * pic_offset_table_rtx is not, and this will cause aborts when we
*             go to spill these things to memory.  */
+/* ??? Actually, the places where we use this expect exactly what is
  tested here, and not everything that is function invariant.  In
  particular, the frame pointer and arg pointer are special cased;
+   pic_offset_table_rtx is not, and we must not spill these things to
  memory.  */
 
-static int
+int
 function_invariant_p (rtx x)
 {
   if (CONSTANT_P (x))
@@ -5029,7 +5010,7 @@ failed_reload (rtx insn, int r)
   /* It's the user's fault; the operand's mode and constraint
      don't match.  Disable this reload so we don't crash in final.  */
   error_for_asm (insn,
-                "`asm' operand constraint incompatible with operand size");
+                "%<asm%> operand constraint incompatible with operand size");
   rld[r].in = 0;
   rld[r].out = 0;
   rld[r].reg_rtx = 0;
@@ -5360,7 +5341,7 @@ choose_reload_regs (struct insn_chain *chain)
          if (rld[r].in != 0 && rld[r].reg_rtx != 0
              && (rtx_equal_p (rld[r].in, rld[r].reg_rtx)
                  || (rtx_equal_p (rld[r].out, rld[r].reg_rtx)
-                     && GET_CODE (rld[r].in) != MEM
+                     && !MEM_P (rld[r].in)
                      && true_regnum (rld[r].in) < FIRST_PSEUDO_REGISTER)))
            continue;
 
@@ -5456,19 +5437,18 @@ choose_reload_regs (struct insn_chain *chain)
                    need_mode = mode;
                  else
                    need_mode
-                     = smallest_mode_for_size (GET_MODE_SIZE (mode) + byte,
+                     = smallest_mode_for_size (GET_MODE_BITSIZE (mode)
+                                               + byte * BITS_PER_UNIT,
                                                GET_MODE_CLASS (mode));
 
-                 if (
-#ifdef CANNOT_CHANGE_MODE_CLASS
-                     (!REG_CANNOT_CHANGE_MODE_P (i, GET_MODE (last_reg),
-                                                 need_mode)
-                      &&
-#endif
-                     (GET_MODE_SIZE (GET_MODE (last_reg))
+                 if ((GET_MODE_SIZE (GET_MODE (last_reg))
                       >= GET_MODE_SIZE (need_mode))
 #ifdef CANNOT_CHANGE_MODE_CLASS
-                     )
+                     /* Verify that the register in "i" can be obtained
+                        from LAST_REG.  */
+                     && !REG_CANNOT_CHANGE_MODE_P (REGNO (last_reg),
+                                                   GET_MODE (last_reg),
+                                                   mode)
 #endif
                      && reg_reloaded_contents[i] == regno
                      && TEST_HARD_REG_BIT (reg_reloaded_valid, i)
@@ -5598,7 +5578,7 @@ choose_reload_regs (struct insn_chain *chain)
              && (CONSTANT_P (rld[r].in)
                  || GET_CODE (rld[r].in) == PLUS
                  || REG_P (rld[r].in)
-                 || GET_CODE (rld[r].in) == MEM)
+                 || MEM_P (rld[r].in))
              && (rld[r].nregs == max_group_size
                  || ! reg_classes_intersect_p (rld[r].class, group_class)))
            search_equiv = rld[r].in;
@@ -5625,17 +5605,25 @@ choose_reload_regs (struct insn_chain *chain)
                {
                  if (REG_P (equiv))
                    regno = REGNO (equiv);
-                 else if (GET_CODE (equiv) == SUBREG)
+                 else
                    {
                      /* This must be a SUBREG of a hard register.
                         Make a new REG since this might be used in an
                         address and not all machines support SUBREGs
                         there.  */
+                     gcc_assert (GET_CODE (equiv) == SUBREG);
                      regno = subreg_regno (equiv);
                      equiv = gen_rtx_REG (rld[r].mode, regno);
+                     /* If we choose EQUIV as the reload register, but the
+                        loop below decides to cancel the inheritance, we'll
+                        end up reloading EQUIV in rld[r].mode, not the mode
+                        it had originally.  That isn't safe when EQUIV isn't
+                        available as a spill register since its value might
+                        still be live at this point.  */
+                     for (i = regno; i < regno + (int) rld[r].nregs; i++)
+                       if (TEST_HARD_REG_BIT (reload_reg_unavailable, i))
+                         equiv = 0;
                    }
-                 else
-                   abort ();
                }
 
              /* If we found a spill reg, reject it unless it is free
@@ -5839,15 +5827,13 @@ choose_reload_regs (struct insn_chain *chain)
 
       /* Some sanity tests to verify that the reloads found in the first
         pass are identical to the ones we have now.  */
-      if (chain->n_reloads != n_reloads)
-       abort ();
+      gcc_assert (chain->n_reloads == n_reloads);
 
       for (i = 0; i < n_reloads; i++)
        {
          if (chain->rld[i].regno < 0 || chain->rld[i].reg_rtx != 0)
            continue;
-         if (chain->rld[i].when_needed != rld[i].when_needed)
-           abort ();
+         gcc_assert (chain->rld[i].when_needed == rld[i].when_needed);
          for (j = 0; j < n_spills; j++)
            if (spill_regs[j] == chain->rld[i].regno)
              if (! set_reload_reg (j, i))
@@ -5960,10 +5946,9 @@ choose_reload_regs (struct insn_chain *chain)
                SET_HARD_REG_BIT (reg_is_output_reload, i + nr);
            }
 
-         if (rld[r].when_needed != RELOAD_OTHER
-             && rld[r].when_needed != RELOAD_FOR_OUTPUT
-             && rld[r].when_needed != RELOAD_FOR_INSN)
-           abort ();
+         gcc_assert (rld[r].when_needed == RELOAD_OTHER
+                     || rld[r].when_needed == RELOAD_FOR_OUTPUT
+                     || rld[r].when_needed == RELOAD_FOR_INSN);
        }
     }
 }
@@ -6103,17 +6088,18 @@ merge_assigned_reloads (rtx insn)
                        || 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,
-                    so abort.  */
+                 /* 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++)
-                     if (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))
-                       abort ();
+                     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));
                }
        }
     }
@@ -6211,7 +6197,7 @@ emit_input_reload_insns (struct insn_chain *chain, struct reload *rl,
      because we will use this equiv reg right away.  */
 
   if (oldequiv == 0 && optimize
-      && (GET_CODE (old) == MEM
+      && (MEM_P (old)
          || (REG_P (old)
              && REGNO (old) >= FIRST_PSEUDO_REGISTER
              && reg_renumber[REGNO (old)] < 0)))
@@ -6327,7 +6313,7 @@ emit_input_reload_insns (struct insn_chain *chain, struct reload *rl,
       where = &other_input_address_reload_insns;
       break;
     default:
-      abort ();
+      gcc_unreachable ();
     }
 
   push_to_sequence (*where);
@@ -6338,8 +6324,7 @@ emit_input_reload_insns (struct insn_chain *chain, struct reload *rl,
       /* We are not going to bother supporting the case where a
         incremented register can't be copied directly from
         OLDEQUIV since this seems highly unlikely.  */
-      if (rl->secondary_in_reload >= 0)
-       abort ();
+      gcc_assert (rl->secondary_in_reload < 0);
 
       if (reload_inherited[j])
        oldequiv = reloadreg;
@@ -6378,10 +6363,10 @@ 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 && GET_CODE (temp) == NOTE)
+      while (temp && NOTE_P (temp))
        temp = PREV_INSN (temp);
       if (temp
-         && GET_CODE (temp) == INSN
+         && NONJUMP_INSN_P (temp)
          && GET_CODE (PATTERN (temp)) == SET
          && SET_DEST (PATTERN (temp)) == old
          /* Make sure we can access insn_operand_constraint.  */
@@ -6652,7 +6637,7 @@ emit_output_reload_insns (struct insn_chain *chain, struct reload *rl,
       if (asm_noperands (PATTERN (insn)) < 0)
        /* It's the compiler's fault.  */
        fatal_insn ("VOIDmode on an output", insn);
-      error_for_asm (insn, "output operand is constant in `asm'");
+      error_for_asm (insn, "output operand is constant in %<asm%>");
       /* Prevent crash--use something we know is valid.  */
       mode = word_mode;
       old = gen_rtx_REG (mode, REGNO (reloadreg));
@@ -6753,7 +6738,8 @@ emit_output_reload_insns (struct insn_chain *chain, struct reload *rl,
          || !(set = single_set (insn))
          || rtx_equal_p (old, SET_DEST (set))
          || !reg_mentioned_p (old, SET_SRC (set))
-         || !regno_clobbered_p (REGNO (old), insn, rl->mode, 0))
+         || !((REGNO (old) < FIRST_PSEUDO_REGISTER)
+              && regno_clobbered_p (REGNO (old), insn, rl->mode, 0)))
        gen_reload (old, reloadreg, rl->opnum,
                    rl->when_needed);
     }
@@ -6843,7 +6829,7 @@ static void
 do_input_reload (struct insn_chain *chain, struct reload *rl, int j)
 {
   rtx insn = chain->insn;
-  rtx old = (rl->in && GET_CODE (rl->in) == MEM
+  rtx old = (rl->in && MEM_P (rl->in)
             ? rl->in_reg : rl->in);
 
   if (old != 0
@@ -6858,8 +6844,8 @@ do_input_reload (struct insn_chain *chain, struct reload *rl, int j)
      e.g. inheriting a SImode output reload for
      (mem:HI (plus:SI (reg:SI 14 fp) (const_int 10)))  */
   if (optimize && reload_inherited[j] && rl->in
-      && GET_CODE (rl->in) == MEM
-      && GET_CODE (rl->in_reg) == MEM
+      && MEM_P (rl->in)
+      && MEM_P (rl->in_reg)
       && reload_spill_index[j] >= 0
       && TEST_HARD_REG_BIT (reg_reloaded_valid, reload_spill_index[j]))
     rl->in = regno_reg_rtx[reg_reloaded_contents[reload_spill_index[j]]];
@@ -6869,6 +6855,10 @@ do_input_reload (struct insn_chain *chain, struct reload *rl, int j)
      actually no need to store the old value in it.  */
 
   if (optimize
+      /* Only attempt this for input reloads; for RELOAD_OTHER we miss
+        that there may be multiple uses of the previous output reload.
+        Restricting to RELOAD_FOR_INPUT is mostly paranoia.  */
+      && rl->when_needed == RELOAD_FOR_INPUT
       && (reload_inherited[j] || reload_override_in[j])
       && rl->reg_rtx
       && REG_P (rl->reg_rtx)
@@ -6955,8 +6945,7 @@ do_output_reload (struct insn_chain *chain, struct reload *rl, int j)
     return;
 
   /* If is a JUMP_INSN, we can't support output reloads yet.  */
-  if (GET_CODE (insn) == JUMP_INSN)
-    abort ();
+  gcc_assert (!JUMP_P (insn));
 
   emit_output_reload_insns (chain, rld + j, j);
 }
@@ -7050,25 +7039,25 @@ emit_reload_insns (struct insn_chain *chain)
      reloads for the operand.  The RELOAD_OTHER output reloads are
      output in descending order by reload number.  */
 
-  emit_insn_before_sameloc (other_input_address_reload_insns, insn);
-  emit_insn_before_sameloc (other_input_reload_insns, insn);
+  emit_insn_before (other_input_address_reload_insns, insn);
+  emit_insn_before (other_input_reload_insns, insn);
 
   for (j = 0; j < reload_n_operands; j++)
     {
-      emit_insn_before_sameloc (inpaddr_address_reload_insns[j], insn);
-      emit_insn_before_sameloc (input_address_reload_insns[j], insn);
-      emit_insn_before_sameloc (input_reload_insns[j], insn);
+      emit_insn_before (inpaddr_address_reload_insns[j], insn);
+      emit_insn_before (input_address_reload_insns[j], insn);
+      emit_insn_before (input_reload_insns[j], insn);
     }
 
-  emit_insn_before_sameloc (other_operand_reload_insns, insn);
-  emit_insn_before_sameloc (operand_reload_insns, insn);
+  emit_insn_before (other_operand_reload_insns, insn);
+  emit_insn_before (operand_reload_insns, insn);
 
   for (j = 0; j < reload_n_operands; j++)
     {
-      rtx x = emit_insn_after_sameloc (outaddr_address_reload_insns[j], insn);
-      x = emit_insn_after_sameloc (output_address_reload_insns[j], x);
-      x = emit_insn_after_sameloc (output_reload_insns[j], x);
-      emit_insn_after_sameloc (other_output_reload_insns[j], x);
+      rtx x = emit_insn_after (outaddr_address_reload_insns[j], insn);
+      x = emit_insn_after (output_address_reload_insns[j], x);
+      x = emit_insn_after (output_reload_insns[j], x);
+      emit_insn_after (other_output_reload_insns[j], x);
     }
 
   /* For all the spill regs newly reloaded in this instruction,
@@ -7289,7 +7278,7 @@ emit_reload_insns (struct insn_chain *chain)
         it thinks only about the original insn.  So invalidate it here.  */
       if (i < 0 && rld[r].out != 0
          && (REG_P (rld[r].out)
-             || (GET_CODE (rld[r].out) == MEM
+             || (MEM_P (rld[r].out)
                  && REG_P (rld[r].out_reg))))
        {
          rtx out = (REG_P (rld[r].out)
@@ -7384,7 +7373,7 @@ emit_reload_insns (struct insn_chain *chain)
 
    Returns first insn emitted.  */
 
-rtx
+static rtx
 gen_reload (rtx out, rtx in, int opnum, enum reload_type type)
 {
   rtx last = get_last_insn ();
@@ -7432,11 +7421,11 @@ gen_reload (rtx out, rtx in, int opnum, enum reload_type type)
   if (GET_CODE (in) == PLUS
       && (REG_P (XEXP (in, 0))
          || GET_CODE (XEXP (in, 0)) == SUBREG
-         || GET_CODE (XEXP (in, 0)) == MEM)
+         || MEM_P (XEXP (in, 0)))
       && (REG_P (XEXP (in, 1))
          || GET_CODE (XEXP (in, 1)) == SUBREG
          || CONSTANT_P (XEXP (in, 1))
-         || GET_CODE (XEXP (in, 1)) == MEM))
+         || MEM_P (XEXP (in, 1))))
     {
       /* We need to compute the sum of a register or a MEM and another
         register, constant, or MEM, and put it into the reload
@@ -7503,7 +7492,7 @@ gen_reload (rtx out, rtx in, int opnum, enum reload_type type)
 
       code = (int) add_optab->handlers[(int) GET_MODE (out)].insn_code;
 
-      if (CONSTANT_P (op1) || GET_CODE (op1) == MEM || GET_CODE (op1) == SUBREG
+      if (CONSTANT_P (op1) || MEM_P (op1) || GET_CODE (op1) == SUBREG
          || (REG_P (op1)
              && REGNO (op1) >= FIRST_PSEUDO_REGISTER)
          || (code != CODE_FOR_nothing
@@ -7633,7 +7622,7 @@ delete_output_reload (rtx insn, int j, int last_reload_reg)
       rtx reg2 = rld[k].in;
       if (! reg2)
        continue;
-      if (GET_CODE (reg2) == MEM || reload_override_in[k])
+      if (MEM_P (reg2) || reload_override_in[k])
        reg2 = rld[k].in_reg;
 #ifdef AUTO_INC_DEC
       if (rld[k].out && ! rld[k].out_reg)
@@ -7668,20 +7657,20 @@ delete_output_reload (rtx insn, int j, int last_reload_reg)
 
   /* If the pseudo-reg we are reloading is no longer referenced
      anywhere between the store into it and here,
-     and no jumps or labels intervene, then the value can get
-     here through the reload reg alone.
+     and we're within the same basic block, then the value can only
+     pass through the reload reg and end up here.
      Otherwise, give up--return.  */
   for (i1 = NEXT_INSN (output_reload_insn);
        i1 != insn; i1 = NEXT_INSN (i1))
     {
-      if (GET_CODE (i1) == CODE_LABEL || GET_CODE (i1) == JUMP_INSN)
+      if (NOTE_INSN_BASIC_BLOCK_P (i1))
        return;
-      if ((GET_CODE (i1) == INSN || GET_CODE (i1) == CALL_INSN)
+      if ((NONJUMP_INSN_P (i1) || CALL_P (i1))
          && reg_mentioned_p (reg, PATTERN (i1)))
        {
          /* If this is USE in front of INSN, we only have to check that
             there are no more references than accounted for by inheritance.  */
-         while (GET_CODE (i1) == INSN && GET_CODE (PATTERN (i1)) == USE)
+         while (NONJUMP_INSN_P (i1) && GET_CODE (PATTERN (i1)) == USE)
            {
              n_occurrences += rtx_equal_p (reg, XEXP (PATTERN (i1), 0)) != 0;
              i1 = NEXT_INSN (i1);
@@ -7727,10 +7716,10 @@ delete_output_reload (rtx insn, int j, int last_reload_reg)
             since if they are the only uses, they are dead.  */
          if (set != 0 && SET_DEST (set) == reg)
            continue;
-         if (GET_CODE (i2) == CODE_LABEL
-             || GET_CODE (i2) == JUMP_INSN)
+         if (LABEL_P (i2)
+             || JUMP_P (i2))
            break;
-         if ((GET_CODE (i2) == INSN || GET_CODE (i2) == CALL_INSN)
+         if ((NONJUMP_INSN_P (i2) || CALL_P (i2))
              && reg_mentioned_p (reg, PATTERN (i2)))
            {
              /* Some other ref remains; just delete the output reload we
@@ -7752,8 +7741,8 @@ delete_output_reload (rtx insn, int j, int last_reload_reg)
              delete_address_reloads (i2, insn);
              delete_insn (i2);
            }
-         if (GET_CODE (i2) == CODE_LABEL
-             || GET_CODE (i2) == JUMP_INSN)
+         if (LABEL_P (i2)
+             || JUMP_P (i2))
            break;
        }
 
@@ -7779,7 +7768,7 @@ delete_address_reloads (rtx dead_insn, rtx current_insn)
   if (set)
     {
       rtx dst = SET_DEST (set);
-      if (GET_CODE (dst) == MEM)
+      if (MEM_P (dst))
        delete_address_reloads_1 (dead_insn, XEXP (dst, 0), current_insn);
     }
   /* If we deleted the store from a reloaded post_{in,de}c expression,
@@ -7864,7 +7853,7 @@ delete_address_reloads_1 (rtx dead_insn, rtx x, rtx current_insn)
         it might have been inherited.  */
       for (i2 = NEXT_INSN (dead_insn); i2; i2 = NEXT_INSN (i2))
        {
-         if (GET_CODE (i2) == CODE_LABEL)
+         if (LABEL_P (i2))
            break;
          if (! INSN_P (i2))
            continue;
@@ -7888,7 +7877,7 @@ delete_address_reloads_1 (rtx dead_insn, rtx x, rtx current_insn)
                }
              return;
            }
-         if (GET_CODE (i2) == JUMP_INSN)
+         if (JUMP_P (i2))
            break;
          /* If DST is still live at CURRENT_INSN, check if it is used for
             any reload.  Note that even if CURRENT_INSN sets DST, we still
@@ -8075,10 +8064,11 @@ fixup_abnormal_edges (void)
   FOR_EACH_BB (bb)
     {
       edge e;
+      edge_iterator ei;
 
       /* Look for cases we are interested in - calls or instructions causing
          exceptions.  */
-      for (e = bb->succ; e; e = e->succ_next)
+      FOR_EACH_EDGE (e, ei, bb->succs)
        {
          if (e->flags & EDGE_ABNORMAL_CALL)
            break;
@@ -8086,22 +8076,21 @@ fixup_abnormal_edges (void)
              == (EDGE_ABNORMAL | EDGE_EH))
            break;
        }
-      if (e && GET_CODE (BB_END (bb)) != CALL_INSN
+      if (e && !CALL_P (BB_END (bb))
          && !can_throw_internal (BB_END (bb)))
        {
          rtx insn = BB_END (bb), stop = NEXT_INSN (BB_END (bb));
          rtx next;
-         for (e = bb->succ; e; e = e->succ_next)
+         FOR_EACH_EDGE (e, ei, bb->succs)
            if (e->flags & EDGE_FALLTHRU)
              break;
          /* Get past the new insns generated. Allow notes, as the insns may
             be already deleted.  */
-         while ((GET_CODE (insn) == INSN || GET_CODE (insn) == NOTE)
+         while ((NONJUMP_INSN_P (insn) || NOTE_P (insn))
                 && !can_throw_internal (insn)
                 && insn != BB_HEAD (bb))
            insn = PREV_INSN (insn);
-         if (GET_CODE (insn) != CALL_INSN && !can_throw_internal (insn))
-           abort ();
+         gcc_assert (CALL_P (insn) || can_throw_internal (insn));
          BB_END (bb) = insn;
          inserted = true;
          insn = NEXT_INSN (insn);