OSDN Git Service

PR c++/10784
[pf3gnuchains/gcc-fork.git] / gcc / reload1.c
index 4fd401c..e1c470e 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 Free Software Foundation, Inc.
+   1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -39,7 +39,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "reload.h"
 #include "recog.h"
 #include "output.h"
-#include "cselib.h"
 #include "real.h"
 #include "toplev.h"
 #include "except.h"
@@ -79,10 +78,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
    fixing up each insn, and generating the new insns to copy values
    into the reload registers.  */
 
-#ifndef REGISTER_MOVE_COST
-#define REGISTER_MOVE_COST(m, x, y) 2
-#endif
-
 #ifndef LOCAL_REGNO
 #define LOCAL_REGNO(REGNO)  0
 #endif
@@ -354,11 +349,14 @@ static int num_eliminable_invariants;
 
 /* For each label, we record the offset of each elimination.  If we reach
    a label by more than one path and an offset differs, we cannot do the
-   elimination.  This information is indexed by the number of the label.
-   The first table is an array of flags that records whether we have yet
-   encountered a label and the second table is an array of arrays, one
-   entry in the latter array for each elimination.  */
-
+   elimination.  This information is indexed by the difference of the
+   number of the label and the first label number.  We can't offset the
+   pointer itself as this can cause problems on machines with segmented
+   memory.  The first table is an array of flags that records whether we
+   have yet encountered a label and the second table is an array of arrays,
+   one entry in the latter array for each elimination.  */
+
+static int first_label_num;
 static char *offsets_known_at;
 static int (*offsets_at)[NUM_ELIMINABLE_REGS];
 
@@ -366,9 +364,7 @@ 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 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));
@@ -401,7 +397,7 @@ static void count_pseudo            PARAMS ((int));
 static void order_regs_for_reload      PARAMS ((struct insn_chain *));
 static void reload_as_needed           PARAMS ((int));
 static void forget_old_reloads_1       PARAMS ((rtx, rtx, void *));
-static int reload_reg_class_lower      PARAMS ((const PTR, const PTR));
+static int reload_reg_class_lower      PARAMS ((const void *, const void *));
 static void mark_reload_reg_in_use     PARAMS ((unsigned int, int,
                                                 enum reload_type,
                                                 enum machine_mode));
@@ -439,25 +435,10 @@ 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 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));
-static int reload_cse_simplify_operands        PARAMS ((rtx, rtx));
-static void reload_combine             PARAMS ((void));
-static void reload_combine_note_use    PARAMS ((rtx *, rtx));
-static void reload_combine_note_store  PARAMS ((rtx, rtx, void *));
-static void reload_cse_move2add                PARAMS ((rtx));
-static void move2add_note_store                PARAMS ((rtx, rtx, void *));
 #ifdef AUTO_INC_DEC
 static void add_auto_inc_notes         PARAMS ((rtx, rtx));
 #endif
 static void copy_eh_notes              PARAMS ((rtx, rtx));
-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_simplify                PARAMS ((rtx, rtx));
-void fixup_abnormal_edges              PARAMS ((void));
 extern void dump_needs                 PARAMS ((struct insn_chain *));
 \f
 /* Initialize the reload pass once per compilation.  */
@@ -582,7 +563,7 @@ compute_use_by_pseudos (to, from)
    equivalences.  */
 
 static void
-replace_pseudos_in_call_usage (loc, mem_mode, usage)
+replace_pseudos_in (loc, mem_mode, usage)
      rtx *loc;
      enum machine_mode mem_mode;
      rtx usage;
@@ -607,7 +588,7 @@ replace_pseudos_in_call_usage (loc, mem_mode, usage)
       if (x != *loc)
        {
          *loc = x;
-         replace_pseudos_in_call_usage (loc, mem_mode, usage);
+         replace_pseudos_in (loc, mem_mode, usage);
          return;
        }
 
@@ -627,7 +608,7 @@ replace_pseudos_in_call_usage (loc, mem_mode, usage)
     }
   else if (code == MEM)
     {
-      replace_pseudos_in_call_usage (& XEXP (x, 0), GET_MODE (x), usage);
+      replace_pseudos_in (& XEXP (x, 0), GET_MODE (x), usage);
       return;
     }
 
@@ -635,10 +616,10 @@ replace_pseudos_in_call_usage (loc, mem_mode, usage)
   fmt = GET_RTX_FORMAT (code);
   for (i = 0; i < GET_RTX_LENGTH (code); i++, fmt++)
     if (*fmt == 'e')
-      replace_pseudos_in_call_usage (&XEXP (x, i), mem_mode, usage);
+      replace_pseudos_in (&XEXP (x, i), mem_mode, usage);
     else if (*fmt == 'E')
       for (j = 0; j < XVECLEN (x, i); j++)
-       replace_pseudos_in_call_usage (& XVECEXP (x, i, j), mem_mode, usage);
+       replace_pseudos_in (& XVECEXP (x, i, j), mem_mode, usage);
 }
 
 \f
@@ -675,11 +656,6 @@ reload (first, global)
   struct elim_table *ep;
   basic_block bb;
 
-  /* The two pointers used to track the true location of the memory used
-     for label offsets.  */
-  char *real_known_ptr = NULL;
-  int (*real_at_ptr)[NUM_ELIMINABLE_REGS];
-
   /* Make sure even insns with volatile mem refs are recognizable.  */
   init_recog ();
 
@@ -689,7 +665,7 @@ reload (first, global)
 
   /* Make sure that the last insn in the chain
      is not something that needs reloading.  */
-  emit_note (NULL, NOTE_INSN_DELETED);
+  emit_note (NOTE_INSN_DELETED);
 
   /* Enable find_equiv_reg to distinguish insns made by reload.  */
   reload_first_uid = get_max_uid ();
@@ -858,21 +834,18 @@ reload (first, global)
 
   init_elim_table ();
 
-  num_labels = max_label_num () - get_first_label_num ();
+  first_label_num = get_first_label_num ();
+  num_labels = max_label_num () - first_label_num;
 
   /* Allocate the tables used to store offset information at labels.  */
   /* We used to use alloca here, but the size of what it would try to
      allocate would occasionally cause it to exceed the stack limit and
      cause a core dump.  */
-  real_known_ptr = xmalloc (num_labels);
-  real_at_ptr
+  offsets_known_at = xmalloc (num_labels);
+  offsets_at
     = (int (*)[NUM_ELIMINABLE_REGS])
     xmalloc (num_labels * NUM_ELIMINABLE_REGS * sizeof (int));
 
-  offsets_known_at = real_known_ptr - get_first_label_num ();
-  offsets_at
-    = (int (*)[NUM_ELIMINABLE_REGS]) (real_at_ptr - get_first_label_num ());
-
   /* Alter each pseudo-reg rtx to contain its hard reg number.
      Assign stack slots to the pseudos that lack hard regs or equivalents.
      Do not touch virtual registers.  */
@@ -1199,9 +1172,8 @@ reload (first, global)
        rtx *pnote;
 
        if (GET_CODE (insn) == CALL_INSN)
-         replace_pseudos_in_call_usage (& CALL_INSN_FUNCTION_USAGE (insn),
-                                        VOIDmode,
-                                        CALL_INSN_FUNCTION_USAGE (insn));
+         replace_pseudos_in (& CALL_INSN_FUNCTION_USAGE (insn),
+                             VOIDmode, CALL_INSN_FUNCTION_USAGE (insn));
 
        if ((GET_CODE (PATTERN (insn)) == USE
             /* We mark with QImode USEs introduced by reload itself.  */
@@ -1220,6 +1192,13 @@ reload (first, global)
            continue;
          }
 
+       /* Some CLOBBERs may survive until here and still reference unassigned
+          pseudos with const equivalent, which may in turn cause ICE in later
+          passes if the reference remains in place.  */
+       if (GET_CODE (PATTERN (insn)) == CLOBBER)
+         replace_pseudos_in (& XEXP (PATTERN (insn), 0),
+                             VOIDmode, PATTERN (insn));
+
        pnote = &REG_NOTES (insn);
        while (*pnote != 0)
          {
@@ -1271,10 +1250,10 @@ reload (first, global)
     free (reg_equiv_memory_loc);
   reg_equiv_memory_loc = 0;
 
-  if (real_known_ptr)
-    free (real_known_ptr);
-  if (real_at_ptr)
-    free (real_at_ptr);
+  if (offsets_known_at)
+    free (offsets_known_at);
+  if (offsets_at)
+    free (offsets_at);
 
   free (reg_equiv_mem);
   free (reg_equiv_init);
@@ -1554,8 +1533,8 @@ calculate_needs_all_insns (global)
 
 static int
 reload_reg_class_lower (r1p, r2p)
-     const PTR r1p;
-     const PTR r2p;
+     const void *r1p;
+     const void *r2p;
 {
   int r1 = *(const short *) r1p, r2 = *(const short *) r2p;
   int t;
@@ -2081,9 +2060,10 @@ alter_reg (i, 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 (REGNO_DECL (i))
+      if (REG_EXPR (regno_reg_rtx[i])
+         && TREE_CODE_CLASS (TREE_CODE (REG_EXPR (regno_reg_rtx[i]))) == 'd')
        {
-         rtx decl = DECL_RTL_IF_SET (REGNO_DECL (i));
+         rtx decl = DECL_RTL_IF_SET (REG_EXPR (regno_reg_rtx[i]));
 
          /* We can do this only for the DECLs home pseudo, not for
             any copies of it, since otherwise when the stack slot
@@ -2094,7 +2074,7 @@ alter_reg (i, from_reg)
              if (from_reg != -1 && spill_stack_slot[from_reg] == x)
                x = copy_rtx (x);
 
-             set_mem_expr (x, REGNO_DECL (i));
+             set_mem_attrs_from_reg (x, regno_reg_rtx[i]);
            }
        }
 
@@ -2159,13 +2139,13 @@ set_label_offsets (x, insn, initial_p)
         we guessed wrong, we will suppress an elimination that might have
         been possible had we been able to guess correctly.  */
 
-      if (! offsets_known_at[CODE_LABEL_NUMBER (x)])
+      if (! offsets_known_at[CODE_LABEL_NUMBER (x) - first_label_num])
        {
          for (i = 0; i < NUM_ELIMINABLE_REGS; i++)
-           offsets_at[CODE_LABEL_NUMBER (x)][i]
+           offsets_at[CODE_LABEL_NUMBER (x) - first_label_num][i]
              = (initial_p ? reg_eliminate[i].initial_offset
                 : reg_eliminate[i].offset);
-         offsets_known_at[CODE_LABEL_NUMBER (x)] = 1;
+         offsets_known_at[CODE_LABEL_NUMBER (x) - first_label_num] = 1;
        }
 
       /* Otherwise, if this is the definition of a label and it is
@@ -2182,7 +2162,7 @@ set_label_offsets (x, insn, initial_p)
           where the offsets disagree.  */
 
        for (i = 0; i < NUM_ELIMINABLE_REGS; i++)
-         if (offsets_at[CODE_LABEL_NUMBER (x)][i]
+         if (offsets_at[CODE_LABEL_NUMBER (x) - first_label_num][i]
              != (initial_p ? reg_eliminate[i].initial_offset
                  : reg_eliminate[i].offset))
            reg_eliminate[i].can_eliminate = 0;
@@ -2544,6 +2524,10 @@ eliminate_regs (x, mem_mode, insn)
     case ABS:
     case SQRT:
     case FFS:
+    case CLZ:
+    case CTZ:
+    case POPCOUNT:
+    case PARITY:
       new = eliminate_regs (XEXP (x, 0), mem_mode, insn);
       if (new != XEXP (x, 0))
        return gen_rtx_fmt_e (code, GET_MODE (x), new);
@@ -2775,6 +2759,10 @@ elimination_effects (x, mem_mode)
     case ABS:
     case SQRT:
     case FFS:
+    case CLZ:
+    case CTZ:
+    case POPCOUNT:
+    case PARITY:
       elimination_effects (XEXP (x, 0), mem_mode);
       return;
 
@@ -3390,7 +3378,7 @@ static void
 set_initial_label_offsets ()
 {
   rtx x;
-  memset ((char *) &offsets_known_at[get_first_label_num ()], 0, num_labels);
+  memset (offsets_known_at, 0, num_labels);
 
   for (x = forced_labels; x; x = XEXP (x, 1))
     if (XEXP (x, 0))
@@ -3411,7 +3399,8 @@ set_offsets_for_label (insn)
   num_not_at_initial_offset = 0;
   for (i = 0, ep = reg_eliminate; i < NUM_ELIMINABLE_REGS; ep++, i++)
     {
-      ep->offset = ep->previous_offset = offsets_at[label_nr][i];
+      ep->offset = ep->previous_offset
+                = offsets_at[label_nr - first_label_num][i];
       if (ep->can_eliminate && ep->offset != ep->initial_offset)
        num_not_at_initial_offset++;
     }
@@ -3842,7 +3831,7 @@ reload_as_needed (live_known)
 
   for (chain = reload_insn_chain; chain; chain = chain->next)
     {
-      rtx prev;
+      rtx prev = 0;
       rtx insn = chain->insn;
       rtx old_next = NEXT_INSN (insn);
 
@@ -3937,6 +3926,7 @@ reload_as_needed (live_known)
              if (asm_noperands (PATTERN (insn)) >= 0)
                for (p = NEXT_INSN (prev); p != next; p = NEXT_INSN (p))
                  if (p != insn && INSN_P (p)
+                     && GET_CODE (PATTERN (p)) != USE
                      && (recog_memoized (p) < 0
                          || (extract_insn (p), ! constrain_operands (1))))
                    {
@@ -3984,7 +3974,7 @@ reload_as_needed (live_known)
                                            REGNO (rld[i].reg_rtx))
                      /* Make sure it is the inc/dec pseudo, and not
                         some other (e.g. output operand) pseudo.  */
-                     && (reg_reloaded_contents[REGNO (rld[i].reg_rtx)]
+                     && ((unsigned) reg_reloaded_contents[REGNO (rld[i].reg_rtx)]
                          == REGNO (XEXP (in_reg, 0))))
 
                    {
@@ -4051,7 +4041,7 @@ reload_as_needed (live_known)
                                                 REGNO (rld[i].reg_rtx))
                           /* Make sure it is the inc/dec pseudo, and not
                              some other (e.g. output operand) pseudo.  */
-                          && (reg_reloaded_contents[REGNO (rld[i].reg_rtx)]
+                          && ((unsigned) reg_reloaded_contents[REGNO (rld[i].reg_rtx)]
                               == REGNO (XEXP (in_reg, 0))))
                    {
                      SET_HARD_REG_BIT (reg_is_output_reload,
@@ -5500,7 +5490,7 @@ choose_reload_regs (chain)
 #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))
                       >= GET_MODE_SIZE (need_mode))
@@ -5677,14 +5667,27 @@ choose_reload_regs (chain)
 
              /* If we found a spill reg, reject it unless it is free
                 and of the desired class.  */
-             if (equiv != 0
-                 && ((TEST_HARD_REG_BIT (reload_reg_used_at_all, regno)
+             if (equiv != 0)
+               {
+                 int regs_used = 0;
+                 int bad_for_class = 0;
+                 int max_regno = regno + rld[r].nregs;
+
+                 for (i = regno; i < max_regno; i++)
+                   {
+                     regs_used |= TEST_HARD_REG_BIT (reload_reg_used_at_all,
+                                                     i);
+                     bad_for_class |= ! TEST_HARD_REG_BIT (reg_class_contents[(int) rld[r].class], 
+                                                          i);
+                   }
+
+                 if ((regs_used
                       && ! free_for_value_p (regno, rld[r].mode,
                                              rld[r].opnum, rld[r].when_needed,
                                              rld[r].in, rld[r].out, r, 1))
-                     || ! TEST_HARD_REG_BIT (reg_class_contents[(int) rld[r].class],
-                                             regno)))
-               equiv = 0;
+                     || bad_for_class)
+                   equiv = 0;
+               }
 
              if (equiv != 0 && ! HARD_REGNO_MODE_OK (regno, rld[r].mode))
                equiv = 0;
@@ -6130,13 +6133,15 @@ merge_assigned_reloads (insn)
                       ? RELOAD_FOR_OTHER_ADDRESS : RELOAD_OTHER);
 
                  /* Check to see if we accidentally converted two reloads
-                    that use the same reload register to the same type.
-                    If so, the resulting code won't work, so abort.  */
+                    that use the same reload register with different inputs
+                    to the same type.  If so, the resulting code won't work,
+                    so abort.  */
                  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].reg_rtx, rld[j].reg_rtx)
+                         && ! rtx_equal_p (rld[k].in, rld[j].in))
                        abort ();
                }
        }
@@ -6260,7 +6265,7 @@ emit_input_reload_insns (chain, rl, old, j)
         or memory.  */
 
       if (oldequiv != 0
-         && ((REGNO_REG_CLASS (regno) != rl->class
+         && (((enum reg_class) REGNO_REG_CLASS (regno) != rl->class
               && (REGISTER_MOVE_COST (mode, REGNO_REG_CLASS (regno),
                                       rl->class)
                   >= MEMORY_MOVE_COST (mode, rl->class, 1)))
@@ -6316,7 +6321,7 @@ emit_input_reload_insns (chain, rl, old, j)
      must always be a REG here.  */
 
   if (GET_MODE (reloadreg) != mode)
-    reloadreg = gen_rtx_REG (mode, REGNO (reloadreg));
+    reloadreg = reload_adjust_reg_for_mode (reloadreg, mode);
   while (GET_CODE (oldequiv) == SUBREG && GET_MODE (oldequiv) != mode)
     oldequiv = SUBREG_REG (oldequiv);
   if (GET_MODE (oldequiv) != VOIDmode
@@ -6565,8 +6570,8 @@ emit_input_reload_insns (chain, rl, old, j)
                        oldequiv = old, real_oldequiv = real_old;
                      else
                        second_reload_reg
-                         = gen_rtx_REG (new_mode,
-                                        REGNO (second_reload_reg));
+                         = reload_adjust_reg_for_mode (second_reload_reg,
+                                                       new_mode);
                    }
                }
            }
@@ -6688,7 +6693,7 @@ emit_output_reload_insns (chain, rl, j)
     }
 
   if (GET_MODE (reloadreg) != mode)
-    reloadreg = gen_rtx_REG (mode, REGNO (reloadreg));
+    reloadreg = reload_adjust_reg_for_mode (reloadreg, mode);
 
 #ifdef SECONDARY_OUTPUT_RELOAD_CLASS
 
@@ -6729,7 +6734,7 @@ emit_output_reload_insns (chain, rl, j)
                = rld[secondary_reload].secondary_out_icode;
 
              if (GET_MODE (reloadreg) != mode)
-               reloadreg = gen_rtx_REG (mode, REGNO (reloadreg));
+               reloadreg = reload_adjust_reg_for_mode (reloadreg, mode);
 
              if (tertiary_icode != CODE_FOR_nothing)
                {
@@ -8015,1396 +8020,6 @@ inc_for_reload (reloadreg, in, value, inc_amount)
   return store;
 }
 \f
-
-/* See whether a single set SET is a noop.  */
-static int
-reload_cse_noop_set_p (set)
-     rtx set;
-{
-  return rtx_equal_for_cselib_p (SET_DEST (set), SET_SRC (set));
-}
-
-/* Try to simplify INSN.  */
-static void
-reload_cse_simplify (insn, testreg)
-     rtx insn;
-     rtx testreg;
-{
-  rtx body = PATTERN (insn);
-
-  if (GET_CODE (body) == SET)
-    {
-      int count = 0;
-
-      /* Simplify even if we may think it is a no-op.
-         We may think a memory load of a value smaller than WORD_SIZE
-         is redundant because we haven't taken into account possible
-         implicit extension.  reload_cse_simplify_set() will bring
-         this out, so it's safer to simplify before we delete.  */
-      count += reload_cse_simplify_set (body, insn);
-
-      if (!count && reload_cse_noop_set_p (body))
-       {
-         rtx value = SET_DEST (body);
-         if (REG_P (value)
-             && ! REG_FUNCTION_VALUE_P (value))
-           value = 0;
-         delete_insn_and_edges (insn);
-         return;
-       }
-
-      if (count > 0)
-       apply_change_group ();
-      else
-       reload_cse_simplify_operands (insn, testreg);
-    }
-  else if (GET_CODE (body) == PARALLEL)
-    {
-      int i;
-      int count = 0;
-      rtx value = NULL_RTX;
-
-      /* If every action in a PARALLEL is a noop, we can delete
-        the entire PARALLEL.  */
-      for (i = XVECLEN (body, 0) - 1; i >= 0; --i)
-       {
-         rtx part = XVECEXP (body, 0, i);
-         if (GET_CODE (part) == SET)
-           {
-             if (! reload_cse_noop_set_p (part))
-               break;
-             if (REG_P (SET_DEST (part))
-                 && REG_FUNCTION_VALUE_P (SET_DEST (part)))
-               {
-                 if (value)
-                   break;
-                 value = SET_DEST (part);
-               }
-           }
-         else if (GET_CODE (part) != CLOBBER)
-           break;
-       }
-
-      if (i < 0)
-       {
-         delete_insn_and_edges (insn);
-         /* We're done with this insn.  */
-         return;
-       }
-
-      /* It's not a no-op, but we can try to simplify it.  */
-      for (i = XVECLEN (body, 0) - 1; i >= 0; --i)
-       if (GET_CODE (XVECEXP (body, 0, i)) == SET)
-         count += reload_cse_simplify_set (XVECEXP (body, 0, i), insn);
-
-      if (count > 0)
-       apply_change_group ();
-      else
-       reload_cse_simplify_operands (insn, testreg);
-    }
-}
-
-/* Do a very simple CSE pass over the hard registers.
-
-   This function detects no-op moves where we happened to assign two
-   different pseudo-registers to the same hard register, and then
-   copied one to the other.  Reload will generate a useless
-   instruction copying a register to itself.
-
-   This function also detects cases where we load a value from memory
-   into two different registers, and (if memory is more expensive than
-   registers) changes it to simply copy the first register into the
-   second register.
-
-   Another optimization is performed that scans the operands of each
-   instruction to see whether the value is already available in a
-   hard register.  It then replaces the operand with the hard register
-   if possible, much like an optional reload would.  */
-
-static void
-reload_cse_regs_1 (first)
-     rtx first;
-{
-  rtx insn;
-  rtx testreg = gen_rtx_REG (VOIDmode, -1);
-
-  cselib_init ();
-  init_alias_analysis ();
-
-  for (insn = first; insn; insn = NEXT_INSN (insn))
-    {
-      if (INSN_P (insn))
-       reload_cse_simplify (insn, testreg);
-
-      cselib_process_insn (insn);
-    }
-
-  /* Clean up.  */
-  end_alias_analysis ();
-  cselib_finish ();
-}
-
-/* Call cse / combine like post-reload optimization phases.
-   FIRST is the first instruction.  */
-void
-reload_cse_regs (first)
-     rtx first;
-{
-  reload_cse_regs_1 (first);
-  reload_combine ();
-  reload_cse_move2add (first);
-  if (flag_expensive_optimizations)
-    reload_cse_regs_1 (first);
-}
-
-/* Try to simplify a single SET instruction.  SET is the set pattern.
-   INSN is the instruction it came from.
-   This function only handles one case: if we set a register to a value
-   which is not a register, we try to find that value in some other register
-   and change the set into a register copy.  */
-
-static int
-reload_cse_simplify_set (set, insn)
-     rtx set;
-     rtx insn;
-{
-  int did_change = 0;
-  int dreg;
-  rtx src;
-  enum reg_class dclass;
-  int old_cost;
-  cselib_val *val;
-  struct elt_loc_list *l;
-#ifdef LOAD_EXTEND_OP
-  enum rtx_code extend_op = NIL;
-#endif
-
-  dreg = true_regnum (SET_DEST (set));
-  if (dreg < 0)
-    return 0;
-
-  src = SET_SRC (set);
-  if (side_effects_p (src) || true_regnum (src) >= 0)
-    return 0;
-
-  dclass = REGNO_REG_CLASS (dreg);
-
-#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
-     the destination must be a register that we can widen.  */
-  if (GET_CODE (src) == MEM
-      && GET_MODE_BITSIZE (GET_MODE (src)) < BITS_PER_WORD
-      && (extend_op = LOAD_EXTEND_OP (GET_MODE (src))) != NIL
-      && GET_CODE (SET_DEST (set)) != REG)
-    return 0;
-#endif
-
-  /* If memory loads are cheaper than register copies, don't change them.  */
-  if (GET_CODE (src) == MEM)
-    old_cost = MEMORY_MOVE_COST (GET_MODE (src), dclass, 1);
-  else if (CONSTANT_P (src))
-    old_cost = rtx_cost (src, SET);
-  else if (GET_CODE (src) == REG)
-    old_cost = REGISTER_MOVE_COST (GET_MODE (src),
-                                  REGNO_REG_CLASS (REGNO (src)), dclass);
-  else
-    /* ???   */
-    old_cost = rtx_cost (src, SET);
-
-  val = cselib_lookup (src, GET_MODE (SET_DEST (set)), 0);
-  if (! val)
-    return 0;
-  for (l = val->locs; l; l = l->next)
-    {
-      rtx this_rtx = l->loc;
-      int this_cost;
-
-      if (CONSTANT_P (this_rtx) && ! references_value_p (this_rtx, 0))
-       {
-#ifdef LOAD_EXTEND_OP
-         if (extend_op != NIL)
-           {
-             HOST_WIDE_INT this_val;
-
-             /* ??? I'm lazy and don't wish to handle CONST_DOUBLE.  Other
-                constants, such as SYMBOL_REF, cannot be extended.  */
-             if (GET_CODE (this_rtx) != CONST_INT)
-               continue;
-
-             this_val = INTVAL (this_rtx);
-             switch (extend_op)
-               {
-               case ZERO_EXTEND:
-                 this_val &= GET_MODE_MASK (GET_MODE (src));
-                 break;
-               case SIGN_EXTEND:
-                 /* ??? In theory we're already extended.  */
-                 if (this_val == trunc_int_for_mode (this_val, GET_MODE (src)))
-                   break;
-               default:
-                 abort ();
-               }
-             this_rtx = GEN_INT (this_val);
-           }
-#endif
-         this_cost = rtx_cost (this_rtx, SET);
-       }
-      else if (GET_CODE (this_rtx) == REG)
-       {
-#ifdef LOAD_EXTEND_OP
-         if (extend_op != NIL)
-           {
-             this_rtx = gen_rtx_fmt_e (extend_op, word_mode, this_rtx);
-             this_cost = rtx_cost (this_rtx, SET);
-           }
-         else
-#endif
-           this_cost = REGISTER_MOVE_COST (GET_MODE (this_rtx),
-                                           REGNO_REG_CLASS (REGNO (this_rtx)),
-                                           dclass);
-       }
-      else
-       continue;
-
-      /* If equal costs, prefer registers over anything else.  That
-        tends to lead to smaller instructions on some machines.  */
-      if (this_cost < old_cost
-         || (this_cost == old_cost
-             && GET_CODE (this_rtx) == REG
-             && GET_CODE (SET_SRC (set)) != REG))
-       {
-#ifdef LOAD_EXTEND_OP
-         if (GET_MODE_BITSIZE (GET_MODE (SET_DEST (set))) < BITS_PER_WORD
-             && extend_op != NIL)
-           {
-             rtx wide_dest = gen_rtx_REG (word_mode, REGNO (SET_DEST (set)));
-             ORIGINAL_REGNO (wide_dest) = ORIGINAL_REGNO (SET_DEST (set));
-             validate_change (insn, &SET_DEST (set), wide_dest, 1);
-           }
-#endif
-
-         validate_change (insn, &SET_SRC (set), copy_rtx (this_rtx), 1);
-         old_cost = this_cost, did_change = 1;
-       }
-    }
-
-  return did_change;
-}
-
-/* Try to replace operands in INSN with equivalent values that are already
-   in registers.  This can be viewed as optional reloading.
-
-   For each non-register operand in the insn, see if any hard regs are
-   known to be equivalent to that operand.  Record the alternatives which
-   can accept these hard registers.  Among all alternatives, select the
-   ones which are better or equal to the one currently matching, where
-   "better" is in terms of '?' and '!' constraints.  Among the remaining
-   alternatives, select the one which replaces most operands with
-   hard registers.  */
-
-static int
-reload_cse_simplify_operands (insn, testreg)
-     rtx insn;
-     rtx testreg;
-{
-  int i, j;
-
-  /* For each operand, all registers that are equivalent to it.  */
-  HARD_REG_SET equiv_regs[MAX_RECOG_OPERANDS];
-
-  const char *constraints[MAX_RECOG_OPERANDS];
-
-  /* Vector recording how bad an alternative is.  */
-  int *alternative_reject;
-  /* Vector recording how many registers can be introduced by choosing
-     this alternative.  */
-  int *alternative_nregs;
-  /* Array of vectors recording, for each operand and each alternative,
-     which hard register to substitute, or -1 if the operand should be
-     left as it is.  */
-  int *op_alt_regno[MAX_RECOG_OPERANDS];
-  /* Array of alternatives, sorted in order of decreasing desirability.  */
-  int *alternative_order;
-
-  extract_insn (insn);
-
-  if (recog_data.n_alternatives == 0 || recog_data.n_operands == 0)
-    return 0;
-
-  /* Figure out which alternative currently matches.  */
-  if (! constrain_operands (1))
-    fatal_insn_not_found (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));
-
-  /* For each operand, find out which regs are equivalent.  */
-  for (i = 0; i < recog_data.n_operands; i++)
-    {
-      cselib_val *v;
-      struct elt_loc_list *l;
-
-      CLEAR_HARD_REG_SET (equiv_regs[i]);
-
-      /* cselib blows up on CODE_LABELs.  Trying to fix that doesn't seem
-        right, so avoid the problem here.  Likewise if we have a constant
-         and the insn pattern doesn't tell us the mode we need.  */
-      if (GET_CODE (recog_data.operand[i]) == CODE_LABEL
-         || (CONSTANT_P (recog_data.operand[i])
-             && recog_data.operand_mode[i] == VOIDmode))
-       continue;
-
-      v = cselib_lookup (recog_data.operand[i], recog_data.operand_mode[i], 0);
-      if (! v)
-       continue;
-
-      for (l = v->locs; l; l = l->next)
-       if (GET_CODE (l->loc) == REG)
-         SET_HARD_REG_BIT (equiv_regs[i], REGNO (l->loc));
-    }
-
-  for (i = 0; i < recog_data.n_operands; i++)
-    {
-      enum machine_mode mode;
-      int regno;
-      const char *p;
-
-      op_alt_regno[i] = (int *) alloca (recog_data.n_alternatives * sizeof (int));
-      for (j = 0; j < recog_data.n_alternatives; j++)
-       op_alt_regno[i][j] = -1;
-
-      p = constraints[i] = recog_data.constraints[i];
-      mode = recog_data.operand_mode[i];
-
-      /* Add the reject values for each alternative given by the constraints
-        for this operand.  */
-      j = 0;
-      while (*p != '\0')
-       {
-         char c = *p++;
-         if (c == ',')
-           j++;
-         else if (c == '?')
-           alternative_reject[j] += 3;
-         else if (c == '!')
-           alternative_reject[j] += 300;
-       }
-
-      /* We won't change operands which are already registers.  We
-        also don't want to modify output operands.  */
-      regno = true_regnum (recog_data.operand[i]);
-      if (regno >= 0
-         || constraints[i][0] == '='
-         || constraints[i][0] == '+')
-       continue;
-
-      for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
-       {
-         int class = (int) NO_REGS;
-
-         if (! TEST_HARD_REG_BIT (equiv_regs[i], regno))
-           continue;
-
-         REGNO (testreg) = regno;
-         PUT_MODE (testreg, mode);
-
-         /* We found a register equal to this operand.  Now look for all
-            alternatives that can accept this register and have not been
-            assigned a register they can use yet.  */
-         j = 0;
-         p = constraints[i];
-         for (;;)
-           {
-             char c = *p;
-
-             switch (c)
-               {
-               case '=':  case '+':  case '?':
-               case '#':  case '&':  case '!':
-               case '*':  case '%':
-               case '0':  case '1':  case '2':  case '3':  case '4':
-               case '5':  case '6':  case '7':  case '8':  case '9':
-               case 'm':  case '<':  case '>':  case 'V':  case 'o':
-               case 'E':  case 'F':  case 'G':  case 'H':
-               case 's':  case 'i':  case 'n':
-               case 'I':  case 'J':  case 'K':  case 'L':
-               case 'M':  case 'N':  case 'O':  case 'P':
-               case 'p': case 'X':
-                 /* These don't say anything we care about.  */
-                 break;
-
-               case 'g': case 'r':
-                 class = reg_class_subunion[(int) class][(int) GENERAL_REGS];
-                 break;
-
-               default:
-                 class
-                   = (reg_class_subunion
-                      [(int) class]
-                      [(int) REG_CLASS_FROM_CONSTRAINT ((unsigned char) c, p)]);
-                 break;
-
-               case ',': case '\0':
-                 /* See if REGNO fits this alternative, and set it up as the
-                    replacement register if we don't have one for this
-                    alternative yet and the operand being replaced is not
-                    a cheap CONST_INT.  */
-                 if (op_alt_regno[i][j] == -1
-                     && reg_fits_class_p (testreg, class, 0, mode)
-                     && (GET_CODE (recog_data.operand[i]) != CONST_INT
-                         || (rtx_cost (recog_data.operand[i], SET)
-                             > rtx_cost (testreg, SET))))
-                   {
-                     alternative_nregs[j]++;
-                     op_alt_regno[i][j] = regno;
-                   }
-                 j++;
-                 break;
-               }
-             p += CONSTRAINT_LEN (c, p);
-
-             if (c == '\0')
-               break;
-           }
-       }
-    }
-
-  /* Record all alternatives which are better or equal to the currently
-     matching one in the alternative_order array.  */
-  for (i = j = 0; i < recog_data.n_alternatives; i++)
-    if (alternative_reject[i] <= alternative_reject[which_alternative])
-      alternative_order[j++] = i;
-  recog_data.n_alternatives = j;
-
-  /* Sort it.  Given a small number of alternatives, a dumb algorithm
-     won't hurt too much.  */
-  for (i = 0; i < recog_data.n_alternatives - 1; i++)
-    {
-      int best = i;
-      int best_reject = alternative_reject[alternative_order[i]];
-      int best_nregs = alternative_nregs[alternative_order[i]];
-      int tmp;
-
-      for (j = i + 1; j < recog_data.n_alternatives; j++)
-       {
-         int this_reject = alternative_reject[alternative_order[j]];
-         int this_nregs = alternative_nregs[alternative_order[j]];
-
-         if (this_reject < best_reject
-             || (this_reject == best_reject && this_nregs < best_nregs))
-           {
-             best = j;
-             best_reject = this_reject;
-             best_nregs = this_nregs;
-           }
-       }
-
-      tmp = alternative_order[best];
-      alternative_order[best] = alternative_order[i];
-      alternative_order[i] = tmp;
-    }
-
-  /* Substitute the operands as determined by op_alt_regno for the best
-     alternative.  */
-  j = alternative_order[0];
-
-  for (i = 0; i < recog_data.n_operands; i++)
-    {
-      enum machine_mode mode = recog_data.operand_mode[i];
-      if (op_alt_regno[i][j] == -1)
-       continue;
-
-      validate_change (insn, recog_data.operand_loc[i],
-                      gen_rtx_REG (mode, op_alt_regno[i][j]), 1);
-    }
-
-  for (i = recog_data.n_dups - 1; i >= 0; i--)
-    {
-      int op = recog_data.dup_num[i];
-      enum machine_mode mode = recog_data.operand_mode[op];
-
-      if (op_alt_regno[op][j] == -1)
-       continue;
-
-      validate_change (insn, recog_data.dup_loc[i],
-                      gen_rtx_REG (mode, op_alt_regno[op][j]), 1);
-    }
-
-  return apply_change_group ();
-}
-\f
-/* If reload couldn't use reg+reg+offset addressing, try to use reg+reg
-   addressing now.
-   This code might also be useful when reload gave up on reg+reg addressing
-   because of clashes between the return register and INDEX_REG_CLASS.  */
-
-/* The maximum number of uses of a register we can keep track of to
-   replace them with reg+reg addressing.  */
-#define RELOAD_COMBINE_MAX_USES 6
-
-/* INSN is the insn where a register has ben used, and USEP points to the
-   location of the register within the rtl.  */
-struct reg_use { rtx insn, *usep; };
-
-/* If the register is used in some unknown fashion, USE_INDEX is negative.
-   If it is dead, USE_INDEX is RELOAD_COMBINE_MAX_USES, and STORE_RUID
-   indicates where it becomes live again.
-   Otherwise, USE_INDEX is the index of the last encountered use of the
-   register (which is first among these we have seen since we scan backwards),
-   OFFSET contains the constant offset that is added to the register in
-   all encountered uses, and USE_RUID indicates the first encountered, i.e.
-   last, of these uses.
-   STORE_RUID is always meaningful if we only want to use a value in a
-   register in a different place: it denotes the next insn in the insn
-   stream (i.e. the last encountered) that sets or clobbers the register.  */
-static struct
-  {
-    struct reg_use reg_use[RELOAD_COMBINE_MAX_USES];
-    int use_index;
-    rtx offset;
-    int store_ruid;
-    int use_ruid;
-  } reg_state[FIRST_PSEUDO_REGISTER];
-
-/* Reverse linear uid.  This is increased in reload_combine while scanning
-   the instructions from last to first.  It is used to set last_label_ruid
-   and the store_ruid / use_ruid fields in reg_state.  */
-static int reload_combine_ruid;
-
-#define LABEL_LIVE(LABEL) \
-  (label_live[CODE_LABEL_NUMBER (LABEL) - min_labelno])
-
-static void
-reload_combine ()
-{
-  rtx insn, set;
-  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;
-  HARD_REG_SET ever_live_at_start, *label_live;
-
-  /* If reg+reg can be used in offsetable memory addresses, the main chunk of
-     reload has already used it where appropriate, so there is no use in
-     trying to generate it now.  */
-  if (double_reg_address_ok && INDEX_REG_CLASS != NO_REGS)
-    return;
-
-  /* To avoid wasting too much time later searching for an index register,
-     determine the minimum and maximum index register numbers.  */
-  for (r = 0; r < FIRST_PSEUDO_REGISTER; r++)
-    if (TEST_HARD_REG_BIT (reg_class_contents[INDEX_REG_CLASS], r))
-      {
-       if (first_index_reg == -1)
-         first_index_reg = r;
-
-       last_index_reg = r;
-      }
-
-  /* If no index register is available, we can quit now.  */
-  if (first_index_reg == -1)
-    return;
-
-  /* Set up LABEL_LIVE and EVER_LIVE_AT_START.  The register lifetime
-     information is a bit fuzzy immediately after reload, but it's
-     still good enough to determine which registers are live at a jump
-     destination.  */
-  min_labelno = get_first_label_num ();
-  n_labels = max_label_num () - min_labelno;
-  label_live = (HARD_REG_SET *) xmalloc (n_labels * sizeof (HARD_REG_SET));
-  CLEAR_HARD_REG_SET (ever_live_at_start);
-
-  FOR_EACH_BB_REVERSE (bb)
-    {
-      insn = bb->head;
-      if (GET_CODE (insn) == CODE_LABEL)
-       {
-         HARD_REG_SET live;
-
-         REG_SET_TO_HARD_REG_SET (live,
-                                  bb->global_live_at_start);
-         compute_use_by_pseudos (&live,
-                                 bb->global_live_at_start);
-         COPY_HARD_REG_SET (LABEL_LIVE (insn), live);
-         IOR_HARD_REG_SET (ever_live_at_start, live);
-       }
-    }
-
-  /* Initialize last_label_ruid, reload_combine_ruid and reg_state.  */
-  last_label_ruid = reload_combine_ruid = 0;
-  for (r = 0; r < FIRST_PSEUDO_REGISTER; r++)
-    {
-      reg_state[r].store_ruid = reload_combine_ruid;
-      if (fixed_regs[r])
-       reg_state[r].use_index = -1;
-      else
-       reg_state[r].use_index = RELOAD_COMBINE_MAX_USES;
-    }
-
-  for (insn = get_last_insn (); insn; insn = PREV_INSN (insn))
-    {
-      rtx note;
-
-      /* We cannot do our optimization across labels.  Invalidating all the use
-        information we have would be costly, so we just note where the label
-        is and then later disable any optimization that would cross it.  */
-      if (GET_CODE (insn) == CODE_LABEL)
-       last_label_ruid = reload_combine_ruid;
-      else if (GET_CODE (insn) == BARRIER)
-       for (r = 0; r < FIRST_PSEUDO_REGISTER; r++)
-         if (! fixed_regs[r])
-             reg_state[r].use_index = RELOAD_COMBINE_MAX_USES;
-
-      if (! INSN_P (insn))
-       continue;
-
-      reload_combine_ruid++;
-
-      /* Look for (set (REGX) (CONST_INT))
-        (set (REGX) (PLUS (REGX) (REGY)))
-        ...
-        ... (MEM (REGX)) ...
-        and convert it to
-        (set (REGZ) (CONST_INT))
-        ...
-        ... (MEM (PLUS (REGZ) (REGY)))... .
-
-        First, check that we have (set (REGX) (PLUS (REGX) (REGY)))
-        and that we know all uses of REGX before it dies.  */
-      set = single_set (insn);
-      if (set != NULL_RTX
-         && GET_CODE (SET_DEST (set)) == REG
-         && (HARD_REGNO_NREGS (REGNO (SET_DEST (set)),
-                               GET_MODE (SET_DEST (set)))
-             == 1)
-         && GET_CODE (SET_SRC (set)) == PLUS
-         && GET_CODE (XEXP (SET_SRC (set), 1)) == REG
-         && rtx_equal_p (XEXP (SET_SRC (set), 0), SET_DEST (set))
-         && last_label_ruid < reg_state[REGNO (SET_DEST (set))].use_ruid)
-       {
-         rtx reg = SET_DEST (set);
-         rtx plus = SET_SRC (set);
-         rtx base = XEXP (plus, 1);
-         rtx prev = prev_nonnote_insn (insn);
-         rtx prev_set = prev ? single_set (prev) : NULL_RTX;
-         unsigned int regno = REGNO (reg);
-         rtx const_reg = NULL_RTX;
-         rtx reg_sum = NULL_RTX;
-
-         /* Now, we need an index register.
-            We'll set index_reg to this index register, const_reg to the
-            register that is to be loaded with the constant
-            (denoted as REGZ in the substitution illustration above),
-            and reg_sum to the register-register that we want to use to
-            substitute uses of REG (typically in MEMs) with.
-            First check REG and BASE for being index registers;
-            we can use them even if they are not dead.  */
-         if (TEST_HARD_REG_BIT (reg_class_contents[INDEX_REG_CLASS], regno)
-             || TEST_HARD_REG_BIT (reg_class_contents[INDEX_REG_CLASS],
-                                   REGNO (base)))
-           {
-             const_reg = reg;
-             reg_sum = plus;
-           }
-         else
-           {
-             /* Otherwise, look for a free index register.  Since we have
-                checked above that neiter REG nor BASE are index registers,
-                if we find anything at all, it will be different from these
-                two registers.  */
-             for (i = first_index_reg; i <= last_index_reg; i++)
-               {
-                 if (TEST_HARD_REG_BIT (reg_class_contents[INDEX_REG_CLASS],
-                                        i)
-                     && reg_state[i].use_index == RELOAD_COMBINE_MAX_USES
-                     && reg_state[i].store_ruid <= reg_state[regno].use_ruid
-                     && HARD_REGNO_NREGS (i, GET_MODE (reg)) == 1)
-                   {
-                     rtx index_reg = gen_rtx_REG (GET_MODE (reg), i);
-
-                     const_reg = index_reg;
-                     reg_sum = gen_rtx_PLUS (GET_MODE (reg), index_reg, base);
-                     break;
-                   }
-               }
-           }
-
-         /* Check that PREV_SET is indeed (set (REGX) (CONST_INT)) and that
-            (REGY), i.e. BASE, is not clobbered before the last use we'll
-            create.  */
-         if (prev_set != 0
-             && GET_CODE (SET_SRC (prev_set)) == CONST_INT
-             && rtx_equal_p (SET_DEST (prev_set), reg)
-             && reg_state[regno].use_index >= 0
-             && (reg_state[REGNO (base)].store_ruid
-                 <= reg_state[regno].use_ruid)
-             && reg_sum != 0)
-           {
-             int i;
-
-             /* Change destination register and, if necessary, the
-                constant value in PREV, the constant loading instruction.  */
-             validate_change (prev, &SET_DEST (prev_set), const_reg, 1);
-             if (reg_state[regno].offset != const0_rtx)
-               validate_change (prev,
-                                &SET_SRC (prev_set),
-                                GEN_INT (INTVAL (SET_SRC (prev_set))
-                                         + INTVAL (reg_state[regno].offset)),
-                                1);
-
-             /* Now for every use of REG that we have recorded, replace REG
-                with REG_SUM.  */
-             for (i = reg_state[regno].use_index;
-                  i < RELOAD_COMBINE_MAX_USES; i++)
-               validate_change (reg_state[regno].reg_use[i].insn,
-                                reg_state[regno].reg_use[i].usep,
-                                /* Each change must have its own
-                                   replacement.  */
-                                copy_rtx (reg_sum), 1);
-
-             if (apply_change_group ())
-               {
-                 rtx *np;
-
-                 /* Delete the reg-reg addition.  */
-                 delete_insn (insn);
-
-                 if (reg_state[regno].offset != const0_rtx)
-                   /* Previous REG_EQUIV / REG_EQUAL notes for PREV
-                      are now invalid.  */
-                   for (np = &REG_NOTES (prev); *np;)
-                     {
-                       if (REG_NOTE_KIND (*np) == REG_EQUAL
-                           || REG_NOTE_KIND (*np) == REG_EQUIV)
-                         *np = XEXP (*np, 1);
-                       else
-                         np = &XEXP (*np, 1);
-                     }
-
-                 reg_state[regno].use_index = RELOAD_COMBINE_MAX_USES;
-                 reg_state[REGNO (const_reg)].store_ruid
-                   = reload_combine_ruid;
-                 continue;
-               }
-           }
-       }
-
-      note_stores (PATTERN (insn), reload_combine_note_store, NULL);
-
-      if (GET_CODE (insn) == CALL_INSN)
-       {
-         rtx link;
-
-         for (r = 0; r < FIRST_PSEUDO_REGISTER; r++)
-           if (call_used_regs[r])
-             {
-               reg_state[r].use_index = RELOAD_COMBINE_MAX_USES;
-               reg_state[r].store_ruid = reload_combine_ruid;
-             }
-
-         for (link = CALL_INSN_FUNCTION_USAGE (insn); link;
-              link = XEXP (link, 1))
-           {
-             rtx usage_rtx = XEXP (XEXP (link, 0), 0);
-             if (GET_CODE (usage_rtx) == REG)
-               {
-                 unsigned int i;
-                 unsigned int start_reg = REGNO (usage_rtx);
-                 unsigned int num_regs =
-                       HARD_REGNO_NREGS (start_reg, GET_MODE (usage_rtx));
-                 unsigned int end_reg  = start_reg + num_regs - 1;
-                 for (i = start_reg; i <= end_reg; i++)
-                   if (GET_CODE (XEXP (link, 0)) == CLOBBER)
-                     {
-                       reg_state[i].use_index = RELOAD_COMBINE_MAX_USES;
-                       reg_state[i].store_ruid = reload_combine_ruid;
-                     }
-                   else
-                     reg_state[i].use_index = -1;
-                }
-            }
-
-       }
-      else if (GET_CODE (insn) == JUMP_INSN
-              && GET_CODE (PATTERN (insn)) != RETURN)
-       {
-         /* Non-spill registers might be used at the call destination in
-            some unknown fashion, so we have to mark the unknown use.  */
-         HARD_REG_SET *live;
-
-         if ((condjump_p (insn) || condjump_in_parallel_p (insn))
-             && JUMP_LABEL (insn))
-           live = &LABEL_LIVE (JUMP_LABEL (insn));
-         else
-           live = &ever_live_at_start;
-
-         for (i = FIRST_PSEUDO_REGISTER - 1; i >= 0; --i)
-           if (TEST_HARD_REG_BIT (*live, i))
-             reg_state[i].use_index = -1;
-       }
-
-      reload_combine_note_use (&PATTERN (insn), insn);
-      for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
-       {
-         if (REG_NOTE_KIND (note) == REG_INC
-             && GET_CODE (XEXP (note, 0)) == REG)
-           {
-             int regno = REGNO (XEXP (note, 0));
-
-             reg_state[regno].store_ruid = reload_combine_ruid;
-             reg_state[regno].use_index = -1;
-           }
-       }
-    }
-
-  free (label_live);
-}
-
-/* Check if DST is a register or a subreg of a register; if it is,
-   update reg_state[regno].store_ruid and reg_state[regno].use_index
-   accordingly.  Called via note_stores from reload_combine.  */
-
-static void
-reload_combine_note_store (dst, set, data)
-     rtx dst, set;
-     void *data ATTRIBUTE_UNUSED;
-{
-  int regno = 0;
-  int i;
-  enum machine_mode mode = GET_MODE (dst);
-
-  if (GET_CODE (dst) == SUBREG)
-    {
-      regno = subreg_regno_offset (REGNO (SUBREG_REG (dst)),
-                                  GET_MODE (SUBREG_REG (dst)),
-                                  SUBREG_BYTE (dst),
-                                  GET_MODE (dst));
-      dst = SUBREG_REG (dst);
-    }
-  if (GET_CODE (dst) != REG)
-    return;
-  regno += REGNO (dst);
-
-  /* note_stores might have stripped a STRICT_LOW_PART, so we have to be
-     careful with registers / register parts that are not full words.
-
-     Similarly for ZERO_EXTRACT and SIGN_EXTRACT.  */
-  if (GET_CODE (set) != SET
-      || GET_CODE (SET_DEST (set)) == ZERO_EXTRACT
-      || GET_CODE (SET_DEST (set)) == SIGN_EXTRACT
-      || GET_CODE (SET_DEST (set)) == STRICT_LOW_PART)
-    {
-      for (i = HARD_REGNO_NREGS (regno, mode) - 1 + regno; i >= regno; i--)
-       {
-         reg_state[i].use_index = -1;
-         reg_state[i].store_ruid = reload_combine_ruid;
-       }
-    }
-  else
-    {
-      for (i = HARD_REGNO_NREGS (regno, mode) - 1 + regno; i >= regno; i--)
-       {
-         reg_state[i].store_ruid = reload_combine_ruid;
-         reg_state[i].use_index = RELOAD_COMBINE_MAX_USES;
-       }
-    }
-}
-
-/* XP points to a piece of rtl that has to be checked for any uses of
-   registers.
-   *XP is the pattern of INSN, or a part of it.
-   Called from reload_combine, and recursively by itself.  */
-static void
-reload_combine_note_use (xp, insn)
-     rtx *xp, insn;
-{
-  rtx x = *xp;
-  enum rtx_code code = x->code;
-  const char *fmt;
-  int i, j;
-  rtx offset = const0_rtx; /* For the REG case below.  */
-
-  switch (code)
-    {
-    case SET:
-      if (GET_CODE (SET_DEST (x)) == REG)
-       {
-         reload_combine_note_use (&SET_SRC (x), insn);
-         return;
-       }
-      break;
-
-    case USE:
-      /* If this is the USE of a return value, we can't change it.  */
-      if (GET_CODE (XEXP (x, 0)) == REG && REG_FUNCTION_VALUE_P (XEXP (x, 0)))
-       {
-       /* Mark the return register as used in an unknown fashion.  */
-         rtx reg = XEXP (x, 0);
-         int regno = REGNO (reg);
-         int nregs = HARD_REGNO_NREGS (regno, GET_MODE (reg));
-
-         while (--nregs >= 0)
-           reg_state[regno + nregs].use_index = -1;
-         return;
-       }
-      break;
-
-    case CLOBBER:
-      if (GET_CODE (SET_DEST (x)) == REG)
-       {
-         /* No spurious CLOBBERs of pseudo registers may remain.  */
-         if (REGNO (SET_DEST (x)) >= FIRST_PSEUDO_REGISTER)
-           abort ();
-         return;
-       }
-      break;
-
-    case PLUS:
-      /* We are interested in (plus (reg) (const_int)) .  */
-      if (GET_CODE (XEXP (x, 0)) != REG
-         || GET_CODE (XEXP (x, 1)) != CONST_INT)
-       break;
-      offset = XEXP (x, 1);
-      x = XEXP (x, 0);
-      /* Fall through.  */
-    case REG:
-      {
-       int regno = REGNO (x);
-       int use_index;
-       int nregs;
-
-       /* No spurious USEs of pseudo registers may remain.  */
-       if (regno >= FIRST_PSEUDO_REGISTER)
-         abort ();
-
-       nregs = HARD_REGNO_NREGS (regno, GET_MODE (x));
-
-       /* We can't substitute into multi-hard-reg uses.  */
-       if (nregs > 1)
-         {
-           while (--nregs >= 0)
-             reg_state[regno + nregs].use_index = -1;
-           return;
-         }
-
-       /* If this register is already used in some unknown fashion, we
-          can't do anything.
-          If we decrement the index from zero to -1, we can't store more
-          uses, so this register becomes used in an unknown fashion.  */
-       use_index = --reg_state[regno].use_index;
-       if (use_index < 0)
-         return;
-
-       if (use_index != RELOAD_COMBINE_MAX_USES - 1)
-         {
-           /* We have found another use for a register that is already
-              used later.  Check if the offsets match; if not, mark the
-              register as used in an unknown fashion.  */
-           if (! rtx_equal_p (offset, reg_state[regno].offset))
-             {
-               reg_state[regno].use_index = -1;
-               return;
-             }
-         }
-       else
-         {
-           /* This is the first use of this register we have seen since we
-              marked it as dead.  */
-           reg_state[regno].offset = offset;
-           reg_state[regno].use_ruid = reload_combine_ruid;
-         }
-       reg_state[regno].reg_use[use_index].insn = insn;
-       reg_state[regno].reg_use[use_index].usep = xp;
-       return;
-      }
-
-    default:
-      break;
-    }
-
-  /* Recursively process the components of X.  */
-  fmt = GET_RTX_FORMAT (code);
-  for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
-    {
-      if (fmt[i] == 'e')
-       reload_combine_note_use (&XEXP (x, i), insn);
-      else if (fmt[i] == 'E')
-       {
-         for (j = XVECLEN (x, i) - 1; j >= 0; j--)
-           reload_combine_note_use (&XVECEXP (x, i, j), insn);
-       }
-    }
-}
-\f
-/* See if we can reduce the cost of a constant by replacing a move
-   with an add.  We track situations in which a register is set to a
-   constant or to a register plus a constant.  */
-/* We cannot do our optimization across labels.  Invalidating all the
-   information about register contents we have would be costly, so we
-   use move2add_last_label_luid to note where the label is and then
-   later disable any optimization that would cross it.
-   reg_offset[n] / reg_base_reg[n] / reg_mode[n] are only valid if
-   reg_set_luid[n] is greater than last_label_luid[n] .  */
-static int reg_set_luid[FIRST_PSEUDO_REGISTER];
-
-/* If reg_base_reg[n] is negative, register n has been set to
-   reg_offset[n] in mode reg_mode[n] .
-   If reg_base_reg[n] is non-negative, register n has been set to the
-   sum of reg_offset[n] and the value of register reg_base_reg[n]
-   before reg_set_luid[n], calculated in mode reg_mode[n] .  */
-static HOST_WIDE_INT reg_offset[FIRST_PSEUDO_REGISTER];
-static int reg_base_reg[FIRST_PSEUDO_REGISTER];
-static enum machine_mode reg_mode[FIRST_PSEUDO_REGISTER];
-
-/* move2add_luid is linearly increased while scanning the instructions
-   from first to last.  It is used to set reg_set_luid in
-   reload_cse_move2add and move2add_note_store.  */
-static int move2add_luid;
-
-/* move2add_last_label_luid is set whenever a label is found.  Labels
-   invalidate all previously collected reg_offset data.  */
-static int move2add_last_label_luid;
-
-/* Generate a CONST_INT and force it in the range of MODE.  */
-
-static HOST_WIDE_INT
-sext_for_mode (mode, value)
-     enum machine_mode mode;
-     HOST_WIDE_INT value;
-{
-  HOST_WIDE_INT cval = value & GET_MODE_MASK (mode);
-  int width = GET_MODE_BITSIZE (mode);
-
-  /* If MODE is narrower than HOST_WIDE_INT and CVAL is a negative number,
-     sign extend it.  */
-  if (width > 0 && width < HOST_BITS_PER_WIDE_INT
-      && (cval & ((HOST_WIDE_INT) 1 << (width - 1))) != 0)
-    cval |= (HOST_WIDE_INT) -1 << width;
-
-  return cval;
-}
-
-/* ??? We don't know how zero / sign extension is handled, hence we
-   can't go from a narrower to a wider mode.  */
-#define MODES_OK_FOR_MOVE2ADD(OUTMODE, INMODE) \
-  (GET_MODE_SIZE (OUTMODE) == GET_MODE_SIZE (INMODE) \
-   || (GET_MODE_SIZE (OUTMODE) <= GET_MODE_SIZE (INMODE) \
-       && TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (OUTMODE), \
-                                GET_MODE_BITSIZE (INMODE))))
-
-static void
-reload_cse_move2add (first)
-     rtx first;
-{
-  int i;
-  rtx insn;
-
-  for (i = FIRST_PSEUDO_REGISTER - 1; i >= 0; i--)
-    reg_set_luid[i] = 0;
-
-  move2add_last_label_luid = 0;
-  move2add_luid = 2;
-  for (insn = first; insn; insn = NEXT_INSN (insn), move2add_luid++)
-    {
-      rtx pat, note;
-
-      if (GET_CODE (insn) == CODE_LABEL)
-       {
-         move2add_last_label_luid = move2add_luid;
-         /* We're going to increment move2add_luid twice after a
-            label, so that we can use move2add_last_label_luid + 1 as
-            the luid for constants.  */
-         move2add_luid++;
-         continue;
-       }
-      if (! INSN_P (insn))
-       continue;
-      pat = PATTERN (insn);
-      /* For simplicity, we only perform this optimization on
-        straightforward SETs.  */
-      if (GET_CODE (pat) == SET
-         && GET_CODE (SET_DEST (pat)) == REG)
-       {
-         rtx reg = SET_DEST (pat);
-         int regno = REGNO (reg);
-         rtx src = SET_SRC (pat);
-
-         /* Check if we have valid information on the contents of this
-            register in the mode of REG.  */
-         if (reg_set_luid[regno] > move2add_last_label_luid
-             && MODES_OK_FOR_MOVE2ADD (GET_MODE (reg), reg_mode[regno]))
-           {
-             /* Try to transform (set (REGX) (CONST_INT A))
-                                 ...
-                                 (set (REGX) (CONST_INT B))
-                to
-                                 (set (REGX) (CONST_INT A))
-                                 ...
-                                 (set (REGX) (plus (REGX) (CONST_INT B-A)))  */
-
-             if (GET_CODE (src) == CONST_INT && reg_base_reg[regno] < 0)
-               {
-                 int success = 0;
-                 rtx new_src = GEN_INT (sext_for_mode (GET_MODE (reg),
-                                                       INTVAL (src)
-                                                       - reg_offset[regno]));
-                 /* (set (reg) (plus (reg) (const_int 0))) is not canonical;
-                    use (set (reg) (reg)) instead.
-                    We don't delete this insn, nor do we convert it into a
-                    note, to avoid losing register notes or the return
-                    value flag.  jump2 already knows how to get rid of
-                    no-op moves.  */
-                 if (new_src == const0_rtx)
-                   success = validate_change (insn, &SET_SRC (pat), reg, 0);
-                 else if (rtx_cost (new_src, PLUS) < rtx_cost (src, SET)
-                          && have_add2_insn (reg, new_src))
-                   success = validate_change (insn, &PATTERN (insn),
-                                              gen_add2_insn (reg, new_src), 0);
-                 reg_set_luid[regno] = move2add_luid;
-                 reg_mode[regno] = GET_MODE (reg);
-                 reg_offset[regno] = INTVAL (src);
-                 continue;
-               }
-
-             /* Try to transform (set (REGX) (REGY))
-                                 (set (REGX) (PLUS (REGX) (CONST_INT A)))
-                                 ...
-                                 (set (REGX) (REGY))
-                                 (set (REGX) (PLUS (REGX) (CONST_INT B)))
-                to
-                                 (REGX) (REGY))
-                                 (set (REGX) (PLUS (REGX) (CONST_INT A)))
-                                 ...
-                                 (set (REGX) (plus (REGX) (CONST_INT B-A)))  */
-             else if (GET_CODE (src) == REG
-                      && reg_set_luid[regno] == reg_set_luid[REGNO (src)]
-                      && reg_base_reg[regno] == reg_base_reg[REGNO (src)]
-                      && MODES_OK_FOR_MOVE2ADD (GET_MODE (reg),
-                                                reg_mode[REGNO (src)]))
-               {
-                 rtx next = next_nonnote_insn (insn);
-                 rtx set = NULL_RTX;
-                 if (next)
-                   set = single_set (next);
-                 if (set
-                     && SET_DEST (set) == reg
-                     && GET_CODE (SET_SRC (set)) == PLUS
-                     && XEXP (SET_SRC (set), 0) == reg
-                     && GET_CODE (XEXP (SET_SRC (set), 1)) == CONST_INT)
-                   {
-                     rtx src3 = XEXP (SET_SRC (set), 1);
-                     HOST_WIDE_INT added_offset = INTVAL (src3);
-                     HOST_WIDE_INT base_offset = reg_offset[REGNO (src)];
-                     HOST_WIDE_INT regno_offset = reg_offset[regno];
-                     rtx new_src = GEN_INT (sext_for_mode (GET_MODE (reg),
-                                                           added_offset
-                                                           + base_offset
-                                                           - regno_offset));
-                     int success = 0;
-
-                     if (new_src == const0_rtx)
-                       /* See above why we create (set (reg) (reg)) here.  */
-                       success
-                         = validate_change (next, &SET_SRC (set), reg, 0);
-                     else if ((rtx_cost (new_src, PLUS)
-                               < COSTS_N_INSNS (1) + rtx_cost (src3, SET))
-                              && have_add2_insn (reg, new_src))
-                       success
-                         = validate_change (next, &PATTERN (next),
-                                            gen_add2_insn (reg, new_src), 0);
-                     if (success)
-                       delete_insn (insn);
-                     insn = next;
-                     reg_mode[regno] = GET_MODE (reg);
-                     reg_offset[regno] = sext_for_mode (GET_MODE (reg),
-                                                        added_offset
-                                                        + base_offset);
-                     continue;
-                   }
-               }
-           }
-       }
-
-      for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
-       {
-         if (REG_NOTE_KIND (note) == REG_INC
-             && GET_CODE (XEXP (note, 0)) == REG)
-           {
-             /* Reset the information about this register.  */
-             int regno = REGNO (XEXP (note, 0));
-             if (regno < FIRST_PSEUDO_REGISTER)
-               reg_set_luid[regno] = 0;
-           }
-       }
-      note_stores (PATTERN (insn), move2add_note_store, NULL);
-      /* If this is a CALL_INSN, all call used registers are stored with
-        unknown values.  */
-      if (GET_CODE (insn) == CALL_INSN)
-       {
-         for (i = FIRST_PSEUDO_REGISTER - 1; i >= 0; i--)
-           {
-             if (call_used_regs[i])
-               /* Reset the information about this register.  */
-               reg_set_luid[i] = 0;
-           }
-       }
-    }
-}
-
-/* SET is a SET or CLOBBER that sets DST.
-   Update reg_set_luid, reg_offset and reg_base_reg accordingly.
-   Called from reload_cse_move2add via note_stores.  */
-
-static void
-move2add_note_store (dst, set, data)
-     rtx dst, set;
-     void *data ATTRIBUTE_UNUSED;
-{
-  unsigned int regno = 0;
-  unsigned int i;
-  enum machine_mode mode = GET_MODE (dst);
-
-  if (GET_CODE (dst) == SUBREG)
-    {
-      regno = subreg_regno_offset (REGNO (SUBREG_REG (dst)),
-                                  GET_MODE (SUBREG_REG (dst)),
-                                  SUBREG_BYTE (dst),
-                                  GET_MODE (dst));
-      dst = SUBREG_REG (dst);
-    }
-
-  /* Some targets do argument pushes without adding REG_INC notes.  */
-
-  if (GET_CODE (dst) == MEM)
-    {
-      dst = XEXP (dst, 0);
-      if (GET_CODE (dst) == PRE_INC || GET_CODE (dst) == POST_INC
-         || GET_CODE (dst) == PRE_DEC || GET_CODE (dst) == POST_DEC)
-       reg_set_luid[REGNO (XEXP (dst, 0))] = 0;
-      return;
-    }
-  if (GET_CODE (dst) != REG)
-    return;
-
-  regno += REGNO (dst);
-
-  if (HARD_REGNO_NREGS (regno, mode) == 1 && GET_CODE (set) == SET
-      && GET_CODE (SET_DEST (set)) != ZERO_EXTRACT
-      && GET_CODE (SET_DEST (set)) != SIGN_EXTRACT
-      && GET_CODE (SET_DEST (set)) != STRICT_LOW_PART)
-    {
-      rtx src = SET_SRC (set);
-      rtx base_reg;
-      HOST_WIDE_INT offset;
-      int base_regno;
-      /* This may be different from mode, if SET_DEST (set) is a
-        SUBREG.  */
-      enum machine_mode dst_mode = GET_MODE (dst);
-
-      switch (GET_CODE (src))
-       {
-       case PLUS:
-         if (GET_CODE (XEXP (src, 0)) == REG)
-           {
-             base_reg = XEXP (src, 0);
-
-             if (GET_CODE (XEXP (src, 1)) == CONST_INT)
-               offset = INTVAL (XEXP (src, 1));
-             else if (GET_CODE (XEXP (src, 1)) == REG
-                      && (reg_set_luid[REGNO (XEXP (src, 1))]
-                          > move2add_last_label_luid)
-                      && (MODES_OK_FOR_MOVE2ADD
-                          (dst_mode, reg_mode[REGNO (XEXP (src, 1))])))
-               {
-                 if (reg_base_reg[REGNO (XEXP (src, 1))] < 0)
-                   offset = reg_offset[REGNO (XEXP (src, 1))];
-                 /* Maybe the first register is known to be a
-                    constant.  */
-                 else if (reg_set_luid[REGNO (base_reg)]
-                          > move2add_last_label_luid
-                          && (MODES_OK_FOR_MOVE2ADD
-                              (dst_mode, reg_mode[REGNO (XEXP (src, 1))]))
-                          && reg_base_reg[REGNO (base_reg)] < 0)
-                   {
-                     offset = reg_offset[REGNO (base_reg)];
-                     base_reg = XEXP (src, 1);
-                   }
-                 else
-                   goto invalidate;
-               }
-             else
-               goto invalidate;
-
-             break;
-           }
-
-         goto invalidate;
-
-       case REG:
-         base_reg = src;
-         offset = 0;
-         break;
-
-       case CONST_INT:
-         /* Start tracking the register as a constant.  */
-         reg_base_reg[regno] = -1;
-         reg_offset[regno] = INTVAL (SET_SRC (set));
-         /* We assign the same luid to all registers set to constants.  */
-         reg_set_luid[regno] = move2add_last_label_luid + 1;
-         reg_mode[regno] = mode;
-         return;
-
-       default:
-       invalidate:
-         /* Invalidate the contents of the register.  */
-         reg_set_luid[regno] = 0;
-         return;
-       }
-
-      base_regno = REGNO (base_reg);
-      /* If information about the base register is not valid, set it
-        up as a new base register, pretending its value is known
-        starting from the current insn.  */
-      if (reg_set_luid[base_regno] <= move2add_last_label_luid)
-       {
-         reg_base_reg[base_regno] = base_regno;
-         reg_offset[base_regno] = 0;
-         reg_set_luid[base_regno] = move2add_luid;
-         reg_mode[base_regno] = mode;
-       }
-      else if (! MODES_OK_FOR_MOVE2ADD (dst_mode,
-                                       reg_mode[base_regno]))
-       goto invalidate;
-
-      reg_mode[regno] = mode;
-
-      /* Copy base information from our base register.  */
-      reg_set_luid[regno] = reg_set_luid[base_regno];
-      reg_base_reg[regno] = reg_base_reg[base_regno];
-
-      /* Compute the sum of the offsets or constants.  */
-      reg_offset[regno] = sext_for_mode (dst_mode,
-                                        offset
-                                        + reg_offset[base_regno]);
-    }
-  else
-    {
-      unsigned int endregno = regno + HARD_REGNO_NREGS (regno, mode);
-
-      for (i = regno; i < endregno; i++)
-       /* Reset the information about this register.  */
-       reg_set_luid[i] = 0;
-    }
-}
-
 #ifdef AUTO_INC_DEC
 static void
 add_auto_inc_notes (insn, x)
@@ -9524,6 +8139,14 @@ fixup_abnormal_edges ()
            }
        }
     }
+  /* We've possibly turned single trapping insn into multiple ones.  */
+  if (flag_non_call_exceptions)
+    {
+      sbitmap blocks;
+      blocks = sbitmap_alloc (last_basic_block);
+      sbitmap_ones (blocks);
+      find_many_sub_basic_blocks (blocks);
+    }
   if (inserted)
     commit_edge_insertions ();
 }