OSDN Git Service

* tree-ssa-loop-ivopts.c: New file.
[pf3gnuchains/gcc-fork.git] / gcc / unroll.c
index 1047ebf..cef4c6e 100644 (file)
@@ -1,5 +1,6 @@
 /* Try to unroll loops, and split induction variables.
-   Copyright (C) 1992, 1993, 1994, 1995, 1997, 1998, 1999, 2000, 2001, 2002
+   Copyright (C) 1992, 1993, 1994, 1995, 1997, 1998, 1999, 2000, 2001,
+   2002, 2003, 2004
    Free Software Foundation, Inc.
    Contributed by James E. Wilson, Cygnus Support/UC Berkeley.
 
@@ -69,7 +70,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 
 /* ??? Improve control of which loops get unrolled.  Could use profiling
    info to only unroll the most commonly executed loops.  Perhaps have
-   a user specifyable option to control the amount of code expansion,
+   a user specifiable option to control the amount of code expansion,
    or the percent of loops to consider for unrolling.  Etc.  */
 
 /* ??? Look at the register copies inside the loop to see if they form a
@@ -133,6 +134,8 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 
 #include "config.h"
 #include "system.h"
+#include "coretypes.h"
+#include "tm.h"
 #include "rtl.h"
 #include "tm_p.h"
 #include "insn-config.h"
@@ -148,6 +151,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "basic-block.h"
 #include "predict.h"
 #include "params.h"
+#include "cfgloop.h"
 
 /* The prime factors looked for when trying to unroll a loop by some
    number which is modulo the total number of iterations.  Just checking
@@ -170,7 +174,7 @@ enum unroll_types
   UNROLL_NAIVE
 };
 
-/* Indexed by register number, if non-zero, then it contains a pointer
+/* Indexed by register number, if nonzero, then it contains a pointer
    to a struct induction for a DEST_REG giv which has been combined with
    one of more address givs.  This is needed because whenever such a DEST_REG
    giv is modified, we must modify the value of all split address givs
@@ -193,26 +197,24 @@ static int *splittable_regs_updates;
 
 /* Forward declarations.  */
 
-static void init_reg_map PARAMS ((struct inline_remap *, int));
-static rtx calculate_giv_inc PARAMS ((rtx, rtx, unsigned int));
-static rtx initial_reg_note_copy PARAMS ((rtx, struct inline_remap *));
-static void final_reg_note_copy PARAMS ((rtx *, struct inline_remap *));
-static void copy_loop_body PARAMS ((struct loop *, rtx, rtx,
-                                   struct inline_remap *, rtx, int,
-                                   enum unroll_types, rtx, rtx, rtx, rtx));
-static int find_splittable_regs PARAMS ((const struct loop *,
-                                        enum unroll_types, int));
-static int find_splittable_givs PARAMS ((const struct loop *,
-                                        struct iv_class *, enum unroll_types,
-                                        rtx, int));
-static int reg_dead_after_loop PARAMS ((const struct loop *, rtx));
-static rtx fold_rtx_mult_add PARAMS ((rtx, rtx, rtx, enum machine_mode));
-static int verify_addresses PARAMS ((struct induction *, rtx, int));
-static rtx remap_split_bivs PARAMS ((struct loop *, rtx));
-static rtx find_common_reg_term PARAMS ((rtx, rtx));
-static rtx subtract_reg_term PARAMS ((rtx, rtx));
-static rtx loop_find_equiv_value PARAMS ((const struct loop *, rtx));
-static rtx ujump_to_loop_cont PARAMS ((rtx, rtx));
+static rtx simplify_cmp_and_jump_insns (enum rtx_code, enum machine_mode,
+                                       rtx, rtx, rtx);
+static void init_reg_map (struct inline_remap *, int);
+static rtx calculate_giv_inc (rtx, rtx, unsigned int);
+static rtx initial_reg_note_copy (rtx, struct inline_remap *);
+static void final_reg_note_copy (rtx *, struct inline_remap *);
+static void copy_loop_body (struct loop *, rtx, rtx,
+                           struct inline_remap *, rtx, int,
+                           enum unroll_types, rtx, rtx, rtx, rtx);
+static int find_splittable_regs (const struct loop *, enum unroll_types,
+                                int);
+static int find_splittable_givs (const struct loop *, struct iv_class *,
+                                enum unroll_types, rtx, int);
+static int reg_dead_after_loop (const struct loop *, rtx);
+static rtx fold_rtx_mult_add (rtx, rtx, rtx, enum machine_mode);
+static rtx remap_split_bivs (struct loop *, rtx);
+static rtx find_common_reg_term (rtx, rtx);
+static rtx loop_find_equiv_value (const struct loop *, rtx);
 
 /* Try to unroll one loop and split induction variables in the loop.
 
@@ -224,10 +226,7 @@ static rtx ujump_to_loop_cont PARAMS ((rtx, rtx));
    in loop.c.  */
 
 void
-unroll_loop (loop, insn_count, strength_reduce_p)
-     struct loop *loop;
-     int insn_count;
-     int strength_reduce_p;
+unroll_loop (struct loop *loop, int insn_count, int strength_reduce_p)
 {
   struct loop_info *loop_info = LOOP_INFO (loop);
   struct loop_ivs *ivs = LOOP_IVS (loop);
@@ -268,53 +267,6 @@ unroll_loop (loop, insn_count, strength_reduce_p)
       return;
     }
 
-  /* When emitting debugger info, we can't unroll loops with unequal numbers
-     of block_beg and block_end notes, because that would unbalance the block
-     structure of the function.  This can happen as a result of the
-     "if (foo) bar; else break;" optimization in jump.c.  */
-  /* ??? Gcc has a general policy that -g is never supposed to change the code
-     that the compiler emits, so we must disable this optimization always,
-     even if debug info is not being output.  This is rare, so this should
-     not be a significant performance problem.  */
-
-  if (1 /* write_symbols != NO_DEBUG */)
-    {
-      int block_begins = 0;
-      int block_ends = 0;
-
-      for (insn = loop_start; insn != loop_end; insn = NEXT_INSN (insn))
-       {
-         if (GET_CODE (insn) == NOTE)
-           {
-             if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_BEG)
-               block_begins++;
-             else if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_END)
-               block_ends++;
-             if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_REGION_BEG
-                 || NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_REGION_END)
-               {
-                 /* Note, would be nice to add code to unroll EH
-                    regions, but until that time, we punt (don't
-                    unroll).  For the proper way of doing it, see
-                    expand_inline_function.  */
-
-                 if (loop_dump_stream)
-                   fprintf (loop_dump_stream,
-                            "Unrolling failure: cannot unroll EH regions.\n");
-                 return;
-               }
-           }
-       }
-
-      if (block_begins != block_ends)
-       {
-         if (loop_dump_stream)
-           fprintf (loop_dump_stream,
-                    "Unrolling failure: Unbalanced block notes.\n");
-         return;
-       }
-    }
-
   /* Determine type of unroll to perform.  Depends on the number of iterations
      and the size of the loop.  */
 
@@ -327,12 +279,8 @@ unroll_loop (loop, insn_count, strength_reduce_p)
     loop_info->n_iterations = 0;
 
   if (loop_dump_stream && loop_info->n_iterations > 0)
-    {
-      fputs ("Loop unrolling: ", loop_dump_stream);
-      fprintf (loop_dump_stream, HOST_WIDE_INT_PRINT_DEC,
-              loop_info->n_iterations);
-      fputs (" iterations.\n", loop_dump_stream);
-    }
+    fprintf (loop_dump_stream, "Loop unrolling: " HOST_WIDE_INT_PRINT_DEC
+            " iterations.\n", loop_info->n_iterations);
 
   /* Find and save a pointer to the last nonnote insn in the loop.  */
 
@@ -347,52 +295,20 @@ unroll_loop (loop, insn_count, strength_reduce_p)
         jump to the loop condition.  Make sure to delete the jump
         insn, otherwise the loop body will never execute.  */
 
-      rtx ujump = ujump_to_loop_cont (loop->start, loop->cont);
-      if (ujump)
-       delete_related_insns (ujump);
-
-      /* If number of iterations is exactly 1, then eliminate the compare and
-        branch at the end of the loop since they will never be taken.
-        Then return, since no other action is needed here.  */
-
       /* If the last instruction is not a BARRIER or a JUMP_INSN, then
         don't do anything.  */
 
-      if (GET_CODE (last_loop_insn) == BARRIER)
+      if (BARRIER_P (last_loop_insn))
        {
          /* Delete the jump insn.  This will delete the barrier also.  */
-         delete_related_insns (PREV_INSN (last_loop_insn));
-       }
-      else if (GET_CODE (last_loop_insn) == JUMP_INSN)
-       {
-#ifdef HAVE_cc0
-         rtx prev = PREV_INSN (last_loop_insn);
-#endif
-         delete_related_insns (last_loop_insn);
-#ifdef HAVE_cc0
-         /* The immediately preceding insn may be a compare which must be
-            deleted.  */
-         if (only_sets_cc0_p (prev))
-           delete_related_insns (prev);
-#endif
+         last_loop_insn = PREV_INSN (last_loop_insn);
        }
-
-      /* Remove the loop notes since this is no longer a loop.  */
-      if (loop->vtop)
-       delete_related_insns (loop->vtop);
-      if (loop->cont)
-       delete_related_insns (loop->cont);
-      if (loop_start)
-       delete_related_insns (loop_start);
-      if (loop_end)
-       delete_related_insns (loop_end);
-
-      return;
     }
-  else if (loop_info->n_iterations > 0
-          /* Avoid overflow in the next expression.  */
-          && loop_info->n_iterations < MAX_UNROLLED_INSNS
-          && loop_info->n_iterations * insn_count < MAX_UNROLLED_INSNS)
+
+  if (loop_info->n_iterations > 0
+      /* Avoid overflow in the next expression.  */
+      && loop_info->n_iterations < (unsigned) MAX_UNROLLED_INSNS
+      && loop_info->n_iterations * insn_count < (unsigned) MAX_UNROLLED_INSNS)
     {
       unroll_number = loop_info->n_iterations;
       unroll_type = UNROLL_COMPLETELY;
@@ -422,7 +338,7 @@ unroll_loop (loop, insn_count, strength_reduce_p)
       for (i = 3; i >= 0; i--)
        while (factors[i].count--)
          {
-           if (temp * factors[i].factor < MAX_UNROLLED_INSNS)
+           if (temp * factors[i].factor < (unsigned) MAX_UNROLLED_INSNS)
              {
                unroll_number *= factors[i].factor;
                temp *= factors[i].factor;
@@ -485,9 +401,9 @@ unroll_loop (loop, insn_count, strength_reduce_p)
         Just return without unrolling the loop in such cases.  */
 
       insn = loop_start;
-      while (GET_CODE (insn) != CODE_LABEL && GET_CODE (insn) != JUMP_INSN)
+      while (!LABEL_P (insn) && !JUMP_P (insn))
        insn = NEXT_INSN (insn);
-      if (GET_CODE (insn) == JUMP_INSN)
+      if (JUMP_P (insn))
        return;
     }
 
@@ -508,9 +424,9 @@ unroll_loop (loop, insn_count, strength_reduce_p)
       insert_before = NEXT_INSN (last_loop_insn);
 
       /* Set copy_end to the insn before the jump at the end of the loop.  */
-      if (GET_CODE (last_loop_insn) == BARRIER)
+      if (BARRIER_P (last_loop_insn))
        copy_end = PREV_INSN (PREV_INSN (last_loop_insn));
-      else if (GET_CODE (last_loop_insn) == JUMP_INSN)
+      else if (JUMP_P (last_loop_insn))
        {
          copy_end = PREV_INSN (last_loop_insn);
 #ifdef HAVE_cc0
@@ -544,12 +460,12 @@ unroll_loop (loop, insn_count, strength_reduce_p)
 
       /* Set insert_before to the jump insn at the end of the loop.
         Set copy_end to before the jump insn at the end of the loop.  */
-      if (GET_CODE (last_loop_insn) == BARRIER)
+      if (BARRIER_P (last_loop_insn))
        {
          insert_before = PREV_INSN (last_loop_insn);
          copy_end = PREV_INSN (insert_before);
        }
-      else if (GET_CODE (last_loop_insn) == JUMP_INSN)
+      else if (JUMP_P (last_loop_insn))
        {
          insert_before = last_loop_insn;
 #ifdef HAVE_cc0
@@ -577,7 +493,7 @@ unroll_loop (loop, insn_count, strength_reduce_p)
       /* Normal case: Must copy the compare and branch instructions at the
         end of the loop.  */
 
-      if (GET_CODE (last_loop_insn) == BARRIER)
+      if (BARRIER_P (last_loop_insn))
        {
          /* Loop ends with an unconditional jump and a barrier.
             Handle this like above, don't copy jump and barrier.
@@ -590,7 +506,7 @@ unroll_loop (loop, insn_count, strength_reduce_p)
          insert_before = PREV_INSN (last_loop_insn);
          copy_end = PREV_INSN (insert_before);
        }
-      else if (GET_CODE (last_loop_insn) == JUMP_INSN)
+      else if (JUMP_P (last_loop_insn))
        {
          /* Set insert_before to immediately after the JUMP_INSN, so that
             NOTEs at the end of the loop will be correctly handled by
@@ -620,10 +536,10 @@ unroll_loop (loop, insn_count, strength_reduce_p)
       exit_label = gen_label_rtx ();
 
       insn = loop_start;
-      while (GET_CODE (insn) != CODE_LABEL && GET_CODE (insn) != JUMP_INSN)
+      while (!LABEL_P (insn) && !JUMP_P (insn))
        insn = NEXT_INSN (insn);
 
-      if (GET_CODE (insn) == JUMP_INSN)
+      if (JUMP_P (insn))
        {
          /* The loop starts with a jump down to the exit condition test.
             Start copying the loop after the barrier following this
@@ -647,9 +563,9 @@ unroll_loop (loop, insn_count, strength_reduce_p)
   /* This should always be the first label in the loop.  */
   start_label = NEXT_INSN (copy_start);
   /* There may be a line number note and/or a loop continue note here.  */
-  while (GET_CODE (start_label) == NOTE)
+  while (NOTE_P (start_label))
     start_label = NEXT_INSN (start_label);
-  if (GET_CODE (start_label) != CODE_LABEL)
+  if (!LABEL_P (start_label))
     {
       /* This can happen as a result of jump threading.  If the first insns in
         the loop test the same condition as the loop's backward jump, or the
@@ -677,8 +593,8 @@ unroll_loop (loop, insn_count, strength_reduce_p)
     }
 
   if (unroll_type == UNROLL_NAIVE
-      && GET_CODE (last_loop_insn) == BARRIER
-      && GET_CODE (PREV_INSN (last_loop_insn)) == JUMP_INSN
+      && BARRIER_P (last_loop_insn)
+      && JUMP_P (PREV_INSN (last_loop_insn))
       && start_label != JUMP_LABEL (PREV_INSN (last_loop_insn)))
     {
       /* In this case, we must copy the jump and barrier, because they will
@@ -689,7 +605,7 @@ unroll_loop (loop, insn_count, strength_reduce_p)
     }
 
   if (unroll_type == UNROLL_NAIVE
-      && GET_CODE (last_loop_insn) == JUMP_INSN
+      && JUMP_P (last_loop_insn)
       && start_label != JUMP_LABEL (last_loop_insn))
     {
       /* ??? The loop ends with a conditional branch that does not branch back
@@ -715,14 +631,14 @@ unroll_loop (loop, insn_count, strength_reduce_p)
      without initializing fields within the map structure.
 
      To be safe, we use xcalloc to zero the memory.  */
-  map = (struct inline_remap *) xcalloc (1, sizeof (struct inline_remap));
+  map = xcalloc (1, sizeof (struct inline_remap));
 
   /* Allocate the label map.  */
 
   if (max_labelno > 0)
     {
-      map->label_map = (rtx *) xcalloc (max_labelno, sizeof (rtx));
-      local_label = (char *) xcalloc (max_labelno, sizeof (char));
+      map->label_map = xcalloc (max_labelno, sizeof (rtx));
+      local_label = xcalloc (max_labelno, sizeof (char));
     }
 
   /* Search the loop and mark all local labels, i.e. the ones which have to
@@ -736,9 +652,9 @@ unroll_loop (loop, insn_count, strength_reduce_p)
     {
       rtx note;
 
-      if (GET_CODE (insn) == CODE_LABEL)
+      if (LABEL_P (insn))
        local_label[CODE_LABEL_NUMBER (insn)] = 1;
-      else if (GET_CODE (insn) == JUMP_INSN)
+      else if (JUMP_P (insn))
        {
          if (JUMP_LABEL (insn))
            set_label_in_map (map,
@@ -766,11 +682,7 @@ unroll_loop (loop, insn_count, strength_reduce_p)
 
   /* Allocate space for the insn map.  */
 
-  map->insn_map = (rtx *) xmalloc (max_insnno * sizeof (rtx));
-
-  /* Set this to zero, to indicate that we are doing loop unrolling,
-     not function inlining.  */
-  map->inline_target = 0;
+  map->insn_map = xmalloc (max_insnno * sizeof (rtx));
 
   /* The register and constant maps depend on the number of registers
      present, so the final maps can't be created until after
@@ -792,11 +704,10 @@ unroll_loop (loop, insn_count, strength_reduce_p)
      preconditioning code and find_splittable_regs will never be used
      to access the splittable_regs[] and addr_combined_regs[] arrays.  */
 
-  splittable_regs = (rtx *) xcalloc (maxregnum, sizeof (rtx));
-  splittable_regs_updates = (int *) xcalloc (maxregnum, sizeof (int));
-  addr_combined_regs
-    = (struct induction **) xcalloc (maxregnum, sizeof (struct induction *));
-  local_regno = (char *) xcalloc (maxregnum, sizeof (char));
+  splittable_regs = xcalloc (maxregnum, sizeof (rtx));
+  splittable_regs_updates = xcalloc (maxregnum, sizeof (int));
+  addr_combined_regs = xcalloc (maxregnum, sizeof (struct induction *));
+  local_regno = xcalloc (maxregnum, sizeof (char));
 
   /* Mark all local registers, i.e. the ones which are referenced only
      inside the loop.  */
@@ -807,13 +718,13 @@ unroll_loop (loop, insn_count, strength_reduce_p)
 
       /* If a register is used in the jump insn, we must not duplicate it
         since it will also be used outside the loop.  */
-      if (GET_CODE (copy_end) == JUMP_INSN)
+      if (JUMP_P (copy_end))
        copy_end_luid--;
 
       /* If we have a target that uses cc0, then we also must not duplicate
         the insn that sets cc0 before the jump insn, if one is present.  */
 #ifdef HAVE_cc0
-      if (GET_CODE (copy_end) == JUMP_INSN
+      if (JUMP_P (copy_end)
          && sets_cc0_p (PREV_INSN (copy_end)))
        copy_end_luid--;
 #endif
@@ -831,9 +742,9 @@ unroll_loop (loop, insn_count, strength_reduce_p)
       /* We must limit the generic test to max_reg_before_loop, because only
         these pseudo registers have valid regno_first_uid info.  */
       for (r = FIRST_PSEUDO_REGISTER; r < max_reg_before_loop; ++r)
-       if (REGNO_FIRST_UID (r) > 0 && REGNO_FIRST_UID (r) <= max_uid_for_loop
+       if (REGNO_FIRST_UID (r) > 0 && REGNO_FIRST_UID (r) < max_uid_for_loop
            && REGNO_FIRST_LUID (r) >= copy_start_luid
-           && REGNO_LAST_UID (r) > 0 && REGNO_LAST_UID (r) <= max_uid_for_loop
+           && REGNO_LAST_UID (r) > 0 && REGNO_LAST_UID (r) < max_uid_for_loop
            && REGNO_LAST_LUID (r) <= copy_end_luid)
          {
            /* However, we must also check for loop-carried dependencies.
@@ -891,14 +802,14 @@ unroll_loop (loop, insn_count, strength_reduce_p)
                               &initial_value, &final_value, &increment,
                               &mode))
        {
-         rtx diff;
+         rtx diff, insn;
          rtx *labels;
          int abs_inc, neg_inc;
          enum rtx_code cc = loop_info->comparison_code;
          int less_p     = (cc == LE  || cc == LEU || cc == LT  || cc == LTU);
          int unsigned_p = (cc == LEU || cc == GEU || cc == LTU || cc == GTU);
 
-         map->reg_map = (rtx *) xmalloc (maxregnum * sizeof (rtx));
+         map->reg_map = xmalloc (maxregnum * sizeof (rtx));
 
          VARRAY_CONST_EQUIV_INIT (map->const_equiv_varray, maxregnum,
                                   "unroll_loop_precondition");
@@ -923,26 +834,20 @@ unroll_loop (loop, insn_count, strength_reduce_p)
 
          start_sequence ();
 
+         /* We must copy the final and initial values here to avoid
+            improperly shared rtl.  */
+         final_value = copy_rtx (final_value);
+         initial_value = copy_rtx (initial_value);
+
          /* Final value may have form of (PLUS val1 const1_rtx).  We need
             to convert it into general operand, so compute the real value.  */
 
-         if (GET_CODE (final_value) == PLUS)
-           {
-             final_value = expand_simple_binop (mode, PLUS,
-                                                copy_rtx (XEXP (final_value, 0)),
-                                                copy_rtx (XEXP (final_value, 1)),
-                                                NULL_RTX, 0, OPTAB_LIB_WIDEN);
-           }
+         final_value = force_operand (final_value, NULL_RTX);
          if (!nonmemory_operand (final_value, VOIDmode))
-           final_value = force_reg (mode, copy_rtx (final_value));
+           final_value = force_reg (mode, final_value);
 
          /* Calculate the difference between the final and initial values.
             Final value may be a (plus (reg x) (const_int 1)) rtx.
-            Let the following cse pass simplify this if initial value is
-            a constant.
-
-            We must copy the final and initial values here to avoid
-            improperly shared rtl.
 
             We have to deal with for (i = 0; --i < 6;) type loops.
             For such loops the real final value is the first time the
@@ -955,23 +860,23 @@ unroll_loop (loop, insn_count, strength_reduce_p)
             so we can pretend that the overflow value is 0/~0.  */
 
          if (cc == NE || less_p != neg_inc)
-           diff = expand_simple_binop (mode, MINUS, final_value,
-                                       copy_rtx (initial_value), NULL_RTX, 0,
-                                       OPTAB_LIB_WIDEN);
+           diff = simplify_gen_binary (MINUS, mode, final_value,
+                                       initial_value);
          else
-           diff = expand_simple_unop (mode, neg_inc ? NOT : NEG,
-                                      copy_rtx (initial_value), NULL_RTX, 0);
+           diff = simplify_gen_unary (neg_inc ? NOT : NEG, mode,
+                                      initial_value, mode);
+         diff = force_operand (diff, NULL_RTX);
 
          /* Now calculate (diff % (unroll * abs (increment))) by using an
             and instruction.  */
-         diff = expand_simple_binop (GET_MODE (diff), AND, diff,
-                                     GEN_INT (unroll_number * abs_inc - 1),
-                                     NULL_RTX, 0, OPTAB_LIB_WIDEN);
+         diff = simplify_gen_binary (AND, mode, diff,
+                                     GEN_INT (unroll_number*abs_inc - 1));
+         diff = force_operand (diff, NULL_RTX);
 
          /* Now emit a sequence of branches to jump to the proper precond
             loop entry point.  */
 
-         labels = (rtx *) xmalloc (sizeof (rtx) * unroll_number);
+         labels = xmalloc (sizeof (rtx) * unroll_number);
          for (i = 0; i < unroll_number; i++)
            labels[i] = gen_label_rtx ();
 
@@ -984,18 +889,22 @@ unroll_loop (loop, insn_count, strength_reduce_p)
          if (cc != NE)
            {
              rtx incremented_initval;
-             incremented_initval = expand_simple_binop (mode, PLUS,
-                                                        initial_value,
-                                                        increment,
-                                                        NULL_RTX, 0,
-                                                        OPTAB_LIB_WIDEN);
-             emit_cmp_and_jump_insns (incremented_initval, final_value,
-                                      less_p ? GE : LE, NULL_RTX,
-                                      mode, unsigned_p, labels[1]);
-             predict_insn_def (get_last_insn (), PRED_LOOP_CONDITION,
-                               TAKEN);
-             JUMP_LABEL (get_last_insn ()) = labels[1];
-             LABEL_NUSES (labels[1])++;
+             enum rtx_code cmp_code;
+
+             incremented_initval
+               = simplify_gen_binary (PLUS, mode, initial_value, increment);
+             incremented_initval
+               = force_operand (incremented_initval, NULL_RTX);
+
+             cmp_code = (less_p
+                         ? (unsigned_p ? GEU : GE)
+                         : (unsigned_p ? LEU : LE));
+
+             insn = simplify_cmp_and_jump_insns (cmp_code, mode,
+                                                 incremented_initval,
+                                                 final_value, labels[1]);
+             if (insn)
+               predict_insn_def (insn, PRED_LOOP_CONDITION, TAKEN);
            }
 
          /* Assuming the unroll_number is 4, and the increment is 2, then
@@ -1034,12 +943,12 @@ unroll_loop (loop, insn_count, strength_reduce_p)
                  cmp_code = LE;
                }
 
-             emit_cmp_and_jump_insns (diff, GEN_INT (abs_inc * cmp_const),
-                                      cmp_code, NULL_RTX, mode, 0, labels[i]);
-             JUMP_LABEL (get_last_insn ()) = labels[i];
-             LABEL_NUSES (labels[i])++;
-             predict_insn (get_last_insn (), PRED_LOOP_PRECONDITIONING,
-                           REG_BR_PROB_BASE / (unroll_number - i));
+             insn = simplify_cmp_and_jump_insns (cmp_code, mode, diff,
+                                                 GEN_INT (abs_inc*cmp_const),
+                                                 labels[i]);
+             if (insn)
+               predict_insn (insn, PRED_LOOP_PRECONDITIONING,
+                             REG_BR_PROB_BASE / (unroll_number - i));
            }
 
          /* If the increment is greater than one, then we need another branch,
@@ -1067,13 +976,11 @@ unroll_loop (loop, insn_count, strength_reduce_p)
                  cmp_code = GE;
                }
 
-             emit_cmp_and_jump_insns (diff, GEN_INT (cmp_const), cmp_code,
-                                      NULL_RTX, mode, 0, labels[0]);
-             JUMP_LABEL (get_last_insn ()) = labels[0];
-             LABEL_NUSES (labels[0])++;
+             simplify_cmp_and_jump_insns (cmp_code, mode, diff,
+                                          GEN_INT (cmp_const), labels[0]);
            }
 
-         sequence = gen_sequence ();
+         sequence = get_insns ();
          end_sequence ();
          loop_insn_hoist (loop, sequence);
 
@@ -1082,9 +989,9 @@ unroll_loop (loop, insn_count, strength_reduce_p)
             and then reset it inside the loop when get to the last
             copy.  */
 
-         if (GET_CODE (last_loop_insn) == BARRIER)
+         if (BARRIER_P (last_loop_insn))
            copy_end = PREV_INSN (PREV_INSN (last_loop_insn));
-         else if (GET_CODE (last_loop_insn) == JUMP_INSN)
+         else if (JUMP_P (last_loop_insn))
            {
              copy_end = PREV_INSN (last_loop_insn);
 #ifdef HAVE_cc0
@@ -1102,8 +1009,8 @@ unroll_loop (loop, insn_count, strength_reduce_p)
              emit_label_after (labels[unroll_number - i],
                                PREV_INSN (loop_start));
 
-             memset ((char *) map->insn_map, 0, max_insnno * sizeof (rtx));
-             memset ((char *) &VARRAY_CONST_EQUIV (map->const_equiv_varray, 0),
+             memset (map->insn_map, 0, max_insnno * sizeof (rtx));
+             memset (&VARRAY_CONST_EQUIV (map->const_equiv_varray, 0),
                      0, (VARRAY_SIZE (map->const_equiv_varray)
                          * sizeof (struct const_equiv_data)));
              map->const_age = 0;
@@ -1126,7 +1033,7 @@ unroll_loop (loop, insn_count, strength_reduce_p)
 
              if (i == unroll_number - 1)
                {
-                 if (GET_CODE (last_loop_insn) == BARRIER)
+                 if (BARRIER_P (last_loop_insn))
                    copy_end = PREV_INSN (PREV_INSN (last_loop_insn));
                  else
                    copy_end = last_loop_insn;
@@ -1140,7 +1047,7 @@ unroll_loop (loop, insn_count, strength_reduce_p)
            }
          emit_label_after (labels[0], PREV_INSN (loop_start));
 
-         if (GET_CODE (last_loop_insn) == BARRIER)
+         if (BARRIER_P (last_loop_insn))
            {
              insert_before = PREV_INSN (last_loop_insn);
              copy_end = PREV_INSN (insert_before);
@@ -1169,7 +1076,7 @@ unroll_loop (loop, insn_count, strength_reduce_p)
 
   /* If reach here, and the loop type is UNROLL_NAIVE, then don't unroll
      the loop unless all loops are being unrolled.  */
-  if (unroll_type == UNROLL_NAIVE && ! flag_unroll_all_loops)
+  if (unroll_type == UNROLL_NAIVE && ! flag_old_unroll_all_loops)
     {
       if (loop_dump_stream)
        fprintf (loop_dump_stream,
@@ -1182,6 +1089,12 @@ unroll_loop (loop, insn_count, strength_reduce_p)
   /* Keep track of the unroll factor for the loop.  */
   loop_info->unroll_number = unroll_number;
 
+  /* And whether the loop has been preconditioned.  */
+  loop_info->preconditioned = loop_preconditioned;
+
+  /* Remember whether it was preconditioned for the second loop pass.  */
+  NOTE_PRECONDITIONED (loop->end) = loop_preconditioned;
+
   /* For each biv and giv, determine whether it can be safely split into
      a different variable for each unrolled copy of the loop body.
      We precalculate and save this info here, since computing it is
@@ -1200,7 +1113,7 @@ unroll_loop (loop, insn_count, strength_reduce_p)
      the constant maps also.  */
 
   maxregnum = max_reg_num ();
-  map->reg_map = (rtx *) xmalloc (maxregnum * sizeof (rtx));
+  map->reg_map = xmalloc (maxregnum * sizeof (rtx));
 
   init_reg_map (map, maxregnum);
 
@@ -1238,7 +1151,7 @@ unroll_loop (loop, insn_count, strength_reduce_p)
   if (unroll_type == UNROLL_MODULO)
     {
       insn = NEXT_INSN (copy_end);
-      if (GET_CODE (insn) == INSN || GET_CODE (insn) == JUMP_INSN)
+      if (NONJUMP_INSN_P (insn) || JUMP_P (insn))
        PATTERN (insn) = remap_split_bivs (loop, PATTERN (insn));
     }
 
@@ -1248,8 +1161,8 @@ unroll_loop (loop, insn_count, strength_reduce_p)
 
   for (i = 0; i < unroll_number; i++)
     {
-      memset ((char *) map->insn_map, 0, max_insnno * sizeof (rtx));
-      memset ((char *) &VARRAY_CONST_EQUIV (map->const_equiv_varray, 0), 0,
+      memset (map->insn_map, 0, max_insnno * sizeof (rtx));
+      memset (&VARRAY_CONST_EQUIV (map->const_equiv_varray, 0), 0,
              VARRAY_SIZE (map->const_equiv_varray) * sizeof (struct const_equiv_data));
       map->const_age = 0;
 
@@ -1317,8 +1230,8 @@ unroll_loop (loop, insn_count, strength_reduce_p)
         associated LABEL_DECL to point to one of the new label instances.  */
       /* ??? Likewise, we can't delete a NOTE_INSN_DELETED_LABEL note.  */
       if (insn != start_label
-         && ! (GET_CODE (insn) == CODE_LABEL && LABEL_NAME (insn))
-         && ! (GET_CODE (insn) == NOTE
+         && ! (LABEL_P (insn) && LABEL_NAME (insn))
+         && ! (NOTE_P (insn)
                && NOTE_LINE_NUMBER (insn) == NOTE_INSN_DELETED_LABEL))
        insn = delete_related_insns (insn);
       else
@@ -1343,10 +1256,6 @@ unroll_loop (loop, insn_count, strength_reduce_p)
   if (unroll_type == UNROLL_COMPLETELY)
     {
       /* Remove the loop notes since this is no longer a loop.  */
-      if (loop->vtop)
-       delete_related_insns (loop->vtop);
-      if (loop->cont)
-       delete_related_insns (loop->cont);
       if (loop_start)
        delete_related_insns (loop_start);
       if (loop_end)
@@ -1369,6 +1278,41 @@ unroll_loop (loop, insn_count, strength_reduce_p)
     free (map->reg_map);
   free (map);
 }
+
+/* A helper function for unroll_loop.  Emit a compare and branch to
+   satisfy (CMP OP1 OP2), but pass this through the simplifier first.
+   If the branch turned out to be conditional, return it, otherwise
+   return NULL.  */
+
+static rtx
+simplify_cmp_and_jump_insns (enum rtx_code code, enum machine_mode mode,
+                            rtx op0, rtx op1, rtx label)
+{
+  rtx t, insn;
+
+  t = simplify_const_relational_operation (code, mode, op0, op1);
+  if (!t)
+    {
+      enum rtx_code scode = signed_condition (code);
+      emit_cmp_and_jump_insns (op0, op1, scode, NULL_RTX, mode,
+                              code != scode, label);
+      insn = get_last_insn ();
+
+      JUMP_LABEL (insn) = label;
+      LABEL_NUSES (label) += 1;
+
+      return insn;
+    }
+  else if (t == const_true_rtx)
+    {
+      insn = emit_jump_insn (gen_jump (label));
+      emit_barrier ();
+      JUMP_LABEL (insn) = label;
+      LABEL_NUSES (label) += 1;
+    }
+
+  return NULL_RTX;
+}
 \f
 /* Return true if the loop can be safely, and profitably, preconditioned
    so that the unrolled copies of the loop body don't need exit tests.
@@ -1388,10 +1332,9 @@ unroll_loop (loop, insn_count, strength_reduce_p)
    reflected in RTX_COST.  */
 
 int
-precondition_loop_p (loop, initial_value, final_value, increment, mode)
-     const struct loop *loop;
-     rtx *initial_value, *final_value, *increment;
-     enum machine_mode *mode;
+precondition_loop_p (const struct loop *loop, rtx *initial_value,
+                    rtx *final_value, rtx *increment,
+                    enum machine_mode *mode)
 {
   rtx loop_start = loop->start;
   struct loop_info *loop_info = LOOP_INFO (loop);
@@ -1413,13 +1356,10 @@ precondition_loop_p (loop, initial_value, final_value, increment, mode)
       *mode = word_mode;
 
       if (loop_dump_stream)
-       {
-         fputs ("Preconditioning: Success, number of iterations known, ",
-                loop_dump_stream);
-         fprintf (loop_dump_stream, HOST_WIDE_INT_PRINT_DEC,
-                  loop_info->n_iterations);
-         fputs (".\n", loop_dump_stream);
-       }
+       fprintf (loop_dump_stream,
+                "Preconditioning: Success, number of iterations known, "
+                HOST_WIDE_INT_PRINT_DEC ".\n",
+                loop_info->n_iterations);
       return 1;
     }
 
@@ -1476,7 +1416,7 @@ precondition_loop_p (loop, initial_value, final_value, increment, mode)
      against max_reg_before_loop to make sure that the register is in
      the range covered by loop_invariant_p.  If it isn't, then it is
      most likely a biv/giv which by definition are not invariant.  */
-  if ((GET_CODE (loop_info->final_value) == REG
+  if ((REG_P (loop_info->final_value)
        && REGNO (loop_info->final_value) >= max_reg_before_loop)
       || (GET_CODE (loop_info->final_value) == PLUS
          && REGNO (XEXP (loop_info->final_value, 0)) >= max_reg_before_loop)
@@ -1551,9 +1491,7 @@ precondition_loop_p (loop, initial_value, final_value, increment, mode)
    modes.  */
 
 static void
-init_reg_map (map, maxregnum)
-     struct inline_remap *map;
-     int maxregnum;
+init_reg_map (struct inline_remap *map, int maxregnum)
 {
   int i;
 
@@ -1578,9 +1516,7 @@ init_reg_map (map, maxregnum)
    The return value is the amount that the giv is incremented by.  */
 
 static rtx
-calculate_giv_inc (pattern, src_insn, regno)
-     rtx pattern, src_insn;
-     unsigned int regno;
+calculate_giv_inc (rtx pattern, rtx src_insn, unsigned int regno)
 {
   rtx increment;
   rtx increment_total = 0;
@@ -1619,7 +1555,7 @@ calculate_giv_inc (pattern, src_insn, regno)
 
       /* Some ports store large constants in memory and add a REG_EQUAL
         note to the store insn.  */
-      else if (GET_CODE (increment) == MEM)
+      else if (MEM_P (increment))
        {
          rtx note = find_reg_note (src_insn, REG_EQUAL, 0);
          if (note)
@@ -1627,15 +1563,17 @@ calculate_giv_inc (pattern, src_insn, regno)
        }
 
       else if (GET_CODE (increment) == IOR
+              || GET_CODE (increment) == PLUS
               || GET_CODE (increment) == ASHIFT
-              || GET_CODE (increment) == PLUS)
+              || GET_CODE (increment) == LSHIFTRT)
        {
          /* The rs6000 port loads some constants with IOR.
-            The alpha port loads some constants with ASHIFT and PLUS.  */
+            The alpha port loads some constants with ASHIFT and PLUS.
+            The sparc64 port loads some constants with LSHIFTRT.  */
          rtx second_part = XEXP (increment, 1);
          enum rtx_code code = GET_CODE (increment);
 
-         increment = find_last_value (XEXP (increment, 0), 
+         increment = find_last_value (XEXP (increment, 0),
                                       &src_insn, NULL_RTX, 0);
          /* Don't need the last insn anymore.  */
          delete_related_insns (get_last_insn ());
@@ -1648,8 +1586,10 @@ calculate_giv_inc (pattern, src_insn, regno)
            increment = GEN_INT (INTVAL (increment) | INTVAL (second_part));
          else if (code == PLUS)
            increment = GEN_INT (INTVAL (increment) + INTVAL (second_part));
-         else
+         else if (code == ASHIFT)
            increment = GEN_INT (INTVAL (increment) << INTVAL (second_part));
+         else
+           increment = GEN_INT ((unsigned HOST_WIDE_INT) INTVAL (increment) >> INTVAL (second_part));
        }
 
       if (GET_CODE (increment) != CONST_INT)
@@ -1667,7 +1607,7 @@ calculate_giv_inc (pattern, src_insn, regno)
 
   /* Check that the source register is the same as the register we expected
      to see as the source.  If not, something is seriously wrong.  */
-  if (GET_CODE (XEXP (SET_SRC (pattern), 0)) != REG
+  if (!REG_P (XEXP (SET_SRC (pattern), 0))
       || REGNO (XEXP (SET_SRC (pattern), 0)) != regno)
     {
       /* Some machines (e.g. the romp), may emit two add instructions for
@@ -1697,9 +1637,7 @@ calculate_giv_inc (pattern, src_insn, regno)
    the reg_map entries can change during copying.  */
 
 static rtx
-initial_reg_note_copy (notes, map)
-     rtx notes;
-     struct inline_remap *map;
+initial_reg_note_copy (rtx notes, struct inline_remap *map)
 {
   rtx copy;
 
@@ -1725,39 +1663,26 @@ initial_reg_note_copy (notes, map)
 /* Fixup insn references in copied REG_NOTES.  */
 
 static void
-final_reg_note_copy (notesp, map)
-     rtx *notesp;
-     struct inline_remap *map;
+final_reg_note_copy (rtx *notesp, struct inline_remap *map)
 {
   while (*notesp)
     {
       rtx note = *notesp;
-      
+
       if (GET_CODE (note) == INSN_LIST)
        {
-         /* Sometimes, we have a REG_WAS_0 note that points to a
-            deleted instruction.  In that case, we can just delete the
-            note.  */
-         if (REG_NOTE_KIND (note) == REG_WAS_0)
+         rtx insn = map->insn_map[INSN_UID (XEXP (note, 0))];
+
+         /* If we failed to remap the note, something is awry.
+            Allow REG_LABEL as it may reference label outside
+            the unrolled loop.  */
+         if (!insn)
            {
-             *notesp = XEXP (note, 1);
-             continue;
+             if (REG_NOTE_KIND (note) != REG_LABEL)
+               abort ();
            }
          else
-           {
-             rtx insn = map->insn_map[INSN_UID (XEXP (note, 0))];
-
-             /* If we failed to remap the note, something is awry.
-                Allow REG_LABEL as it may reference label outside
-                the unrolled loop.  */
-             if (!insn)
-               {
-                 if (REG_NOTE_KIND (note) != REG_LABEL)
-                   abort ();
-               }
-             else
-               XEXP (note, 0) = insn;
-           }
+           XEXP (note, 0) = insn;
        }
 
       notesp = &XEXP (note, 1);
@@ -1768,16 +1693,11 @@ final_reg_note_copy (notesp, map)
    This is very similar to a loop in expand_inline_function.  */
 
 static void
-copy_loop_body (loop, copy_start, copy_end, map, exit_label, last_iteration,
-               unroll_type, start_label, loop_end, insert_before,
-               copy_notes_from)
-     struct loop *loop;
-     rtx copy_start, copy_end;
-     struct inline_remap *map;
-     rtx exit_label;
-     int last_iteration;
-     enum unroll_types unroll_type;
-     rtx start_label, loop_end, insert_before, copy_notes_from;
+copy_loop_body (struct loop *loop, rtx copy_start, rtx copy_end,
+               struct inline_remap *map, rtx exit_label,
+               int last_iteration, enum unroll_types unroll_type,
+               rtx start_label, rtx loop_end, rtx insert_before,
+               rtx copy_notes_from)
 {
   struct loop_ivs *ivs = LOOP_IVS (loop);
   rtx insn, pattern;
@@ -1805,12 +1725,6 @@ copy_loop_body (loop, copy_start, copy_end, map, exit_label, last_iteration,
 
   start_sequence ();
 
-  /* Emit a NOTE_INSN_DELETED to force at least two insns onto the sequence.
-     Else gen_sequence could return a raw pattern for a jump which we pass
-     off to emit_insn_before (instead of emit_jump_insn_before) which causes
-     a variety of losing behaviors later.  */
-  emit_note (0, NOTE_INSN_DELETED);
-
   insn = copy_start;
   do
     {
@@ -1834,7 +1748,7 @@ copy_loop_body (loop, copy_start, copy_end, map, exit_label, last_iteration,
             SET_DEST to a new register.  */
 
          if ((set = single_set (insn))
-             && GET_CODE (SET_DEST (set)) == REG
+             && REG_P (SET_DEST (set))
              && addr_combined_regs[REGNO (SET_DEST (set))])
            {
              struct iv_class *bl;
@@ -1882,7 +1796,7 @@ copy_loop_body (loop, copy_start, copy_end, map, exit_label, last_iteration,
 
                        /* tv->dest_reg will be either a bare register,
                           or else a register plus a constant.  */
-                       if (GET_CODE (tv->dest_reg) == REG)
+                       if (REG_P (tv->dest_reg))
                          dest_reg = tv->dest_reg;
                        else
                          dest_reg = XEXP (tv->dest_reg, 0);
@@ -1928,7 +1842,7 @@ copy_loop_body (loop, copy_start, copy_end, map, exit_label, last_iteration,
          dest_reg_was_split = 0;
 
          if ((set = single_set (insn))
-             && GET_CODE (SET_DEST (set)) == REG
+             && REG_P (SET_DEST (set))
              && splittable_regs[REGNO (SET_DEST (set))])
            {
              unsigned int regno = REGNO (SET_DEST (set));
@@ -2046,6 +1960,14 @@ copy_loop_body (loop, copy_start, copy_end, map, exit_label, last_iteration,
              copy = emit_insn (pattern);
            }
          REG_NOTES (copy) = initial_reg_note_copy (REG_NOTES (insn), map);
+         INSN_LOCATOR (copy) = INSN_LOCATOR (insn);
+
+         /* If there is a REG_EQUAL note present whose value
+            is not loop invariant, then delete it, since it
+            may cause problems with later optimization passes.  */
+         if ((tem = find_reg_note (copy, REG_EQUAL, NULL_RTX))
+             && !loop_invariant_p (loop, XEXP (tem, 0)))
+           remove_note (copy, tem);
 
 #ifdef HAVE_cc0
          /* If this insn is setting CC0, it may need to look at
@@ -2092,6 +2014,7 @@ copy_loop_body (loop, copy_start, copy_end, map, exit_label, last_iteration,
          pattern = copy_rtx_and_substitute (PATTERN (insn), map, 0);
          copy = emit_jump_insn (pattern);
          REG_NOTES (copy) = initial_reg_note_copy (REG_NOTES (insn), map);
+         INSN_LOCATOR (copy) = INSN_LOCATOR (insn);
 
          if (JUMP_LABEL (insn))
            {
@@ -2158,7 +2081,7 @@ copy_loop_body (loop, copy_start, copy_end, map, exit_label, last_iteration,
                    }
                }
 
-             if (label && GET_CODE (label) == CODE_LABEL)
+             if (label && LABEL_P (label))
                JUMP_LABEL (copy) = label;
              else
                {
@@ -2215,7 +2138,9 @@ copy_loop_body (loop, copy_start, copy_end, map, exit_label, last_iteration,
          pattern = copy_rtx_and_substitute (PATTERN (insn), map, 0);
          copy = emit_call_insn (pattern);
          REG_NOTES (copy) = initial_reg_note_copy (REG_NOTES (insn), map);
+         INSN_LOCATOR (copy) = INSN_LOCATOR (insn);
          SIBLING_CALL_P (copy) = SIBLING_CALL_P (insn);
+         CONST_OR_PURE_CALL_P (copy) = CONST_OR_PURE_CALL_P (insn);
 
          /* Because the USAGE information potentially contains objects other
             than hard registers, we need to copy it.  */
@@ -2252,20 +2177,14 @@ copy_loop_body (loop, copy_start, copy_end, map, exit_label, last_iteration,
          break;
 
        case NOTE:
-         /* VTOP and CONT notes are valid only before the loop exit test.
-            If placed anywhere else, loop may generate bad code.  */
          /* BASIC_BLOCK notes exist to stabilize basic block structures with
             the associated rtl.  We do not want to share the structure in
             this new block.  */
 
          if (NOTE_LINE_NUMBER (insn) != NOTE_INSN_DELETED
              && NOTE_LINE_NUMBER (insn) != NOTE_INSN_DELETED_LABEL
-             && NOTE_LINE_NUMBER (insn) != NOTE_INSN_BASIC_BLOCK
-             && ((NOTE_LINE_NUMBER (insn) != NOTE_INSN_LOOP_VTOP
-                  && NOTE_LINE_NUMBER (insn) != NOTE_INSN_LOOP_CONT)
-                 || (last_iteration && unroll_type != UNROLL_COMPLETELY)))
-           copy = emit_note (NOTE_SOURCE_FILE (insn),
-                             NOTE_LINE_NUMBER (insn));
+             && NOTE_LINE_NUMBER (insn) != NOTE_INSN_BASIC_BLOCK)
+           copy = emit_note_copy (insn);
          else
            copy = 0;
          break;
@@ -2283,8 +2202,7 @@ copy_loop_body (loop, copy_start, copy_end, map, exit_label, last_iteration,
   do
     {
       insn = NEXT_INSN (insn);
-      if ((GET_CODE (insn) == INSN || GET_CODE (insn) == JUMP_INSN
-          || GET_CODE (insn) == CALL_INSN)
+      if (INSN_P (insn)
          && map->insn_map[INSN_UID (insn)])
        final_reg_note_copy (&REG_NOTES (map->insn_map[INSN_UID (insn)]), map);
     }
@@ -2304,25 +2222,17 @@ copy_loop_body (loop, copy_start, copy_end, map, exit_label, last_iteration,
     {
       for (insn = copy_notes_from; insn != loop_end; insn = NEXT_INSN (insn))
        {
-         /* VTOP notes are valid only before the loop exit test.
-            If placed anywhere else, loop may generate bad code.
-            There is no need to test for NOTE_INSN_LOOP_CONT notes
-            here, since COPY_NOTES_FROM will be at most one or two (for cc0)
-            instructions before the last insn in the loop, and if the
-            end test is that short, there will be a VTOP note between
-            the CONT note and the test.  */
-         if (GET_CODE (insn) == NOTE
+         if (NOTE_P (insn)
              && NOTE_LINE_NUMBER (insn) != NOTE_INSN_DELETED
-             && NOTE_LINE_NUMBER (insn) != NOTE_INSN_BASIC_BLOCK
-             && NOTE_LINE_NUMBER (insn) != NOTE_INSN_LOOP_VTOP)
-           emit_note (NOTE_SOURCE_FILE (insn), NOTE_LINE_NUMBER (insn));
+             && NOTE_LINE_NUMBER (insn) != NOTE_INSN_BASIC_BLOCK)
+           emit_note_copy (insn);
        }
     }
 
   if (final_label && LABEL_NUSES (final_label) > 0)
     emit_label (final_label);
 
-  tem = gen_sequence ();
+  tem = get_insns ();
   end_sequence ();
   loop_insn_emit_before (loop, 0, insert_before, tem);
 }
@@ -2332,8 +2242,7 @@ copy_loop_body (loop, copy_start, copy_end, map, exit_label, last_iteration,
    won't fit in the immediate field of a PLUS insns.  */
 
 void
-emit_unrolled_add (dest_reg, src_reg, increment)
-     rtx dest_reg, src_reg, increment;
+emit_unrolled_add (rtx dest_reg, rtx src_reg, rtx increment)
 {
   rtx result;
 
@@ -2353,9 +2262,7 @@ emit_unrolled_add (dest_reg, src_reg, increment)
    and uses a negligible amount of CPU time on average.  */
 
 int
-back_branch_in_range_p (loop, insn)
-     const struct loop *loop;
-     rtx insn;
+back_branch_in_range_p (const struct loop *loop, rtx insn)
 {
   rtx p, q, target_insn;
   rtx loop_start = loop->start;
@@ -2364,7 +2271,7 @@ back_branch_in_range_p (loop, insn)
 
   /* Stop before we get to the backward branch at the end of the loop.  */
   loop_end = prev_nonnote_insn (loop_end);
-  if (GET_CODE (loop_end) == BARRIER)
+  if (BARRIER_P (loop_end))
     loop_end = PREV_INSN (loop_end);
 
   /* Check in case insn has been deleted, search forward for first non
@@ -2380,7 +2287,7 @@ back_branch_in_range_p (loop, insn)
 
   for (p = NEXT_INSN (insn); p != loop_end; p = NEXT_INSN (p))
     {
-      if (GET_CODE (p) == JUMP_INSN)
+      if (JUMP_P (p))
        {
          target_insn = JUMP_LABEL (p);
 
@@ -2401,9 +2308,7 @@ back_branch_in_range_p (loop, insn)
    value of giv's.  */
 
 static rtx
-fold_rtx_mult_add (mult1, mult2, add1, mode)
-     rtx mult1, mult2, add1;
-     enum machine_mode mode;
+fold_rtx_mult_add (rtx mult1, rtx mult2, rtx add1, enum machine_mode mode)
 {
   rtx temp, mult_res;
   rtx result;
@@ -2450,8 +2355,7 @@ fold_rtx_mult_add (mult1, mult2, add1, mode)
    if it can be calculated.  Otherwise, returns 0.  */
 
 rtx
-biv_total_increment (bl)
-     const struct iv_class *bl;
+biv_total_increment (const struct iv_class *bl)
 {
   struct induction *v;
   rtx result;
@@ -2467,8 +2371,15 @@ biv_total_increment (bl)
   for (v = bl->biv; v; v = v->next_iv)
     {
       if (v->always_computable && v->mult_val == const1_rtx
-         && ! v->maybe_multiple)
-       result = fold_rtx_mult_add (result, const1_rtx, v->add_val, v->mode);
+         && ! v->maybe_multiple
+         && SCALAR_INT_MODE_P (v->mode))
+       {
+         /* If we have already counted it, skip it.  */
+         if (v->same)
+           continue;
+
+         result = fold_rtx_mult_add (result, const1_rtx, v->add_val, v->mode);
+       }
       else
        return 0;
     }
@@ -2501,10 +2412,8 @@ biv_total_increment (bl)
    times, since multiplies by small integers (1,2,3,4) are very cheap.  */
 
 static int
-find_splittable_regs (loop, unroll_type, unroll_number)
-     const struct loop *loop;
-     enum unroll_types unroll_type;
-     int unroll_number;
+find_splittable_regs (const struct loop *loop,
+                     enum unroll_types unroll_type, int unroll_number)
 {
   struct loop_ivs *ivs = LOOP_IVS (loop);
   struct iv_class *bl;
@@ -2529,7 +2438,7 @@ find_splittable_regs (loop, unroll_type, unroll_number)
         it is unsafe to split the biv since it may not have the proper
         value on loop exit.  */
 
-      /* loop_number_exit_count is non-zero if the loop has an exit other than
+      /* loop_number_exit_count is nonzero if the loop has an exit other than
         a fall through at the end.  */
 
       biv_splittable = 1;
@@ -2549,12 +2458,12 @@ find_splittable_regs (loop, unroll_type, unroll_number)
         PLUS, we don't know how to split it.  */
       for (v = bl->biv; biv_splittable && v; v = v->next_iv)
        if ((tem = single_set (v->insn)) == 0
-           || GET_CODE (SET_DEST (tem)) != REG
+           || !REG_P (SET_DEST (tem))
            || REGNO (SET_DEST (tem)) != bl->regno
            || GET_CODE (SET_SRC (tem)) != PLUS)
          biv_splittable = 0;
 
-      /* If final value is non-zero, then must emit an instruction which sets
+      /* If final value is nonzero, then must emit an instruction which sets
         the value of the biv to the proper value.  This is done after
         handling all of the givs, since some of them may need to use the
         biv's value in their initialization code.  */
@@ -2571,7 +2480,7 @@ find_splittable_regs (loop, unroll_type, unroll_number)
                 register, or it isn't invariant, then we must create a new
                 pseudo reg to hold the initial value of the biv.  */
 
-             if (GET_CODE (bl->initial_value) == REG
+             if (REG_P (bl->initial_value)
                  && (REGNO (bl->initial_value) == bl->regno
                      || REGNO (bl->initial_value) < FIRST_PSEUDO_REGISTER
                      || ! loop_invariant_p (loop, bl->initial_value)))
@@ -2579,7 +2488,7 @@ find_splittable_regs (loop, unroll_type, unroll_number)
                  rtx tem = gen_reg_rtx (bl->biv->mode);
 
                  record_base_value (REGNO (tem), bl->biv->add_val, 0);
-                 loop_insn_hoist (loop, 
+                 loop_insn_hoist (loop,
                                   gen_move_insn (tem, bl->biv->src_reg));
 
                  if (loop_dump_stream)
@@ -2614,7 +2523,7 @@ find_splittable_regs (loop, unroll_type, unroll_number)
       result += find_splittable_givs (loop, bl, unroll_type, increment,
                                      unroll_number);
 
-      /* If final value is non-zero, then must emit an instruction which sets
+      /* If final value is nonzero, then must emit an instruction which sets
         the value of the biv to the proper value.  This is done after
         handling all of the givs, since some of them may need to use the
         biv's value in their initialization code.  */
@@ -2654,47 +2563,15 @@ find_splittable_regs (loop, unroll_type, unroll_number)
   return result;
 }
 
-/* Return 1 if the first and last unrolled copy of the address giv V is valid
-   for the instruction that is using it.  Do not make any changes to that
-   instruction.  */
-
-static int
-verify_addresses (v, giv_inc, unroll_number)
-     struct induction *v;
-     rtx giv_inc;
-     int unroll_number;
-{
-  int ret = 1;
-  rtx orig_addr = *v->location;
-  rtx last_addr = plus_constant (v->dest_reg,
-                                INTVAL (giv_inc) * (unroll_number - 1));
-
-  /* First check to see if either address would fail.   Handle the fact
-     that we have may have a match_dup.  */
-  if (! validate_replace_rtx (*v->location, v->dest_reg, v->insn)
-      || ! validate_replace_rtx (*v->location, last_addr, v->insn))
-    ret = 0;
-
-  /* Now put things back the way they were before.  This should always
-   succeed.  */
-  if (! validate_replace_rtx (*v->location, orig_addr, v->insn))
-    abort ();
-
-  return ret;
-}
-
 /* For every giv based on the biv BL, check to determine whether it is
    splittable.  This is a subroutine to find_splittable_regs ().
 
    Return the number of instructions that set splittable registers.  */
 
 static int
-find_splittable_givs (loop, bl, unroll_type, increment, unroll_number)
-     const struct loop *loop;
-     struct iv_class *bl;
-     enum unroll_types unroll_type;
-     rtx increment;
-     int unroll_number;
+find_splittable_givs (const struct loop *loop, struct iv_class *bl,
+                     enum unroll_types unroll_type, rtx increment,
+                     int unroll_number ATTRIBUTE_UNUSED)
 {
   struct loop_ivs *ivs = LOOP_IVS (loop);
   struct induction *v, *v2;
@@ -2772,7 +2649,7 @@ find_splittable_givs (loop, bl, unroll_type, increment, unroll_number)
       /* Should emit insns after the loop if possible, as the biv final value
         code below does.  */
 
-      /* If the final value is non-zero, and the giv has not been reduced,
+      /* If the final value is nonzero, and the giv has not been reduced,
         then must emit an instruction to set the final value.  */
       if (final_value && !v->new_reg)
        {
@@ -2806,7 +2683,7 @@ find_splittable_givs (loop, bl, unroll_type, increment, unroll_number)
 
          if (splittable_regs[bl->regno])
            biv_initial_value = splittable_regs[bl->regno];
-         else if (GET_CODE (bl->initial_value) != REG
+         else if (!REG_P (bl->initial_value)
                   || (REGNO (bl->initial_value) != bl->regno
                       && REGNO (bl->initial_value) >= FIRST_PSEUDO_REGISTER))
            biv_initial_value = bl->initial_value;
@@ -2850,218 +2727,23 @@ find_splittable_givs (loop, bl, unroll_type, increment, unroll_number)
                 is going before the loop start.  */
              if (unroll_type == UNROLL_COMPLETELY
                  && GET_CODE (value) != CONST_INT
-                 && GET_CODE (value) != REG
+                 && !REG_P (value)
                  && (GET_CODE (value) != PLUS
-                     || GET_CODE (XEXP (value, 0)) != REG
+                     || !REG_P (XEXP (value, 0))
                      || GET_CODE (XEXP (value, 1)) != CONST_INT))
                {
                  rtx tem = gen_reg_rtx (v->mode);
                  record_base_value (REGNO (tem), v->add_val, 0);
-                 loop_iv_add_mult_hoist (loop, bl->initial_value, v->mult_val,
-                                         v->add_val, tem);
+                 loop_iv_add_mult_hoist (loop, 
+                               extend_value_for_giv (v, bl->initial_value), 
+                               v->mult_val, v->add_val, tem);
                  value = tem;
                }
 
-             splittable_regs[REGNO (v->new_reg)] = value;
+             splittable_regs[reg_or_subregno (v->new_reg)] = value;
            }
          else
-           {
-             /* Splitting address givs is useful since it will often allow us
-                to eliminate some increment insns for the base giv as
-                unnecessary.  */
-
-             /* If the addr giv is combined with a dest_reg giv, then all
-                references to that dest reg will be remapped, which is NOT
-                what we want for split addr regs. We always create a new
-                register for the split addr giv, just to be safe.  */
-
-             /* If we have multiple identical address givs within a
-                single instruction, then use a single pseudo reg for
-                both.  This is necessary in case one is a match_dup
-                of the other.  */
-
-             v->const_adjust = 0;
-
-             if (v->same_insn)
-               {
-                 v->dest_reg = v->same_insn->dest_reg;
-                 if (loop_dump_stream)
-                   fprintf (loop_dump_stream,
-                            "Sharing address givs in insn %d\n",
-                            INSN_UID (v->insn));
-               }
-             /* If multiple address GIVs have been combined with the
-                same dest_reg GIV, do not create a new register for
-                each.  */
-             else if (unroll_type != UNROLL_COMPLETELY
-                      && v->giv_type == DEST_ADDR
-                      && v->same && v->same->giv_type == DEST_ADDR
-                      && v->same->unrolled
-                      /* combine_givs_p may return true for some cases
-                         where the add and mult values are not equal.
-                         To share a register here, the values must be
-                         equal.  */
-                      && rtx_equal_p (v->same->mult_val, v->mult_val)
-                      && rtx_equal_p (v->same->add_val, v->add_val)
-                      /* If the memory references have different modes,
-                         then the address may not be valid and we must
-                         not share registers.  */
-                      && verify_addresses (v, giv_inc, unroll_number))
-               {
-                 v->dest_reg = v->same->dest_reg;
-                 v->shared = 1;
-               }
-             else if (unroll_type != UNROLL_COMPLETELY)
-               {
-                 /* If not completely unrolling the loop, then create a new
-                    register to hold the split value of the DEST_ADDR giv.
-                    Emit insn to initialize its value before loop start.  */
-
-                 rtx tem = gen_reg_rtx (v->mode);
-                 struct induction *same = v->same;
-                 rtx new_reg = v->new_reg;
-                 record_base_value (REGNO (tem), v->add_val, 0);
-
-                 /* If the address giv has a constant in its new_reg value,
-                    then this constant can be pulled out and put in value,
-                    instead of being part of the initialization code.  */
-
-                 if (GET_CODE (new_reg) == PLUS
-                     && GET_CODE (XEXP (new_reg, 1)) == CONST_INT)
-                   {
-                     v->dest_reg
-                       = plus_constant (tem, INTVAL (XEXP (new_reg, 1)));
-
-                     /* Only succeed if this will give valid addresses.
-                        Try to validate both the first and the last
-                        address resulting from loop unrolling, if
-                        one fails, then can't do const elim here.  */
-                     if (verify_addresses (v, giv_inc, unroll_number))
-                       {
-                         /* Save the negative of the eliminated const, so
-                            that we can calculate the dest_reg's increment
-                            value later.  */
-                         v->const_adjust = -INTVAL (XEXP (new_reg, 1));
-
-                         new_reg = XEXP (new_reg, 0);
-                         if (loop_dump_stream)
-                           fprintf (loop_dump_stream,
-                                    "Eliminating constant from giv %d\n",
-                                    REGNO (tem));
-                       }
-                     else
-                       v->dest_reg = tem;
-                   }
-                 else
-                   v->dest_reg = tem;
-
-                 /* If the address hasn't been checked for validity yet, do so
-                    now, and fail completely if either the first or the last
-                    unrolled copy of the address is not a valid address
-                    for the instruction that uses it.  */
-                 if (v->dest_reg == tem
-                     && ! verify_addresses (v, giv_inc, unroll_number))
-                   {
-                     for (v2 = v->next_iv; v2; v2 = v2->next_iv)
-                       if (v2->same_insn == v)
-                         v2->same_insn = 0;
-
-                     if (loop_dump_stream)
-                       fprintf (loop_dump_stream,
-                                "Invalid address for giv at insn %d\n",
-                                INSN_UID (v->insn));
-                     continue;
-                   }
-
-                 v->new_reg = new_reg;
-                 v->same = same;
-
-                 /* We set this after the address check, to guarantee that
-                    the register will be initialized.  */
-                 v->unrolled = 1;
-
-                 /* To initialize the new register, just move the value of
-                    new_reg into it.  This is not guaranteed to give a valid
-                    instruction on machines with complex addressing modes.
-                    If we can't recognize it, then delete it and emit insns
-                    to calculate the value from scratch.  */
-                 loop_insn_hoist (loop, gen_rtx_SET (VOIDmode, tem,
-                                                     copy_rtx (v->new_reg)));
-                 if (recog_memoized (PREV_INSN (loop->start)) < 0)
-                   {
-                     rtx sequence, ret;
-
-                     /* We can't use bl->initial_value to compute the initial
-                        value, because the loop may have been preconditioned.
-                        We must calculate it from NEW_REG.  */
-                     delete_related_insns (PREV_INSN (loop->start));
-
-                     start_sequence ();
-                     ret = force_operand (v->new_reg, tem);
-                     if (ret != tem)
-                       emit_move_insn (tem, ret);
-                     sequence = gen_sequence ();
-                     end_sequence ();
-                     loop_insn_hoist (loop, sequence);
-
-                     if (loop_dump_stream)
-                       fprintf (loop_dump_stream,
-                                "Invalid init insn, rewritten.\n");
-                   }
-               }
-             else
-               {
-                 v->dest_reg = value;
-
-                 /* Check the resulting address for validity, and fail
-                    if the resulting address would be invalid.  */
-                 if (! verify_addresses (v, giv_inc, unroll_number))
-                   {
-                     for (v2 = v->next_iv; v2; v2 = v2->next_iv)
-                       if (v2->same_insn == v)
-                         v2->same_insn = 0;
-
-                     if (loop_dump_stream)
-                       fprintf (loop_dump_stream,
-                                "Invalid address for giv at insn %d\n",
-                                INSN_UID (v->insn));
-                     continue;
-                   }
-               }
-
-             /* Store the value of dest_reg into the insn.  This sharing
-                will not be a problem as this insn will always be copied
-                later.  */
-
-             *v->location = v->dest_reg;
-
-             /* If this address giv is combined with a dest reg giv, then
-                save the base giv's induction pointer so that we will be
-                able to handle this address giv properly.  The base giv
-                itself does not have to be splittable.  */
-
-             if (v->same && v->same->giv_type == DEST_REG)
-               addr_combined_regs[REGNO (v->same->new_reg)] = v->same;
-
-             if (GET_CODE (v->new_reg) == REG)
-               {
-                 /* This giv maybe hasn't been combined with any others.
-                    Make sure that it's giv is marked as splittable here.  */
-
-                 splittable_regs[REGNO (v->new_reg)] = value;
-
-                 /* Make it appear to depend upon itself, so that the
-                    giv will be properly split in the main loop above.  */
-                 if (! v->same)
-                   {
-                     v->same = v;
-                     addr_combined_regs[REGNO (v->new_reg)] = v;
-                   }
-               }
-
-             if (loop_dump_stream)
-               fprintf (loop_dump_stream, "DEST_ADDR giv being split.\n");
-           }
+           continue;
        }
       else
        {
@@ -3086,13 +2768,13 @@ find_splittable_givs (loop, bl, unroll_type, increment, unroll_number)
         a splittable register.  Don't need to do anything for address givs
         where this may not be a register.  */
 
-      if (GET_CODE (v->new_reg) == REG)
+      if (REG_P (v->new_reg))
        {
          int count = 1;
          if (! v->ignore)
            count = REG_IV_CLASS (ivs, REGNO (v->src_reg))->biv_count;
 
-         splittable_regs_updates[REGNO (v->new_reg)] = count;
+         splittable_regs_updates[reg_or_subregno (v->new_reg)] = count;
        }
 
       result++;
@@ -3103,7 +2785,7 @@ find_splittable_givs (loop, bl, unroll_type, increment, unroll_number)
 
          if (GET_CODE (v->dest_reg) == CONST_INT)
            regnum = -1;
-         else if (GET_CODE (v->dest_reg) != REG)
+         else if (!REG_P (v->dest_reg))
            regnum = REGNO (XEXP (v->dest_reg, 0));
          else
            regnum = REGNO (v->dest_reg);
@@ -3124,12 +2806,9 @@ find_splittable_givs (loop, bl, unroll_type, increment, unroll_number)
    it can search past if statements and other similar structures.  */
 
 static int
-reg_dead_after_loop (loop, reg)
-     const struct loop *loop;
-     rtx reg;
+reg_dead_after_loop (const struct loop *loop, rtx reg)
 {
   rtx insn, label;
-  enum rtx_code code;
   int jump_count = 0;
   int label_count = 0;
 
@@ -3159,29 +2838,32 @@ reg_dead_after_loop (loop, reg)
       insn = NEXT_INSN (XEXP (label, 0));
       while (insn)
        {
-         code = GET_CODE (insn);
-         if (GET_RTX_CLASS (code) == 'i')
+         if (INSN_P (insn))
            {
-             rtx set;
+             rtx set, note;
 
              if (reg_referenced_p (reg, PATTERN (insn)))
                return 0;
 
+             note = find_reg_equal_equiv_note (insn);
+             if (note && reg_overlap_mentioned_p (reg, XEXP (note, 0)))
+               return 0;
+
              set = single_set (insn);
              if (set && rtx_equal_p (SET_DEST (set), reg))
                break;
-           }
 
-         if (code == JUMP_INSN)
-           {
-             if (GET_CODE (PATTERN (insn)) == RETURN)
-               break;
-             else if (!any_uncondjump_p (insn)
-                      /* Prevent infinite loop following infinite loops.  */
-                      || jump_count++ > 20)
-               return 0;
-             else
-               insn = JUMP_LABEL (insn);
+             if (JUMP_P (insn))
+               {
+                 if (GET_CODE (PATTERN (insn)) == RETURN)
+                   break;
+                 else if (!any_uncondjump_p (insn)
+                          /* Prevent infinite loop following infinite loops.  */
+                          || jump_count++ > 20)
+                   return 0;
+                 else
+                   insn = JUMP_LABEL (insn);
+               }
            }
 
          insn = NEXT_INSN (insn);
@@ -3196,9 +2878,7 @@ reg_dead_after_loop (loop, reg)
    the end of the loop.  If we can do it, return that value.  */
 
 rtx
-final_biv_value (loop, bl)
-     const struct loop *loop;
-     struct iv_class *bl;
+final_biv_value (const struct loop *loop, struct iv_class *bl)
 {
   unsigned HOST_WIDE_INT n_iterations = LOOP_INFO (loop)->n_iterations;
   rtx increment, tem;
@@ -3270,9 +2950,7 @@ final_biv_value (loop, bl)
    the end of the loop.  If we can do it, return that value.  */
 
 rtx
-final_giv_value (loop, v)
-     const struct loop *loop;
-     struct induction *v;
+final_giv_value (const struct loop *loop, struct induction *v)
 {
   struct loop_ivs *ivs = LOOP_IVS (loop);
   struct iv_class *bl;
@@ -3299,7 +2977,8 @@ final_giv_value (loop, v)
 
   /* Try to calculate the final value as a function of the biv it depends
      upon.  The only exit from the loop must be the fall through at the bottom
-     (otherwise it may not have its final value when the loop exits).  */
+     and the insn that sets the giv must be executed on every iteration
+     (otherwise the giv may not have its final value when the loop exits).  */
 
   /* ??? Can calculate the final giv value by subtracting off the
      extra biv increments times the giv's mult_val.  The loop must have
@@ -3307,7 +2986,8 @@ final_giv_value (loop, v)
      to be known.  */
 
   if (n_iterations != 0
-      && ! loop->exit_count)
+      && ! loop->exit_count
+      && v->always_executed)
     {
       /* ?? It is tempting to use the biv's value here since these insns will
         be put after the loop, and hence the biv will have its final value
@@ -3356,7 +3036,7 @@ final_giv_value (loop, v)
                    tem = expand_simple_binop (GET_MODE (tem), MINUS, tem,
                                               biv->add_val, NULL_RTX, 0,
                                               OPTAB_LIB_WIDEN);
-                   seq = gen_sequence ();
+                   seq = get_insns ();
                    end_sequence ();
                    loop_insn_sink (loop, seq);
                  }
@@ -3397,9 +3077,7 @@ final_giv_value (loop, v)
    the SET_SRC of REG.  */
 
 static rtx
-loop_find_equiv_value (loop, reg)
-     const struct loop *loop;
-     rtx reg;
+loop_find_equiv_value (const struct loop *loop, rtx reg)
 {
   rtx loop_start = loop->start;
   rtx insn, set;
@@ -3408,7 +3086,7 @@ loop_find_equiv_value (loop, reg)
   ret = reg;
   for (insn = PREV_INSN (loop_start); insn; insn = PREV_INSN (insn))
     {
-      if (GET_CODE (insn) == CODE_LABEL)
+      if (LABEL_P (insn))
        break;
 
       else if (INSN_P (insn) && reg_set_p (reg, insn))
@@ -3441,43 +3119,15 @@ loop_find_equiv_value (loop, reg)
   return ret;
 }
 
-/* Return a simplified rtx for the expression OP - REG.
-
-   REG must appear in OP, and OP must be a register or the sum of a register
-   and a second term.
-
-   Thus, the return value must be const0_rtx or the second term.
-
-   The caller is responsible for verifying that REG appears in OP and OP has
-   the proper form.  */
-
-static rtx
-subtract_reg_term (op, reg)
-     rtx op, reg;
-{
-  if (op == reg)
-    return const0_rtx;
-  if (GET_CODE (op) == PLUS)
-    {
-      if (XEXP (op, 0) == reg)
-       return XEXP (op, 1);
-      else if (XEXP (op, 1) == reg)
-       return XEXP (op, 0);
-    }
-  /* OP does not contain REG as a term.  */
-  abort ();
-}
-
 /* Find and return register term common to both expressions OP0 and
    OP1 or NULL_RTX if no such term exists.  Each expression must be a
    REG or a PLUS of a REG.  */
 
 static rtx
-find_common_reg_term (op0, op1)
-     rtx op0, op1;
+find_common_reg_term (rtx op0, rtx op1)
 {
-  if ((GET_CODE (op0) == REG || GET_CODE (op0) == PLUS)
-      && (GET_CODE (op1) == REG || GET_CODE (op1) == PLUS))
+  if ((REG_P (op0) || GET_CODE (op0) == PLUS)
+      && (REG_P (op1) || GET_CODE (op1) == PLUS))
     {
       rtx op00;
       rtx op01;
@@ -3510,8 +3160,7 @@ find_common_reg_term (op0, op1)
    be calculated, otherwise returns zero.  */
 
 unsigned HOST_WIDE_INT
-loop_iterations (loop)
-     struct loop *loop;
+loop_iterations (struct loop *loop)
 {
   struct loop_info *loop_info = LOOP_INFO (loop);
   struct loop_ivs *ivs = LOOP_IVS (loop);
@@ -3525,7 +3174,6 @@ loop_iterations (loop)
   int increment_dir;
   int unsigned_p, compare_dir, final_larger;
   rtx last_loop_insn;
-  rtx reg_term;
   struct iv_class *bl;
 
   loop_info->n_iterations = 0;
@@ -3548,7 +3196,7 @@ loop_iterations (loop)
   /* ??? We should probably try harder to find the jump insn
      at the end of the loop.  The following code assumes that
      the last loop insn is a jump to the top of the loop.  */
-  if (GET_CODE (last_loop_insn) != JUMP_INSN)
+  if (!JUMP_P (last_loop_insn))
     {
       if (loop_dump_stream)
        fprintf (loop_dump_stream,
@@ -3566,44 +3214,6 @@ loop_iterations (loop)
       return 0;
     }
 
-  /* If there are multiple conditionalized loop exit tests, they may jump
-     back to differing CODE_LABELs.  */
-  if (loop->top && loop->cont)
-    {
-      rtx temp = PREV_INSN (last_loop_insn);
-
-      do
-       {
-         if (GET_CODE (temp) == JUMP_INSN)
-           {
-             /* There are some kinds of jumps we can't deal with easily.  */
-             if (JUMP_LABEL (temp) == 0)
-               {
-                 if (loop_dump_stream)
-                   fprintf
-                     (loop_dump_stream,
-                      "Loop iterations: Jump insn has null JUMP_LABEL.\n");
-                 return 0;
-               }
-
-             if (/* Previous unrolling may have generated new insns not
-                    covered by the uid_luid array.  */
-                 INSN_UID (JUMP_LABEL (temp)) < max_uid_for_loop
-                 /* Check if we jump back into the loop body.  */
-                 && INSN_LUID (JUMP_LABEL (temp)) > INSN_LUID (loop->top)
-                 && INSN_LUID (JUMP_LABEL (temp)) < INSN_LUID (loop->cont))
-               {
-                 if (loop_dump_stream)
-                   fprintf 
-                     (loop_dump_stream,
-                      "Loop iterations: Loop has multiple back edges.\n");
-                 return 0;
-               }
-           }
-       }
-      while ((temp = PREV_INSN (temp)) != loop->cont);
-    }
-
   /* Find the iteration variable.  If the last insn is a conditional
      branch, and the insn before tests a register value, make that the
      iteration variable.  */
@@ -3624,7 +3234,7 @@ loop_iterations (loop)
   iteration_var = XEXP (comparison, 0);
   comparison_value = XEXP (comparison, 1);
 
-  if (GET_CODE (iteration_var) != REG)
+  if (!REG_P (iteration_var))
     {
       if (loop_dump_stream)
        fprintf (loop_dump_stream,
@@ -3682,7 +3292,20 @@ loop_iterations (loop)
                 "Loop iterations: Iteration var not an integer.\n");
       return 0;
     }
-  else if (REG_IV_TYPE (ivs, REGNO (iteration_var)) == BASIC_INDUCT)
+
+  /* Try swapping the comparison to identify a suitable iv.  */
+  if (REG_IV_TYPE (ivs, REGNO (iteration_var)) != BASIC_INDUCT
+      && REG_IV_TYPE (ivs, REGNO (iteration_var)) != GENERAL_INDUCT
+      && REG_P (comparison_value)
+      && REGNO (comparison_value) < ivs->n_regs)
+    {
+      rtx temp = comparison_value;
+      comparison_code = swap_condition (comparison_code);
+      comparison_value = iteration_var;
+      iteration_var = temp;
+    }
+
+  if (REG_IV_TYPE (ivs, REGNO (iteration_var)) == BASIC_INDUCT)
     {
       if (REGNO (iteration_var) >= ivs->n_regs)
        abort ();
@@ -3748,6 +3371,10 @@ loop_iterations (loop)
                        return 0;
                    }
 
+                 /* If we have already counted it, skip it.  */
+                 if (biv_inc->same)
+                   continue;
+
                  offset -= INTVAL (biv_inc->add_val);
                }
            }
@@ -3805,6 +3432,7 @@ loop_iterations (loop)
       unsigned_p = 1;
     case GT:
       compare_dir = -1;
+      break;
     case NE:
       compare_dir = 0;
       break;
@@ -3816,7 +3444,7 @@ loop_iterations (loop)
      its value from the insns before the start of the loop.  */
 
   final_value = comparison_value;
-  if (GET_CODE (comparison_value) == REG
+  if (REG_P (comparison_value)
       && loop_invariant_p (loop, comparison_value))
     {
       final_value = loop_find_equiv_value (loop, comparison_value);
@@ -3885,7 +3513,7 @@ loop_iterations (loop)
 
          if (find_common_reg_term (temp, reg2))
            initial_value = temp;
-         else
+         else if (loop_invariant_p (loop, reg2))
            {
              /* Find what reg2 is equivalent to.  Hopefully it will
                 either be reg1 or reg1 plus a constant.  Let's ignore
@@ -3899,44 +3527,6 @@ loop_iterations (loop)
                  ? reg1 : gen_rtx_PLUS (GET_MODE (reg1), reg1, const2);
            }
        }
-      else if (loop->vtop && GET_CODE (reg2) == CONST_INT)
-       {
-         rtx temp;
-
-         /* When running the loop optimizer twice, check_dbra_loop
-            further obfuscates reversible loops of the form:
-            for (i = init; i < init + const; i++).  We often end up with
-            final_value = 0, initial_value = temp, temp = temp2 - init,
-            where temp2 = init + const.  If the loop has a vtop we
-            can replace initial_value with const.  */
-
-         temp = loop_find_equiv_value (loop, reg1);
-
-         if (GET_CODE (temp) == MINUS && REG_P (XEXP (temp, 0)))
-           {
-             rtx temp2 = loop_find_equiv_value (loop, XEXP (temp, 0));
-
-             if (GET_CODE (temp2) == PLUS
-                 && XEXP (temp2, 0) == XEXP (temp, 1))
-               initial_value = XEXP (temp2, 1);
-           }
-       }
-    }
-
-  /* If have initial_value = reg + const1 and final_value = reg +
-     const2, then replace initial_value with const1 and final_value
-     with const2.  This should be safe since we are protected by the
-     initial comparison before entering the loop if we have a vtop.
-     For example, a + b < a + c is not equivalent to b < c for all a
-     when using modulo arithmetic.
-
-     ??? Without a vtop we could still perform the optimization if we check
-     the initial and final values carefully.  */
-  if (loop->vtop
-      && (reg_term = find_common_reg_term (initial_value, final_value)))
-    {
-      initial_value = subtract_reg_term (initial_value, reg_term);
-      final_value = subtract_reg_term (final_value, reg_term);
     }
 
   loop_info->initial_equiv_value = initial_value;
@@ -3961,7 +3551,7 @@ loop_iterations (loop)
       /* If we have a REG, check to see if REG holds a constant value.  */
       /* ??? Other RTL, such as (neg (reg)) is possible here, but it isn't
         clear if it is worthwhile to try to handle such RTL.  */
-      if (GET_CODE (increment) == REG || GET_CODE (increment) == SUBREG)
+      if (REG_P (increment) || GET_CODE (increment) == SUBREG)
        increment = loop_find_equiv_value (loop, increment);
 
       if (GET_CODE (increment) != CONST_INT)
@@ -3989,12 +3579,6 @@ loop_iterations (loop)
        }
       return 0;
     }
-  else if (comparison_code == EQ)
-    {
-      if (loop_dump_stream)
-       fprintf (loop_dump_stream, "Loop iterations: EQ comparison loop.\n");
-      return 0;
-    }
   else if (GET_CODE (final_value) != CONST_INT)
     {
       if (loop_dump_stream)
@@ -4006,6 +3590,43 @@ loop_iterations (loop)
        }
       return 0;
     }
+  else if (comparison_code == EQ)
+    {
+      rtx inc_once;
+
+      if (loop_dump_stream)
+       fprintf (loop_dump_stream, "Loop iterations: EQ comparison loop.\n");
+
+      inc_once = gen_int_mode (INTVAL (initial_value) + INTVAL (increment),
+                              GET_MODE (iteration_var));
+
+      if (inc_once == final_value)
+       {
+         /* The iterator value once through the loop is equal to the
+            comparison value.  Either we have an infinite loop, or
+            we'll loop twice.  */
+         if (increment == const0_rtx)
+           return 0;
+         loop_info->n_iterations = 2;
+       }
+      else
+       loop_info->n_iterations = 1;
+
+      if (GET_CODE (loop_info->initial_value) == CONST_INT)
+       loop_info->final_value
+         = gen_int_mode ((INTVAL (loop_info->initial_value)
+                          + loop_info->n_iterations * INTVAL (increment)),
+                         GET_MODE (iteration_var));
+      else
+       loop_info->final_value
+         = plus_constant (loop_info->initial_value,
+                          loop_info->n_iterations * INTVAL (increment));
+      loop_info->final_equiv_value
+       = gen_int_mode ((INTVAL (initial_value)
+                        + loop_info->n_iterations * INTVAL (increment)),
+                       GET_MODE (iteration_var));
+      return loop_info->n_iterations;
+    }
 
   /* Final_larger is 1 if final larger, 0 if they are equal, otherwise -1.  */
   if (unsigned_p)
@@ -4108,9 +3729,7 @@ loop_iterations (loop)
    copying.  */
 
 static rtx
-remap_split_bivs (loop, x)
-     struct loop *loop;
-     rtx x;
+remap_split_bivs (struct loop *loop, rtx x)
 {
   struct loop_ivs *ivs = LOOP_IVS (loop);
   enum rtx_code code;
@@ -4178,19 +3797,15 @@ remap_split_bivs (loop, x)
    must dominate LAST_UID.  */
 
 int
-set_dominates_use (regno, first_uid, last_uid, copy_start, copy_end)
-     int regno;
-     int first_uid;
-     int last_uid;
-     rtx copy_start;
-     rtx copy_end;
+set_dominates_use (int regno, int first_uid, int last_uid, rtx copy_start,
+                  rtx copy_end)
 {
   int passed_jump = 0;
   rtx p = NEXT_INSN (copy_start);
 
   while (INSN_UID (p) != first_uid)
     {
-      if (GET_CODE (p) == JUMP_INSN)
+      if (JUMP_P (p))
        passed_jump = 1;
       /* Could not find FIRST_UID.  */
       if (p == copy_end)
@@ -4210,7 +3825,7 @@ set_dominates_use (regno, first_uid, last_uid, copy_start, copy_end)
     {
       /* If we see a CODE_LABEL between FIRST_UID and LAST_UID, then we
         can not be sure that FIRST_UID dominates LAST_UID.  */
-      if (GET_CODE (p) == CODE_LABEL)
+      if (LABEL_P (p))
        return 0;
       /* Could not find LAST_UID, but we reached the end of the loop, so
         it must be safe.  */
@@ -4223,38 +3838,3 @@ set_dominates_use (regno, first_uid, last_uid, copy_start, copy_end)
   return 1;
 }
 
-/* This routine is called when the number of iterations for the unrolled
-   loop is one.   The goal is to identify a loop that begins with an
-   unconditional branch to the loop continuation note (or a label just after).
-   In this case, the unconditional branch that starts the loop needs to be
-   deleted so that we execute the single iteration.  */
-
-static rtx
-ujump_to_loop_cont (loop_start, loop_cont)
-     rtx loop_start;
-     rtx loop_cont;
-{
-  rtx x, label, label_ref;
-
-  /* See if loop start, or the next insn is an unconditional jump.  */
-  loop_start = next_nonnote_insn (loop_start);
-
-  x = pc_set (loop_start);
-  if (!x)
-    return NULL_RTX;
-
-  label_ref = SET_SRC (x);
-  if (!label_ref)
-    return NULL_RTX;
-
-  /* Examine insn after loop continuation note.  Return if not a label.  */
-  label = next_nonnote_insn (loop_cont);
-  if (label == 0 || GET_CODE (label) != CODE_LABEL)
-    return NULL_RTX;
-
-  /* Return the loop start if the branch label matches the code label.  */
-  if (CODE_LABEL_NUMBER (label) == CODE_LABEL_NUMBER (XEXP (label_ref, 0)))
-    return loop_start;
-  else
-    return NULL_RTX;
-}