OSDN Git Service

* config/xtensa/xtensa.c (xtensa_init_machine_status): Fix
[pf3gnuchains/gcc-fork.git] / gcc / reload1.c
index 1f20a48..1ce3199 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 Free Software Foundation, Inc.
+   1999, 2000, 2001, 2002 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -41,6 +41,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "real.h"
 #include "toplev.h"
 #include "except.h"
+#include "tree.h"
 
 /* This file contains the reload pass of the compiler, which is
    run after register allocation has been done.  It checks that
@@ -323,10 +324,10 @@ static struct elim_table *reg_eliminate = 0;
 
 /* This is an intermediate structure to initialize the table.  It has
    exactly the members provided by ELIMINABLE_REGS.  */
-static struct elim_table_1
+static const struct elim_table_1
 {
-  int from;
-  int to;
+  const int from;
+  const int to;
 } reg_eliminate_1[] =
 
 /* If a set of eliminable registers was specified, define the table from it.
@@ -366,9 +367,9 @@ static int (*offsets_at)[NUM_ELIMINABLE_REGS];
 
 static int num_labels;
 \f
-static void replace_pseudos_in_call_usage      PARAMS((rtx *,
-                                                       enum machine_mode,
-                                                       rtx));
+static void replace_pseudos_in_call_usage      PARAMS ((rtx *,
+                                                        enum machine_mode,
+                                                        rtx));
 static void maybe_fix_stack_asms       PARAMS ((void));
 static void copy_reloads               PARAMS ((struct insn_chain *));
 static void calculate_needs_all_insns  PARAMS ((int));
@@ -439,7 +440,6 @@ static void delete_output_reload    PARAMS ((rtx, int, int));
 static void delete_address_reloads     PARAMS ((rtx, rtx));
 static void delete_address_reloads_1   PARAMS ((rtx, rtx, rtx));
 static rtx inc_for_reload              PARAMS ((rtx, rtx, rtx, int));
-static int constraint_accepts_reg_p    PARAMS ((const char *, rtx));
 static void reload_cse_regs_1          PARAMS ((rtx));
 static int reload_cse_noop_set_p       PARAMS ((rtx));
 static int reload_cse_simplify_set     PARAMS ((rtx, rtx));
@@ -457,9 +457,8 @@ static HOST_WIDE_INT sext_for_mode  PARAMS ((enum machine_mode,
                                                 HOST_WIDE_INT));
 static void failed_reload              PARAMS ((rtx, int));
 static int set_reload_reg              PARAMS ((int, int));
-static void reload_cse_delete_noop_set PARAMS ((rtx, rtx));
 static void reload_cse_simplify                PARAMS ((rtx));
-static void fixup_abnormal_edges       PARAMS ((void));
+void fixup_abnormal_edges              PARAMS ((void));
 extern void dump_needs                 PARAMS ((struct insn_chain *));
 \f
 /* Initialize the reload pass once per compilation.  */
@@ -675,6 +674,7 @@ reload (first, global)
   int i;
   rtx insn;
   struct elim_table *ep;
+  basic_block bb;
 
   /* The two pointers used to track the true location of the memory used
      for label offsets.  */
@@ -790,7 +790,12 @@ reload (first, global)
              i = REGNO (SET_DEST (set));
              if (i > LAST_VIRTUAL_REGISTER)
                {
-                 if (GET_CODE (x) == MEM)
+                 /* 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
@@ -1117,8 +1122,8 @@ reload (first, global)
      pseudo.  */
 
   if (! frame_pointer_needed)
-    for (i = 0; i < n_basic_blocks; i++)
-      CLEAR_REGNO_REG_SET (BASIC_BLOCK (i)->global_live_at_start,
+    FOR_EACH_BB (bb)
+      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
@@ -1154,9 +1159,9 @@ reload (first, global)
            {
              rtx reg = regno_reg_rtx[i];
 
+             REG_USERVAR_P (reg) = 0;
              PUT_CODE (reg, MEM);
              XEXP (reg, 0) = addr;
-             REG_USERVAR_P (reg) = 0;
              if (reg_equiv_memory_loc[i])
                MEM_COPY_ATTRIBUTES (reg, reg_equiv_memory_loc[i]);
              else
@@ -1278,6 +1283,11 @@ reload (first, global)
   unused_insn_chains = 0;
   fixup_abnormal_edges ();
 
+  /* Replacing pseudos with their memory equivalents might have
+     created shared rtx.  Subsequent passes would get confused
+     by this, so unshare everything here.  */
+  unshare_all_rtl_again (first);
+
   return failure;
 }
 
@@ -1363,7 +1373,8 @@ maybe_fix_stack_asms ()
                  break;
 
                case 'p':
-                 cls = (int) reg_class_subunion[cls][(int) BASE_REG_CLASS];
+                 cls = (int) reg_class_subunion[cls]
+                   [(int) MODE_BASE_REG_CLASS (VOIDmode)];
                  break;
 
                case 'g':
@@ -1888,13 +1899,13 @@ spill_failure (insn, 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 `%s' 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 `%s'",
             reg_class_names[class]);
-      fatal_insn ("This is the insn:", insn);
+      fatal_insn ("this is the insn:", insn);
     }
 }
 \f
@@ -2056,10 +2067,19 @@ alter_reg (i, from_reg)
         memory.  If this is a shared MEM, make a copy.  */
       if (REGNO_DECL (i))
        {
-         if (from_reg != -1 && spill_stack_slot[from_reg] == x)
-           x = copy_rtx (x);
+         rtx decl = DECL_RTL_IF_SET (REGNO_DECL (i));
+
+         /* We can do this only for the DECLs home pseudo, not for
+            any copies of it, since otherwise when the stack slot
+            is reused, nonoverlapping_memrefs_p might think they
+            cannot overlap.  */
+         if (decl && GET_CODE (decl) == REG && REGNO (decl) == (unsigned) i)
+           {
+             if (from_reg != -1 && spill_stack_slot[from_reg] == x)
+               x = copy_rtx (x);
 
-         set_mem_decl (x, REGNO_DECL (i));
+             set_mem_expr (x, REGNO_DECL (i));
+           }
        }
 
       /* Save the stack slot for later.  */
@@ -2281,6 +2301,7 @@ eliminate_regs (x, mem_mode, insn)
     {
     case CONST_INT:
     case CONST_DOUBLE:
+    case CONST_VECTOR:
     case CONST:
     case SYMBOL_REF:
     case CODE_LABEL:
@@ -2551,14 +2572,7 @@ eliminate_regs (x, mem_mode, insn)
                   )
                  || x_size == new_size)
              )
-           {
-             int offset = SUBREG_BYTE (x);
-             enum machine_mode mode = GET_MODE (x);
-
-             PUT_MODE (new, mode);
-             XEXP (new, 0) = plus_constant (XEXP (new, 0), offset);
-             return new;
-           }
+           return adjust_address_nv (new, GET_MODE (x), SUBREG_BYTE (x));
          else
            return gen_rtx_SUBREG (GET_MODE (x), new, SUBREG_BYTE (x));
        }
@@ -2666,6 +2680,7 @@ elimination_effects (x, mem_mode)
     {
     case CONST_INT:
     case CONST_DOUBLE:
+    case CONST_VECTOR:
     case CONST:
     case SYMBOL_REF:
     case CODE_LABEL:
@@ -2938,38 +2953,32 @@ eliminate_regs_in_insn (insn, replace)
            if (ep->from == FRAME_POINTER_REGNUM
                && ep->to == HARD_FRAME_POINTER_REGNUM)
              {
-               rtx src = SET_SRC (old_set);
-               int offset = 0, ok = 0;
-               rtx prev_insn, prev_set;
-
-               if (src == ep->to_rtx)
-                 offset = 0, ok = 1;
-               else if (GET_CODE (src) == PLUS
-                        && GET_CODE (XEXP (src, 0)) == CONST_INT
-                        && XEXP (src, 1) == ep->to_rtx)
-                 offset = INTVAL (XEXP (src, 0)), ok = 1;
-               else if (GET_CODE (src) == PLUS
-                        && GET_CODE (XEXP (src, 1)) == CONST_INT
-                        && XEXP (src, 0) == ep->to_rtx)
-                 offset = INTVAL (XEXP (src, 1)), ok = 1;
-               else if ((prev_insn = prev_nonnote_insn (insn)) != 0
-                        && (prev_set = single_set (prev_insn)) != 0
-                        && rtx_equal_p (SET_DEST (prev_set), src))
+               rtx base = SET_SRC (old_set);
+               rtx base_insn = insn;
+               int offset = 0;
+
+               while (base != ep->to_rtx)
                  {
-                   src = SET_SRC (prev_set);
-                   if (src == ep->to_rtx)
-                     offset = 0, ok = 1;
-                   else if (GET_CODE (src) == PLUS
-                            && GET_CODE (XEXP (src, 0)) == CONST_INT
-                            && XEXP (src, 1) == ep->to_rtx)
-                     offset = INTVAL (XEXP (src, 0)), ok = 1;
-                   else if (GET_CODE (src) == PLUS
-                            && GET_CODE (XEXP (src, 1)) == CONST_INT
-                            && XEXP (src, 0) == ep->to_rtx)
-                     offset = INTVAL (XEXP (src, 1)), ok = 1;
+                   rtx prev_insn, prev_set;
+
+                   if (GET_CODE (base) == PLUS
+                       && GET_CODE (XEXP (base, 1)) == CONST_INT)
+                     {
+                       offset += INTVAL (XEXP (base, 1));
+                       base = XEXP (base, 0);
+                     }
+                   else if ((prev_insn = prev_nonnote_insn (base_insn)) != 0
+                            && (prev_set = single_set (prev_insn)) != 0
+                            && rtx_equal_p (SET_DEST (prev_set), base))
+                     {
+                       base = SET_SRC (prev_set);
+                       base_insn = prev_insn;
+                     }
+                   else
+                     break;
                  }
 
-               if (ok)
+               if (base == ep->to_rtx)
                  {
                    rtx src
                      = plus_constant (ep->to_rtx, offset - ep->offset);
@@ -3485,7 +3494,7 @@ init_elim_table ()
 {
   struct elim_table *ep;
 #ifdef ELIMINABLE_REGS
-  struct elim_table_1 *ep1;
+  const struct elim_table_1 *ep1;
 #endif
 
   if (!reg_eliminate)
@@ -3761,6 +3770,7 @@ scan_paradoxical_subregs (x)
     case SYMBOL_REF:
     case LABEL_REF:
     case CONST_DOUBLE:
+    case CONST_VECTOR: /* shouldn't happen, but just in case.  */
     case CC0:
     case PC:
     case USE:
@@ -4064,7 +4074,7 @@ reload_as_needed (live_known)
       /* Don't assume a reload reg is still good after a call insn
         if it is a call-used reg.  */
       else if (GET_CODE (insn) == CALL_INSN)
-       AND_COMPL_HARD_REG_SET(reg_reloaded_valid, call_used_reg_set);
+       AND_COMPL_HARD_REG_SET (reg_reloaded_valid, call_used_reg_set);
     }
 
   /* Clean up.  */
@@ -4087,23 +4097,21 @@ forget_old_reloads_1 (x, ignored, data)
 {
   unsigned int regno;
   unsigned int nr;
-  int offset = 0;
 
   /* note_stores does give us subregs of hard regs,
      subreg_regno_offset will abort if it is not a hard reg.  */
   while (GET_CODE (x) == SUBREG)
     {
-      offset += subreg_regno_offset (REGNO (SUBREG_REG (x)),
-                                    GET_MODE (SUBREG_REG (x)),
-                                    SUBREG_BYTE (x),
-                                    GET_MODE (x));
+      /* We ignore the subreg offset when calculating the regno,
+        because we are using the entire underlying hard register
+        below.  */
       x = SUBREG_REG (x);
     }
 
   if (GET_CODE (x) != REG)
     return;
 
-  regno = REGNO (x) + offset;
+  regno = REGNO (x);
 
   if (regno >= FIRST_PSEUDO_REGISTER)
     nr = 1;
@@ -4319,7 +4327,7 @@ clear_reload_reg_in_use (regno, opnum, type, mode)
      excluding the intervals of of reload registers by them from the
      interval of freed reload registers.  Since we only keep track of
      one set of interval bounds, we might have to exclude somewhat
-     more then what would be necessary if we used a HARD_REG_SET here.
+     more than what would be necessary if we used a HARD_REG_SET here.
      But this should only happen very infrequently, so there should
      be no reason to worry about it.  */
 
@@ -4841,7 +4849,7 @@ reload_reg_free_for_value_p (start_regno, regno, opnum, type, value, out,
       rtx reg = rld[i].reg_rtx;
       if (reg && GET_CODE (reg) == REG
          && ((unsigned) regno - true_regnum (reg)
-             <= HARD_REGNO_NREGS (REGNO (reg), GET_MODE (reg)) - (unsigned)1)
+             <= HARD_REGNO_NREGS (REGNO (reg), GET_MODE (reg)) - (unsigned) 1)
          && i != reloadnum)
        {
          rtx other_input = rld[i].in;
@@ -5036,7 +5044,7 @@ failed_reload (insn, r)
 {
   if (asm_noperands (PATTERN (insn)) < 0)
     /* It's the compiler's fault.  */
-    fatal_insn ("Could not find a spill register", insn);
+    fatal_insn ("could not find a spill register", insn);
 
   /* 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.  */
@@ -5323,7 +5331,7 @@ choose_reload_regs (chain)
        {
          max_group_size = MAX (rld[j].nregs, max_group_size);
          group_class
-           = reg_class_superunion[(int) rld[j].class][(int)group_class];
+           = reg_class_superunion[(int) rld[j].class][(int) group_class];
        }
 
       save_reload_reg_rtx[j] = rld[j].reg_rtx;
@@ -5564,6 +5572,7 @@ choose_reload_regs (chain)
                                  && ! TEST_HARD_REG_BIT (reg_reloaded_dead, i))
                              /* Don't clobber the frame pointer.  */
                              || (i == HARD_FRAME_POINTER_REGNUM
+                                 && frame_pointer_needed
                                  && rld[r].out)
                              /* Don't really use the inherited spill reg
                                 if we need it wider than we've got it.  */
@@ -5734,7 +5743,9 @@ choose_reload_regs (chain)
 
              /* If we found an equivalent reg, say no code need be generated
                 to load it, and use it as our reload reg.  */
-             if (equiv != 0 && regno != HARD_FRAME_POINTER_REGNUM)
+             if (equiv != 0
+                 && (regno != HARD_FRAME_POINTER_REGNUM
+                     || !frame_pointer_needed))
                {
                  int nr = HARD_REGNO_NREGS (regno, rld[r].mode);
                  int k;
@@ -6370,38 +6381,43 @@ emit_input_reload_insns (chain, rl, old, j)
          && SET_DEST (PATTERN (temp)) == old
          /* Make sure we can access insn_operand_constraint.  */
          && asm_noperands (PATTERN (temp)) < 0
-         /* This is unsafe if prev insn rejects our reload reg.  */
-         && constraint_accepts_reg_p (insn_data[recog_memoized (temp)].operand[0].constraint,
-                                      reloadreg)
          /* This is unsafe if operand occurs more than once in current
             insn.  Perhaps some occurrences aren't reloaded.  */
-         && count_occurrences (PATTERN (insn), old, 0) == 1
-         /* Don't risk splitting a matching pair of operands.  */
-         && ! reg_mentioned_p (old, SET_SRC (PATTERN (temp))))
+         && count_occurrences (PATTERN (insn), old, 0) == 1)
        {
+         rtx old = SET_DEST (PATTERN (temp));
          /* Store into the reload register instead of the pseudo.  */
          SET_DEST (PATTERN (temp)) = reloadreg;
 
-         /* If the previous insn is an output reload, the source is
-            a reload register, and its spill_reg_store entry will
-            contain the previous destination.  This is now
-            invalid.  */
-         if (GET_CODE (SET_SRC (PATTERN (temp))) == REG
-             && REGNO (SET_SRC (PATTERN (temp))) < FIRST_PSEUDO_REGISTER)
+         /* Verify that resulting insn is valid.  */
+         extract_insn (temp);
+         if (constrain_operands (1))
            {
-             spill_reg_store[REGNO (SET_SRC (PATTERN (temp)))] = 0;
-             spill_reg_stored_to[REGNO (SET_SRC (PATTERN (temp)))] = 0;
-           }
+             /* If the previous insn is an output reload, the source is
+                a reload register, and its spill_reg_store entry will
+                contain the previous destination.  This is now
+                invalid.  */
+             if (GET_CODE (SET_SRC (PATTERN (temp))) == REG
+                 && REGNO (SET_SRC (PATTERN (temp))) < FIRST_PSEUDO_REGISTER)
+               {
+                 spill_reg_store[REGNO (SET_SRC (PATTERN (temp)))] = 0;
+                 spill_reg_stored_to[REGNO (SET_SRC (PATTERN (temp)))] = 0;
+               }
 
-         /* If these are the only uses of the pseudo reg,
-            pretend for GDB it lives in the reload reg we used.  */
-         if (REG_N_DEATHS (REGNO (old)) == 1
-             && REG_N_SETS (REGNO (old)) == 1)
+             /* If these are the only uses of the pseudo reg,
+                pretend for GDB it lives in the reload reg we used.  */
+             if (REG_N_DEATHS (REGNO (old)) == 1
+                 && REG_N_SETS (REGNO (old)) == 1)
+               {
+                 reg_renumber[REGNO (old)] = REGNO (rl->reg_rtx);
+                 alter_reg (REGNO (old), -1);
+               }
+             special = 1;
+           }
+         else
            {
-             reg_renumber[REGNO (old)] = REGNO (rl->reg_rtx);
-             alter_reg (REGNO (old), -1);
+             SET_DEST (PATTERN (temp)) = old;
            }
-         special = 1;
        }
     }
 
@@ -6597,7 +6613,7 @@ emit_input_reload_insns (chain, rl, old, j)
   /* End this sequence.  */
   *where = get_insns ();
   end_sequence ();
-                                
+
   /* Update reload_override_in so that delete_address_reloads_1
      can see the actual register usage.  */
   if (oldequiv_reg)
@@ -6897,6 +6913,7 @@ do_output_reload (chain, rl, j)
   rtx pseudo = rl->out_reg;
 
   if (pseudo
+      && optimize
       && GET_CODE (pseudo) == REG
       && ! rtx_equal_p (rl->in_reg, pseudo)
       && REGNO (pseudo) >= FIRST_PSEUDO_REGISTER
@@ -7543,9 +7560,8 @@ gen_reload (out, in, opnum, type)
   return last ? NEXT_INSN (last) : get_insns ();
 }
 \f
-/* Delete a previously made output-reload
-   whose result we now believe is not needed.
-   First we double-check.
+/* Delete a previously made output-reload whose result we now believe
+   is not needed.  First we double-check.
 
    INSN is the insn now being processed.
    LAST_RELOAD_REG is the hard register number for which we want to delete
@@ -7639,15 +7655,21 @@ delete_output_reload (insn, j, last_reload_reg)
        }
     }
 
+  /* We will be deleting the insn.  Remove the spill reg information.  */
+  for (k = HARD_REGNO_NREGS (last_reload_reg, GET_MODE (reg)); k-- > 0; )
+    {
+      spill_reg_store[last_reload_reg + k] = 0;
+      spill_reg_stored_to[last_reload_reg + k] = 0;
+    }
+
   /* The caller has already checked that REG dies or is set in INSN.
-     It has also checked that we are optimizing, and thus some inaccurancies
-     in the debugging information are acceptable.
-     So we could just delete output_reload_insn.
-     But in some cases we can improve the debugging information without
-     sacrificing optimization - maybe even improving the code:
-     See if the pseudo reg has been completely replaced
-     with reload regs.  If so, delete the store insn
-     and forget we had a stack slot for the pseudo.  */
+     It has also checked that we are optimizing, and thus some
+     inaccurancies in the debugging information are acceptable.
+     So we could just delete output_reload_insn.  But in some cases
+     we can improve the debugging information without sacrificing
+     optimization - maybe even improving the code: See if the pseudo
+     reg has been completely replaced with reload regs.  If so, delete
+     the store insn and forget we had a stack slot for the pseudo.  */
   if (rld[j].out != rld[j].in
       && REG_N_DEATHS (REGNO (reg)) == 1
       && REG_N_SETS (REGNO (reg)) == 1
@@ -7656,11 +7678,10 @@ delete_output_reload (insn, j, last_reload_reg)
     {
       rtx i2;
 
-      /* We know that it was used only between here
-        and the beginning of the current basic block.
-        (We also know that the last use before INSN was
-        the output reload we are thinking of deleting, but never mind that.)
-        Search that range; see if any ref remains.  */
+      /* We know that it was used only between here and the beginning of
+        the current basic block.  (We also know that the last use before
+        INSN was the output reload we are thinking of deleting, but never
+        mind that.)  Search that range; see if any ref remains.  */
       for (i2 = PREV_INSN (insn); i2; i2 = PREV_INSN (i2))
        {
          rtx set = single_set (i2);
@@ -7683,7 +7704,8 @@ delete_output_reload (insn, j, last_reload_reg)
            }
        }
 
-      /* Delete the now-dead stores into this pseudo.  */
+      /* Delete the now-dead stores into this pseudo.  Note that this
+        loop also takes care of deleting output_reload_insn.  */
       for (i2 = PREV_INSN (insn); i2; i2 = PREV_INSN (i2))
        {
          rtx set = single_set (i2);
@@ -7691,8 +7713,6 @@ delete_output_reload (insn, j, last_reload_reg)
          if (set != 0 && SET_DEST (set) == reg)
            {
              delete_address_reloads (i2, insn);
-             /* This might be a basic block head,
-                thus don't use delete_insn.  */
              delete_insn (i2);
            }
          if (GET_CODE (i2) == CODE_LABEL
@@ -7700,14 +7720,15 @@ delete_output_reload (insn, j, last_reload_reg)
            break;
        }
 
-      /* For the debugging info,
-        say the pseudo lives in this reload reg.  */
+      /* For the debugging info, say the pseudo lives in this reload reg.  */
       reg_renumber[REGNO (reg)] = REGNO (rld[j].reg_rtx);
       alter_reg (REGNO (reg), -1);
     }
-  delete_address_reloads (output_reload_insn, insn);
-  delete_insn (output_reload_insn);
-
+  else
+    {
+      delete_address_reloads (output_reload_insn, insn);
+      delete_insn (output_reload_insn);
+    }
 }
 
 /* We are going to delete DEAD_INSN.  Recursively delete loads of
@@ -7962,72 +7983,6 @@ inc_for_reload (reloadreg, in, value, inc_amount)
   return store;
 }
 \f
-/* Return 1 if we are certain that the constraint-string STRING allows
-   the hard register REG.  Return 0 if we can't be sure of this.  */
-
-static int
-constraint_accepts_reg_p (string, reg)
-     const char *string;
-     rtx reg;
-{
-  int value = 0;
-  int regno = true_regnum (reg);
-  int c;
-
-  /* Initialize for first alternative.  */
-  value = 0;
-  /* Check that each alternative contains `g' or `r'.  */
-  while (1)
-    switch (c = *string++)
-      {
-      case 0:
-       /* If an alternative lacks `g' or `r', we lose.  */
-       return value;
-      case ',':
-       /* If an alternative lacks `g' or `r', we lose.  */
-       if (value == 0)
-         return 0;
-       /* Initialize for next alternative.  */
-       value = 0;
-       break;
-      case 'g':
-      case 'r':
-       /* Any general reg wins for this alternative.  */
-       if (TEST_HARD_REG_BIT (reg_class_contents[(int) GENERAL_REGS], regno))
-         value = 1;
-       break;
-      default:
-       /* Any reg in specified class wins for this alternative.  */
-       {
-         enum reg_class class = REG_CLASS_FROM_LETTER (c);
-
-         if (TEST_HARD_REG_BIT (reg_class_contents[(int) class], regno))
-           value = 1;
-       }
-      }
-}
-\f
-/* INSN is a no-op; delete it.
-   If this sets the return value of the function, we must keep a USE around,
-   in case this is in a different basic block than the final USE.  Otherwise,
-   we could loose important register lifeness information on
-   SMALL_REGISTER_CLASSES machines, where return registers might be used as
-   spills:  subsequent passes assume that spill registers are dead at the end
-   of a basic block.
-   VALUE must be the return value in such a case, NULL otherwise.  */
-static void
-reload_cse_delete_noop_set (insn, value)
-     rtx insn, value;
-{
-  if (value)
-    {
-      PATTERN (insn) = gen_rtx_USE (VOIDmode, value);
-      INSN_CODE (insn) = -1;
-      REG_NOTES (insn) = NULL_RTX;
-    }
-  else
-    delete_insn (insn);
-}
 
 /* See whether a single set SET is a noop.  */
 static int
@@ -8058,9 +8013,10 @@ reload_cse_simplify (insn)
       if (!count && reload_cse_noop_set_p (body))
        {
          rtx value = SET_DEST (body);
-         if (! REG_FUNCTION_VALUE_P (SET_DEST (body)))
+         if (REG_P (value)
+             && ! REG_FUNCTION_VALUE_P (value))
            value = 0;
-         reload_cse_delete_noop_set (insn, value);
+         delete_insn_and_edges (insn);
          return;
        }
 
@@ -8097,7 +8053,7 @@ reload_cse_simplify (insn)
 
       if (i < 0)
        {
-         reload_cse_delete_noop_set (insn, value);
+         delete_insn_and_edges (insn);
          /* We're done with this insn.  */
          return;
        }
@@ -8201,7 +8157,7 @@ reload_cse_simplify_set (set, insn)
 #ifdef LOAD_EXTEND_OP
   /* When replacing a memory with a register, we need to honor assumptions
      that combine made wrt the contents of sign bits.  We'll do this by
-     generating an extend instruction instead of a reg->reg copy.  Thus 
+     generating an extend instruction instead of a reg->reg copy.  Thus
      the destination must be a register that we can widen.  */
   if (GET_CODE (src) == MEM
       && GET_MODE_BITSIZE (GET_MODE (src)) < BITS_PER_WORD
@@ -8349,8 +8305,8 @@ reload_cse_simplify_operands (insn)
   alternative_reject = (int *) alloca (recog_data.n_alternatives * sizeof (int));
   alternative_nregs = (int *) alloca (recog_data.n_alternatives * sizeof (int));
   alternative_order = (int *) alloca (recog_data.n_alternatives * sizeof (int));
-  memset ((char *)alternative_reject, 0, recog_data.n_alternatives * sizeof (int));
-  memset ((char *)alternative_nregs, 0, recog_data.n_alternatives * sizeof (int));
+  memset ((char *) alternative_reject, 0, recog_data.n_alternatives * sizeof (int));
+  memset ((char *) alternative_nregs, 0, recog_data.n_alternatives * sizeof (int));
 
   /* For each operand, find out which regs are equivalent.  */
   for (i = 0; i < recog_data.n_operands; i++)
@@ -8453,7 +8409,7 @@ reload_cse_simplify_operands (insn)
 
                default:
                  class
-                   = reg_class_subunion[(int) class][(int) REG_CLASS_FROM_LETTER ((unsigned char)c)];
+                   = reg_class_subunion[(int) class][(int) REG_CLASS_FROM_LETTER ((unsigned char) c)];
                  break;
 
                case ',': case '\0':
@@ -8592,6 +8548,7 @@ reload_combine ()
   int first_index_reg = -1;
   int last_index_reg = 0;
   int i;
+  basic_block bb;
   unsigned int r;
   int last_label_ruid;
   int min_labelno, n_labels;
@@ -8627,17 +8584,17 @@ reload_combine ()
   label_live = (HARD_REG_SET *) xmalloc (n_labels * sizeof (HARD_REG_SET));
   CLEAR_HARD_REG_SET (ever_live_at_start);
 
-  for (i = n_basic_blocks - 1; i >= 0; i--)
+  FOR_EACH_BB_REVERSE (bb)
     {
-      insn = BLOCK_HEAD (i);
+      insn = bb->head;
       if (GET_CODE (insn) == CODE_LABEL)
        {
          HARD_REG_SET live;
 
          REG_SET_TO_HARD_REG_SET (live,
-                                  BASIC_BLOCK (i)->global_live_at_start);
+                                  bb->global_live_at_start);
          compute_use_by_pseudos (&live,
-                                 BASIC_BLOCK (i)->global_live_at_start);
+                                 bb->global_live_at_start);
          COPY_HARD_REG_SET (LABEL_LIVE (insn), live);
          IOR_HARD_REG_SET (ever_live_at_start, live);
        }
@@ -8771,7 +8728,9 @@ reload_combine ()
                   i < RELOAD_COMBINE_MAX_USES; i++)
                validate_change (reg_state[regno].reg_use[i].insn,
                                 reg_state[regno].reg_use[i].usep,
-                                reg_sum, 1);
+                                /* Each change must have its own
+                                   replacement.  */
+                                copy_rtx (reg_sum), 1);
 
              if (apply_change_group ())
                {
@@ -9364,7 +9323,7 @@ move2add_note_store (dst, set, data)
          reg_set_luid[regno] = move2add_last_label_luid + 1;
          reg_mode[regno] = mode;
          return;
-         
+
        default:
        invalidate:
          /* Invalidate the contents of the register.  */
@@ -9450,7 +9409,7 @@ copy_eh_notes (insn, x)
       for (; x != 0; x = NEXT_INSN (x))
        {
          if (may_trap_p (PATTERN (x)))
-           REG_NOTES (x) 
+           REG_NOTES (x)
              = gen_rtx_EXPR_LIST (REG_EH_REGION, XEXP (eh_note, 0),
                                   REG_NOTES (x));
        }
@@ -9461,17 +9420,16 @@ copy_eh_notes (insn, x)
    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
    proper call and fix the damage.
+
    Similar handle instructions throwing exceptions internally.  */
-static void
+void
 fixup_abnormal_edges ()
 {
-  int i;
   bool inserted = false;
+  basic_block bb;
 
-  for (i = 0; i < n_basic_blocks; i++)
+  FOR_EACH_BB (bb)
     {
-      basic_block bb = BASIC_BLOCK (i);
       edge e;
 
       /* Look for cases we are interested in - an calls or instructions causing
@@ -9507,8 +9465,19 @@ fixup_abnormal_edges ()
              next = NEXT_INSN (insn);
              if (INSN_P (insn))
                {
-                 insert_insn_on_edge (PATTERN (insn), e);
+                 rtx seq;
+
                  delete_insn (insn);
+
+                 /* We're not deleting it, we're moving it.  */
+                 INSN_DELETED_P (insn) = 0;
+
+                 /* Emit a sequence, rather than scarfing the pattern, so
+                    that we don't lose REG_NOTES etc.  */
+                 /* ??? Could copy the test from gen_sequence, but don't
+                    think it's worth the bother.  */
+                 seq = gen_rtx_SEQUENCE (VOIDmode, gen_rtvec (1, insn));
+                 insert_insn_on_edge (seq, e);
                }
              insn = next;
            }