OSDN Git Service

* g++.dg/rtti/tinfo1.C: Remove xfails.
[pf3gnuchains/gcc-fork.git] / gcc / loop.c
index 97d1571..08b8529 100644 (file)
@@ -57,7 +57,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "recog.h"
 #include "flags.h"
 #include "real.h"
-#include "loop.h"
 #include "cselib.h"
 #include "except.h"
 #include "toplev.h"
@@ -67,6 +66,354 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "cfgloop.h"
 #include "ggc.h"
 
+/* Get the loop info pointer of a loop.  */
+#define LOOP_INFO(LOOP) ((struct loop_info *) (LOOP)->aux)
+
+/* Get a pointer to the loop movables structure.  */
+#define LOOP_MOVABLES(LOOP) (&LOOP_INFO (LOOP)->movables)
+
+/* Get a pointer to the loop registers structure.  */
+#define LOOP_REGS(LOOP) (&LOOP_INFO (LOOP)->regs)
+
+/* Get a pointer to the loop induction variables structure.  */
+#define LOOP_IVS(LOOP) (&LOOP_INFO (LOOP)->ivs)
+
+/* Get the luid of an insn.  Catch the error of trying to reference the LUID
+   of an insn added during loop, since these don't have LUIDs.  */
+
+#define INSN_LUID(INSN)                        \
+  (INSN_UID (INSN) < max_uid_for_loop ? uid_luid[INSN_UID (INSN)] \
+   : (abort (), -1))
+
+#define REGNO_FIRST_LUID(REGNO)                        \
+  (REGNO_FIRST_UID (REGNO) < max_uid_for_loop  \
+       ? uid_luid[REGNO_FIRST_UID (REGNO)]     \
+       : 0)
+#define REGNO_LAST_LUID(REGNO)                 \
+  (REGNO_LAST_UID (REGNO) < max_uid_for_loop   \
+       ? uid_luid[REGNO_LAST_UID (REGNO)]      \
+       : INT_MAX)
+
+/* A "basic induction variable" or biv is a pseudo reg that is set
+   (within this loop) only by incrementing or decrementing it.  */
+/* A "general induction variable" or giv is a pseudo reg whose
+   value is a linear function of a biv.  */
+
+/* Bivs are recognized by `basic_induction_var';
+   Givs by `general_induction_var'.  */
+
+/* An enum for the two different types of givs, those that are used
+   as memory addresses and those that are calculated into registers.  */
+enum g_types
+{
+  DEST_ADDR,
+  DEST_REG
+};
+
+
+/* A `struct induction' is created for every instruction that sets
+   an induction variable (either a biv or a giv).  */
+
+struct induction
+{
+  rtx insn;                    /* The insn that sets a biv or giv */
+  rtx new_reg;                 /* New register, containing strength reduced
+                                  version of this giv.  */
+  rtx src_reg;                 /* Biv from which this giv is computed.
+                                  (If this is a biv, then this is the biv.) */
+  enum g_types giv_type;       /* Indicate whether DEST_ADDR or DEST_REG */
+  rtx dest_reg;                        /* Destination register for insn: this is the
+                                  register which was the biv or giv.
+                                  For a biv, this equals src_reg.
+                                  For a DEST_ADDR type giv, this is 0.  */
+  rtx *location;               /* Place in the insn where this giv occurs.
+                                  If GIV_TYPE is DEST_REG, this is 0.  */
+                               /* For a biv, this is the place where add_val
+                                  was found.  */
+  enum machine_mode mode;      /* The mode of this biv or giv */
+  rtx mem;                     /* For DEST_ADDR, the memory object.  */
+  rtx mult_val;                        /* Multiplicative factor for src_reg.  */
+  rtx add_val;                 /* Additive constant for that product.  */
+  int benefit;                 /* Gain from eliminating this insn.  */
+  rtx final_value;             /* If the giv is used outside the loop, and its
+                                  final value could be calculated, it is put
+                                  here, and the giv is made replaceable.  Set
+                                  the giv to this value before the loop.  */
+  unsigned combined_with;      /* The number of givs this giv has been
+                                  combined with.  If nonzero, this giv
+                                  cannot combine with any other giv.  */
+  unsigned replaceable : 1;    /* 1 if we can substitute the strength-reduced
+                                  variable for the original variable.
+                                  0 means they must be kept separate and the
+                                  new one must be copied into the old pseudo
+                                  reg each time the old one is set.  */
+  unsigned not_replaceable : 1;        /* Used to prevent duplicating work.  This is
+                                  1 if we know that the giv definitely can
+                                  not be made replaceable, in which case we
+                                  don't bother checking the variable again
+                                  even if further info is available.
+                                  Both this and the above can be zero.  */
+  unsigned ignore : 1;         /* 1 prohibits further processing of giv */
+  unsigned always_computable : 1;/* 1 if this value is computable every
+                                   iteration.  */
+  unsigned always_executed : 1; /* 1 if this set occurs each iteration.  */
+  unsigned maybe_multiple : 1; /* Only used for a biv and  1 if this biv
+                                  update may be done multiple times per
+                                  iteration.  */
+  unsigned cant_derive : 1;    /* For giv's, 1 if this giv cannot derive
+                                  another giv.  This occurs in many cases
+                                  where a giv's lifetime spans an update to
+                                  a biv.  */
+  unsigned maybe_dead : 1;     /* 1 if this giv might be dead.  In that case,
+                                  we won't use it to eliminate a biv, it
+                                  would probably lose.  */
+  unsigned auto_inc_opt : 1;   /* 1 if this giv had its increment output next
+                                  to it to try to form an auto-inc address.  */
+  unsigned shared : 1;
+  unsigned no_const_addval : 1; /* 1 if add_val does not contain a const.  */
+  int lifetime;                        /* Length of life of this giv */
+  rtx derive_adjustment;       /* If nonzero, is an adjustment to be
+                                  subtracted from add_val when this giv
+                                  derives another.  This occurs when the
+                                  giv spans a biv update by incrementation.  */
+  rtx ext_dependent;           /* If nonzero, is a sign or zero extension
+                                  if a biv on which this giv is dependent.  */
+  struct induction *next_iv;   /* For givs, links together all givs that are
+                                  based on the same biv.  For bivs, links
+                                  together all biv entries that refer to the
+                                  same biv register.  */
+  struct induction *same;      /* For givs, if the giv has been combined with
+                                  another giv, this points to the base giv.
+                                  The base giv will have COMBINED_WITH nonzero.
+                                  For bivs, if the biv has the same LOCATION
+                                  than another biv, this points to the base
+                                  biv.  */
+  struct induction *same_insn; /* If there are multiple identical givs in
+                                  the same insn, then all but one have this
+                                  field set, and they all point to the giv
+                                  that doesn't have this field set.  */
+  rtx last_use;                        /* For a giv made from a biv increment, this is
+                                  a substitute for the lifetime information.  */
+};
+
+
+/* A `struct iv_class' is created for each biv.  */
+
+struct iv_class
+{
+  unsigned int regno;          /* Pseudo reg which is the biv.  */
+  int biv_count;               /* Number of insns setting this reg.  */
+  struct induction *biv;       /* List of all insns that set this reg.  */
+  int giv_count;               /* Number of DEST_REG givs computed from this
+                                  biv.  The resulting count is only used in
+                                  check_dbra_loop.  */
+  struct induction *giv;       /* List of all insns that compute a giv
+                                  from this reg.  */
+  int total_benefit;           /* Sum of BENEFITs of all those givs.  */
+  rtx initial_value;           /* Value of reg at loop start.  */
+  rtx initial_test;            /* Test performed on BIV before loop.  */
+  rtx final_value;             /* Value of reg at loop end, if known.  */
+  struct iv_class *next;       /* Links all class structures together.  */
+  rtx init_insn;               /* insn which initializes biv, 0 if none.  */
+  rtx init_set;                        /* SET of INIT_INSN, if any.  */
+  unsigned incremented : 1;    /* 1 if somewhere incremented/decremented */
+  unsigned eliminable : 1;     /* 1 if plausible candidate for
+                                   elimination.  */
+  unsigned nonneg : 1;         /* 1 if we added a REG_NONNEG note for
+                                   this.  */
+  unsigned reversed : 1;       /* 1 if we reversed the loop that this
+                                  biv controls.  */
+  unsigned all_reduced : 1;    /* 1 if all givs using this biv have
+                                   been reduced.  */
+};
+
+
+/* Definitions used by the basic induction variable discovery code.  */
+enum iv_mode
+{
+  UNKNOWN_INDUCT,
+  BASIC_INDUCT,
+  NOT_BASIC_INDUCT,
+  GENERAL_INDUCT
+};
+
+
+/* A `struct iv' is created for every register.  */
+
+struct iv
+{
+  enum iv_mode type;
+  union
+  {
+    struct iv_class *class;
+    struct induction *info;
+  } iv;
+};
+
+
+#define REG_IV_TYPE(ivs, n) ivs->regs[n].type
+#define REG_IV_INFO(ivs, n) ivs->regs[n].iv.info
+#define REG_IV_CLASS(ivs, n) ivs->regs[n].iv.class
+
+
+struct loop_ivs
+{
+  /* Indexed by register number, contains pointer to `struct
+     iv' if register is an induction variable.  */
+  struct iv *regs;
+
+  /* Size of regs array.  */
+  unsigned int n_regs;
+
+  /* The head of a list which links together (via the next field)
+     every iv class for the current loop.  */
+  struct iv_class *list;
+};
+
+
+typedef struct loop_mem_info
+{
+  rtx mem;      /* The MEM itself.  */
+  rtx reg;      /* Corresponding pseudo, if any.  */
+  int optimize; /* Nonzero if we can optimize access to this MEM.  */
+} loop_mem_info;
+
+
+
+struct loop_reg
+{
+  /* Number of times the reg is set during the loop being scanned.
+     During code motion, a negative value indicates a reg that has
+     been made a candidate; in particular -2 means that it is an
+     candidate that we know is equal to a constant and -1 means that
+     it is a candidate not known equal to a constant.  After code
+     motion, regs moved have 0 (which is accurate now) while the
+     failed candidates have the original number of times set.
+
+     Therefore, at all times, == 0 indicates an invariant register;
+     < 0 a conditionally invariant one.  */
+  int set_in_loop;
+
+  /* Original value of set_in_loop; same except that this value
+     is not set negative for a reg whose sets have been made candidates
+     and not set to 0 for a reg that is moved.  */
+  int n_times_set;
+
+  /* Contains the insn in which a register was used if it was used
+     exactly once; contains const0_rtx if it was used more than once.  */
+  rtx single_usage;
+
+  /* Nonzero indicates that the register cannot be moved or strength
+     reduced.  */
+  char may_not_optimize;
+
+  /* Nonzero means reg N has already been moved out of one loop.
+     This reduces the desire to move it out of another.  */
+  char moved_once;
+};
+
+
+struct loop_regs
+{
+  int num;                     /* Number of regs used in table.  */
+  int size;                    /* Size of table.  */
+  struct loop_reg *array;      /* Register usage info. array.  */
+  int multiple_uses;           /* Nonzero if a reg has multiple uses.  */
+};
+
+
+
+struct loop_movables
+{
+  /* Head of movable chain.  */
+  struct movable *head;
+  /* Last movable in chain.  */
+  struct movable *last;
+};
+
+
+/* Information pertaining to a loop.  */
+
+struct loop_info
+{
+  /* Nonzero if there is a subroutine call in the current loop.  */
+  int has_call;
+  /* Nonzero if there is a libcall in the current loop.  */
+  int has_libcall;
+  /* Nonzero if there is a non constant call in the current loop.  */
+  int has_nonconst_call;
+  /* Nonzero if there is a prefetch instruction in the current loop.  */
+  int has_prefetch;
+  /* Nonzero if there is a volatile memory reference in the current
+     loop.  */
+  int has_volatile;
+  /* Nonzero if there is a tablejump in the current loop.  */
+  int has_tablejump;
+  /* Nonzero if there are ways to leave the loop other than falling
+     off the end.  */
+  int has_multiple_exit_targets;
+  /* Nonzero if there is an indirect jump in the current function.  */
+  int has_indirect_jump;
+  /* Register or constant initial loop value.  */
+  rtx initial_value;
+  /* Register or constant value used for comparison test.  */
+  rtx comparison_value;
+  /* Register or constant approximate final value.  */
+  rtx final_value;
+  /* Register or constant initial loop value with term common to
+     final_value removed.  */
+  rtx initial_equiv_value;
+  /* Register or constant final loop value with term common to
+     initial_value removed.  */
+  rtx final_equiv_value;
+  /* Register corresponding to iteration variable.  */
+  rtx iteration_var;
+  /* Constant loop increment.  */
+  rtx increment;
+  enum rtx_code comparison_code;
+  /* Holds the number of loop iterations.  It is zero if the number
+     could not be calculated.  Must be unsigned since the number of
+     iterations can be as high as 2^wordsize - 1.  For loops with a
+     wider iterator, this number will be zero if the number of loop
+     iterations is too large for an unsigned integer to hold.  */
+  unsigned HOST_WIDE_INT n_iterations;
+  int used_count_register;
+  /* The loop iterator induction variable.  */
+  struct iv_class *iv;
+  /* List of MEMs that are stored in this loop.  */
+  rtx store_mems;
+  /* Array of MEMs that are used (read or written) in this loop, but
+     cannot be aliased by anything in this loop, except perhaps
+     themselves.  In other words, if mems[i] is altered during
+     the loop, it is altered by an expression that is rtx_equal_p to
+     it.  */
+  loop_mem_info *mems;
+  /* The index of the next available slot in MEMS.  */
+  int mems_idx;
+  /* The number of elements allocated in MEMS.  */
+  int mems_allocated;
+  /* Nonzero if we don't know what MEMs were changed in the current
+     loop.  This happens if the loop contains a call (in which case
+     `has_call' will also be set) or if we store into more than
+     NUM_STORES MEMs.  */
+  int unknown_address_altered;
+  /* The above doesn't count any readonly memory locations that are
+     stored.  This does.  */
+  int unknown_constant_address_altered;
+  /* Count of memory write instructions discovered in the loop.  */
+  int num_mem_sets;
+  /* The insn where the first of these was found.  */
+  rtx first_loop_store_insn;
+  /* The chain of movable insns in loop.  */
+  struct loop_movables movables;
+  /* The registers used the in loop.  */
+  struct loop_regs regs;
+  /* The induction variable information in loop.  */
+  struct loop_ivs ivs;
+  /* Nonzero if call is in pre_header extended basic block.  */
+  int pre_header_has_call;
+};
+
 /* Not really meaningful values, but at least something.  */
 #ifndef SIMULTANEOUS_PREFETCHES
 #define SIMULTANEOUS_PREFETCHES 3
@@ -170,16 +517,16 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
    The luids are like uids but increase monotonically always.
    We use them to see whether a jump comes from outside a given loop.  */
 
-int *uid_luid;
+static int *uid_luid;
 
 /* Indexed by INSN_UID, contains the ordinal giving the (innermost) loop
    number the insn is contained in.  */
 
-struct loop **uid_loop;
+static struct loop **uid_loop;
 
 /* 1 + largest uid of any insn.  */
 
-int max_uid_for_loop;
+static int max_uid_for_loop;
 
 /* Number of loops detected in current function.  Used as index to the
    next few tables.  */
@@ -188,7 +535,7 @@ static int max_loop_num;
 
 /* Bound on pseudo register number before loop optimization.
    A pseudo has valid regscan info if its number is < max_reg_before_loop.  */
-unsigned int max_reg_before_loop;
+static unsigned int max_reg_before_loop;
 
 /* The value to pass to the next call of reg_scan_update.  */
 static int loop_max_reg;
@@ -241,7 +588,7 @@ struct movable
 };
 
 
-FILE *loop_dump_stream;
+static FILE *loop_dump_stream;
 
 /* Forward declarations.  */
 
@@ -345,6 +692,18 @@ static rtx check_insn_for_bivs (struct loop *, rtx, int, int);
 static rtx gen_add_mult (rtx, rtx, rtx, rtx);
 static void loop_regs_update (const struct loop *, rtx);
 static int iv_add_mult_cost (rtx, rtx, rtx, rtx);
+static int loop_invariant_p (const struct loop *, rtx);
+static rtx loop_insn_hoist (const struct loop *, rtx);
+static void loop_iv_add_mult_emit_before (const struct loop *, rtx, rtx, rtx,
+                                         rtx, basic_block, rtx);
+static rtx loop_insn_emit_before (const struct loop *, basic_block,
+                                 rtx, rtx);
+static int loop_insn_first_p (rtx, rtx);
+static rtx get_condition_for_loop (const struct loop *, rtx);
+static void loop_iv_add_mult_sink (const struct loop *, rtx, rtx, rtx, rtx);
+static void loop_iv_add_mult_hoist (const struct loop *, rtx, rtx, rtx, rtx);
+static rtx extend_value_for_giv (struct induction *, rtx);
+static rtx loop_insn_sink (const struct loop *, rtx);
 
 static rtx loop_insn_emit_after (const struct loop *, basic_block, rtx, rtx);
 static rtx loop_call_insn_emit_before (const struct loop *, basic_block,
@@ -644,8 +1003,6 @@ scan_loop (struct loop *loop, int flags)
      since in that case saving an insn makes more difference
      and more registers are available.  */
   int threshold;
-  /* Nonzero if we are scanning instructions in a sub-loop.  */
-  int loop_depth = 0;
   int in_libcall;
 
   loop->top = 0;
@@ -738,13 +1095,8 @@ scan_loop (struct loop *loop, int flags)
   insn_count = count_insns_in_loop (loop);
 
   if (loop_dump_stream)
-    {
-      fprintf (loop_dump_stream, "\nLoop from %d to %d: %d real insns.\n",
-              INSN_UID (loop_start), INSN_UID (loop_end), insn_count);
-      if (loop->cont)
-       fprintf (loop_dump_stream, "Continue at insn %d.\n",
-                INSN_UID (loop->cont));
-    }
+    fprintf (loop_dump_stream, "\nLoop from %d to %d: %d real insns.\n",
+            INSN_UID (loop_start), INSN_UID (loop_end), insn_count);
 
   /* Scan through the loop finding insns that are safe to move.
      Set REGS->ARRAY[I].SET_IN_LOOP negative for the reg I being set, so that
@@ -1120,18 +1472,6 @@ scan_loop (struct loop *loop, int flags)
                     && NEXT_INSN (NEXT_INSN (p)) == loop_end
                     && any_uncondjump_p (p)))
        maybe_never = 1;
-      else if (NOTE_P (p))
-       {
-         /* At the virtual top of a converted loop, insns are again known to
-            be executed: logically, the loop begins here even though the exit
-            code has been duplicated.  */
-         if (NOTE_LINE_NUMBER (p) == NOTE_INSN_LOOP_VTOP && loop_depth == 0)
-           maybe_never = call_passed = 0;
-         else if (NOTE_LINE_NUMBER (p) == NOTE_INSN_LOOP_BEG)
-           loop_depth++;
-         else if (NOTE_LINE_NUMBER (p) == NOTE_INSN_LOOP_END)
-           loop_depth--;
-       }
     }
 
   /* If one movable subsumes another, ignore that other.  */
@@ -1904,7 +2244,6 @@ move_movables (struct loop *loop, struct loop_movables *movables,
             extra cost because something else was already moved.  */
 
          if (already_moved[regno]
-             || flag_move_all_movables
              || (threshold * savings * m->lifetime) >=
                 (regs->array[regno].moved_once ? insn_count * 2 : insn_count)
              || (m->forces && m->forces->done
@@ -2501,7 +2840,7 @@ count_nonfixed_reads (const struct loop *loop, rtx x)
   return value;
 }
 \f
-/* Scan a loop setting the elements `cont', `vtop', `loops_enclosed',
+/* Scan a loop setting the elements `loops_enclosed',
    `has_call', `has_nonconst_call', `has_volatile', `has_tablejump',
    `unknown_address_altered', `unknown_constant_address_altered', and
    `num_mem_sets' in LOOP.  Also, fill in the array `mems' and the
@@ -2537,8 +2876,6 @@ prescan_loop (struct loop *loop)
   loop_info->first_loop_store_insn = NULL_RTX;
   loop_info->mems_idx = 0;
   loop_info->num_mem_sets = 0;
-  /* If loop opts run twice, this was set on 1st pass for 2nd.  */
-  loop_info->preconditioned = NOTE_PRECONDITIONED (end);
 
   for (insn = start; insn && !LABEL_P (insn);
        insn = PREV_INSN (insn))
@@ -2577,30 +2914,6 @@ prescan_loop (struct loop *loop)
          loop_info->has_call = 1;
          if (can_throw_internal (insn))
            loop_info->has_multiple_exit_targets = 1;
-
-         /* Calls initializing constant objects have CLOBBER of MEM /u in the
-            attached FUNCTION_USAGE expression list, not accounted for by the
-            code above. We should note these to avoid missing dependencies in
-            later references.  */
-         {
-           rtx fusage_entry;
-
-           for (fusage_entry = CALL_INSN_FUNCTION_USAGE (insn);
-                fusage_entry; fusage_entry = XEXP (fusage_entry, 1))
-             {
-               rtx fusage = XEXP (fusage_entry, 0);
-
-               if (GET_CODE (fusage) == CLOBBER
-                   && MEM_P (XEXP (fusage, 0))
-                   && RTX_UNCHANGING_P (XEXP (fusage, 0)))
-                 {
-                   note_stores (fusage, note_addr_stored, loop_info);
-                   if (! loop_info->first_loop_store_insn
-                       && loop_info->store_mems)
-                     loop_info->first_loop_store_insn = insn;
-                 }
-             }
-         }
          break;
 
        case JUMP_INSN:
@@ -2707,8 +3020,7 @@ prescan_loop (struct loop *loop)
   if (loop_info->unknown_constant_address_altered)
     {
       rtx mem = gen_rtx_MEM (BLKmode, const0_rtx);
-
-      RTX_UNCHANGING_P (mem) = 1;
+      MEM_READONLY_P (mem) = 1;
       loop_info->store_mems
        = gen_rtx_EXPR_LIST (VOIDmode, mem, loop_info->store_mems);
     }
@@ -2766,14 +3078,6 @@ find_and_verify_loops (rtx f, struct loops *loops)
            current_loop = next_loop;
            break;
 
-         case NOTE_INSN_LOOP_CONT:
-           current_loop->cont = insn;
-           break;
-
-         case NOTE_INSN_LOOP_VTOP:
-           current_loop->vtop = insn;
-           break;
-
          case NOTE_INSN_LOOP_END:
            if (! current_loop)
              abort ();
@@ -3241,7 +3545,7 @@ note_addr_stored (rtx x, rtx y ATTRIBUTE_UNUSED,
   /* BLKmode MEM means all memory is clobbered.  */
   if (GET_MODE (x) == BLKmode)
     {
-      if (RTX_UNCHANGING_P (x))
+      if (MEM_READONLY_P (x))
        loop_info->unknown_constant_address_altered = 1;
       else
        loop_info->unknown_address_altered = 1;
@@ -3254,7 +3558,7 @@ note_addr_stored (rtx x, rtx y ATTRIBUTE_UNUSED,
 }
 
 /* X is a value modified by an INSN that references a biv inside a loop
-   exit test (ie, X is somehow related to the value of the biv).  If X
+   exit test (i.e., X is somehow related to the value of the biv).  If X
    is a pseudo that is used more than once, then the biv is (effectively)
    used more than once.  DATA is a pointer to a loop_regs structure.  */
 
@@ -3290,7 +3594,7 @@ note_set_pseudo_multiple_uses (rtx x, rtx y ATTRIBUTE_UNUSED, void *data)
    A memory ref is invariant if it is not volatile and does not conflict
    with anything stored in `loop_info->store_mems'.  */
 
-int
+static int
 loop_invariant_p (const struct loop *loop, rtx x)
 {
   struct loop_info *loop_info = LOOP_INFO (loop);
@@ -3313,19 +3617,7 @@ loop_invariant_p (const struct loop *loop, rtx x)
       return 1;
 
     case LABEL_REF:
-      /* A LABEL_REF is normally invariant, however, if we are unrolling
-        loops, and this label is inside the loop, then it isn't invariant.
-        This is because each unrolled copy of the loop body will have
-        a copy of this label.  If this was invariant, then an insn loading
-        the address of this label into a register might get moved outside
-        the loop, and then each loop body would end up using the same label.
-
-        We don't know the loop bounds here though, so just fail for all
-        labels.  */
-      if (flag_old_unroll_loops)
-       return 0;
-      else
-       return 1;
+      return 1;
 
     case PC:
     case CC0:
@@ -3333,9 +3625,6 @@ loop_invariant_p (const struct loop *loop, rtx x)
       return 0;
 
     case REG:
-      /* We used to check RTX_UNCHANGING_P (x) here, but that is invalid
-        since the reg might be set by initialization within the loop.  */
-
       if ((x == frame_pointer_rtx || x == hard_frame_pointer_rtx
           || x == arg_pointer_rtx || x == pic_offset_table_rtx)
          && ! current_function_has_nonlocal_goto)
@@ -4288,6 +4577,56 @@ static rtx addr_placeholder;
    was rerun in loop_optimize whenever a register was added or moved.
    Also, some of the optimizations could be a little less conservative.  */
 \f
+/* Searches the insns between INSN and LOOP->END.  Returns 1 if there
+   is a backward branch in that range that branches to somewhere between
+   LOOP->START and INSN.  Returns 0 otherwise.  */
+
+/* ??? This is quadratic algorithm.  Could be rewritten to be linear.
+   In practice, this is not a problem, because this function is seldom called,
+   and uses a negligible amount of CPU time on average.  */
+
+static int
+back_branch_in_range_p (const struct loop *loop, rtx insn)
+{
+  rtx p, q, target_insn;
+  rtx loop_start = loop->start;
+  rtx loop_end = loop->end;
+  rtx orig_loop_end = loop->end;
+
+  /* Stop before we get to the backward branch at the end of the loop.  */
+  loop_end = prev_nonnote_insn (loop_end);
+  if (BARRIER_P (loop_end))
+    loop_end = PREV_INSN (loop_end);
+
+  /* Check in case insn has been deleted, search forward for first non
+     deleted insn following it.  */
+  while (INSN_DELETED_P (insn))
+    insn = NEXT_INSN (insn);
+
+  /* Check for the case where insn is the last insn in the loop.  Deal
+     with the case where INSN was a deleted loop test insn, in which case
+     it will now be the NOTE_LOOP_END.  */
+  if (insn == loop_end || insn == orig_loop_end)
+    return 0;
+
+  for (p = NEXT_INSN (insn); p != loop_end; p = NEXT_INSN (p))
+    {
+      if (JUMP_P (p))
+       {
+         target_insn = JUMP_LABEL (p);
+
+         /* Search from loop_start to insn, to see if one of them is
+            the target_insn.  We can't use INSN_LUID comparisons here,
+            since insn may not have an LUID entry.  */
+         for (q = loop_start; q != insn; q = NEXT_INSN (q))
+           if (q == target_insn)
+             return 1;
+       }
+    }
+
+  return 0;
+}
+
 /* 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.
@@ -4298,13 +4637,13 @@ static rtx addr_placeholder;
    MAYBE_MULTIPLE is 1 if current insn may be executed more than once for every
    loop iteration.
  */
-void
+typedef rtx (*loop_insn_callback) (struct loop *, rtx, int, int);
+static void
 for_each_insn_in_loop (struct loop *loop, loop_insn_callback fncall)
 {
   int not_every_iteration = 0;
   int maybe_multiple = 0;
   int past_loop_latch = 0;
-  int loop_depth = 0;
   rtx p;
 
   /* If loop_scan_start points to the loop exit test, we have to be wary of
@@ -4387,24 +4726,6 @@ for_each_insn_in_loop (struct loop *loop, loop_insn_callback fncall)
            not_every_iteration = 1;
        }
 
-      else if (NOTE_P (p))
-       {
-         /* At the virtual top of a converted loop, insns are again known to
-            be executed each iteration: logically, the loop begins here
-            even though the exit code has been duplicated.
-
-            Insns are also again known to be executed each iteration at
-            the LOOP_CONT note.  */
-         if ((NOTE_LINE_NUMBER (p) == NOTE_INSN_LOOP_VTOP
-              || NOTE_LINE_NUMBER (p) == NOTE_INSN_LOOP_CONT)
-             && loop_depth == 0)
-           not_every_iteration = 0;
-         else if (NOTE_LINE_NUMBER (p) == NOTE_INSN_LOOP_BEG)
-           loop_depth++;
-         else if (NOTE_LINE_NUMBER (p) == NOTE_INSN_LOOP_END)
-           loop_depth--;
-       }
-
       /* Note if we pass a loop latch.  If we do, then we can not clear
          NOT_EVERY_ITERATION below when we pass the last CODE_LABEL in
          a loop since a jump before the last CODE_LABEL may have started
@@ -4430,8 +4751,7 @@ for_each_insn_in_loop (struct loop *loop, loop_insn_callback fncall)
       if (not_every_iteration
          && !past_loop_latch
          && LABEL_P (p)
-         && no_labels_between_p (p, loop->end)
-         && loop_insn_first_p (p, loop->cont))
+         && no_labels_between_p (p, loop->end))
        not_every_iteration = 0;
     }
 }
@@ -4621,6 +4941,238 @@ loop_givs_check (struct loop *loop)
     }
 }
 
+/* Try to generate the simplest rtx for the expression
+   (PLUS (MULT mult1 mult2) add1).  This is used to calculate the initial
+   value of giv's.  */
+
+static rtx
+fold_rtx_mult_add (rtx mult1, rtx mult2, rtx add1, enum machine_mode mode)
+{
+  rtx temp, mult_res;
+  rtx result;
+
+  /* The modes must all be the same.  This should always be true.  For now,
+     check to make sure.  */
+  if ((GET_MODE (mult1) != mode && GET_MODE (mult1) != VOIDmode)
+      || (GET_MODE (mult2) != mode && GET_MODE (mult2) != VOIDmode)
+      || (GET_MODE (add1) != mode && GET_MODE (add1) != VOIDmode))
+    abort ();
+
+  /* Ensure that if at least one of mult1/mult2 are constant, then mult2
+     will be a constant.  */
+  if (GET_CODE (mult1) == CONST_INT)
+    {
+      temp = mult2;
+      mult2 = mult1;
+      mult1 = temp;
+    }
+
+  mult_res = simplify_binary_operation (MULT, mode, mult1, mult2);
+  if (! mult_res)
+    mult_res = gen_rtx_MULT (mode, mult1, mult2);
+
+  /* Again, put the constant second.  */
+  if (GET_CODE (add1) == CONST_INT)
+    {
+      temp = add1;
+      add1 = mult_res;
+      mult_res = temp;
+    }
+
+  result = simplify_binary_operation (PLUS, mode, add1, mult_res);
+  if (! result)
+    result = gen_rtx_PLUS (mode, add1, mult_res);
+
+  return result;
+}
+
+/* Searches the list of induction struct's for the biv BL, to try to calculate
+   the total increment value for one iteration of the loop as a constant.
+
+   Returns the increment value as an rtx, simplified as much as possible,
+   if it can be calculated.  Otherwise, returns 0.  */
+
+static rtx
+biv_total_increment (const struct iv_class *bl)
+{
+  struct induction *v;
+  rtx result;
+
+  /* For increment, must check every instruction that sets it.  Each
+     instruction must be executed only once each time through the loop.
+     To verify this, we check that the insn is always executed, and that
+     there are no backward branches after the insn that branch to before it.
+     Also, the insn must have a mult_val of one (to make sure it really is
+     an increment).  */
+
+  result = const0_rtx;
+  for (v = bl->biv; v; v = v->next_iv)
+    {
+      if (v->always_computable && v->mult_val == const1_rtx
+         && ! 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;
+    }
+
+  return result;
+}
+
+/* Try to prove that the register is dead after the loop exits.  Trace every
+   loop exit looking for an insn that will always be executed, which sets
+   the register to some value, and appears before the first use of the register
+   is found.  If successful, then return 1, otherwise return 0.  */
+
+/* ?? Could be made more intelligent in the handling of jumps, so that
+   it can search past if statements and other similar structures.  */
+
+static int
+reg_dead_after_loop (const struct loop *loop, rtx reg)
+{
+  rtx insn, label;
+  int jump_count = 0;
+  int label_count = 0;
+
+  /* In addition to checking all exits of this loop, we must also check
+     all exits of inner nested loops that would exit this loop.  We don't
+     have any way to identify those, so we just give up if there are any
+     such inner loop exits.  */
+
+  for (label = loop->exit_labels; label; label = LABEL_NEXTREF (label))
+    label_count++;
+
+  if (label_count != loop->exit_count)
+    return 0;
+
+  /* HACK: Must also search the loop fall through exit, create a label_ref
+     here which points to the loop->end, and append the loop_number_exit_labels
+     list to it.  */
+  label = gen_rtx_LABEL_REF (VOIDmode, loop->end);
+  LABEL_NEXTREF (label) = loop->exit_labels;
+
+  for (; label; label = LABEL_NEXTREF (label))
+    {
+      /* Succeed if find an insn which sets the biv or if reach end of
+        function.  Fail if find an insn that uses the biv, or if come to
+        a conditional jump.  */
+
+      insn = NEXT_INSN (XEXP (label, 0));
+      while (insn)
+       {
+         if (INSN_P (insn))
+           {
+             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 (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);
+       }
+    }
+
+  /* Success, the register is dead on all loop exits.  */
+  return 1;
+}
+
+/* Try to calculate the final value of the biv, the value it will have at
+   the end of the loop.  If we can do it, return that value.  */
+
+static rtx
+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;
+
+  /* ??? This only works for MODE_INT biv's.  Reject all others for now.  */
+
+  if (GET_MODE_CLASS (bl->biv->mode) != MODE_INT)
+    return 0;
+
+  /* The final value for reversed bivs must be calculated differently than
+     for ordinary bivs.  In this case, there is already an insn after the
+     loop which sets this biv's final value (if necessary), and there are
+     no other loop exits, so we can return any value.  */
+  if (bl->reversed)
+    {
+      if (loop_dump_stream)
+       fprintf (loop_dump_stream,
+                "Final biv value for %d, reversed biv.\n", bl->regno);
+
+      return const0_rtx;
+    }
+
+  /* Try to calculate the final value as initial value + (number of iterations
+     * increment).  For this to work, increment must be invariant, 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 initial
+     value of the biv must be invariant.  */
+
+  if (n_iterations != 0
+      && ! loop->exit_count
+      && loop_invariant_p (loop, bl->initial_value))
+    {
+      increment = biv_total_increment (bl);
+
+      if (increment && loop_invariant_p (loop, increment))
+       {
+         /* Can calculate the loop exit value, emit insns after loop
+            end to calculate this value into a temporary register in
+            case it is needed later.  */
+
+         tem = gen_reg_rtx (bl->biv->mode);
+         record_base_value (REGNO (tem), bl->biv->add_val, 0);
+         loop_iv_add_mult_sink (loop, increment, GEN_INT (n_iterations),
+                                bl->initial_value, tem);
+
+         if (loop_dump_stream)
+           fprintf (loop_dump_stream,
+                    "Final biv value for %d, calculated.\n", bl->regno);
+
+         return tem;
+       }
+    }
+
+  /* Check to see if the biv is dead at all loop exits.  */
+  if (reg_dead_after_loop (loop, bl->biv->src_reg))
+    {
+      if (loop_dump_stream)
+       fprintf (loop_dump_stream,
+                "Final biv value for %d, biv dead after loop exit.\n",
+                bl->regno);
+
+      return const0_rtx;
+    }
+
+  return 0;
+}
 
 /* Return nonzero if it is possible to eliminate the biv BL provided
    all givs are reduced.  This is possible if either the reg is not
@@ -5028,42 +5580,692 @@ loop_giv_reduce_benefit (struct loop *loop ATTRIBUTE_UNUSED,
     }
 #endif
 
-  return benefit;
-}
+  return benefit;
+}
+
+
+/* Free IV structures for LOOP.  */
+
+static void
+loop_ivs_free (struct loop *loop)
+{
+  struct loop_ivs *ivs = LOOP_IVS (loop);
+  struct iv_class *iv = ivs->list;
+
+  free (ivs->regs);
+
+  while (iv)
+    {
+      struct iv_class *next = iv->next;
+      struct induction *induction;
+      struct induction *next_induction;
+
+      for (induction = iv->biv; induction; induction = next_induction)
+       {
+         next_induction = induction->next_iv;
+         free (induction);
+       }
+      for (induction = iv->giv; induction; induction = next_induction)
+       {
+         next_induction = induction->next_iv;
+         free (induction);
+       }
+
+      free (iv);
+      iv = next;
+    }
+}
+
+/* Look back before LOOP->START for the insn that sets REG and return
+   the equivalent constant if there is a REG_EQUAL note otherwise just
+   the SET_SRC of REG.  */
+
+static rtx
+loop_find_equiv_value (const struct loop *loop, rtx reg)
+{
+  rtx loop_start = loop->start;
+  rtx insn, set;
+  rtx ret;
+
+  ret = reg;
+  for (insn = PREV_INSN (loop_start); insn; insn = PREV_INSN (insn))
+    {
+      if (LABEL_P (insn))
+       break;
+
+      else if (INSN_P (insn) && reg_set_p (reg, insn))
+       {
+         /* We found the last insn before the loop that sets the register.
+            If it sets the entire register, and has a REG_EQUAL note,
+            then use the value of the REG_EQUAL note.  */
+         if ((set = single_set (insn))
+             && (SET_DEST (set) == reg))
+           {
+             rtx note = find_reg_note (insn, REG_EQUAL, NULL_RTX);
+
+             /* Only use the REG_EQUAL note if it is a constant.
+                Other things, divide in particular, will cause
+                problems later if we use them.  */
+             if (note && GET_CODE (XEXP (note, 0)) != EXPR_LIST
+                 && CONSTANT_P (XEXP (note, 0)))
+               ret = XEXP (note, 0);
+             else
+               ret = SET_SRC (set);
+
+             /* We cannot do this if it changes between the
+                assignment and loop start though.  */
+             if (modified_between_p (ret, insn, loop_start))
+               ret = reg;
+           }
+         break;
+       }
+    }
+  return ret;
+}
+
+/* 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 (rtx op0, rtx op1)
+{
+  if ((REG_P (op0) || GET_CODE (op0) == PLUS)
+      && (REG_P (op1) || GET_CODE (op1) == PLUS))
+    {
+      rtx op00;
+      rtx op01;
+      rtx op10;
+      rtx op11;
+
+      if (GET_CODE (op0) == PLUS)
+       op01 = XEXP (op0, 1), op00 = XEXP (op0, 0);
+      else
+       op01 = const0_rtx, op00 = op0;
+
+      if (GET_CODE (op1) == PLUS)
+       op11 = XEXP (op1, 1), op10 = XEXP (op1, 0);
+      else
+       op11 = const0_rtx, op10 = op1;
+
+      /* Find and return common register term if present.  */
+      if (REG_P (op00) && (op00 == op10 || op00 == op11))
+       return op00;
+      else if (REG_P (op01) && (op01 == op10 || op01 == op11))
+       return op01;
+    }
+
+  /* No common register term found.  */
+  return NULL_RTX;
+}
+
+/* Determine the loop iterator and calculate the number of loop
+   iterations.  Returns the exact number of loop iterations if it can
+   be calculated, otherwise returns zero.  */
+
+static unsigned HOST_WIDE_INT
+loop_iterations (struct loop *loop)
+{
+  struct loop_info *loop_info = LOOP_INFO (loop);
+  struct loop_ivs *ivs = LOOP_IVS (loop);
+  rtx comparison, comparison_value;
+  rtx iteration_var, initial_value, increment, final_value;
+  enum rtx_code comparison_code;
+  HOST_WIDE_INT inc;
+  unsigned HOST_WIDE_INT abs_inc;
+  unsigned HOST_WIDE_INT abs_diff;
+  int off_by_one;
+  int increment_dir;
+  int unsigned_p, compare_dir, final_larger;
+  rtx last_loop_insn;
+  struct iv_class *bl;
+
+  loop_info->n_iterations = 0;
+  loop_info->initial_value = 0;
+  loop_info->initial_equiv_value = 0;
+  loop_info->comparison_value = 0;
+  loop_info->final_value = 0;
+  loop_info->final_equiv_value = 0;
+  loop_info->increment = 0;
+  loop_info->iteration_var = 0;
+  loop_info->iv = 0;
+
+  /* We used to use prev_nonnote_insn here, but that fails because it might
+     accidentally get the branch for a contained loop if the branch for this
+     loop was deleted.  We can only trust branches immediately before the
+     loop_end.  */
+  last_loop_insn = PREV_INSN (loop->end);
+
+  /* ??? 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 (!JUMP_P (last_loop_insn))
+    {
+      if (loop_dump_stream)
+       fprintf (loop_dump_stream,
+                "Loop iterations: No final conditional branch found.\n");
+      return 0;
+    }
+
+  /* If there is a more than a single jump to the top of the loop
+     we cannot (easily) determine the iteration count.  */
+  if (LABEL_NUSES (JUMP_LABEL (last_loop_insn)) > 1)
+    {
+      if (loop_dump_stream)
+       fprintf (loop_dump_stream,
+                "Loop iterations: Loop has multiple back edges.\n");
+      return 0;
+    }
+
+  /* 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.  */
+
+  comparison = get_condition_for_loop (loop, last_loop_insn);
+  if (comparison == 0)
+    {
+      if (loop_dump_stream)
+       fprintf (loop_dump_stream,
+                "Loop iterations: No final comparison found.\n");
+      return 0;
+    }
+
+  /* ??? Get_condition may switch position of induction variable and
+     invariant register when it canonicalizes the comparison.  */
+
+  comparison_code = GET_CODE (comparison);
+  iteration_var = XEXP (comparison, 0);
+  comparison_value = XEXP (comparison, 1);
+
+  if (!REG_P (iteration_var))
+    {
+      if (loop_dump_stream)
+       fprintf (loop_dump_stream,
+                "Loop iterations: Comparison not against register.\n");
+      return 0;
+    }
+
+  /* The only new registers that are created before loop iterations
+     are givs made from biv increments or registers created by
+     load_mems.  In the latter case, it is possible that try_copy_prop
+     will propagate a new pseudo into the old iteration register but
+     this will be marked by having the REG_USERVAR_P bit set.  */
+
+  if ((unsigned) REGNO (iteration_var) >= ivs->n_regs
+      && ! REG_USERVAR_P (iteration_var))
+    abort ();
+
+  /* Determine the initial value of the iteration variable, and the amount
+     that it is incremented each loop.  Use the tables constructed by
+     the strength reduction pass to calculate these values.  */
+
+  /* Clear the result values, in case no answer can be found.  */
+  initial_value = 0;
+  increment = 0;
+
+  /* The iteration variable can be either a giv or a biv.  Check to see
+     which it is, and compute the variable's initial value, and increment
+     value if possible.  */
+
+  /* If this is a new register, can't handle it since we don't have any
+     reg_iv_type entry for it.  */
+  if ((unsigned) REGNO (iteration_var) >= ivs->n_regs)
+    {
+      if (loop_dump_stream)
+       fprintf (loop_dump_stream,
+                "Loop iterations: No reg_iv_type entry for iteration var.\n");
+      return 0;
+    }
+
+  /* Reject iteration variables larger than the host wide int size, since they
+     could result in a number of iterations greater than the range of our
+     `unsigned HOST_WIDE_INT' variable loop_info->n_iterations.  */
+  else if ((GET_MODE_BITSIZE (GET_MODE (iteration_var))
+           > HOST_BITS_PER_WIDE_INT))
+    {
+      if (loop_dump_stream)
+       fprintf (loop_dump_stream,
+                "Loop iterations: Iteration var rejected because mode too large.\n");
+      return 0;
+    }
+  else if (GET_MODE_CLASS (GET_MODE (iteration_var)) != MODE_INT)
+    {
+      if (loop_dump_stream)
+       fprintf (loop_dump_stream,
+                "Loop iterations: Iteration var not an integer.\n");
+      return 0;
+    }
+
+  /* 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 ();
+
+      /* Grab initial value, only useful if it is a constant.  */
+      bl = REG_IV_CLASS (ivs, REGNO (iteration_var));
+      initial_value = bl->initial_value;
+      if (!bl->biv->always_executed || bl->biv->maybe_multiple)
+       {
+         if (loop_dump_stream)
+           fprintf (loop_dump_stream,
+                    "Loop iterations: Basic induction var not set once in each iteration.\n");
+         return 0;
+       }
+
+      increment = biv_total_increment (bl);
+    }
+  else if (REG_IV_TYPE (ivs, REGNO (iteration_var)) == GENERAL_INDUCT)
+    {
+      HOST_WIDE_INT offset = 0;
+      struct induction *v = REG_IV_INFO (ivs, REGNO (iteration_var));
+      rtx biv_initial_value;
+
+      if (REGNO (v->src_reg) >= ivs->n_regs)
+       abort ();
+
+      if (!v->always_executed || v->maybe_multiple)
+       {
+         if (loop_dump_stream)
+           fprintf (loop_dump_stream,
+                    "Loop iterations: General induction var not set once in each iteration.\n");
+         return 0;
+       }
+
+      bl = REG_IV_CLASS (ivs, REGNO (v->src_reg));
+
+      /* Increment value is mult_val times the increment value of the biv.  */
+
+      increment = biv_total_increment (bl);
+      if (increment)
+       {
+         struct induction *biv_inc;
+
+         increment = fold_rtx_mult_add (v->mult_val,
+                                        extend_value_for_giv (v, increment),
+                                        const0_rtx, v->mode);
+         /* The caller assumes that one full increment has occurred at the
+            first loop test.  But that's not true when the biv is incremented
+            after the giv is set (which is the usual case), e.g.:
+            i = 6; do {;} while (i++ < 9) .
+            Therefore, we bias the initial value by subtracting the amount of
+            the increment that occurs between the giv set and the giv test.  */
+         for (biv_inc = bl->biv; biv_inc; biv_inc = biv_inc->next_iv)
+           {
+             if (loop_insn_first_p (v->insn, biv_inc->insn))
+               {
+                 if (REG_P (biv_inc->add_val))
+                   {
+                     if (loop_dump_stream)
+                       fprintf (loop_dump_stream,
+                                "Loop iterations: Basic induction var add_val is REG %d.\n",
+                                REGNO (biv_inc->add_val));
+                       return 0;
+                   }
+
+                 /* If we have already counted it, skip it.  */
+                 if (biv_inc->same)
+                   continue;
+
+                 offset -= INTVAL (biv_inc->add_val);
+               }
+           }
+       }
+      if (loop_dump_stream)
+       fprintf (loop_dump_stream,
+                "Loop iterations: Giv iterator, initial value bias %ld.\n",
+                (long) offset);
+
+      /* Initial value is mult_val times the biv's initial value plus
+        add_val.  Only useful if it is a constant.  */
+      biv_initial_value = extend_value_for_giv (v, bl->initial_value);
+      initial_value
+       = fold_rtx_mult_add (v->mult_val,
+                            plus_constant (biv_initial_value, offset),
+                            v->add_val, v->mode);
+    }
+  else
+    {
+      if (loop_dump_stream)
+       fprintf (loop_dump_stream,
+                "Loop iterations: Not basic or general induction var.\n");
+      return 0;
+    }
+
+  if (initial_value == 0)
+    return 0;
+
+  unsigned_p = 0;
+  off_by_one = 0;
+  switch (comparison_code)
+    {
+    case LEU:
+      unsigned_p = 1;
+    case LE:
+      compare_dir = 1;
+      off_by_one = 1;
+      break;
+    case GEU:
+      unsigned_p = 1;
+    case GE:
+      compare_dir = -1;
+      off_by_one = -1;
+      break;
+    case EQ:
+      /* Cannot determine loop iterations with this case.  */
+      compare_dir = 0;
+      break;
+    case LTU:
+      unsigned_p = 1;
+    case LT:
+      compare_dir = 1;
+      break;
+    case GTU:
+      unsigned_p = 1;
+    case GT:
+      compare_dir = -1;
+      break;
+    case NE:
+      compare_dir = 0;
+      break;
+    default:
+      abort ();
+    }
+
+  /* If the comparison value is an invariant register, then try to find
+     its value from the insns before the start of the loop.  */
+
+  final_value = comparison_value;
+  if (REG_P (comparison_value)
+      && loop_invariant_p (loop, comparison_value))
+    {
+      final_value = loop_find_equiv_value (loop, comparison_value);
+
+      /* If we don't get an invariant final value, we are better
+        off with the original register.  */
+      if (! loop_invariant_p (loop, final_value))
+       final_value = comparison_value;
+    }
+
+  /* Calculate the approximate final value of the induction variable
+     (on the last successful iteration).  The exact final value
+     depends on the branch operator, and increment sign.  It will be
+     wrong if the iteration variable is not incremented by one each
+     time through the loop and (comparison_value + off_by_one -
+     initial_value) % increment != 0.
+     ??? Note that the final_value may overflow and thus final_larger
+     will be bogus.  A potentially infinite loop will be classified
+     as immediate, e.g. for (i = 0x7ffffff0; i <= 0x7fffffff; i++)  */
+  if (off_by_one)
+    final_value = plus_constant (final_value, off_by_one);
+
+  /* Save the calculated values describing this loop's bounds, in case
+     precondition_loop_p will need them later.  These values can not be
+     recalculated inside precondition_loop_p because strength reduction
+     optimizations may obscure the loop's structure.
+
+     These values are only required by precondition_loop_p and insert_bct
+     whenever the number of iterations cannot be computed at compile time.
+     Only the difference between final_value and initial_value is
+     important.  Note that final_value is only approximate.  */
+  loop_info->initial_value = initial_value;
+  loop_info->comparison_value = comparison_value;
+  loop_info->final_value = plus_constant (comparison_value, off_by_one);
+  loop_info->increment = increment;
+  loop_info->iteration_var = iteration_var;
+  loop_info->comparison_code = comparison_code;
+  loop_info->iv = bl;
+
+  /* Try to determine the iteration count for loops such
+     as (for i = init; i < init + const; i++).  When running the
+     loop optimization twice, the first pass often converts simple
+     loops into this form.  */
+
+  if (REG_P (initial_value))
+    {
+      rtx reg1;
+      rtx reg2;
+      rtx const2;
+
+      reg1 = initial_value;
+      if (GET_CODE (final_value) == PLUS)
+       reg2 = XEXP (final_value, 0), const2 = XEXP (final_value, 1);
+      else
+       reg2 = final_value, const2 = const0_rtx;
+
+      /* Check for initial_value = reg1, final_value = reg2 + const2,
+        where reg1 != reg2.  */
+      if (REG_P (reg2) && reg2 != reg1)
+       {
+         rtx temp;
+
+         /* Find what reg1 is equivalent to.  Hopefully it will
+            either be reg2 or reg2 plus a constant.  */
+         temp = loop_find_equiv_value (loop, reg1);
 
+         if (find_common_reg_term (temp, reg2))
+           initial_value = temp;
+         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
+                the latter case for now since it is not so common.  */
+             temp = loop_find_equiv_value (loop, reg2);
+
+             if (temp == loop_info->iteration_var)
+               temp = initial_value;
+             if (temp == reg1)
+               final_value = (const2 == const0_rtx)
+                 ? reg1 : gen_rtx_PLUS (GET_MODE (reg1), reg1, const2);
+           }
+       }
+    }
 
-/* Free IV structures for LOOP.  */
+  loop_info->initial_equiv_value = initial_value;
+  loop_info->final_equiv_value = final_value;
 
-static void
-loop_ivs_free (struct loop *loop)
-{
-  struct loop_ivs *ivs = LOOP_IVS (loop);
-  struct iv_class *iv = ivs->list;
+  /* For EQ comparison loops, we don't have a valid final value.
+     Check this now so that we won't leave an invalid value if we
+     return early for any other reason.  */
+  if (comparison_code == EQ)
+    loop_info->final_equiv_value = loop_info->final_value = 0;
 
-  free (ivs->regs);
+  if (increment == 0)
+    {
+      if (loop_dump_stream)
+       fprintf (loop_dump_stream,
+                "Loop iterations: Increment value can't be calculated.\n");
+      return 0;
+    }
 
-  while (iv)
+  if (GET_CODE (increment) != CONST_INT)
     {
-      struct iv_class *next = iv->next;
-      struct induction *induction;
-      struct induction *next_induction;
+      /* 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 (REG_P (increment) || GET_CODE (increment) == SUBREG)
+       increment = loop_find_equiv_value (loop, increment);
 
-      for (induction = iv->biv; induction; induction = next_induction)
+      if (GET_CODE (increment) != CONST_INT)
        {
-         next_induction = induction->next_iv;
-         free (induction);
+         if (loop_dump_stream)
+           {
+             fprintf (loop_dump_stream,
+                      "Loop iterations: Increment value not constant ");
+             print_simple_rtl (loop_dump_stream, increment);
+             fprintf (loop_dump_stream, ".\n");
+           }
+         return 0;
        }
-      for (induction = iv->giv; induction; induction = next_induction)
+      loop_info->increment = increment;
+    }
+
+  if (GET_CODE (initial_value) != CONST_INT)
+    {
+      if (loop_dump_stream)
        {
-         next_induction = induction->next_iv;
-         free (induction);
+         fprintf (loop_dump_stream,
+                  "Loop iterations: Initial value not constant ");
+         print_simple_rtl (loop_dump_stream, initial_value);
+         fprintf (loop_dump_stream, ".\n");
+       }
+      return 0;
+    }
+  else if (GET_CODE (final_value) != CONST_INT)
+    {
+      if (loop_dump_stream)
+       {
+         fprintf (loop_dump_stream,
+                  "Loop iterations: Final value not constant ");
+         print_simple_rtl (loop_dump_stream, final_value);
+         fprintf (loop_dump_stream, ".\n");
+       }
+      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;
 
-      free (iv);
-      iv = next;
+      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)
+    final_larger
+      = ((unsigned HOST_WIDE_INT) INTVAL (final_value)
+        > (unsigned HOST_WIDE_INT) INTVAL (initial_value))
+       - ((unsigned HOST_WIDE_INT) INTVAL (final_value)
+          < (unsigned HOST_WIDE_INT) INTVAL (initial_value));
+  else
+    final_larger = (INTVAL (final_value) > INTVAL (initial_value))
+      - (INTVAL (final_value) < INTVAL (initial_value));
+
+  if (INTVAL (increment) > 0)
+    increment_dir = 1;
+  else if (INTVAL (increment) == 0)
+    increment_dir = 0;
+  else
+    increment_dir = -1;
+
+  /* There are 27 different cases: compare_dir = -1, 0, 1;
+     final_larger = -1, 0, 1; increment_dir = -1, 0, 1.
+     There are 4 normal cases, 4 reverse cases (where the iteration variable
+     will overflow before the loop exits), 4 infinite loop cases, and 15
+     immediate exit (0 or 1 iteration depending on loop type) cases.
+     Only try to optimize the normal cases.  */
+
+  /* (compare_dir/final_larger/increment_dir)
+     Normal cases: (0/-1/-1), (0/1/1), (-1/-1/-1), (1/1/1)
+     Reverse cases: (0/-1/1), (0/1/-1), (-1/-1/1), (1/1/-1)
+     Infinite loops: (0/-1/0), (0/1/0), (-1/-1/0), (1/1/0)
+     Immediate exit: (0/0/X), (-1/0/X), (-1/1/X), (1/0/X), (1/-1/X) */
+
+  /* ?? If the meaning of reverse loops (where the iteration variable
+     will overflow before the loop exits) is undefined, then could
+     eliminate all of these special checks, and just always assume
+     the loops are normal/immediate/infinite.  Note that this means
+     the sign of increment_dir does not have to be known.  Also,
+     since it does not really hurt if immediate exit loops or infinite loops
+     are optimized, then that case could be ignored also, and hence all
+     loops can be optimized.
+
+     According to ANSI Spec, the reverse loop case result is undefined,
+     because the action on overflow is undefined.
+
+     See also the special test for NE loops below.  */
+
+  if (final_larger == increment_dir && final_larger != 0
+      && (final_larger == compare_dir || compare_dir == 0))
+    /* Normal case.  */
+    ;
+  else
+    {
+      if (loop_dump_stream)
+       fprintf (loop_dump_stream, "Loop iterations: Not normal loop.\n");
+      return 0;
     }
-}
 
+  /* Calculate the number of iterations, final_value is only an approximation,
+     so correct for that.  Note that abs_diff and n_iterations are
+     unsigned, because they can be as large as 2^n - 1.  */
+
+  inc = INTVAL (increment);
+  if (inc > 0)
+    {
+      abs_diff = INTVAL (final_value) - INTVAL (initial_value);
+      abs_inc = inc;
+    }
+  else if (inc < 0)
+    {
+      abs_diff = INTVAL (initial_value) - INTVAL (final_value);
+      abs_inc = -inc;
+    }
+  else
+    abort ();
+
+  /* Given that iteration_var is going to iterate over its own mode,
+     not HOST_WIDE_INT, disregard higher bits that might have come
+     into the picture due to sign extension of initial and final
+     values.  */
+  abs_diff &= ((unsigned HOST_WIDE_INT) 1
+              << (GET_MODE_BITSIZE (GET_MODE (iteration_var)) - 1)
+              << 1) - 1;
+
+  /* For NE tests, make sure that the iteration variable won't miss
+     the final value.  If abs_diff mod abs_incr is not zero, then the
+     iteration variable will overflow before the loop exits, and we
+     can not calculate the number of iterations.  */
+  if (compare_dir == 0 && (abs_diff % abs_inc) != 0)
+    return 0;
+
+  /* Note that the number of iterations could be calculated using
+     (abs_diff + abs_inc - 1) / abs_inc, provided care was taken to
+     handle potential overflow of the summation.  */
+  loop_info->n_iterations = abs_diff / abs_inc + ((abs_diff % abs_inc) != 0);
+  return loop_info->n_iterations;
+}
 
 /* Perform strength reduction and induction variable elimination.
 
@@ -5092,7 +6294,6 @@ strength_reduce (struct loop *loop, int flags)
   /* Map of pseudo-register replacements.  */
   rtx *reg_map = NULL;
   int reg_map_size;
-  int unrolled_insn_copies = 0;
   rtx test_reg = gen_rtx_REG (word_mode, LAST_VIRTUAL_REGISTER + 1);
   int insn_count = count_insns_in_loop (loop);
 
@@ -5107,11 +6308,6 @@ strength_reduce (struct loop *loop, int flags)
   /* Exit if there are no bivs.  */
   if (! ivs->list)
     {
-      /* Can still unroll the loop anyways, but indicate that there is no
-        strength reduction info available.  */
-      if (flags & LOOP_UNROLL)
-       unroll_loop (loop, insn_count, 0);
-
       loop_ivs_free (loop);
       return;
     }
@@ -5197,8 +6393,7 @@ strength_reduce (struct loop *loop, int flags)
             of such giv's whether or not we know they are used after the loop
             exit.  */
 
-         if (! flag_reduce_all_givs
-             && v->lifetime * threshold * benefit < insn_count
+         if (v->lifetime * threshold * benefit < insn_count
              && ! bl->reversed)
            {
              if (loop_dump_stream)
@@ -5324,43 +6519,6 @@ strength_reduce (struct loop *loop, int flags)
        INSN_CODE (p) = -1;
       }
 
-  if (loop_info->n_iterations > 0)
-    {
-      /* When we completely unroll a loop we will likely not need the increment
-        of the loop BIV and we will not need the conditional branch at the
-        end of the loop.  */
-      unrolled_insn_copies = insn_count - 2;
-
-#ifdef HAVE_cc0
-      /* When we completely unroll a loop on a HAVE_cc0 machine we will not
-        need the comparison before the conditional branch at the end of the
-        loop.  */
-      unrolled_insn_copies -= 1;
-#endif
-
-      /* We'll need one copy for each loop iteration.  */
-      unrolled_insn_copies *= loop_info->n_iterations;
-
-      /* A little slop to account for the ability to remove initialization
-        code, better CSE, and other secondary benefits of completely
-        unrolling some loops.  */
-      unrolled_insn_copies -= 1;
-
-      /* Clamp the value.  */
-      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 ((flags & LOOP_UNROLL)
-      || ((flags & LOOP_AUTO_UNROLL)
-         && loop_info->n_iterations > 0
-         && unrolled_insn_copies <= insn_count))
-    unroll_loop (loop, insn_count, 1);
-
   if (loop_dump_stream)
     fprintf (loop_dump_stream, "\n");
 
@@ -5485,7 +6643,7 @@ check_insn_for_givs (struct loop *loop, rtx p, int not_every_iteration,
 
   /* 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 (INSN_P (p))
+  if (INSN_P (p) || LABEL_P (p))
     update_giv_derive (loop, p);
   return p;
 }
@@ -5754,7 +6912,6 @@ record_giv (const struct loop *loop, struct induction *v, rtx insn,
   v->final_value = 0;
   v->same_insn = 0;
   v->auto_inc_opt = 0;
-  v->unrolled = 0;
   v->shared = 0;
 
   /* The v->always_computable field is used in update_giv_derive, to
@@ -5914,6 +7071,132 @@ record_giv (const struct loop *loop, struct induction *v, rtx insn,
     loop_giv_dump (v, loop_dump_stream, 0);
 }
 
+/* Try to calculate the final value of the giv, the value it will have at
+   the end of the loop.  If we can do it, return that value.  */
+
+static rtx
+final_giv_value (const struct loop *loop, struct induction *v)
+{
+  struct loop_ivs *ivs = LOOP_IVS (loop);
+  struct iv_class *bl;
+  rtx insn;
+  rtx increment, tem;
+  rtx seq;
+  rtx loop_end = loop->end;
+  unsigned HOST_WIDE_INT n_iterations = LOOP_INFO (loop)->n_iterations;
+
+  bl = REG_IV_CLASS (ivs, REGNO (v->src_reg));
+
+  /* The final value for givs which depend on reversed bivs must be calculated
+     differently than for ordinary givs.  In this case, there is already an
+     insn after the loop which sets this giv's final value (if necessary),
+     and there are no other loop exits, so we can return any value.  */
+  if (bl->reversed)
+    {
+      if (loop_dump_stream)
+       fprintf (loop_dump_stream,
+                "Final giv value for %d, depends on reversed biv\n",
+                REGNO (v->dest_reg));
+      return const0_rtx;
+    }
+
+  /* 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
+     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
+     only one exit for this to work, but the loop iterations does not need
+     to be known.  */
+
+  if (n_iterations != 0
+      && ! 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
+        then.  However, this fails if the biv is subsequently eliminated.
+        Perhaps determine whether biv's are eliminable before trying to
+        determine whether giv's are replaceable so that we can use the
+        biv value here if it is not eliminable.  */
+
+      /* We are emitting code after the end of the loop, so we must make
+        sure that bl->initial_value is still valid then.  It will still
+        be valid if it is invariant.  */
+
+      increment = biv_total_increment (bl);
+
+      if (increment && loop_invariant_p (loop, increment)
+         && loop_invariant_p (loop, bl->initial_value))
+       {
+         /* Can calculate the loop exit value of its biv as
+            (n_iterations * increment) + initial_value */
+
+         /* The loop exit value of the giv is then
+            (final_biv_value - extra increments) * mult_val + add_val.
+            The extra increments are any increments to the biv which
+            occur in the loop after the giv's value is calculated.
+            We must search from the insn that sets the giv to the end
+            of the loop to calculate this value.  */
+
+         /* Put the final biv value in tem.  */
+         tem = gen_reg_rtx (v->mode);
+         record_base_value (REGNO (tem), bl->biv->add_val, 0);
+         loop_iv_add_mult_sink (loop, extend_value_for_giv (v, increment),
+                                GEN_INT (n_iterations),
+                                extend_value_for_giv (v, bl->initial_value),
+                                tem);
+
+         /* Subtract off extra increments as we find them.  */
+         for (insn = NEXT_INSN (v->insn); insn != loop_end;
+              insn = NEXT_INSN (insn))
+           {
+             struct induction *biv;
+
+             for (biv = bl->biv; biv; biv = biv->next_iv)
+               if (biv->insn == insn)
+                 {
+                   start_sequence ();
+                   tem = expand_simple_binop (GET_MODE (tem), MINUS, tem,
+                                              biv->add_val, NULL_RTX, 0,
+                                              OPTAB_LIB_WIDEN);
+                   seq = get_insns ();
+                   end_sequence ();
+                   loop_insn_sink (loop, seq);
+                 }
+           }
+
+         /* Now calculate the giv's final value.  */
+         loop_iv_add_mult_sink (loop, tem, v->mult_val, v->add_val, tem);
+
+         if (loop_dump_stream)
+           fprintf (loop_dump_stream,
+                    "Final giv value for %d, calc from biv's value.\n",
+                    REGNO (v->dest_reg));
+
+         return tem;
+       }
+    }
+
+  /* Replaceable giv's should never reach here.  */
+  if (v->replaceable)
+    abort ();
+
+  /* Check to see if the biv is dead at all loop exits.  */
+  if (reg_dead_after_loop (loop, v->dest_reg))
+    {
+      if (loop_dump_stream)
+       fprintf (loop_dump_stream,
+                "Final giv value for %d, giv dead after loop exit.\n",
+                REGNO (v->dest_reg));
+
+      return const0_rtx;
+    }
+
+  return 0;
+}
+
 /* 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
@@ -7201,7 +8484,7 @@ express_from_1 (rtx a, rtx b, rtx mult)
   return NULL_RTX;
 }
 
-rtx
+static rtx
 express_from (struct induction *g1, struct induction *g2)
 {
   rtx mult, add;
@@ -7517,7 +8800,7 @@ check_ext_dependent_givs (const struct loop *loop, struct iv_class *bl)
 
 /* Generate a version of VALUE in a mode appropriate for initializing V.  */
 
-rtx
+static rtx
 extend_value_for_giv (struct induction *v, rtx value)
 {
   rtx ext_dep = v->ext_dependent;
@@ -7779,7 +9062,7 @@ loop_regs_update (const struct loop *loop ATTRIBUTE_UNUSED, rtx seq)
    multiplicative constant, A an additive constant and REG the
    destination register.  */
 
-void
+static void
 loop_iv_add_mult_emit_before (const struct loop *loop, rtx b, rtx m, rtx a,
                              rtx reg, basic_block before_bb, rtx before_insn)
 {
@@ -7813,7 +9096,7 @@ loop_iv_add_mult_emit_before (const struct loop *loop, rtx b, rtx m, rtx a,
    constant, A an additive constant and REG the destination
    register.  */
 
-void
+static void
 loop_iv_add_mult_sink (const struct loop *loop, rtx b, rtx m, rtx a, rtx reg)
 {
   rtx seq;
@@ -7840,7 +9123,7 @@ loop_iv_add_mult_sink (const struct loop *loop, rtx b, rtx m, rtx a, rtx reg)
    value of the basic induction variable, M a multiplicative constant,
    A an additive constant and REG the destination register.  */
 
-void
+static void
 loop_iv_add_mult_hoist (const struct loop *loop, rtx b, rtx m, rtx a, rtx reg)
 {
   rtx seq;
@@ -8001,7 +9284,7 @@ check_dbra_loop (struct loop *loop, int insn_count)
 
   /* Try to compute whether the compare/branch at the loop end is one or
      two instructions.  */
-  get_condition (jump, &first_compare, false);
+  get_condition (jump, &first_compare, false, true);
   if (first_compare == jump)
     compare_and_branch = 1;
   else if (first_compare == prev_nonnote_insn (jump))
@@ -8018,8 +9301,8 @@ check_dbra_loop (struct loop *loop, int insn_count)
        sequence and see if we've got another comparison sequence.  */
 
     rtx jump1;
-    if ((jump1 = prev_nonnote_insn (first_compare)) != loop->cont)
-      if (JUMP_P (jump1))
+    if ((jump1 = prev_nonnote_insn (first_compare))
+       && JUMP_P (jump1))
        return 0;
   }
 
@@ -8332,17 +9615,6 @@ check_dbra_loop (struct loop *loop, int insn_count)
 
              /* First check if we can do a vanilla loop reversal.  */
              if (initial_value == const0_rtx
-                 /* If we have a decrement_and_branch_on_count,
-                    prefer the NE test, since this will allow that
-                    instruction to be generated.  Note that we must
-                    use a vanilla loop reversal if the biv is used to
-                    calculate a giv or has a non-counting use.  */
-#if ! defined (HAVE_decrement_and_branch_until_zero) \
-&& defined (HAVE_decrement_and_branch_on_count)
-                 && (! (add_val == 1 && loop->vtop
-                        && (bl->biv_count == 0
-                            || no_use_except_counting)))
-#endif
                  && GET_CODE (comparison_value) == CONST_INT
                     /* Now do postponed overflow checks on COMPARISON_VAL.  */
                  && ! (((comparison_val - add_val) ^ INTVAL (comparison_value))
@@ -8354,13 +9626,6 @@ check_dbra_loop (struct loop *loop, int insn_count)
                  nonneg = 1;
                  cmp_code = GE;
                }
-             else if (add_val == 1 && loop->vtop
-                      && (bl->biv_count == 0
-                          || no_use_except_counting))
-               {
-                 add_adjust = 0;
-                 cmp_code = NE;
-               }
              else
                return 0;
 
@@ -8667,7 +9932,7 @@ maybe_eliminate_biv (const struct loop *loop, struct iv_class *bl,
 /* INSN and REFERENCE are instructions in the same insn chain.
    Return nonzero if INSN is first.  */
 
-int
+static int
 loop_insn_first_p (rtx insn, rtx reference)
 {
   rtx p, q;
@@ -9173,313 +10438,13 @@ update_reg_last_use (rtx x, rtx insn)
     }
 }
 \f
-/* Given an insn INSN and condition COND, return the condition in a
-   canonical form to simplify testing by callers.  Specifically:
-
-   (1) The code will always be a comparison operation (EQ, NE, GT, etc.).
-   (2) Both operands will be machine operands; (cc0) will have been replaced.
-   (3) If an operand is a constant, it will be the second operand.
-   (4) (LE x const) will be replaced with (LT x <const+1>) and similarly
-       for GE, GEU, and LEU.
-
-   If the condition cannot be understood, or is an inequality floating-point
-   comparison which needs to be reversed, 0 will be returned.
-
-   If REVERSE is nonzero, then reverse the condition prior to canonizing it.
-
-   If EARLIEST is nonzero, it is a pointer to a place where the earliest
-   insn used in locating the condition was found.  If a replacement test
-   of the condition is desired, it should be placed in front of that
-   insn and we will be sure that the inputs are still valid.
-
-   If WANT_REG is nonzero, we wish the condition to be relative to that
-   register, if possible.  Therefore, do not canonicalize the condition
-   further.  If ALLOW_CC_MODE is nonzero, allow the condition returned 
-   to be a compare to a CC mode register.  */
-
-rtx
-canonicalize_condition (rtx insn, rtx cond, int reverse, rtx *earliest,
-                       rtx want_reg, int allow_cc_mode)
-{
-  enum rtx_code code;
-  rtx prev = insn;
-  rtx set;
-  rtx tem;
-  rtx op0, op1;
-  int reverse_code = 0;
-  enum machine_mode mode;
-
-  code = GET_CODE (cond);
-  mode = GET_MODE (cond);
-  op0 = XEXP (cond, 0);
-  op1 = XEXP (cond, 1);
-
-  if (reverse)
-    code = reversed_comparison_code (cond, insn);
-  if (code == UNKNOWN)
-    return 0;
-
-  if (earliest)
-    *earliest = insn;
-
-  /* If we are comparing a register with zero, see if the register is set
-     in the previous insn to a COMPARE or a comparison operation.  Perform
-     the same tests as a function of STORE_FLAG_VALUE as find_comparison_args
-     in cse.c  */
-
-  while ((GET_RTX_CLASS (code) == RTX_COMPARE
-         || GET_RTX_CLASS (code) == RTX_COMM_COMPARE)
-        && op1 == CONST0_RTX (GET_MODE (op0))
-        && op0 != want_reg)
-    {
-      /* Set nonzero when we find something of interest.  */
-      rtx x = 0;
-
-#ifdef HAVE_cc0
-      /* If comparison with cc0, import actual comparison from compare
-        insn.  */
-      if (op0 == cc0_rtx)
-       {
-         if ((prev = prev_nonnote_insn (prev)) == 0
-             || !NONJUMP_INSN_P (prev)
-             || (set = single_set (prev)) == 0
-             || SET_DEST (set) != cc0_rtx)
-           return 0;
-
-         op0 = SET_SRC (set);
-         op1 = CONST0_RTX (GET_MODE (op0));
-         if (earliest)
-           *earliest = prev;
-       }
-#endif
-
-      /* If this is a COMPARE, pick up the two things being compared.  */
-      if (GET_CODE (op0) == COMPARE)
-       {
-         op1 = XEXP (op0, 1);
-         op0 = XEXP (op0, 0);
-         continue;
-       }
-      else if (!REG_P (op0))
-       break;
-
-      /* Go back to the previous insn.  Stop if it is not an INSN.  We also
-        stop if it isn't a single set or if it has a REG_INC note because
-        we don't want to bother dealing with it.  */
-
-      if ((prev = prev_nonnote_insn (prev)) == 0
-         || !NONJUMP_INSN_P (prev)
-         || FIND_REG_INC_NOTE (prev, NULL_RTX))
-       break;
-
-      set = set_of (op0, prev);
-
-      if (set
-         && (GET_CODE (set) != SET
-             || !rtx_equal_p (SET_DEST (set), op0)))
-       break;
-
-      /* If this is setting OP0, get what it sets it to if it looks
-        relevant.  */
-      if (set)
-       {
-         enum machine_mode inner_mode = GET_MODE (SET_DEST (set));
-#ifdef FLOAT_STORE_FLAG_VALUE
-         REAL_VALUE_TYPE fsfv;
-#endif
-
-         /* ??? We may not combine comparisons done in a CCmode with
-            comparisons not done in a CCmode.  This is to aid targets
-            like Alpha that have an IEEE compliant EQ instruction, and
-            a non-IEEE compliant BEQ instruction.  The use of CCmode is
-            actually artificial, simply to prevent the combination, but
-            should not affect other platforms.
-
-            However, we must allow VOIDmode comparisons to match either
-            CCmode or non-CCmode comparison, because some ports have
-            modeless comparisons inside branch patterns.
-
-            ??? This mode check should perhaps look more like the mode check
-            in simplify_comparison in combine.  */
-
-         if ((GET_CODE (SET_SRC (set)) == COMPARE
-              || (((code == NE
-                    || (code == LT
-                        && GET_MODE_CLASS (inner_mode) == MODE_INT
-                        && (GET_MODE_BITSIZE (inner_mode)
-                            <= HOST_BITS_PER_WIDE_INT)
-                        && (STORE_FLAG_VALUE
-                            & ((HOST_WIDE_INT) 1
-                               << (GET_MODE_BITSIZE (inner_mode) - 1))))
-#ifdef FLOAT_STORE_FLAG_VALUE
-                    || (code == LT
-                        && GET_MODE_CLASS (inner_mode) == MODE_FLOAT
-                        && (fsfv = FLOAT_STORE_FLAG_VALUE (inner_mode),
-                            REAL_VALUE_NEGATIVE (fsfv)))
-#endif
-                    ))
-                  && COMPARISON_P (SET_SRC (set))))
-             && (((GET_MODE_CLASS (mode) == MODE_CC)
-                  == (GET_MODE_CLASS (inner_mode) == MODE_CC))
-                 || mode == VOIDmode || inner_mode == VOIDmode))
-           x = SET_SRC (set);
-         else if (((code == EQ
-                    || (code == GE
-                        && (GET_MODE_BITSIZE (inner_mode)
-                            <= HOST_BITS_PER_WIDE_INT)
-                        && GET_MODE_CLASS (inner_mode) == MODE_INT
-                        && (STORE_FLAG_VALUE
-                            & ((HOST_WIDE_INT) 1
-                               << (GET_MODE_BITSIZE (inner_mode) - 1))))
-#ifdef FLOAT_STORE_FLAG_VALUE
-                    || (code == GE
-                        && GET_MODE_CLASS (inner_mode) == MODE_FLOAT
-                        && (fsfv = FLOAT_STORE_FLAG_VALUE (inner_mode),
-                            REAL_VALUE_NEGATIVE (fsfv)))
-#endif
-                    ))
-                  && COMPARISON_P (SET_SRC (set))
-                  && (((GET_MODE_CLASS (mode) == MODE_CC)
-                       == (GET_MODE_CLASS (inner_mode) == MODE_CC))
-                      || mode == VOIDmode || inner_mode == VOIDmode))
-
-           {
-             reverse_code = 1;
-             x = SET_SRC (set);
-           }
-         else
-           break;
-       }
-
-      else if (reg_set_p (op0, prev))
-       /* If this sets OP0, but not directly, we have to give up.  */
-       break;
-
-      if (x)
-       {
-         if (COMPARISON_P (x))
-           code = GET_CODE (x);
-         if (reverse_code)
-           {
-             code = reversed_comparison_code (x, prev);
-             if (code == UNKNOWN)
-               return 0;
-             reverse_code = 0;
-           }
-
-         op0 = XEXP (x, 0), op1 = XEXP (x, 1);
-         if (earliest)
-           *earliest = prev;
-       }
-    }
-
-  /* If constant is first, put it last.  */
-  if (CONSTANT_P (op0))
-    code = swap_condition (code), tem = op0, op0 = op1, op1 = tem;
-
-  /* If OP0 is the result of a comparison, we weren't able to find what
-     was really being compared, so fail.  */
-  if (!allow_cc_mode
-      && GET_MODE_CLASS (GET_MODE (op0)) == MODE_CC)
-    return 0;
-
-  /* Canonicalize any ordered comparison with integers involving equality
-     if we can do computations in the relevant mode and we do not
-     overflow.  */
-
-  if (GET_MODE_CLASS (GET_MODE (op0)) != MODE_CC
-      && GET_CODE (op1) == CONST_INT
-      && GET_MODE (op0) != VOIDmode
-      && GET_MODE_BITSIZE (GET_MODE (op0)) <= HOST_BITS_PER_WIDE_INT)
-    {
-      HOST_WIDE_INT const_val = INTVAL (op1);
-      unsigned HOST_WIDE_INT uconst_val = const_val;
-      unsigned HOST_WIDE_INT max_val
-       = (unsigned HOST_WIDE_INT) GET_MODE_MASK (GET_MODE (op0));
-
-      switch (code)
-       {
-       case LE:
-         if ((unsigned HOST_WIDE_INT) const_val != max_val >> 1)
-           code = LT, op1 = gen_int_mode (const_val + 1, GET_MODE (op0));
-         break;
-
-       /* When cross-compiling, const_val might be sign-extended from
-          BITS_PER_WORD to HOST_BITS_PER_WIDE_INT */
-       case GE:
-         if ((HOST_WIDE_INT) (const_val & max_val)
-             != (((HOST_WIDE_INT) 1
-                  << (GET_MODE_BITSIZE (GET_MODE (op0)) - 1))))
-           code = GT, op1 = gen_int_mode (const_val - 1, GET_MODE (op0));
-         break;
-
-       case LEU:
-         if (uconst_val < max_val)
-           code = LTU, op1 = gen_int_mode (uconst_val + 1, GET_MODE (op0));
-         break;
-
-       case GEU:
-         if (uconst_val != 0)
-           code = GTU, op1 = gen_int_mode (uconst_val - 1, GET_MODE (op0));
-         break;
+/* Similar to rtlanal.c:get_condition, except that we also put an
+   invariant last unless both operands are invariants.  */
 
-       default:
-         break;
-       }
-    }
-
-  /* Never return CC0; return zero instead.  */
-  if (CC0_P (op0))
-    return 0;
-
-  return gen_rtx_fmt_ee (code, VOIDmode, op0, op1);
-}
-
-/* Given a jump insn JUMP, return the condition that will cause it to branch
-   to its JUMP_LABEL.  If the condition cannot be understood, or is an
-   inequality floating-point comparison which needs to be reversed, 0 will
-   be returned.
-
-   If EARLIEST is nonzero, it is a pointer to a place where the earliest
-   insn used in locating the condition was found.  If a replacement test
-   of the condition is desired, it should be placed in front of that
-   insn and we will be sure that the inputs are still valid.  
-
-   If ALLOW_CC_MODE is nonzero, allow the condition returned to be a
-   compare CC mode register.  */
-
-rtx
-get_condition (rtx jump, rtx *earliest, int allow_cc_mode)
-{
-  rtx cond;
-  int reverse;
-  rtx set;
-
-  /* If this is not a standard conditional jump, we can't parse it.  */
-  if (!JUMP_P (jump)
-      || ! any_condjump_p (jump))
-    return 0;
-  set = pc_set (jump);
-
-  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 (set), 2)) == LABEL_REF
-      && XEXP (XEXP (SET_SRC (set), 2), 0) == JUMP_LABEL (jump);
-
-  return canonicalize_condition (jump, cond, reverse, earliest, NULL_RTX,
-                                allow_cc_mode);
-}
-
-/* Similar to above routine, except that we also put an invariant last
-   unless both operands are invariants.  */
-
-rtx
+static rtx
 get_condition_for_loop (const struct loop *loop, rtx x)
 {
-  rtx comparison = get_condition (x, (rtx*) 0, false);
+  rtx comparison = get_condition (x, (rtx*) 0, false, true);
 
   if (comparison == 0
       || ! loop_invariant_p (loop, XEXP (comparison, 0))
@@ -9966,6 +10931,7 @@ load_mems (const struct loop *loop)
          rtx best = mem;
          int j;
          struct elt_loc_list *const_equiv = 0;
+         reg_set_iterator rsi;
 
          if (e)
            {
@@ -10044,17 +11010,17 @@ load_mems (const struct loop *loop)
             data flow, and enables {basic,general}_induction_var to find
             more bivs/givs.  */
          EXECUTE_IF_SET_IN_REG_SET
-           (&load_copies, FIRST_PSEUDO_REGISTER, j,
-            {
-              try_copy_prop (loop, reg, j);
-            });
+           (&load_copies, FIRST_PSEUDO_REGISTER, j, rsi)
+           {
+             try_copy_prop (loop, reg, j);
+           }
          CLEAR_REG_SET (&load_copies);
 
          EXECUTE_IF_SET_IN_REG_SET
-           (&store_copies, FIRST_PSEUDO_REGISTER, j,
-            {
-              try_swap_copy_prop (loop, reg, j);
-            });
+           (&store_copies, FIRST_PSEUDO_REGISTER, j, rsi)
+           {
+             try_swap_copy_prop (loop, reg, j);
+           }
          CLEAR_REG_SET (&store_copies);
        }
     }
@@ -10434,7 +11400,7 @@ loop_insn_emit_after (const struct loop *loop ATTRIBUTE_UNUSED,
    in basic block WHERE_BB (ignored in the interim) within the loop
    otherwise hoist PATTERN into the loop pre-header.  */
 
-rtx
+static rtx
 loop_insn_emit_before (const struct loop *loop,
                       basic_block where_bb ATTRIBUTE_UNUSED,
                       rtx where_insn, rtx pattern)
@@ -10459,7 +11425,7 @@ loop_call_insn_emit_before (const struct loop *loop ATTRIBUTE_UNUSED,
 
 /* Hoist insn for PATTERN into the loop pre-header.  */
 
-rtx
+static rtx
 loop_insn_hoist (const struct loop *loop, rtx pattern)
 {
   return loop_insn_emit_before (loop, 0, loop->start, pattern);
@@ -10477,7 +11443,7 @@ loop_call_insn_hoist (const struct loop *loop, rtx pattern)
 
 /* Sink insn for PATTERN after the loop end.  */
 
-rtx
+static rtx
 loop_insn_sink (const struct loop *loop, rtx pattern)
 {
   return loop_insn_emit_before (loop, 0, loop->sink, pattern);
@@ -10727,7 +11693,7 @@ loop_dump_aux (const struct loop *loop, FILE *file,
 {
   rtx label;
 
-  if (! loop || ! file)
+  if (! loop || ! file || !BB_HEAD (loop->first))
     return;
 
   /* Print diagnostics to compare our concept of a loop with
@@ -10748,15 +11714,9 @@ loop_dump_aux (const struct loop *loop, FILE *file,
   if (loop->start)
     {
       fprintf (file,
-              ";;  start %d (%d), cont dom %d (%d), cont %d (%d), vtop %d (%d), end %d (%d)\n",
+              ";;  start %d (%d), end %d (%d)\n",
               LOOP_BLOCK_NUM (loop->start),
               LOOP_INSN_UID (loop->start),
-              LOOP_BLOCK_NUM (loop->cont),
-              LOOP_INSN_UID (loop->cont),
-              LOOP_BLOCK_NUM (loop->cont),
-              LOOP_INSN_UID (loop->cont),
-              LOOP_BLOCK_NUM (loop->vtop),
-              LOOP_INSN_UID (loop->vtop),
               LOOP_BLOCK_NUM (loop->end),
               LOOP_INSN_UID (loop->end));
       fprintf (file, ";;  top %d (%d), scan start %d (%d)\n",
@@ -10775,12 +11735,6 @@ loop_dump_aux (const struct loop *loop, FILE *file,
            }
        }
       fputs ("\n", file);
-
-      /* This can happen when a marked loop appears as two nested loops,
-        say from while (a || b) {}.  The inner loop won't match
-        the loop markers but the outer one will.  */
-      if (LOOP_BLOCK_NUM (loop->cont) != loop->latch->index)
-       fprintf (file, ";;  NOTE_INSN_LOOP_CONT not in loop latch\n");
     }
 }