OSDN Git Service

* flow.c (attempt_auto_inc): Remove unused variable `bb'.
[pf3gnuchains/gcc-fork.git] / gcc / loop.c
index 91da78b..ddaf017 100644 (file)
@@ -19,10 +19,9 @@ along with GNU CC; see the file COPYING.  If not, write to
 the Free Software Foundation, 59 Temple Place - Suite 330,
 Boston, MA 02111-1307, USA.  */
 
-
 /* This is the loop optimization pass of the compiler.
    It finds invariant computations within loops and moves them
-   to the beginning of the loop.  Then it identifies basic and 
+   to the beginning of the loop.  Then it identifies basic and
    general induction variables.  Strength reduction is applied to the general
    induction variables, and induction variable elimination is applied to
    the basic induction variables.
@@ -42,11 +41,11 @@ Boston, MA 02111-1307, USA.  */
 #include "obstack.h"
 #include "function.h"
 #include "expr.h"
+#include "hard-reg-set.h"
 #include "basic-block.h"
 #include "insn-config.h"
 #include "insn-flags.h"
 #include "regs.h"
-#include "hard-reg-set.h"
 #include "recog.h"
 #include "flags.h"
 #include "real.h"
@@ -192,7 +191,7 @@ struct movable
   rtx set_dest;                        /* The destination of this SET.  */
   rtx dependencies;            /* When INSN is libcall, this is an EXPR_LIST
                                   of any registers used within the LIBCALL.  */
-  int consec;                  /* Number of consecutive following insns 
+  int consec;                  /* Number of consecutive following insns
                                   that must be moved with this one.  */
   unsigned int regno;          /* The register it sets */
   short lifetime;              /* lifetime of that register;
@@ -208,7 +207,7 @@ struct movable
                   that the reg is live outside the range from where it is set
                   to the following label.  */
   unsigned int done : 1;       /* 1 inhibits further processing of this */
-  
+
   unsigned int partial : 1;    /* 1 means this reg is used for zero-extending.
                                   In particular, moving it does not make it
                                   invariant.  */
@@ -242,11 +241,11 @@ static int labels_in_range_p PARAMS ((rtx, int));
 static void count_one_set PARAMS ((rtx, rtx, varray_type, rtx *));
 
 static void count_loop_regs_set PARAMS ((rtx, rtx, varray_type, varray_type,
-                                        int *, int)); 
+                                        int *, int));
 static void note_addr_stored PARAMS ((rtx, rtx, void *));
 static void note_set_pseudo_multiple_uses PARAMS ((rtx, rtx, void *));
 static int loop_reg_used_before_p PARAMS ((const struct loop *, rtx, rtx));
-static void scan_loop PARAMS ((struct loop*, int, int));
+static void scan_loop PARAMS ((struct loop*, int));
 #if 0
 static void replace_call_address PARAMS ((rtx, rtx, rtx));
 #endif
@@ -258,27 +257,27 @@ static void combine_movables PARAMS ((struct movable *, int));
 static int regs_match_p PARAMS ((rtx, rtx, struct movable *));
 static int rtx_equal_for_loop_p PARAMS ((rtx, rtx, struct movable *));
 static void add_label_notes PARAMS ((rtx, rtx));
-static void move_movables PARAMS ((struct loop *loop, struct movable *, 
+static void move_movables PARAMS ((struct loop *loop, struct movable *,
                                   int, int, int));
 static int count_nonfixed_reads PARAMS ((const struct loop *, rtx));
-static void strength_reduce PARAMS ((struct loop *, int, int, int));
+static void strength_reduce PARAMS ((struct loop *, int, int));
 static void find_single_use_in_loop PARAMS ((rtx, rtx, varray_type));
 static int valid_initial_value_p PARAMS ((rtx, rtx, int, rtx));
 static void find_mem_givs PARAMS ((const struct loop *, rtx, rtx, int, int));
-static void record_biv PARAMS ((struct induction *, rtx, rtx, rtx, rtx, rtx *, 
-                               int, int, int));
+static void record_biv PARAMS ((struct induction *, rtx, rtx, rtx, rtx, rtx *,
+                               int, int));
 static void check_final_value PARAMS ((const struct loop *,
                                       struct induction *));
-static void record_giv PARAMS ((const struct loop *, struct induction *, 
-                               rtx, rtx, rtx, rtx, rtx, int, enum g_types, 
+static void record_giv PARAMS ((const struct loop *, struct induction *,
+                               rtx, rtx, rtx, rtx, rtx, int, enum g_types,
                                int, int, rtx *));
 static void update_giv_derive PARAMS ((const struct loop *, rtx));
-static int basic_induction_var PARAMS ((const struct loop *, rtx, 
+static int basic_induction_var PARAMS ((const struct loop *, rtx,
                                        enum machine_mode, rtx, rtx,
-                                       rtx *, rtx *, rtx **, int *));
+                                       rtx *, rtx *, rtx **));
 static rtx simplify_giv_expr PARAMS ((const struct loop *, rtx, int *));
 static int general_induction_var PARAMS ((const struct loop *loop, rtx, rtx *,
-                                         rtx *, rtx *, int, int *));
+                                         rtx *, rtx *, int, int *, enum machine_mode));
 static int consec_sets_giv PARAMS ((const struct loop *, int, rtx,
                                    rtx, rtx, rtx *, rtx *, rtx *));
 static int check_dbra_loop PARAMS ((struct loop *, int));
@@ -293,7 +292,7 @@ static void recombine_givs PARAMS ((const struct loop *, struct iv_class *,
 static int product_cheap_p PARAMS ((rtx, rtx));
 static int maybe_eliminate_biv PARAMS ((const struct loop *, struct iv_class *,
                                        int, int, int));
-static int maybe_eliminate_biv_1 PARAMS ((const struct loop *, rtx, rtx, 
+static int maybe_eliminate_biv_1 PARAMS ((const struct loop *, rtx, rtx,
                                          struct iv_class *, int, rtx));
 static int last_use_this_basic_block PARAMS ((rtx, rtx));
 static void record_initial PARAMS ((rtx, rtx, void *));
@@ -307,6 +306,8 @@ static int replace_loop_mem PARAMS ((rtx *, void *));
 static int replace_loop_reg PARAMS ((rtx *, void *));
 static void note_reg_stored PARAMS ((rtx, rtx, void *));
 static void try_copy_prop PARAMS ((const struct loop *, rtx, unsigned int));
+static void try_swap_copy_prop PARAMS ((const struct loop *, rtx,
+                                        unsigned int));
 static int replace_label PARAMS ((rtx *, void *));
 static rtx check_insn_for_givs PARAMS((struct loop *, rtx, int, int));
 static rtx check_insn_for_bivs PARAMS((struct loop *, rtx, int, int));
@@ -327,16 +328,8 @@ typedef struct rtx_pair {
    && INSN_LUID (INSN) >= INSN_LUID (START)    \
    && INSN_LUID (INSN) <= INSN_LUID (END))
 
-#ifdef HAVE_decrement_and_branch_on_count
-/* Test whether BCT applicable and safe.  */
-static void insert_bct PARAMS ((struct loop *));
-
-/* Auxiliary function that inserts the BCT pattern into the loop.  */
-static void instrument_loop_bct PARAMS ((rtx, rtx, rtx));
-#endif /* HAVE_decrement_and_branch_on_count */
-
 /* Indirect_jump_in_function is computed once per function.  */
-int indirect_jump_in_function = 0;
+static int indirect_jump_in_function;
 static int indirect_jump_in_function_p PARAMS ((rtx));
 
 static int compute_luids PARAMS ((rtx, rtx, int));
@@ -358,7 +351,6 @@ static int copy_cost;
 /* Cost of using a register, to normalize the benefits of a giv.  */
 static int reg_address_cost;
 
-
 void
 init_loop ()
 {
@@ -367,11 +359,7 @@ init_loop ()
 
   add_cost = rtx_cost (gen_rtx_PLUS (word_mode, reg, reg), SET);
 
-#ifdef ADDRESS_COST
-  reg_address_cost = ADDRESS_COST (reg);
-#else
-  reg_address_cost = rtx_cost (reg, MEM);
-#endif
+  reg_address_cost = address_cost (reg, SImode);
 
   /* We multiply by 2 to reconcile the difference in scale between
      these two ways of computing costs.  Otherwise the cost of a copy
@@ -421,11 +409,11 @@ compute_luids (start, end, prev_luid)
    (or 0 if none should be output).  */
 
 void
-loop_optimize (f, dumpfile, unroll_p, bct_p)
+loop_optimize (f, dumpfile, flags)
      /* f is the first instruction of a chain of insns for one function */
      rtx f;
      FILE *dumpfile;
-     int unroll_p, bct_p;
+     int flags;
 {
   register rtx insn;
   register int i;
@@ -465,7 +453,7 @@ loop_optimize (f, dumpfile, unroll_p, bct_p)
   max_uid_for_loop = get_max_uid () + 1 + max_loop_num * 32;
 
   uid_luid = (int *) xcalloc (max_uid_for_loop, sizeof (int));
-  uid_loop = (struct loop **) xcalloc (max_uid_for_loop, 
+  uid_loop = (struct loop **) xcalloc (max_uid_for_loop,
                                       sizeof (struct loop *));
 
   /* Allocate storage for array of loops.  */
@@ -531,7 +519,7 @@ loop_optimize (f, dumpfile, unroll_p, bct_p)
       struct loop *loop = &loops->array[i];
 
       if (! loop->invalid && loop->end)
-       scan_loop (loop, unroll_p, bct_p);
+       scan_loop (loop, flags);
     }
 
   /* If there were lexical blocks inside the loop, they have been
@@ -590,9 +578,9 @@ next_insn_in_loop (loop, insn)
    write, then we can also mark the memory read as invariant.  */
 
 static void
-scan_loop (loop, unroll_p, bct_p)
+scan_loop (loop, flags)
      struct loop *loop;
-     int unroll_p, bct_p;
+     int flags;
 {
   register int i;
   rtx loop_start = loop->start;
@@ -644,12 +632,12 @@ scan_loop (loop, unroll_p, bct_p)
      Note that if we mistakenly think that a loop is entered at the top
      when, in fact, it is entered at the exit test, the only effect will be
      slightly poorer optimization.  Making the opposite error can generate
-     incorrect code.  Since very few loops now start with a jump to the 
+     incorrect code.  Since very few loops now start with a jump to the
      exit test, the code here to detect that case is very conservative.  */
 
   for (p = NEXT_INSN (loop_start);
        p != loop_end
-        && GET_CODE (p) != CODE_LABEL && GET_RTX_CLASS (GET_CODE (p)) != 'i'
+        && GET_CODE (p) != CODE_LABEL && ! INSN_P (p)
         && (GET_CODE (p) != NOTE
             || (NOTE_LINE_NUMBER (p) != NOTE_INSN_LOOP_BEG
                 && NOTE_LINE_NUMBER (p) != NOTE_INSN_LOOP_END));
@@ -672,7 +660,7 @@ scan_loop (loop, unroll_p, bct_p)
       loop_entry_jump = p;
 
       /* Loop entry must be unconditional jump (and not a RETURN)  */
-      if (simplejump_p (p)
+      if (any_uncondjump_p (p)
          && JUMP_LABEL (p) != 0
          /* Check to see whether the jump actually
             jumps out of the loop (meaning it's no loop).
@@ -689,7 +677,7 @@ scan_loop (loop, unroll_p, bct_p)
 
   /* If LOOP->SCAN_START was an insn created by loop, we don't know its luid
      as required by loop_reg_used_before_p.  So skip such loops.  (This
-     test may never be true, but it's best to play it safe.) 
+     test may never be true, but it's best to play it safe.)
 
      Also, skip loops where we do not start scanning at a label.  This
      test also rejects loops starting with a JUMP_INSN that failed the
@@ -707,7 +695,7 @@ scan_loop (loop, unroll_p, bct_p)
   /* Count number of times each reg is set during this loop.
      Set VARRAY_CHAR (may_not_optimize, I) if it is not safe to move out
      the setting of register I.  Set VARRAY_RTX (reg_single_usage, I).  */
-  
+
   /* Allocate extra space for REGS that might be created by
      load_mems.  We allocate a little extra slop as well, in the hopes
      that even after the moving of movables creates some new registers
@@ -736,7 +724,7 @@ scan_loop (loop, unroll_p, bct_p)
       VARRAY_CHAR (may_not_optimize, i) = 1;
 #endif
 
-  bcopy ((char *) &set_in_loop->data, 
+  bcopy ((char *) &set_in_loop->data,
         (char *) &n_times_set->data, nregs * sizeof (int));
 
   if (loop_dump_stream)
@@ -761,15 +749,13 @@ scan_loop (loop, unroll_p, bct_p)
      When MAYBE_NEVER is 0, all insns will be executed at least once
      so that is not a problem.  */
 
-  for (p = next_insn_in_loop (loop, loop->scan_start); 
+  for (p = next_insn_in_loop (loop, loop->scan_start);
        p != NULL_RTX;
        p = next_insn_in_loop (loop, p))
     {
-      if (GET_RTX_CLASS (GET_CODE (p)) == 'i'
-         && find_reg_note (p, REG_LIBCALL, NULL_RTX))
+      if (INSN_P (p) && find_reg_note (p, REG_LIBCALL, NULL_RTX))
        in_libcall = 1;
-      else if (GET_RTX_CLASS (GET_CODE (p)) == 'i'
-              && find_reg_note (p, REG_RETVAL, NULL_RTX))
+      else if (INSN_P (p) && find_reg_note (p, REG_RETVAL, NULL_RTX))
        in_libcall = 0;
 
       if (GET_CODE (p) == INSN
@@ -794,7 +780,7 @@ scan_loop (loop, unroll_p, bct_p)
          temp = find_reg_note (p, REG_EQUIV, NULL_RTX);
          if (temp)
            src = XEXP (temp, 0), move_insn = 1;
-         else 
+         else
            {
              temp = find_reg_note (p, REG_EQUAL, NULL_RTX);
              if (temp && CONSTANT_P (XEXP (temp, 0)))
@@ -821,7 +807,7 @@ scan_loop (loop, unroll_p, bct_p)
                   ! reg_in_basic_block_p (p, SET_DEST (set))
                   /* And the set is not guaranteed to be executed one
                      the loop starts, or the value before the set is
-                     needed before the set occurs... 
+                     needed before the set occurs...
 
                      ??? Note we have quadratic behaviour here, mitigated
                      by the fact that the previous test will often fail for
@@ -830,7 +816,7 @@ scan_loop (loop, unroll_p, bct_p)
                      of the register usage and use them here instead.  */
                   && (maybe_never
                       || loop_reg_used_before_p (loop, set, p)))
-           /* It is unsafe to move the set.  
+           /* It is unsafe to move the set.
 
               This code used to consider it OK to move a set of a variable
               which was not created by the user and not used in an exit test.
@@ -839,10 +825,10 @@ scan_loop (loop, unroll_p, bct_p)
          else if ((tem = loop_invariant_p (loop, src))
                   && (dependencies == 0
                       || (tem2 = loop_invariant_p (loop, dependencies)) != 0)
-                  && (VARRAY_INT (set_in_loop, 
+                  && (VARRAY_INT (set_in_loop,
                                   REGNO (SET_DEST (set))) == 1
                       || (tem1
-                          = consec_sets_invariant_p 
+                          = consec_sets_invariant_p
                           (loop, SET_DEST (set),
                            VARRAY_INT (set_in_loop, REGNO (SET_DEST (set))),
                            p)))
@@ -861,12 +847,12 @@ scan_loop (loop, unroll_p, bct_p)
                 can be combined as long as they are both in the loop, but
                 we move one of them outside the loop.  For large loops,
                 this can lose.  The most common case of this is the address
-                of a function being called.  
+                of a function being called.
 
                 Therefore, if this register is marked as being used exactly
                 once if we are in a loop with calls (a "large loop"), see if
                 we can replace the usage of this register with the source
-                of this SET.  If we can, delete this insn. 
+                of this SET.  If we can, delete this insn.
 
                 Don't do this if P has a REG_RETVAL note or if we have
                 SMALL_REGISTER_CLASSES and SET_SRC is a hard register.  */
@@ -888,20 +874,20 @@ scan_loop (loop, unroll_p, bct_p)
                     might span a call.  */
                  && ! modified_between_p (SET_SRC (set), p,
                                           VARRAY_RTX
-                                          (reg_single_usage, regno)) 
+                                          (reg_single_usage, regno))
                  && no_labels_between_p (p, VARRAY_RTX (reg_single_usage, regno))
                  && validate_replace_rtx (SET_DEST (set), SET_SRC (set),
                                           VARRAY_RTX
-                                          (reg_single_usage, regno))) 
+                                          (reg_single_usage, regno)))
                {
                  /* Replace any usage in a REG_EQUAL note.  Must copy the
                     new source, so that we don't get rtx sharing between the
                     SET_SOURCE and REG_NOTES of insn p.  */
                  REG_NOTES (VARRAY_RTX (reg_single_usage, regno))
                    = replace_rtx (REG_NOTES (VARRAY_RTX
-                                             (reg_single_usage, regno)), 
+                                             (reg_single_usage, regno)),
                                   SET_DEST (set), copy_rtx (SET_SRC (set)));
-                                  
+
                  PUT_CODE (p, NOTE);
                  NOTE_LINE_NUMBER (p) = NOTE_INSN_DELETED;
                  NOTE_SOURCE_FILE (p) = 0;
@@ -916,7 +902,7 @@ scan_loop (loop, unroll_p, bct_p)
              m->dependencies = dependencies;
              m->set_dest = SET_DEST (set);
              m->force = 0;
-             m->consec = VARRAY_INT (set_in_loop, 
+             m->consec = VARRAY_INT (set_in_loop,
                                      REGNO (SET_DEST (set))) - 1;
              m->done = 0;
              m->forces = 0;
@@ -930,7 +916,7 @@ scan_loop (loop, unroll_p, bct_p)
                 or consec_sets_invariant_p returned 2
                 (only conditionally invariant).  */
              m->cond = ((tem | tem1 | tem2) > 1);
-             m->global = (uid_luid[REGNO_LAST_UID (regno)] 
+             m->global = (uid_luid[REGNO_LAST_UID (regno)]
                           > INSN_LUID (loop_end)
                           || uid_luid[REGNO_FIRST_UID (regno)] < INSN_LUID (loop_start));
              m->match = 0;
@@ -1078,7 +1064,7 @@ scan_loop (loop, unroll_p, bct_p)
                  followed a by barrier then loop end.  */
                && ! (GET_CODE (p) == JUMP_INSN && JUMP_LABEL (p) == loop->top
                     && NEXT_INSN (NEXT_INSN (p)) == loop_end
-                    && simplejump_p (p)))
+                    && any_uncondjump_p (p)))
        maybe_never = 1;
       else if (GET_CODE (p) == NOTE)
        {
@@ -1111,7 +1097,7 @@ scan_loop (loop, unroll_p, bct_p)
      all together as the priority of the first.  */
 
   combine_movables (movables, nregs);
-       
+
   /* Now consider each movable insn to decide whether it is worth moving.
      Store 0 in set_in_loop for each reg that is moved.
 
@@ -1143,11 +1129,19 @@ scan_loop (loop, unroll_p, bct_p)
 
   if (flag_strength_reduce)
     {
+      if (update_end && GET_CODE (update_end) == CODE_LABEL)
+       /* Ensure our label doesn't go away.  */
+       LABEL_NUSES (update_end)++;
+
       the_movables = movables;
-      strength_reduce (loop, insn_count, unroll_p, bct_p);
+      strength_reduce (loop, insn_count, flags);
 
       reg_scan_update (update_start, update_end, loop_max_reg);
       loop_max_reg = max_reg_num ();
+
+      if (update_end && GET_CODE (update_end) == CODE_LABEL
+         && --LABEL_NUSES (update_end) == 0)
+       delete_insn (update_end);
     }
 
   VARRAY_FREE (reg_single_usage);
@@ -1186,7 +1180,7 @@ record_excess_regs (in_this, not_in_this, output)
          && ! reg_mentioned_p (in_this, not_in_this))
        *output = gen_rtx_EXPR_LIST (VOIDmode, in_this, *output);
       return;
-      
+
     default:
       break;
     }
@@ -1240,7 +1234,7 @@ libcall_other_reg (insn, equiv)
 /* Return 1 if all uses of REG
    are between INSN and the end of the basic block.  */
 
-static int 
+static int
 reg_in_basic_block_p (insn, reg)
      rtx insn, reg;
 {
@@ -1276,7 +1270,7 @@ reg_in_basic_block_p (insn, reg)
        case BARRIER:
          /* It's the end of the basic block, so we lose.  */
          return 0;
-         
+
        default:
          break;
        }
@@ -1328,13 +1322,14 @@ skip_consec_insns (insn, count)
       rtx temp;
 
       /* If first insn of libcall sequence, skip to end.  */
-      /* Do this at start of loop, since INSN is guaranteed to 
+      /* Do this at start of loop, since INSN is guaranteed to
         be an insn here.  */
       if (GET_CODE (insn) != NOTE
          && (temp = find_reg_note (insn, REG_LIBCALL, NULL_RTX)))
        insn = XEXP (temp, 0);
 
-      do insn = NEXT_INSN (insn);
+      do
+       insn = NEXT_INSN (insn);
       while (GET_CODE (insn) == NOTE);
     }
 
@@ -1371,7 +1366,7 @@ ignore_some_movables (movables)
                m1->done = 1;
        }
     }
-}        
+}
 
 /* For each movable insn, see if the reg that it loads
    leads when it dies right into another conditionally movable insn.
@@ -1431,7 +1426,8 @@ combine_movables (movables, nregs)
   /* Perhaps testing m->consec_sets would be more appropriate here?  */
 
   for (m = movables; m; m = m->next)
-    if (m->match == 0 && VARRAY_INT (n_times_set, m->regno) == 1 && !m->partial)
+    if (m->match == 0 && VARRAY_INT (n_times_set, m->regno) == 1
+       && !m->partial)
       {
        register struct movable *m1;
        int regno = m->regno;
@@ -1501,13 +1497,13 @@ combine_movables (movables, nregs)
              {
                /* First one: don't check for overlap, just record it.  */
                m0 = m;
-                 continue;
+               continue;
              }
 
            /* Make sure they extend to the same mode.
               (Almost always true.)  */
            if (GET_MODE (m->set_dest) != GET_MODE (m0->set_dest))
-               continue;
+             continue;
 
            /* We already have one: check for overlap with those
               already combined together.  */
@@ -1523,7 +1519,8 @@ combine_movables (movables, nregs)
            m->done = 1;
            m->match = m0;
 
-         overlap: ;
+         overlap:
+           ;
          }
     }
 
@@ -1918,7 +1915,7 @@ move_movables (loop, movables, threshold, insn_count, nregs)
                      rtx i1, temp;
 
                      /* If first insn of libcall sequence, skip to end.  */
-                     /* Do this at start of loop, since p is guaranteed to 
+                     /* Do this at start of loop, since p is guaranteed to
                         be an insn here.  */
                      if (GET_CODE (p) != NOTE
                          && (temp = find_reg_note (p, REG_LIBCALL, NULL_RTX)))
@@ -1955,7 +1952,7 @@ move_movables (loop, movables, threshold, insn_count, nregs)
                                       && GET_CODE (PATTERN (next)) == USE)
                                    && GET_CODE (next) != NOTE)
                                  break;
-                             
+
                              /* If that is the call, this may be the insn
                                 that loads the function address.
 
@@ -2019,7 +2016,7 @@ move_movables (loop, movables, threshold, insn_count, nregs)
                          rtx reg = m->set_dest;
                          rtx sequence;
                          rtx tem;
-                     
+
                          start_sequence ();
                          tem = expand_binop
                            (GET_MODE (reg), and_optab, reg,
@@ -2075,7 +2072,7 @@ move_movables (loop, movables, threshold, insn_count, nregs)
                             may cause problems with later optimization passes.
                             It is possible for cse to create such notes
                             like this as a result of record_jump_cond.  */
-                     
+
                          if ((temp = find_reg_note (i1, REG_EQUAL, NULL_RTX))
                              && ! loop_invariant_p (loop, XEXP (temp, 0)))
                            remove_note (i1, temp);
@@ -2166,7 +2163,7 @@ move_movables (loop, movables, threshold, insn_count, nregs)
                        reg_map[m1->regno]
                          = gen_lowpart_common (GET_MODE (m1->set_dest),
                                                m->set_dest);
-                   
+
                      /* Get rid of the matching insn
                         and prevent further processing of it.  */
                      m1->done = 1;
@@ -2265,7 +2262,7 @@ replace_call_address (x, reg, addr)
        abort ();
       XEXP (x, 0) = addr;
       return;
-      
+
     default:
       break;
     }
@@ -2317,7 +2314,7 @@ count_nonfixed_reads (loop, x)
     case MEM:
       return ((loop_invariant_p (loop, XEXP (x, 0)) != 1)
              + count_nonfixed_reads (loop, XEXP (x, 0)));
-      
+
     default:
       break;
     }
@@ -2337,7 +2334,6 @@ count_nonfixed_reads (loop, x)
     }
   return value;
 }
-
 \f
 #if 0
 /* P is an instruction that sets a register to the result of a ZERO_EXTEND.
@@ -2471,7 +2467,7 @@ prescan_loop (loop)
              && (GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC
                  || GET_CODE (PATTERN (insn)) == ADDR_VEC))
            loop_info->has_tablejump = 1;
-         
+
          note_stores (PATTERN (insn), note_addr_stored, NULL);
          if (! first_loop_store_insn && loop_store_mems)
            first_loop_store_insn = insn;
@@ -2491,27 +2487,29 @@ prescan_loop (loop)
                  label1 = SET_SRC (PATTERN (insn));
                }
 
-             do {
-               if (label1 && label1 != pc_rtx)
-                 {
-                   if (GET_CODE (label1) != LABEL_REF)
-                     {
-                       /* Something tricky.  */
-                       loop_info->has_multiple_exit_targets = 1;
-                       break;
-                     }
-                   else if (XEXP (label1, 0) != exit_target
-                            && LABEL_OUTSIDE_LOOP_P (label1))
-                     {
-                       /* A jump outside the current loop.  */
-                       loop_info->has_multiple_exit_targets = 1;
-                       break;
-                     }
-                 }
+             do
+               {
+                 if (label1 && label1 != pc_rtx)
+                   {
+                     if (GET_CODE (label1) != LABEL_REF)
+                       {
+                         /* Something tricky.  */
+                         loop_info->has_multiple_exit_targets = 1;
+                         break;
+                       }
+                     else if (XEXP (label1, 0) != exit_target
+                              && LABEL_OUTSIDE_LOOP_P (label1))
+                       {
+                         /* A jump outside the current loop.  */
+                         loop_info->has_multiple_exit_targets = 1;
+                         break;
+                       }
+                   }
 
-               label1 = label2;
-               label2 = NULL_RTX;
-             } while (label1);
+                 label1 = label2;
+                 label2 = NULL_RTX;
+               }
+             while (label1);
            }
        }
       else if (GET_CODE (insn) == RETURN)
@@ -2520,7 +2518,7 @@ prescan_loop (loop)
 
   /* Now, rescan the loop, setting up the LOOP_MEMS array.  */
   if (/* We can't tell what MEMs are aliased by what.  */
-      ! unknown_address_altered 
+      ! unknown_address_altered
       /* An exception thrown by a called function might land us
         anywhere.  */
       && ! loop_info->has_call
@@ -2573,8 +2571,7 @@ verify_dominator (loop)
             which we do not have jump target information in the JUMP_LABEL
             field (consider ADDR_VEC and ADDR_DIFF_VEC insns), then clear
             LOOP->CONT_DOMINATOR.  */
-         if ((! condjump_p (insn)
-              && ! condjump_in_parallel_p (insn))
+         if (! any_condjump_p (insn)
              || label == NULL_RTX)
            {
              loop->cont_dominator = NULL_RTX;
@@ -2670,7 +2667,7 @@ find_and_verify_loops (f, loops)
        {
          rtx label = JUMP_LABEL (insn);
 
-         if (! condjump_p (insn) && ! condjump_in_parallel_p (insn))
+         if (! any_condjump_p (insn))
            label = NULL_RTX;
 
          loop = current_loop;
@@ -2734,14 +2731,14 @@ find_and_verify_loops (f, loops)
      anywhere.
 
      Also look for blocks of code ending in an unconditional branch that
-     exits the loop.  If such a block is surrounded by a conditional 
+     exits the loop.  If such a block is surrounded by a conditional
      branch around the block, move the block elsewhere (see below) and
      invert the jump to point to the code block.  This may eliminate a
      label in our loop and will simplify processing by both us and a
      possible second cse pass.  */
 
   for (insn = f; insn; insn = NEXT_INSN (insn))
-    if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
+    if (INSN_P (insn))
       {
        struct loop *this_loop = uid_loop[INSN_UID (insn)];
 
@@ -2764,7 +2761,8 @@ find_and_verify_loops (f, loops)
        /* See if this is an unconditional branch outside the loop.  */
        if (this_loop
            && (GET_CODE (PATTERN (insn)) == RETURN
-               || (simplejump_p (insn)
+               || (any_uncondjump_p (insn)
+                   && onlyjump_p (insn)
                    && (uid_loop[INSN_UID (JUMP_LABEL (insn))]
                        != this_loop)))
            && get_max_uid () < max_uid_for_loop)
@@ -2821,12 +2819,11 @@ find_and_verify_loops (f, loops)
                /* Just ignore jumps to labels that were never emitted.
                   These always indicate compilation errors.  */
                && INSN_UID (JUMP_LABEL (p)) != 0
-               && condjump_p (p)
-               && ! simplejump_p (p)
+               && any_condjump_p (p) && onlyjump_p (p)
                && next_real_insn (JUMP_LABEL (p)) == our_next
                /* If it's not safe to move the sequence, then we
                   mustn't try.  */
-               && insns_safe_to_move_p (p, NEXT_INSN (insn), 
+               && insns_safe_to_move_p (p, NEXT_INSN (insn),
                                         &last_insn_to_move))
              {
                rtx target
@@ -2869,86 +2866,86 @@ find_and_verify_loops (f, loops)
 
                    /* Verify that uid_loop is large enough and that
                       we can invert P.  */
-                  if (invert_jump (p, new_label))
-                    {
-                      rtx q, r;
-
-                      /* If no suitable BARRIER was found, create a suitable
-                         one before TARGET.  Since TARGET is a fall through
-                         path, we'll need to insert an jump around our block
-                         and a add a BARRIER before TARGET.
-
-                         This creates an extra unconditional jump outside
-                         the loop.  However, the benefits of removing rarely
-                         executed instructions from inside the loop usually
-                         outweighs the cost of the extra unconditional jump
-                         outside the loop.  */
-                      if (loc == 0)
-                        {
-                          rtx temp;
-
-                          temp = gen_jump (JUMP_LABEL (insn));
-                          temp = emit_jump_insn_before (temp, target);
-                          JUMP_LABEL (temp) = JUMP_LABEL (insn);
-                          LABEL_NUSES (JUMP_LABEL (insn))++;
-                          loc = emit_barrier_before (target);
-                        }
-
-                      /* Include the BARRIER after INSN and copy the
-                         block after LOC.  */
-                      new_label = squeeze_notes (new_label, 
-                                                 last_insn_to_move);
-                      reorder_insns (new_label, last_insn_to_move, loc);
-
-                      /* All those insns are now in TARGET_LOOP.  */
-                      for (q = new_label; 
-                           q != NEXT_INSN (last_insn_to_move);
-                           q = NEXT_INSN (q))
-                        uid_loop[INSN_UID (q)] = target_loop;
-
-                      /* The label jumped to by INSN is no longer a loop exit.
-                         Unless INSN does not have a label (e.g., it is a
-                         RETURN insn), search loop->exit_labels to find
-                         its label_ref, and remove it.  Also turn off
-                         LABEL_OUTSIDE_LOOP_P bit.  */
-                      if (JUMP_LABEL (insn))
-                        {
-                          for (q = 0,
-                               r = this_loop->exit_labels;
-                               r; q = r, r = LABEL_NEXTREF (r))
-                            if (XEXP (r, 0) == JUMP_LABEL (insn))
-                              {
-                                LABEL_OUTSIDE_LOOP_P (r) = 0;
-                                if (q)
-                                  LABEL_NEXTREF (q) = LABEL_NEXTREF (r);
-                                else
-                                  this_loop->exit_labels = LABEL_NEXTREF (r);
-                                break;
-                              }
-
-                          for (loop = this_loop; loop && loop != target_loop;
-                               loop = loop->outer)
-                            loop->exit_count--;
-
-                          /* If we didn't find it, then something is
-                              wrong.  */
-                          if (! r)
-                            abort ();
-                        }
-
-                      /* P is now a jump outside the loop, so it must be put
-                         in loop->exit_labels, and marked as such.
-                         The easiest way to do this is to just call
-                         mark_loop_jump again for P.  */
-                      mark_loop_jump (PATTERN (p), this_loop);
-
-                      /* If INSN now jumps to the insn after it,
-                         delete INSN.  */
-                      if (JUMP_LABEL (insn) != 0
-                          && (next_real_insn (JUMP_LABEL (insn))
-                              == next_real_insn (insn)))
-                        delete_insn (insn);
-                    }
+                   if (invert_jump (p, new_label, 1))
+                     {
+                       rtx q, r;
+
+                       /* If no suitable BARRIER was found, create a suitable
+                          one before TARGET.  Since TARGET is a fall through
+                          path, we'll need to insert an jump around our block
+                          and a add a BARRIER before TARGET.
+
+                          This creates an extra unconditional jump outside
+                          the loop.  However, the benefits of removing rarely
+                          executed instructions from inside the loop usually
+                          outweighs the cost of the extra unconditional jump
+                          outside the loop.  */
+                       if (loc == 0)
+                         {
+                           rtx temp;
+
+                           temp = gen_jump (JUMP_LABEL (insn));
+                           temp = emit_jump_insn_before (temp, target);
+                           JUMP_LABEL (temp) = JUMP_LABEL (insn);
+                           LABEL_NUSES (JUMP_LABEL (insn))++;
+                           loc = emit_barrier_before (target);
+                         }
+
+                       /* Include the BARRIER after INSN and copy the
+                          block after LOC.  */
+                       new_label = squeeze_notes (new_label,
+                                                  last_insn_to_move);
+                       reorder_insns (new_label, last_insn_to_move, loc);
+
+                       /* All those insns are now in TARGET_LOOP.  */
+                       for (q = new_label;
+                            q != NEXT_INSN (last_insn_to_move);
+                            q = NEXT_INSN (q))
+                         uid_loop[INSN_UID (q)] = target_loop;
+
+                       /* The label jumped to by INSN is no longer a loop
+                          exit.  Unless INSN does not have a label (e.g.,
+                          it is a RETURN insn), search loop->exit_labels
+                          to find its label_ref, and remove it.  Also turn
+                          off LABEL_OUTSIDE_LOOP_P bit.  */
+                       if (JUMP_LABEL (insn))
+                         {
+                           for (q = 0,
+                                  r = this_loop->exit_labels;
+                                r; q = r, r = LABEL_NEXTREF (r))
+                             if (XEXP (r, 0) == JUMP_LABEL (insn))
+                               {
+                                 LABEL_OUTSIDE_LOOP_P (r) = 0;
+                                 if (q)
+                                   LABEL_NEXTREF (q) = LABEL_NEXTREF (r);
+                                 else
+                                   this_loop->exit_labels = LABEL_NEXTREF (r);
+                                 break;
+                               }
+
+                           for (loop = this_loop; loop && loop != target_loop;
+                                loop = loop->outer)
+                             loop->exit_count--;
+
+                           /* If we didn't find it, then something is
+                              wrong.  */
+                           if (! r)
+                             abort ();
+                         }
+
+                       /* P is now a jump outside the loop, so it must be put
+                          in loop->exit_labels, and marked as such.
+                          The easiest way to do this is to just call
+                          mark_loop_jump again for P.  */
+                       mark_loop_jump (PATTERN (p), this_loop);
+
+                       /* If INSN now jumps to the insn after it,
+                          delete INSN.  */
+                       if (JUMP_LABEL (insn) != 0
+                           && (next_real_insn (JUMP_LABEL (insn))
+                               == next_real_insn (insn)))
+                         delete_insn (insn);
+                     }
 
                    /* Continue the loop after where the conditional
                       branch used to jump, since the only branch insn
@@ -3068,7 +3065,7 @@ mark_loop_jump (x, loop)
            fprintf (loop_dump_stream,
                     "\nLoop at %d ignored due to multiple entry points.\n",
                     INSN_UID (dest_loop->start));
-         
+
          dest_loop->invalid = 1;
        }
       return;
@@ -3274,7 +3271,7 @@ loop_invariant_p (loop, x)
       /* If we had a subroutine call, any location in memory could
         have been clobbered.  We used to test here for volatile and
         readonly, but true_dependence knows how to do that better
-        than we do. */
+        than we do.  */
       if (RTX_UNCHANGING_P (x)
          ? unknown_constant_address_altered : unknown_address_altered)
        return 0;
@@ -3299,7 +3296,7 @@ loop_invariant_p (loop, x)
       if (MEM_VOLATILE_P (x))
        return 0;
       break;
-      
+
     default:
       break;
     }
@@ -3332,7 +3329,6 @@ loop_invariant_p (loop, x)
 
   return 1 + conditional;
 }
-
 \f
 /* Return nonzero if all the insns in the loop that set REG
    are INSN and the immediately following insns,
@@ -3461,7 +3457,7 @@ find_single_use_in_loop (insn, x, usage)
 
   if (code == REG)
     VARRAY_RTX (usage, REGNO (x))
-      = (VARRAY_RTX (usage, REGNO (x)) != 0 
+      = (VARRAY_RTX (usage, REGNO (x)) != 0
         && VARRAY_RTX (usage, REGNO (x)) != insn)
        ? const0_rtx : insn;
 
@@ -3469,7 +3465,7 @@ find_single_use_in_loop (insn, x, usage)
     {
       /* Don't count SET_DEST if it is a REG; otherwise count things
         in SET_DEST because if a register is partially modified, it won't
-        show up as a potential movable so we don't care how USAGE is set 
+        show up as a potential movable so we don't care how USAGE is set
         for it.  */
       if (GET_CODE (SET_DEST (x)) != REG)
        find_single_use_in_loop (insn, SET_DEST (x), usage);
@@ -3515,7 +3511,7 @@ count_one_set (insn, x, may_not_move, last_set)
             in current basic block, and it was set before,
             it must be set in two basic blocks, so it cannot
             be moved out of the loop.  */
-         if (VARRAY_INT (set_in_loop, regno) > 0 
+         if (VARRAY_INT (set_in_loop, regno) > 0
              && last_set[regno] == 0)
            VARRAY_CHAR (may_not_move, regno) = 1;
          /* If this is not first setting in current basic block,
@@ -3561,7 +3557,7 @@ count_loop_regs_set (from, to, may_not_move, single_usage, count_ptr, nregs)
 
   for (insn = from; insn != to; insn = NEXT_INSN (insn))
     {
-      if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
+      if (INSN_P (insn))
        {
          ++count;
 
@@ -3614,8 +3610,7 @@ loop_reg_used_before_p (loop, set, insn)
      are done.  Otherwise, if we hit LOOP->END, wrap around to LOOP->START.  */
   for (p = loop->scan_start; p != insn; p = NEXT_INSN (p))
     {
-      if (GET_RTX_CLASS (GET_CODE (p)) == 'i'
-         && reg_overlap_mentioned_p (reg, PATTERN (p)))
+      if (INSN_P (p) && reg_overlap_mentioned_p (reg, PATTERN (p)))
        return 1;
 
       if (p == loop->end)
@@ -3699,7 +3694,7 @@ static rtx addr_placeholder;
 /* Scan the loop body and call FNCALL for each insn.  In the addition to the
    LOOP and INSN parameters pass MAYBE_MULTIPLE and NOT_EVERY_ITERATION to the
    callback.
+
    NOT_EVERY_ITERATION if current insn is not executed at least once for every
    loop iteration except for the last one.
 
@@ -3730,7 +3725,7 @@ for_each_insn_in_loop (loop, fncall)
        p != NULL_RTX;
        p = next_insn_in_loop (loop, p))
     {
-      p = fncall (loop, p, not_every_iteration, not_every_iteration);
+      p = fncall (loop, p, not_every_iteration, maybe_multiple);
 
       /* Past CODE_LABEL, we get to insns that may be executed multiple
          times.  The only way we can be sure that they can't is if every
@@ -3761,7 +3756,7 @@ for_each_insn_in_loop (loop, fncall)
 
              if (GET_CODE (insn) == JUMP_INSN
                  && GET_CODE (PATTERN (insn)) != RETURN
-                 && (!condjump_p (insn)
+                 && (!any_condjump_p (insn)
                      || (JUMP_LABEL (insn) != 0
                          && JUMP_LABEL (insn) != loop->scan_start
                          && !loop_insn_first_p (p, JUMP_LABEL (insn)))))
@@ -3782,8 +3777,9 @@ for_each_insn_in_loop (loop, fncall)
          This can be any kind of jump, since we want to know if insns
          will be executed if the loop is executed.  */
          && !(JUMP_LABEL (p) == loop->top
-            && ((NEXT_INSN (NEXT_INSN (p)) == loop->end && simplejump_p (p))
-                || (NEXT_INSN (p) == loop->end && condjump_p (p)))))
+            && ((NEXT_INSN (NEXT_INSN (p)) == loop->end
+                 && any_uncondjump_p (p))
+                || (NEXT_INSN (p) == loop->end && any_condjump_p (p)))))
        {
          rtx label = 0;
 
@@ -3848,7 +3844,7 @@ for_each_insn_in_loop (loop, fncall)
     }
 }
 \f
-/* Perform strength reduction and induction variable elimination.  
+/* Perform strength reduction and induction variable elimination.
 
    Pseudo registers created during this function will be beyond the last
    valid index in several tables including n_times_set and regno_last_uid.
@@ -3857,10 +3853,10 @@ for_each_insn_in_loop (loop, fncall)
    But scan_loop must check regnos to make sure they are in bounds.   */
 
 static void
-strength_reduce (loop, insn_count, unroll_p, bct_p)
+strength_reduce (loop, insn_count, flags)
      struct loop *loop;
      int insn_count;
-     int unroll_p, bct_p ATTRIBUTE_UNUSED;
+     int flags;
 {
   rtx p;
   /* Temporary list pointers for traversing loop_iv_list.  */
@@ -3894,9 +3890,9 @@ strength_reduce (loop, insn_count, unroll_p, bct_p)
 
   /* Save insn immediately after the loop_end.  Insns inserted after loop_end
      must be put before this insn, so that they will appear in the right
-     order (i.e. loop order). 
+     order (i.e. loop order).
 
-     If loop_end is the end of the current function, then emit a 
+     If loop_end is the end of the current function, then emit a
      NOTE_INSN_DELETED after loop_end and set end_insert_before to the
      dummy note insn.  */
   if (NEXT_INSN (loop_end) != 0)
@@ -3910,8 +3906,6 @@ strength_reduce (loop, insn_count, unroll_p, bct_p)
      Make a sanity check against n_times_set.  */
   for (backbl = &loop_iv_list, bl = *backbl; bl; bl = bl->next)
     {
-      int fail = 0;
-
       if (REG_IV_TYPE (bl->regno) != BASIC_INDUCT
          /* Above happens if register modified by subreg, etc.  */
          /* Make sure it is not recognized as a basic induction var: */
@@ -3919,21 +3913,6 @@ strength_reduce (loop, insn_count, unroll_p, bct_p)
          /* If never incremented, it is invariant that we decided not to
             move.  So leave it alone.  */
          || ! bl->incremented)
-       fail = 1;
-      else if (bl->biv_count > 1)
-       {
-         /* ??? If we have multiple increments for this BIV, and any of
-            them take multiple insns to perform the increment, drop the
-            BIV, since the bit below that converts the extra increments
-            into GIVs can't handle the multiple insn increment.  */
-         
-         struct induction *v;
-         for (v = bl->biv; v ; v = v->next_iv)
-           if (v->multi_insn_incr)
-             fail = 1;
-       }
-
-      if (fail)
        {
          if (loop_dump_stream)
            fprintf (loop_dump_stream, "Reg %d: biv discarded, %s\n",
@@ -3942,7 +3921,7 @@ strength_reduce (loop, insn_count, unroll_p, bct_p)
                      ? "not induction variable"
                      : (! bl->incremented ? "never incremented"
                         : "count error")));
-         
+
          REG_IV_TYPE (bl->regno) = NOT_BASIC_INDUCT;
          *backbl = bl->next;
        }
@@ -3960,7 +3939,7 @@ strength_reduce (loop, insn_count, unroll_p, bct_p)
     {
       /* Can still unroll the loop anyways, but indicate that there is no
         strength reduction info available.  */
-      if (unroll_p)
+      if (flags & LOOP_UNROLL)
        unroll_loop (loop, insn_count, end_insert_before, 0);
 
       goto egress;
@@ -3977,8 +3956,7 @@ strength_reduce (loop, insn_count, unroll_p, bct_p)
       if (GET_CODE (p) == CALL_INSN)
        call_seen = 1;
 
-      if (GET_CODE (p) == INSN || GET_CODE (p) == JUMP_INSN
-         || GET_CODE (p) == CALL_INSN)
+      if (INSN_P (p))
        note_stores (PATTERN (p), record_initial, NULL);
 
       /* Record any test of a biv that branches around the loop if no store
@@ -4076,7 +4054,7 @@ strength_reduce (loop, insn_count, unroll_p, bct_p)
                if (bl2->regno == regno)
                  break;
            }
-       
+
          /* Now, can we transform this biv into a giv?  */
          if (bl2
              && bl2->biv_count == 1
@@ -4122,16 +4100,14 @@ strength_reduce (loop, insn_count, unroll_p, bct_p)
                  rtx p;
                  rtx next;
 
-                 for (next = NEXT_INSN (dominator); ; next = NEXT_INSN (next))
+                 for (next = NEXT_INSN (dominator);; next = NEXT_INSN (next))
                    {
-                     if ((GET_RTX_CLASS (GET_CODE (next)) == 'i'
-                          && (reg_mentioned_p (giv, PATTERN (next))
-                              || reg_set_p (bl2->biv->src_reg, next)))
-                         || GET_CODE (next) == JUMP_INSN)
+                     if (GET_CODE (next) == JUMP_INSN
+                         || (INSN_P (next)
+                             && insn_dependent_p (giv_insn, next)))
                        break;
 #ifdef HAVE_cc0
-                     if (GET_RTX_CLASS (GET_CODE (next)) != 'i'
-                         || ! sets_cc0_p (PATTERN (next)))
+                     if (! INSN_P (next) || ! sets_cc0_p (PATTERN (next)))
 #endif
                        dominator = next;
                    }
@@ -4141,7 +4117,7 @@ strength_reduce (loop, insn_count, unroll_p, bct_p)
                  /* Avoid problems with luids by actually moving the insn
                     and adjusting all luids in the range.  */
                  reorder_insns (giv_insn, giv_insn, dominator);
-                 for (p = dominator; INSN_UID (p) >= max_uid_for_loop; )
+                 for (p = dominator; INSN_UID (p) >= max_uid_for_loop;)
                    p = PREV_INSN (p);
                  compute_luids (giv_insn, after_giv, INSN_LUID (p));
                  /* If the only purpose of the init insn is to initialize
@@ -4160,19 +4136,7 @@ strength_reduce (loop, insn_count, unroll_p, bct_p)
                                 INSN_LUID (p));
                }
              /* Remove this biv from the chain.  */
-             if (bl->next)
-               {
-                 /* We move the following giv from *bl->next into *bl.
-                    We have to update reg_biv_class for that moved biv
-                    to point to its new address.  */
-                 *bl = *bl->next;
-                 reg_biv_class[bl->regno] = bl;
-               }
-             else
-               {
-                 *backbl = 0;
-                 break;
-               }
+             *backbl = bl->next;
            }
 
          /* If we can't make it a giv,
@@ -4246,6 +4210,7 @@ strength_reduce (loop, insn_count, unroll_p, bct_p)
              HOST_WIDE_INT offset;
              rtx set, add_val, old_reg, dest_reg, last_use_insn, note;
              int old_regno, new_regno;
+             rtx next_loc_insn;
 
              if (! v->always_executed
                  || v->maybe_multiple
@@ -4266,7 +4231,7 @@ strength_reduce (loop, insn_count, unroll_p, bct_p)
              add_val = plus_constant (next->add_val, offset);
              old_reg = v->dest_reg;
              dest_reg = gen_reg_rtx (v->mode);
-    
+
              /* Unlike reg_iv_type / reg_iv_info, the other three arrays
                 have been allocated with some slop space, so we may not
                 actually need to reallocate them.  If we do, the following
@@ -4279,8 +4244,18 @@ strength_reduce (loop, insn_count, unroll_p, bct_p)
                  VARRAY_GROW (may_not_optimize, nregs);
                  VARRAY_GROW (reg_single_usage, nregs);
                }
-    
-             if (! validate_change (next->insn, next->location, add_val, 0))
+
+             /* Some bivs are incremented with a multi-insn sequence.
+                The first insn contains the add.  */
+             next_loc_insn = next->insn;
+             while (! loc_mentioned_in_p (next->location,
+                                          PATTERN (next_loc_insn)))
+               next_loc_insn = PREV_INSN (next_loc_insn);
+
+             if (next_loc_insn == v->insn)
+               abort ();
+
+             if (! validate_change (next_loc_insn, next->location, add_val, 0))
                {
                  vp = &v->next_iv;
                  continue;
@@ -4292,10 +4267,10 @@ strength_reduce (loop, insn_count, unroll_p, bct_p)
              /* Set last_use_insn so that we can check against it.  */
 
              for (last_use_insn = v->insn, p = NEXT_INSN (v->insn);
-                  p != next->insn;
+                  p != next_loc_insn;
                   p = next_insn_in_loop (loop, p))
                {
-                 if (GET_RTX_CLASS (GET_CODE (p)) != 'i')
+                 if (!INSN_P (p))
                    continue;
                  if (reg_mentioned_p (old_reg, PATTERN (p)))
                    {
@@ -4312,7 +4287,7 @@ strength_reduce (loop, insn_count, unroll_p, bct_p)
                  || ! validate_change (v->insn, &SET_DEST (set), dest_reg, 0))
                {
                  /* Change the increment at NEXT back to what it was.  */
-                 if (! validate_change (next->insn, next->location,
+                 if (! validate_change (next_loc_insn, next->location,
                      next->add_val, 0))
                    abort ();
                  vp = &v->next_iv;
@@ -4339,7 +4314,7 @@ strength_reduce (loop, insn_count, unroll_p, bct_p)
              v->always_executed = 1;
              v->replaceable = 1;
              v->no_const_addval = 0;
-    
+
              old_regno = REGNO (old_reg);
              new_regno = REGNO (dest_reg);
              VARRAY_INT (set_in_loop, old_regno)--;
@@ -4347,7 +4322,7 @@ strength_reduce (loop, insn_count, unroll_p, bct_p)
              VARRAY_INT (n_times_set, old_regno)--;
              VARRAY_INT (n_times_set, new_regno) = 1;
              VARRAY_CHAR (may_not_optimize, new_regno) = 0;
-    
+
              REG_IV_TYPE (new_regno) = GENERAL_INDUCT;
              REG_IV_INFO (new_regno) = v;
 
@@ -4366,17 +4341,17 @@ strength_reduce (loop, insn_count, unroll_p, bct_p)
              bl->giv_count++;
              v->benefit = rtx_cost (SET_SRC (set), SET);
              bl->total_benefit += v->benefit;
-    
+
              /* Now replace the biv with DEST_REG in all insns between
                 the replaced increment and the next increment, and
                 remember the last insn that needed a replacement.  */
              for (last_use_insn = v->insn, p = NEXT_INSN (v->insn);
-                  p != next->insn;
+                  p != next_loc_insn;
                   p = next_insn_in_loop (loop, p))
                {
                  rtx note;
-    
-                 if (GET_RTX_CLASS (GET_CODE (p)) != 'i')
+
+                 if (! INSN_P (p))
                    continue;
                  if (reg_mentioned_p (old_reg, PATTERN (p)))
                    {
@@ -4391,7 +4366,7 @@ strength_reduce (loop, insn_count, unroll_p, bct_p)
                          = replace_rtx (XEXP (note, 0), old_reg, dest_reg);
                    }
                }
-    
+
              v->last_use = last_use_insn;
              v->lifetime = INSN_LUID (last_use_insn) - INSN_LUID (v->insn);
              /* If the lifetime is zero, it means that this register is really
@@ -4402,7 +4377,7 @@ strength_reduce (loop, insn_count, unroll_p, bct_p)
 
              if (loop_dump_stream)
                fprintf (loop_dump_stream,
-                        "Increment %d of biv %d converted to giv %d.\n",
+                        "Increment %d of biv %d converted to giv %d.\n\n",
                         INSN_UID (v->insn), old_regno, new_regno);
            }
        }
@@ -4485,7 +4460,7 @@ strength_reduce (loop, insn_count, unroll_p, bct_p)
              && ! bl->nonneg
 #endif
              ))
-       bl->eliminable = maybe_eliminate_biv (loop, bl, 0, threshold, 
+       bl->eliminable = maybe_eliminate_biv (loop, bl, 0, threshold,
                                              insn_count);
       else
        {
@@ -4650,7 +4625,7 @@ strength_reduce (loop, insn_count, unroll_p, bct_p)
          VARRAY_GROW (reg_iv_type, nregs);
          VARRAY_GROW (reg_iv_info, nregs);
        }
-      recombine_givs (loop, bl, unroll_p);
+      recombine_givs (loop, bl, flags & LOOP_UNROLL);
 
       /* Reduce each giv that we decided to reduce.  */
 
@@ -4771,7 +4746,7 @@ strength_reduce (loop, insn_count, unroll_p, bct_p)
                    if ((auto_inc_opt == 1 && sets_cc0_p (PATTERN (v->insn)))
                        || (auto_inc_opt == -1
                            && (prev = prev_nonnote_insn (v->insn)) != 0
-                           && GET_RTX_CLASS (GET_CODE (prev)) == 'i'
+                           && INSN_P (prev)
                            && sets_cc0_p (PATTERN (prev))))
                      auto_inc_opt = 0;
                  }
@@ -4814,7 +4789,7 @@ strength_reduce (loop, insn_count, unroll_p, bct_p)
 
       /* Rescan all givs.  If a giv is the same as a giv not reduced, mark it
         as not reduced.
-        
+
         For each giv register that can be reduced now: if replaceable,
         substitute reduced reg wherever the old giv occurs;
         else add new move insn "giv_reg = reduced_reg".  */
@@ -4938,11 +4913,11 @@ strength_reduce (loop, insn_count, unroll_p, bct_p)
 
         We have to be careful that we didn't initially think we could eliminate
         this biv because of a giv that we now think may be dead and shouldn't
-        be used as a biv replacement.  
+        be used as a biv replacement.
 
         Also, there is the possibility that we may have a giv that looks
         like it can be used to eliminate a biv, but the resulting insn
-        isn't valid.  This can happen, for example, on the 88k, where a 
+        isn't valid.  This can happen, for example, on the 88k, where a
         JUMP_INSN can compare a register only with zero.  Attempts to
         replace it with a compare with a constant will fail.
 
@@ -5006,7 +4981,7 @@ strength_reduce (loop, insn_count, unroll_p, bct_p)
 
   for (p = loop_start; p != loop_end; p = NEXT_INSN (p))
     if (GET_CODE (p) == INSN || GET_CODE (p) == JUMP_INSN
-       || GET_CODE (p) == CALL_INSN)
+       || GET_CODE (p) == CALL_INSN)
       {
        replace_regs (PATTERN (p), reg_map, reg_map_size, 0);
        replace_regs (REG_NOTES (p), reg_map, reg_map_size, 0);
@@ -5039,22 +5014,20 @@ strength_reduce (loop, insn_count, unroll_p, bct_p)
       if (unrolled_insn_copies < 0)
        unrolled_insn_copies = 0;
     }
-  
+
   /* Unroll loops from within strength reduction so that we can use the
      induction variable information that strength_reduce has already
      collected.  Always unroll loops that would be as small or smaller
      unrolled than when rolled.  */
-  if (unroll_p
+  if ((flags & LOOP_UNROLL)
       || (loop_info->n_iterations > 0
          && unrolled_insn_copies <= insn_count))
     unroll_loop (loop, insn_count, end_insert_before, 1);
 
-#ifdef HAVE_decrement_and_branch_on_count
-  /* Instrument the loop with BCT insn.  */
-  if (HAVE_decrement_and_branch_on_count && bct_p
-      && flag_branch_on_count_reg)
-    insert_bct (loop);
-#endif  /* HAVE_decrement_and_branch_on_count */
+#ifdef HAVE_doloop_end
+  if (HAVE_doloop_end && (flags & LOOP_BCT) && flag_branch_on_count_reg)
+    doloop_optimize (loop);
+#endif  /* HAVE_doloop_end  */
 
   if (loop_dump_stream)
     fprintf (loop_dump_stream, "\n");
@@ -5090,22 +5063,19 @@ check_insn_for_bivs (loop, p, not_every_iteration, maybe_multiple)
          && REGNO (dest_reg) >= FIRST_PSEUDO_REGISTER
          && REG_IV_TYPE (REGNO (dest_reg)) != NOT_BASIC_INDUCT)
        {
-         int multi_insn_incr = 0;
-
          if (basic_induction_var (loop, SET_SRC (set),
                                   GET_MODE (SET_SRC (set)),
                                   dest_reg, p, &inc_val, &mult_val,
-                                  &location, &multi_insn_incr))
+                                  &location))
            {
              /* It is a possible basic induction variable.
                 Create and initialize an induction structure for it.  */
 
              struct induction *v
-             = (struct induction *) oballoc (sizeof (struct induction));
+               = (struct induction *) oballoc (sizeof (struct induction));
 
              record_biv (v, p, dest_reg, inc_val, mult_val, location,
-                         not_every_iteration, maybe_multiple,
-                         multi_insn_incr);
+                         not_every_iteration, maybe_multiple);
              REG_IV_TYPE (REGNO (dest_reg)) = BASIC_INDUCT;
            }
          else if (REGNO (dest_reg) < max_reg_before_loop)
@@ -5115,7 +5085,7 @@ check_insn_for_bivs (loop, p, not_every_iteration, maybe_multiple)
   return p;
 }
 \f
-/* Record all givs calculated in the insn.  
+/* Record all givs calculated in the insn.
    A register is a giv if: it is only set once, it is a function of a
    biv and a constant (or invariant), and it is not a biv.  */
 static rtx
@@ -5146,12 +5116,12 @@ check_insn_for_givs (loop, p, not_every_iteration, maybe_multiple)
 
       if (/* SET_SRC is a giv.  */
          (general_induction_var (loop, SET_SRC (set), &src_reg, &add_val,
-                                 &mult_val, 0, &benefit)
+                                 &mult_val, 0, &benefit, VOIDmode)
           /* Equivalent expression is a giv.  */
           || ((regnote = find_reg_note (p, REG_EQUAL, NULL_RTX))
               && general_induction_var (loop, XEXP (regnote, 0), &src_reg,
                                         &add_val, &mult_val, 0,
-                                        &benefit)))
+                                        &benefit, VOIDmode)))
          /* Don't try to handle any regs made by loop optimization.
             We have nothing on them in regno_first_uid, etc.  */
          && REGNO (dest_reg) < max_reg_before_loop
@@ -5195,7 +5165,7 @@ check_insn_for_givs (loop, p, not_every_iteration, maybe_multiple)
   /* Update the status of whether giv can derive other givs.  This can
      change when we pass a label or an insn that updates a biv.  */
   if (GET_CODE (p) == INSN || GET_CODE (p) == JUMP_INSN
-    || GET_CODE (p) == CODE_LABEL)
+      || GET_CODE (p) == CODE_LABEL)
     update_giv_derive (loop, p);
   return p;
 }
@@ -5284,12 +5254,12 @@ find_mem_givs (loop, x, insn, not_every_iteration, maybe_multiple)
        int benefit;
 
        /* This code used to disable creating GIVs with mult_val == 1 and
-          add_val == 0.  However, this leads to lost optimizations when 
+          add_val == 0.  However, this leads to lost optimizations when
           it comes time to combine a set of related DEST_ADDR GIVs, since
           this one would not be seen.   */
 
        if (general_induction_var (loop, XEXP (x, 0), &src_reg, &add_val,
-                                  &mult_val, 1, &benefit))
+                                  &mult_val, 1, &benefit, GET_MODE (x)))
          {
            /* Found one; record it.  */
            struct induction *v
@@ -5339,7 +5309,7 @@ find_mem_givs (loop, x, insn, not_every_iteration, maybe_multiple)
 
 static void
 record_biv (v, insn, dest_reg, inc_val, mult_val, location,
-           not_every_iteration, maybe_multiple, multi_insn_incr)
+           not_every_iteration, maybe_multiple)
      struct induction *v;
      rtx insn;
      rtx dest_reg;
@@ -5348,7 +5318,6 @@ record_biv (v, insn, dest_reg, inc_val, mult_val, location,
      rtx *location;
      int not_every_iteration;
      int maybe_multiple;
-     int multi_insn_incr;
 {
   struct iv_class *bl;
 
@@ -5362,7 +5331,6 @@ record_biv (v, insn, dest_reg, inc_val, mult_val, location,
   v->always_computable = ! not_every_iteration;
   v->always_executed = ! not_every_iteration;
   v->maybe_multiple = maybe_multiple;
-  v->multi_insn_incr = multi_insn_incr;
 
   /* Add this to the reg's iv_class, creating a class
      if this is the first incrementation of the reg.  */
@@ -5457,6 +5425,12 @@ record_giv (loop, v, insn, src_reg, dest_reg, mult_val, add_val, benefit,
   struct induction *b;
   struct iv_class *bl;
   rtx set = single_set (insn);
+  rtx temp;
+
+  /* Attempt to prove constantness of the values.  */
+  temp = simplify_rtx (add_val);
+  if (temp)
+    add_val = temp;
 
   v->insn = insn;
   v->src_reg = src_reg;
@@ -5469,7 +5443,6 @@ record_giv (loop, v, insn, src_reg, dest_reg, mult_val, add_val, benefit,
   v->cant_derive = 0;
   v->combined_with = 0;
   v->maybe_multiple = maybe_multiple;
-  v->multi_insn_incr = 0;
   v->maybe_dead = 0;
   v->derive_adjustment = 0;
   v->same = 0;
@@ -5553,17 +5526,17 @@ record_giv (loop, v, insn, src_reg, dest_reg, mult_val, add_val, benefit,
 
       if (REGNO_FIRST_UID (REGNO (dest_reg)) == INSN_UID (insn)
          /* Previous line always fails if INSN was moved by loop opt.  */
-         && uid_luid[REGNO_LAST_UID (REGNO (dest_reg))] 
+         && uid_luid[REGNO_LAST_UID (REGNO (dest_reg))]
          < INSN_LUID (loop->end)
          && (! not_every_iteration
              || last_use_this_basic_block (dest_reg, insn)))
-       {
+       {
          /* Now check that there are no assignments to the biv within the
             giv's lifetime.  This requires two separate checks.  */
 
          /* Check each biv update, and fail if any are between the first
             and last use of the giv.
-            
+
             If this loop contains an inner loop that was unrolled, then
             the insn modifying the biv may have been emitted by the loop
             unrolling code, and hence does not have a valid luid.  Just
@@ -5584,7 +5557,7 @@ record_giv (loop, v, insn, src_reg, dest_reg, mult_val, add_val, benefit,
                  v->replaceable = 0;
                  v->not_replaceable = 1;
                  break;
-               }
+               }
            }
 
          /* If there are any backwards branches that go from after the
@@ -5615,11 +5588,11 @@ record_giv (loop, v, insn, src_reg, dest_reg, mult_val, add_val, benefit,
     v->no_const_addval = 1;
     if (tem == const0_rtx)
       ;
-    else if (GET_CODE (tem) == CONST_INT)
+    else if (CONSTANT_P (add_val))
       v->no_const_addval = 0;
-    else if (GET_CODE (tem) == PLUS)
+    if (GET_CODE (tem) == PLUS)
       {
-        while (1)
+       while (1)
          {
            if (GET_CODE (XEXP (tem, 0)) == PLUS)
              tem = XEXP (tem, 0);
@@ -5628,8 +5601,8 @@ record_giv (loop, v, insn, src_reg, dest_reg, mult_val, add_val, benefit,
            else
              break;
          }
-        if (GET_CODE (XEXP (tem, 1)) == CONST_INT)
-          v->no_const_addval = 0;
+       if (CONSTANT_P (XEXP (tem, 1)))
+         v->no_const_addval = 0;
       }
   }
 
@@ -5681,7 +5654,6 @@ record_giv (loop, v, insn, src_reg, dest_reg, mult_val, add_val, benefit,
 
 }
 
-
 /* All this does is determine whether a giv can be made replaceable because
    its final value can be calculated.  This code can not be part of record_giv
    above, because final_giv_value requires that the number of loop iterations
@@ -5773,7 +5745,7 @@ check_final_value (loop, v)
                last_giv_use = p;
            }
        }
-      
+
       /* Now that the lifetime of the giv is known, check for branches
         from within the lifetime to outside the lifetime if it is still
         replaceable.  */
@@ -5831,7 +5803,7 @@ check_final_value (loop, v)
 
 static void
 update_giv_derive (loop, p)
-     const  struct loop *loop;
+     const struct loop *loop;
      rtx p;
 {
   struct iv_class *bl;
@@ -5953,7 +5925,7 @@ update_giv_derive (loop, p)
    Note that treating the entire pseudo as a BIV will result in making
    simple increments to any GIVs based on it.  However, if the variable
    overflows in its declared mode but not its promoted mode, the result will
-   be incorrect.  This is acceptable if the variable is signed, since 
+   be incorrect.  This is acceptable if the variable is signed, since
    overflows in such cases are undefined, but not if it is unsigned, since
    those overflows are defined.  So we only check for SIGN_EXTEND and
    not ZERO_EXTEND.
@@ -5961,8 +5933,7 @@ update_giv_derive (loop, p)
    If we cannot find a biv, we return 0.  */
 
 static int
-basic_induction_var (loop, x, mode, dest_reg, p, inc_val, mult_val,
-                    location, multi_insn_incr)
+basic_induction_var (loop, x, mode, dest_reg, p, inc_val, mult_val, location)
      const struct loop *loop;
      register rtx x;
      enum machine_mode mode;
@@ -5971,7 +5942,6 @@ basic_induction_var (loop, x, mode, dest_reg, p, inc_val, mult_val,
      rtx *inc_val;
      rtx *mult_val;
      rtx **location;
-     int *multi_insn_incr;
 {
   register enum rtx_code code;
   rtx *argp, arg;
@@ -5997,7 +5967,7 @@ basic_induction_var (loop, x, mode, dest_reg, p, inc_val, mult_val,
          argp = &XEXP (x, 0);
        }
       else
-       return 0;
+       return 0;
 
       arg = *argp;
       if (loop_invariant_p (loop, arg) != 1)
@@ -6014,23 +5984,29 @@ basic_induction_var (loop, x, mode, dest_reg, p, inc_val, mult_val,
       if (SUBREG_PROMOTED_VAR_P (x))
        return basic_induction_var (loop, SUBREG_REG (x),
                                    GET_MODE (SUBREG_REG (x)),
-                                   dest_reg, p, inc_val, mult_val, location,
-                                   multi_insn_incr);
+                                   dest_reg, p, inc_val, mult_val, location);
       return 0;
 
     case REG:
       /* If this register is assigned in a previous insn, look at its
         source, but don't go outside the loop or past a label.  */
 
+      /* If this sets a register to itself, we would repeat any previous
+        biv increment if we applied this strategy blindly.  */
+      if (rtx_equal_p (dest_reg, x))
+       return 0;
+
       insn = p;
       while (1)
        {
-         do {
-           insn = PREV_INSN (insn);
-         } while (insn && GET_CODE (insn) == NOTE
-                  && NOTE_LINE_NUMBER (insn) != NOTE_INSN_LOOP_BEG);
+         do
+           {
+             insn = PREV_INSN (insn);
+           }
+         while (insn && GET_CODE (insn) == NOTE
+                && NOTE_LINE_NUMBER (insn) != NOTE_INSN_LOOP_BEG);
 
-          if (!insn)
+         if (!insn)
            break;
          set = single_set (insn);
          if (set == 0)
@@ -6048,12 +6024,8 @@ basic_induction_var (loop, x, mode, dest_reg, p, inc_val, mult_val,
                                       ? GET_MODE (x)
                                       : GET_MODE (SET_SRC (set))),
                                      dest_reg, insn,
-                                     inc_val, mult_val, location,
-                                     multi_insn_incr))
-           {
-             *multi_insn_incr = 1;
-             return 1;
-           }
+                                     inc_val, mult_val, location))
+           return 1;
        }
       /* ... fall through ...  */
 
@@ -6076,16 +6048,15 @@ basic_induction_var (loop, x, mode, dest_reg, p, inc_val, mult_val,
        {
          /* Possible bug here?  Perhaps we don't know the mode of X.  */
          *inc_val = convert_modes (GET_MODE (dest_reg), mode, x, 0);
-         *mult_val = const0_rtx;
-         return 1;
-       }
+         *mult_val = const0_rtx;
+         return 1;
+       }
       else
-       return 0;
+       return 0;
 
     case SIGN_EXTEND:
       return basic_induction_var (loop, XEXP (x, 0), GET_MODE (XEXP (x, 0)),
-                                 dest_reg, p, inc_val, mult_val, location,
-                                 multi_insn_incr);
+                                 dest_reg, p, inc_val, mult_val, location);
 
     case ASHIFTRT:
       /* Similar, since this can be a sign extension.  */
@@ -6098,19 +6069,16 @@ basic_induction_var (loop, x, mode, dest_reg, p, inc_val, mult_val,
       if (insn)
        set = single_set (insn);
 
-      if (set && SET_DEST (set) == XEXP (x, 0)
+      if (! rtx_equal_p (dest_reg, XEXP (x, 0))
+         && set && SET_DEST (set) == XEXP (x, 0)
          && GET_CODE (XEXP (x, 1)) == CONST_INT
          && INTVAL (XEXP (x, 1)) >= 0
          && GET_CODE (SET_SRC (set)) == ASHIFT
-         && XEXP (x, 1) == XEXP (SET_SRC (set), 1)
-         && basic_induction_var (loop, XEXP (SET_SRC (set), 0),
-                                 GET_MODE (XEXP (x, 0)),
-                                 dest_reg, insn, inc_val, mult_val,
-                                 location, multi_insn_incr))
-       {
-         *multi_insn_incr = 1;
-         return 1;
-       }
+         && XEXP (x, 1) == XEXP (SET_SRC (set), 1))
+       return basic_induction_var (loop, XEXP (SET_SRC (set), 0),
+                                   GET_MODE (XEXP (x, 0)),
+                                   dest_reg, insn, inc_val, mult_val,
+                                   location);
       return 0;
 
     default:
@@ -6133,7 +6101,8 @@ basic_induction_var (loop, x, mode, dest_reg, p, inc_val, mult_val,
      such that the value of X is biv * mult + add;  */
 
 static int
-general_induction_var (loop, x, src_reg, add_val, mult_val, is_addr, pbenefit)
+general_induction_var (loop, x, src_reg, add_val, mult_val, is_addr,
+                      pbenefit, addr_mode)
      const struct loop *loop;
      rtx x;
      rtx *src_reg;
@@ -6141,6 +6110,7 @@ general_induction_var (loop, x, src_reg, add_val, mult_val, is_addr, pbenefit)
      rtx *mult_val;
      int is_addr;
      int *pbenefit;
+     enum machine_mode addr_mode;
 {
   rtx orig_x = x;
   char *storage;
@@ -6214,20 +6184,14 @@ general_induction_var (loop, x, src_reg, add_val, mult_val, is_addr, pbenefit)
     *mult_val = XEXP (*mult_val, 0);
 
   if (is_addr)
-    {
-#ifdef ADDRESS_COST
-      *pbenefit += ADDRESS_COST (orig_x) - reg_address_cost;
-#else
-      *pbenefit += rtx_cost (orig_x, MEM) - reg_address_cost;
-#endif
-    }
+    *pbenefit += address_cost (orig_x, addr_mode) - reg_address_cost;
   else
     *pbenefit += rtx_cost (orig_x, SET);
 
   /* Always return true if this is a giv so it will be detected as such,
-     even if the benefit is zero or negative.  This allows elimination  
-     of bivs that might otherwise not be eliminated.  */                
-  return 1;                                                             
+     even if the benefit is zero or negative.  This allows elimination
+     of bivs that might otherwise not be eliminated.  */
+  return 1;
 }
 \f
 /* Given an expression, X, try to form it as a linear function of a biv.
@@ -6246,7 +6210,7 @@ general_induction_var (loop, x, src_reg, add_val, mult_val, is_addr, pbenefit)
    returns 0.
 
    For a non-zero return, the result will have a code of CONST_INT, USE,
-   REG (for a BIV), PLUS, or MULT.  No other codes will occur.  
+   REG (for a BIV), PLUS, or MULT.  No other codes will occur.
 
    *BENEFIT will be incremented by the benefit of any sub-giv encountered.  */
 
@@ -6414,25 +6378,40 @@ simplify_giv_expr (loop, x, benefit)
          return GEN_INT (INTVAL (arg0) * INTVAL (arg1));
 
        case USE:
-         /* invar * invar.  It is a giv, but very few of these will 
-            actually pay off, so limit to simple registers.  */
+         /* invar * invar is a giv, but attempt to simplify it somehow.  */
          if (GET_CODE (arg1) != CONST_INT)
            return NULL_RTX;
 
          arg0 = XEXP (arg0, 0);
-         if (GET_CODE (arg0) == REG)
-           tem = gen_rtx_MULT (mode, arg0, arg1);
-         else if (GET_CODE (arg0) == MULT
-                  && GET_CODE (XEXP (arg0, 0)) == REG
-                  && GET_CODE (XEXP (arg0, 1)) == CONST_INT)
+         if (GET_CODE (arg0) == MULT)
            {
-             tem = gen_rtx_MULT (mode, XEXP (arg0, 0), 
-                                 GEN_INT (INTVAL (XEXP (arg0, 1))
-                                          * INTVAL (arg1)));
+             /* (invar_0 * invar_1) * invar_2.  Associate.  */
+             return simplify_giv_expr (loop,
+                                       gen_rtx_MULT (mode,
+                                                     XEXP (arg0, 0),
+                                                     gen_rtx_MULT (mode,
+                                                                   XEXP (arg0,
+                                                                         1),
+                                                                   arg1)),
+                                       benefit);
            }
-         else
-           return NULL_RTX;
-         return gen_rtx_USE (mode, tem);
+         /* Porpagate the MULT expressions to the intermost nodes.  */
+         else if (GET_CODE (arg0) == PLUS)
+           {
+             /* (invar_0 + invar_1) * invar_2.  Distribute.  */
+             return simplify_giv_expr (loop,
+                                       gen_rtx_PLUS (mode,
+                                                     gen_rtx_MULT (mode,
+                                                                   XEXP (arg0,
+                                                                         0),
+                                                                   arg1),
+                                                     gen_rtx_MULT (mode,
+                                                                   XEXP (arg0,
+                                                                         1),
+                                                                   arg1)),
+                                       benefit);
+           }
+         return gen_rtx_USE (mode, gen_rtx_MULT (mode, arg0, arg1));
 
        case MULT:
          /* (a * invar_1) * invar_2.  Associate.  */
@@ -6528,15 +6507,15 @@ simplify_giv_expr (loop, x, benefit)
            {
              struct movable *m;
 
-             for (m = the_movables; m ; m = m->next)
+             for (m = the_movables; m; m = m->next)
                if (rtx_equal_p (x, m->set_dest))
                  {
                    /* Ok, we found a match.  Substitute and simplify.  */
 
-                   /* If we match another movable, we must use that, as 
+                   /* If we match another movable, we must use that, as
                       this one is going away.  */
                    if (m->match)
-                     return simplify_giv_expr (loop, m->match->set_dest, 
+                     return simplify_giv_expr (loop, m->match->set_dest,
                                                benefit);
 
                    /* If consec is non-zero, this is a member of a group of
@@ -6555,8 +6534,8 @@ simplify_giv_expr (loop, x, benefit)
                      }
                    else
                      {
-                       tem = single_set (m->insn);
-                       if (tem)
+                       tem = single_set (m->insn);
+                       if (tem)
                          tem = SET_SRC (tem);
                      }
 
@@ -6703,7 +6682,7 @@ consec_sets_giv (loop, first_benefit, p, src_reg, dest_reg,
   rtx set;
 
   /* Indicate that this is a giv so that we can update the value produced in
-     each insn of the multi-insn sequence. 
+     each insn of the multi-insn sequence.
 
      This induction structure will be used only by the call to
      general_induction_var below, so we can allocate it on our stack.
@@ -6737,11 +6716,12 @@ consec_sets_giv (loop, first_benefit, p, src_reg, dest_reg,
          && GET_CODE (SET_DEST (set)) == REG
          && SET_DEST (set) == dest_reg
          && (general_induction_var (loop, SET_SRC (set), &src_reg,
-                                    add_val, mult_val, 0, &benefit)
+                                    add_val, mult_val, 0, &benefit, VOIDmode)
              /* Giv created by equivalent expression.  */
              || ((temp = find_reg_note (p, REG_EQUAL, NULL_RTX))
                  && general_induction_var (loop, XEXP (temp, 0), &src_reg,
-                                           add_val, mult_val, 0, &benefit)))
+                                           add_val, mult_val, 0, &benefit,
+                                           VOIDmode)))
          && src_reg == v->src_reg)
        {
          if (find_reg_note (p, REG_RETVAL, NULL_RTX))
@@ -6774,7 +6754,7 @@ consec_sets_giv (loop, first_benefit, p, src_reg, dest_reg,
 \f
 /* Return an rtx, if any, that expresses giv G2 as a function of the register
    represented by G1.  If no such expression can be found, or it is clear that
-   it cannot possibly be a valid address, 0 is returned. 
+   it cannot possibly be a valid address, 0 is returned.
 
    To perform the computation, we note that
        G1 = x * v + a          and
@@ -6818,11 +6798,11 @@ express_from_1 (a, b, mult)
 
       ra = XEXP (a, 0), oa = XEXP (a, 1);
       if (GET_CODE (ra) == PLUS)
-        tmp = ra, ra = oa, oa = tmp;
+       tmp = ra, ra = oa, oa = tmp;
 
       rb = XEXP (b, 0), ob = XEXP (b, 1);
       if (GET_CODE (rb) == PLUS)
-        tmp = rb, rb = ob, ob = tmp;
+       tmp = rb, rb = ob, ob = tmp;
 
       if (rtx_equal_p (ra, rb))
        /* We matched: remove one reg completely.  */
@@ -6835,7 +6815,7 @@ express_from_1 (a, b, mult)
        a = ra, b = ob;
       else
        {
-          /* Indicates an extra register in B.  Strip one level from B and 
+          /* Indicates an extra register in B.  Strip one level from B and
             recurse, hoping B was the higher order expression.  */
          ob = express_from_1 (a, ob, mult);
          if (ob == NULL_RTX)
@@ -6866,6 +6846,10 @@ express_from_1 (a, b, mult)
     {
       return plus_constant (b, -INTVAL (a) * INTVAL (mult));
     }
+  else if (CONSTANT_P (a))
+    {
+      return simplify_gen_binary (MINUS, GET_MODE (b) != VOIDmode ? GET_MODE (b) : GET_MODE (a), const0_rtx, a);
+    }
   else if (GET_CODE (b) == PLUS)
     {
       if (rtx_equal_p (a, XEXP (b, 0)))
@@ -6894,8 +6878,8 @@ express_from (g1, g2)
       && GET_CODE (g2->mult_val) == CONST_INT)
     {
       if (g1->mult_val == const0_rtx
-          || INTVAL (g2->mult_val) % INTVAL (g1->mult_val) != 0)
-        return NULL_RTX;
+         || INTVAL (g2->mult_val) % INTVAL (g1->mult_val) != 0)
+       return NULL_RTX;
       mult = GEN_INT (INTVAL (g2->mult_val) / INTVAL (g1->mult_val));
     }
   else if (rtx_equal_p (g1->mult_val, g2->mult_val))
@@ -6953,10 +6937,9 @@ express_from (g1, g2)
          mult = gen_rtx_PLUS (g2->mode, mult, XEXP (add, 0));
          add = tem;
        }
-      
+
       return gen_rtx_PLUS (g2->mode, mult, add);
     }
-  
 }
 \f
 /* Return an rtx, if any, that expresses giv G2 as a function of the register
@@ -7059,7 +7042,7 @@ combine_givs (bl)
       giv_array[i++] = g1;
 
   stats = (struct combine_givs_stats *) xcalloc (giv_count, sizeof (*stats));
-  can_combine = (rtx *) xcalloc (giv_count, giv_count * sizeof(rtx));
+  can_combine = (rtx *) xcalloc (giv_count, giv_count * sizeof (rtx));
 
   for (i = 0; i < giv_count; i++)
     {
@@ -7072,7 +7055,7 @@ combine_givs (bl)
       /* If a DEST_REG GIV is used only once, do not allow it to combine
         with anything, for in doing so we will gain nothing that cannot
         be had by simply letting the GIV with which we would have combined
-        to be reduced on its own.  The losage shows up in particular with 
+        to be reduced on its own.  The losage shows up in particular with
         DEST_ADDR targets on hosts with reg+reg addressing, though it can
         be seen elsewhere as well.  */
       if (g1->giv_type == DEST_REG
@@ -7093,7 +7076,7 @@ combine_givs (bl)
          if (g1 != g2
              && (this_combine = combine_givs_p (g1, g2)) != NULL_RTX)
            {
-             can_combine[i*giv_count + j] = this_combine;
+             can_combine[i * giv_count + j] = this_combine;
              this_benefit += g2->benefit + extra_benefit;
            }
        }
@@ -7102,7 +7085,7 @@ combine_givs (bl)
 
   /* Iterate, combining until we can't.  */
 restart:
-  qsort (stats, giv_count, sizeof(*stats), cmp_combine_givs_stats);
+  qsort (stats, giv_count, sizeof (*stats), cmp_combine_givs_stats);
 
   if (loop_dump_stream)
     {
@@ -7111,7 +7094,7 @@ restart:
        {
          g1 = giv_array[stats[k].giv_number];
          if (!g1->combined_with && !g1->same)
-           fprintf (loop_dump_stream, " {%d, %d}", 
+           fprintf (loop_dump_stream, " {%d, %d}",
                     INSN_UID (giv_array[stats[k].giv_number]->insn),
                     stats[k].total_benefit);
        }
@@ -7132,13 +7115,13 @@ restart:
       for (j = 0; j < giv_count; j++)
        {
          g2 = giv_array[j];
-         if (g1 != g2 && can_combine[i*giv_count + j]
+         if (g1 != g2 && can_combine[i * giv_count + j]
              /* If it has already been combined, skip.  */
              && ! g2->same && ! g2->combined_with)
            {
              int l;
 
-             g2->new_reg = can_combine[i*giv_count + j];
+             g2->new_reg = can_combine[i * giv_count + j];
              g2->same = g1;
              g1->combined_with++;
              g1->lifetime += g2->lifetime;
@@ -7150,13 +7133,13 @@ restart:
                 longer be necessary.  */
              if (! g2->replaceable && REG_USERVAR_P (g2->dest_reg))
                g1_add_benefit -= copy_cost;
-               
+
              /* To help optimize the next set of combinations, remove
                 this giv from the benefits of other potential mates.  */
              for (l = 0; l < giv_count; ++l)
                {
                  int m = stats[l].giv_number;
-                 if (can_combine[m*giv_count + j])
+                 if (can_combine[m * giv_count + j])
                    stats[l].total_benefit -= g2->benefit + extra_benefit;
                }
 
@@ -7174,14 +7157,14 @@ restart:
          for (j = 0; j < giv_count; ++j)
            {
              int m = stats[j].giv_number;
-             if (can_combine[m*giv_count + i])
+             if (can_combine[m * giv_count + i])
                stats[j].total_benefit -= g1->benefit + extra_benefit;
            }
 
          g1->benefit += g1_add_benefit;
 
          /* We've finished with this giv, and everything it touched.
-            Restart the combination so that proper weights for the 
+            Restart the combination so that proper weights for the
             rest of the givs are properly taken into account.  */
          /* ??? Ideally we would compact the arrays at this point, so
             as to not cover old ground.  But sanely compacting
@@ -7302,7 +7285,7 @@ find_life_end (x, stats, insn, biv)
        retval += find_life_end (XEXP (x, i), stats, insn, biv);
 
       else if (fmt[i] == 'E')
-        for (j = XVECLEN (x, i) - 1; j >= 0; j--)
+       for (j = XVECLEN (x, i) - 1; j >= 0; j--)
          retval += find_life_end (XVECEXP (x, i, j), stats, insn, biv);
     }
   return retval;
@@ -7351,7 +7334,7 @@ recombine_givs (loop, bl, unroll_p)
       i++;
     }
 
-  qsort (stats, giv_count, sizeof(*stats), cmp_recombine_givs_stats);
+  qsort (stats, giv_count, sizeof (*stats), cmp_recombine_givs_stats);
 
   /* Set up the ix field for each giv in stats to name
      the corresponding index into stats, and
@@ -7415,7 +7398,7 @@ recombine_givs (loop, bl, unroll_p)
          /* Loop unrolling of an inner loop can even create new DEST_REG
             givs.  */
          rtx p;
-         for (p = v->insn; INSN_UID (p) >= max_uid_for_loop; )
+         for (p = v->insn; INSN_UID (p) >= max_uid_for_loop;)
            p = PREV_INSN (p);
          stats[i].start_luid = stats[i].end_luid = INSN_LUID (p);
          if (p != v->insn)
@@ -7456,7 +7439,7 @@ recombine_givs (loop, bl, unroll_p)
                {
                  p = prev_nonnote_insn (p);
                  if (reg_set_p (v->dest_reg, p))
-                 count--;
+                   count--;
                }
 
              stats[i].start_luid = INSN_LUID (p);
@@ -7490,7 +7473,7 @@ recombine_givs (loop, bl, unroll_p)
          if (p == loop->start)
            p = loop->end;
          p = PREV_INSN (p);
-         if (GET_RTX_CLASS (GET_CODE (p)) != 'i')
+         if (! INSN_P (p))
            continue;
          ends_need_computing -= find_life_end (PATTERN (p), stats, p, biv);
        }
@@ -7528,7 +7511,7 @@ recombine_givs (loop, bl, unroll_p)
        }
     }
 
-  qsort (stats, giv_count, sizeof(*stats), cmp_recombine_givs_stats);
+  qsort (stats, giv_count, sizeof (*stats), cmp_recombine_givs_stats);
 
   /* Try to derive DEST_REG givs from previous DEST_REG givs with the
      same mult_val and non-overlapping lifetime.  This reduces register
@@ -7659,8 +7642,8 @@ emit_iv_add_mult (b, m, a, reg, insert_before)
 
   emit_insn_before (seq, insert_before);
 
-  /* It is entirely possible that the expansion created lots of new 
-     registers.  Iterate over the sequence we just created and 
+  /* It is entirely possible that the expansion created lots of new
+     registers.  Iterate over the sequence we just created and
      record them all.  */
 
   if (GET_CODE (seq) == SEQUENCE)
@@ -7796,6 +7779,8 @@ check_dbra_loop (loop, insn_count)
   comparison = get_condition_for_loop (loop, jump);
   if (comparison == 0)
     return 0;
+  if (!onlyjump_p (jump))
+    return 0;
 
   /* Try to compute whether the compare/branch at the loop end is one or
      two instructions.  */
@@ -7807,6 +7792,20 @@ check_dbra_loop (loop, insn_count)
   else
     return 0;
 
+  {
+    /* If more than one condition is present to control the loop, then
+       do not proceed, as this function does not know how to rewrite
+       loop tests with more than one condition.
+
+       Look backwards from the first insn in the last comparison
+       sequence and see if we've got another comparison sequence.  */
+
+    rtx jump1;
+    if ((jump1 = prev_nonnote_insn (first_compare)) != loop->cont)
+      if (GET_CODE (jump1) == JUMP_INSN)
+        return 0;
+  }
+
   /* Check all of the bivs to see if the compare uses one of them.
      Skip biv's set more than once because we can't guarantee that
      it will be zero on the last iteration.  Also skip if the biv is
@@ -7847,9 +7846,10 @@ check_dbra_loop (loop, insn_count)
              % (-INTVAL (bl->biv->add_val))) == 0)
        {
          /* register always nonnegative, add REG_NOTE to branch */
-         REG_NOTES (PREV_INSN (loop_end))
-           = gen_rtx_EXPR_LIST (REG_NONNEG, NULL_RTX,
-                                REG_NOTES (PREV_INSN (loop_end)));
+         if (! find_reg_note (jump, REG_NONNEG, NULL_RTX))
+           REG_NOTES (jump)
+             = gen_rtx_EXPR_LIST (REG_NONNEG, bl->biv->dest_reg,
+                                  REG_NOTES (jump));
          bl->nonneg = 1;
 
          return 1;
@@ -7872,9 +7872,10 @@ check_dbra_loop (loop, insn_count)
              && ! reg_set_between_p (bl->biv->dest_reg, p, loop_start)
              && INTVAL (bl->biv->add_val) == -1)
            {
-             REG_NOTES (PREV_INSN (loop_end))
-               = gen_rtx_EXPR_LIST (REG_NONNEG, NULL_RTX,
-                                    REG_NOTES (PREV_INSN (loop_end)));
+             if (! find_reg_note (jump, REG_NONNEG, NULL_RTX))
+               REG_NOTES (jump)
+                 = gen_rtx_EXPR_LIST (REG_NONNEG, bl->biv->dest_reg,
+                                      REG_NOTES (jump));
              bl->nonneg = 1;
 
              return 1;
@@ -7911,7 +7912,7 @@ check_dbra_loop (loop, insn_count)
             see if perhaps there are no uses except to count.  */
          no_use_except_counting = 1;
          for (p = loop_start; p != loop_end; p = NEXT_INSN (p))
-           if (GET_RTX_CLASS (GET_CODE (p)) == 'i')
+           if (INSN_P (p))
              {
                rtx set = single_set (p);
 
@@ -7945,11 +7946,12 @@ check_dbra_loop (loop, insn_count)
        }
 
       if (no_use_except_counting)
-       ; /* no need to worry about MEMs.  */
+       /* No need to worry about MEMs.  */
+       ;
       else if (num_mem_sets <= 1)
        {
          for (p = loop_start; p != loop_end; p = NEXT_INSN (p))
-           if (GET_RTX_CLASS (GET_CODE (p)) == 'i')
+           if (INSN_P (p))
              num_nonfixed_reads += count_nonfixed_reads (loop, PATTERN (p));
 
          /* If the loop has a single store, and the destination address is
@@ -7976,7 +7978,7 @@ check_dbra_loop (loop, insn_count)
                {
                  if (v->giv_type == DEST_REG
                      && reg_mentioned_p (v->dest_reg,
-                                        PATTERN (first_loop_store_insn)) 
+                                         PATTERN (first_loop_store_insn))
                      && loop_insn_first_p (first_loop_store_insn, v->insn))
                    reversible_mem_store = 0;
                }
@@ -8011,7 +8013,7 @@ check_dbra_loop (loop, insn_count)
          /* Now check other conditions:
 
             The increment must be a constant, as must the initial value,
-            and the comparison code must be LT. 
+            and the comparison code must be LT.
 
             This test can probably be improved since +/- 1 in the constant
             can be obtained by changing LT to LE and vice versa; this is
@@ -8041,7 +8043,7 @@ check_dbra_loop (loop, insn_count)
              if (comparison_const_width > HOST_BITS_PER_WIDE_INT)
                comparison_const_width = HOST_BITS_PER_WIDE_INT;
              comparison_sign_mask
-               = (unsigned HOST_WIDE_INT)1 << (comparison_const_width - 1);
+               = (unsigned HOST_WIDE_INT) 1 << (comparison_const_width - 1);
 
              /* If the comparison value is not a loop invariant, then we
                 can not reverse this loop.
@@ -8055,8 +8057,8 @@ check_dbra_loop (loop, insn_count)
              if (GET_CODE (comparison_value) == CONST_INT)
                comparison_val = INTVAL (comparison_value);
              initial_value = bl->initial_value;
-               
-             /* Normalize the initial value if it is an integer and 
+
+             /* Normalize the initial value if it is an integer and
                 has no other use except as a counter.  This will allow
                 a few more loops to be reversed.  */
              if (no_use_except_counting
@@ -8211,12 +8213,12 @@ check_dbra_loop (loop, insn_count)
                 create a sequence to hold all the insns from expand_inc.  */
              start_sequence ();
              expand_inc (reg, new_add_val);
-              tem = gen_sequence ();
-              end_sequence ();
+             tem = gen_sequence ();
+             end_sequence ();
 
              p = emit_insn_before (tem, bl->biv->insn);
              delete_insn (bl->biv->insn);
-                     
+
              /* Update biv info to reflect its new status.  */
              bl->biv->insn = p;
              bl->initial_value = start_value;
@@ -8251,7 +8253,7 @@ check_dbra_loop (loop, insn_count)
              /* Add new compare/branch insn at end of loop.  */
              start_sequence ();
              emit_cmp_and_jump_insns (reg, const0_rtx, cmp_code, NULL_RTX,
-                                      GET_MODE (reg), 0, 0, 
+                                      GET_MODE (reg), 0, 0,
                                       XEXP (jump_label, 0));
              tem = gen_sequence ();
              end_sequence ();
@@ -8272,7 +8274,7 @@ check_dbra_loop (loop, insn_count)
                      /* Increment of LABEL_NUSES done above.  */
                      /* Register is now always nonnegative,
                         so add REG_NONNEG note to the branch.  */
-                     REG_NOTES (tem) = gen_rtx_EXPR_LIST (REG_NONNEG, NULL_RTX,
+                     REG_NOTES (tem) = gen_rtx_EXPR_LIST (REG_NONNEG, reg,
                                                           REG_NOTES (tem));
                    }
                  bl->nonneg = 1;
@@ -8290,7 +8292,7 @@ check_dbra_loop (loop, insn_count)
                 remove all REG_EQUAL notes based on the reversed biv
                 here.  */
              for (p = loop_start; p != loop_end; p = NEXT_INSN (p))
-               if (GET_RTX_CLASS (GET_CODE (p)) == 'i')
+               if (INSN_P (p))
                  {
                    rtx *pnote;
                    rtx set = single_set (p);
@@ -8418,7 +8420,7 @@ loop_insn_first_p (insn, reference)
 {
   rtx p, q;
 
-  for (p = insn, q = reference; ;)
+  for (p = insn, q = reference;;)
     {
       /* Start with test for not first so that INSN == REFERENCE yields not
          first.  */
@@ -8541,7 +8543,7 @@ maybe_eliminate_biv_1 (loop, x, insn, bl, eliminate_p, where)
             overflows.  */
 
          for (v = bl->giv; v; v = v->next_iv)
-           if (CONSTANT_P (v->mult_val) && v->mult_val != const0_rtx
+           if (GET_CODE (v->mult_val) == CONST_INT && v->mult_val != const0_rtx
                && v->add_val == const0_rtx
                && ! v->ignore && ! v->maybe_dead && v->always_computable
                && v->mode == mode
@@ -8573,7 +8575,8 @@ maybe_eliminate_biv_1 (loop, x, insn, bl, eliminate_p, where)
             overflow problem.  */
 
          for (v = bl->giv; v; v = v->next_iv)
-           if (CONSTANT_P (v->mult_val) && v->mult_val != const0_rtx
+           if (GET_CODE (v->mult_val) == CONST_INT
+               && v->mult_val != const0_rtx
                && ! v->ignore && ! v->maybe_dead && v->always_computable
                && v->mode == mode
                && (GET_CODE (v->add_val) == SYMBOL_REF
@@ -8610,7 +8613,7 @@ maybe_eliminate_biv_1 (loop, x, insn, bl, eliminate_p, where)
                                  where);
 
                /* Substitute the new register for its invariant value in
-                  the compare expression. */
+                  the compare expression.  */
                XEXP (new, (INTVAL (v->mult_val) < 0) ? 0 : 1) = tem;
                if (validate_change (insn, &SET_SRC (PATTERN (insn)), new, 0))
                  return 1;
@@ -8638,7 +8641,8 @@ maybe_eliminate_biv_1 (loop, x, insn, bl, eliminate_p, where)
             negative mult_val, but it seems complex to do it in general.  */
 
          for (v = bl->giv; v; v = v->next_iv)
-           if (CONSTANT_P (v->mult_val) && INTVAL (v->mult_val) > 0
+           if (GET_CODE (v->mult_val) == CONST_INT
+               && INTVAL (v->mult_val) > 0
                && (GET_CODE (v->add_val) == SYMBOL_REF
                    || GET_CODE (v->add_val) == LABEL_REF
                    || GET_CODE (v->add_val) == CONST
@@ -8654,36 +8658,38 @@ maybe_eliminate_biv_1 (loop, x, insn, bl, eliminate_p, where)
                  return 1;
 
                /* Replace biv with the giv's reduced reg.  */
-               XEXP (x, 1-arg_operand) = v->new_reg;
+               validate_change (insn, &XEXP (x, 1 - arg_operand), v->new_reg, 1);
 
                /* If all constants are actually constant integers and
                   the derived constant can be directly placed in the COMPARE,
                   do so.  */
                if (GET_CODE (arg) == CONST_INT
                    && GET_CODE (v->mult_val) == CONST_INT
-                   && GET_CODE (v->add_val) == CONST_INT
-                   && validate_change (insn, &XEXP (x, arg_operand),
-                                       GEN_INT (INTVAL (arg)
-                                                * INTVAL (v->mult_val)
-                                                + INTVAL (v->add_val)), 0))
-                 return 1;
-
-               /* Otherwise, load it into a register.  */
-               tem = gen_reg_rtx (mode);
-               emit_iv_add_mult (arg, v->mult_val, v->add_val, tem, where);
-               if (validate_change (insn, &XEXP (x, arg_operand), tem, 0))
+                   && GET_CODE (v->add_val) == CONST_INT)
+                 {
+                   validate_change (insn, &XEXP (x, arg_operand),
+                                    GEN_INT (INTVAL (arg)
+                                             * INTVAL (v->mult_val)
+                                             + INTVAL (v->add_val)), 1);
+                 }
+               else
+                 {
+                   /* Otherwise, load it into a register.  */
+                   tem = gen_reg_rtx (mode);
+                   emit_iv_add_mult (arg, v->mult_val, v->add_val, tem, where);
+                   validate_change (insn, &XEXP (x, arg_operand), tem, 1);
+                 }
+               if (apply_change_group ())
                  return 1;
-
-               /* If that failed, put back the change we made above.  */
-               XEXP (x, 1-arg_operand) = reg;
              }
-         
+
          /* Look for giv with positive constant mult_val and nonconst add_val.
-            Insert insns to calculate new compare value.  
+            Insert insns to calculate new compare value.
             ??? Turn this off due to possible overflow.  */
 
          for (v = bl->giv; v; v = v->next_iv)
-           if (CONSTANT_P (v->mult_val) && INTVAL (v->mult_val) > 0
+           if (GET_CODE (v->mult_val) == CONST_INT
+               && INTVAL (v->mult_val) > 0
                && ! v->ignore && ! v->maybe_dead && v->always_computable
                && v->mode == mode
                && 0)
@@ -8715,11 +8721,11 @@ maybe_eliminate_biv_1 (loop, x, insn, bl, eliminate_p, where)
          if (loop_invariant_p (loop, arg) == 1)
            {
              /* Look for giv with constant positive mult_val and nonconst
-                add_val. Insert insns to compute new compare value. 
+                add_val. Insert insns to compute new compare value.
                 ??? Turn this off due to possible overflow.  */
 
              for (v = bl->giv; v; v = v->next_iv)
-               if (CONSTANT_P (v->mult_val) && INTVAL (v->mult_val) > 0
+               if (GET_CODE (v->mult_val) == CONST_INT && INTVAL (v->mult_val) > 0
                    && ! v->ignore && ! v->maybe_dead && v->always_computable
                    && v->mode == mode
                    && 0)
@@ -8787,7 +8793,7 @@ maybe_eliminate_biv_1 (loop, x, insn, bl, eliminate_p, where)
                      return 1;
 
                    /* Replace biv with its giv's reduced reg.  */
-                   XEXP (x, 1-arg_operand) = v->new_reg;
+                   XEXP (x, 1 - arg_operand) = v->new_reg;
                    /* Replace other operand with the other giv's
                       reduced reg.  */
                    XEXP (x, arg_operand) = tv->new_reg;
@@ -8819,7 +8825,7 @@ maybe_eliminate_biv_1 (loop, x, insn, bl, eliminate_p, where)
       switch (fmt[i])
        {
        case 'e':
-         if (! maybe_eliminate_biv_1 (loop, XEXP (x, i), insn, bl, 
+         if (! maybe_eliminate_biv_1 (loop, XEXP (x, i), insn, bl,
                                       eliminate_p, where))
            return 0;
          break;
@@ -8834,7 +8840,7 @@ maybe_eliminate_biv_1 (loop, x, insn, bl, eliminate_p, where)
     }
 
   return 1;
-}  
+}
 \f
 /* Return nonzero if the last use of REG
    is in an insn following INSN in the same basic block.  */
@@ -9022,7 +9028,7 @@ canonicalize_condition (insn, cond, reverse, earliest, want_reg)
         relevant.  */
       if (rtx_equal_p (SET_DEST (set), op0))
        {
-         enum machine_mode inner_mode = GET_MODE (SET_SRC (set));
+         enum machine_mode inner_mode = GET_MODE (SET_DEST (set));
 
          /* ??? We may not combine comparisons done in a CCmode with
             comparisons not done in a CCmode.  This is to aid targets
@@ -9075,7 +9081,7 @@ canonicalize_condition (insn, cond, reverse, earliest, want_reg)
 #endif
                     ))
                   && GET_RTX_CLASS (GET_CODE (SET_SRC (set))) == '<'
-                  && (((GET_MODE_CLASS (mode) == MODE_CC)
+                  && (((GET_MODE_CLASS (mode) == MODE_CC)
                        == (GET_MODE_CLASS (inner_mode) == MODE_CC))
                       || mode == VOIDmode || inner_mode == VOIDmode))
 
@@ -9140,7 +9146,7 @@ canonicalize_condition (insn, cond, reverse, earliest, want_reg)
        {
        case LE:
          if ((unsigned HOST_WIDE_INT) const_val != max_val >> 1)
-           code = LT,  op1 = GEN_INT (const_val + 1);
+           code = LT, op1 = GEN_INT (const_val + 1);
          break;
 
        /* When cross-compiling, const_val might be sign-extended from
@@ -9202,19 +9208,21 @@ get_condition (jump, earliest)
 {
   rtx cond;
   int reverse;
+  rtx set;
 
   /* If this is not a standard conditional jump, we can't parse it.  */
   if (GET_CODE (jump) != JUMP_INSN
-      || ! condjump_p (jump) || simplejump_p (jump))
+      || ! any_condjump_p (jump))
     return 0;
+  set = pc_set (jump);
 
-  cond = XEXP (SET_SRC (PATTERN (jump)), 0);
+  cond = XEXP (SET_SRC (set), 0);
 
   /* If this branches to JUMP_LABEL when the condition is false, reverse
      the condition.  */
   reverse
-    = GET_CODE (XEXP (SET_SRC (PATTERN (jump)), 2)) == LABEL_REF
-      && XEXP (XEXP (SET_SRC (PATTERN (jump)), 2), 0) == JUMP_LABEL (jump);
+    = GET_CODE (XEXP (SET_SRC (set), 2)) == LABEL_REF
+      && XEXP (XEXP (SET_SRC (set), 2), 0) == JUMP_LABEL (jump);
 
   return canonicalize_condition (jump, cond, reverse, earliest, NULL_RTX);
 }
@@ -9238,289 +9246,6 @@ get_condition_for_loop (loop, x)
                         XEXP (comparison, 1), XEXP (comparison, 0));
 }
 
-#ifdef HAVE_decrement_and_branch_on_count
-/* Instrument loop for insertion of bct instruction.  We distinguish between
-   loops with compile-time bounds and those with run-time bounds. 
-   Information from loop_iterations() is used to compute compile-time bounds.
-   Run-time bounds should use loop preconditioning, but currently ignored.
- */
-
-static void
-insert_bct (loop)
-     struct loop *loop;
-{
-  unsigned HOST_WIDE_INT n_iterations;
-  rtx loop_start = loop->start;
-  rtx loop_end = loop->end;
-  struct loop_info *loop_info = LOOP_INFO (loop);  
-  int loop_num = loop->num;
-
-#if 0
-  int increment_direction, compare_direction;
-  /* If the loop condition is <= or >=, the number of iteration
-      is 1 more than the range of the bounds of the loop.  */
-  int add_iteration = 0;
-  enum machine_mode loop_var_mode = word_mode;
-#endif
-
-  /* It's impossible to instrument a competely unrolled loop.  */
-  if (loop_info->unroll_number == loop_info->n_iterations)
-    return;
-
-  /* Make sure that the count register is not in use.  */
-  if (loop_info->used_count_register)
-    {
-      if (loop_dump_stream)
-       fprintf (loop_dump_stream,
-                "insert_bct %d: BCT instrumentation failed: count register already in use\n",
-                loop_num);
-      return;
-    }
-
-  /* Make sure that the function has no indirect jumps.  */
-  if (indirect_jump_in_function)
-    {
-      if (loop_dump_stream)
-       fprintf (loop_dump_stream,
-                "insert_bct %d: BCT instrumentation failed: indirect jump in function\n",
-                loop_num);
-      return;
-    }
-
-  /* Make sure that the last loop insn is a conditional jump.  */
-  if (GET_CODE (PREV_INSN (loop_end)) != JUMP_INSN
-      || ! condjump_p (PREV_INSN (loop_end))
-      || simplejump_p (PREV_INSN (loop_end)))
-    {
-      if (loop_dump_stream)
-       fprintf (loop_dump_stream,
-                "insert_bct %d: BCT instrumentation failed: invalid jump at loop end\n",
-                loop_num);
-      return;
-    }
-
-  /* Make sure that the loop does not contain a function call
-     (the count register might be altered by the called function).  */
-  if (loop_info->has_call)
-    {
-      if (loop_dump_stream)
-       fprintf (loop_dump_stream,
-                "insert_bct %d: BCT instrumentation failed: function call in loop\n",
-                loop_num);
-      return;
-    }
-
-  /* Make sure that the loop does not jump via a table.
-     (the count register might be used to perform the branch on table).  */
-  if (loop_info->has_tablejump)
-    {
-      if (loop_dump_stream)
-       fprintf (loop_dump_stream,
-                "insert_bct %d: BCT instrumentation failed: computed branch in the loop\n",
-                loop_num);
-      return;
-    }
-
-  /* Account for loop unrolling in instrumented iteration count.  */
-  if (loop_info->unroll_number > 1)
-    n_iterations = loop_info->n_iterations / loop_info->unroll_number;
-  else
-    n_iterations = loop_info->n_iterations;
-
-  if (n_iterations != 0 && n_iterations < 3)
-    {
-      /* Allow an enclosing outer loop to benefit if possible.  */
-      if (loop_dump_stream)
-       fprintf (loop_dump_stream,
-                "insert_bct %d: Too few iterations to benefit from BCT optimization\n",
-                loop_num);
-      return;
-    }
-
-  /* Try to instrument the loop.  */
-
-  /* Handle the simpler case, where the bounds are known at compile time.  */
-  if (n_iterations > 0)
-    {
-      struct loop *outer_loop;
-      struct loop_info *outer_loop_info;
-
-      /* Mark all enclosing loops that they cannot use count register.  */
-      for (outer_loop = loop; outer_loop; outer_loop = outer_loop->outer)
-       {
-         outer_loop_info = LOOP_INFO (outer_loop);
-         outer_loop_info->used_count_register = 1;
-       }
-      instrument_loop_bct (loop_start, loop_end, GEN_INT (n_iterations));
-      return;
-    }
-
-  /* Handle the more complex case, that the bounds are NOT known
-     at compile time.  In this case we generate run_time calculation
-     of the number of iterations.  */
-
-  if (loop_info->iteration_var == 0)
-    {
-      if (loop_dump_stream)
-       fprintf (loop_dump_stream,
-                "insert_bct %d: BCT Runtime Instrumentation failed: no loop iteration variable found\n",
-                loop_num);
-      return;
-    }
-
-  if (GET_MODE_CLASS (GET_MODE (loop_info->iteration_var)) != MODE_INT
-      || GET_MODE_SIZE (GET_MODE (loop_info->iteration_var)) != UNITS_PER_WORD)
-    {
-      if (loop_dump_stream)
-       fprintf (loop_dump_stream,
-                "insert_bct %d: BCT Runtime Instrumentation failed: loop variable not integer\n",
-                loop_num);
-      return;
-    }
-
-  /* With runtime bounds, if the compare is of the form '!=' we give up */
-  if (loop_info->comparison_code == NE)
-    {
-      if (loop_dump_stream)
-       fprintf (loop_dump_stream,
-                "insert_bct %d: BCT Runtime Instrumentation failed: runtime bounds with != comparison\n",
-                loop_num);
-      return;
-    }
-/* Use common loop preconditioning code instead.  */
-#if 0
-  else
-    {
-      /* We rely on the existence of run-time guard to ensure that the
-        loop executes at least once.  */
-      rtx sequence;
-      rtx iterations_num_reg;
-
-      unsigned HOST_WIDE_INT increment_value_abs
-       = INTVAL (increment) * increment_direction;
-
-      /* make sure that the increment is a power of two, otherwise (an
-        expensive) divide is needed.  */
-      if (exact_log2 (increment_value_abs) == -1)
-       {
-         if (loop_dump_stream)
-           fprintf (loop_dump_stream,
-                    "insert_bct: not instrumenting BCT because the increment is not power of 2\n");
-         return;
-       }
-
-      /* compute the number of iterations */
-      start_sequence ();
-      {
-       rtx temp_reg;
-
-       /* Again, the number of iterations is calculated by:
-          ;
-          ;                  compare-val - initial-val + (increment -1) + additional-iteration
-          ; num_iterations = -----------------------------------------------------------------
-          ;                                           increment
-        */
-       /* ??? Do we have to call copy_rtx here before passing rtx to
-          expand_binop?  */
-       if (compare_direction > 0)
-         {
-           /* <, <= :the loop variable is increasing */
-           temp_reg = expand_binop (loop_var_mode, sub_optab,
-                                    comparison_value, initial_value,
-                                    NULL_RTX, 0, OPTAB_LIB_WIDEN);
-         }
-       else
-         {
-           temp_reg = expand_binop (loop_var_mode, sub_optab,
-                                    initial_value, comparison_value,
-                                    NULL_RTX, 0, OPTAB_LIB_WIDEN);
-         }
-
-       if (increment_value_abs - 1 + add_iteration != 0)
-         temp_reg = expand_binop (loop_var_mode, add_optab, temp_reg,
-                                  GEN_INT (increment_value_abs - 1
-                                           + add_iteration),
-                                  NULL_RTX, 0, OPTAB_LIB_WIDEN);
-
-       if (increment_value_abs != 1)
-         iterations_num_reg = expand_binop (loop_var_mode, asr_optab,
-                                            temp_reg,
-                                            GEN_INT (exact_log2 (increment_value_abs)),
-                                            NULL_RTX, 0, OPTAB_LIB_WIDEN);
-       else
-         iterations_num_reg = temp_reg;
-      }
-      sequence = gen_sequence ();
-      end_sequence ();
-      emit_insn_before (sequence, loop_start);
-      instrument_loop_bct (loop_start, loop_end, iterations_num_reg);
-    }
-
-  return;
-#endif /* Complex case */
-}
-
-/* Instrument loop by inserting a bct in it as follows:
-   1. A new counter register is created.
-   2. In the head of the loop the new variable is initialized to the value
-   passed in the loop_num_iterations parameter.
-   3. At the end of the loop, comparison of the register with 0 is generated.
-   The created comparison follows the pattern defined for the
-   decrement_and_branch_on_count insn, so this insn will be generated.
-   4. The branch on the old variable are deleted.  The compare must remain
-   because it might be used elsewhere.  If the loop-variable or condition
-   register are used elsewhere, they will be eliminated by flow.  */
-
-static void
-instrument_loop_bct (loop_start, loop_end, loop_num_iterations)
-     rtx loop_start, loop_end;
-     rtx loop_num_iterations;
-{
-  rtx counter_reg;
-  rtx start_label;
-  rtx sequence;
-
-  if (HAVE_decrement_and_branch_on_count)
-    {
-      if (loop_dump_stream)
-       {
-         fputs ("instrument_bct: Inserting BCT (", loop_dump_stream);
-         if (GET_CODE (loop_num_iterations) == CONST_INT)
-           fprintf (loop_dump_stream, HOST_WIDE_INT_PRINT_DEC,
-                    INTVAL (loop_num_iterations));
-         else
-           fputs ("runtime", loop_dump_stream);
-         fputs (" iterations)", loop_dump_stream);
-       }
-
-      /* Discard original jump to continue loop.  Original compare result
-        may still be live, so it cannot be discarded explicitly.  */
-      delete_insn (PREV_INSN (loop_end));
-
-      /* Insert the label which will delimit the start of the loop.  */
-      start_label = gen_label_rtx ();
-      emit_label_after (start_label, loop_start);
-
-      /* Insert initialization of the count register into the loop header.  */
-      start_sequence ();
-      counter_reg = gen_reg_rtx (word_mode);
-      emit_insn (gen_move_insn (counter_reg, loop_num_iterations));
-      sequence = gen_sequence ();
-      end_sequence ();
-      emit_insn_before (sequence, loop_start);
-
-      /* Insert new comparison on the count register instead of the
-        old one, generating the needed BCT pattern (that will be
-        later recognized by assembly generation phase).  */
-      emit_jump_insn_before (gen_decrement_and_branch_on_count (counter_reg,
-                                                               start_label),
-                            loop_end);
-      LABEL_NUSES (start_label)++;
-    }
-
-}
-#endif /* HAVE_decrement_and_branch_on_count */
-
 /* Scan the function and determine whether it has indirect (computed) jumps.
 
    This is taken mostly from flow.c; similar code exists elsewhere
@@ -9578,7 +9303,7 @@ insert_loop_mem (mem, data)
 
   /* See if we've already seen this MEM.  */
   for (i = 0; i < loop_mems_idx; ++i)
-    if (rtx_equal_p (m, loop_mems[i].mem)) 
+    if (rtx_equal_p (m, loop_mems[i].mem))
       {
        if (GET_MODE (m) != GET_MODE (loop_mems[i].mem))
          /* The modes of the two memory accesses are different.  If
@@ -9590,16 +9315,16 @@ insert_loop_mem (mem, data)
       }
 
   /* Resize the array, if necessary.  */
-  if (loop_mems_idx == loop_mems_allocated) 
+  if (loop_mems_idx == loop_mems_allocated)
     {
       if (loop_mems_allocated != 0)
        loop_mems_allocated *= 2;
       else
        loop_mems_allocated = 32;
 
-      loop_mems = (loop_mem_info*) 
+      loop_mems = (loop_mem_info*)
        xrealloc (loop_mems,
-                 loop_mems_allocated * sizeof (loop_mem_info)); 
+                 loop_mems_allocated * sizeof (loop_mem_info));
     }
 
   /* Actually insert the MEM.  */
@@ -9627,7 +9352,7 @@ load_mems_and_recount_loop_regs_set (loop, insn_count)
   int nregs = max_reg_num ();
 
   load_mems (loop);
-  
+
   /* Recalculate set_in_loop and friends since load_mems may have
      created new registers.  */
   if (max_reg_num () > nregs)
@@ -9653,14 +9378,14 @@ load_mems_and_recount_loop_regs_set (loop, insn_count)
 
       count_loop_regs_set (loop->top ? loop->top : loop->start, loop->end,
                           may_not_optimize, reg_single_usage,
-                          insn_count, nregs); 
+                          insn_count, nregs);
 
       for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
        {
          VARRAY_CHAR (may_not_optimize, i) = 1;
          VARRAY_INT (set_in_loop, i) = 1;
        }
-      
+
 #ifdef AVOID_CCMODE_COPIES
       /* Don't try to move insns which set CC registers if we should not
         create CCmode register copies.  */
@@ -9709,8 +9434,8 @@ load_mems (loop)
 
   /* Check to see if it's possible that some instructions in the
      loop are never executed.  */
-  for (p = next_insn_in_loop (loop, loop->scan_start); 
-       p != NULL_RTX && ! maybe_never; 
+  for (p = next_insn_in_loop (loop, loop->scan_start);
+       p != NULL_RTX && ! maybe_never;
        p = next_insn_in_loop (loop, p))
     {
       if (GET_CODE (p) == CODE_LABEL)
@@ -9722,33 +9447,34 @@ load_mems (loop)
                  otherwise the code at the top of the loop might
                  never be executed.  Unconditional jumps are
                  followed a by barrier then loop end.  */
-              && ! (GET_CODE (p) == JUMP_INSN 
+              && ! (GET_CODE (p) == JUMP_INSN
                     && JUMP_LABEL (p) == loop->top
                     && NEXT_INSN (NEXT_INSN (p)) == loop->end
-                    && simplejump_p (p)))
+                    && any_uncondjump_p (p)))
        {
-         if (!condjump_p (p))
+         if (!any_condjump_p (p))
            /* Something complicated.  */
            maybe_never = 1;
          else
            /* If there are any more instructions in the loop, they
               might not be reached.  */
-           next_maybe_never = 1; 
-       } 
+           next_maybe_never = 1;
+       }
       else if (next_maybe_never)
        maybe_never = 1;
     }
 
   /* Actually move the MEMs.  */
-  for (i = 0; i < loop_mems_idx; ++i) 
+  for (i = 0; i < loop_mems_idx; ++i)
     {
-      regset_head copies;
+      regset_head load_copies;
+      regset_head store_copies;
       int written = 0;
       rtx reg;
       rtx mem = loop_mems[i].mem;
       rtx mem_list_entry;
 
-      if (MEM_VOLATILE_P (mem) 
+      if (MEM_VOLATILE_P (mem)
          || loop_invariant_p (loop, XEXP (mem, 0)) != 1)
        /* There's no telling whether or not MEM is modified.  */
        loop_mems[i].optimize = 0;
@@ -9773,9 +9499,9 @@ load_mems (loop)
       if (flag_float_store && written
          && GET_MODE_CLASS (GET_MODE (mem)) == MODE_FLOAT)
        loop_mems[i].optimize = 0;
-  
+
       /* If this MEM is written to, we must be sure that there
-        are no reads from another MEM that aliases this one.  */ 
+        are no reads from another MEM that aliases this one.  */
       if (loop_mems[i].optimize && written)
        {
          int j;
@@ -9802,13 +9528,14 @@ load_mems (loop)
        /* We can't access the MEM outside the loop; it might
           cause a trap that wouldn't have happened otherwise.  */
        loop_mems[i].optimize = 0;
-         
+
       if (!loop_mems[i].optimize)
        /* We thought we were going to lift this MEM out of the
           loop, but later discovered that we could not.  */
        continue;
 
-      INIT_REG_SET (&copies);
+      INIT_REG_SET (&load_copies);
+      INIT_REG_SET (&store_copies);
 
       /* Allocate a pseudo for this MEM.  We set REG_USERVAR_P in
         order to keep scan_loop from moving stores to this MEM
@@ -9826,14 +9553,16 @@ load_mems (loop)
           p = next_insn_in_loop (loop, p))
        {
          rtx_and_int ri;
-         rtx set;
 
-         if (GET_RTX_CLASS (GET_CODE (p)) == 'i')
+         if (INSN_P (p))
            {
+             rtx set;
+
+             set = single_set (p);
+
              /* See if this copies the mem into a register that isn't
                 modified afterwards.  We'll try to do copy propagation
                 a little further on.  */
-             set = single_set (p);
              if (set
                  /* @@@ This test is _way_ too conservative.  */
                  && ! maybe_never
@@ -9841,8 +9570,24 @@ load_mems (loop)
                  && REGNO (SET_DEST (set)) >= FIRST_PSEUDO_REGISTER
                  && REGNO (SET_DEST (set)) < last_max_reg
                  && VARRAY_INT (n_times_set, REGNO (SET_DEST (set))) == 1
-                 && rtx_equal_p (SET_SRC (set), loop_mems[i].mem))
-               SET_REGNO_REG_SET (&copies, REGNO (SET_DEST (set)));
+                 && rtx_equal_p (SET_SRC (set), mem))
+               SET_REGNO_REG_SET (&load_copies, REGNO (SET_DEST (set)));
+
+             /* See if this copies the mem from a register that isn't
+                modified afterwards.  We'll try to remove the
+                redundant copy later on by doing a little register
+                renaming and copy propagation.   This will help
+                to untangle things for the BIV detection code.  */
+             if (set
+                 && ! maybe_never
+                 && GET_CODE (SET_SRC (set)) == REG
+                 && REGNO (SET_SRC (set)) >= FIRST_PSEUDO_REGISTER
+                 && REGNO (SET_SRC (set)) < last_max_reg
+                 && VARRAY_INT (n_times_set, REGNO (SET_SRC (set))) == 1
+                 && rtx_equal_p (SET_DEST (set), mem))
+               SET_REGNO_REG_SET (&store_copies, REGNO (SET_SRC (set)));
+             
+             /* Replace the memory reference with the shadow register.  */
              ri.r = p;
              ri.i = i;
              for_each_rtx (&p, replace_loop_mem, &ri);
@@ -9874,7 +9619,13 @@ load_mems (loop)
                {
                  if (CONSTANT_P (equiv->loc))
                    const_equiv = equiv;
-                 else if (GET_CODE (equiv->loc) == REG)
+                 else if (GET_CODE (equiv->loc) == REG
+                          /* Extending hard register lifetimes cuases crash
+                             on SRC targets.  Doing so on non-SRC is
+                             probably also not good idea, since we most
+                             probably have pseudoregister equivalence as
+                             well.  */
+                          && REGNO (equiv->loc) >= FIRST_PSEUDO_REGISTER)
                    best_equiv = equiv;
                }
              /* Use the constant equivalence if that is cheap enough.  */
@@ -9916,7 +9667,7 @@ load_mems (loop)
 
              /* Store the memory immediately after END, which is
                 the NOTE_LOOP_END.  */
-             set = gen_move_insn (copy_rtx (mem), reg); 
+             set = gen_move_insn (copy_rtx (mem), reg);
              emit_insn_after (set, label);
            }
 
@@ -9932,11 +9683,18 @@ load_mems (loop)
             data flow, and enables {basic,general}_induction_var to find
             more bivs/givs.  */
          EXECUTE_IF_SET_IN_REG_SET
-           (&copies, FIRST_PSEUDO_REGISTER, j,
+           (&load_copies, FIRST_PSEUDO_REGISTER, j,
             {
-              try_copy_prop (loop, loop_mems[i].reg, j);
+              try_copy_prop (loop, reg, j);
             });
-         CLEAR_REG_SET (&copies);
+         CLEAR_REG_SET (&load_copies);
+
+         EXECUTE_IF_SET_IN_REG_SET
+           (&store_copies, FIRST_PSEUDO_REGISTER, j,
+            {
+              try_swap_copy_prop (loop, reg, j);
+            });
+         CLEAR_REG_SET (&store_copies);
        }
     }
 
@@ -9944,7 +9702,7 @@ load_mems (loop)
     {
       /* Now, we need to replace all references to the previous exit
         label with the new one.  */
-      rtx_pair rr; 
+      rtx_pair rr;
       rr.r1 = end_label;
       rr.r2 = label;
 
@@ -9980,7 +9738,7 @@ note_reg_stored (x, setter, arg)
      rtx x, setter ATTRIBUTE_UNUSED;
      void *arg;
 {
-  struct note_reg_stored_arg *t = (struct note_reg_stored_arg *)arg;
+  struct note_reg_stored_arg *t = (struct note_reg_stored_arg *) arg;
   if (t->reg == x)
     t->set_seen = 1;
 }
@@ -10015,7 +9773,7 @@ try_copy_prop (loop, replacement, regno)
       if (GET_CODE (insn) == CODE_LABEL && init_insn)
        break;
 
-      if (GET_RTX_CLASS (GET_CODE (insn)) != 'i')
+      if (! INSN_P (insn))
        continue;
 
       /* Is this the initializing insn?  */
@@ -10034,7 +9792,7 @@ try_copy_prop (loop, replacement, regno)
 
       /* Only substitute after seeing the initializing insn.  */
       if (init_insn && insn != init_insn)
-       {       
+       {
          struct note_reg_stored_arg arg;
          rtx array[3];
          array[0] = reg_rtx;
@@ -10072,6 +9830,95 @@ try_copy_prop (loop, replacement, regno)
     }
 }
 
+
+/* Try to replace occurrences of pseudo REGNO with REPLACEMENT within
+   loop LOOP if the order of the sets of these registers can be
+   swapped.  There must be exactly one insn within the loop that sets
+   this pseudo followed immediately by a move insn that sets
+   REPLACEMENT with REGNO.  */
+static void
+try_swap_copy_prop (loop, replacement, regno)
+     const struct loop *loop;
+     rtx replacement;
+     unsigned int regno;
+{
+  rtx insn;
+  rtx set;
+  unsigned int new_regno;
+
+  new_regno = REGNO (replacement);
+
+  for (insn = next_insn_in_loop (loop, loop->scan_start);
+       insn != NULL_RTX;
+       insn = next_insn_in_loop (loop, insn))
+    {
+      /* Search for the insn that copies REGNO to NEW_REGNO?  */
+      if (GET_RTX_CLASS (GET_CODE (insn)) == 'i'
+         && (set = single_set (insn))
+         && GET_CODE (SET_DEST (set)) == REG
+         && REGNO (SET_DEST (set)) == new_regno
+         && GET_CODE (SET_SRC (set)) == REG
+         && REGNO (SET_SRC (set)) == regno)
+       break;
+    }
+
+  if (insn != NULL_RTX)
+    {
+      rtx prev_insn;
+      rtx prev_set;
+      
+      /* Some DEF-USE info would come in handy here to make this
+        function more general.  For now, just check the previous insn
+        which is the most likely candidate for setting REGNO.  */
+      
+      prev_insn = PREV_INSN (insn);
+      
+      if (GET_RTX_CLASS (GET_CODE (insn)) == 'i'
+         && (prev_set = single_set (prev_insn))
+         && GET_CODE (SET_DEST (prev_set)) == REG
+         && REGNO (SET_DEST (prev_set)) == regno)
+       {
+         /* We have:
+            (set (reg regno) (expr))
+            (set (reg new_regno) (reg regno))
+            
+            so try converting this to:
+            (set (reg new_regno) (expr))
+            (set (reg regno) (reg new_regno))
+
+            The former construct is often generated when a global
+            variable used for an induction variable is shadowed by a
+            register (NEW_REGNO).  The latter construct improves the
+            chances of GIV replacement and BIV elimination.  */
+
+         validate_change (prev_insn, &SET_DEST (prev_set),
+                          replacement, 1);
+         validate_change (insn, &SET_DEST (set),
+                          SET_SRC (set), 1);
+         validate_change (insn, &SET_SRC (set),
+                          replacement, 1);
+
+         if (apply_change_group ())
+           {
+             if (loop_dump_stream)
+               fprintf (loop_dump_stream, 
+                        "  Swapped set of reg %d at %d with reg %d at %d.\n", 
+                        regno, INSN_UID (insn), 
+                        new_regno, INSN_UID (prev_insn));
+
+             /* Update first use of REGNO.  */
+             if (REGNO_FIRST_UID (regno) == INSN_UID (prev_insn))
+               REGNO_FIRST_UID (regno) = INSN_UID (insn);
+
+             /* Now perform copy propagation to hopefully
+                remove all uses of REGNO within the loop.  */
+             try_copy_prop (loop, replacement, regno);
+           }
+       }
+    }
+}
+
+
 /* Replace MEM with its associated pseudo register.  This function is
    called from load_mems via for_each_rtx.  DATA is actually an
    rtx_and_int * describing the instruction currently being scanned
@@ -10082,7 +9929,7 @@ replace_loop_mem (mem, data)
      rtx *mem;
      void *data;
 {
-  rtx_and_int *ri; 
+  rtx_and_int *ri;
   rtx insn;
   int i;
   rtx m = *mem;
@@ -10105,7 +9952,7 @@ replace_loop_mem (mem, data)
       return 0;
     }
 
-  ri = (rtx_and_int*) data;
+  ri = (rtx_and_int *) data;
   i = ri->i;
 
   if (!rtx_equal_p (loop_mems[i].mem, m))
@@ -10131,7 +9978,7 @@ replace_loop_reg (px, data)
      void *data;
 {
   rtx x = *px;
-  rtx *array = (rtx *)data;
+  rtx *array = (rtx *) data;
 
   if (x == NULL_RTX)
     return 0;
@@ -10152,8 +9999,8 @@ replace_label (x, data)
      void *data;
 {
   rtx l = *x;
-  rtx old_label = ((rtx_pair*) data)->r1;
-  rtx new_label = ((rtx_pair*) data)->r2;
+  rtx old_label = ((rtx_pair *) data)->r1;
+  rtx new_label = ((rtx_pair *) data)->r2;
 
   if (l == NULL_RTX)
     return 0;
@@ -10163,7 +10010,7 @@ replace_label (x, data)
 
   if (XEXP (l, 0) != old_label)
     return 0;
-  
+
   XEXP (l, 0) = new_label;
   ++LABEL_NUSES (new_label);
   --LABEL_NUSES (old_label);