OSDN Git Service

* real.c (toe64): Remove stale #endif from the last change.
[pf3gnuchains/gcc-fork.git] / gcc / reload1.c
index a716b13..3520883 100644 (file)
@@ -39,6 +39,7 @@ Boston, MA 02111-1307, USA.  */
 #include "reload.h"
 #include "recog.h"
 #include "output.h"
+#include "cselib.h"
 #include "real.h"
 #include "toplev.h"
 
@@ -119,7 +120,7 @@ rtx *reg_equiv_address;
 rtx *reg_equiv_mem;
 
 /* Widest width in which each pseudo reg is referred to (via subreg).  */
-static int *reg_max_ref_width;
+static unsigned int *reg_max_ref_width;
 
 /* Element N is the list of insns that initialized reg N from its equivalent
    constant or memory slot.  */
@@ -236,7 +237,7 @@ char double_reg_address_ok;
 static rtx spill_stack_slot[FIRST_PSEUDO_REGISTER];
 
 /* Width allocated so far for that stack slot.  */
-static int spill_stack_slot_width[FIRST_PSEUDO_REGISTER];
+static unsigned int spill_stack_slot_width[FIRST_PSEUDO_REGISTER];
 
 /* Record which pseudos needed to be spilled.  */
 static regset_head spilled_pseudos;
@@ -392,7 +393,7 @@ static void set_initial_label_offsets       PARAMS ((void));
 static void set_offsets_for_label      PARAMS ((rtx));
 static void init_elim_table            PARAMS ((void));
 static void update_eliminables         PARAMS ((HARD_REG_SET *));
-static void spill_hard_reg             PARAMS ((int, FILE *, int));
+static void spill_hard_reg             PARAMS ((unsigned int, FILE *, int));
 static int finish_spills               PARAMS ((int, FILE *));
 static void ior_hard_reg_set           PARAMS ((HARD_REG_SET *, HARD_REG_SET *));
 static void scan_paradoxical_subregs   PARAMS ((rtx));
@@ -401,28 +402,33 @@ 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 void mark_reload_reg_in_use     PARAMS ((int, int, enum reload_type,
-                                              enum machine_mode));
-static void clear_reload_reg_in_use    PARAMS ((int, int, enum reload_type,
-                                              enum machine_mode));
-static int reload_reg_free_p           PARAMS ((int, int, enum reload_type));
+static void mark_reload_reg_in_use     PARAMS ((unsigned int, int,
+                                                enum reload_type,
+                                                enum machine_mode));
+static void clear_reload_reg_in_use    PARAMS ((unsigned int, int,
+                                                enum reload_type,
+                                                enum machine_mode));
+static int reload_reg_free_p           PARAMS ((unsigned int, int,
+                                                enum reload_type));
 static int reload_reg_free_for_value_p PARAMS ((int, int, enum reload_type,
-                                              rtx, rtx, int, int));
-static int reload_reg_reaches_end_p    PARAMS ((int, int, enum reload_type));
-static int allocate_reload_reg         PARAMS ((struct insn_chain *, int, int));
+                                                rtx, rtx, int, int));
+static int reload_reg_reaches_end_p    PARAMS ((unsigned int, int,
+                                                enum reload_type));
+static int allocate_reload_reg         PARAMS ((struct insn_chain *, int,
+                                                int));
 static void failed_reload              PARAMS ((rtx, int));
 static int set_reload_reg              PARAMS ((int, int));
 static void choose_reload_regs_init    PARAMS ((struct insn_chain *, rtx *));
 static void choose_reload_regs         PARAMS ((struct insn_chain *));
 static void merge_assigned_reloads     PARAMS ((rtx));
 static void emit_input_reload_insns    PARAMS ((struct insn_chain *,
-                                              struct reload *, rtx, int));
+                                                struct reload *, rtx, int));
 static void emit_output_reload_insns   PARAMS ((struct insn_chain *,
-                                              struct reload *, int));
+                                                struct reload *, int));
 static void do_input_reload            PARAMS ((struct insn_chain *,
-                                              struct reload *, int));
+                                                struct reload *, int));
 static void do_output_reload           PARAMS ((struct insn_chain *,
-                                              struct reload *, int));
+                                                struct reload *, int));
 static void emit_reload_insns          PARAMS ((struct insn_chain *));
 static void delete_output_reload       PARAMS ((rtx, int, int));
 static void delete_address_reloads     PARAMS ((rtx, rtx));
@@ -430,28 +436,23 @@ 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 void reload_cse_invalidate_regno        PARAMS ((int, enum machine_mode, int));
-static int reload_cse_mem_conflict_p   PARAMS ((rtx, rtx));
-static void reload_cse_invalidate_mem  PARAMS ((rtx));
-static void reload_cse_invalidate_rtx  PARAMS ((rtx, rtx, void *));
-static int reload_cse_regno_equal_p    PARAMS ((int, rtx, enum machine_mode));
-static int reload_cse_noop_set_p       PARAMS ((rtx, 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));
-static void reload_cse_check_clobber   PARAMS ((rtx, rtx, void *));
-static void reload_cse_record_set      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 *));
+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));
+static void add_auto_inc_notes         PARAMS ((rtx, rtx));
 #endif
 static rtx gen_mode_int                        PARAMS ((enum machine_mode,
-                                              HOST_WIDE_INT));
+                                                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));
 extern void dump_needs                 PARAMS ((struct insn_chain *, FILE *));
 \f
 /* Initialize the reload pass once per compilation.  */
@@ -540,17 +541,20 @@ new_insn_chain ()
 
 /* Small utility function to set all regs in hard reg set TO which are
    allocated to pseudos in regset FROM.  */
+
 void
 compute_use_by_pseudos (to, from)
      HARD_REG_SET *to;
      regset from;
 {
-  int regno;
+  unsigned int regno;
+
   EXECUTE_IF_SET_IN_REG_SET
     (from, FIRST_PSEUDO_REGISTER, regno,
      {
        int r = reg_renumber[regno];
        int nregs;
+
        if (r < 0)
         {
           /* reload_combine uses the information from
@@ -1481,6 +1485,7 @@ static int spill_cost[FIRST_PSEUDO_REGISTER];
 static int spill_add_cost[FIRST_PSEUDO_REGISTER];
 
 /* Update the spill cost arrays, considering that pseudo REG is live.  */
+
 static void
 count_pseudo (reg)
      int reg;
@@ -1558,6 +1563,7 @@ static HARD_REG_SET used_spill_regs_local;
    SPILLED_NREGS.  Determine how pseudo REG, which is live during the insn,
    is affected.  We will add it to SPILLED_PSEUDOS if necessary, and we will
    update SPILL_COST/SPILL_ADD_COST.  */
+
 static void
 count_spilled_pseudo (spilled, spilled_nregs, reg)
      int spilled, spilled_nregs, reg;
@@ -1588,7 +1594,8 @@ find_reg (chain, order, dumpfile)
   struct reload *rl = rld + rnum;
   int best_cost = INT_MAX;
   int best_reg = -1;
-  int i, j;
+  unsigned int i, j;
+  int k;
   HARD_REG_SET not_usable;
   HARD_REG_SET used_by_other_reload;
 
@@ -1597,9 +1604,10 @@ find_reg (chain, order, dumpfile)
   IOR_COMPL_HARD_REG_SET (not_usable, reg_class_contents[rl->class]);
 
   CLEAR_HARD_REG_SET (used_by_other_reload);
-  for (i = 0; i < order; i++)
+  for (k = 0; k < order; k++)
     {
-      int other = reload_order[i];
+      int other = reload_order[k];
+
       if (rld[other].regno >= 0 && reloads_conflict (other, rnum))
        for (j = 0; j < rld[other].nregs; j++)
          SET_HARD_REG_BIT (used_by_other_reload, rld[other].regno + j);
@@ -1607,14 +1615,15 @@ find_reg (chain, order, dumpfile)
 
   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
     {
-      int regno = i;
+      unsigned int regno = i;
+
       if (! TEST_HARD_REG_BIT (not_usable, regno)
          && ! TEST_HARD_REG_BIT (used_by_other_reload, regno)
          && HARD_REGNO_MODE_OK (regno, rl->mode))
        {
          int this_cost = spill_cost[regno];
          int ok = 1;
-         int this_nregs = HARD_REGNO_NREGS (regno, rl->mode);
+         unsigned int this_nregs = HARD_REGNO_NREGS (regno, rl->mode);
 
          for (j = 1; j < this_nregs; j++)
            {
@@ -1649,8 +1658,10 @@ find_reg (chain, order, dumpfile)
     }
   if (best_reg == -1)
     return 0;
+
   if (dumpfile)
     fprintf (dumpfile, "Using reg %d for reload %d\n", best_reg, rnum);
+
   rl->nregs = HARD_REGNO_NREGS (best_reg, rl->mode);
   rl->regno = best_reg;
 
@@ -1659,6 +1670,7 @@ find_reg (chain, order, dumpfile)
      {
        count_spilled_pseudo (best_reg, rl->nregs, j);
      });
+
   EXECUTE_IF_SET_IN_REG_SET
     (&chain->dead_or_set, FIRST_PSEUDO_REGISTER, j,
      {
@@ -1699,7 +1711,8 @@ find_reload_regs (chain, dumpfile)
        {
          int regno = REGNO (chain->rld[i].reg_rtx);
          chain->rld[i].regno = regno;
-         chain->rld[i].nregs = HARD_REGNO_NREGS (regno, GET_MODE (chain->rld[i].reg_rtx));
+         chain->rld[i].nregs
+           = HARD_REGNO_NREGS (regno, GET_MODE (chain->rld[i].reg_rtx));
        }
       else
        chain->rld[i].regno = -1;
@@ -1874,8 +1887,8 @@ alter_reg (i, from_reg)
       && reg_equiv_memory_loc[i] == 0)
     {
       register rtx x;
-      int inherent_size = PSEUDO_REGNO_BYTES (i);
-      int total_size = MAX (inherent_size, reg_max_ref_width[i]);
+      unsigned int inherent_size = PSEUDO_REGNO_BYTES (i);
+      unsigned int total_size = MAX (inherent_size, reg_max_ref_width[i]);
       int adjust = 0;
 
       /* Each pseudo reg has an inherent size which comes from its own mode,
@@ -1976,6 +1989,7 @@ mark_home_live (regno)
      int regno;
 {
   register int i, lim;
+
   i = reg_renumber[regno];
   if (i < 0)
     return;
@@ -3425,7 +3439,7 @@ init_elim_table ()
 
 static void
 spill_hard_reg (regno, dumpfile, cant_eliminate)
-     register int regno;
+     unsigned int regno;
      FILE *dumpfile ATTRIBUTE_UNUSED;
      int cant_eliminate;
 {
@@ -3442,9 +3456,9 @@ spill_hard_reg (regno, dumpfile, cant_eliminate)
 
   for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
     if (reg_renumber[i] >= 0
-       && reg_renumber[i] <= regno
-       && (reg_renumber[i]
-           + HARD_REGNO_NREGS (reg_renumber[i],
+       && (unsigned int) reg_renumber[i] <= regno
+       && ((unsigned int) reg_renumber[i]
+           + HARD_REGNO_NREGS ((unsigned int) reg_renumber[i],
                                PSEUDO_REGNO_MODE (i))
            > regno))
       SET_REGNO_REG_SET (&spilled_pseudos, i);
@@ -3452,6 +3466,7 @@ spill_hard_reg (regno, dumpfile, cant_eliminate)
 
 /* I'm getting weird preprocessor errors if I use IOR_HARD_REG_SET
    from within EXECUTE_IF_SET_IN_REG_SET.  Hence this awkwardness.  */
+
 static void
 ior_hard_reg_set (set1, set2)
      HARD_REG_SET *set1, *set2;
@@ -3962,8 +3977,8 @@ forget_old_reloads_1 (x, ignored, data)
      rtx ignored ATTRIBUTE_UNUSED;
      void *data ATTRIBUTE_UNUSED;
 {
-  register int regno;
-  int nr;
+  unsigned int regno;
+  unsigned int nr;
   int offset = 0;
 
   /* note_stores does give us subregs of hard regs.  */
@@ -3982,7 +3997,8 @@ forget_old_reloads_1 (x, ignored, data)
     nr = 1;
   else
     {
-      int i;
+      unsigned int i;
+
       nr = HARD_REGNO_NREGS (regno, GET_MODE (x));
       /* Storing into a spilled-reg invalidates its contents.
         This can happen if a block-local pseudo is allocated to that reg
@@ -4051,13 +4067,13 @@ static HARD_REG_SET reg_used_in_insn;
 
 static void
 mark_reload_reg_in_use (regno, opnum, type, mode)
-     int regno;
+     unsigned int regno;
      int opnum;
      enum reload_type type;
      enum machine_mode mode;
 {
-  int nregs = HARD_REGNO_NREGS (regno, mode);
-  int i;
+  unsigned int nregs = HARD_REGNO_NREGS (regno, mode);
+  unsigned int i;
 
   for (i = regno; i < nregs + regno; i++)
     {
@@ -4116,13 +4132,13 @@ mark_reload_reg_in_use (regno, opnum, type, mode)
 
 static void
 clear_reload_reg_in_use (regno, opnum, type, mode)
-     int regno;
+     unsigned int regno;
      int opnum;
      enum reload_type type;
      enum machine_mode mode;
 {
-  int nregs = HARD_REGNO_NREGS (regno, mode);
-  int start_regno, end_regno;
+  unsigned int nregs = HARD_REGNO_NREGS (regno, mode);
+  unsigned int start_regno, end_regno, r;
   int i;
   /* A complication is that for some reload types, inheritance might
      allow multiple reloads of the same types to share a reload register.
@@ -4202,8 +4218,8 @@ clear_reload_reg_in_use (regno, opnum, type, mode)
              && (check_any || rld[i].opnum == opnum)
              && rld[i].reg_rtx)
            {
-             int conflict_start = true_regnum (rld[i].reg_rtx);
-             int conflict_end
+             unsigned int conflict_start = true_regnum (rld[i].reg_rtx);
+             unsigned int conflict_end
                = (conflict_start
                   + HARD_REGNO_NREGS (conflict_start, rld[i].mode));
 
@@ -4218,8 +4234,9 @@ clear_reload_reg_in_use (regno, opnum, type, mode)
            }
        }
     }
-  for (i = start_regno; i < end_regno; i++)
-    CLEAR_HARD_REG_BIT (*used_in_set, i);
+
+  for (r = start_regno; r < end_regno; r++)
+    CLEAR_HARD_REG_BIT (*used_in_set, r);
 }
 
 /* 1 if reg REGNO is free as a reload reg for a reload of the sort
@@ -4227,7 +4244,7 @@ clear_reload_reg_in_use (regno, opnum, type, mode)
 
 static int
 reload_reg_free_p (regno, opnum, type)
-     int regno;
+     unsigned int regno;
      int opnum;
      enum reload_type type;
 {
@@ -4387,7 +4404,7 @@ reload_reg_free_p (regno, opnum, type)
 
 static int
 reload_reg_reaches_end_p (regno, opnum, type)
-     int regno;
+     unsigned int regno;
      int opnum;
      enum reload_type type;
 {
@@ -5107,7 +5124,7 @@ choose_reload_regs (chain)
 {
   rtx insn = chain->insn;
   register int i, j;
-  int max_group_size = 1;
+  unsigned int max_group_size = 1;
   enum reg_class group_class = NO_REGS;
   int pass, win, inheritance;
 
@@ -5130,7 +5147,8 @@ choose_reload_regs (chain)
       if (rld[j].nregs > 1)
        {
          max_group_size = MAX (rld[j].nregs, max_group_size);
-         group_class = reg_class_superunion[(int)rld[j].class][(int)group_class];
+         group_class
+           = reg_class_superunion[(int)rld[j].class][(int)group_class];
        }
 
       save_reload_reg_rtx[j] = rld[j].reg_rtx;
@@ -5152,11 +5170,11 @@ choose_reload_regs (chain)
       /* Process the reloads in order of preference just found.
         Beyond this point, subregs can be found in reload_reg_rtx.
 
-        This used to look for an existing reloaded home for all
-        of the reloads, and only then perform any new reloads.
-        But that could lose if the reloads were done out of reg-class order
-        because a later reload with a looser constraint might have an old
-        home in a register needed by an earlier reload with a tighter constraint.
+        This used to look for an existing reloaded home for all of the
+        reloads, and only then perform any new reloads.  But that could lose
+        if the reloads were done out of reg-class order because a later
+        reload with a looser constraint might have an old home in a register
+        needed by an earlier reload with a tighter constraint.
 
         To solve this, we make two passes over the reloads, in the order
         described above.  In the first pass we try to inherit a reload
@@ -5879,6 +5897,7 @@ static HARD_REG_SET reg_reloaded_died;
 
 /* Generate insns to perform reload RL, which is for the insn in CHAIN and
    has the number J.  OLD contains the value to be used as input.  */
+
 static void
 emit_input_reload_insns (chain, rl, old, j)
      struct insn_chain *chain;
@@ -5963,7 +5982,7 @@ emit_input_reload_insns (chain, rl, old, j)
 
   if (oldequiv)
     {
-      int regno = true_regnum (oldequiv);
+      unsigned int regno = true_regnum (oldequiv);
 
       /* Don't use OLDEQUIV if any other reload changes it at an
         earlier stage of this insn or at this stage.  */
@@ -7842,229 +7861,110 @@ count_occurrences (x, find)
   return count;
 }
 \f
-/* This array holds values which are equivalent to a hard register
-   during reload_cse_regs.  Each array element is an EXPR_LIST of
-   values.  Each time a hard register is set, we set the corresponding
-   array element to the value.  Each time a hard register is copied
-   into memory, we add the memory location to the corresponding array
-   element.  We don't store values or memory addresses with side
-   effects in this array.
-
-   If the value is a CONST_INT, then the mode of the containing
-   EXPR_LIST is the mode in which that CONST_INT was referenced.
-
-   We sometimes clobber a specific entry in a list.  In that case, we
-   just set XEXP (list-entry, 0) to 0.  */
-
-static rtx *reg_values;
-
-/* This is a preallocated REG rtx which we use as a temporary in
-   reload_cse_invalidate_regno, so that we don't need to allocate a
-   new one each time through a loop in that function.  */
-
-static rtx invalidate_regno_rtx;
-
-/* Invalidate any entries in reg_values which depend on REGNO,
-   including those for REGNO itself.  This is called if REGNO is
-   changing.  If CLOBBER is true, then always forget anything we
-   currently know about REGNO.  MODE is the mode of the assignment to
-   REGNO, which is used to determine how many hard registers are being
-   changed.  If MODE is VOIDmode, then only REGNO is being changed;
-   this is used when invalidating call clobbered registers across a
-   call.  */
-
+/* 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_invalidate_regno (regno, mode, clobber)
-     int regno;
-     enum machine_mode mode;
-     int clobber;
+reload_cse_delete_noop_set (insn, value)
+     rtx insn, value;
 {
-  int endregno;
-  register int i;
-
-  /* Our callers don't always go through true_regnum; we may see a
-     pseudo-register here from a CLOBBER or the like.  We probably
-     won't ever see a pseudo-register that has a real register number,
-     for we check anyhow for safety.  */
-  if (regno >= FIRST_PSEUDO_REGISTER)
-    regno = reg_renumber[regno];
-  if (regno < 0)
-    return;
-
-  if (mode == VOIDmode)
-    endregno = regno + 1;
-  else
-    endregno = regno + HARD_REGNO_NREGS (regno, mode);
-
-  if (clobber)
-    for (i = regno; i < endregno; i++)
-      reg_values[i] = 0;
-
-  for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+  if (value)
     {
-      rtx x;
-
-      for (x = reg_values[i]; x; x = XEXP (x, 1))
-       {
-         if (XEXP (x, 0) != 0
-             && refers_to_regno_p (regno, endregno, XEXP (x, 0), NULL_PTR))
-           {
-             /* If this is the only entry on the list, clear
-                reg_values[i].  Otherwise, just clear this entry on
-                the list.  */
-             if (XEXP (x, 1) == 0 && x == reg_values[i])
-               {
-                 reg_values[i] = 0;
-                 break;
-               }
-             XEXP (x, 0) = 0;
-           }
-       }
+      PATTERN (insn) = gen_rtx_USE (VOIDmode, value);
+      INSN_CODE (insn) = -1;
+      REG_NOTES (insn) = NULL_RTX;
     }
-
-  /* We must look at earlier registers, in case REGNO is part of a
-     multi word value but is not the first register.  If an earlier
-     register has a value in a mode which overlaps REGNO, then we must
-     invalidate that earlier register.  Note that we do not need to
-     check REGNO or later registers (we must not check REGNO itself,
-     because we would incorrectly conclude that there was a conflict).  */
-
-  for (i = 0; i < regno; i++)
+  else
     {
-      rtx x;
-
-      for (x = reg_values[i]; x; x = XEXP (x, 1))
-       {
-         if (XEXP (x, 0) != 0)
-           {
-             PUT_MODE (invalidate_regno_rtx, GET_MODE (x));
-             REGNO (invalidate_regno_rtx) = i;
-             if (refers_to_regno_p (regno, endregno, invalidate_regno_rtx,
-                                    NULL_PTR))
-               {
-                 reload_cse_invalidate_regno (i, VOIDmode, 1);
-                 break;
-               }
-           }
-       }
+      PUT_CODE (insn, NOTE);
+      NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
+      NOTE_SOURCE_FILE (insn) = 0;
     }
 }
 
-/* The memory at address MEM_BASE is being changed.
-   Return whether this change will invalidate VAL.  */
-
+/* See whether a single set SET is a noop.  */
 static int
-reload_cse_mem_conflict_p (mem_base, val)
-     rtx mem_base;
-     rtx val;
+reload_cse_noop_set_p (set)
+     rtx set;
 {
-  enum rtx_code code;
-  const char *fmt;
-  int i;
-
-  code = GET_CODE (val);
-  switch (code)
-    {
-      /* Get rid of a few simple cases quickly. */
-    case REG:
-    case PC:
-    case CC0:
-    case SCRATCH:
-    case CONST:
-    case CONST_INT:
-    case CONST_DOUBLE:
-    case SYMBOL_REF:
-    case LABEL_REF:
-      return 0;
-
-    case MEM:
-      if (GET_MODE (mem_base) == BLKmode
-         || GET_MODE (val) == BLKmode)
-       return 1;
-      if (anti_dependence (val, mem_base))
-       return 1;
-      /* The address may contain nested MEMs.  */
-      break;
-
-    default:
-      break;
-    }
+  return rtx_equal_for_cselib_p (SET_DEST (set), SET_SRC (set));
+}
 
-  fmt = GET_RTX_FORMAT (code);
+/* Try to simplify INSN.  */
+static void
+reload_cse_simplify (insn)
+     rtx insn;
+{
+  rtx body = PATTERN (insn);
 
-  for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
+  if (GET_CODE (body) == SET)
     {
-      if (fmt[i] == 'e')
+      int count = 0;
+      if (reload_cse_noop_set_p (body))
        {
-         if (reload_cse_mem_conflict_p (mem_base, XEXP (val, i)))
-           return 1;
-       }
-      else if (fmt[i] == 'E')
-       {
-         int j;
-
-         for (j = 0; j < XVECLEN (val, i); j++)
-           if (reload_cse_mem_conflict_p (mem_base, XVECEXP (val, i, j)))
-             return 1;
+         rtx value = SET_DEST (body);
+         if (! REG_FUNCTION_VALUE_P (SET_DEST (body)))
+           value = 0;
+         reload_cse_delete_noop_set (insn, value);
+         return;
        }
-    }
-
-  return 0;
-}
-
-/* Invalidate any entries in reg_values which are changed because of a
-   store to MEM_RTX.  If this is called because of a non-const call
-   instruction, MEM_RTX is (mem:BLK const0_rtx).  */
 
-static void
-reload_cse_invalidate_mem (mem_rtx)
-     rtx mem_rtx;
-{
-  register int i;
+      /* It's not a no-op, but we can try to simplify it.  */
+      count += reload_cse_simplify_set (body, insn);
 
-  for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+      if (count > 0)
+       apply_change_group ();
+      else
+       reload_cse_simplify_operands (insn);
+    }
+  else if (GET_CODE (body) == PARALLEL)
     {
-      rtx x;
+      int i;
+      int count = 0;
+      rtx value = NULL_RTX;
 
-      for (x = reg_values[i]; x; x = XEXP (x, 1))
+      /* If every action in a PARALLEL is a noop, we can delete
+        the entire PARALLEL.  */
+      for (i = XVECLEN (body, 0) - 1; i >= 0; --i)
        {
-         if (XEXP (x, 0) != 0
-             && reload_cse_mem_conflict_p (mem_rtx, XEXP (x, 0)))
+         rtx part = XVECEXP (body, 0, i);
+         if (GET_CODE (part) == SET)
            {
-             /* If this is the only entry on the list, clear
-                reg_values[i].  Otherwise, just clear this entry on
-                the list.  */
-             if (XEXP (x, 1) == 0 && x == reg_values[i])
+             if (! reload_cse_noop_set_p (part))
+               break;
+             if (REG_FUNCTION_VALUE_P (SET_DEST (part)))
                {
-                 reg_values[i] = 0;
-                 break;
+                 if (value)
+                   break;
+                 value = SET_DEST (part);
                }
-             XEXP (x, 0) = 0;
            }
+         else if (GET_CODE (part) != CLOBBER)
+           break;
        }
-    }
-}
 
-/* Invalidate DEST, which is being assigned to or clobbered.  The
-   second parameter exists so that this function can be passed to
-   note_stores; it is ignored.  */
+      if (i < 0)
+       {
+         reload_cse_delete_noop_set (insn, value);
+         /* We're done with this insn.  */
+         return;
+       }
 
-static void
-reload_cse_invalidate_rtx (dest, ignore, data)
-     rtx dest;
-     rtx ignore ATTRIBUTE_UNUSED;
-     void *data ATTRIBUTE_UNUSED;
-{
-  while (GET_CODE (dest) == STRICT_LOW_PART
-        || GET_CODE (dest) == SIGN_EXTRACT
-        || GET_CODE (dest) == ZERO_EXTRACT
-        || GET_CODE (dest) == SUBREG)
-    dest = XEXP (dest, 0);
-
-  if (GET_CODE (dest) == REG)
-    reload_cse_invalidate_regno (REGNO (dest), GET_MODE (dest), 1);
-  else if (GET_CODE (dest) == MEM)
-    reload_cse_invalidate_mem (dest);
+      /* 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);
+    }
 }
 
 /* Do a very simple CSE pass over the hard registers.
@@ -8088,223 +7988,22 @@ static void
 reload_cse_regs_1 (first)
      rtx first;
 {
-  char *firstobj;
-  rtx callmem;
-  register int i;
   rtx insn;
 
+  cselib_init ();  
   init_alias_analysis ();
 
-  reg_values = (rtx *) alloca (FIRST_PSEUDO_REGISTER * sizeof (rtx));
-  bzero ((char *)reg_values, FIRST_PSEUDO_REGISTER * sizeof (rtx));
-
-  /* Create our EXPR_LIST structures on reload_obstack, so that we can
-     free them when we are done.  */
-  push_obstacks (&reload_obstack, &reload_obstack);
-  firstobj = (char *) obstack_alloc (&reload_obstack, 0);
-
-  /* We pass this to reload_cse_invalidate_mem to invalidate all of
-     memory for a non-const call instruction.  */
-  callmem = gen_rtx_MEM (BLKmode, const0_rtx);
-
-  /* This is used in reload_cse_invalidate_regno to avoid consing a
-     new REG in a loop in that function.  */
-  invalidate_regno_rtx = gen_rtx_REG (VOIDmode, 0);
-
   for (insn = first; insn; insn = NEXT_INSN (insn))
     {
-      rtx body;
-
-      if (GET_CODE (insn) == CODE_LABEL)
-       {
-         /* Forget all the register values at a code label.  We don't
-            try to do anything clever around jumps.  */
-         for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
-           reg_values[i] = 0;
-
-         continue;
-       }
-
-#ifdef NON_SAVING_SETJMP
-      if (NON_SAVING_SETJMP && GET_CODE (insn) == NOTE
-         && NOTE_LINE_NUMBER (insn) == NOTE_INSN_SETJMP)
-       {
-         for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
-           reg_values[i] = 0;
-
-         continue;
-       }
-#endif
-
-      if (GET_RTX_CLASS (GET_CODE (insn)) != 'i')
-       continue;
-
-      /* If this is a call instruction, forget anything stored in a
-        call clobbered register, or, if this is not a const call, in
-        memory.  */
-      if (GET_CODE (insn) == CALL_INSN)
-       {
-         for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
-           if (call_used_regs[i])
-             reload_cse_invalidate_regno (i, VOIDmode, 1);
-
-         if (! CONST_CALL_P (insn))
-           reload_cse_invalidate_mem (callmem);
-       }
-
-
-      /* Forget all the register values at a volatile asm.  */
-      if (GET_CODE (insn) == INSN
-         && GET_CODE (PATTERN (insn)) == ASM_OPERANDS
-         && MEM_VOLATILE_P (PATTERN (insn)))
-       for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
-         reg_values[i] = 0;
-
-      body = PATTERN (insn);
-      if (GET_CODE (body) == SET)
-       {
-         int count = 0;
-         if (reload_cse_noop_set_p (body, insn))
-           {
-             /* 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.  */
-             if (REG_FUNCTION_VALUE_P (SET_DEST (body)))
-               {
-                 pop_obstacks ();
-                 PATTERN (insn) = gen_rtx_USE (VOIDmode, SET_DEST (body));
-                 INSN_CODE (insn) = -1;
-                 REG_NOTES (insn) = NULL_RTX;
-                 push_obstacks (&reload_obstack, &reload_obstack);
-               }
-             else
-               {
-                 PUT_CODE (insn, NOTE);
-                 NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
-                 NOTE_SOURCE_FILE (insn) = 0;
-               }
-
-             /* We're done with this insn.  */
-             continue;
-           }
-
-         /* It's not a no-op, but we can try to simplify it.  */
-         count += reload_cse_simplify_set (body, insn);
-
-         if (count > 0)
-           apply_change_group ();
-         else
-           reload_cse_simplify_operands (insn);
-
-         reload_cse_record_set (body, body);
-       }
-      else if (GET_CODE (body) == PARALLEL)
-       {
-         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, insn))
-                   break;
-                 if (REG_FUNCTION_VALUE_P (SET_DEST (part)))
-                   {
-                     if (value)
-                       break;
-                     value = SET_DEST (part);
-                   }
-               }
-             else if (GET_CODE (part) != CLOBBER)
-               break;
-           }
-         if (i < 0)
-           {
-             if (value)
-               {
-                 pop_obstacks ();
-                 PATTERN (insn) = gen_rtx_USE (VOIDmode, value);
-                 INSN_CODE (insn) = -1;
-                 REG_NOTES (insn) = NULL_RTX;
-                 push_obstacks (&reload_obstack, &reload_obstack);
-               }
-             else
-               {
-                 PUT_CODE (insn, NOTE);
-                 NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
-                 NOTE_SOURCE_FILE (insn) = 0;
-               }
-
-             /* We're done with this insn.  */
-             continue;
-           }
-
-         /* 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);
-
-         /* Look through the PARALLEL and record the values being
-            set, if possible.  Also handle any CLOBBERs.  */
-         for (i = XVECLEN (body, 0) - 1; i >= 0; --i)
-           {
-             rtx x = XVECEXP (body, 0, i);
-
-             if (GET_CODE (x) == SET)
-               reload_cse_record_set (x, body);
-             else
-               note_stores (x, reload_cse_invalidate_rtx, NULL);
-           }
-       }
-      else
-       note_stores (body, reload_cse_invalidate_rtx, NULL);
-
-#ifdef AUTO_INC_DEC
-      /* Clobber any registers which appear in REG_INC notes.  We
-        could keep track of the changes to their values, but it is
-        unlikely to help.  */
-      {
-       rtx x;
-
-       for (x = REG_NOTES (insn); x; x = XEXP (x, 1))
-         if (REG_NOTE_KIND (x) == REG_INC)
-           reload_cse_invalidate_rtx (XEXP (x, 0), NULL_RTX, NULL);
-      }
-#endif
-
-      /* Look for any CLOBBERs in CALL_INSN_FUNCTION_USAGE, but only
-        after we have processed the insn.  */
-      if (GET_CODE (insn) == CALL_INSN)
-       {
-         rtx x;
+      if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
+       reload_cse_simplify (insn);
 
-         for (x = CALL_INSN_FUNCTION_USAGE (insn); x; x = XEXP (x, 1))
-           if (GET_CODE (XEXP (x, 0)) == CLOBBER)
-             reload_cse_invalidate_rtx (XEXP (XEXP (x, 0), 0), NULL_RTX,
-                                        NULL);
-       }
+      cselib_process_insn (insn);
     }
 
   /* Clean up.  */
   end_alias_analysis ();
-
-  /* Free all the temporary structures we created, and go back to the
-     regular obstacks.  */
-  obstack_free (&reload_obstack, firstobj);
-  pop_obstacks ();
+  cselib_finish ();
 }
 
 /* Call cse / combine like post-reload optimization phases.
@@ -8320,127 +8019,6 @@ reload_cse_regs (first)
     reload_cse_regs_1 (first);
 }
 
-/* Return whether the values known for REGNO are equal to VAL.  MODE
-   is the mode of the object that VAL is being copied to; this matters
-   if VAL is a CONST_INT.  */
-
-static int
-reload_cse_regno_equal_p (regno, val, mode)
-     int regno;
-     rtx val;
-     enum machine_mode mode;
-{
-  rtx x;
-
-  if (val == 0)
-    return 0;
-
-  for (x = reg_values[regno]; x; x = XEXP (x, 1))
-    if (XEXP (x, 0) != 0
-       && rtx_equal_p (XEXP (x, 0), val)
-       && (! flag_float_store || GET_CODE (XEXP (x, 0)) != MEM
-           || GET_MODE_CLASS (GET_MODE (x)) != MODE_FLOAT)
-       && (GET_CODE (val) != CONST_INT
-           || mode == GET_MODE (x)
-           || (GET_MODE_SIZE (mode) < GET_MODE_SIZE (GET_MODE (x))
-               /* On a big endian machine if the value spans more than
-                  one register then this register holds the high part of
-                  it and we can't use it.
-
-                  ??? We should also compare with the high part of the
-                  value.  */
-               && !(WORDS_BIG_ENDIAN
-                    && HARD_REGNO_NREGS (regno, GET_MODE (x)) > 1)
-               && TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (mode),
-                                         GET_MODE_BITSIZE (GET_MODE (x))))))
-      return 1;
-
-  return 0;
-}
-
-/* See whether a single set is a noop.  SET is the set instruction we
-   are should check, and INSN is the instruction from which it came.  */
-
-static int
-reload_cse_noop_set_p (set, insn)
-     rtx set;
-     rtx insn ATTRIBUTE_UNUSED;
-{
-  rtx src, dest;
-  enum machine_mode dest_mode;
-  int dreg, sreg;
-  int ret;
-
-  src = SET_SRC (set);
-  dest = SET_DEST (set);
-  dest_mode = GET_MODE (dest);
-
-  if (side_effects_p (src))
-    return 0;
-
-  dreg = true_regnum (dest);
-  sreg = true_regnum (src);
-
-  /* Check for setting a register to itself.  In this case, we don't
-     have to worry about REG_DEAD notes.  */
-  if (dreg >= 0 && dreg == sreg)
-    return 1;
-
-  ret = 0;
-  if (dreg >= 0)
-    {
-      /* Check for setting a register to itself.  */
-      if (dreg == sreg)
-       ret = 1;
-
-      /* Check for setting a register to a value which we already know
-        is in the register.  */
-      else if (reload_cse_regno_equal_p (dreg, src, dest_mode))
-       ret = 1;
-
-      /* Check for setting a register DREG to another register SREG
-        where SREG is equal to a value which is already in DREG.  */
-      else if (sreg >= 0)
-       {
-         rtx x;
-
-         for (x = reg_values[sreg]; x; x = XEXP (x, 1))
-           {
-             rtx tmp;
-
-             if (XEXP (x, 0) == 0)
-               continue;
-
-             if (dest_mode == GET_MODE (x))
-               tmp = XEXP (x, 0);
-             else if (GET_MODE_BITSIZE (dest_mode)
-                      < GET_MODE_BITSIZE (GET_MODE (x)))
-               tmp = gen_lowpart_common (dest_mode, XEXP (x, 0));
-             else
-               continue;
-
-             if (tmp
-                 && reload_cse_regno_equal_p (dreg, tmp, dest_mode))
-               {
-                 ret = 1;
-                 break;
-               }
-           }
-       }
-    }
-  else if (GET_CODE (dest) == MEM)
-    {
-      /* Check for storing a register to memory when we know that the
-        register is equivalent to the memory location. */
-      if (sreg >= 0
-         && reload_cse_regno_equal_p (sreg, dest, dest_mode)
-         && ! side_effects_p (dest))
-       ret = 1;
-    }
-
-  return ret;
-}
-
 /* 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
@@ -8452,11 +8030,13 @@ reload_cse_simplify_set (set, insn)
      rtx set;
      rtx insn;
 {
+  int did_change = 0;
   int dreg;
   rtx src;
-  enum machine_mode dest_mode;
   enum reg_class dclass;
-  register int i;
+  int old_cost;
+  cselib_val *val;
+  struct elt_loc_list *l;
 
   dreg = true_regnum (SET_DEST (set));
   if (dreg < 0)
@@ -8469,39 +8049,40 @@ reload_cse_simplify_set (set, insn)
   dclass = REGNO_REG_CLASS (dreg);
 
   /* If memory loads are cheaper than register copies, don't change them.  */
-  if (GET_CODE (src) == MEM
-      && MEMORY_MOVE_COST (GET_MODE (src), dclass, 1) < 2)
-    return 0;
+  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 (REGNO_REG_CLASS (REGNO (src)), dclass);
+  else
+    /* ???   */
+    old_cost = rtx_cost (src, SET);
 
-  /* If the constant is cheaper than a register, don't change it.  */
-  if (CONSTANT_P (src)
-      && rtx_cost (src, SET) < 2)
+  val = cselib_lookup (src, VOIDmode, 0);
+  if (! val)
     return 0;
-
-  dest_mode = GET_MODE (SET_DEST (set));
-  for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
-    {
-      if (i != dreg
-         && REGISTER_MOVE_COST (REGNO_REG_CLASS (i), dclass) == 2
-         && reload_cse_regno_equal_p (i, src, dest_mode))
-       {
-         int validated;
-
-         /* Pop back to the real obstacks while changing the insn.  */
-         pop_obstacks ();
-
-         validated = validate_change (insn, &SET_SRC (set),
-                                      gen_rtx_REG (dest_mode, i), 1);
-
-         /* Go back to the obstack we are using for temporary
-            storage.  */
-         push_obstacks (&reload_obstack, &reload_obstack);
-
-         if (validated)
-           return 1;
-       }
+  for (l = val->locs; l; l = l->next)
+    {
+      int this_cost;
+      if (CONSTANT_P (l->loc) && ! references_value_p (l->loc, 0))
+       this_cost = rtx_cost (l->loc, SET);
+      else if (GET_CODE (l->loc) == REG)
+       this_cost = REGISTER_MOVE_COST (REGNO_REG_CLASS (REGNO (l->loc)),
+                                       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 (l->loc) == REG
+              && GET_CODE (SET_SRC (set)) != REG))
+         && validate_change (insn, &SET_SRC (set), copy_rtx (l->loc), 1))
+       old_cost = this_cost, did_change = 1;
     }
-  return 0;
+
+  return did_change;
 }
 
 /* Try to replace operands in INSN with equivalent values that are already
@@ -8521,6 +8102,9 @@ reload_cse_simplify_operands (insn)
 {
   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.  */
@@ -8544,13 +8128,35 @@ reload_cse_simplify_operands (insn)
   /* 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));
   bzero ((char *)alternative_reject, recog_data.n_alternatives * sizeof (int));
   bzero ((char *)alternative_nregs, 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.  */
+      if (GET_CODE (recog_data.operand[i]) == CODE_LABEL)
+       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;
@@ -8590,7 +8196,7 @@ reload_cse_simplify_operands (insn)
        {
          int class = (int) NO_REGS;
 
-         if (! reload_cse_regno_equal_p (regno, recog_data.operand[i], mode))
+         if (! TEST_HARD_REG_BIT (equiv_regs[i], regno))
            continue;
 
          REGNO (reg) = regno;
@@ -8696,9 +8302,6 @@ reload_cse_simplify_operands (insn)
      alternative.  */
   j = alternative_order[0];
 
-  /* Pop back to the real obstacks while changing the insn.  */
-  pop_obstacks ();
-
   for (i = 0; i < recog_data.n_operands; i++)
     {
       enum machine_mode mode = recog_data.operand_mode[i];
@@ -8721,178 +8324,8 @@ reload_cse_simplify_operands (insn)
                       gen_rtx_REG (mode, op_alt_regno[op][j]), 1);
     }
 
-  /* Go back to the obstack we are using for temporary
-     storage.  */
-  push_obstacks (&reload_obstack, &reload_obstack);
-
   return apply_change_group ();
 }
-
-/* These two variables are used to pass information from
-   reload_cse_record_set to reload_cse_check_clobber.  */
-
-static int reload_cse_check_clobbered;
-static rtx reload_cse_check_src;
-
-/* See if DEST overlaps with RELOAD_CSE_CHECK_SRC. If it does, set
-   RELOAD_CSE_CHECK_CLOBBERED.  This is called via note_stores.  The
-   second argument, which is passed by note_stores, is ignored.  */
-
-static void
-reload_cse_check_clobber (dest, ignore, data)
-     rtx dest;
-     rtx ignore ATTRIBUTE_UNUSED;
-     void *data ATTRIBUTE_UNUSED;
-{
-  if (reg_overlap_mentioned_p (dest, reload_cse_check_src))
-    reload_cse_check_clobbered = 1;
-}
-
-/* Record the result of a SET instruction.  SET is the set pattern.
-   BODY is the pattern of the insn that it came from.  */
-
-static void
-reload_cse_record_set (set, body)
-     rtx set;
-     rtx body;
-{
-  rtx dest, src, x;
-  int dreg, sreg;
-  enum machine_mode dest_mode;
-
-  dest = SET_DEST (set);
-  src = SET_SRC (set);
-  dreg = true_regnum (dest);
-  sreg = true_regnum (src);
-  dest_mode = GET_MODE (dest);
-
-  /* Some machines don't define AUTO_INC_DEC, but they still use push
-     instructions.  We need to catch that case here in order to
-     invalidate the stack pointer correctly.  Note that invalidating
-     the stack pointer is different from invalidating DEST.  */
-  x = dest;
-  while (GET_CODE (x) == SUBREG
-        || GET_CODE (x) == ZERO_EXTRACT
-        || GET_CODE (x) == SIGN_EXTRACT
-        || GET_CODE (x) == STRICT_LOW_PART)
-    x = XEXP (x, 0);
-  if (push_operand (x, GET_MODE (x)))
-    {
-      reload_cse_invalidate_rtx (stack_pointer_rtx, NULL_RTX, NULL);
-      reload_cse_invalidate_rtx (dest, NULL_RTX, NULL);
-      return;
-    }
-
-  /* We can only handle an assignment to a register, or a store of a
-     register to a memory location.  For other cases, we just clobber
-     the destination.  We also have to just clobber if there are side
-     effects in SRC or DEST.  */
-  if ((dreg < 0 && GET_CODE (dest) != MEM)
-      || side_effects_p (src)
-      || side_effects_p (dest))
-    {
-      reload_cse_invalidate_rtx (dest, NULL_RTX, NULL);
-      return;
-    }
-
-#ifdef HAVE_cc0
-  /* We don't try to handle values involving CC, because it's a pain
-     to keep track of when they have to be invalidated.  */
-  if (reg_mentioned_p (cc0_rtx, src)
-      || reg_mentioned_p (cc0_rtx, dest))
-    {
-      reload_cse_invalidate_rtx (dest, NULL_RTX, NULL);
-      return;
-    }
-#endif
-
-  /* If BODY is a PARALLEL, then we need to see whether the source of
-     SET is clobbered by some other instruction in the PARALLEL.  */
-  if (GET_CODE (body) == PARALLEL)
-    {
-      int i;
-
-      for (i = XVECLEN (body, 0) - 1; i >= 0; --i)
-       {
-         rtx x;
-
-         x = XVECEXP (body, 0, i);
-         if (x == set)
-           continue;
-
-         reload_cse_check_clobbered = 0;
-         reload_cse_check_src = src;
-         note_stores (x, reload_cse_check_clobber, NULL);
-         if (reload_cse_check_clobbered)
-           {
-             reload_cse_invalidate_rtx (dest, NULL_RTX, NULL);
-             return;
-           }
-       }
-    }
-
-  if (dreg >= 0)
-    {
-      int i;
-
-      /* This is an assignment to a register.  Update the value we
-        have stored for the register.  */
-      if (sreg >= 0)
-       {
-         rtx x;
-
-         /* This is a copy from one register to another.  Any values
-            which were valid for SREG are now valid for DREG.  If the
-            mode changes, we use gen_lowpart_common to extract only
-            the part of the value that is copied.  */
-         reg_values[dreg] = 0;
-         for (x = reg_values[sreg]; x; x = XEXP (x, 1))
-           {
-             rtx tmp;
-
-             if (XEXP (x, 0) == 0)
-               continue;
-             if (dest_mode == GET_MODE (XEXP (x, 0)))
-               tmp = XEXP (x, 0);
-             else if (GET_MODE_BITSIZE (dest_mode)
-                       > GET_MODE_BITSIZE (GET_MODE (XEXP (x, 0))))
-               continue;
-             else
-               tmp = gen_lowpart_common (dest_mode, XEXP (x, 0));
-             if (tmp)
-               reg_values[dreg] = gen_rtx_EXPR_LIST (dest_mode, tmp,
-                                                     reg_values[dreg]);
-           }
-       }
-      else
-       reg_values[dreg] = gen_rtx_EXPR_LIST (dest_mode, src, NULL_RTX);
-
-      /* We've changed DREG, so invalidate any values held by other
-        registers that depend upon it.  */
-      reload_cse_invalidate_regno (dreg, dest_mode, 0);
-
-      /* If this assignment changes more than one hard register,
-        forget anything we know about the others.  */
-      for (i = 1; i < HARD_REGNO_NREGS (dreg, dest_mode); i++)
-       reg_values[dreg + i] = 0;
-    }
-  else if (GET_CODE (dest) == MEM)
-    {
-      /* Invalidate conflicting memory locations.  */
-      reload_cse_invalidate_mem (dest);
-
-      /* If we're storing a register to memory, add DEST to the list
-        in REG_VALUES.  */
-      if (sreg >= 0 && ! side_effects_p (dest))
-       reg_values[sreg] = gen_rtx_EXPR_LIST (dest_mode, dest,
-                                   reg_values[sreg]);
-    }
-  else
-    {
-      /* We should have bailed out earlier.  */
-      abort ();
-    }
-}
 \f
 /* If reload couldn't use reg+reg+offset addressing, try to use reg+reg
    addressing now.
@@ -9376,6 +8809,7 @@ reload_combine_note_use (xp, insn)
    reg_offset[n] / reg_base_reg[n] / reg_mode[n] are only valid if
    reg_set_luid[n] is larger than last_label_luid[n] .  */
 static int reg_set_luid[FIRST_PSEUDO_REGISTER];
+
 /* reg_offset[n] has to be CONST_INT for it and reg_base_reg[n] /
    reg_mode[n] to be valid.
    If reg_offset[n] is a CONST_INT and reg_base_reg[n] is negative, register n
@@ -9386,12 +8820,14 @@ static int reg_set_luid[FIRST_PSEUDO_REGISTER];
 static rtx 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 linearily 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;
 
 /* Generate a CONST_INT and force it in the range of MODE.  */
+
 static rtx
 gen_mode_int (mode, value)
      enum machine_mode mode;
@@ -9492,7 +8928,7 @@ reload_cse_move2add (first)
                                  ...
                                  (set (REGX) (plus (REGX) (CONST_INT B-A)))  */
              else if (GET_CODE (src) == REG
-                      && reg_base_reg[regno] == REGNO (src)
+                      && reg_base_reg[regno] == (int) REGNO (src)
                       && reg_set_luid[regno] > reg_set_luid[REGNO (src)])
                {
                  rtx next = next_nonnote_insn (insn);
@@ -9577,20 +9013,22 @@ reload_cse_move2add (first)
 /* 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;
 {
-  int regno = 0;
-  int i;
-
+  unsigned int regno = 0;
+  unsigned int i;
   enum machine_mode mode = GET_MODE (dst);
+
   if (GET_CODE (dst) == SUBREG)
     {
       regno = SUBREG_WORD (dst);
       dst = SUBREG_REG (dst);
     }
+
   if (GET_CODE (dst) != REG)
     return;
 
@@ -9609,6 +9047,7 @@ move2add_note_store (dst, set, data)
        case PLUS:
          {
            rtx src0 = XEXP (src, 0);
+
            if (GET_CODE (src0) == REG)
              {
                if (REGNO (src0) != regno
@@ -9617,9 +9056,11 @@ move2add_note_store (dst, set, data)
                    reg_base_reg[regno] = REGNO (src0);
                    reg_set_luid[regno] = move2add_luid;
                  }
+
                reg_offset[regno] = XEXP (src, 1);
                break;
              }
+
            reg_set_luid[regno] = move2add_luid;
            reg_offset[regno] = set;    /* Invalidate contents.  */
            break;
@@ -9640,7 +9081,9 @@ move2add_note_store (dst, set, data)
     }
   else
     {
-      for (i = regno + HARD_REGNO_NREGS (regno, mode) - 1; i >= regno; i--)
+      unsigned int endregno = regno + HARD_REGNO_NREGS (regno, mode);
+
+      for (i = regno; i < endregno; i++)
        {
          /* Indicate that this register has been recently written to,
             but the exact contents are not available.  */