OSDN Git Service

Fix date on last entry.
[pf3gnuchains/gcc-fork.git] / gcc / loop.c
index 936adfb..cbb1731 100644 (file)
@@ -1,5 +1,6 @@
 /* Perform various loop optimizations, including strength reduction.
-   Copyright (C) 1987, 88, 89, 91-99, 2000 Free Software Foundation, Inc.
+   Copyright (C) 1987, 1988, 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
+   1998, 1999, 2000 Free Software Foundation, Inc.
 
 This file is part of GNU CC.
 
@@ -50,14 +51,10 @@ Boston, MA 02111-1307, USA.  */
 #include "flags.h"
 #include "real.h"
 #include "loop.h"
+#include "cselib.h"
 #include "except.h"
 #include "toplev.h"
 
-/* Information about the current loop being processed used to compute
-   the number of loop iterations for loop unrolling and doloop
-   optimization.  */
-static struct loop_info *current_loop_info;
-
 /* Vector mapping INSN_UIDs to luids.
    The luids are like uids but increase monotonically always.
    We use them to see whether a jump comes from outside a given loop.  */
@@ -165,7 +162,7 @@ static int num_mem_sets;
 
 /* Bound on pseudo register number before loop optimization.
    A pseudo has valid regscan info if its number is < max_reg_before_loop.  */
-int max_reg_before_loop;
+unsigned int max_reg_before_loop;
 
 /* The value to pass to the next call of reg_scan_update.  */
 static int loop_max_reg;
@@ -197,7 +194,7 @@ struct movable
                                   of any registers used within the LIBCALL.  */
   int consec;                  /* Number of consecutive following insns 
                                   that must be moved with this one.  */
-  int regno;                   /* The register it sets */
+  unsigned int regno;          /* The register it sets */
   short lifetime;              /* lifetime of that register;
                                   may be adjusted when matching movables
                                   that load the same value are found.  */
@@ -239,12 +236,13 @@ static void find_and_verify_loops PARAMS ((rtx, struct loops *));
 static void mark_loop_jump PARAMS ((rtx, struct loop *));
 static void prescan_loop PARAMS ((struct loop *));
 static int reg_in_basic_block_p PARAMS ((rtx, rtx));
-static int consec_sets_invariant_p PARAMS ((rtx, int, rtx));
+static int consec_sets_invariant_p PARAMS ((const struct loop *,
+                                           rtx, int, rtx));
 static int labels_in_range_p PARAMS ((rtx, int));
 static void count_one_set PARAMS ((rtx, rtx, varray_type, rtx *));
 
 static void count_loop_regs_set PARAMS ((rtx, rtx, varray_type, varray_type,
-                                      int *, int)); 
+                                        int *, int)); 
 static void note_addr_stored PARAMS ((rtx, rtx, void *));
 static void note_set_pseudo_multiple_uses PARAMS ((rtx, rtx, void *));
 static int loop_reg_used_before_p PARAMS ((const struct loop *, rtx, rtx));
@@ -260,43 +258,55 @@ static void combine_movables PARAMS ((struct movable *, int));
 static int regs_match_p PARAMS ((rtx, rtx, struct movable *));
 static int rtx_equal_for_loop_p PARAMS ((rtx, rtx, struct movable *));
 static void add_label_notes PARAMS ((rtx, rtx));
-static void move_movables PARAMS ((struct movable *, int, int, rtx, rtx, int));
-static int count_nonfixed_reads PARAMS ((rtx));
+static void move_movables PARAMS ((struct loop *loop, struct movable *, 
+                                  int, int, int));
+static int count_nonfixed_reads PARAMS ((const struct loop *, rtx));
 static void strength_reduce PARAMS ((struct loop *, int, int, int));
 static void find_single_use_in_loop PARAMS ((rtx, rtx, varray_type));
 static int valid_initial_value_p PARAMS ((rtx, rtx, int, rtx));
-static void find_mem_givs PARAMS ((rtx, rtx, int, int, rtx, rtx));
-static void record_biv PARAMS ((struct induction *, rtx, rtx, rtx, rtx, rtx *, int, int, int));
-static void check_final_value PARAMS ((struct induction *, rtx, rtx, 
-                                    unsigned HOST_WIDE_INT));
-static void record_giv PARAMS ((struct induction *, rtx, rtx, rtx, rtx, rtx, int, enum g_types, int, int, rtx *, rtx, rtx));
-static void update_giv_derive PARAMS ((rtx));
-static int basic_induction_var PARAMS ((rtx, enum machine_mode, rtx, rtx, int, rtx *, rtx *, rtx **, int *));
-static rtx simplify_giv_expr PARAMS ((rtx, int *));
-static int general_induction_var PARAMS ((rtx, rtx *, rtx *, rtx *, int, int *));
-static int consec_sets_giv PARAMS ((int, rtx, rtx, rtx, rtx *, rtx *, rtx *));
+static void find_mem_givs PARAMS ((const struct loop *, rtx, rtx, int, int));
+static void record_biv PARAMS ((struct induction *, rtx, rtx, rtx, rtx, rtx *, 
+                               int, int, int));
+static void check_final_value PARAMS ((const struct loop *,
+                                      struct induction *));
+static void record_giv PARAMS ((const struct loop *, struct induction *, 
+                               rtx, rtx, rtx, rtx, rtx, int, enum g_types, 
+                               int, int, rtx *));
+static void update_giv_derive PARAMS ((const struct loop *, rtx));
+static int basic_induction_var PARAMS ((const struct loop *, rtx, 
+                                       enum machine_mode, rtx, rtx,
+                                       rtx *, rtx *, rtx **, int *));
+static rtx simplify_giv_expr PARAMS ((const struct loop *, rtx, int *));
+static int general_induction_var PARAMS ((const struct loop *loop, rtx, rtx *,
+                                         rtx *, rtx *, int, int *));
+static int consec_sets_giv PARAMS ((const struct loop *, int, rtx,
+                                   rtx, rtx, rtx *, rtx *, rtx *));
 static int check_dbra_loop PARAMS ((struct loop *, int));
 static rtx express_from_1 PARAMS ((rtx, rtx, rtx));
 static rtx combine_givs_p PARAMS ((struct induction *, struct induction *));
 static void combine_givs PARAMS ((struct iv_class *));
 struct recombine_givs_stats;
-static int find_life_end PARAMS ((rtx, struct recombine_givs_stats *, rtx, rtx));
-static void recombine_givs PARAMS ((struct iv_class *, rtx, rtx, int));
+static int find_life_end PARAMS ((rtx, struct recombine_givs_stats *,
+                                 rtx, rtx));
+static void recombine_givs PARAMS ((const struct loop *, struct iv_class *,
+                                   int));
 static int product_cheap_p PARAMS ((rtx, rtx));
-static int maybe_eliminate_biv PARAMS ((struct iv_class *, rtx, rtx, int, int, int));
-static int maybe_eliminate_biv_1 PARAMS ((rtx, rtx, struct iv_class *, int, rtx));
+static int maybe_eliminate_biv PARAMS ((const struct loop *, struct iv_class *,
+                                       int, int, int));
+static int maybe_eliminate_biv_1 PARAMS ((const struct loop *, rtx, rtx, 
+                                         struct iv_class *, int, rtx));
 static int last_use_this_basic_block PARAMS ((rtx, rtx));
 static void record_initial PARAMS ((rtx, rtx, void *));
 static void update_reg_last_use PARAMS ((rtx, rtx));
 static rtx next_insn_in_loop PARAMS ((const struct loop *, rtx));
 static void load_mems_and_recount_loop_regs_set PARAMS ((const struct loop*,
-                                                      int *));
+                                                        int *));
 static void load_mems PARAMS ((const struct loop *));
 static int insert_loop_mem PARAMS ((rtx *, void *));
 static int replace_loop_mem PARAMS ((rtx *, void *));
 static int replace_loop_reg PARAMS ((rtx *, void *));
 static void note_reg_stored PARAMS ((rtx, rtx, void *));
-static void try_copy_prop PARAMS ((const struct loop *, rtx, int));
+static void try_copy_prop PARAMS ((const struct loop *, rtx, unsigned int));
 static int replace_label PARAMS ((rtx *, void *));
 
 typedef struct rtx_and_int {
@@ -467,7 +477,7 @@ loop_optimize (f, dumpfile, unroll_p, bct_p)
   /* Allocate and initialize auxiliary loop information.  */
   loops_info = xcalloc (loops->num, sizeof (struct loop_info));
   for (i = 0; i < loops->num; i++)
-    loops->array[i].info = loops_info + i;
+    loops->array[i].aux = loops_info + i;
 
   /* Now find all register lifetimes.  This must be done after
      find_and_verify_loops, because it might reorder the insns in the
@@ -508,14 +518,6 @@ loop_optimize (f, dumpfile, unroll_p, bct_p)
     if (uid_luid[i] == 0)
       uid_luid[i] = uid_luid[i - 1];
 
-  /* If debugging and unrolling loops, we must replicate the tree
-     nodes corresponding to the BLOCKs inside the loop, so that the
-     original one to one mapping will remain.  We sometimes unroll
-     loops even when unroll_p is false, so we must always do this when
-     debugging.  */
-  if (write_symbols != NO_DEBUG)
-    find_loop_tree_blocks ();
-
   /* Determine if the function has indirect jump.  On some systems
      this prevents low overhead loop instructions from being used.  */
   indirect_jump_in_function = indirect_jump_in_function_p (f);
@@ -530,9 +532,12 @@ loop_optimize (f, dumpfile, unroll_p, bct_p)
        scan_loop (loop, unroll_p, bct_p);
     }
 
-  /* Replicate the BLOCKs.  */
+  /* If there were lexical blocks inside the loop, they have been
+     replicated.  We will now have more than one NOTE_INSN_BLOCK_BEG
+     and NOTE_INSN_BLOCK_END for each such block.  We must duplicate
+     the BLOCKs as well.  */
   if (write_symbols != NO_DEBUG)
-    unroll_block_trees ();
+    reorder_blocks ();
 
   end_alias_analysis ();
 
@@ -546,7 +551,7 @@ loop_optimize (f, dumpfile, unroll_p, bct_p)
 \f
 /* Returns the next insn, in execution order, after INSN.  START and
    END are the NOTE_INSN_LOOP_BEG and NOTE_INSN_LOOP_END for the loop,
-   respectively.  LOOP_TOP, if non-NULL, is the top of the loop in the
+   respectively.  LOOP->TOP, if non-NULL, is the top of the loop in the
    insn-stream; it is used with loops that are entered near the
    bottom.  */
 
@@ -590,7 +595,10 @@ scan_loop (loop, unroll_p, bct_p)
   register int i;
   rtx loop_start = loop->start;
   rtx loop_end = loop->end;
-  struct loop_info *loop_info = loop->info;
+  /* Additional information about the current loop being processed
+     that is used to compute the number of loop iterations for loop
+     unrolling and doloop optimization.  */
+  struct loop_info *loop_info = LOOP_INFO (loop);
   rtx p;
   /* 1 if we are scanning insns that could be executed zero times.  */
   int maybe_never = 0;
@@ -619,7 +627,6 @@ scan_loop (loop, unroll_p, bct_p)
   int loop_depth = 0;
   int nregs;
 
-  current_loop_info = loop_info;
   loop->top = 0;
 
   /* Determine whether this loop starts with a jump down to a test at
@@ -827,14 +834,14 @@ scan_loop (loop, unroll_p, bct_p)
               which was not created by the user and not used in an exit test.
               That behavior is incorrect and was removed.  */
            ;
-         else if ((tem = invariant_p (src))
+         else if ((tem = loop_invariant_p (loop, src))
                   && (dependencies == 0
-                      || (tem2 = invariant_p (dependencies)) != 0)
+                      || (tem2 = loop_invariant_p (loop, dependencies)) != 0)
                   && (VARRAY_INT (set_in_loop, 
                                   REGNO (SET_DEST (set))) == 1
                       || (tem1
                           = consec_sets_invariant_p 
-                          (SET_DEST (set),
+                          (loop, SET_DEST (set),
                            VARRAY_INT (set_in_loop, REGNO (SET_DEST (set))),
                            p)))
                   /* If the insn can cause a trap (such as divide by zero),
@@ -917,8 +924,9 @@ scan_loop (loop, unroll_p, bct_p)
              m->is_equiv = (find_reg_note (p, REG_EQUIV, NULL_RTX) != 0);
              m->savemode = VOIDmode;
              m->regno = regno;
-             /* Set M->cond if either invariant_p or consec_sets_invariant_p
-                returned 2 (only conditionally invariant).  */
+             /* Set M->cond if either loop_invariant_p
+                or consec_sets_invariant_p returned 2
+                (only conditionally invariant).  */
              m->cond = ((tem | tem1 | tem2) > 1);
              m->global = (uid_luid[REGNO_LAST_UID (regno)] 
                           > INSN_LUID (loop_end)
@@ -1109,8 +1117,7 @@ scan_loop (loop, unroll_p, bct_p)
      optimizing for code size.  */
 
   if (! optimize_size)
-    move_movables (movables, threshold,
-                  insn_count, loop_start, loop_end, nregs);
+    move_movables (loop, movables, threshold, insn_count, nregs);
 
   /* Now candidates that still are negative are those not moved.
      Change set_in_loop to indicate that those are not actually invariant.  */
@@ -1123,7 +1130,8 @@ scan_loop (loop, unroll_p, bct_p)
   load_mems_and_recount_loop_regs_set (loop, &insn_count);
 
   for (update_start = loop_start;
-       PREV_INSN (update_start) && GET_CODE (PREV_INSN (update_start)) != CODE_LABEL;
+       PREV_INSN (update_start)
+        && GET_CODE (PREV_INSN (update_start)) != CODE_LABEL;
        update_start = PREV_INSN (update_start))
     ;
   update_end = NEXT_INSN (loop_end);
@@ -1272,8 +1280,12 @@ reg_in_basic_block_p (insn, reg)
        }
     }
 
-  /* The "last use" doesn't follow the "first use"??  */
-  abort ();
+  /* The "last use" that was recorded can't be found after the first
+     use.  This can happen when the last use was deleted while
+     processing an inner loop, this inner loop was then completely
+     unrolled, and the outer loop is always exited after the inner loop,
+     so that everything after the first use becomes a single basic block.  */
+  return 1;
 }
 \f
 /* Compute the benefit of eliminating the insns in the block whose
@@ -1524,8 +1536,8 @@ regs_match_p (x, y, movables)
      rtx x, y;
      struct movable *movables;
 {
-  int xn = REGNO (x);
-  int yn = REGNO (y);
+  unsigned int xn = REGNO (x);
+  unsigned int yn = REGNO (y);
   struct movable *mx, *my;
 
   for (mx = movables; mx; mx = mx->next)
@@ -1702,17 +1714,18 @@ add_label_notes (x, insns)
    other throughout.  */
 
 static void
-move_movables (movables, threshold, insn_count, loop_start, end, nregs)
+move_movables (loop, movables, threshold, insn_count, nregs)
+     struct loop *loop;
      struct movable *movables;
      int threshold;
      int insn_count;
-     rtx loop_start;
-     rtx end;
      int nregs;
 {
   rtx new_start = 0;
   register struct movable *m;
   register rtx p;
+  rtx loop_start = loop->start;
+  rtx loop_end = loop->end;
   /* Map of pseudo-register replacements to handle combining
      when we move several insns that load the same value
      into different pseudo-registers.  */
@@ -1757,11 +1770,11 @@ move_movables (movables, threshold, insn_count, loop_start, end, nregs)
 
       if (!m->done
          && (! m->cond
-             || (1 == invariant_p (m->set_src)
+             || (1 == loop_invariant_p (loop, m->set_src)
                  && (m->dependencies == 0
-                     || 1 == invariant_p (m->dependencies))
+                     || 1 == loop_invariant_p (loop, m->dependencies))
                  && (m->consec == 0
-                     || 1 == consec_sets_invariant_p (m->set_dest,
+                     || 1 == consec_sets_invariant_p (loop, m->set_dest,
                                                       m->consec + 1,
                                                       m->insn))))
          && (! m->forces || m->forces->done))
@@ -2062,7 +2075,7 @@ move_movables (movables, threshold, insn_count, loop_start, end, nregs)
                             like this as a result of record_jump_cond.  */
                      
                          if ((temp = find_reg_note (i1, REG_EQUAL, NULL_RTX))
-                             && ! invariant_p (XEXP (temp, 0)))
+                             && ! loop_invariant_p (loop, XEXP (temp, 0)))
                            remove_note (i1, temp);
                        }
 
@@ -2123,8 +2136,8 @@ move_movables (movables, threshold, insn_count, loop_start, end, nregs)
                   We can't use the moved insn because it is out of range
                   in uid_luid.  Only the old insns have luids.  */
                REGNO_FIRST_UID (regno) = INSN_UID (loop_start);
-             if (uid_luid[REGNO_LAST_UID (regno)] < INSN_LUID (end))
-               REGNO_LAST_UID (regno) = INSN_UID (end);
+             if (uid_luid[REGNO_LAST_UID (regno)] < INSN_LUID (loop_end))
+               REGNO_LAST_UID (regno) = INSN_UID (loop_end);
 
              /* Combine with this moved insn any other matching movables.  */
 
@@ -2192,7 +2205,7 @@ move_movables (movables, threshold, insn_count, loop_start, end, nregs)
 
   /* Go through all the instructions in the loop, making
      all the register substitutions scheduled in REG_MAP.  */
-  for (p = new_start; p != end; p = NEXT_INSN (p))
+  for (p = new_start; p != loop_end; p = NEXT_INSN (p))
     if (GET_CODE (p) == INSN || GET_CODE (p) == JUMP_INSN
        || GET_CODE (p) == CALL_INSN)
       {
@@ -2274,7 +2287,8 @@ replace_call_address (x, reg, addr)
    in the rtx X.  */
 
 static int
-count_nonfixed_reads (x)
+count_nonfixed_reads (loop, x)
+     const struct loop *loop;
      rtx x;
 {
   register enum rtx_code code;
@@ -2299,8 +2313,8 @@ count_nonfixed_reads (x)
       return 0;
 
     case MEM:
-      return ((invariant_p (XEXP (x, 0)) != 1)
-             + count_nonfixed_reads (XEXP (x, 0)));
+      return ((loop_invariant_p (loop, XEXP (x, 0)) != 1)
+             + count_nonfixed_reads (loop, XEXP (x, 0)));
       
     default:
       break;
@@ -2311,12 +2325,12 @@ count_nonfixed_reads (x)
   for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
     {
       if (fmt[i] == 'e')
-       value += count_nonfixed_reads (XEXP (x, i));
-      else if (fmt[i] == 'E')
+       value += count_nonfixed_reads (loop, XEXP (x, i));
+      if (fmt[i] == 'E')
        {
          register int j;
          for (j = 0; j < XVECLEN (x, i); j++)
-           value += count_nonfixed_reads (XVECEXP (x, i, j));
+           value += count_nonfixed_reads (loop, XVECEXP (x, i, j));
        }
     }
   return value;
@@ -2366,7 +2380,7 @@ constant_high_bytes (p, loop_start)
 #endif
 \f
 /* Scan a loop setting the elements `cont', `vtop', `loops_enclosed',
-   `has_call', `has_volatile', and `has_tablejump' within LOOP_INFO.
+   `has_call', `has_volatile', and `has_tablejump' within LOOP.
    Set the global variables `unknown_address_altered',
    `unknown_constant_address_altered', and `num_mem_sets'.  Also, fill
    in the array `loop_mems' and the list `loop_store_mems'.  */
@@ -2377,7 +2391,7 @@ prescan_loop (loop)
 {
   register int level = 1;
   rtx insn;
-  struct loop_info *loop_info = loop->info;
+  struct loop_info *loop_info = LOOP_INFO (loop);
   rtx start = loop->start;
   rtx end = loop->end;
   /* The label after END.  Jumping here is just like falling off the
@@ -3189,7 +3203,8 @@ note_set_pseudo_multiple_uses (x, y, data)
    anything stored in `loop_store_mems'.  */
 
 int
-invariant_p (x)
+loop_invariant_p (loop, x)
+     const struct loop *loop;
      register rtx x;
 {
   register int i;
@@ -3238,7 +3253,7 @@ invariant_p (x)
          && ! current_function_has_nonlocal_goto)
        return 1;
 
-      if (current_loop_info->has_call
+      if (LOOP_INFO (loop)->has_call
          && REGNO (x) < FIRST_PSEUDO_REGISTER && call_used_regs[REGNO (x)])
        return 0;
 
@@ -3292,7 +3307,7 @@ invariant_p (x)
     {
       if (fmt[i] == 'e')
        {
-         int tem = invariant_p (XEXP (x, i));
+         int tem = loop_invariant_p (loop, XEXP (x, i));
          if (tem == 0)
            return 0;
          if (tem == 2)
@@ -3303,7 +3318,7 @@ invariant_p (x)
          register int j;
          for (j = 0; j < XVECLEN (x, i); j++)
            {
-             int tem = invariant_p (XVECEXP (x, i, j));
+             int tem = loop_invariant_p (loop, XVECEXP (x, i, j));
              if (tem == 0)
                return 0;
              if (tem == 2)
@@ -3328,12 +3343,13 @@ invariant_p (x)
    and that its source is invariant.  */
 
 static int
-consec_sets_invariant_p (reg, n_sets, insn)
+consec_sets_invariant_p (loop, reg, n_sets, insn)
+     const struct loop *loop;
      int n_sets;
      rtx reg, insn;
 {
-  register rtx p = insn;
-  register int regno = REGNO (reg);
+  rtx p = insn;
+  unsigned int regno = REGNO (reg);
   rtx temp;
   /* Number of sets we have to insist on finding after INSN.  */
   int count = n_sets - 1;
@@ -3365,7 +3381,7 @@ consec_sets_invariant_p (reg, n_sets, insn)
          && GET_CODE (SET_DEST (set)) == REG
          && REGNO (SET_DEST (set)) == regno)
        {
-         this = invariant_p (SET_SRC (set));
+         this = loop_invariant_p (loop, SET_SRC (set));
          if (this != 0)
            value |= this;
          else if ((temp = find_reg_note (p, REG_EQUAL, NULL_RTX)))
@@ -3375,7 +3391,7 @@ consec_sets_invariant_p (reg, n_sets, insn)
                 notes are OK.  */
              this = (CONSTANT_P (XEXP (temp, 0))
                      || (find_reg_note (p, REG_RETVAL, NULL_RTX)
-                         && invariant_p (XEXP (temp, 0))));
+                         && loop_invariant_p (loop, XEXP (temp, 0))));
              if (this != 0)
                value |= this;
            }
@@ -3390,7 +3406,7 @@ consec_sets_invariant_p (reg, n_sets, insn)
     }
 
   VARRAY_INT (set_in_loop, regno) = old;
-  /* If invariant_p ever returned 2, we return 2.  */
+  /* If loop_invariant_p ever returned 2, we return 2.  */
   return 1 + (value & 2);
 }
 
@@ -3420,7 +3436,7 @@ all_sets_invariant_p (reg, insn, table)
          && GET_CODE (SET_DEST (PATTERN (p))) == REG
          && REGNO (SET_DEST (PATTERN (p))) == regno)
        {
-         if (!invariant_p (SET_SRC (PATTERN (p)), table))
+         if (! loop_invariant_p (loop, SET_SRC (PATTERN (p)), table))
            return 0;
        }
     }
@@ -3575,11 +3591,10 @@ count_loop_regs_set (from, to, may_not_move, single_usage, count_ptr, nregs)
   free (last_set);
 }
 \f
-/* Given a loop that is bounded by LOOP_START and LOOP_END
-   and that is entered at LOOP_SCAN_START,
-   return 1 if the register set in SET contained in insn INSN is used by
-   any insn that precedes INSN in cyclic order starting
-   from the loop entry point.
+/* Given a loop that is bounded by LOOP->START and LOOP->END and that
+   is entered at LOOP->SCAN_START, return 1 if the register set in SET
+   contained in insn INSN is used by any insn that precedes INSN in
+   cyclic order starting from the loop entry point.
 
    We don't want to use INSN_LUID here because if we restrict INSN to those
    that have a valid INSN_LUID, it means we cannot move an invariant out
@@ -3642,7 +3657,7 @@ struct iv_class *loop_iv_list;
 /* Givs made from biv increments are always splittable for loop unrolling.
    Since there is no regscan info for them, we have to keep track of them
    separately.  */
-int first_increment_giv, last_increment_giv;
+unsigned int first_increment_giv, last_increment_giv;
 
 /* Communication with routines called via `note_stores'.  */
 
@@ -3685,13 +3700,7 @@ static rtx addr_placeholder;
    valid index in several tables including n_times_set and regno_last_uid.
    This does not cause a problem here, because the added registers cannot be
    givs outside of their loop, and hence will never be reconsidered.
-   But scan_loop must check regnos to make sure they are in bounds. 
-   
-   LOOP_SCAN_START is the first instruction in the loop, as the loop would
-   actually be executed.  END is the NOTE_INSN_LOOP_END.  LOOP_TOP is
-   the first instruction in the loop, as it is layed out in the
-   instruction stream.  LOOP_START is the NOTE_INSN_LOOP_BEG.
-   LOOP_CONT is the NOTE_INSN_LOOP_CONT.  */
+   But scan_loop must check regnos to make sure they are in bounds.   */
 
 static void
 strength_reduce (loop, insn_count, unroll_p, bct_p)
@@ -3716,7 +3725,7 @@ strength_reduce (loop, insn_count, unroll_p, bct_p)
   int past_loop_latch = 0;
   /* Temporary list pointers for traversing loop_iv_list.  */
   struct iv_class *bl, **backbl;
-  struct loop_info *loop_info = loop->info;
+  struct loop_info *loop_info = LOOP_INFO (loop);
   /* Ratio of extra register life span we can justify
      for saving an instruction.  More if loop doesn't call subroutines
      since in that case saving an insn makes more difference
@@ -3741,7 +3750,7 @@ strength_reduce (loop, insn_count, unroll_p, bct_p)
   /* If loop_scan_start points to the loop exit test, we have to be wary of
      subversive use of gotos inside expression statements.  */
   if (prev_nonnote_insn (loop_scan_start) != prev_nonnote_insn (loop_start))
-    maybe_multiple = back_branch_in_range_p (loop_scan_start, loop_start, loop_end);
+    maybe_multiple = back_branch_in_range_p (loop, loop_scan_start);
 
   VARRAY_INT_INIT (reg_iv_type, max_reg_before_loop, "reg_iv_type");
   VARRAY_GENERIC_PTR_INIT (reg_iv_info, max_reg_before_loop, "reg_iv_info");
@@ -3780,9 +3789,9 @@ strength_reduce (loop, insn_count, unroll_p, bct_p)
            {
              int multi_insn_incr = 0;
 
-             if (basic_induction_var (SET_SRC (set), GET_MODE (SET_SRC (set)),
-                                      dest_reg, p, loop->level,
-                                      &inc_val, &mult_val,
+             if (basic_induction_var (loop, SET_SRC (set),
+                                      GET_MODE (SET_SRC (set)),
+                                      dest_reg, p, &inc_val, &mult_val,
                                       &location, &multi_insn_incr))
                {
                  /* It is a possible basic induction variable.
@@ -3860,9 +3869,7 @@ strength_reduce (loop, insn_count, unroll_p, bct_p)
             matter.  Check to see if the target of this branch is on the
             loop->exits_labels list.  */
             
-         for (label = uid_loop[INSN_UID (loop_start)]->exit_labels;
-              label;
-              label = LABEL_NEXTREF (label))
+         for (label = loop->exit_labels; label; label = LABEL_NEXTREF (label))
            if (XEXP (label, 0) == JUMP_LABEL (p))
              break;
 
@@ -3999,7 +4006,7 @@ strength_reduce (loop, insn_count, unroll_p, bct_p)
       if (GET_CODE (p) == JUMP_INSN
          && JUMP_LABEL (p) != 0
          && next_real_insn (JUMP_LABEL (p)) == next_real_insn (loop_end)
-         && (test = get_condition_for_loop (p)) != 0
+         && (test = get_condition_for_loop (loop, p)) != 0
          && GET_CODE (XEXP (test, 0)) == REG
          && REGNO (XEXP (test, 0)) < max_reg_before_loop
          && (bl = reg_biv_class[REGNO (XEXP (test, 0))]) != 0
@@ -4080,10 +4087,9 @@ strength_reduce (loop, insn_count, unroll_p, bct_p)
              && GET_CODE (src) == PLUS
              && GET_CODE (XEXP (src, 0)) == REG
              && CONSTANT_P (XEXP (src, 1))
-             && ((increment = biv_total_increment (bl, loop_start, loop_end))
-                 != NULL_RTX))
+             && ((increment = biv_total_increment (bl)) != NULL_RTX))
            {
-             int regno = REGNO (XEXP (src, 0));
+             unsigned int regno = REGNO (XEXP (src, 0));
 
              for (bl2 = loop_iv_list; bl2; bl2 = bl2->next)
                if (bl2->regno == regno)
@@ -4093,8 +4099,7 @@ strength_reduce (loop, insn_count, unroll_p, bct_p)
          /* Now, can we transform this biv into a giv?  */
          if (bl2
              && bl2->biv_count == 1
-             && rtx_equal_p (increment,
-                             biv_total_increment (bl2, loop_start, loop_end))
+             && rtx_equal_p (increment, biv_total_increment (bl2))
              /* init_insn is only set to insns that are before loop_start
                 without any intervening labels.  */
              && ! reg_set_between_p (bl2->biv->src_reg,
@@ -4114,7 +4119,7 @@ strength_reduce (loop, insn_count, unroll_p, bct_p)
                                  &SET_SRC (single_set (bl->biv->insn)),
                                  copy_rtx (src), 0))
            {
-             rtx dominator = uid_loop[INSN_UID (loop_start)]->cont_dominator;
+             rtx dominator = loop->cont_dominator;
              rtx giv = bl->biv->src_reg;
              rtx giv_insn = bl->biv->insn;
              rtx after_giv = NEXT_INSN (giv_insn);
@@ -4210,7 +4215,7 @@ strength_reduce (loop, insn_count, unroll_p, bct_p)
      markers.  */
   if (n_extra_increment  && ! loop_info->has_volatile)
     {
-      int nregs = first_increment_giv + n_extra_increment;
+      unsigned int nregs = first_increment_giv + n_extra_increment;
 
       /* Reallocate reg_iv_type and reg_iv_info.  */
       VARRAY_GROW (reg_iv_type, nregs);
@@ -4467,11 +4472,11 @@ strength_reduce (loop, insn_count, unroll_p, bct_p)
            continue;
 
          if (/* SET_SRC is a giv.  */
-             (general_induction_var (SET_SRC (set), &src_reg, &add_val,
+             (general_induction_var (loop, SET_SRC (set), &src_reg, &add_val,
                                      &mult_val, 0, &benefit)
               /* Equivalent expression is a giv.  */
               || ((regnote = find_reg_note (p, REG_EQUAL, NULL_RTX))
-                  && general_induction_var (XEXP (regnote, 0), &src_reg,
+                  && general_induction_var (loop, XEXP (regnote, 0), &src_reg,
                                             &add_val, &mult_val, 0,
                                             &benefit)))
              /* Don't try to handle any regs made by loop optimization.
@@ -4482,7 +4487,7 @@ strength_reduce (loop, insn_count, unroll_p, bct_p)
              /* This must be the only place where the register is set.  */
              && (VARRAY_INT (n_times_set, REGNO (dest_reg)) == 1
                  /* or all sets must be consecutive and make a giv.  */
-                 || (benefit = consec_sets_giv (benefit, p,
+                 || (benefit = consec_sets_giv (loop, benefit, p,
                                                 src_reg, dest_reg,
                                                 &add_val, &mult_val,
                                                 &last_consec_insn))))
@@ -4498,9 +4503,9 @@ strength_reduce (loop, insn_count, unroll_p, bct_p)
              if (VARRAY_INT (n_times_set, REGNO (dest_reg)) != 1)
                p = last_consec_insn;
 
-             record_giv (v, p, src_reg, dest_reg, mult_val, add_val, benefit,
-                         DEST_REG, not_every_iteration, maybe_multiple,
-                         NULL_PTR, loop_start, loop_end);
+             record_giv (loop, v, p, src_reg, dest_reg, mult_val, add_val,
+                         benefit, DEST_REG, not_every_iteration,
+                         maybe_multiple, NULL_PTR);
 
            }
        }
@@ -4510,15 +4515,15 @@ strength_reduce (loop, insn_count, unroll_p, bct_p)
       /* This resulted in worse code on a VAX 8600.  I wonder if it
         still does.  */
       if (GET_CODE (p) == INSN)
-       find_mem_givs (PATTERN (p), p, not_every_iteration, maybe_multiple,
-                      loop_start, loop_end);
+       find_mem_givs (loop, PATTERN (p), p, not_every_iteration,
+                      maybe_multiple);
 #endif
 
       /* Update the status of whether giv can derive other givs.  This can
         change when we pass a label or an insn that updates a biv.  */
       if (GET_CODE (p) == INSN || GET_CODE (p) == JUMP_INSN
        || GET_CODE (p) == CODE_LABEL)
-       update_giv_derive (p);
+       update_giv_derive (loop, p);
 
       /* Past CODE_LABEL, we get to insns that may be executed multiple
         times.  The only way we can be sure that they can't is if every
@@ -4582,9 +4587,7 @@ strength_reduce (loop, insn_count, unroll_p, bct_p)
             matter.  Check to see if the target of this branch is on the
             loop->exits_labels list.  */
             
-         for (label = uid_loop[INSN_UID (loop_start)]->exit_labels;
-              label;
-              label = LABEL_NEXTREF (label))
+         for (label = loop->exit_labels; label; label = LABEL_NEXTREF (label))
            if (XEXP (label, 0) == JUMP_LABEL (p))
              break;
 
@@ -4643,7 +4646,7 @@ strength_reduce (loop, insn_count, unroll_p, bct_p)
 
       for (v = bl->giv; v; v = v->next_iv)
        if (! v->replaceable && ! v->not_replaceable)
-         check_final_value (v, loop_start, loop_end, loop_info->n_iterations);
+         check_final_value (loop, v);
     }
 
   /* Try to prove that the loop counter variable (if any) is always
@@ -4692,14 +4695,13 @@ strength_reduce (loop, insn_count, unroll_p, bct_p)
           && ! bl->nonneg
 #endif
           && ! reg_mentioned_p (bl->biv->dest_reg, SET_SRC (bl->init_set)))
-         || ((final_value = final_biv_value (bl, loop_start, loop_end, 
-                                             loop_info->n_iterations))
+         || ((final_value = final_biv_value (loop, bl))
 #ifdef HAVE_decrement_and_branch_until_zero
              && ! bl->nonneg
 #endif
              ))
-       bl->eliminable = maybe_eliminate_biv (bl, loop_start, loop_end, 0,
-                                             threshold, insn_count);
+       bl->eliminable = maybe_eliminate_biv (loop, bl, 0, threshold, 
+                                             insn_count);
       else
        {
          if (loop_dump_stream)
@@ -4863,7 +4865,7 @@ strength_reduce (loop, insn_count, unroll_p, bct_p)
          VARRAY_GROW (reg_iv_type, nregs);
          VARRAY_GROW (reg_iv_info, nregs);
        }
-      recombine_givs (bl, loop_start, loop_end, unroll_p);
+      recombine_givs (loop, bl, unroll_p);
 
       /* Reduce each giv that we decided to reduce.  */
 
@@ -5096,7 +5098,7 @@ strength_reduce (loop, insn_count, unroll_p, bct_p)
                 loop to ensure that it will always be executed no matter
                 how the loop exits.  Otherwise, emit the insn after the loop,
                 since this is slightly more efficient.  */
-             if (uid_loop[INSN_UID (loop_start)]->exit_count)
+             if (loop->exit_count)
                insert_before = loop_start;
              else
                insert_before = end_insert_before;
@@ -5164,9 +5166,7 @@ strength_reduce (loop, insn_count, unroll_p, bct_p)
         doing so in the rare cases where it can occur.  */
 
       if (all_reduced == 1 && bl->eliminable
-         && maybe_eliminate_biv (bl, loop_start, loop_end, 1,
-                                 threshold, insn_count))
-
+         && maybe_eliminate_biv (loop, bl, 1, threshold, insn_count))
        {
          /* ?? If we created a new test to bypass the loop entirely,
             or otherwise drop straight in, based on this test, then
@@ -5188,7 +5188,7 @@ strength_reduce (loop, insn_count, unroll_p, bct_p)
                 loop to ensure that it will always be executed no matter
                 how the loop exits.  Otherwise, emit the insn after the
                 loop, since this is slightly more efficient.  */
-             if (uid_loop[INSN_UID (loop_start)]->exit_count)
+             if (loop->exit_count)
                insert_before = loop_start;
              else
                insert_before = end_insert_before;
@@ -5328,12 +5328,11 @@ valid_initial_value_p (x, insn, call_seen, loop_start)
    more thanonce in each loop iteration.  */
 
 static void
-find_mem_givs (x, insn, not_every_iteration, maybe_multiple, loop_start,
-              loop_end)
+find_mem_givs (loop, x, insn, not_every_iteration, maybe_multiple)
+     const struct loop *loop;
      rtx x;
      rtx insn;
      int not_every_iteration, maybe_multiple;
-     rtx loop_start, loop_end;
 {
   register int i, j;
   register enum rtx_code code;
@@ -5371,16 +5370,16 @@ find_mem_givs (x, insn, not_every_iteration, maybe_multiple, loop_start,
           it comes time to combine a set of related DEST_ADDR GIVs, since
           this one would not be seen.   */
 
-       if (general_induction_var (XEXP (x, 0), &src_reg, &add_val,
+       if (general_induction_var (loop, XEXP (x, 0), &src_reg, &add_val,
                                   &mult_val, 1, &benefit))
          {
            /* Found one; record it.  */
            struct induction *v
              = (struct induction *) oballoc (sizeof (struct induction));
 
-           record_giv (v, insn, src_reg, addr_placeholder, mult_val,
+           record_giv (loop, v, insn, src_reg, addr_placeholder, mult_val,
                        add_val, benefit, DEST_ADDR, not_every_iteration,
-                       maybe_multiple, &XEXP (x, 0), loop_start, loop_end);
+                       maybe_multiple, &XEXP (x, 0));
 
            v->mem_mode = GET_MODE (x);
          }
@@ -5396,12 +5395,12 @@ find_mem_givs (x, insn, not_every_iteration, maybe_multiple, loop_start,
   fmt = GET_RTX_FORMAT (code);
   for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
     if (fmt[i] == 'e')
-      find_mem_givs (XEXP (x, i), insn, not_every_iteration, maybe_multiple,
-                    loop_start, loop_end);
+      find_mem_givs (loop, XEXP (x, i), insn, not_every_iteration,
+                    maybe_multiple);
     else if (fmt[i] == 'E')
       for (j = 0; j < XVECLEN (x, i); j++)
-       find_mem_givs (XVECEXP (x, i, j), insn, not_every_iteration,
-                      maybe_multiple, loop_start, loop_end);
+       find_mem_givs (loop, XVECEXP (x, i, j), insn, not_every_iteration,
+                      maybe_multiple);
 }
 \f
 /* Fill in the data about one biv update.
@@ -5524,9 +5523,9 @@ record_biv (v, insn, dest_reg, inc_val, mult_val, location,
    LOCATION points to the place where this giv's value appears in INSN.  */
 
 static void
-record_giv (v, insn, src_reg, dest_reg, mult_val, add_val, benefit,
-           type, not_every_iteration, maybe_multiple, location, loop_start,
-           loop_end)
+record_giv (loop, v, insn, src_reg, dest_reg, mult_val, add_val, benefit,
+           type, not_every_iteration, maybe_multiple, location)
+     const struct loop *loop;
      struct induction *v;
      rtx insn;
      rtx src_reg;
@@ -5536,7 +5535,6 @@ record_giv (v, insn, src_reg, dest_reg, mult_val, add_val, benefit,
      enum g_types type;
      int not_every_iteration, maybe_multiple;
      rtx *location;
-     rtx loop_start, loop_end;
 {
   struct induction *b;
   struct iv_class *bl;
@@ -5637,7 +5635,8 @@ record_giv (v, insn, src_reg, dest_reg, mult_val, add_val, benefit,
 
       if (REGNO_FIRST_UID (REGNO (dest_reg)) == INSN_UID (insn)
          /* Previous line always fails if INSN was moved by loop opt.  */
-         && uid_luid[REGNO_LAST_UID (REGNO (dest_reg))] < INSN_LUID (loop_end)
+         && uid_luid[REGNO_LAST_UID (REGNO (dest_reg))] 
+         < INSN_LUID (loop->end)
          && (! not_every_iteration
              || last_use_this_basic_block (dest_reg, insn)))
        {
@@ -5674,7 +5673,7 @@ record_giv (v, insn, src_reg, dest_reg, mult_val, add_val, benefit,
             biv update to before it, then this giv is not replaceable.  */
          if (v->replaceable)
            for (b = bl->biv; b; b = b->next_iv)
-             if (back_branch_in_range_p (b->insn, loop_start, loop_end))
+             if (back_branch_in_range_p (loop, b->insn))
                {
                  v->replaceable = 0;
                  v->not_replaceable = 1;
@@ -5772,10 +5771,9 @@ record_giv (v, insn, src_reg, dest_reg, mult_val, add_val, benefit,
    have been identified.  */
 
 static void
-check_final_value (v, loop_start, loop_end, n_iterations)
+check_final_value (loop, v)
+     const struct loop *loop;
      struct induction *v;
-     rtx loop_start, loop_end;
-     unsigned HOST_WIDE_INT n_iterations;
 {
   struct iv_class *bl;
   rtx final_value = 0;
@@ -5802,7 +5800,7 @@ check_final_value (v, loop_start, loop_end, n_iterations)
   v->replaceable = 0;
 #endif
 
-  if ((final_value = final_giv_value (v, loop_start, loop_end, n_iterations))
+  if ((final_value = final_giv_value (loop, v))
       && (v->always_computable || last_use_this_basic_block (v->dest_reg, v->insn)))
     {
       int biv_increment_seen = 0;
@@ -5834,8 +5832,8 @@ check_final_value (v, loop_start, loop_end, n_iterations)
       while (1)
        {
          p = NEXT_INSN (p);
-         if (p == loop_end)
-           p = NEXT_INSN (loop_start);
+         if (p == loop->end)
+           p = NEXT_INSN (loop->start);
          if (p == v->insn)
            break;
 
@@ -5868,17 +5866,17 @@ check_final_value (v, loop_start, loop_end, n_iterations)
          while (1)
            {
              p = NEXT_INSN (p);
-             if (p == loop_end)
-               p = NEXT_INSN (loop_start);
+             if (p == loop->end)
+               p = NEXT_INSN (loop->start);
              if (p == last_giv_use)
                break;
 
              if (GET_CODE (p) == JUMP_INSN && JUMP_LABEL (p)
                  && LABEL_NAME (JUMP_LABEL (p))
                  && ((loop_insn_first_p (JUMP_LABEL (p), v->insn)
-                      && loop_insn_first_p (loop_start, JUMP_LABEL (p)))
+                      && loop_insn_first_p (loop->start, JUMP_LABEL (p)))
                      || (loop_insn_first_p (last_giv_use, JUMP_LABEL (p))
-                         && loop_insn_first_p (JUMP_LABEL (p), loop_end))))
+                         && loop_insn_first_p (JUMP_LABEL (p), loop->end))))
                {
                  v->replaceable = 0;
                  v->not_replaceable = 1;
@@ -5914,7 +5912,8 @@ check_final_value (v, loop_start, loop_end, n_iterations)
    The cases we look at are when a label or an update to a biv is passed.  */
 
 static void
-update_giv_derive (p)
+update_giv_derive (loop, p)
+     const  struct loop *loop;
      rtx p;
 {
   struct iv_class *bl;
@@ -5982,14 +5981,16 @@ update_giv_derive (p)
                  tem = 0;
 
                  if (biv->mult_val == const1_rtx)
-                   tem = simplify_giv_expr (gen_rtx_MULT (giv->mode,
+                   tem = simplify_giv_expr (loop,
+                                            gen_rtx_MULT (giv->mode,
                                                           biv->add_val,
                                                           giv->mult_val),
                                             &dummy);
 
                  if (tem && giv->derive_adjustment)
                    tem = simplify_giv_expr
-                     (gen_rtx_PLUS (giv->mode, tem, giv->derive_adjustment),
+                     (loop,
+                      gen_rtx_PLUS (giv->mode, tem, giv->derive_adjustment),
                       &dummy);
 
                  if (tem)
@@ -6042,13 +6043,13 @@ update_giv_derive (p)
    If we cannot find a biv, we return 0.  */
 
 static int
-basic_induction_var (x, mode, dest_reg, p, level, inc_val, mult_val,
+basic_induction_var (loop, x, mode, dest_reg, p, inc_val, mult_val,
                     location, multi_insn_incr)
+     const struct loop *loop;
      register rtx x;
      enum machine_mode mode;
      rtx dest_reg;
      rtx p;
-     int level;
      rtx *inc_val;
      rtx *mult_val;
      rtx **location;
@@ -6081,7 +6082,7 @@ basic_induction_var (x, mode, dest_reg, p, level, inc_val, mult_val,
        return 0;
 
       arg = *argp;
-      if (invariant_p (arg) != 1)
+      if (loop_invariant_p (loop, arg) != 1)
        return 0;
 
       *inc_val = convert_modes (GET_MODE (dest_reg), GET_MODE (x), arg, 0);
@@ -6093,9 +6094,9 @@ basic_induction_var (x, mode, dest_reg, p, level, inc_val, mult_val,
       /* If this is a SUBREG for a promoted variable, check the inner
         value.  */
       if (SUBREG_PROMOTED_VAR_P (x))
-       return basic_induction_var (SUBREG_REG (x), GET_MODE (SUBREG_REG (x)),
-                                   dest_reg, p, level, 
-                                   inc_val, mult_val, location,
+       return basic_induction_var (loop, SUBREG_REG (x),
+                                   GET_MODE (SUBREG_REG (x)),
+                                   dest_reg, p, inc_val, mult_val, location,
                                    multi_insn_incr);
       return 0;
 
@@ -6124,11 +6125,11 @@ basic_induction_var (x, mode, dest_reg, p, level, inc_val, mult_val,
                   && (GET_MODE_CLASS (GET_MODE (SET_DEST (set)))
                       == MODE_INT)
                   && SUBREG_REG (SET_DEST (set)) == x))
-             && basic_induction_var (SET_SRC (set),
+             && basic_induction_var (loop, SET_SRC (set),
                                      (GET_MODE (SET_SRC (set)) == VOIDmode
                                       ? GET_MODE (x)
                                       : GET_MODE (SET_SRC (set))),
-                                     dest_reg, insn, level,
+                                     dest_reg, insn,
                                      inc_val, mult_val, location,
                                      multi_insn_incr))
            {
@@ -6143,7 +6144,7 @@ basic_induction_var (x, mode, dest_reg, p, level, inc_val, mult_val,
         as a biv of the outer loop,
         causing code to be moved INTO the inner loop.  */
     case MEM:
-      if (invariant_p (x) != 1)
+      if (loop_invariant_p (loop, x) != 1)
        return 0;
     case CONST_INT:
     case SYMBOL_REF:
@@ -6151,7 +6152,7 @@ basic_induction_var (x, mode, dest_reg, p, level, inc_val, mult_val,
       /* convert_modes aborts if we try to convert to or from CCmode, so just
          exclude that case.  It is very unlikely that a condition code value
         would be a useful iterator anyways.  */
-      if (level == 0
+      if (loop->level == 1
          && GET_MODE_CLASS (mode) != MODE_CC
          && GET_MODE_CLASS (GET_MODE (dest_reg)) != MODE_CC)
        {
@@ -6164,9 +6165,9 @@ basic_induction_var (x, mode, dest_reg, p, level, inc_val, mult_val,
        return 0;
 
     case SIGN_EXTEND:
-      return basic_induction_var (XEXP (x, 0), GET_MODE (XEXP (x, 0)),
-                                 dest_reg, p, level, inc_val, mult_val,
-                                 location, multi_insn_incr);
+      return basic_induction_var (loop, XEXP (x, 0), GET_MODE (XEXP (x, 0)),
+                                 dest_reg, p, inc_val, mult_val, location,
+                                 multi_insn_incr);
 
     case ASHIFTRT:
       /* Similar, since this can be a sign extension.  */
@@ -6184,9 +6185,9 @@ basic_induction_var (x, mode, dest_reg, p, level, inc_val, mult_val,
          && INTVAL (XEXP (x, 1)) >= 0
          && GET_CODE (SET_SRC (set)) == ASHIFT
          && XEXP (x, 1) == XEXP (SET_SRC (set), 1)
-         && basic_induction_var (XEXP (SET_SRC (set), 0),
+         && basic_induction_var (loop, XEXP (SET_SRC (set), 0),
                                  GET_MODE (XEXP (x, 0)),
-                                 dest_reg, insn, level, inc_val, mult_val,
+                                 dest_reg, insn, inc_val, mult_val,
                                  location, multi_insn_incr))
        {
          *multi_insn_incr = 1;
@@ -6214,7 +6215,8 @@ basic_induction_var (x, mode, dest_reg, p, level, inc_val, mult_val,
      such that the value of X is biv * mult + add;  */
 
 static int
-general_induction_var (x, src_reg, add_val, mult_val, is_addr, pbenefit)
+general_induction_var (loop, x, src_reg, add_val, mult_val, is_addr, pbenefit)
+     const struct loop *loop;
      rtx x;
      rtx *src_reg;
      rtx *add_val;
@@ -6226,14 +6228,14 @@ general_induction_var (x, src_reg, add_val, mult_val, is_addr, pbenefit)
   char *storage;
 
   /* If this is an invariant, forget it, it isn't a giv.  */
-  if (invariant_p (x) == 1)
+  if (loop_invariant_p (loop, x) == 1)
     return 0;
 
   /* See if the expression could be a giv and get its form.
      Mark our place on the obstack in case we don't find a giv.  */
   storage = (char *) oballoc (0);
   *pbenefit = 0;
-  x = simplify_giv_expr (x, pbenefit);
+  x = simplify_giv_expr (loop, x, pbenefit);
   if (x == 0)
     {
       obfree (storage);
@@ -6336,7 +6338,8 @@ static int cmp_combine_givs_stats PARAMS ((const PTR, const PTR));
 static int cmp_recombine_givs_stats PARAMS ((const PTR, const PTR));
 
 static rtx
-simplify_giv_expr (x, benefit)
+simplify_giv_expr (loop, x, benefit)
+     const struct loop *loop;
      rtx x;
      int *benefit;
 {
@@ -6354,8 +6357,8 @@ simplify_giv_expr (x, benefit)
   switch (GET_CODE (x))
     {
     case PLUS:
-      arg0 = simplify_giv_expr (XEXP (x, 0), benefit);
-      arg1 = simplify_giv_expr (XEXP (x, 1), benefit);
+      arg0 = simplify_giv_expr (loop, XEXP (x, 0), benefit);
+      arg1 = simplify_giv_expr (loop, XEXP (x, 1), benefit);
       if (arg0 == 0 || arg1 == 0)
        return NULL_RTX;
 
@@ -6401,7 +6404,8 @@ simplify_giv_expr (x, benefit)
          case PLUS:
            /* (a + invar_1) + invar_2.  Associate.  */
            return
-             simplify_giv_expr (gen_rtx_PLUS (mode,
+             simplify_giv_expr (loop,
+                                gen_rtx_PLUS (mode,
                                               XEXP (arg0, 0),
                                               gen_rtx_PLUS (mode,
                                                             XEXP (arg0, 1),
@@ -6427,7 +6431,8 @@ simplify_giv_expr (x, benefit)
 
       if (GET_CODE (arg1) == PLUS)
          return
-           simplify_giv_expr (gen_rtx_PLUS (mode,
+           simplify_giv_expr (loop,
+                              gen_rtx_PLUS (mode,
                                             gen_rtx_PLUS (mode, arg0,
                                                           XEXP (arg1, 0)),
                                             XEXP (arg1, 1)),
@@ -6440,7 +6445,8 @@ simplify_giv_expr (x, benefit)
       if (!rtx_equal_p (arg0, arg1))
        return NULL_RTX;
 
-      return simplify_giv_expr (gen_rtx_MULT (mode,
+      return simplify_giv_expr (loop,
+                               gen_rtx_MULT (mode,
                                              XEXP (arg0, 0),
                                              gen_rtx_PLUS (mode,
                                                            XEXP (arg0, 1),
@@ -6449,7 +6455,8 @@ simplify_giv_expr (x, benefit)
 
     case MINUS:
       /* Handle "a - b" as "a + b * (-1)".  */
-      return simplify_giv_expr (gen_rtx_PLUS (mode,
+      return simplify_giv_expr (loop,
+                               gen_rtx_PLUS (mode,
                                              XEXP (x, 0),
                                              gen_rtx_MULT (mode,
                                                            XEXP (x, 1),
@@ -6457,8 +6464,8 @@ simplify_giv_expr (x, benefit)
                                benefit);
 
     case MULT:
-      arg0 = simplify_giv_expr (XEXP (x, 0), benefit);
-      arg1 = simplify_giv_expr (XEXP (x, 1), benefit);
+      arg0 = simplify_giv_expr (loop, XEXP (x, 0), benefit);
+      arg1 = simplify_giv_expr (loop, XEXP (x, 1), benefit);
       if (arg0 == 0 || arg1 == 0)
        return NULL_RTX;
 
@@ -6511,7 +6518,8 @@ simplify_giv_expr (x, benefit)
 
        case MULT:
          /* (a * invar_1) * invar_2.  Associate.  */
-         return simplify_giv_expr (gen_rtx_MULT (mode,
+         return simplify_giv_expr (loop,
+                                   gen_rtx_MULT (mode,
                                                  XEXP (arg0, 0),
                                                  gen_rtx_MULT (mode,
                                                                XEXP (arg0, 1),
@@ -6520,7 +6528,8 @@ simplify_giv_expr (x, benefit)
 
        case PLUS:
          /* (a + invar_1) * invar_2.  Distribute.  */
-         return simplify_giv_expr (gen_rtx_PLUS (mode,
+         return simplify_giv_expr (loop,
+                                   gen_rtx_PLUS (mode,
                                                  gen_rtx_MULT (mode,
                                                                XEXP (arg0, 0),
                                                                arg1),
@@ -6539,7 +6548,8 @@ simplify_giv_expr (x, benefit)
        return 0;
 
       return
-       simplify_giv_expr (gen_rtx_MULT (mode,
+       simplify_giv_expr (loop,
+                          gen_rtx_MULT (mode,
                                         XEXP (x, 0),
                                         GEN_INT ((HOST_WIDE_INT) 1
                                                  << INTVAL (XEXP (x, 1)))),
@@ -6547,12 +6557,14 @@ simplify_giv_expr (x, benefit)
 
     case NEG:
       /* "-a" is "a * (-1)" */
-      return simplify_giv_expr (gen_rtx_MULT (mode, XEXP (x, 0), constm1_rtx),
+      return simplify_giv_expr (loop,
+                               gen_rtx_MULT (mode, XEXP (x, 0), constm1_rtx),
                                benefit);
 
     case NOT:
       /* "~a" is "-a - 1". Silly, but easy.  */
-      return simplify_giv_expr (gen_rtx_MINUS (mode,
+      return simplify_giv_expr (loop,
+                               gen_rtx_MINUS (mode,
                                               gen_rtx_NEG (mode, XEXP (x, 0)),
                                               const1_rtx),
                                benefit);
@@ -6587,14 +6599,14 @@ simplify_giv_expr (x, benefit)
 
            if (v->derive_adjustment)
              tem = gen_rtx_MINUS (mode, tem, v->derive_adjustment);
-           return simplify_giv_expr (tem, benefit);
+           return simplify_giv_expr (loop, tem, benefit);
          }
 
        default:
          /* If it isn't an induction variable, and it is invariant, we
             may be able to simplify things further by looking through
             the bits we just moved outside the loop.  */
-         if (invariant_p (x) == 1)
+         if (loop_invariant_p (loop, x) == 1)
            {
              struct movable *m;
 
@@ -6606,7 +6618,8 @@ simplify_giv_expr (x, benefit)
                    /* If we match another movable, we must use that, as 
                       this one is going away.  */
                    if (m->match)
-                     return simplify_giv_expr (m->match->set_dest, benefit);
+                     return simplify_giv_expr (loop, m->match->set_dest, 
+                                               benefit);
 
                    /* If consec is non-zero, this is a member of a group of
                       instructions that were moved together.  We handle this
@@ -6640,7 +6653,7 @@ simplify_giv_expr (x, benefit)
                            || GET_CODE (tem) == CONST_INT
                            || GET_CODE (tem) == SYMBOL_REF)
                          {
-                           tem = simplify_giv_expr (tem, benefit);
+                           tem = simplify_giv_expr (loop, tem, benefit);
                            if (tem)
                              return tem;
                          }
@@ -6649,7 +6662,8 @@ simplify_giv_expr (x, benefit)
                            && GET_CODE (XEXP (XEXP (tem, 0), 0)) == SYMBOL_REF
                            && GET_CODE (XEXP (XEXP (tem, 0), 1)) == CONST_INT)
                          {
-                           tem = simplify_giv_expr (XEXP (tem, 0), benefit);
+                           tem = simplify_giv_expr (loop, XEXP (tem, 0),
+                                                    benefit);
                            if (tem)
                              return tem;
                          }
@@ -6667,7 +6681,7 @@ simplify_giv_expr (x, benefit)
       if (GET_CODE (x) == USE)
        x = XEXP (x, 0);
 
-      if (invariant_p (x) == 1)
+      if (loop_invariant_p (loop, x) == 1)
        {
          if (GET_CODE (x) == CONST_INT)
            return x;
@@ -6753,8 +6767,9 @@ sge_plus (mode, x, y)
    *MULT_VAL and *ADD_VAL.  */
 
 static int
-consec_sets_giv (first_benefit, p, src_reg, dest_reg,
+consec_sets_giv (loop, first_benefit, p, src_reg, dest_reg,
                 add_val, mult_val, last_consec_insn)
+     const struct loop *loop;
      int first_benefit;
      rtx p;
      rtx src_reg;
@@ -6803,11 +6818,11 @@ consec_sets_giv (first_benefit, p, src_reg, dest_reg,
          && (set = single_set (p))
          && GET_CODE (SET_DEST (set)) == REG
          && SET_DEST (set) == dest_reg
-         && (general_induction_var (SET_SRC (set), &src_reg,
+         && (general_induction_var (loop, SET_SRC (set), &src_reg,
                                     add_val, mult_val, 0, &benefit)
              /* Giv created by equivalent expression.  */
              || ((temp = find_reg_note (p, REG_EQUAL, NULL_RTX))
-                 && general_induction_var (XEXP (temp, 0), &src_reg,
+                 && general_induction_var (loop, XEXP (temp, 0), &src_reg,
                                            add_val, mult_val, 0, &benefit)))
          && src_reg == v->src_reg)
        {
@@ -7380,9 +7395,9 @@ find_life_end (x, stats, insn, biv)
    This tends to shorten giv lifetimes, and helps the next step:
    try to derive givs from other givs.  */
 static void
-recombine_givs (bl, loop_start, loop_end, unroll_p)
+recombine_givs (loop, bl, unroll_p)
+     const struct loop *loop;
      struct iv_class *bl;
-     rtx loop_start, loop_end;
      int unroll_p;
 {
   struct induction *v, **giv_array, *last_giv;
@@ -7535,7 +7550,7 @@ recombine_givs (bl, loop_start, loop_end, unroll_p)
              else
                {
                  stats[i].end_luid = uid_luid[REGNO_LAST_UID (regno)];
-                 if (stats[i].end_luid > INSN_LUID (loop_end))
+                 if (stats[i].end_luid > INSN_LUID (loop->end))
                    {
                      stats[i].end_luid = -1;
                      ends_need_computing++;
@@ -7550,12 +7565,12 @@ recombine_givs (bl, loop_start, loop_end, unroll_p)
   if (ends_need_computing)
     {
       rtx biv = bl->biv->src_reg;
-      rtx p = loop_end;
+      rtx p = loop->end;
 
       do
        {
-         if (p == loop_start)
-           p = loop_end;
+         if (p == loop->start)
+           p = loop->end;
          p = PREV_INSN (p);
          if (GET_RTX_CLASS (GET_CODE (p)) != 'i')
            continue;
@@ -7641,8 +7656,8 @@ recombine_givs (bl, loop_start, loop_end, unroll_p)
                  derived giv would defeat the purpose of reducing register
                  pressure.
                  ??? We could arrange to move the insn.  */
-             && ((unsigned) stats[i].end_luid - INSN_LUID (loop_start)
-                  > (unsigned) stats[i].start_luid - INSN_LUID (loop_start))
+             && ((unsigned) stats[i].end_luid - INSN_LUID (loop->start)
+                  > (unsigned) stats[i].start_luid - INSN_LUID (loop->start))
              && rtx_equal_p (last_giv->mult_val, v->mult_val)
              /* ??? Could handle libcalls, but would need more logic.  */
              && ! find_reg_note (v->insn, REG_RETVAL, NULL_RTX)
@@ -7854,13 +7869,13 @@ check_dbra_loop (loop, insn_count)
   int compare_and_branch;
   rtx loop_start = loop->start;
   rtx loop_end = loop->end;
-  struct loop_info *loop_info = loop->info;
+  struct loop_info *loop_info = LOOP_INFO (loop);
 
   /* If last insn is a conditional branch, and the insn before tests a
      register value, try to optimize it.  Otherwise, we can't do anything.  */
 
   jump = PREV_INSN (loop_end);
-  comparison = get_condition_for_loop (jump);
+  comparison = get_condition_for_loop (loop, jump);
   if (comparison == 0)
     return 0;
 
@@ -7931,7 +7946,7 @@ check_dbra_loop (loop, insn_count)
          if (GET_CODE (p) != JUMP_INSN)
            continue;
 
-         before_comparison = get_condition_for_loop (p);
+         before_comparison = get_condition_for_loop (loop, p);
          if (before_comparison
              && XEXP (before_comparison, 0) == bl->biv->dest_reg
              && GET_CODE (before_comparison) == LT
@@ -7969,8 +7984,7 @@ check_dbra_loop (loop, insn_count)
         which is reversible.  */
       int reversible_mem_store = 1;
 
-      if (bl->giv_count == 0
-         && ! uid_loop[INSN_UID (loop_start)]->exit_count)
+      if (bl->giv_count == 0 && ! loop->exit_count)
        {
          rtx bivreg = regno_reg_rtx[bl->regno];
 
@@ -8018,7 +8032,7 @@ check_dbra_loop (loop, insn_count)
        {
          for (p = loop_start; p != loop_end; p = NEXT_INSN (p))
            if (GET_RTX_CLASS (GET_CODE (p)) == 'i')
-             num_nonfixed_reads += count_nonfixed_reads (PATTERN (p));
+             num_nonfixed_reads += count_nonfixed_reads (loop, PATTERN (p));
 
          /* If the loop has a single store, and the destination address is
             invariant, then we can't reverse the loop, because this address
@@ -8033,7 +8047,9 @@ check_dbra_loop (loop, insn_count)
              reversible_mem_store
                = (! unknown_address_altered
                   && ! unknown_constant_address_altered
-                  && ! invariant_p (XEXP (XEXP (loop_store_mems, 0), 0)));
+                  && ! loop_invariant_p (loop,
+                                         XEXP (XEXP (loop_store_mems, 0),
+                                               0)));
 
              /* If the store depends on a register that is set after the
                 store, it depends on the initial value, and is thus not
@@ -8115,7 +8131,7 @@ check_dbra_loop (loop, insn_count)
                 ??? If the insns which initialize the comparison value as
                 a whole compute an invariant result, then we could move
                 them out of the loop and proceed with loop reversal.  */
-             if (!invariant_p (comparison_value))
+             if (! loop_invariant_p (loop, comparison_value))
                return 0;
 
              if (GET_CODE (comparison_value) == CONST_INT)
@@ -8403,7 +8419,6 @@ check_dbra_loop (loop, insn_count)
 \f
 /* Verify whether the biv BL appears to be eliminable,
    based on the insns in the loop that refer to it.
-   LOOP_START is the first insn of the loop, and END is the end insn.
 
    If ELIMINATE_P is non-zero, actually do the elimination.
 
@@ -8412,15 +8427,15 @@ check_dbra_loop (loop, insn_count)
    start of the loop.  */
 
 static int
-maybe_eliminate_biv (bl, loop_start, loop_end, eliminate_p, threshold,
-                    insn_count)
+maybe_eliminate_biv (loop, bl, eliminate_p, threshold, insn_count)
+     const struct loop *loop;
      struct iv_class *bl;
-     rtx loop_start;
-     rtx loop_end;
      int eliminate_p;
      int threshold, insn_count;
 {
   rtx reg = bl->biv->dest_reg;
+  rtx loop_start = loop->start;
+  rtx loop_end = loop->end;
   rtx p;
 
   /* Scan all insns in the loop, stopping if we find one that uses the
@@ -8443,7 +8458,7 @@ maybe_eliminate_biv (bl, loop_start, loop_end, eliminate_p, threshold,
 
              if (set && GET_CODE (SET_DEST (set)) == REG)
                {
-                 int regno = REGNO (SET_DEST (set));
+                 unsigned int regno = REGNO (SET_DEST (set));
 
                  if (regno < max_reg_before_loop
                      && REG_IV_TYPE (regno) == GENERAL_INDUCT
@@ -8454,7 +8469,8 @@ maybe_eliminate_biv (bl, loop_start, loop_end, eliminate_p, threshold,
        }
       if ((code == INSN || code == JUMP_INSN || code == CALL_INSN)
          && reg_mentioned_p (reg, PATTERN (p))
-         && ! maybe_eliminate_biv_1 (PATTERN (p), p, bl, eliminate_p, where))
+         && ! maybe_eliminate_biv_1 (loop, PATTERN (p), p, bl,
+                                     eliminate_p, where))
        {
          if (loop_dump_stream)
            fprintf (loop_dump_stream,
@@ -8558,7 +8574,8 @@ biv_elimination_giv_has_0_offset (biv, giv, insn)
    the loop.  */
 
 static int
-maybe_eliminate_biv_1 (x, insn, bl, eliminate_p, where)
+maybe_eliminate_biv_1 (loop, x, insn, bl, eliminate_p, where)
+     const struct loop *loop;
      rtx x, insn;
      struct iv_class *bl;
      int eliminate_p;
@@ -8777,7 +8794,7 @@ maybe_eliminate_biv_1 (x, insn, bl, eliminate_p, where)
        }
       else if (GET_CODE (arg) == REG || GET_CODE (arg) == MEM)
        {
-         if (invariant_p (arg) == 1)
+         if (loop_invariant_p (loop, arg) == 1)
            {
              /* Look for giv with constant positive mult_val and nonconst
                 add_val. Insert insns to compute new compare value. 
@@ -8884,14 +8901,14 @@ maybe_eliminate_biv_1 (x, insn, bl, eliminate_p, where)
       switch (fmt[i])
        {
        case 'e':
-         if (! maybe_eliminate_biv_1 (XEXP (x, i), insn, bl, 
+         if (! maybe_eliminate_biv_1 (loop, XEXP (x, i), insn, bl, 
                                       eliminate_p, where))
            return 0;
          break;
 
        case 'E':
          for (j = XVECLEN (x, i) - 1; j >= 0; j--)
-           if (! maybe_eliminate_biv_1 (XVECEXP (x, i, j), insn, bl,
+           if (! maybe_eliminate_biv_1 (loop, XVECEXP (x, i, j), insn, bl,
                                         eliminate_p, where))
              return 0;
          break;
@@ -8979,32 +8996,34 @@ update_reg_last_use (x, insn)
     }
 }
 \f
-/* 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 non-zero, 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.
-
-   The condition will be returned in a canonical form to simplify testing by
-   callers.  Specifically:
+/* 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.  */
+       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 non-zero, then reverse the condition prior to canonizing it.
+
+   If EARLIEST is non-zero, 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.  */
 
 rtx
-get_condition (jump, earliest)
-     rtx jump;
+canonicalize_condition (insn, cond, reverse, earliest)
+     rtx insn;
+     rtx cond;
+     int reverse;
      rtx *earliest;
 {
   enum rtx_code code;
-  rtx prev = jump;
+  rtx prev = insn;
   rtx set;
   rtx tem;
   rtx op0, op1;
@@ -9012,24 +9031,19 @@ get_condition (jump, earliest)
   int did_reverse_condition = 0;
   enum machine_mode mode;
 
-  /* If this is not a standard conditional jump, we can't parse it.  */
-  if (GET_CODE (jump) != JUMP_INSN
-      || ! condjump_p (jump) || simplejump_p (jump))
-    return 0;
+  code = GET_CODE (cond);
+  mode = GET_MODE (cond);
+  op0 = XEXP (cond, 0);
+  op1 = XEXP (cond, 1);
 
-  code = GET_CODE (XEXP (SET_SRC (PATTERN (jump)), 0));
-  mode = GET_MODE (XEXP (SET_SRC (PATTERN (jump)), 0));
-  op0 = XEXP (XEXP (SET_SRC (PATTERN (jump)), 0), 0);
-  op1 = XEXP (XEXP (SET_SRC (PATTERN (jump)), 0), 1);
+  if (reverse)
+    {
+      code = reverse_condition (code);
+      did_reverse_condition ^= 1;
+    }
 
   if (earliest)
-    *earliest = jump;
-
-  /* If this branches to JUMP_LABEL when the condition is false, reverse
-     the condition.  */
-  if (GET_CODE (XEXP (SET_SRC (PATTERN (jump)), 2)) == LABEL_REF
-      && XEXP (XEXP (SET_SRC (PATTERN (jump)), 2), 0) == JUMP_LABEL (jump))
-    code = reverse_condition (code), did_reverse_condition ^= 1;
+    *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
@@ -9163,6 +9177,8 @@ get_condition (jump, earliest)
          if (reverse_code)
            {
              code = reverse_condition (code);
+             if (code == UNKNOWN)
+               return 0;
              did_reverse_condition ^= 1;
              reverse_code = 0;
            }
@@ -9227,9 +9243,10 @@ get_condition (jump, earliest)
     }
 
   /* If this was floating-point and we reversed anything other than an
-     EQ or NE, return zero.  */
+     EQ or NE or (UN)ORDERED, return zero.  */
   if (TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT
-      && did_reverse_condition && code != NE && code != EQ
+      && did_reverse_condition
+      && code != NE && code != EQ && code != UNORDERED && code != ORDERED
       && ! flag_fast_math
       && GET_MODE_CLASS (GET_MODE (op0)) == MODE_FLOAT)
     return 0;
@@ -9243,18 +9260,53 @@ get_condition (jump, earliest)
   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 non-zero, 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.  */
+
+rtx
+get_condition (jump, earliest)
+     rtx jump;
+     rtx *earliest;
+{
+  rtx cond;
+  int reverse;
+
+  /* If this is not a standard conditional jump, we can't parse it.  */
+  if (GET_CODE (jump) != JUMP_INSN
+      || ! condjump_p (jump) || simplejump_p (jump))
+    return 0;
+
+  cond = XEXP (SET_SRC (PATTERN (jump)), 0);
+
+  /* If this branches to JUMP_LABEL when the condition is false, reverse
+     the condition.  */
+  reverse
+    = GET_CODE (XEXP (SET_SRC (PATTERN (jump)), 2)) == LABEL_REF
+      && XEXP (XEXP (SET_SRC (PATTERN (jump)), 2), 0) == JUMP_LABEL (jump);
+
+  return canonicalize_condition (jump, cond, reverse, earliest);
+}
+
 /* Similar to above routine, except that we also put an invariant last
    unless both operands are invariants.  */
 
 rtx
-get_condition_for_loop (x)
+get_condition_for_loop (loop, x)
+     const struct loop *loop;
      rtx x;
 {
   rtx comparison = get_condition (x, NULL_PTR);
 
   if (comparison == 0
-      || ! invariant_p (XEXP (comparison, 0))
-      || invariant_p (XEXP (comparison, 1)))
+      || ! loop_invariant_p (loop, XEXP (comparison, 0))
+      || loop_invariant_p (loop, XEXP (comparison, 1)))
     return comparison;
 
   return gen_rtx_fmt_ee (swap_condition (GET_CODE (comparison)), VOIDmode,
@@ -9275,7 +9327,7 @@ insert_bct (loop)
   unsigned HOST_WIDE_INT n_iterations;
   rtx loop_start = loop->start;
   rtx loop_end = loop->end;
-  struct loop_info *loop_info = loop->info;  
+  struct loop_info *loop_info = LOOP_INFO (loop);  
   int loop_num = loop->num;
 
 #if 0
@@ -9371,7 +9423,7 @@ insert_bct (loop)
       /* Mark all enclosing loops that they cannot use count register.  */
       for (outer_loop = loop; outer_loop; outer_loop = outer_loop->outer)
        {
-         outer_loop_info = outer_loop->info;
+         outer_loop_info = LOOP_INFO (outer_loop);
          outer_loop_info->used_count_register = 1;
        }
       instrument_loop_bct (loop_start, loop_end, GEN_INT (n_iterations));
@@ -9717,6 +9769,19 @@ load_mems (loop)
   if (loop_mems_idx == 0)
     return;
 
+  /* Find start of the extended basic block that enters the loop.  */
+  for (p = loop->start;
+       PREV_INSN (p) && GET_CODE (p) != CODE_LABEL;
+       p = PREV_INSN (p))
+    ;
+
+  cselib_init ();
+
+  /* Build table of mems that get set to constant values before the
+     loop.  */
+  for (; p != loop->start; p = NEXT_INSN (p))
+    cselib_process_insn (p);
+
   /* Check to see if it's possible that some instructions in the
      loop are never executed.  */
   for (p = next_insn_in_loop (loop, loop->scan_start); 
@@ -9759,7 +9824,7 @@ load_mems (loop)
       rtx mem_list_entry;
 
       if (MEM_VOLATILE_P (mem) 
-         || invariant_p (XEXP (mem, 0)) != 1)
+         || loop_invariant_p (loop, XEXP (mem, 0)) != 1)
        /* There's no telling whether or not MEM is modified.  */
        loop_mems[i].optimize = 0;
 
@@ -9868,13 +9933,49 @@ load_mems (loop)
        loop_mems[i].optimize = 0;
       else
        {
-         int j;
+         /* Load the memory immediately before LOOP->START, which is
+            the NOTE_LOOP_BEG.  */
+         cselib_val *e = cselib_lookup (mem, VOIDmode, 0);
          rtx set;
+         rtx best = mem;
+         int j;
+         struct elt_loc_list *const_equiv = 0;
 
-         /* Load the memory immediately before START, which is
-            the NOTE_LOOP_BEG.  */
-         set = gen_move_insn (reg, mem);
-         emit_insn_before (set, loop->start);
+         if (e)
+           {
+             struct elt_loc_list *equiv;
+             struct elt_loc_list *best_equiv = 0;
+             for (equiv = e->locs; equiv; equiv = equiv->next)
+               {
+                 if (CONSTANT_P (equiv->loc))
+                   const_equiv = equiv;
+                 else if (GET_CODE (equiv->loc) == REG)
+                   best_equiv = equiv;
+               }
+             /* Use the constant equivalence if that is cheap enough.  */
+             if (! best_equiv)
+               best_equiv = const_equiv;
+             else if (const_equiv
+                      && (rtx_cost (const_equiv->loc, SET)
+                          <= rtx_cost (best_equiv->loc, SET)))
+               {
+                 best_equiv = const_equiv;
+                 const_equiv = 0;
+               }
+
+             /* If best_equiv is nonzero, we know that MEM is set to a
+                constant or register before the loop.  We will use this
+                knowledge to initialize the shadow register with that
+                constant or reg rather than by loading from MEM.  */
+             if (best_equiv)
+               best = copy_rtx (best_equiv->loc);
+           }
+         set = gen_move_insn (reg, best);
+         set = emit_insn_before (set, loop->start);
+         if (const_equiv)
+           REG_NOTES (set) = gen_rtx_EXPR_LIST (REG_EQUAL,
+                                                copy_rtx (const_equiv->loc),
+                                                REG_NOTES (set));
 
          if (written)
            {
@@ -9936,6 +10037,8 @@ load_mems (loop)
            JUMP_LABEL (p) = label;
        }
     }
+
+  cselib_finish ();
 }
 
 /* For communication between note_reg_stored and its caller.  */
@@ -9960,13 +10063,13 @@ note_reg_stored (x, setter, arg)
 /* Try to replace every occurrence of pseudo REGNO with REPLACEMENT.
    There must be exactly one insn that sets this pseudo; it will be
    deleted if all replacements succeed and we can prove that the register
-   is not used after the loop.
-   The arguments SCAN_START, LOOP_TOP and END are as in load_mems.  */
+   is not used after the loop.  */
+
 static void
 try_copy_prop (loop, replacement, regno)
      const struct loop *loop;
      rtx replacement;
-     int regno;
+     unsigned int regno;
 {
   /* This is the reg that we are copying from.  */
   rtx reg_rtx = regno_reg_rtx[regno];