OSDN Git Service

2004-07-20 Frank Ch. Eigler <fche@redhat.com>
[pf3gnuchains/gcc-fork.git] / gcc / loop.c
index bc75f8b..a6353d7 100644 (file)
@@ -1,6 +1,6 @@
 /* Perform various loop optimizations, including strength reduction.
    Copyright (C) 1987, 1988, 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
-   1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+   1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -22,8 +22,16 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 /* This is the loop optimization pass of the compiler.
    It finds invariant computations within loops and moves them
    to the beginning of the loop.  Then it identifies basic and
-   general induction variables.  Strength reduction is applied to the general
-   induction variables, and induction variable elimination is applied to
+   general induction variables.
+
+   Basic induction variables (BIVs) are a pseudo registers which are set within
+   a loop only by incrementing or decrementing its value.  General induction
+   variables (GIVs) are pseudo registers with a value which is a linear function
+   of a basic induction variable.  BIVs are recognized by `basic_induction_var';
+   GIVs by `general_induction_var'.
+
+   Once induction variables are identified, strength reduction is applied to the
+   general induction variables, and induction variable elimination is applied to
    the basic induction variables.
 
    It also finds cases where
@@ -36,9 +44,10 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 
 #include "config.h"
 #include "system.h"
+#include "coretypes.h"
+#include "tm.h"
 #include "rtl.h"
 #include "tm_p.h"
-#include "obstack.h"
 #include "function.h"
 #include "expr.h"
 #include "hard-reg-set.h"
@@ -55,6 +64,8 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "predict.h"
 #include "insn-flags.h"
 #include "optabs.h"
+#include "cfgloop.h"
+#include "ggc.h"
 
 /* Not really meaningful values, but at least something.  */
 #ifndef SIMULTANEOUS_PREFETCHES
@@ -69,7 +80,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #define gen_prefetch(a,b,c) (abort(), NULL_RTX)
 #endif
 
-/* Give up the prefetch optimizations once we exceed a given threshhold.
+/* Give up the prefetch optimizations once we exceed a given threshold.
    It is unlikely that we would be able to optimize something in a loop
    with so many detected prefetches.  */
 #define MAX_PREFETCHES 100
@@ -79,12 +90,9 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 /* For very tiny loops it is not worthwhile to prefetch even before the loop,
    since it is likely that the data are already in the cache.  */
 #define PREFETCH_BLOCKS_BEFORE_LOOP_MIN  2
-/* The minimal number of prefetch blocks that a loop must consume to make
-   the emitting of prefetch instruction in the body of loop worthwhile.  */
-#define PREFETCH_BLOCKS_IN_LOOP_MIN  6
 
 /* Parameterize some prefetch heuristics so they can be turned on and off
-   easily for performance testing on new architecures.  These can be
+   easily for performance testing on new architectures.  These can be
    defined in target-dependent files.  */
 
 /* Prefetch is worthwhile only when loads/stores are dense.  */
@@ -146,12 +154,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #define PREFETCH_CONDITIONAL 1
 #endif
 
-/* If the loop requires more prefetches than the target can process in
-   parallel then don't prefetch anything in that loop.  */
-#ifndef PREFETCH_LIMIT_TO_SIMULTANEOUS
-#define PREFETCH_LIMIT_TO_SIMULTANEOUS 1
-#endif
-
 #define LOOP_REG_LIFETIME(LOOP, REGNO) \
 ((REGNO_LAST_LUID (REGNO) - REGNO_FIRST_LUID (REGNO)))
 
@@ -161,7 +163,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 
 #define LOOP_REGNO_NREGS(REGNO, SET_DEST) \
 ((REGNO) < FIRST_PSEUDO_REGISTER \
- ? HARD_REGNO_NREGS ((REGNO), GET_MODE (SET_DEST)) : 1)
+ ? (int) hard_regno_nregs[(REGNO)][GET_MODE (SET_DEST)] : 1)
 
 
 /* Vector mapping INSN_UIDs to luids.
@@ -179,10 +181,6 @@ struct loop **uid_loop;
 
 int max_uid_for_loop;
 
-/* 1 + luid of last insn.  */
-
-static int max_luid;
-
 /* Number of loops detected in current function.  Used as index to the
    next few tables.  */
 
@@ -194,9 +192,6 @@ unsigned int max_reg_before_loop;
 
 /* The value to pass to the next call of reg_scan_update.  */
 static int loop_max_reg;
-
-#define obstack_chunk_alloc xmalloc
-#define obstack_chunk_free free
 \f
 /* During the analysis of a loop, a chain of `struct movable's
    is made to record all the movable insns found.
@@ -218,6 +213,9 @@ struct movable
   short savings;               /* Number of insns we can move for this reg,
                                   including other movables that force this
                                   or match this one.  */
+  ENUM_BITFIELD(machine_mode) savemode : 8;   /* Nonzero means it is a mode for
+                                  a low part that we should avoid changing when
+                                  clearing the rest of the reg.  */
   unsigned int cond : 1;       /* 1 if only conditionally movable */
   unsigned int force : 1;      /* 1 means MUST move this insn */
   unsigned int global : 1;     /* 1 means reg is live outside this loop */
@@ -234,9 +232,9 @@ struct movable
   unsigned int move_insn_first:1;/* Same as above, if this is necessary for the
                                    first insn of a consecutive sets group.  */
   unsigned int is_equiv : 1;   /* 1 means a REG_EQUIV is present on INSN.  */
-  enum machine_mode savemode;   /* Nonzero means it is a mode for a low part
-                                  that we should avoid changing when clearing
-                                  the rest of the reg.  */
+  unsigned int insert_temp : 1;  /* 1 means we copy to a new pseudo and replace
+                                   the original insn with a copy from that
+                                   pseudo, rather than deleting it.  */
   struct movable *match;       /* First entry for same value */
   struct movable *forces;      /* An insn that must be moved if this is */
   struct movable *next;
@@ -247,138 +245,123 @@ FILE *loop_dump_stream;
 
 /* Forward declarations.  */
 
-static void invalidate_loops_containing_label PARAMS ((rtx));
-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 ((const struct loop *,
-                                           rtx, int, rtx));
-static int labels_in_range_p PARAMS ((rtx, int));
-static void count_one_set PARAMS ((struct loop_regs *, rtx, rtx, rtx *));
-static void note_addr_stored PARAMS ((rtx, rtx, void *));
-static void note_set_pseudo_multiple_uses PARAMS ((rtx, rtx, void *));
-static int loop_reg_used_before_p PARAMS ((const struct loop *, rtx, rtx));
-static void scan_loop PARAMS ((struct loop*, int));
+static void invalidate_loops_containing_label (rtx);
+static void find_and_verify_loops (rtx, struct loops *);
+static void mark_loop_jump (rtx, struct loop *);
+static void prescan_loop (struct loop *);
+static int reg_in_basic_block_p (rtx, rtx);
+static int consec_sets_invariant_p (const struct loop *, rtx, int, rtx);
+static int labels_in_range_p (rtx, int);
+static void count_one_set (struct loop_regs *, rtx, rtx, rtx *);
+static void note_addr_stored (rtx, rtx, void *);
+static void note_set_pseudo_multiple_uses (rtx, rtx, void *);
+static int loop_reg_used_before_p (const struct loop *, rtx, rtx);
+static rtx find_regs_nested (rtx, rtx);
+static void scan_loop (struct loop*, int);
 #if 0
-static void replace_call_address PARAMS ((rtx, rtx, rtx));
+static void replace_call_address (rtx, rtx, rtx);
 #endif
-static rtx skip_consec_insns PARAMS ((rtx, int));
-static int libcall_benefit PARAMS ((rtx));
-static void ignore_some_movables PARAMS ((struct loop_movables *));
-static void force_movables PARAMS ((struct loop_movables *));
-static void combine_movables PARAMS ((struct loop_movables *,
-                                     struct loop_regs *));
-static int num_unmoved_movables PARAMS ((const struct loop *));
-static int regs_match_p PARAMS ((rtx, rtx, struct loop_movables *));
-static int rtx_equal_for_loop_p PARAMS ((rtx, rtx, struct loop_movables *,
-                                        struct loop_regs *));
-static void add_label_notes PARAMS ((rtx, rtx));
-static void move_movables PARAMS ((struct loop *loop, struct loop_movables *,
-                                  int, int));
-static void loop_movables_add PARAMS((struct loop_movables *,
-                                     struct movable *));
-static void loop_movables_free PARAMS((struct loop_movables *));
-static int count_nonfixed_reads PARAMS ((const struct loop *, rtx));
-static void loop_bivs_find PARAMS((struct loop *));
-static void loop_bivs_init_find PARAMS((struct loop *));
-static void loop_bivs_check PARAMS((struct loop *));
-static void loop_givs_find PARAMS((struct loop *));
-static void loop_givs_check PARAMS((struct loop *));
-static int loop_biv_eliminable_p PARAMS((struct loop *, struct iv_class *,
-                                        int, int));
-static int loop_giv_reduce_benefit PARAMS((struct loop *, struct iv_class *,
-                                          struct induction *, rtx));
-static void loop_givs_dead_check PARAMS((struct loop *, struct iv_class *));
-static void loop_givs_reduce PARAMS((struct loop *, struct iv_class *));
-static void loop_givs_rescan PARAMS((struct loop *, struct iv_class *,
-                                    rtx *));
-static void loop_ivs_free PARAMS((struct loop *));
-static void strength_reduce PARAMS ((struct loop *, int));
-static void find_single_use_in_loop PARAMS ((struct loop_regs *, rtx, rtx));
-static int valid_initial_value_p PARAMS ((rtx, rtx, int, rtx));
-static void find_mem_givs PARAMS ((const struct loop *, rtx, rtx, int, int));
-static void record_biv PARAMS ((struct loop *, struct induction *,
-                               rtx, rtx, rtx, rtx, rtx *,
-                               int, int));
-static void check_final_value PARAMS ((const struct loop *,
-                                      struct induction *));
-static void loop_ivs_dump PARAMS((const struct loop *, FILE *, int));
-static void loop_iv_class_dump PARAMS((const struct iv_class *, FILE *, int));
-static void loop_biv_dump PARAMS((const struct induction *, FILE *, int));
-static void loop_giv_dump PARAMS((const struct induction *, FILE *, int));
-static void record_giv PARAMS ((const struct loop *, struct induction *,
-                               rtx, rtx, rtx, rtx, rtx, rtx, int,
-                               enum g_types, int, int, rtx *));
-static void update_giv_derive PARAMS ((const struct loop *, rtx));
-static void check_ext_dependent_givs PARAMS ((struct iv_class *,
-                                             struct loop_info *));
-static int basic_induction_var PARAMS ((const struct loop *, rtx,
-                                       enum machine_mode, rtx, rtx,
-                                       rtx *, rtx *, rtx **));
-static rtx simplify_giv_expr PARAMS ((const struct loop *, rtx, rtx *, int *));
-static int general_induction_var PARAMS ((const struct loop *loop, rtx, rtx *,
-                                         rtx *, rtx *, rtx *, int, int *,
-                                         enum machine_mode));
-static int consec_sets_giv PARAMS ((const struct loop *, int, rtx,
-                                   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 int cmp_combine_givs_stats PARAMS ((const PTR, const PTR));
-static void combine_givs PARAMS ((struct loop_regs *, struct iv_class *));
-static int product_cheap_p PARAMS ((rtx, rtx));
-static int maybe_eliminate_biv PARAMS ((const struct loop *, struct iv_class *,
-                                       int, int, int));
-static int maybe_eliminate_biv_1 PARAMS ((const struct loop *, rtx, rtx,
-                                         struct iv_class *, int,
-                                         basic_block, 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 loop_regs_scan PARAMS ((const struct loop *, int));
-static int count_insns_in_loop PARAMS ((const struct loop *));
-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 void replace_loop_mems PARAMS ((rtx, rtx, rtx));
-static int replace_loop_reg PARAMS ((rtx *, void *));
-static void replace_loop_regs PARAMS ((rtx insn, rtx, rtx));
-static void note_reg_stored PARAMS ((rtx, rtx, void *));
-static void try_copy_prop PARAMS ((const struct loop *, rtx, unsigned int));
-static void try_swap_copy_prop PARAMS ((const struct loop *, rtx,
-                                        unsigned int));
-static int replace_label PARAMS ((rtx *, void *));
-static rtx check_insn_for_givs PARAMS((struct loop *, rtx, int, int));
-static rtx check_insn_for_bivs PARAMS((struct loop *, rtx, int, int));
-static rtx gen_add_mult PARAMS ((rtx, rtx, rtx, rtx));
-static void loop_regs_update PARAMS ((const struct loop *, rtx));
-static int iv_add_mult_cost PARAMS ((rtx, rtx, rtx, rtx));
-
-static rtx loop_insn_emit_after PARAMS((const struct loop *, basic_block,
-                                       rtx, rtx));
-static rtx loop_call_insn_emit_before PARAMS((const struct loop *,
-                                             basic_block, rtx, rtx));
-static rtx loop_call_insn_hoist PARAMS((const struct loop *, rtx));
-static rtx loop_insn_sink_or_swim PARAMS((const struct loop *, rtx));
-
-static void loop_dump_aux PARAMS ((const struct loop *, FILE *, int));
-static void loop_delete_insns PARAMS ((rtx, rtx));
-static HOST_WIDE_INT remove_constant_addition PARAMS ((rtx *));
-static rtx gen_load_of_final_value PARAMS ((rtx, rtx));
-void debug_ivs PARAMS ((const struct loop *));
-void debug_iv_class PARAMS ((const struct iv_class *));
-void debug_biv PARAMS ((const struct induction *));
-void debug_giv PARAMS ((const struct induction *));
-void debug_loop PARAMS ((const struct loop *));
-void debug_loops PARAMS ((const struct loops *));
-
-typedef struct rtx_pair
-{
-  rtx r1;
-  rtx r2;
-} rtx_pair;
+static rtx skip_consec_insns (rtx, int);
+static int libcall_benefit (rtx);
+static rtx libcall_other_reg (rtx, rtx);
+static void record_excess_regs (rtx, rtx, rtx *);
+static void ignore_some_movables (struct loop_movables *);
+static void force_movables (struct loop_movables *);
+static void combine_movables (struct loop_movables *, struct loop_regs *);
+static int num_unmoved_movables (const struct loop *);
+static int regs_match_p (rtx, rtx, struct loop_movables *);
+static int rtx_equal_for_loop_p (rtx, rtx, struct loop_movables *,
+                                struct loop_regs *);
+static void add_label_notes (rtx, rtx);
+static void move_movables (struct loop *loop, struct loop_movables *, int,
+                          int);
+static void loop_movables_add (struct loop_movables *, struct movable *);
+static void loop_movables_free (struct loop_movables *);
+static int count_nonfixed_reads (const struct loop *, rtx);
+static void loop_bivs_find (struct loop *);
+static void loop_bivs_init_find (struct loop *);
+static void loop_bivs_check (struct loop *);
+static void loop_givs_find (struct loop *);
+static void loop_givs_check (struct loop *);
+static int loop_biv_eliminable_p (struct loop *, struct iv_class *, int, int);
+static int loop_giv_reduce_benefit (struct loop *, struct iv_class *,
+                                   struct induction *, rtx);
+static void loop_givs_dead_check (struct loop *, struct iv_class *);
+static void loop_givs_reduce (struct loop *, struct iv_class *);
+static void loop_givs_rescan (struct loop *, struct iv_class *, rtx *);
+static void loop_ivs_free (struct loop *);
+static void strength_reduce (struct loop *, int);
+static void find_single_use_in_loop (struct loop_regs *, rtx, rtx);
+static int valid_initial_value_p (rtx, rtx, int, rtx);
+static void find_mem_givs (const struct loop *, rtx, rtx, int, int);
+static void record_biv (struct loop *, struct induction *, rtx, rtx, rtx,
+                       rtx, rtx *, int, int);
+static void check_final_value (const struct loop *, struct induction *);
+static void loop_ivs_dump (const struct loop *, FILE *, int);
+static void loop_iv_class_dump (const struct iv_class *, FILE *, int);
+static void loop_biv_dump (const struct induction *, FILE *, int);
+static void loop_giv_dump (const struct induction *, FILE *, int);
+static void record_giv (const struct loop *, struct induction *, rtx, rtx,
+                       rtx, rtx, rtx, rtx, int, enum g_types, int, int,
+                       rtx *);
+static void update_giv_derive (const struct loop *, rtx);
+static void check_ext_dependent_givs (const struct loop *, struct iv_class *);
+static int basic_induction_var (const struct loop *, rtx, enum machine_mode,
+                               rtx, rtx, rtx *, rtx *, rtx **);
+static rtx simplify_giv_expr (const struct loop *, rtx, rtx *, int *);
+static int general_induction_var (const struct loop *loop, rtx, rtx *, rtx *,
+                                 rtx *, rtx *, int, int *, enum machine_mode);
+static int consec_sets_giv (const struct loop *, int, rtx, rtx, rtx, rtx *,
+                           rtx *, rtx *, rtx *);
+static int check_dbra_loop (struct loop *, int);
+static rtx express_from_1 (rtx, rtx, rtx);
+static rtx combine_givs_p (struct induction *, struct induction *);
+static int cmp_combine_givs_stats (const void *, const void *);
+static void combine_givs (struct loop_regs *, struct iv_class *);
+static int product_cheap_p (rtx, rtx);
+static int maybe_eliminate_biv (const struct loop *, struct iv_class *, int,
+                               int, int);
+static int maybe_eliminate_biv_1 (const struct loop *, rtx, rtx,
+                                 struct iv_class *, int, basic_block, rtx);
+static int last_use_this_basic_block (rtx, rtx);
+static void record_initial (rtx, rtx, void *);
+static void update_reg_last_use (rtx, rtx);
+static rtx next_insn_in_loop (const struct loop *, rtx);
+static void loop_regs_scan (const struct loop *, int);
+static int count_insns_in_loop (const struct loop *);
+static int find_mem_in_note_1 (rtx *, void *);
+static rtx find_mem_in_note (rtx);
+static void load_mems (const struct loop *);
+static int insert_loop_mem (rtx *, void *);
+static int replace_loop_mem (rtx *, void *);
+static void replace_loop_mems (rtx, rtx, rtx, int);
+static int replace_loop_reg (rtx *, void *);
+static void replace_loop_regs (rtx insn, rtx, rtx);
+static void note_reg_stored (rtx, rtx, void *);
+static void try_copy_prop (const struct loop *, rtx, unsigned int);
+static void try_swap_copy_prop (const struct loop *, rtx, unsigned int);
+static rtx check_insn_for_givs (struct loop *, rtx, int, int);
+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 rtx loop_insn_emit_after (const struct loop *, basic_block, rtx, rtx);
+static rtx loop_call_insn_emit_before (const struct loop *, basic_block,
+                                      rtx, rtx);
+static rtx loop_call_insn_hoist (const struct loop *, rtx);
+static rtx loop_insn_sink_or_swim (const struct loop *, rtx);
+
+static void loop_dump_aux (const struct loop *, FILE *, int);
+static void loop_delete_insns (rtx, rtx);
+static HOST_WIDE_INT remove_constant_addition (rtx *);
+static rtx gen_load_of_final_value (rtx, rtx);
+void debug_ivs (const struct loop *);
+void debug_iv_class (const struct iv_class *);
+void debug_biv (const struct induction *);
+void debug_giv (const struct induction *);
+void debug_loop (const struct loop *);
+void debug_loops (const struct loops *);
 
 typedef struct loop_replace_args
 {
@@ -395,13 +378,12 @@ typedef struct loop_replace_args
 
 /* Indirect_jump_in_function is computed once per function.  */
 static int indirect_jump_in_function;
-static int indirect_jump_in_function_p PARAMS ((rtx));
+static int indirect_jump_in_function_p (rtx);
 
-static int compute_luids PARAMS ((rtx, rtx, int));
+static int compute_luids (rtx, rtx, int);
 
-static int biv_elimination_giv_has_0_offset PARAMS ((struct induction *,
-                                                    struct induction *,
-                                                    rtx));
+static int biv_elimination_giv_has_0_offset (struct induction *,
+                                            struct induction *, rtx);
 \f
 /* Benefit penalty, if a giv is not replaceable, i.e. must emit an insn to
    copy the value of the strength reduced giv to its original register.  */
@@ -411,7 +393,7 @@ static int copy_cost;
 static int reg_address_cost;
 
 void
-init_loop ()
+init_loop (void)
 {
   rtx reg = gen_rtx_REG (word_mode, LAST_VIRTUAL_REGISTER + 1);
 
@@ -426,9 +408,7 @@ init_loop ()
    Start at insn START and stop just before END.  Assign LUIDs
    starting with PREV_LUID + 1.  Return the last assigned LUID + 1.  */
 static int
-compute_luids (start, end, prev_luid)
-     rtx start, end;
-     int prev_luid;
+compute_luids (rtx start, rtx end, int prev_luid)
 {
   int i;
   rtx insn;
@@ -439,7 +419,7 @@ compute_luids (start, end, prev_luid)
        continue;
       /* Don't assign luids to line-number NOTEs, so that the distance in
         luids between two insns is not affected by -g.  */
-      if (GET_CODE (insn) != NOTE
+      if (!NOTE_P (insn)
          || NOTE_LINE_NUMBER (insn) <= 0)
        uid_luid[INSN_UID (insn)] = ++i;
       else
@@ -455,11 +435,7 @@ compute_luids (start, end, prev_luid)
    (or 0 if none should be output).  */
 
 void
-loop_optimize (f, dumpfile, flags)
-     /* f is the first instruction of a chain of insns for one function */
-     rtx f;
-     FILE *dumpfile;
-     int flags;
+loop_optimize (rtx f, FILE *dumpfile, int flags)
 {
   rtx insn;
   int i;
@@ -481,7 +457,7 @@ loop_optimize (f, dumpfile, flags)
   max_loop_num = 0;
   for (insn = f; insn; insn = NEXT_INSN (insn))
     {
-      if (GET_CODE (insn) == NOTE
+      if (NOTE_P (insn)
          && NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG)
        max_loop_num++;
     }
@@ -496,13 +472,11 @@ loop_optimize (f, dumpfile, flags)
      Leave some space for labels allocated by find_and_verify_loops.  */
   max_uid_for_loop = get_max_uid () + 1 + max_loop_num * 32;
 
-  uid_luid = (int *) xcalloc (max_uid_for_loop, sizeof (int));
-  uid_loop = (struct loop **) xcalloc (max_uid_for_loop,
-                                      sizeof (struct loop *));
+  uid_luid = xcalloc (max_uid_for_loop, sizeof (int));
+  uid_loop = xcalloc (max_uid_for_loop, sizeof (struct loop *));
 
   /* Allocate storage for array of loops.  */
-  loops->array = (struct loop *)
-    xcalloc (loops->num, sizeof (struct loop));
+  loops->array = xcalloc (loops->num, sizeof (struct loop));
 
   /* Find and process each loop.
      First, find them, and record them in order of their beginnings.  */
@@ -510,7 +484,7 @@ loop_optimize (f, dumpfile, flags)
 
   /* Allocate and initialize auxiliary loop information.  */
   loops_info = xcalloc (loops->num, sizeof (struct loop_info));
-  for (i = 0; i < loops->num; i++)
+  for (i = 0; i < (int) loops->num; i++)
     loops->array[i].aux = loops_info + i;
 
   /* Now find all register lifetimes.  This must be done after
@@ -535,7 +509,7 @@ loop_optimize (f, dumpfile, flags)
   /* find_and_verify_loops has already called compute_luids, but it
      might have rearranged code afterwards, so we need to recompute
      the luids now.  */
-  max_luid = compute_luids (f, NULL_RTX, 0);
+  compute_luids (f, NULL_RTX, 0);
 
   /* Don't leave gaps in uid_luid for insns that have been
      deleted.  It is possible that the first or last insn
@@ -563,12 +537,18 @@ loop_optimize (f, dumpfile, flags)
       struct loop *loop = &loops->array[i];
 
       if (! loop->invalid && loop->end)
-       scan_loop (loop, flags);
+       {
+         scan_loop (loop, flags);
+         ggc_collect ();
+       }
     }
 
   end_alias_analysis ();
 
   /* Clean up.  */
+  for (i = 0; i < (int) loops->num; i++)
+    free (loops_info[i].mems);
+  
   free (uid_luid);
   free (uid_loop);
   free (loops_info);
@@ -582,9 +562,7 @@ loop_optimize (f, dumpfile, flags)
    bottom.  */
 
 static rtx
-next_insn_in_loop (loop, insn)
-     const struct loop *loop;
-     rtx insn;
+next_insn_in_loop (const struct loop *loop, rtx insn)
 {
   insn = NEXT_INSN (insn);
 
@@ -605,6 +583,32 @@ next_insn_in_loop (loop, insn)
   return insn;
 }
 
+/* Find any register references hidden inside X and add them to
+   the dependency list DEPS.  This is used to look inside CLOBBER (MEM
+   when checking whether a PARALLEL can be pulled out of a loop.  */
+
+static rtx
+find_regs_nested (rtx deps, rtx x)
+{
+  enum rtx_code code = GET_CODE (x);
+  if (code == REG)
+    deps = gen_rtx_EXPR_LIST (VOIDmode, x, deps);
+  else
+    {
+      const char *fmt = GET_RTX_FORMAT (code);
+      int i, j;
+      for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
+       {
+         if (fmt[i] == 'e')
+           deps = find_regs_nested (deps, XEXP (x, i));
+         else if (fmt[i] == 'E')
+           for (j = 0; j < XVECLEN (x, i); j++)
+             deps = find_regs_nested (deps, XVECEXP (x, i, j));
+       }
+    }
+  return deps;
+}
+
 /* Optimize one loop described by LOOP.  */
 
 /* ??? Could also move memory writes out of loops if the destination address
@@ -614,9 +618,7 @@ next_insn_in_loop (loop, insn)
    write, then we can also mark the memory read as invariant.  */
 
 static void
-scan_loop (loop, flags)
-     struct loop *loop;
-     int flags;
+scan_loop (struct loop *loop, int flags)
 {
   struct loop_info *loop_info = LOOP_INFO (loop);
   struct loop_regs *regs = LOOP_REGS (loop);
@@ -629,8 +631,6 @@ scan_loop (loop, flags)
   /* 1 if we are scanning insns that might never be executed
      due to a subroutine call which might exit before they are reached.  */
   int call_passed = 0;
-  /* Jump insn that enters the loop, or 0 if control drops in.  */
-  rtx loop_entry_jump = 0;
   /* Number of insns in the loop.  */
   int insn_count;
   int tem;
@@ -646,6 +646,7 @@ scan_loop (loop, flags)
   int threshold;
   /* Nonzero if we are scanning instructions in a sub-loop.  */
   int loop_depth = 0;
+  int in_libcall;
 
   loop->top = 0;
 
@@ -670,8 +671,8 @@ scan_loop (loop, flags)
 
   for (p = NEXT_INSN (loop_start);
        p != loop_end
-        && GET_CODE (p) != CODE_LABEL && ! INSN_P (p)
-        && (GET_CODE (p) != NOTE
+        && !LABEL_P (p) && ! INSN_P (p)
+        && (!NOTE_P (p)
             || (NOTE_LINE_NUMBER (p) != NOTE_INSN_LOOP_BEG
                 && NOTE_LINE_NUMBER (p) != NOTE_INSN_LOOP_END));
        p = NEXT_INSN (p))
@@ -697,24 +698,20 @@ scan_loop (loop, flags)
      Start scan from there.
      But record in LOOP->TOP the place where the end-test jumps
      back to so we can scan that after the end of the loop.  */
-  if (GET_CODE (p) == JUMP_INSN)
-    {
-      loop_entry_jump = p;
-
+  if (JUMP_P (p)
       /* Loop entry must be unconditional jump (and not a RETURN)  */
-      if (any_uncondjump_p (p)
-         && JUMP_LABEL (p) != 0
-         /* Check to see whether the jump actually
-            jumps out of the loop (meaning it's no loop).
-            This case can happen for things like
-            do {..} while (0).  If this label was generated previously
-            by loop, we can't tell anything about it and have to reject
-            the loop.  */
-         && INSN_IN_RANGE_P (JUMP_LABEL (p), loop_start, loop_end))
-       {
-         loop->top = next_label (loop->scan_start);
-         loop->scan_start = JUMP_LABEL (p);
-       }
+      && any_uncondjump_p (p)
+      && JUMP_LABEL (p) != 0
+      /* Check to see whether the jump actually
+        jumps out of the loop (meaning it's no loop).
+        This case can happen for things like
+        do {..} while (0).  If this label was generated previously
+        by loop, we can't tell anything about it and have to reject
+        the loop.  */
+      && INSN_IN_RANGE_P (JUMP_LABEL (p), loop_start, loop_end))
+    {
+      loop->top = next_label (loop->scan_start);
+      loop->scan_start = JUMP_LABEL (p);
     }
 
   /* If LOOP->SCAN_START was an insn created by loop, we don't know its luid
@@ -726,7 +723,7 @@ scan_loop (loop, flags)
      test above.  */
 
   if (INSN_UID (loop->scan_start) >= max_uid_for_loop
-      || GET_CODE (loop->scan_start) != CODE_LABEL)
+      || !LABEL_P (loop->scan_start))
     {
       if (loop_dump_stream)
        fprintf (loop_dump_stream, "\nLoop from %d to %d is phony.\n\n",
@@ -762,68 +759,79 @@ scan_loop (loop, flags)
      When MAYBE_NEVER is 0, all insns will be executed at least once
      so that is not a problem.  */
 
-  for (p = next_insn_in_loop (loop, loop->scan_start);
+  for (in_libcall = 0, p = next_insn_in_loop (loop, loop->scan_start);
        p != NULL_RTX;
        p = next_insn_in_loop (loop, p))
     {
-      if (GET_CODE (p) == INSN
-         && (set = single_set (p))
-         && GET_CODE (SET_DEST (set)) == REG
-#ifdef PIC_OFFSET_TABLE_REG_CALL_CLOBBERED
-         && SET_DEST (set) != pic_offset_table_rtx
-#endif
-         && ! regs->array[REGNO (SET_DEST (set))].may_not_optimize)
+      if (in_libcall && INSN_P (p) && find_reg_note (p, REG_RETVAL, NULL_RTX))
+       in_libcall--;
+      if (NONJUMP_INSN_P (p))
        {
-         int tem1 = 0;
-         int tem2 = 0;
-         int move_insn = 0;
-         rtx src = SET_SRC (set);
-         rtx dependencies = 0;
-
-         /* Figure out what to use as a source of this insn.  If a REG_EQUIV
-            note is given or if a REG_EQUAL note with a constant operand is
-            specified, use it as the source and mark that we should move
-            this insn by calling emit_move_insn rather that duplicating the
-            insn.
-
-            Otherwise, only use the REG_EQUAL contents if a REG_RETVAL note
-            is present.  */
-         temp = find_reg_note (p, REG_EQUIV, NULL_RTX);
+         temp = find_reg_note (p, REG_LIBCALL, NULL_RTX);
          if (temp)
-           src = XEXP (temp, 0), move_insn = 1;
-         else
+           in_libcall++;
+         if (! in_libcall
+             && (set = single_set (p))
+             && REG_P (SET_DEST (set))
+#ifdef PIC_OFFSET_TABLE_REG_CALL_CLOBBERED
+             && SET_DEST (set) != pic_offset_table_rtx
+#endif
+             && ! regs->array[REGNO (SET_DEST (set))].may_not_optimize)
            {
-             temp = find_reg_note (p, REG_EQUAL, NULL_RTX);
-             if (temp && CONSTANT_P (XEXP (temp, 0)))
+             int tem1 = 0;
+             int tem2 = 0;
+             int move_insn = 0;
+             int insert_temp = 0;
+             rtx src = SET_SRC (set);
+             rtx dependencies = 0;
+
+             /* Figure out what to use as a source of this insn.  If a
+                REG_EQUIV note is given or if a REG_EQUAL note with a
+                constant operand is specified, use it as the source and
+                mark that we should move this insn by calling
+                emit_move_insn rather that duplicating the insn.
+
+                Otherwise, only use the REG_EQUAL contents if a REG_RETVAL
+                note is present.  */
+             temp = find_reg_note (p, REG_EQUIV, NULL_RTX);
+             if (temp)
                src = XEXP (temp, 0), move_insn = 1;
-             if (temp && find_reg_note (p, REG_RETVAL, NULL_RTX))
+             else
                {
-                 src = XEXP (temp, 0);
-                 /* A libcall block can use regs that don't appear in
-                    the equivalent expression.  To move the libcall,
-                    we must move those regs too.  */
-                 dependencies = libcall_other_reg (p, src);
+                 temp = find_reg_note (p, REG_EQUAL, NULL_RTX);
+                 if (temp && CONSTANT_P (XEXP (temp, 0)))
+                   src = XEXP (temp, 0), move_insn = 1;
+                 if (temp && find_reg_note (p, REG_RETVAL, NULL_RTX))
+                   {
+                     src = XEXP (temp, 0);
+                     /* A libcall block can use regs that don't appear in
+                        the equivalent expression.  To move the libcall,
+                        we must move those regs too.  */
+                     dependencies = libcall_other_reg (p, src);
+                   }
                }
-           }
 
-         /* For parallels, add any possible uses to the depencies, as we can't move
-            the insn without resolving them first.  */
-         if (GET_CODE (PATTERN (p)) == PARALLEL)
-           {
-             for (i = 0; i < XVECLEN (PATTERN (p), 0); i++)
+             /* For parallels, add any possible uses to the dependencies, as
+                we can't move the insn without resolving them first.
+                MEMs inside CLOBBERs may also reference registers; these
+                count as implicit uses.  */
+             if (GET_CODE (PATTERN (p)) == PARALLEL)
                {
-                 rtx x = XVECEXP (PATTERN (p), 0, i);
-                 if (GET_CODE (x) == USE)
-                   dependencies = gen_rtx_EXPR_LIST (VOIDmode, XEXP (x, 0), dependencies);
+                 for (i = 0; i < XVECLEN (PATTERN (p), 0); i++)
+                   {
+                     rtx x = XVECEXP (PATTERN (p), 0, i);
+                     if (GET_CODE (x) == USE)
+                       dependencies
+                         = gen_rtx_EXPR_LIST (VOIDmode, XEXP (x, 0),
+                                              dependencies);
+                     else if (GET_CODE (x) == CLOBBER 
+                              && MEM_P (XEXP (x, 0)))
+                       dependencies = find_regs_nested (dependencies, 
+                                                 XEXP (XEXP (x, 0), 0));
+                   }
                }
-           }
 
-         /* Don't try to optimize a register that was made
-            by loop-optimization for an inner loop.
-            We don't know its life-span, so we can't compute the benefit.  */
-         if (REGNO (SET_DEST (set)) >= max_reg_before_loop)
-           ;
-         else if (/* The register is used in basic blocks other
+             if (/* The register is used in basic blocks other
                      than the one where it is set (meaning that
                      something after this point in the loop might
                      depend on its value before the set).  */
@@ -832,227 +840,269 @@ scan_loop (loop, flags)
                      the loop starts, or the value before the set is
                      needed before the set occurs...
 
-                     ??? Note we have quadratic behaviour here, mitigated
+                     ??? Note we have quadratic behavior here, mitigated
                      by the fact that the previous test will often fail for
                      large loops.  Rather than re-scanning the entire loop
                      each time for register usage, we should build tables
                      of the register usage and use them here instead.  */
                   && (maybe_never
                       || loop_reg_used_before_p (loop, set, p)))
-           /* It is unsafe to move the set.
-
-              This code used to consider it OK to move a set of a variable
-              which was not created by the user and not used in an exit test.
-              That behavior is incorrect and was removed.  */
-           ;
-         else if ((tem = loop_invariant_p (loop, src))
-                  && (dependencies == 0
-                      || (tem2 = loop_invariant_p (loop, dependencies)) != 0)
-                  && (regs->array[REGNO (SET_DEST (set))].set_in_loop == 1
-                      || (tem1
-                          = consec_sets_invariant_p
-                          (loop, SET_DEST (set),
-                           regs->array[REGNO (SET_DEST (set))].set_in_loop,
-                           p)))
-                  /* If the insn can cause a trap (such as divide by zero),
-                     can't move it unless it's guaranteed to be executed
-                     once loop is entered.  Even a function call might
-                     prevent the trap insn from being reached
-                     (since it might exit!)  */
-                  && ! ((maybe_never || call_passed)
-                        && may_trap_p (src)))
-           {
-             struct movable *m;
-             int regno = REGNO (SET_DEST (set));
-
-             /* A potential lossage is where we have a case where two insns
-                can be combined as long as they are both in the loop, but
-                we move one of them outside the loop.  For large loops,
-                this can lose.  The most common case of this is the address
-                of a function being called.
-
-                Therefore, if this register is marked as being used exactly
-                once if we are in a loop with calls (a "large loop"), see if
-                we can replace the usage of this register with the source
-                of this SET.  If we can, delete this insn.
-
-                Don't do this if P has a REG_RETVAL note or if we have
-                SMALL_REGISTER_CLASSES and SET_SRC is a hard register.  */
-
-             if (loop_info->has_call
-                 && regs->array[regno].single_usage != 0
-                 && regs->array[regno].single_usage != const0_rtx
-                 && REGNO_FIRST_UID (regno) == INSN_UID (p)
-                 && (REGNO_LAST_UID (regno)
-                     == INSN_UID (regs->array[regno].single_usage))
-                 && regs->array[regno].set_in_loop == 1
-                 && GET_CODE (SET_SRC (set)) != ASM_OPERANDS
-                 && ! side_effects_p (SET_SRC (set))
-                 && ! find_reg_note (p, REG_RETVAL, NULL_RTX)
-                 && (! SMALL_REGISTER_CLASSES
-                     || (! (GET_CODE (SET_SRC (set)) == REG
-                            && REGNO (SET_SRC (set)) < FIRST_PSEUDO_REGISTER)))
-                 /* This test is not redundant; SET_SRC (set) might be
-                    a call-clobbered register and the life of REGNO
-                    might span a call.  */
-                 && ! modified_between_p (SET_SRC (set), p,
-                                          regs->array[regno].single_usage)
-                 && no_labels_between_p (p, regs->array[regno].single_usage)
-                 && validate_replace_rtx (SET_DEST (set), SET_SRC (set),
-                                          regs->array[regno].single_usage))
-               {
-                 /* Replace any usage in a REG_EQUAL note.  Must copy the
-                    new source, so that we don't get rtx sharing between the
-                    SET_SOURCE and REG_NOTES of insn p.  */
-                 REG_NOTES (regs->array[regno].single_usage)
-                   = replace_rtx (REG_NOTES (regs->array[regno].single_usage),
-                                  SET_DEST (set), copy_rtx (SET_SRC (set)));
-
-                 delete_insn (p);
-                 for (i = 0; i < LOOP_REGNO_NREGS (regno, SET_DEST (set)); i++)
-                   regs->array[regno+i].set_in_loop = 0;
-                 continue;
-               }
-
-             m = (struct movable *) xmalloc (sizeof (struct movable));
-             m->next = 0;
-             m->insn = p;
-             m->set_src = src;
-             m->dependencies = dependencies;
-             m->set_dest = SET_DEST (set);
-             m->force = 0;
-             m->consec = regs->array[REGNO (SET_DEST (set))].set_in_loop - 1;
-             m->done = 0;
-             m->forces = 0;
-             m->partial = 0;
-             m->move_insn = move_insn;
-             m->move_insn_first = 0;
-             m->is_equiv = (find_reg_note (p, REG_EQUIV, NULL_RTX) != 0);
-             m->savemode = VOIDmode;
-             m->regno = regno;
-             /* 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 =  LOOP_REG_GLOBAL_P (loop, regno);
-             m->match = 0;
-             m->lifetime = LOOP_REG_LIFETIME (loop, regno);
-             m->savings = regs->array[regno].n_times_set;
-             if (find_reg_note (p, REG_RETVAL, NULL_RTX))
-               m->savings += libcall_benefit (p);
-             for (i = 0; i < LOOP_REGNO_NREGS (regno, SET_DEST (set)); i++)
-               regs->array[regno+i].set_in_loop = move_insn ? -2 : -1;
-             /* Add M to the end of the chain MOVABLES.  */
-             loop_movables_add (movables, m);
-
-             if (m->consec > 0)
+               /* It is unsafe to move the set.  However, it may be OK to
+                  move the source into a new pseudo, and substitute a
+                  reg-to-reg copy for the original insn.
+
+                  This code used to consider it OK to move a set of a variable
+                  which was not created by the user and not used in an exit
+                  test.
+                  That behavior is incorrect and was removed.  */
+               insert_temp = 1;
+
+             /* Don't try to optimize a MODE_CC set with a constant
+                source.  It probably will be combined with a conditional
+                jump.  */
+             if (GET_MODE_CLASS (GET_MODE (SET_DEST (set))) == MODE_CC
+                 && CONSTANT_P (src))
+               ;
+             /* Don't try to optimize a register that was made
+                by loop-optimization for an inner loop.
+                We don't know its life-span, so we can't compute
+                the benefit.  */
+             else if (REGNO (SET_DEST (set)) >= max_reg_before_loop)
+               ;
+             /* Don't move the source and add a reg-to-reg copy:
+                - with -Os (this certainly increases size),
+                - if the mode doesn't support copy operations (obviously),
+                - if the source is already a reg (the motion will gain nothing),
+                - if the source is a legitimate constant (likewise).  */
+             else if (insert_temp
+                      && (optimize_size
+                          || ! can_copy_p (GET_MODE (SET_SRC (set)))
+                          || REG_P (SET_SRC (set))
+                          || (CONSTANT_P (SET_SRC (set))
+                              && LEGITIMATE_CONSTANT_P (SET_SRC (set)))))
+               ;
+             else if ((tem = loop_invariant_p (loop, src))
+                      && (dependencies == 0
+                          || (tem2
+                              = loop_invariant_p (loop, dependencies)) != 0)
+                      && (regs->array[REGNO (SET_DEST (set))].set_in_loop == 1
+                          || (tem1
+                              = consec_sets_invariant_p
+                              (loop, SET_DEST (set),
+                               regs->array[REGNO (SET_DEST (set))].set_in_loop,
+                               p)))
+                      /* If the insn can cause a trap (such as divide by zero),
+                         can't move it unless it's guaranteed to be executed
+                         once loop is entered.  Even a function call might
+                         prevent the trap insn from being reached
+                         (since it might exit!)  */
+                      && ! ((maybe_never || call_passed)
+                            && may_trap_p (src)))
                {
-                 /* It is possible for the first instruction to have a
-                    REG_EQUAL note but a non-invariant SET_SRC, so we must
-                    remember the status of the first instruction in case
-                    the last instruction doesn't have a REG_EQUAL note.  */
-                 m->move_insn_first = m->move_insn;
-
-                 /* Skip this insn, not checking REG_LIBCALL notes.  */
-                 p = next_nonnote_insn (p);
-                 /* Skip the consecutive insns, if there are any.  */
-                 p = skip_consec_insns (p, m->consec);
-                 /* Back up to the last insn of the consecutive group.  */
-                 p = prev_nonnote_insn (p);
-
-                 /* We must now reset m->move_insn, m->is_equiv, and possibly
-                    m->set_src to correspond to the effects of all the
-                    insns.  */
-                 temp = find_reg_note (p, REG_EQUIV, NULL_RTX);
-                 if (temp)
-                   m->set_src = XEXP (temp, 0), m->move_insn = 1;
-                 else
+                 struct movable *m;
+                 int regno = REGNO (SET_DEST (set));
+
+                 /* A potential lossage is where we have a case where two insns
+                    can be combined as long as they are both in the loop, but
+                    we move one of them outside the loop.  For large loops,
+                    this can lose.  The most common case of this is the address
+                    of a function being called.
+
+                    Therefore, if this register is marked as being used
+                    exactly once if we are in a loop with calls
+                    (a "large loop"), see if we can replace the usage of
+                    this register with the source of this SET.  If we can,
+                    delete this insn.
+
+                    Don't do this if P has a REG_RETVAL note or if we have
+                    SMALL_REGISTER_CLASSES and SET_SRC is a hard register.  */
+
+                 if (loop_info->has_call
+                     && regs->array[regno].single_usage != 0
+                     && regs->array[regno].single_usage != const0_rtx
+                     && REGNO_FIRST_UID (regno) == INSN_UID (p)
+                     && (REGNO_LAST_UID (regno)
+                         == INSN_UID (regs->array[regno].single_usage))
+                     && regs->array[regno].set_in_loop == 1
+                     && GET_CODE (SET_SRC (set)) != ASM_OPERANDS
+                     && ! side_effects_p (SET_SRC (set))
+                     && ! find_reg_note (p, REG_RETVAL, NULL_RTX)
+                     && (! SMALL_REGISTER_CLASSES
+                         || (! (REG_P (SET_SRC (set))
+                                && (REGNO (SET_SRC (set))
+                                    < FIRST_PSEUDO_REGISTER))))
+                     && regno >= FIRST_PSEUDO_REGISTER 
+                     /* This test is not redundant; SET_SRC (set) might be
+                        a call-clobbered register and the life of REGNO
+                        might span a call.  */
+                     && ! modified_between_p (SET_SRC (set), p,
+                                              regs->array[regno].single_usage)
+                     && no_labels_between_p (p,
+                                             regs->array[regno].single_usage)
+                     && validate_replace_rtx (SET_DEST (set), SET_SRC (set),
+                                              regs->array[regno].single_usage))
                    {
-                     temp = find_reg_note (p, REG_EQUAL, NULL_RTX);
-                     if (temp && CONSTANT_P (XEXP (temp, 0)))
-                       m->set_src = XEXP (temp, 0), m->move_insn = 1;
-                     else
-                       m->move_insn = 0;
+                     /* Replace any usage in a REG_EQUAL note.  Must copy
+                        the new source, so that we don't get rtx sharing
+                        between the SET_SOURCE and REG_NOTES of insn p.  */
+                     REG_NOTES (regs->array[regno].single_usage)
+                       = (replace_rtx
+                          (REG_NOTES (regs->array[regno].single_usage),
+                           SET_DEST (set), copy_rtx (SET_SRC (set))));
 
+                     delete_insn (p);
+                     for (i = 0; i < LOOP_REGNO_NREGS (regno, SET_DEST (set));
+                          i++)
+                       regs->array[regno+i].set_in_loop = 0;
+                     continue;
                    }
-                 m->is_equiv = (find_reg_note (p, REG_EQUIV, NULL_RTX) != 0);
-               }
-           }
-         /* If this register is always set within a STRICT_LOW_PART
-            or set to zero, then its high bytes are constant.
-            So clear them outside the loop and within the loop
-            just load the low bytes.
-            We must check that the machine has an instruction to do so.
-            Also, if the value loaded into the register
-            depends on the same register, this cannot be done.  */
-         else if (SET_SRC (set) == const0_rtx
-                  && GET_CODE (NEXT_INSN (p)) == INSN
-                  && (set1 = single_set (NEXT_INSN (p)))
-                  && GET_CODE (set1) == SET
-                  && (GET_CODE (SET_DEST (set1)) == STRICT_LOW_PART)
-                  && (GET_CODE (XEXP (SET_DEST (set1), 0)) == SUBREG)
-                  && (SUBREG_REG (XEXP (SET_DEST (set1), 0))
-                      == SET_DEST (set))
-                  && !reg_mentioned_p (SET_DEST (set), SET_SRC (set1)))
-           {
-             int regno = REGNO (SET_DEST (set));
-             if (regs->array[regno].set_in_loop == 2)
-               {
-                 struct movable *m;
-                 m = (struct movable *) xmalloc (sizeof (struct movable));
+
+                 m = xmalloc (sizeof (struct movable));
                  m->next = 0;
                  m->insn = p;
+                 m->set_src = src;
+                 m->dependencies = dependencies;
                  m->set_dest = SET_DEST (set);
-                 m->dependencies = 0;
                  m->force = 0;
-                 m->consec = 0;
+                 m->consec
+                   = regs->array[REGNO (SET_DEST (set))].set_in_loop - 1;
                  m->done = 0;
                  m->forces = 0;
-                 m->move_insn = 0;
+                 m->partial = 0;
+                 m->move_insn = move_insn;
                  m->move_insn_first = 0;
-                 m->partial = 1;
-                 /* If the insn may not be executed on some cycles,
-                    we can't clear the whole reg; clear just high part.
-                    Not even if the reg is used only within this loop.
-                    Consider this:
-                    while (1)
-                      while (s != t) {
-                        if (foo ()) x = *s;
-                        use (x);
-                      }
-                    Clearing x before the inner loop could clobber a value
-                    being saved from the last time around the outer loop.
-                    However, if the reg is not used outside this loop
-                    and all uses of the register are in the same
-                    basic block as the store, there is no problem.
-
-                    If this insn was made by loop, we don't know its
-                    INSN_LUID and hence must make a conservative
-                    assumption.  */
-                 m->global = (INSN_UID (p) >= max_uid_for_loop
-                              || LOOP_REG_GLOBAL_P (loop, regno)
-                              || (labels_in_range_p
-                                  (p, REGNO_FIRST_LUID (regno))));
-                 if (maybe_never && m->global)
-                   m->savemode = GET_MODE (SET_SRC (set1));
-                 else
-                   m->savemode = VOIDmode;
+                 m->insert_temp = insert_temp;
+                 m->is_equiv = (find_reg_note (p, REG_EQUIV, NULL_RTX) != 0);
+                 m->savemode = VOIDmode;
                  m->regno = regno;
-                 m->cond = 0;
+                 /* 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 =  LOOP_REG_GLOBAL_P (loop, regno);
                  m->match = 0;
                  m->lifetime = LOOP_REG_LIFETIME (loop, regno);
-                 m->savings = 1;
+                 m->savings = regs->array[regno].n_times_set;
+                 if (find_reg_note (p, REG_RETVAL, NULL_RTX))
+                   m->savings += libcall_benefit (p);
                  for (i = 0; i < LOOP_REGNO_NREGS (regno, SET_DEST (set)); i++)
-                   regs->array[regno+i].set_in_loop = -1;
+                   regs->array[regno+i].set_in_loop = move_insn ? -2 : -1;
                  /* Add M to the end of the chain MOVABLES.  */
                  loop_movables_add (movables, m);
+
+                 if (m->consec > 0)
+                   {
+                     /* It is possible for the first instruction to have a
+                        REG_EQUAL note but a non-invariant SET_SRC, so we must
+                        remember the status of the first instruction in case
+                        the last instruction doesn't have a REG_EQUAL note.  */
+                     m->move_insn_first = m->move_insn;
+
+                     /* Skip this insn, not checking REG_LIBCALL notes.  */
+                     p = next_nonnote_insn (p);
+                     /* Skip the consecutive insns, if there are any.  */
+                     p = skip_consec_insns (p, m->consec);
+                     /* Back up to the last insn of the consecutive group.  */
+                     p = prev_nonnote_insn (p);
+
+                     /* We must now reset m->move_insn, m->is_equiv, and
+                        possibly m->set_src to correspond to the effects of
+                        all the insns.  */
+                     temp = find_reg_note (p, REG_EQUIV, NULL_RTX);
+                     if (temp)
+                       m->set_src = XEXP (temp, 0), m->move_insn = 1;
+                     else
+                       {
+                         temp = find_reg_note (p, REG_EQUAL, NULL_RTX);
+                         if (temp && CONSTANT_P (XEXP (temp, 0)))
+                           m->set_src = XEXP (temp, 0), m->move_insn = 1;
+                         else
+                           m->move_insn = 0;
+
+                       }
+                     m->is_equiv
+                       = (find_reg_note (p, REG_EQUIV, NULL_RTX) != 0);
+                   }
+               }
+             /* If this register is always set within a STRICT_LOW_PART
+                or set to zero, then its high bytes are constant.
+                So clear them outside the loop and within the loop
+                just load the low bytes.
+                We must check that the machine has an instruction to do so.
+                Also, if the value loaded into the register
+                depends on the same register, this cannot be done.  */
+             else if (SET_SRC (set) == const0_rtx
+                      && NONJUMP_INSN_P (NEXT_INSN (p))
+                      && (set1 = single_set (NEXT_INSN (p)))
+                      && GET_CODE (set1) == SET
+                      && (GET_CODE (SET_DEST (set1)) == STRICT_LOW_PART)
+                      && (GET_CODE (XEXP (SET_DEST (set1), 0)) == SUBREG)
+                      && (SUBREG_REG (XEXP (SET_DEST (set1), 0))
+                          == SET_DEST (set))
+                      && !reg_mentioned_p (SET_DEST (set), SET_SRC (set1)))
+               {
+                 int regno = REGNO (SET_DEST (set));
+                 if (regs->array[regno].set_in_loop == 2)
+                   {
+                     struct movable *m;
+                     m = xmalloc (sizeof (struct movable));
+                     m->next = 0;
+                     m->insn = p;
+                     m->set_dest = SET_DEST (set);
+                     m->dependencies = 0;
+                     m->force = 0;
+                     m->consec = 0;
+                     m->done = 0;
+                     m->forces = 0;
+                     m->move_insn = 0;
+                     m->move_insn_first = 0;
+                     m->insert_temp = insert_temp;
+                     m->partial = 1;
+                     /* If the insn may not be executed on some cycles,
+                        we can't clear the whole reg; clear just high part.
+                        Not even if the reg is used only within this loop.
+                        Consider this:
+                        while (1)
+                          while (s != t) {
+                            if (foo ()) x = *s;
+                            use (x);
+                          }
+                        Clearing x before the inner loop could clobber a value
+                        being saved from the last time around the outer loop.
+                        However, if the reg is not used outside this loop
+                        and all uses of the register are in the same
+                        basic block as the store, there is no problem.
+
+                        If this insn was made by loop, we don't know its
+                        INSN_LUID and hence must make a conservative
+                        assumption.  */
+                     m->global = (INSN_UID (p) >= max_uid_for_loop
+                                  || LOOP_REG_GLOBAL_P (loop, regno)
+                                  || (labels_in_range_p
+                                      (p, REGNO_FIRST_LUID (regno))));
+                     if (maybe_never && m->global)
+                       m->savemode = GET_MODE (SET_SRC (set1));
+                     else
+                       m->savemode = VOIDmode;
+                     m->regno = regno;
+                     m->cond = 0;
+                     m->match = 0;
+                     m->lifetime = LOOP_REG_LIFETIME (loop, regno);
+                     m->savings = 1;
+                     for (i = 0;
+                          i < LOOP_REGNO_NREGS (regno, SET_DEST (set));
+                          i++)
+                       regs->array[regno+i].set_in_loop = -1;
+                     /* Add M to the end of the chain MOVABLES.  */
+                     loop_movables_add (movables, m);
+                   }
                }
            }
        }
       /* Past a call insn, we get to insns which might not be executed
         because the call might exit.  This matters for insns that trap.
         Constant and pure call insns always return, so they don't count.  */
-      else if (GET_CODE (p) == CALL_INSN && ! CONST_OR_PURE_CALL_P (p))
+      else if (CALL_P (p) && ! CONST_OR_PURE_CALL_P (p))
        call_passed = 1;
       /* Past a label or a jump, we get to insns for which we
         can't count on whether or how many times they will be
@@ -1060,17 +1110,17 @@ scan_loop (loop, flags)
         only move out sets of trivial variables
         (those not used after the loop).  */
       /* Similar code appears twice in strength_reduce.  */
-      else if ((GET_CODE (p) == CODE_LABEL || GET_CODE (p) == JUMP_INSN)
+      else if ((LABEL_P (p) || JUMP_P (p))
               /* If we enter the loop in the middle, and scan around to the
                  beginning, don't set maybe_never for that.  This must be an
                  unconditional jump, otherwise the code at the top of the
                  loop might never be executed.  Unconditional jumps are
                  followed by a barrier then the loop_end.  */
-              && ! (GET_CODE (p) == JUMP_INSN && JUMP_LABEL (p) == loop->top
+              && ! (JUMP_P (p) && JUMP_LABEL (p) == loop->top
                     && NEXT_INSN (NEXT_INSN (p)) == loop_end
                     && any_uncondjump_p (p)))
        maybe_never = 1;
-      else if (GET_CODE (p) == NOTE)
+      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
@@ -1105,10 +1155,12 @@ scan_loop (loop, flags)
   /* Now consider each movable insn to decide whether it is worth moving.
      Store 0 in regs->array[I].set_in_loop for each reg I that is moved.
 
-     Generally this increases code size, so do not move moveables when
-     optimizing for code size.  */
+     For machines with few registers this increases code size, so do not
+     move moveables when optimizing for code size on such machines.
+     (The 18 below is the value for i386.)  */
 
-  if (! optimize_size)
+  if (!optimize_size
+      || (reg_class_size[GENERAL_REGS] > 18 && !loop_info->has_call))
     {
       move_movables (loop, movables, threshold, insn_count);
 
@@ -1119,7 +1171,7 @@ scan_loop (loop, flags)
          loop_regs_scan (loop, 0);
          for (update_start = loop_start;
               PREV_INSN (update_start)
-              && GET_CODE (PREV_INSN (update_start)) != CODE_LABEL;
+              && !LABEL_P (PREV_INSN (update_start));
               update_start = PREV_INSN (update_start))
            ;
          update_end = NEXT_INSN (loop_end);
@@ -1146,7 +1198,7 @@ scan_loop (loop, flags)
 
   for (update_start = loop_start;
        PREV_INSN (update_start)
-        && GET_CODE (PREV_INSN (update_start)) != CODE_LABEL;
+        && !LABEL_P (PREV_INSN (update_start));
        update_start = PREV_INSN (update_start))
     ;
   update_end = NEXT_INSN (loop_end);
@@ -1156,7 +1208,7 @@ scan_loop (loop, flags)
 
   if (flag_strength_reduce)
     {
-      if (update_end && GET_CODE (update_end) == CODE_LABEL)
+      if (update_end && LABEL_P (update_end))
        /* Ensure our label doesn't go away.  */
        LABEL_NUSES (update_end)++;
 
@@ -1165,7 +1217,7 @@ scan_loop (loop, flags)
       reg_scan_update (update_start, update_end, loop_max_reg);
       loop_max_reg = max_reg_num ();
 
-      if (update_end && GET_CODE (update_end) == CODE_LABEL
+      if (update_end && LABEL_P (update_end)
          && --LABEL_NUSES (update_end) == 0)
        delete_related_insns (update_end);
     }
@@ -1182,10 +1234,8 @@ scan_loop (loop, flags)
 /* Add elements to *OUTPUT to record all the pseudo-regs
    mentioned in IN_THIS but not mentioned in NOT_IN_THIS.  */
 
-void
-record_excess_regs (in_this, not_in_this, output)
-     rtx in_this, not_in_this;
-     rtx *output;
+static void
+record_excess_regs (rtx in_this, rtx not_in_this, rtx *output)
 {
   enum rtx_code code;
   const char *fmt;
@@ -1238,9 +1288,8 @@ record_excess_regs (in_this, not_in_this, output)
    If there are none, return 0.
    If there are one or more, return an EXPR_LIST containing all of them.  */
 
-rtx
-libcall_other_reg (insn, equiv)
-     rtx insn, equiv;
+static rtx
+libcall_other_reg (rtx insn, rtx equiv)
 {
   rtx note = find_reg_note (insn, REG_RETVAL, NULL_RTX);
   rtx p = XEXP (note, 0);
@@ -1251,8 +1300,7 @@ libcall_other_reg (insn, equiv)
 
   while (p != insn)
     {
-      if (GET_CODE (p) == INSN || GET_CODE (p) == JUMP_INSN
-         || GET_CODE (p) == CALL_INSN)
+      if (INSN_P (p))
        record_excess_regs (PATTERN (p), equiv, &output);
       p = NEXT_INSN (p);
     }
@@ -1264,8 +1312,7 @@ libcall_other_reg (insn, equiv)
    are between INSN and the end of the basic block.  */
 
 static int
-reg_in_basic_block_p (insn, reg)
-     rtx insn, reg;
+reg_in_basic_block_p (rtx insn, rtx reg)
 {
   int regno = REGNO (reg);
   rtx p;
@@ -1318,8 +1365,7 @@ reg_in_basic_block_p (insn, reg)
    value directly or can contain a library call.  */
 
 static int
-libcall_benefit (last)
-     rtx last;
+libcall_benefit (rtx last)
 {
   rtx insn;
   int benefit = 0;
@@ -1327,10 +1373,10 @@ libcall_benefit (last)
   for (insn = XEXP (find_reg_note (last, REG_RETVAL, NULL_RTX), 0);
        insn != last; insn = NEXT_INSN (insn))
     {
-      if (GET_CODE (insn) == CALL_INSN)
+      if (CALL_P (insn))
        benefit += 10;          /* Assume at least this many insns in a library
                                   routine.  */
-      else if (GET_CODE (insn) == INSN
+      else if (NONJUMP_INSN_P (insn)
               && GET_CODE (PATTERN (insn)) != USE
               && GET_CODE (PATTERN (insn)) != CLOBBER)
        benefit++;
@@ -1342,9 +1388,7 @@ libcall_benefit (last)
 /* Skip COUNT insns from INSN, counting library calls as 1 insn.  */
 
 static rtx
-skip_consec_insns (insn, count)
-     rtx insn;
-     int count;
+skip_consec_insns (rtx insn, int count)
 {
   for (; count > 0; count--)
     {
@@ -1353,13 +1397,13 @@ skip_consec_insns (insn, count)
       /* If first insn of libcall sequence, skip to end.  */
       /* Do this at start of loop, since INSN is guaranteed to
         be an insn here.  */
-      if (GET_CODE (insn) != NOTE
+      if (!NOTE_P (insn)
          && (temp = find_reg_note (insn, REG_LIBCALL, NULL_RTX)))
        insn = XEXP (temp, 0);
 
       do
        insn = NEXT_INSN (insn);
-      while (GET_CODE (insn) == NOTE);
+      while (NOTE_P (insn));
     }
 
   return insn;
@@ -1371,8 +1415,7 @@ skip_consec_insns (insn, count)
    was made later and so appears later on the chain.  */
 
 static void
-ignore_some_movables (movables)
-     struct loop_movables *movables;
+ignore_some_movables (struct loop_movables *movables)
 {
   struct movable *m, *m1;
 
@@ -1403,8 +1446,7 @@ ignore_some_movables (movables)
    since the second can be moved only if the first is.  */
 
 static void
-force_movables (movables)
-     struct loop_movables *movables;
+force_movables (struct loop_movables *movables)
 {
   struct movable *m, *m1;
 
@@ -1429,12 +1471,18 @@ force_movables (movables)
          m = 0;
 
        /* Increase the priority of the moving the first insn
-          since it permits the second to be moved as well.  */
+          since it permits the second to be moved as well.
+          Likewise for insns already forced by the first insn.  */
        if (m != 0)
          {
+           struct movable *m2;
+
            m->forces = m1;
-           m1->lifetime += m->lifetime;
-           m1->savings += m->savings;
+           for (m2 = m1; m2; m2 = m2->forces)
+             {
+               m2->lifetime += m->lifetime;
+               m2->savings += m->savings;
+             }
          }
       }
 }
@@ -1443,12 +1491,10 @@ force_movables (movables)
    one register.  */
 
 static void
-combine_movables (movables, regs)
-     struct loop_movables *movables;
-     struct loop_regs *regs;
+combine_movables (struct loop_movables *movables, struct loop_regs *regs)
 {
   struct movable *m;
-  char *matched_regs = (char *) xmalloc (regs->num);
+  char *matched_regs = xmalloc (regs->num);
   enum machine_mode mode;
 
   /* Regs that are set more than once are not allowed to match
@@ -1460,6 +1506,7 @@ combine_movables (movables, regs)
   for (m = movables->head; m; m = m->next)
     if (m->match == 0 && regs->array[m->regno].n_times_set == 1
        && m->regno >= FIRST_PSEUDO_REGISTER
+       && !m->insert_temp
        && !m->partial)
       {
        struct movable *m1;
@@ -1472,6 +1519,7 @@ combine_movables (movables, regs)
           one match any later ones.  So start this loop at m->next.  */
        for (m1 = m->next; m1; m1 = m1->next)
          if (m != m1 && m1->match == 0
+             && !m1->insert_temp
              && regs->array[m1->regno].n_times_set == 1
              && m1->regno >= FIRST_PSEUDO_REGISTER
              /* A reg used outside the loop mustn't be eliminated.  */
@@ -1494,7 +1542,7 @@ combine_movables (movables, regs)
                        && (GET_MODE_BITSIZE (GET_MODE (m->set_dest))
                            >= GET_MODE_BITSIZE (GET_MODE (m1->set_dest)))))
                   /* See if the source of M1 says it matches M.  */
-                  && ((GET_CODE (m1->set_src) == REG
+                  && ((REG_P (m1->set_src)
                        && matched_regs[REGNO (m1->set_src)])
                       || rtx_equal_for_loop_p (m->set_src, m1->set_src,
                                                movables, regs))))
@@ -1568,8 +1616,7 @@ combine_movables (movables, regs)
    moved outside the loop.  */
 
 static int
-num_unmoved_movables (loop)
-     const struct loop *loop;
+num_unmoved_movables (const struct loop *loop)
 {
   int num = 0;
   struct movable *m;
@@ -1585,9 +1632,7 @@ num_unmoved_movables (loop)
 /* Return 1 if regs X and Y will become the same if moved.  */
 
 static int
-regs_match_p (x, y, movables)
-     rtx x, y;
-     struct loop_movables *movables;
+regs_match_p (rtx x, rtx y, struct loop_movables *movables)
 {
   unsigned int xn = REGNO (x);
   unsigned int yn = REGNO (y);
@@ -1614,10 +1659,8 @@ regs_match_p (x, y, movables)
    equivalent constant, consider them equal.  */
 
 static int
-rtx_equal_for_loop_p (x, y, movables, regs)
-     rtx x, y;
-     struct loop_movables *movables;
-     struct loop_regs *regs;
+rtx_equal_for_loop_p (rtx x, rtx y, struct loop_movables *movables,
+                     struct loop_regs *regs)
 {
   int i;
   int j;
@@ -1634,7 +1677,7 @@ rtx_equal_for_loop_p (x, y, movables, regs)
 
   /* If we have a register and a constant, they may sometimes be
      equal.  */
-  if (GET_CODE (x) == REG && regs->array[REGNO (x)].set_in_loop == -2
+  if (REG_P (x) && regs->array[REGNO (x)].set_in_loop == -2
       && CONSTANT_P (y))
     {
       for (m = movables->head; m; m = m->next)
@@ -1642,7 +1685,7 @@ rtx_equal_for_loop_p (x, y, movables, regs)
            && rtx_equal_p (m->set_src, y))
          return 1;
     }
-  else if (GET_CODE (y) == REG && regs->array[REGNO (y)].set_in_loop == -2
+  else if (REG_P (y) && regs->array[REGNO (y)].set_in_loop == -2
           && CONSTANT_P (x))
     {
       for (m = movables->head; m; m = m->next)
@@ -1733,9 +1776,7 @@ rtx_equal_for_loop_p (x, y, movables, regs)
    references is incremented once for each added note.  */
 
 static void
-add_label_notes (x, insns)
-     rtx x;
-     rtx insns;
+add_label_notes (rtx x, rtx insns)
 {
   enum rtx_code code = GET_CODE (x);
   int i, j;
@@ -1745,7 +1786,7 @@ add_label_notes (x, insns)
   if (code == LABEL_REF && !LABEL_REF_NONLOCAL_P (x))
     {
       /* This code used to ignore labels that referred to dispatch tables to
-         avoid flow generating (slighly) worse code.
+         avoid flow generating (slightly) worse code.
 
          We no longer ignore such label references (see LABEL_REF handling in
          mark_jump_label for additional information).  */
@@ -1775,11 +1816,8 @@ add_label_notes (x, insns)
    other throughout.  */
 
 static void
-move_movables (loop, movables, threshold, insn_count)
-     struct loop *loop;
-     struct loop_movables *movables;
-     int threshold;
-     int insn_count;
+move_movables (struct loop *loop, struct loop_movables *movables,
+              int threshold, int insn_count)
 {
   struct loop_regs *regs = LOOP_REGS (loop);
   int nregs = regs->num;
@@ -1791,8 +1829,8 @@ move_movables (loop, movables, threshold, insn_count)
   /* Map of pseudo-register replacements to handle combining
      when we move several insns that load the same value
      into different pseudo-registers.  */
-  rtx *reg_map = (rtx *) xcalloc (nregs, sizeof (rtx));
-  char *already_moved = (char *) xcalloc (nregs, sizeof (char));
+  rtx *reg_map = xcalloc (nregs, sizeof (rtx));
+  char *already_moved = xcalloc (nregs, sizeof (char));
 
   for (m = movables->head; m; m = m->next)
     {
@@ -1875,6 +1913,10 @@ move_movables (loop, movables, threshold, insn_count)
              int count;
              struct movable *m1;
              rtx first = NULL_RTX;
+             rtx newreg = NULL_RTX;
+
+             if (m->insert_temp)
+               newreg = gen_reg_rtx (GET_MODE (m->set_dest));
 
              /* Now move the insns that set the reg.  */
 
@@ -1918,15 +1960,15 @@ move_movables (loop, movables, threshold, insn_count)
                  for (count = m->consec; count >= 0; count--)
                    {
                      /* If this is the first insn of a library call sequence,
-                        skip to the end.  */
-                     if (GET_CODE (p) != NOTE
+                        something is very wrong.  */
+                     if (!NOTE_P (p)
                          && (temp = find_reg_note (p, REG_LIBCALL, NULL_RTX)))
-                       p = XEXP (temp, 0);
+                       abort ();
 
                      /* If this is the last insn of a libcall sequence, then
                         delete every insn in the sequence except the last.
                         The last insn is handled in the normal manner.  */
-                     if (GET_CODE (p) != NOTE
+                     if (!NOTE_P (p)
                          && (temp = find_reg_note (p, REG_RETVAL, NULL_RTX)))
                        {
                          temp = XEXP (temp, 0);
@@ -1943,17 +1985,28 @@ move_movables (loop, movables, threshold, insn_count)
                         pointers, but when we skip over a NOTE we must fix
                         it up.  Otherwise that code walks into the non-deleted
                         insn stream.  */
-                     while (p && GET_CODE (p) == NOTE)
+                     while (p && NOTE_P (p))
                        p = NEXT_INSN (temp) = NEXT_INSN (p);
+
+                     if (m->insert_temp)
+                       {
+                         /* Replace the original insn with a move from
+                            our newly created temp.  */
+                         start_sequence ();
+                         emit_move_insn (m->set_dest, newreg);
+                         seq = get_insns ();
+                         end_sequence ();
+                         emit_insn_before (seq, p);
+                       }
                    }
 
                  start_sequence ();
-                 emit_move_insn (m->set_dest, m->set_src);
-                 temp = get_insns ();
-                 seq = gen_sequence ();
+                 emit_move_insn (m->insert_temp ? newreg : m->set_dest,
+                                 m->set_src);
+                 seq = get_insns ();
                  end_sequence ();
 
-                 add_label_notes (m->set_src, temp);
+                 add_label_notes (m->set_src, seq);
 
                  i1 = loop_insn_hoist (loop, seq);
                  if (! find_reg_note (i1, REG_EQUAL, NULL_RTX))
@@ -1976,14 +2029,14 @@ move_movables (loop, movables, threshold, insn_count)
                      /* If first insn of libcall sequence, skip to end.  */
                      /* Do this at start of loop, since p is guaranteed to
                         be an insn here.  */
-                     if (GET_CODE (p) != NOTE
+                     if (!NOTE_P (p)
                          && (temp = find_reg_note (p, REG_LIBCALL, NULL_RTX)))
                        p = XEXP (temp, 0);
 
                      /* If last insn of libcall sequence, move all
                         insns except the last before the loop.  The last
                         insn is handled in the normal manner.  */
-                     if (GET_CODE (p) != NOTE
+                     if (!NOTE_P (p)
                          && (temp = find_reg_note (p, REG_RETVAL, NULL_RTX)))
                        {
                          rtx fn_address = 0;
@@ -1998,7 +2051,7 @@ move_movables (loop, movables, threshold, insn_count)
                              rtx n;
                              rtx next;
 
-                             if (GET_CODE (temp) == NOTE)
+                             if (NOTE_P (temp))
                                continue;
 
                              body = PATTERN (temp);
@@ -2007,9 +2060,9 @@ move_movables (loop, movables, threshold, insn_count)
                                 not counting USE or NOTE insns.  */
                              for (next = NEXT_INSN (temp); next != p;
                                   next = NEXT_INSN (next))
-                               if (! (GET_CODE (next) == INSN
+                               if (! (NONJUMP_INSN_P (next)
                                       && GET_CODE (PATTERN (next)) == USE)
-                                   && GET_CODE (next) != NOTE)
+                                   && !NOTE_P (next))
                                  break;
 
                              /* If that is the call, this may be the insn
@@ -2023,14 +2076,14 @@ move_movables (loop, movables, threshold, insn_count)
                                 function address into the register that the
                                 call insn will use.  flow.c will delete any
                                 redundant stores that we have created.  */
-                             if (GET_CODE (next) == CALL_INSN
+                             if (CALL_P (next)
                                  && GET_CODE (body) == SET
-                                 && GET_CODE (SET_DEST (body)) == REG
+                                 && REG_P (SET_DEST (body))
                                  && (n = find_reg_note (temp, REG_EQUAL,
                                                         NULL_RTX)))
                                {
                                  fn_reg = SET_SRC (body);
-                                 if (GET_CODE (fn_reg) != REG)
+                                 if (!REG_P (fn_reg))
                                    fn_reg = SET_DEST (body);
                                  fn_address = XEXP (n, 0);
                                  fn_address_insn = temp;
@@ -2038,14 +2091,14 @@ move_movables (loop, movables, threshold, insn_count)
                              /* We have the call insn.
                                 If it uses the register we suspect it might,
                                 load it with the correct address directly.  */
-                             if (GET_CODE (temp) == CALL_INSN
+                             if (CALL_P (temp)
                                  && fn_address != 0
                                  && reg_referenced_p (fn_reg, body))
                                loop_insn_emit_after (loop, 0, fn_address_insn,
                                                      gen_move_insn
                                                      (fn_reg, fn_address));
 
-                             if (GET_CODE (temp) == CALL_INSN)
+                             if (CALL_P (temp))
                                {
                                  i1 = loop_call_insn_hoist (loop, body);
                                  /* Because the USAGE information potentially
@@ -2088,11 +2141,11 @@ move_movables (loop, movables, threshold, insn_count)
                            abort ();
                          if (tem != reg)
                            emit_move_insn (reg, tem);
-                         sequence = gen_sequence ();
+                         sequence = get_insns ();
                          end_sequence ();
                          i1 = loop_insn_hoist (loop, sequence);
                        }
-                     else if (GET_CODE (p) == CALL_INSN)
+                     else if (CALL_P (p))
                        {
                          i1 = loop_call_insn_hoist (loop, PATTERN (p));
                          /* Because the USAGE information potentially
@@ -2108,18 +2161,28 @@ move_movables (loop, movables, threshold, insn_count)
                          /* The SET_SRC might not be invariant, so we must
                             use the REG_EQUAL note.  */
                          start_sequence ();
-                         emit_move_insn (m->set_dest, m->set_src);
-                         temp = get_insns ();
-                         seq = gen_sequence ();
+                         emit_move_insn (m->insert_temp ? newreg : m->set_dest,
+                                         m->set_src);
+                         seq = get_insns ();
                          end_sequence ();
 
-                         add_label_notes (m->set_src, temp);
+                         add_label_notes (m->set_src, seq);
 
                          i1 = loop_insn_hoist (loop, seq);
                          if (! find_reg_note (i1, REG_EQUAL, NULL_RTX))
                            set_unique_reg_note (i1, m->is_equiv ? REG_EQUIV
                                                     : REG_EQUAL, m->set_src);
                        }
+                     else if (m->insert_temp)
+                       {
+                         rtx *reg_map2 = xcalloc (REGNO (newreg),
+                                                  sizeof(rtx));
+                         reg_map2 [m->regno] = newreg;
+
+                         i1 = loop_insn_hoist (loop, copy_rtx (PATTERN (p)));
+                         replace_regs (i1, reg_map2, REGNO (newreg), 1);
+                         free (reg_map2);
+                       }
                      else
                        i1 = loop_insn_hoist (loop, PATTERN (p));
 
@@ -2166,42 +2229,57 @@ move_movables (loop, movables, threshold, insn_count)
                         pointers, but when we skip over a NOTE we must fix
                         it up.  Otherwise that code walks into the non-deleted
                         insn stream.  */
-                     while (p && GET_CODE (p) == NOTE)
+                     while (p && NOTE_P (p))
                        p = NEXT_INSN (temp) = NEXT_INSN (p);
+
+                     if (m->insert_temp)
+                       {
+                         rtx seq;
+                         /* Replace the original insn with a move from
+                            our newly created temp.  */
+                         start_sequence ();
+                         emit_move_insn (m->set_dest, newreg);
+                         seq = get_insns ();
+                         end_sequence ();
+                         emit_insn_before (seq, p);
+                       }
                    }
 
                  /* The more regs we move, the less we like moving them.  */
                  threshold -= 3;
                }
 
-             /* Any other movable that loads the same register
-                MUST be moved.  */
-             already_moved[regno] = 1;
-
-             /* This reg has been moved out of one loop.  */
-             regs->array[regno].moved_once = 1;
+             m->done = 1;
 
-             /* The reg set here is now invariant.  */
-             if (! m->partial)
+             if (!m->insert_temp)
                {
-                 int i;
-                 for (i = 0; i < LOOP_REGNO_NREGS (regno, m->set_dest); i++)
-                   regs->array[regno+i].set_in_loop = 0;
-               }
+                 /* Any other movable that loads the same register
+                    MUST be moved.  */
+                 already_moved[regno] = 1;
 
-             m->done = 1;
+                 /* This reg has been moved out of one loop.  */
+                 regs->array[regno].moved_once = 1;
 
-             /* Change the length-of-life info for the register
-                to say it lives at least the full length of this loop.
-                This will help guide optimizations in outer loops.  */
+                 /* The reg set here is now invariant.  */
+                 if (! m->partial)
+                   {
+                     int i;
+                     for (i = 0; i < LOOP_REGNO_NREGS (regno, m->set_dest); i++)
+                       regs->array[regno+i].set_in_loop = 0;
+                   }
 
-             if (REGNO_FIRST_LUID (regno) > INSN_LUID (loop_start))
-               /* This is the old insn before all the moved insns.
-                  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 (REGNO_LAST_LUID (regno) < INSN_LUID (loop_end))
-               REGNO_LAST_UID (regno) = INSN_UID (loop_end);
+                 /* Change the length-of-life info for the register
+                    to say it lives at least the full length of this loop.
+                    This will help guide optimizations in outer loops.  */
+
+                 if (REGNO_FIRST_LUID (regno) > INSN_LUID (loop_start))
+                   /* This is the old insn before all the moved insns.
+                      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 (REGNO_LAST_LUID (regno) < INSN_LUID (loop_end))
+                   REGNO_LAST_UID (regno) = INSN_UID (loop_end);
+               }
 
              /* Combine with this moved insn any other matching movables.  */
 
@@ -2233,7 +2311,7 @@ move_movables (loop, movables, threshold, insn_count)
                         and prevent further processing of it.  */
                      m1->done = 1;
 
-                     /* if library call, delete all insns.  */
+                     /* If library call, delete all insns.  */
                      if ((temp = find_reg_note (m1->insn, REG_RETVAL,
                                                 NULL_RTX)))
                        delete_insn_chain (XEXP (temp, 0), m1->insn);
@@ -2272,8 +2350,7 @@ move_movables (loop, movables, threshold, insn_count)
   /* Go through all the instructions in the loop, making
      all the register substitutions scheduled in REG_MAP.  */
   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)
+    if (INSN_P (p))
       {
        replace_regs (PATTERN (p), reg_map, nregs, 0);
        replace_regs (REG_NOTES (p), reg_map, nregs, 0);
@@ -2287,9 +2364,7 @@ move_movables (loop, movables, threshold, insn_count)
 
 
 static void
-loop_movables_add (movables, m)
-     struct loop_movables *movables;
-     struct movable *m;
+loop_movables_add (struct loop_movables *movables, struct movable *m)
 {
   if (movables->head == 0)
     movables->head = m;
@@ -2300,8 +2375,7 @@ loop_movables_add (movables, m)
 
 
 static void
-loop_movables_free (movables)
-     struct loop_movables *movables;
+loop_movables_free (struct loop_movables *movables)
 {
   struct movable *m;
   struct movable *m_next;
@@ -2318,8 +2392,7 @@ loop_movables_free (movables)
    REG is the address that MEM should have before the replacement.  */
 
 static void
-replace_call_address (x, reg, addr)
-     rtx x, reg, addr;
+replace_call_address (rtx x, rtx reg, rtx addr)
 {
   enum rtx_code code;
   int i;
@@ -2381,9 +2454,7 @@ replace_call_address (x, reg, addr)
    in the rtx X.  */
 
 static int
-count_nonfixed_reads (loop, x)
-     const struct loop *loop;
-     rtx x;
+count_nonfixed_reads (const struct loop *loop, rtx x)
 {
   enum rtx_code code;
   int i;
@@ -2437,8 +2508,7 @@ count_nonfixed_reads (loop, x)
    list `store_mems' in LOOP.  */
 
 static void
-prescan_loop (loop)
-     struct loop *loop;
+prescan_loop (struct loop *loop)
 {
   int level = 1;
   rtx insn;
@@ -2467,12 +2537,13 @@ prescan_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 && GET_CODE (insn) != CODE_LABEL;
+  for (insn = start; insn && !LABEL_P (insn);
        insn = PREV_INSN (insn))
     {
-      if (GET_CODE (insn) == CALL_INSN)
+      if (CALL_P (insn))
        {
          loop_info->pre_header_has_call = 1;
          break;
@@ -2506,6 +2577,30 @@ prescan_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:
@@ -2559,13 +2654,13 @@ prescan_loop (loop)
                  loop_info->has_multiple_exit_targets = 1;
                }
            }
-         /* FALLTHRU */
+         /* Fall through.  */
 
        case INSN:
          if (volatile_refs_p (PATTERN (insn)))
            loop_info->has_volatile = 1;
 
-         if (GET_CODE (insn) == JUMP_INSN
+         if (JUMP_P (insn)
              && (GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC
                  || GET_CODE (PATTERN (insn)) == ADDR_VEC))
            loop_info->has_tablejump = 1;
@@ -2622,8 +2717,7 @@ prescan_loop (loop)
 /* Invalidate all loops containing LABEL.  */
 
 static void
-invalidate_loops_containing_label (label)
-     rtx label;
+invalidate_loops_containing_label (rtx label)
 {
   struct loop *loop;
   for (loop = uid_loop[INSN_UID (label)]; loop; loop = loop->outer)
@@ -2635,9 +2729,7 @@ invalidate_loops_containing_label (label)
    to from outside the loop.  */
 
 static void
-find_and_verify_loops (f, loops)
-     rtx f;
-     struct loops *loops;
+find_and_verify_loops (rtx f, struct loops *loops)
 {
   rtx insn;
   rtx label;
@@ -2662,7 +2754,7 @@ find_and_verify_loops (f, loops)
   current_loop = NULL;
   for (insn = f; insn; insn = NEXT_INSN (insn))
     {
-      if (GET_CODE (insn) == NOTE)
+      if (NOTE_P (insn))
        switch (NOTE_LINE_NUMBER (insn))
          {
          case NOTE_INSN_LOOP_BEG:
@@ -2694,7 +2786,7 @@ find_and_verify_loops (f, loops)
            break;
          }
 
-      if (GET_CODE (insn) == CALL_INSN
+      if (CALL_P (insn)
          && find_reg_note (insn, REG_SETJMP, NULL))
        {
          /* In this case, we must invalidate our current loop and any
@@ -2741,14 +2833,14 @@ find_and_verify_loops (f, loops)
       {
        struct loop *this_loop = uid_loop[INSN_UID (insn)];
 
-       if (GET_CODE (insn) == INSN || GET_CODE (insn) == CALL_INSN)
+       if (NONJUMP_INSN_P (insn) || CALL_P (insn))
          {
            rtx note = find_reg_note (insn, REG_LABEL, NULL_RTX);
            if (note)
              invalidate_loops_containing_label (XEXP (note, 0));
          }
 
-       if (GET_CODE (insn) != JUMP_INSN)
+       if (!JUMP_P (insn))
          continue;
 
        mark_loop_jump (PATTERN (insn), this_loop);
@@ -2771,10 +2863,10 @@ find_and_verify_loops (f, loops)
            /* Go backwards until we reach the start of the loop, a label,
               or a JUMP_INSN.  */
            for (p = PREV_INSN (insn);
-                GET_CODE (p) != CODE_LABEL
-                && ! (GET_CODE (p) == NOTE
+                !LABEL_P (p)
+                && ! (NOTE_P (p)
                       && NOTE_LINE_NUMBER (p) == NOTE_INSN_LOOP_BEG)
-                && GET_CODE (p) != JUMP_INSN;
+                && !JUMP_P (p);
                 p = PREV_INSN (p))
              ;
 
@@ -2795,7 +2887,7 @@ find_and_verify_loops (f, loops)
 
            /* Make sure that the target of P is within the current loop.  */
 
-           if (GET_CODE (p) == JUMP_INSN && JUMP_LABEL (p)
+           if (JUMP_P (p) && JUMP_LABEL (p)
                && uid_loop[INSN_UID (JUMP_LABEL (p))] != this_loop)
              outer_loop = this_loop;
 
@@ -2809,7 +2901,7 @@ find_and_verify_loops (f, loops)
               and move the block of code to the spot we found.  */
 
            if (! outer_loop
-               && GET_CODE (p) == JUMP_INSN
+               && JUMP_P (p)
                && JUMP_LABEL (p) != 0
                /* Just ignore jumps to labels that were never emitted.
                   These always indicate compilation errors.  */
@@ -2830,17 +2922,17 @@ find_and_verify_loops (f, loops)
                /* Search for possible garbage past the conditional jumps
                   and look for the last barrier.  */
                for (tmp = last_insn_to_move;
-                    tmp && GET_CODE (tmp) != CODE_LABEL; tmp = NEXT_INSN (tmp))
-                 if (GET_CODE (tmp) == BARRIER)
+                    tmp && !LABEL_P (tmp); tmp = NEXT_INSN (tmp))
+                 if (BARRIER_P (tmp))
                    last_insn_to_move = tmp;
 
                for (loc = target; loc; loc = PREV_INSN (loc))
-                 if (GET_CODE (loc) == BARRIER
+                 if (BARRIER_P (loc)
                      /* Don't move things inside a tablejump.  */
                      && ((loc2 = next_nonnote_insn (loc)) == 0
-                         || GET_CODE (loc2) != CODE_LABEL
+                         || !LABEL_P (loc2)
                          || (loc2 = next_nonnote_insn (loc2)) == 0
-                         || GET_CODE (loc2) != JUMP_INSN
+                         || !JUMP_P (loc2)
                          || (GET_CODE (PATTERN (loc2)) != ADDR_VEC
                              && GET_CODE (PATTERN (loc2)) != ADDR_DIFF_VEC))
                      && uid_loop[INSN_UID (loc)] == target_loop)
@@ -2848,12 +2940,12 @@ find_and_verify_loops (f, loops)
 
                if (loc == 0)
                  for (loc = target; loc; loc = NEXT_INSN (loc))
-                   if (GET_CODE (loc) == BARRIER
+                   if (BARRIER_P (loc)
                        /* Don't move things inside a tablejump.  */
                        && ((loc2 = next_nonnote_insn (loc)) == 0
-                           || GET_CODE (loc2) != CODE_LABEL
+                           || !LABEL_P (loc2)
                            || (loc2 = next_nonnote_insn (loc2)) == 0
-                           || GET_CODE (loc2) != JUMP_INSN
+                           || !JUMP_P (loc2)
                            || (GET_CODE (PATTERN (loc2)) != ADDR_VEC
                                && GET_CODE (PATTERN (loc2)) != ADDR_DIFF_VEC))
                        && uid_loop[INSN_UID (loc)] == target_loop)
@@ -2875,7 +2967,7 @@ find_and_verify_loops (f, loops)
 
                        /* If no suitable BARRIER was found, create a suitable
                           one before TARGET.  Since TARGET is a fall through
-                          path, we'll need to insert an jump around our block
+                          path, we'll need to insert a jump around our block
                           and add a BARRIER before TARGET.
 
                           This creates an extra unconditional jump outside
@@ -2973,9 +3065,7 @@ find_and_verify_loops (f, loops)
    For speed, we assume that X is part of a pattern of a JUMP_INSN.  */
 
 static void
-mark_loop_jump (x, loop)
-     rtx x;
-     struct loop *loop;
+mark_loop_jump (rtx x, struct loop *loop)
 {
   struct loop *dest_loop;
   struct loop *outer_loop;
@@ -3121,13 +3211,11 @@ mark_loop_jump (x, loop)
    been previously created by loop.c).  */
 
 static int
-labels_in_range_p (insn, end)
-     rtx insn;
-     int end;
+labels_in_range_p (rtx insn, int end)
 {
   while (insn && INSN_LUID (insn) <= end)
     {
-      if (GET_CODE (insn) == CODE_LABEL)
+      if (LABEL_P (insn))
        return 1;
       insn = NEXT_INSN (insn);
     }
@@ -3138,14 +3226,12 @@ labels_in_range_p (insn, end)
 /* Record that a memory reference X is being set.  */
 
 static void
-note_addr_stored (x, y, data)
-     rtx x;
-     rtx y ATTRIBUTE_UNUSED;
-     void *data ATTRIBUTE_UNUSED;
+note_addr_stored (rtx x, rtx y ATTRIBUTE_UNUSED,
+                 void *data ATTRIBUTE_UNUSED)
 {
   struct loop_info *loop_info = data;
 
-  if (x == 0 || GET_CODE (x) != MEM)
+  if (x == 0 || !MEM_P (x))
     return;
 
   /* Count number of memory writes.
@@ -3173,10 +3259,7 @@ note_addr_stored (x, y, data)
    used more than once.  DATA is a pointer to a loop_regs structure.  */
 
 static void
-note_set_pseudo_multiple_uses (x, y, data)
-     rtx x;
-     rtx y ATTRIBUTE_UNUSED;
-     void *data;
+note_set_pseudo_multiple_uses (rtx x, rtx y ATTRIBUTE_UNUSED, void *data)
 {
   struct loop_regs *regs = (struct loop_regs *) data;
 
@@ -3189,7 +3272,7 @@ note_set_pseudo_multiple_uses (x, y, data)
         || GET_CODE (x) == SUBREG)
     x = XEXP (x, 0);
 
-  if (GET_CODE (x) != REG || REGNO (x) < FIRST_PSEUDO_REGISTER)
+  if (!REG_P (x) || REGNO (x) < FIRST_PSEUDO_REGISTER)
     return;
 
   /* If we do not have usage information, or if we know the register
@@ -3208,9 +3291,7 @@ note_set_pseudo_multiple_uses (x, y, data)
    with anything stored in `loop_info->store_mems'.  */
 
 int
-loop_invariant_p (loop, x)
-     const struct loop *loop;
-     rtx x;
+loop_invariant_p (const struct loop *loop, rtx x)
 {
   struct loop_info *loop_info = LOOP_INFO (loop);
   struct loop_regs *regs = LOOP_REGS (loop);
@@ -3241,7 +3322,7 @@ loop_invariant_p (loop, x)
 
         We don't know the loop bounds here though, so just fail for all
         labels.  */
-      if (flag_unroll_loops)
+      if (flag_old_unroll_loops)
        return 0;
       else
        return 1;
@@ -3264,6 +3345,19 @@ loop_invariant_p (loop, x)
          && REGNO (x) < FIRST_PSEUDO_REGISTER && call_used_regs[REGNO (x)])
        return 0;
 
+      /* Out-of-range regs can occur when we are called from unrolling.
+        These registers created by the unroller are set in the loop,
+        hence are never invariant.
+        Other out-of-range regs can be generated by load_mems; those that
+        are written to in the loop are not invariant, while those that are
+        not written to are invariant.  It would be easy for load_mems
+        to set n_times_set correctly for these registers, however, there
+        is no easy way to distinguish them from registers created by the
+        unroller.  */
+
+      if (REGNO (x) >= (unsigned) regs->num)
+       return 0;
+
       if (regs->array[REGNO (x)].set_in_loop < 0)
        return 2;
 
@@ -3341,10 +3435,8 @@ loop_invariant_p (loop, x)
    and that its source is invariant.  */
 
 static int
-consec_sets_invariant_p (loop, reg, n_sets, insn)
-     const struct loop *loop;
-     int n_sets;
-     rtx reg, insn;
+consec_sets_invariant_p (const struct loop *loop, rtx reg, int n_sets,
+                        rtx insn)
 {
   struct loop_regs *regs = LOOP_REGS (loop);
   rtx p = insn;
@@ -3377,7 +3469,7 @@ consec_sets_invariant_p (loop, reg, n_sets, insn)
       this = 0;
       if (code == INSN
          && (set = single_set (p))
-         && GET_CODE (SET_DEST (set)) == REG
+         && REG_P (SET_DEST (set))
          && REGNO (SET_DEST (set)) == regno)
        {
          this = loop_invariant_p (loop, SET_SRC (set));
@@ -3408,49 +3500,13 @@ consec_sets_invariant_p (loop, reg, n_sets, insn)
   /* If loop_invariant_p ever returned 2, we return 2.  */
   return 1 + (value & 2);
 }
-
-#if 0
-/* I don't think this condition is sufficient to allow INSN
-   to be moved, so we no longer test it.  */
-
-/* Return 1 if all insns in the basic block of INSN and following INSN
-   that set REG are invariant according to TABLE.  */
-
-static int
-all_sets_invariant_p (reg, insn, table)
-     rtx reg, insn;
-     short *table;
-{
-  rtx p = insn;
-  int regno = REGNO (reg);
-
-  while (1)
-    {
-      enum rtx_code code;
-      p = NEXT_INSN (p);
-      code = GET_CODE (p);
-      if (code == CODE_LABEL || code == JUMP_INSN)
-       return 1;
-      if (code == INSN && GET_CODE (PATTERN (p)) == SET
-         && GET_CODE (SET_DEST (PATTERN (p))) == REG
-         && REGNO (SET_DEST (PATTERN (p))) == regno)
-       {
-         if (! loop_invariant_p (loop, SET_SRC (PATTERN (p)), table))
-           return 0;
-       }
-    }
-}
-#endif /* 0 */
 \f
 /* Look at all uses (not sets) of registers in X.  For each, if it is
    the single use, set USAGE[REGNO] to INSN; if there was a previous use in
    a different insn, set USAGE[REGNO] to const0_rtx.  */
 
 static void
-find_single_use_in_loop (regs, insn, x)
-     struct loop_regs *regs;
-     rtx insn;
-     rtx x;
+find_single_use_in_loop (struct loop_regs *regs, rtx insn, rtx x)
 {
   enum rtx_code code = GET_CODE (x);
   const char *fmt = GET_RTX_FORMAT (code);
@@ -3468,7 +3524,7 @@ find_single_use_in_loop (regs, insn, x)
         in SET_DEST because if a register is partially modified, it won't
         show up as a potential movable so we don't care how USAGE is set
         for it.  */
-      if (GET_CODE (SET_DEST (x)) != REG)
+      if (!REG_P (SET_DEST (x)))
        find_single_use_in_loop (regs, insn, SET_DEST (x));
       find_single_use_in_loop (regs, insn, SET_SRC (x));
     }
@@ -3488,12 +3544,9 @@ find_single_use_in_loop (regs, insn, x)
    in X.  */
 
 static void
-count_one_set (regs, insn, x, last_set)
-     struct loop_regs *regs;
-     rtx insn, x;
-     rtx *last_set;
+count_one_set (struct loop_regs *regs, rtx insn, rtx x, rtx *last_set)
 {
-  if (GET_CODE (x) == CLOBBER && GET_CODE (XEXP (x, 0)) == REG)
+  if (GET_CODE (x) == CLOBBER && REG_P (XEXP (x, 0)))
     /* Don't move a reg that has an explicit clobber.
        It's not worth the pain to try to do it correctly.  */
     regs->array[REGNO (XEXP (x, 0))].may_not_optimize = 1;
@@ -3506,7 +3559,7 @@ count_one_set (regs, insn, x, last_set)
             || GET_CODE (dest) == SIGN_EXTRACT
             || GET_CODE (dest) == STRICT_LOW_PART)
        dest = XEXP (dest, 0);
-      if (GET_CODE (dest) == REG)
+      if (REG_P (dest))
        {
          int i;
          int regno = REGNO (dest);
@@ -3517,7 +3570,7 @@ count_one_set (regs, insn, x, last_set)
                 it must be set in two basic blocks, so it cannot
                 be moved out of the loop.  */
              if (regs->array[regno].set_in_loop > 0
-                 && last_set == 0)
+                 && last_set[regno] == 0)
                regs->array[regno+i].may_not_optimize = 1;
              /* If this is not first setting in current basic block,
                 see if reg was used in between previous one and this.
@@ -3543,9 +3596,7 @@ count_one_set (regs, insn, x, last_set)
    from an inner loop past two loops.  */
 
 static int
-loop_reg_used_before_p (loop, set, insn)
-     const struct loop *loop;
-     rtx set, insn;
+loop_reg_used_before_p (const struct loop *loop, rtx set, rtx insn)
 {
   rtx reg = SET_DEST (set);
   rtx p;
@@ -3575,7 +3626,7 @@ struct prefetch_info
   HOST_WIDE_INT index;
   HOST_WIDE_INT stride;                /* Prefetch stride in bytes in each
                                   iteration.  */
-  unsigned int bytes_accessed; /* Sum of sizes of all acceses to this
+  unsigned int bytes_accessed; /* Sum of sizes of all accesses to this
                                   prefetch area in one iteration.  */
   unsigned int total_bytes;    /* Total bytes loop will access in this block.
                                   This is set only for loops with known
@@ -3593,33 +3644,30 @@ struct check_store_data
   int mem_write;
 };
 
-static void check_store PARAMS ((rtx, rtx, void *));
-static void emit_prefetch_instructions PARAMS ((struct loop *));
-static int rtx_equal_for_prefetch_p PARAMS ((rtx, rtx));
+static void check_store (rtx, rtx, void *);
+static void emit_prefetch_instructions (struct loop *);
+static int rtx_equal_for_prefetch_p (rtx, rtx);
 
 /* Set mem_write when mem_address is found.  Used as callback to
    note_stores.  */
 static void
-check_store (x, pat, data)
-     rtx x, pat ATTRIBUTE_UNUSED;
-     void *data;
+check_store (rtx x, rtx pat ATTRIBUTE_UNUSED, void *data)
 {
   struct check_store_data *d = (struct check_store_data *) data;
 
-  if ((GET_CODE (x) == MEM) && rtx_equal_p (d->mem_address, XEXP (x, 0)))
+  if ((MEM_P (x)) && rtx_equal_p (d->mem_address, XEXP (x, 0)))
     d->mem_write = 1;
 }
 \f
 /* Like rtx_equal_p, but attempts to swap commutative operands.  This is
    important to get some addresses combined.  Later more sophisticated
-   transformations can be added when necesary.
+   transformations can be added when necessary.
 
    ??? Same trick with swapping operand is done at several other places.
    It can be nice to develop some common way to handle this.  */
 
 static int
-rtx_equal_for_prefetch_p (x, y)
-     rtx x, y;
+rtx_equal_for_prefetch_p (rtx x, rtx y)
 {
   int i;
   int j;
@@ -3631,15 +3679,14 @@ rtx_equal_for_prefetch_p (x, y)
   if (code != GET_CODE (y))
     return 0;
 
-  code = GET_CODE (x);
-
-  if (GET_RTX_CLASS (code) == 'c')
+  if (COMMUTATIVE_ARITH_P (x))
     {
       return ((rtx_equal_for_prefetch_p (XEXP (x, 0), XEXP (y, 0))
               && rtx_equal_for_prefetch_p (XEXP (x, 1), XEXP (y, 1)))
              || (rtx_equal_for_prefetch_p (XEXP (x, 0), XEXP (y, 1))
                  && rtx_equal_for_prefetch_p (XEXP (x, 1), XEXP (y, 0))));
     }
+
   /* Compare the elements.  If any pair of corresponding elements fails to
      match, return 0 for the whole thing.  */
 
@@ -3701,8 +3748,7 @@ rtx_equal_for_prefetch_p (x, y)
    and return it.  */
 
 static HOST_WIDE_INT
-remove_constant_addition (x)
-     rtx *x;
+remove_constant_addition (rtx *x)
 {
   HOST_WIDE_INT addval = 0;
   rtx exp = *x;
@@ -3764,8 +3810,7 @@ remove_constant_addition (x)
    controlled by defined symbols that can be overridden for each target.  */
 
 static void
-emit_prefetch_instructions (loop)
-     struct loop *loop;
+emit_prefetch_instructions (struct loop *loop)
 {
   int num_prefetches = 0;
   int num_real_prefetches = 0;
@@ -4097,11 +4142,9 @@ emit_prefetch_instructions (loop)
                   " density: %d%%; bytes_accessed: %u; total_bytes: %u\n",
                   (int) (info[i].bytes_accessed * 100 / info[i].stride),
                   info[i].bytes_accessed, info[i].total_bytes);
-         fprintf (loop_dump_stream, " index: ");
-         fprintf (loop_dump_stream, HOST_WIDE_INT_PRINT_DEC, info[i].index);
-         fprintf (loop_dump_stream, "; stride: ");
-         fprintf (loop_dump_stream, HOST_WIDE_INT_PRINT_DEC, info[i].stride);
-         fprintf (loop_dump_stream, "; address: ");
+         fprintf (loop_dump_stream, " index: " HOST_WIDE_INT_PRINT_DEC
+                  "; stride: " HOST_WIDE_INT_PRINT_DEC "; address: ",
+                  info[i].index, info[i].stride);
          print_rtl (loop_dump_stream, info[i].base_address);
          fprintf (loop_dump_stream, "\n");
        }
@@ -4142,8 +4185,8 @@ emit_prefetch_instructions (loop)
            {
              rtx reg = gen_reg_rtx (Pmode);
              loop_iv_add_mult_emit_before (loop, loc, const1_rtx,
-                                           GEN_INT (bytes_ahead), reg,
-                                           0, before_insn);
+                                           GEN_INT (bytes_ahead), reg,
+                                           0, before_insn);
              loc = reg;
            }
 
@@ -4154,7 +4197,7 @@ emit_prefetch_instructions (loop)
            loc = force_reg (Pmode, loc);
          emit_insn (gen_prefetch (loc, GEN_INT (info[i].write),
                                   GEN_INT (3)));
-         seq = gen_sequence ();
+         seq = get_insns ();
          end_sequence ();
          emit_insn_before (seq, before_insn);
 
@@ -4188,7 +4231,15 @@ emit_prefetch_instructions (loop)
                 non-constant INIT_VAL to have the same mode as REG, which
                 in this case we know to be Pmode.  */
              if (GET_MODE (init_val) != Pmode && !CONSTANT_P (init_val))
-               init_val = convert_to_mode (Pmode, init_val, 0);
+               {
+                 rtx seq;
+
+                 start_sequence ();
+                 init_val = convert_to_mode (Pmode, init_val, 0);
+                 seq = get_insns ();
+                 end_sequence ();
+                 loop_insn_emit_before (loop, 0, loop_start, seq);
+               }
              loop_iv_add_mult_emit_before (loop, init_val,
                                            info[i].giv->mult_val,
                                            add_val, reg, 0, loop_start);
@@ -4202,19 +4253,11 @@ emit_prefetch_instructions (loop)
   return;
 }
 \f
-/* 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'.  */
-
 /* Communication with routines called via `note_stores'.  */
 
 static rtx note_insn;
 
-/* Dummy register to have non-zero DEST_REG for DEST_ADDR type givs.  */
+/* Dummy register to have nonzero DEST_REG for DEST_ADDR type givs.  */
 
 static rtx addr_placeholder;
 
@@ -4249,19 +4292,15 @@ static rtx addr_placeholder;
    LOOP and INSN parameters pass MAYBE_MULTIPLE and NOT_EVERY_ITERATION to the
    callback.
 
-   NOT_EVERY_ITERATION if current insn is not executed at least once for every
-   loop iteration except for the last one.
+   NOT_EVERY_ITERATION is 1 if current insn is not known to be executed at
+   least once for every loop iteration except for the last one.
 
    MAYBE_MULTIPLE is 1 if current insn may be executed more than once for every
    loop iteration.
  */
 void
-for_each_insn_in_loop (loop, fncall)
-     struct loop *loop;
-     loop_insn_callback fncall;
+for_each_insn_in_loop (struct loop *loop, loop_insn_callback fncall)
 {
-  /* This is 1 if current insn is not executed at least once for every loop
-     iteration.  */
   int not_every_iteration = 0;
   int maybe_multiple = 0;
   int past_loop_latch = 0;
@@ -4273,8 +4312,7 @@ for_each_insn_in_loop (loop, fncall)
   if (prev_nonnote_insn (loop->scan_start) != prev_nonnote_insn (loop->start))
     maybe_multiple = back_branch_in_range_p (loop, loop->scan_start);
 
-  /* Scan through loop to find all possible bivs.  */
-
+  /* Scan through loop and update NOT_EVERY_ITERATION and MAYBE_MULTIPLE.  */
   for (p = next_insn_in_loop (loop, loop->scan_start);
        p != NULL_RTX;
        p = next_insn_in_loop (loop, p))
@@ -4287,7 +4325,7 @@ for_each_insn_in_loop (loop, fncall)
          returns, exits the loop, is a jump to a location that is still
          behind the label, or is a jump to the loop start.  */
 
-      if (GET_CODE (p) == CODE_LABEL)
+      if (LABEL_P (p))
        {
          rtx insn = p;
 
@@ -4308,7 +4346,7 @@ for_each_insn_in_loop (loop, fncall)
                    break;
                }
 
-             if (GET_CODE (insn) == JUMP_INSN
+             if (JUMP_P (insn)
                  && GET_CODE (PATTERN (insn)) != RETURN
                  && (!any_condjump_p (insn)
                      || (JUMP_LABEL (insn) != 0
@@ -4325,15 +4363,15 @@ for_each_insn_in_loop (loop, fncall)
          on whether they will be executed during each iteration.  */
       /* This code appears twice in strength_reduce.  There is also similar
          code in scan_loop.  */
-      if (GET_CODE (p) == JUMP_INSN
+      if (JUMP_P (p)
       /* If we enter the loop in the middle, and scan around to the
          beginning, don't set not_every_iteration for that.
          This can be any kind of jump, since we want to know if insns
          will be executed if the loop is executed.  */
          && !(JUMP_LABEL (p) == loop->top
-            && ((NEXT_INSN (NEXT_INSN (p)) == loop->end
-                 && any_uncondjump_p (p))
-                || (NEXT_INSN (p) == loop->end && any_condjump_p (p)))))
+              && ((NEXT_INSN (NEXT_INSN (p)) == loop->end
+                   && any_uncondjump_p (p))
+                  || (NEXT_INSN (p) == loop->end && any_condjump_p (p)))))
        {
          rtx label = 0;
 
@@ -4349,7 +4387,7 @@ for_each_insn_in_loop (loop, fncall)
            not_every_iteration = 1;
        }
 
-      else if (GET_CODE (p) == NOTE)
+      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
@@ -4375,7 +4413,7 @@ for_each_insn_in_loop (loop, fncall)
          Note that LOOP_TOP is only set for rotated loops and we need
          this check for all loops, so compare against the CODE_LABEL
          which immediately follows LOOP_START.  */
-      if (GET_CODE (p) == JUMP_INSN
+      if (JUMP_P (p)
          && JUMP_LABEL (p) == NEXT_INSN (loop->start))
        past_loop_latch = 1;
 
@@ -4391,7 +4429,7 @@ for_each_insn_in_loop (loop, fncall)
 
       if (not_every_iteration
          && !past_loop_latch
-         && GET_CODE (p) == CODE_LABEL
+         && LABEL_P (p)
          && no_labels_between_p (p, loop->end)
          && loop_insn_first_p (p, loop->cont))
        not_every_iteration = 0;
@@ -4399,8 +4437,7 @@ for_each_insn_in_loop (loop, fncall)
 }
 \f
 static void
-loop_bivs_find (loop)
-     struct loop *loop;
+loop_bivs_find (struct loop *loop)
 {
   struct loop_regs *regs = LOOP_REGS (loop);
   struct loop_ivs *ivs = LOOP_IVS (loop);
@@ -4445,11 +4482,10 @@ loop_bivs_find (loop)
 }
 
 
-/* Determine how BIVS are initialised by looking through pre-header
+/* Determine how BIVS are initialized by looking through pre-header
    extended basic block.  */
 static void
-loop_bivs_init_find (loop)
-     struct loop *loop;
+loop_bivs_init_find (struct loop *loop)
 {
   struct loop_ivs *ivs = LOOP_IVS (loop);
   /* Temporary list pointers for traversing ivs->list.  */
@@ -4461,13 +4497,13 @@ loop_bivs_init_find (loop)
      halting at first label.  Also record any test condition.  */
 
   call_seen = 0;
-  for (p = loop->start; p && GET_CODE (p) != CODE_LABEL; p = PREV_INSN (p))
+  for (p = loop->start; p && !LABEL_P (p); p = PREV_INSN (p))
     {
       rtx test;
 
       note_insn = p;
 
-      if (GET_CODE (p) == CALL_INSN)
+      if (CALL_P (p))
        call_seen = 1;
 
       if (INSN_P (p))
@@ -4476,11 +4512,11 @@ loop_bivs_init_find (loop)
       /* Record any test of a biv that branches around the loop if no store
         between it and the start of loop.  We only care about tests with
         constants and registers and only certain of those.  */
-      if (GET_CODE (p) == JUMP_INSN
+      if (JUMP_P (p)
          && JUMP_LABEL (p) != 0
          && next_real_insn (JUMP_LABEL (p)) == next_real_insn (loop->end)
          && (test = get_condition_for_loop (loop, p)) != 0
-         && GET_CODE (XEXP (test, 0)) == REG
+         && REG_P (XEXP (test, 0))
          && REGNO (XEXP (test, 0)) < max_reg_before_loop
          && (bl = REG_IV_CLASS (ivs, REGNO (XEXP (test, 0)))) != 0
          && valid_initial_value_p (XEXP (test, 1), p, call_seen, loop->start)
@@ -4504,8 +4540,7 @@ loop_bivs_init_find (loop)
    initial value from any initializing insns set up above.  (This is done
    in two passes to avoid missing SETs in a PARALLEL.)  */
 static void
-loop_bivs_check (loop)
-     struct loop *loop;
+loop_bivs_check (struct loop *loop)
 {
   struct loop_ivs *ivs = LOOP_IVS (loop);
   /* Temporary list pointers for traversing ivs->list.  */
@@ -4560,8 +4595,7 @@ loop_bivs_check (loop)
 /* Search the loop for general induction variables.  */
 
 static void
-loop_givs_find (loop)
-     struct loop* loop;
+loop_givs_find (struct loop* loop)
 {
   for_each_insn_in_loop (loop, check_insn_for_givs);
 }
@@ -4572,8 +4606,7 @@ loop_givs_find (loop)
    can be calculated.  */
 
 static void
-loop_givs_check (loop)
-     struct loop *loop;
+loop_givs_check (struct loop *loop)
 {
   struct loop_ivs *ivs = LOOP_IVS (loop);
   struct iv_class *bl;
@@ -4589,17 +4622,14 @@ loop_givs_check (loop)
 }
 
 
-/* Return non-zero if it is possible to eliminate the biv BL provided
+/* 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
    used outside the loop, or we can compute what its final value will
    be.  */
 
 static int
-loop_biv_eliminable_p (loop, bl, threshold, insn_count)
-     struct loop *loop;
-     struct iv_class *bl;
-     int threshold;
-     int insn_count;
+loop_biv_eliminable_p (struct loop *loop, struct iv_class *bl,
+                      int threshold, int insn_count)
 {
   /* For architectures with a decrement_and_branch_until_zero insn,
      don't do this if we put a REG_NONNEG note on the endtest for this
@@ -4647,9 +4677,7 @@ loop_biv_eliminable_p (loop, bl, threshold, insn_count)
 /* Reduce each giv of BL that we have decided to reduce.  */
 
 static void
-loop_givs_reduce (loop, bl)
-     struct loop *loop;
-     struct iv_class *bl;
+loop_givs_reduce (struct loop *loop, struct iv_class *bl)
 {
   struct induction *v;
 
@@ -4670,13 +4698,24 @@ loop_givs_reduce (loop, bl)
             this is an address giv, then try to put the increment
             immediately after its use, so that flow can create an
             auto-increment addressing mode.  */
+         /* Don't do this for loops entered at the bottom, to avoid
+            this invalid transformation:
+               jmp L;          ->          jmp L;
+            TOP:                       TOP:
+               use giv                     use giv
+            L:                             inc giv
+               inc biv                 L:
+               test biv                    test giv
+               cbr TOP                     cbr TOP
+         */
          if (v->giv_type == DEST_ADDR && bl->biv_count == 1
              && bl->biv->always_executed && ! bl->biv->maybe_multiple
              /* We don't handle reversed biv's because bl->biv->insn
                 does not have a valid INSN_LUID.  */
              && ! bl->reversed
              && v->always_executed && ! v->maybe_multiple
-             && INSN_UID (v->insn) < max_uid_for_loop)
+             && INSN_UID (v->insn) < max_uid_for_loop
+             && !loop->top)    
            {
              /* If other giv's have been combined with this one, then
                 this will work only if all uses of the other giv's occur
@@ -4748,8 +4787,11 @@ loop_givs_reduce (loop, bl)
            {
              rtx insert_before;
 
+             /* Skip if location is the same as a previous one.  */
+             if (tv->same)
+               continue;
              if (! auto_inc_opt)
-               insert_before = tv->insn;
+               insert_before = NEXT_INSN (tv->insn);
              else if (auto_inc_opt == 1)
                insert_before = NEXT_INSN (v->insn);
              else
@@ -4783,9 +4825,7 @@ loop_givs_reduce (loop, bl)
    eliminate a biv.  */
 
 static void
-loop_givs_dead_check (loop, bl)
-     struct loop *loop ATTRIBUTE_UNUSED;
-     struct iv_class *bl;
+loop_givs_dead_check (struct loop *loop ATTRIBUTE_UNUSED, struct iv_class *bl)
 {
   struct induction *v;
 
@@ -4809,10 +4849,7 @@ loop_givs_dead_check (loop, bl)
 
 
 static void
-loop_givs_rescan (loop, bl, reg_map)
-     struct loop *loop;
-     struct iv_class *bl;
-     rtx *reg_map;
+loop_givs_rescan (struct loop *loop, struct iv_class *bl, rtx *reg_map)
 {
   struct induction *v;
 
@@ -4837,12 +4874,12 @@ loop_givs_rescan (loop, bl, reg_map)
         computational information.  If not, and this is a DEST_ADDR
         giv, at least we know that it's a pointer, though we don't know
         the alignment.  */
-      if (GET_CODE (v->new_reg) == REG
+      if (REG_P (v->new_reg)
          && v->giv_type == DEST_REG
          && REG_POINTER (v->dest_reg))
        mark_reg_pointer (v->new_reg,
                          REGNO_POINTER_ALIGN (REGNO (v->dest_reg)));
-      else if (GET_CODE (v->new_reg) == REG
+      else if (REG_P (v->new_reg)
               && REG_POINTER (v->src_reg))
        {
          unsigned int align = REGNO_POINTER_ALIGN (REGNO (v->src_reg));
@@ -4854,8 +4891,8 @@ loop_givs_rescan (loop, bl, reg_map)
 
          mark_reg_pointer (v->new_reg, align);
        }
-      else if (GET_CODE (v->new_reg) == REG
-              && GET_CODE (v->add_val) == REG
+      else if (REG_P (v->new_reg)
+              && REG_P (v->add_val)
               && REG_POINTER (v->add_val))
        {
          unsigned int align = REGNO_POINTER_ALIGN (REGNO (v->add_val));
@@ -4866,7 +4903,7 @@ loop_givs_rescan (loop, bl, reg_map)
 
          mark_reg_pointer (v->new_reg, align);
        }
-      else if (GET_CODE (v->new_reg) == REG && v->giv_type == DEST_ADDR)
+      else if (REG_P (v->new_reg) && v->giv_type == DEST_ADDR)
        mark_reg_pointer (v->new_reg, 0);
 
       if (v->giv_type == DEST_ADDR)
@@ -4879,10 +4916,22 @@ loop_givs_rescan (loop, bl, reg_map)
        }
       else
        {
+         rtx original_insn = v->insn;
+         rtx note;
+
          /* Not replaceable; emit an insn to set the original giv reg from
             the reduced giv, same as above.  */
-         loop_insn_emit_after (loop, 0, v->insn,
-                               gen_move_insn (v->dest_reg, v->new_reg));
+         v->insn = loop_insn_emit_after (loop, 0, original_insn,
+                                         gen_move_insn (v->dest_reg,
+                                                        v->new_reg));
+
+         /* The original insn may have a REG_EQUAL note.  This note is
+            now incorrect and may result in invalid substitutions later.
+            The original insn is dead, but may be part of a libcall
+            sequence, which doesn't seem worth the bother of handling.  */
+         note = find_reg_note (original_insn, REG_EQUAL, NULL_RTX);
+         if (note)
+           remove_note (original_insn, note);
        }
 
       /* When a loop is reversed, givs which depend on the reversed
@@ -4911,11 +4960,9 @@ loop_givs_rescan (loop, bl, reg_map)
 
 
 static int
-loop_giv_reduce_benefit (loop, bl, v, test_reg)
-     struct loop *loop ATTRIBUTE_UNUSED;
-     struct iv_class *bl;
-     struct induction *v;
-     rtx test_reg;
+loop_giv_reduce_benefit (struct loop *loop ATTRIBUTE_UNUSED,
+                        struct iv_class *bl, struct induction *v,
+                        rtx test_reg)
 {
   int add_cost;
   int benefit;
@@ -4988,8 +5035,7 @@ loop_giv_reduce_benefit (loop, bl, v, test_reg)
 /* Free IV structures for LOOP.  */
 
 static void
-loop_ivs_free (loop)
-     struct loop *loop;
+loop_ivs_free (struct loop *loop)
 {
   struct loop_ivs *ivs = LOOP_IVS (loop);
   struct iv_class *iv = ivs->list;
@@ -5029,9 +5075,7 @@ loop_ivs_free (loop)
    must check regnos to make sure they are in bounds.  */
 
 static void
-strength_reduce (loop, flags)
-     struct loop *loop;
-     int flags;
+strength_reduce (struct loop *loop, int flags)
 {
   struct loop_info *loop_info = LOOP_INFO (loop);
   struct loop_regs *regs = LOOP_REGS (loop);
@@ -5055,7 +5099,7 @@ strength_reduce (loop, flags)
   addr_placeholder = gen_reg_rtx (Pmode);
 
   ivs->n_regs = max_reg_before_loop;
-  ivs->regs = (struct iv *) xcalloc (ivs->n_regs, sizeof (struct iv));
+  ivs->regs = xcalloc (ivs->n_regs, sizeof (struct iv));
 
   /* Find all BIVs in loop.  */
   loop_bivs_find (loop);
@@ -5072,7 +5116,7 @@ strength_reduce (loop, flags)
       return;
     }
 
-  /* Determine how BIVS are initialised by looking through pre-header
+  /* Determine how BIVS are initialized by looking through pre-header
      extended basic block.  */
   loop_bivs_init_find (loop);
 
@@ -5109,7 +5153,7 @@ strength_reduce (loop, flags)
      Some givs might have been made from biv increments, so look at
      ivs->reg_iv_type for a suitable size.  */
   reg_map_size = ivs->n_regs;
-  reg_map = (rtx *) xcalloc (reg_map_size, sizeof (rtx));
+  reg_map = xcalloc (reg_map_size, sizeof (rtx));
 
   /* Examine each iv class for feasibility of strength reduction/induction
      variable elimination.  */
@@ -5130,7 +5174,7 @@ strength_reduce (loop, flags)
 
       /* Check each extension dependent giv in this class to see if its
         root biv is safe from wrapping in the interior mode.  */
-      check_ext_dependent_givs (bl, loop_info);
+      check_ext_dependent_givs (loop, bl);
 
       /* Combine all giv's for this iv_class.  */
       combine_givs (regs, bl);
@@ -5273,8 +5317,7 @@ strength_reduce (loop, flags)
      register substitutions scheduled in REG_MAP.  */
 
   for (p = loop->start; p != loop->end; p = NEXT_INSN (p))
-    if (GET_CODE (p) == INSN || GET_CODE (p) == JUMP_INSN
-       || GET_CODE (p) == CALL_INSN)
+    if (INSN_P (p))
       {
        replace_regs (PATTERN (p), reg_map, reg_map_size, 0);
        replace_regs (REG_NOTES (p), reg_map, reg_map_size, 0);
@@ -5313,28 +5356,11 @@ strength_reduce (loop, flags)
      collected.  Always unroll loops that would be as small or smaller
      unrolled than when rolled.  */
   if ((flags & LOOP_UNROLL)
-      || (!(flags & LOOP_FIRST_PASS)
+      || ((flags & LOOP_AUTO_UNROLL)
          && loop_info->n_iterations > 0
          && unrolled_insn_copies <= insn_count))
     unroll_loop (loop, insn_count, 1);
 
-#ifdef HAVE_doloop_end
-  if (HAVE_doloop_end && (flags & LOOP_BCT) && flag_branch_on_count_reg)
-    doloop_optimize (loop);
-#endif  /* HAVE_doloop_end  */
-
-  /* In case number of iterations is known, drop branch prediction note
-     in the branch.  Do that only in second loop pass, as loop unrolling
-     may change the number of iterations performed.  */
-  if (flags & LOOP_BCT)
-    {
-      unsigned HOST_WIDE_INT n
-       = loop_info->n_iterations / loop_info->unroll_number;
-      if (n > 1)
-       predict_insn (PREV_INSN (loop->end), PRED_LOOP_ITERATIONS,
-                     REG_BR_PROB_BASE - REG_BR_PROB_BASE / n);
-    }
-
   if (loop_dump_stream)
     fprintf (loop_dump_stream, "\n");
 
@@ -5345,11 +5371,8 @@ strength_reduce (loop, flags)
 \f
 /*Record all basic induction variables calculated in the insn.  */
 static rtx
-check_insn_for_bivs (loop, p, not_every_iteration, maybe_multiple)
-     struct loop *loop;
-     rtx p;
-     int not_every_iteration;
-     int maybe_multiple;
+check_insn_for_bivs (struct loop *loop, rtx p, int not_every_iteration,
+                    int maybe_multiple)
 {
   struct loop_ivs *ivs = LOOP_IVS (loop);
   rtx set;
@@ -5358,9 +5381,9 @@ check_insn_for_bivs (loop, p, not_every_iteration, maybe_multiple)
   rtx mult_val;
   rtx *location;
 
-  if (GET_CODE (p) == INSN
+  if (NONJUMP_INSN_P (p)
       && (set = single_set (p))
-      && GET_CODE (SET_DEST (set)) == REG)
+      && REG_P (SET_DEST (set)))
     {
       dest_reg = SET_DEST (set);
       if (REGNO (dest_reg) < max_reg_before_loop
@@ -5375,8 +5398,7 @@ check_insn_for_bivs (loop, p, not_every_iteration, maybe_multiple)
              /* It is a possible basic induction variable.
                 Create and initialize an induction structure for it.  */
 
-             struct induction *v
-               = (struct induction *) xmalloc (sizeof (struct induction));
+             struct induction *v = xmalloc (sizeof (struct induction));
 
              record_biv (loop, v, p, dest_reg, inc_val, mult_val, location,
                          not_every_iteration, maybe_multiple);
@@ -5393,19 +5415,16 @@ check_insn_for_bivs (loop, p, not_every_iteration, maybe_multiple)
    A register is a giv if: it is only set once, it is a function of a
    biv and a constant (or invariant), and it is not a biv.  */
 static rtx
-check_insn_for_givs (loop, p, not_every_iteration, maybe_multiple)
-     struct loop *loop;
-     rtx p;
-     int not_every_iteration;
-     int maybe_multiple;
+check_insn_for_givs (struct loop *loop, rtx p, int not_every_iteration,
+                    int maybe_multiple)
 {
   struct loop_regs *regs = LOOP_REGS (loop);
 
   rtx set;
   /* Look for a general induction variable in a register.  */
-  if (GET_CODE (p) == INSN
+  if (NONJUMP_INSN_P (p)
       && (set = single_set (p))
-      && GET_CODE (SET_DEST (set)) == REG
+      && REG_P (SET_DEST (set))
       && ! regs->array[REGNO (SET_DEST (set))].may_not_optimize)
     {
       rtx src_reg;
@@ -5442,8 +5461,7 @@ check_insn_for_givs (loop, p, not_every_iteration, maybe_multiple)
                                             &add_val, &mult_val, &ext_val,
                                             &last_consec_insn))))
        {
-         struct induction *v
-           = (struct induction *) xmalloc (sizeof (struct induction));
+         struct induction *v = xmalloc (sizeof (struct induction));
 
          /* If this is a library call, increase benefit.  */
          if (find_reg_note (p, REG_RETVAL, NULL_RTX))
@@ -5460,19 +5478,14 @@ check_insn_for_givs (loop, p, not_every_iteration, maybe_multiple)
        }
     }
 
-#ifndef DONT_REDUCE_ADDR
   /* Look for givs which are memory addresses.  */
-  /* This resulted in worse code on a VAX 8600.  I wonder if it
-     still does.  */
-  if (GET_CODE (p) == INSN)
+  if (NONJUMP_INSN_P (p))
     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)
+  if (INSN_P (p) || LABEL_P (p))
     update_giv_derive (loop, p);
   return p;
 }
@@ -5486,18 +5499,14 @@ check_insn_for_givs (loop, p, not_every_iteration, maybe_multiple)
    INSN is the insn containing X.  */
 
 static int
-valid_initial_value_p (x, insn, call_seen, loop_start)
-     rtx x;
-     rtx insn;
-     int call_seen;
-     rtx loop_start;
+valid_initial_value_p (rtx x, rtx insn, int call_seen, rtx loop_start)
 {
   if (CONSTANT_P (x))
     return 1;
 
   /* Only consider pseudos we know about initialized in insns whose luids
      we know.  */
-  if (GET_CODE (x) != REG
+  if (!REG_P (x)
       || REGNO (x) >= max_reg_before_loop)
     return 0;
 
@@ -5520,14 +5529,11 @@ valid_initial_value_p (x, insn, call_seen, loop_start)
    as a possible giv.  INSN is the insn whose pattern X comes from.
    NOT_EVERY_ITERATION is 1 if the insn might not be executed during
    every loop iteration.  MAYBE_MULTIPLE is 1 if the insn might be executed
-   more thanonce in each loop iteration.  */
+   more than once in each loop iteration.  */
 
 static void
-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;
+find_mem_givs (const struct loop *loop, rtx x, rtx insn,
+              int not_every_iteration, int maybe_multiple)
 {
   int i, j;
   enum rtx_code code;
@@ -5571,8 +5577,7 @@ find_mem_givs (loop, x, insn, not_every_iteration, maybe_multiple)
                                   GET_MODE (x)))
          {
            /* Found one; record it.  */
-           struct induction *v
-             = (struct induction *) xmalloc (sizeof (struct induction));
+           struct induction *v = xmalloc (sizeof (struct induction));
 
            record_giv (loop, v, insn, src_reg, addr_placeholder, mult_val,
                        add_val, ext_val, benefit, DEST_ADDR,
@@ -5617,17 +5622,9 @@ find_mem_givs (loop, x, insn, not_every_iteration, maybe_multiple)
    executed exactly once per iteration.  */
 
 static void
-record_biv (loop, v, insn, dest_reg, inc_val, mult_val, location,
-           not_every_iteration, maybe_multiple)
-     struct loop *loop;
-     struct induction *v;
-     rtx insn;
-     rtx dest_reg;
-     rtx inc_val;
-     rtx mult_val;
-     rtx *location;
-     int not_every_iteration;
-     int maybe_multiple;
+record_biv (struct loop *loop, struct induction *v, rtx insn, rtx dest_reg,
+           rtx inc_val, rtx mult_val, rtx *location,
+           int not_every_iteration, int maybe_multiple)
 {
   struct loop_ivs *ivs = LOOP_IVS (loop);
   struct iv_class *bl;
@@ -5643,6 +5640,7 @@ record_biv (loop, v, insn, dest_reg, inc_val, mult_val, location,
   v->always_computable = ! not_every_iteration;
   v->always_executed = ! not_every_iteration;
   v->maybe_multiple = maybe_multiple;
+  v->same = 0;
 
   /* Add this to the reg's iv_class, creating a class
      if this is the first incrementation of the reg.  */
@@ -5652,7 +5650,7 @@ record_biv (loop, v, insn, dest_reg, inc_val, mult_val, location,
     {
       /* Create and initialize new iv_class.  */
 
-      bl = (struct iv_class *) xmalloc (sizeof (struct iv_class));
+      bl = xmalloc (sizeof (struct iv_class));
 
       bl->regno = REGNO (dest_reg);
       bl->biv = 0;
@@ -5663,7 +5661,7 @@ record_biv (loop, v, insn, dest_reg, inc_val, mult_val, location,
       /* Set initial value to the reg itself.  */
       bl->initial_value = dest_reg;
       bl->final_value = 0;
-      /* We haven't seen the initializing insn yet */
+      /* We haven't seen the initializing insn yet */
       bl->init_insn = 0;
       bl->init_set = 0;
       bl->initial_test = 0;
@@ -5680,6 +5678,17 @@ record_biv (loop, v, insn, dest_reg, inc_val, mult_val, location,
       /* Put it in the array of biv register classes.  */
       REG_IV_CLASS (ivs, REGNO (dest_reg)) = bl;
     }
+  else
+    {
+      /* Check if location is the same as a previous one.  */
+      struct induction *induction;
+      for (induction = bl->biv; induction; induction = induction->next_iv)
+       if (location == induction->location)
+         {
+           v->same = induction;
+           break;
+         }
+    }
 
   /* Update IV_CLASS entry for this biv.  */
   v->next_iv = bl->biv;
@@ -5706,18 +5715,10 @@ record_biv (loop, 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 (loop, v, insn, src_reg, dest_reg, mult_val, add_val, ext_val,
-           benefit, type, not_every_iteration, maybe_multiple, location)
-     const struct loop *loop;
-     struct induction *v;
-     rtx insn;
-     rtx src_reg;
-     rtx dest_reg;
-     rtx mult_val, add_val, ext_val;
-     int benefit;
-     enum g_types type;
-     int not_every_iteration, maybe_multiple;
-     rtx *location;
+record_giv (const struct loop *loop, struct induction *v, rtx insn,
+           rtx src_reg, rtx dest_reg, rtx mult_val, rtx add_val,
+           rtx ext_val, int benefit, enum g_types type,
+           int not_every_iteration, int maybe_multiple, rtx *location)
 {
   struct loop_ivs *ivs = LOOP_IVS (loop);
   struct induction *b;
@@ -5725,7 +5726,7 @@ record_giv (loop, v, insn, src_reg, dest_reg, mult_val, add_val, ext_val,
   rtx set = single_set (insn);
   rtx temp;
 
-  /* Attempt to prove constantness of the values.  Don't let simplity_rtx
+  /* Attempt to prove constantness of the values.  Don't let simplify_rtx
      undo the MULT canonicalization that we performed earlier.  */
   temp = simplify_rtx (add_val);
   if (temp
@@ -5810,7 +5811,10 @@ record_giv (loop, v, insn, src_reg, dest_reg, mult_val, add_val, ext_val,
     abort ();
 
   if (type == DEST_ADDR)
-    v->replaceable = 1;
+    {
+      v->replaceable = 1;
+      v->not_replaceable = 0;
+    }
   else
     {
       /* The giv can be replaced outright by the reduced register only if all
@@ -5845,6 +5849,7 @@ record_giv (loop, v, insn, src_reg, dest_reg, mult_val, add_val, ext_val,
             using this biv anyways.  */
 
          v->replaceable = 1;
+         v->not_replaceable = 0;
          for (b = bl->biv; b; b = b->next_iv)
            {
              if (INSN_UID (b->insn) >= max_uid_for_loop
@@ -5916,16 +5921,10 @@ record_giv (loop, v, insn, src_reg, dest_reg, mult_val, add_val, ext_val,
    have been identified.  */
 
 static void
-check_final_value (loop, v)
-     const struct loop *loop;
-     struct induction *v;
+check_final_value (const struct loop *loop, struct induction *v)
 {
-  struct loop_ivs *ivs = LOOP_IVS (loop);
-  struct iv_class *bl;
   rtx final_value = 0;
 
-  bl = REG_IV_CLASS (ivs, REGNO (v->src_reg));
-
   /* DEST_ADDR givs will never reach here, because they are always marked
      replaceable above in record_giv.  */
 
@@ -5948,13 +5947,15 @@ check_final_value (loop, v)
 #endif
 
   if ((final_value = final_giv_value (loop, v))
-      && (v->always_computable || last_use_this_basic_block (v->dest_reg, v->insn)))
+      && (v->always_executed
+         || last_use_this_basic_block (v->dest_reg, v->insn)))
     {
       int biv_increment_seen = 0, before_giv_insn = 0;
       rtx p = v->insn;
       rtx last_giv_use;
 
       v->replaceable = 1;
+      v->not_replaceable = 0;
 
       /* When trying to determine whether or not a biv increment occurs
         during the lifetime of the giv, we can ignore uses of the variable
@@ -5987,8 +5988,7 @@ check_final_value (loop, v)
          if (p == v->insn)
            break;
 
-         if (GET_CODE (p) == INSN || GET_CODE (p) == JUMP_INSN
-             || GET_CODE (p) == CALL_INSN)
+         if (INSN_P (p))
            {
              /* It is possible for the BIV increment to use the GIV if we
                 have a cycle.  Thus we must be sure to check each insn for
@@ -6027,7 +6027,7 @@ check_final_value (loop, v)
              if (p == last_giv_use)
                break;
 
-             if (GET_CODE (p) == JUMP_INSN && JUMP_LABEL (p)
+             if (JUMP_P (p) && 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)))
@@ -6068,9 +6068,7 @@ check_final_value (loop, v)
    The cases we look at are when a label or an update to a biv is passed.  */
 
 static void
-update_giv_derive (loop, p)
-     const struct loop *loop;
-     rtx p;
+update_giv_derive (const struct loop *loop, rtx p)
 {
   struct loop_ivs *ivs = LOOP_IVS (loop);
   struct iv_class *bl;
@@ -6107,9 +6105,13 @@ update_giv_derive (loop, p)
 
   for (bl = ivs->list; bl; bl = bl->next)
     for (biv = bl->biv; biv; biv = biv->next_iv)
-      if (GET_CODE (p) == CODE_LABEL || GET_CODE (p) == JUMP_INSN
+      if (LABEL_P (p) || JUMP_P (p)
          || biv->insn == p)
        {
+         /* Skip if location is the same as a previous one.  */
+         if (biv->same)
+           continue;
+
          for (giv = bl->giv; giv; giv = giv->next_iv)
            {
              /* If cant_derive is already true, there is no point in
@@ -6119,7 +6121,7 @@ update_giv_derive (loop, p)
 
              /* If this giv is conditionally set and we have passed a label,
                 it cannot derive anything.  */
-             if (GET_CODE (p) == CODE_LABEL && ! giv->always_computable)
+             if (LABEL_P (p) && ! giv->always_computable)
                giv->cant_derive = 1;
 
              /* Skip givs that have mult_val == 0, since
@@ -6156,8 +6158,8 @@ update_giv_derive (loop, p)
                  else
                    giv->cant_derive = 1;
                }
-             else if ((GET_CODE (p) == CODE_LABEL && ! biv->always_computable)
-                      || (GET_CODE (p) == JUMP_INSN && biv->maybe_multiple))
+             else if ((LABEL_P (p) && ! biv->always_computable)
+                      || (JUMP_P (p) && biv->maybe_multiple))
                giv->cant_derive = 1;
            }
        }
@@ -6180,7 +6182,7 @@ update_giv_derive (loop, p)
    *MULT_VAL to CONST0_RTX, and store the invariant into *INC_VAL.
 
    We also want to detect a BIV when it corresponds to a variable
-   whose mode was promoted via PROMOTED_MODE.  In that case, an increment
+   whose mode was promoted.  In that case, an increment
    of the variable may be a PLUS that adds a SUBREG of that variable to
    an invariant and then sign- or zero-extends the result of the PLUS
    into the variable.
@@ -6201,19 +6203,13 @@ update_giv_derive (loop, p)
    If we cannot find a biv, we return 0.  */
 
 static int
-basic_induction_var (loop, x, mode, dest_reg, p, inc_val, mult_val, location)
-     const struct loop *loop;
-     rtx x;
-     enum machine_mode mode;
-     rtx dest_reg;
-     rtx p;
-     rtx *inc_val;
-     rtx *mult_val;
-     rtx **location;
+basic_induction_var (const struct loop *loop, rtx x, enum machine_mode mode,
+                    rtx dest_reg, rtx p, rtx *inc_val, rtx *mult_val,
+                    rtx **location)
 {
   enum rtx_code code;
   rtx *argp, arg;
-  rtx insn, set = 0;
+  rtx insn, set = 0, last, inc;
 
   code = GET_CODE (x);
   *location = NULL;
@@ -6241,7 +6237,26 @@ basic_induction_var (loop, x, mode, dest_reg, p, inc_val, mult_val, location)
       if (loop_invariant_p (loop, arg) != 1)
        return 0;
 
-      *inc_val = convert_modes (GET_MODE (dest_reg), GET_MODE (x), arg, 0);
+      /* convert_modes can emit new instructions, e.g. when arg is a loop
+        invariant MEM and dest_reg has a different mode.
+        These instructions would be emitted after the end of the function
+        and then *inc_val would be an uninitialized pseudo.
+        Detect this and bail in this case.
+        Other alternatives to solve this can be introducing a convert_modes
+        variant which is allowed to fail but not allowed to emit new
+        instructions, emit these instructions before loop start and let
+        it be garbage collected if *inc_val is never used or saving the
+        *inc_val initialization sequence generated here and when *inc_val
+        is going to be actually used, emit it at some suitable place.  */
+      last = get_last_insn ();
+      inc = convert_modes (GET_MODE (dest_reg), GET_MODE (x), arg, 0);
+      if (get_last_insn () != last)
+       {
+         delete_insns_since (last);
+         return 0;
+       }
+
+      *inc_val = inc;
       *mult_val = const1_rtx;
       *location = argp;
       return 1;
@@ -6272,7 +6287,7 @@ basic_induction_var (loop, x, mode, dest_reg, p, inc_val, mult_val, location)
            {
              insn = PREV_INSN (insn);
            }
-         while (insn && GET_CODE (insn) == NOTE
+         while (insn && NOTE_P (insn)
                 && NOTE_LINE_NUMBER (insn) != NOTE_INSN_LOOP_BEG);
 
          if (!insn)
@@ -6322,7 +6337,15 @@ basic_induction_var (loop, x, mode, dest_reg, p, inc_val, mult_val, location)
          && GET_MODE_CLASS (mode) != MODE_CC)
        {
          /* Possible bug here?  Perhaps we don't know the mode of X.  */
-         *inc_val = convert_modes (GET_MODE (dest_reg), mode, x, 0);
+         last = get_last_insn ();
+         inc = convert_modes (GET_MODE (dest_reg), mode, x, 0);
+         if (get_last_insn () != last)
+           {
+             delete_insns_since (last);
+             return 0;
+           }
+
+         *inc_val = inc;
          *mult_val = const0_rtx;
          return 1;
        }
@@ -6330,13 +6353,16 @@ basic_induction_var (loop, x, mode, dest_reg, p, inc_val, mult_val, location)
        return 0;
 
     case SIGN_EXTEND:
+      /* Ignore this BIV if signed arithmetic overflow is defined.  */
+      if (flag_wrapv)
+       return 0;
       return basic_induction_var (loop, XEXP (x, 0), GET_MODE (XEXP (x, 0)),
                                  dest_reg, p, inc_val, mult_val, location);
 
     case ASHIFTRT:
       /* Similar, since this can be a sign extension.  */
       for (insn = PREV_INSN (p);
-          (insn && GET_CODE (insn) == NOTE
+          (insn && NOTE_P (insn)
            && NOTE_LINE_NUMBER (insn) != NOTE_INSN_LOOP_BEG);
           insn = PREV_INSN (insn))
        ;
@@ -6376,17 +6402,10 @@ basic_induction_var (loop, x, mode, dest_reg, p, inc_val, mult_val, location)
      such that the value of X is biv * mult + add;  */
 
 static int
-general_induction_var (loop, x, src_reg, add_val, mult_val, ext_val,
-                      is_addr, pbenefit, addr_mode)
-     const struct loop *loop;
-     rtx x;
-     rtx *src_reg;
-     rtx *add_val;
-     rtx *mult_val;
-     rtx *ext_val;
-     int is_addr;
-     int *pbenefit;
-     enum machine_mode addr_mode;
+general_induction_var (const struct loop *loop, rtx x, rtx *src_reg,
+                      rtx *add_val, rtx *mult_val, rtx *ext_val,
+                      int is_addr, int *pbenefit,
+                      enum machine_mode addr_mode)
 {
   struct loop_ivs *ivs = LOOP_IVS (loop);
   rtx orig_x = x;
@@ -6480,20 +6499,16 @@ general_induction_var (loop, x, src_reg, add_val, mult_val, ext_val,
    expression that is neither invariant nor a biv or giv), this routine
    returns 0.
 
-   For a non-zero return, the result will have a code of CONST_INT, USE,
+   For a nonzero return, the result will have a code of CONST_INT, USE,
    REG (for a BIV), PLUS, or MULT.  No other codes will occur.
 
    *BENEFIT will be incremented by the benefit of any sub-giv encountered.  */
 
-static rtx sge_plus PARAMS ((enum machine_mode, rtx, rtx));
-static rtx sge_plus_constant PARAMS ((rtx, rtx));
+static rtx sge_plus (enum machine_mode, rtx, rtx);
+static rtx sge_plus_constant (rtx, rtx);
 
 static rtx
-simplify_giv_expr (loop, x, ext_val, benefit)
-     const struct loop *loop;
-     rtx x;
-     rtx *ext_val;
-     int *benefit;
+simplify_giv_expr (const struct loop *loop, rtx x, rtx *ext_val, int *benefit)
 {
   struct loop_ivs *ivs = LOOP_IVS (loop);
   struct loop_regs *regs = LOOP_REGS (loop);
@@ -6572,9 +6587,9 @@ simplify_giv_expr (loop, x, ext_val, benefit)
 
       /* Each argument must be either REG, PLUS, or MULT.  Convert REG to
         MULT to reduce cases.  */
-      if (GET_CODE (arg0) == REG)
+      if (REG_P (arg0))
        arg0 = gen_rtx_MULT (mode, arg0, const1_rtx);
-      if (GET_CODE (arg1) == REG)
+      if (REG_P (arg1))
        arg1 = gen_rtx_MULT (mode, arg1, const1_rtx);
 
       /* Now have PLUS + PLUS, PLUS + MULT, MULT + PLUS, or MULT + MULT.
@@ -6667,7 +6682,7 @@ simplify_giv_expr (loop, x, ext_val, benefit)
                                                                    arg1)),
                                        ext_val, benefit);
            }
-         /* Porpagate the MULT expressions to the intermost nodes.  */
+         /* Propagate the MULT expressions to the innermost nodes.  */
          else if (GET_CODE (arg0) == PLUS)
            {
              /* (invar_0 + invar_1) * invar_2.  Distribute.  */
@@ -6751,7 +6766,7 @@ simplify_giv_expr (loop, x, ext_val, benefit)
       if (*ext_val == NULL_RTX)
        {
          arg0 = simplify_giv_expr (loop, XEXP (x, 0), ext_val, benefit);
-         if (arg0 && *ext_val == NULL_RTX && GET_CODE (arg0) == REG)
+         if (arg0 && *ext_val == NULL_RTX && REG_P (arg0))
            {
              *ext_val = gen_rtx_fmt_e (GET_CODE (x), mode, arg0);
              return arg0;
@@ -6833,7 +6848,7 @@ simplify_giv_expr (loop, x, ext_val, benefit)
                      return simplify_giv_expr (loop, m->match->set_dest,
                                                ext_val, benefit);
 
-                   /* If consec is non-zero, this is a member of a group of
+                   /* If consec is nonzero, this is a member of a group of
                       instructions that were moved together.  We handle this
                       case only to the point of seeking to the last insn and
                       looking for a REG_EQUAL.  Fail if we don't find one.  */
@@ -6918,8 +6933,7 @@ simplify_giv_expr (loop, x, ext_val, benefit)
    CONST_INT in the summation.  It is only used by simplify_giv_expr.  */
 
 static rtx
-sge_plus_constant (x, c)
-     rtx x, c;
+sge_plus_constant (rtx x, rtx c)
 {
   if (GET_CODE (x) == CONST_INT)
     return GEN_INT (INTVAL (x) + INTVAL (c));
@@ -6944,9 +6958,7 @@ sge_plus_constant (x, c)
 }
 
 static rtx
-sge_plus (mode, x, y)
-     enum machine_mode mode;
-     rtx x, y;
+sge_plus (enum machine_mode mode, rtx x, rtx y)
 {
   while (GET_CODE (y) == PLUS)
     {
@@ -6984,17 +6996,9 @@ sge_plus (mode, x, y)
    *MULT_VAL and *ADD_VAL.  */
 
 static int
-consec_sets_giv (loop, first_benefit, p, src_reg, dest_reg,
-                add_val, mult_val, ext_val, last_consec_insn)
-     const struct loop *loop;
-     int first_benefit;
-     rtx p;
-     rtx src_reg;
-     rtx dest_reg;
-     rtx *add_val;
-     rtx *mult_val;
-     rtx *ext_val;
-     rtx *last_consec_insn;
+consec_sets_giv (const struct loop *loop, int first_benefit, rtx p,
+                rtx src_reg, rtx dest_reg, rtx *add_val, rtx *mult_val,
+                rtx *ext_val, rtx *last_consec_insn)
 {
   struct loop_ivs *ivs = LOOP_IVS (loop);
   struct loop_regs *regs = LOOP_REGS (loop);
@@ -7016,7 +7020,7 @@ consec_sets_giv (loop, first_benefit, p, src_reg, dest_reg,
   if (REG_IV_TYPE (ivs, REGNO (dest_reg)) != UNKNOWN_INDUCT)
     return 0;
 
-  v = (struct induction *) alloca (sizeof (struct induction));
+  v = alloca (sizeof (struct induction));
   v->src_reg = src_reg;
   v->mult_val = *mult_val;
   v->add_val = *add_val;
@@ -7041,7 +7045,7 @@ consec_sets_giv (loop, first_benefit, p, src_reg, dest_reg,
 
       if (code == INSN
          && (set = single_set (p))
-         && GET_CODE (SET_DEST (set)) == REG
+         && REG_P (SET_DEST (set))
          && SET_DEST (set) == dest_reg
          && (general_induction_var (loop, SET_SRC (set), &src_reg,
                                     add_val, mult_val, ext_val, 0,
@@ -7100,8 +7104,7 @@ consec_sets_giv (loop, first_benefit, p, src_reg, dest_reg,
    subtracting variables.  */
 
 static rtx
-express_from_1 (a, b, mult)
-     rtx a, b, mult;
+express_from_1 (rtx a, rtx b, rtx mult)
 {
   /* If MULT is zero, then A*MULT is zero, and our expression is B.  */
 
@@ -7199,8 +7202,7 @@ express_from_1 (a, b, mult)
 }
 
 rtx
-express_from (g1, g2)
-     struct induction *g1, *g2;
+express_from (struct induction *g1, struct induction *g2)
 {
   rtx mult, add;
 
@@ -7211,6 +7213,9 @@ express_from (g1, g2)
       && GET_CODE (g2->mult_val) == CONST_INT)
     {
       if (g1->mult_val == const0_rtx
+         || (g1->mult_val == constm1_rtx
+             && INTVAL (g2->mult_val)
+                == (HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT - 1))
          || INTVAL (g2->mult_val) % INTVAL (g1->mult_val) != 0)
        return NULL_RTX;
       mult = GEN_INT (INTVAL (g2->mult_val) / INTVAL (g1->mult_val));
@@ -7281,8 +7286,7 @@ express_from (g1, g2)
    used to represent G1.  */
 
 static rtx
-combine_givs_p (g1, g2)
-     struct induction *g1, *g2;
+combine_givs_p (struct induction *g1, struct induction *g2)
 {
   rtx comb, ret;
 
@@ -7313,21 +7317,8 @@ combine_givs_p (g1, g2)
      the expression of G2 in terms of G1 can be used.  */
   if (ret != NULL_RTX
       && g2->giv_type == DEST_ADDR
-      && memory_address_p (GET_MODE (g2->mem), ret)
-      /* ??? Looses, especially with -fforce-addr, where *g2->location
-        will always be a register, and so anything more complicated
-        gets discarded.  */
-#if 0
-#ifdef ADDRESS_COST
-      && ADDRESS_COST (tem) <= ADDRESS_COST (*g2->location)
-#else
-      && rtx_cost (tem, MEM) <= rtx_cost (*g2->location, MEM)
-#endif
-#endif
-      )
-    {
-      return ret;
-    }
+      && memory_address_p (GET_MODE (g2->mem), ret))
+    return ret;
 
   return NULL_RTX;
 }
@@ -7337,10 +7328,9 @@ combine_givs_p (g1, g2)
    make the giv illegal.  */
 
 static void
-check_ext_dependent_givs (bl, loop_info)
-     struct iv_class *bl;
-     struct loop_info *loop_info;
+check_ext_dependent_givs (const struct loop *loop, struct iv_class *bl)
 {
+  struct loop_info *loop_info = LOOP_INFO (loop);
   int ze_ok = 0, se_ok = 0, info_ok = 0;
   enum machine_mode biv_mode = GET_MODE (bl->biv->src_reg);
   HOST_WIDE_INT start_val;
@@ -7351,9 +7341,6 @@ check_ext_dependent_givs (bl, loop_info)
 
   /* Make sure the iteration data is available.  We must have
      constants in order to be certain of no overflow.  */
-  /* ??? An unknown iteration count with an increment of +-1
-     combined with friendly exit tests of against an invariant
-     value is also ameanable to optimization.  Not implemented.  */
   if (loop_info->n_iterations > 0
       && bl->initial_value
       && GET_CODE (bl->initial_value) == CONST_INT
@@ -7375,7 +7362,7 @@ check_ext_dependent_givs (bl, loop_info)
        neg_incr = 1, abs_incr = -abs_incr;
       total_incr = abs_incr * loop_info->n_iterations;
 
-      /* Check for host arithmatic overflow.  */
+      /* Check for host arithmetic overflow.  */
       if (total_incr / loop_info->n_iterations == abs_incr)
        {
          unsigned HOST_WIDE_INT u_max;
@@ -7388,7 +7375,7 @@ check_ext_dependent_givs (bl, loop_info)
 
          /* Check zero extension of biv ok.  */
          if (start_val >= 0
-             /* Check for host arithmatic overflow.  */
+             /* Check for host arithmetic overflow.  */
              && (neg_incr
                  ? u_end_val < u_start_val
                  : u_end_val > u_start_val)
@@ -7406,7 +7393,7 @@ check_ext_dependent_givs (bl, loop_info)
             keep this fact in mind -- myself included on occasion.
             So leave alone with the signed overflow optimizations.  */
          if (start_val >= -s_max - 1
-             /* Check for host arithmatic overflow.  */
+             /* Check for host arithmetic overflow.  */
              && (neg_incr
                  ? s_end_val < start_val
                  : s_end_val > start_val)
@@ -7420,6 +7407,37 @@ check_ext_dependent_givs (bl, loop_info)
        }
     }
 
+  /* If we know the BIV is compared at run-time against an 
+     invariant value, and the increment is +/- 1, we may also 
+     be able to prove that the BIV cannot overflow.  */
+  else if (bl->biv->src_reg == loop_info->iteration_var
+           && loop_info->comparison_value
+           && loop_invariant_p (loop, loop_info->comparison_value)
+           && (incr = biv_total_increment (bl))
+           && GET_CODE (incr) == CONST_INT)
+    {
+      /* If the increment is +1, and the exit test is a <,
+         the BIV cannot overflow.  (For <=, we have the 
+         problematic case that the comparison value might
+         be the maximum value of the range.)  */
+       if (INTVAL (incr) == 1)
+         {
+           if (loop_info->comparison_code == LT)
+             se_ok = ze_ok = 1;
+           else if (loop_info->comparison_code == LTU)
+             ze_ok = 1;
+         }
+
+       /* Likewise for increment -1 and exit test >.  */
+       if (INTVAL (incr) == -1)
+         {
+           if (loop_info->comparison_code == GT)
+             se_ok = ze_ok = 1;
+           else if (loop_info->comparison_code == GTU)
+             ze_ok = 1;
+         }
+    }
+
   /* Invalidate givs that fail the tests.  */
   for (v = bl->giv; v; v = v->next_iv)
     if (v->ext_dependent)
@@ -7441,8 +7459,9 @@ check_ext_dependent_givs (bl, loop_info)
               signed or unsigned, so to safely truncate we must satisfy
               both.  The initial check here verifies the BIV itself;
               once that is successful we may check its range wrt the
-              derived GIV.  */
-           if (se_ok && ze_ok)
+              derived GIV.  This works only if we were able to determine
+              constant start and end values above.  */
+           if (se_ok && ze_ok && info_ok)
              {
                enum machine_mode outer_mode = GET_MODE (v->ext_dependent);
                unsigned HOST_WIDE_INT max = GET_MODE_MASK (outer_mode) >> 1;
@@ -7499,9 +7518,7 @@ check_ext_dependent_givs (bl, loop_info)
 /* Generate a version of VALUE in a mode appropriate for initializing V.  */
 
 rtx
-extend_value_for_giv (v, value)
-     struct induction *v;
-     rtx value;
+extend_value_for_giv (struct induction *v, rtx value)
 {
   rtx ext_dep = v->ext_dependent;
 
@@ -7526,9 +7543,7 @@ struct combine_givs_stats
 };
 
 static int
-cmp_combine_givs_stats (xp, yp)
-     const PTR xp;
-     const PTR yp;
+cmp_combine_givs_stats (const void *xp, const void *yp)
 {
   const struct combine_givs_stats * const x =
     (const struct combine_givs_stats *) xp;
@@ -7548,9 +7563,7 @@ cmp_combine_givs_stats (xp, yp)
    giv.  Also, update BENEFIT and related fields for cost/benefit analysis.  */
 
 static void
-combine_givs (regs, bl)
-     struct loop_regs *regs;
-     struct iv_class *bl;
+combine_givs (struct loop_regs *regs, struct iv_class *bl)
 {
   /* Additional benefit to add for being combined multiple times.  */
   const int extra_benefit = 3;
@@ -7566,15 +7579,14 @@ combine_givs (regs, bl)
     if (!g1->ignore)
       giv_count++;
 
-  giv_array
-    = (struct induction **) alloca (giv_count * sizeof (struct induction *));
+  giv_array = alloca (giv_count * sizeof (struct induction *));
   i = 0;
   for (g1 = bl->giv; g1; g1 = g1->next_iv)
     if (!g1->ignore)
       giv_array[i++] = g1;
 
-  stats = (struct combine_givs_stats *) xcalloc (giv_count, sizeof (*stats));
-  can_combine = (rtx *) xcalloc (giv_count, giv_count * sizeof (rtx));
+  stats = xcalloc (giv_count, sizeof (*stats));
+  can_combine = xcalloc (giv_count, giv_count * sizeof (rtx));
 
   for (i = 0; i < giv_count; i++)
     {
@@ -7718,14 +7730,12 @@ restart:
   free (can_combine);
 }
 \f
-/* Generate sequence for REG = B * M + A.  */
+/* Generate sequence for REG = B * M + A.  B is the initial value of
+   the basic induction variable, M a multiplicative constant, A an
+   additive constant and REG the destination register.  */
 
 static rtx
-gen_add_mult (b, m, a, reg)
-     rtx b;          /* initial value of basic induction variable */
-     rtx m;          /* multiplicative constant */
-     rtx a;          /* additive constant */
-     rtx reg;        /* destination register */
+gen_add_mult (rtx b,  rtx m, rtx a, rtx reg)
 {
   rtx seq;
   rtx result;
@@ -7735,7 +7745,7 @@ gen_add_mult (b, m, a, reg)
   result = expand_mult_add (b, reg, m, a, GET_MODE (reg), 1);
   if (reg != result)
     emit_move_insn (reg, result);
-  seq = gen_sequence ();
+  seq = get_insns ();
   end_sequence ();
 
   return seq;
@@ -7745,42 +7755,33 @@ gen_add_mult (b, m, a, reg)
 /* Update registers created in insn sequence SEQ.  */
 
 static void
-loop_regs_update (loop, seq)
-     const struct loop *loop ATTRIBUTE_UNUSED;
-     rtx seq;
+loop_regs_update (const struct loop *loop ATTRIBUTE_UNUSED, rtx seq)
 {
+  rtx insn;
+
   /* Update register info for alias analysis.  */
 
-  if (GET_CODE (seq) == SEQUENCE)
-    {
-      int i;
-      for (i = 0; i < XVECLEN (seq, 0); ++i)
-       {
-         rtx set = single_set (XVECEXP (seq, 0, i));
-         if (set && GET_CODE (SET_DEST (set)) == REG)
-           record_base_value (REGNO (SET_DEST (set)), SET_SRC (set), 0);
-       }
-    }
-  else
+  insn = seq;
+  while (insn != NULL_RTX)
     {
-      if (GET_CODE (seq) == SET
-         && GET_CODE (SET_DEST (seq)) == REG)
-       record_base_value (REGNO (SET_DEST (seq)), SET_SRC (seq), 0);
+      rtx set = single_set (insn);
+
+      if (set && REG_P (SET_DEST (set)))
+       record_base_value (REGNO (SET_DEST (set)), SET_SRC (set), 0);
+
+      insn = NEXT_INSN (insn);
     }
 }
 
 
-/* EMIT code before BEFORE_BB/BEFORE_INSN to set REG = B * M + A.  */
+/* EMIT code before BEFORE_BB/BEFORE_INSN to set REG = B * M + A.  B
+   is the initial value of the basic induction variable, M a
+   multiplicative constant, A an additive constant and REG the
+   destination register.  */
 
 void
-loop_iv_add_mult_emit_before (loop, b, m, a, reg, before_bb, before_insn)
-     const struct loop *loop;
-     rtx b;          /* initial value of basic induction variable */
-     rtx m;          /* multiplicative constant */
-     rtx a;          /* additive constant */
-     rtx reg;        /* destination register */
-     basic_block before_bb;
-     rtx before_insn;
+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)
 {
   rtx seq;
 
@@ -7798,23 +7799,22 @@ loop_iv_add_mult_emit_before (loop, b, m, a, reg, before_bb, before_insn)
   update_reg_last_use (b, before_insn);
   update_reg_last_use (m, before_insn);
 
-  loop_insn_emit_before (loop, before_bb, before_insn, seq);
-
   /* It is possible that the expansion created lots of new registers.
-     Iterate over the sequence we just created and record them all.  */
+     Iterate over the sequence we just created and record them all.  We
+     must do this before inserting the sequence.  */
   loop_regs_update (loop, seq);
+
+  loop_insn_emit_before (loop, before_bb, before_insn, seq);
 }
 
 
-/* Emit insns in loop pre-header to set REG = B * M + A.  */
+/* Emit insns in loop pre-header to set REG = B * M + A.  B is the
+   initial value of the basic induction variable, M a multiplicative
+   constant, A an additive constant and REG the destination
+   register.  */
 
 void
-loop_iv_add_mult_sink (loop, b, m, a, reg)
-     const struct loop *loop;
-     rtx b;          /* initial value of basic induction variable */
-     rtx m;          /* multiplicative constant */
-     rtx a;          /* additive constant */
-     rtx reg;        /* destination register */
+loop_iv_add_mult_sink (const struct loop *loop, rtx b, rtx m, rtx a, rtx reg)
 {
   rtx seq;
 
@@ -7827,34 +7827,33 @@ loop_iv_add_mult_sink (loop, b, m, a, reg)
   update_reg_last_use (b, loop->sink);
   update_reg_last_use (m, loop->sink);
 
-  loop_insn_sink (loop, seq);
-
   /* It is possible that the expansion created lots of new registers.
-     Iterate over the sequence we just created and record them all.  */
+     Iterate over the sequence we just created and record them all.  We
+     must do this before inserting the sequence.  */
   loop_regs_update (loop, seq);
+
+  loop_insn_sink (loop, seq);
 }
 
 
-/* Emit insns after loop to set REG = B * M + A.  */
+/* Emit insns after loop to set REG = B * M + A.  B is the initial
+   value of the basic induction variable, M a multiplicative constant,
+   A an additive constant and REG the destination register.  */
 
 void
-loop_iv_add_mult_hoist (loop, b, m, a, reg)
-     const struct loop *loop;
-     rtx b;          /* initial value of basic induction variable */
-     rtx m;          /* multiplicative constant */
-     rtx a;          /* additive constant */
-     rtx reg;        /* destination register */
+loop_iv_add_mult_hoist (const struct loop *loop, rtx b, rtx m, rtx a, rtx reg)
 {
   rtx seq;
 
   /* Use copy_rtx to prevent unexpected sharing of these rtx.  */
   seq = gen_add_mult (copy_rtx (b), copy_rtx (m), copy_rtx (a), reg);
 
-  loop_insn_hoist (loop, seq);
-
   /* It is possible that the expansion created lots of new registers.
-     Iterate over the sequence we just created and record them all.  */
+     Iterate over the sequence we just created and record them all.  We
+     must do this before inserting the sequence.  */
   loop_regs_update (loop, seq);
+
+  loop_insn_hoist (loop, seq);
 }
 
 
@@ -7863,11 +7862,7 @@ loop_iv_add_mult_hoist (loop, b, m, a, reg)
    sequence.  */
 
 static int
-iv_add_mult_cost (b, m, a, reg)
-     rtx b;          /* initial value of basic induction variable */
-     rtx m;          /* multiplicative constant */
-     rtx a;          /* additive constant */
-     rtx reg;        /* destination register */
+iv_add_mult_cost (rtx b, rtx m, rtx a, rtx reg)
 {
   int cost = 0;
   rtx last, result;
@@ -7889,16 +7884,18 @@ iv_add_mult_cost (b, m, a, reg)
 }
 \f
 /* Test whether A * B can be computed without
-   an actual multiply insn.  Value is 1 if so.  */
+   an actual multiply insn.  Value is 1 if so.
+
+  ??? This function stinks because it generates a ton of wasted RTL
+  ??? and as a result fragments GC memory to no end.  There are other
+  ??? places in the compiler which are invoked a lot and do the same
+  ??? thing, generate wasted RTL just to see if something is possible.  */
 
 static int
-product_cheap_p (a, b)
-     rtx a;
-     rtx b;
+product_cheap_p (rtx a, rtx b)
 {
-  int i;
   rtx tmp;
-  int win = 1;
+  int win, n_insns;
 
   /* If only one is constant, make it B.  */
   if (GET_CODE (a) == CONST_INT)
@@ -7918,31 +7915,31 @@ product_cheap_p (a, b)
 
   start_sequence ();
   expand_mult (GET_MODE (a), a, b, NULL_RTX, 1);
-  tmp = gen_sequence ();
+  tmp = get_insns ();
   end_sequence ();
 
-  if (GET_CODE (tmp) == SEQUENCE)
+  win = 1;
+  if (INSN_P (tmp))
     {
-      if (XVEC (tmp, 0) == 0)
-       win = 1;
-      else if (XVECLEN (tmp, 0) > 3)
-       win = 0;
-      else
-       for (i = 0; i < XVECLEN (tmp, 0); i++)
-         {
-           rtx insn = XVECEXP (tmp, 0, i);
-
-           if (GET_CODE (insn) != INSN
-               || (GET_CODE (PATTERN (insn)) == SET
-                   && GET_CODE (SET_SRC (PATTERN (insn))) == MULT)
-               || (GET_CODE (PATTERN (insn)) == PARALLEL
-                   && GET_CODE (XVECEXP (PATTERN (insn), 0, 0)) == SET
-                   && GET_CODE (SET_SRC (XVECEXP (PATTERN (insn), 0, 0))) == MULT))
-             {
-               win = 0;
-               break;
-             }
-         }
+      n_insns = 0;
+      while (tmp != NULL_RTX)
+       {
+         rtx next = NEXT_INSN (tmp);
+
+         if (++n_insns > 3
+             || !NONJUMP_INSN_P (tmp)
+             || (GET_CODE (PATTERN (tmp)) == SET
+                 && GET_CODE (SET_SRC (PATTERN (tmp))) == MULT)
+             || (GET_CODE (PATTERN (tmp)) == PARALLEL
+                 && GET_CODE (XVECEXP (PATTERN (tmp), 0, 0)) == SET
+                 && GET_CODE (SET_SRC (XVECEXP (PATTERN (tmp), 0, 0))) == MULT))
+           {
+             win = 0;
+             break;
+           }
+
+         tmp = next;
+       }
     }
   else if (GET_CODE (tmp) == SET
           && GET_CODE (SET_SRC (tmp)) == MULT)
@@ -7971,15 +7968,14 @@ product_cheap_p (a, b)
    final_[bg]iv_value.  */
 
 static int
-check_dbra_loop (loop, insn_count)
-     struct loop *loop;
-     int insn_count;
+check_dbra_loop (struct loop *loop, int insn_count)
 {
   struct loop_info *loop_info = LOOP_INFO (loop);
   struct loop_regs *regs = LOOP_REGS (loop);
   struct loop_ivs *ivs = LOOP_IVS (loop);
   struct iv_class *bl;
   rtx reg;
+  enum machine_mode mode;
   rtx jump_label;
   rtx final_value;
   rtx start_value;
@@ -8005,7 +8001,7 @@ check_dbra_loop (loop, insn_count)
 
   /* Try to compute whether the compare/branch at the loop end is one or
      two instructions.  */
-  get_condition (jump, &first_compare);
+  get_condition (jump, &first_compare, false);
   if (first_compare == jump)
     compare_and_branch = 1;
   else if (first_compare == prev_nonnote_insn (jump))
@@ -8023,7 +8019,7 @@ check_dbra_loop (loop, insn_count)
 
     rtx jump1;
     if ((jump1 = prev_nonnote_insn (first_compare)) != loop->cont)
-      if (GET_CODE (jump1) == JUMP_INSN)
+      if (JUMP_P (jump1))
        return 0;
   }
 
@@ -8042,6 +8038,22 @@ check_dbra_loop (loop, insn_count)
        break;
     }
 
+  /* Try swapping the comparison to identify a suitable biv.  */
+  if (!bl)
+    for (bl = ivs->list; bl; bl = bl->next)
+      if (bl->biv_count == 1
+         && ! bl->biv->maybe_multiple
+         && bl->biv->dest_reg == XEXP (comparison, 1)
+         && ! reg_used_between_p (regno_reg_rtx[bl->regno], bl->biv->insn,
+                                  first_compare))
+       {
+         comparison = gen_rtx_fmt_ee (swap_condition (GET_CODE (comparison)),
+                                      VOIDmode,
+                                      XEXP (comparison, 1),
+                                      XEXP (comparison, 0));
+         break;
+       }
+
   if (! bl)
     return 0;
 
@@ -8050,9 +8062,7 @@ check_dbra_loop (loop, insn_count)
      In this case, add a reg_note REG_NONNEG, which allows the
      m68k DBRA instruction to be used.  */
 
-  if (((GET_CODE (comparison) == GT
-       && GET_CODE (XEXP (comparison, 1)) == CONST_INT
-       && INTVAL (XEXP (comparison, 1)) == -1)
+  if (((GET_CODE (comparison) == GT && XEXP (comparison, 1) == constm1_rtx)
        || (GET_CODE (comparison) == NE && XEXP (comparison, 1) == const0_rtx))
       && GET_CODE (bl->biv->add_val) == CONST_INT
       && INTVAL (bl->biv->add_val) < 0)
@@ -8066,7 +8076,7 @@ check_dbra_loop (loop, insn_count)
          && (INTVAL (bl->initial_value)
              % (-INTVAL (bl->biv->add_val))) == 0)
        {
-         /* register always nonnegative, add REG_NOTE to branch */
+         /* Register always nonnegative, add REG_NOTE to branch.  */
          if (! find_reg_note (jump, REG_NONNEG, NULL_RTX))
            REG_NOTES (jump)
              = gen_rtx_EXPR_LIST (REG_NONNEG, bl->biv->dest_reg,
@@ -8080,15 +8090,16 @@ check_dbra_loop (loop, insn_count)
         the loop, then we can safely optimize.  */
       for (p = loop_start; p; p = PREV_INSN (p))
        {
-         if (GET_CODE (p) == CODE_LABEL)
+         if (LABEL_P (p))
            break;
-         if (GET_CODE (p) != JUMP_INSN)
+         if (!JUMP_P (p))
            continue;
 
          before_comparison = get_condition_for_loop (loop, p);
          if (before_comparison
              && XEXP (before_comparison, 0) == bl->biv->dest_reg
-             && GET_CODE (before_comparison) == LT
+             && (GET_CODE (before_comparison) == LT
+                 || GET_CODE (before_comparison) == LTU)
              && XEXP (before_comparison, 1) == const0_rtx
              && ! reg_set_between_p (bl->biv->dest_reg, p, loop_start)
              && INTVAL (bl->biv->add_val) == -1)
@@ -8140,13 +8151,15 @@ check_dbra_loop (loop, insn_count)
              {
                rtx set = single_set (p);
 
-               if (set && GET_CODE (SET_DEST (set)) == REG
+               if (set && REG_P (SET_DEST (set))
                    && REGNO (SET_DEST (set)) == bl->regno)
                  /* An insn that sets the biv is okay.  */
                  ;
-               else if ((p == prev_nonnote_insn (prev_nonnote_insn (loop_end))
-                         || p == prev_nonnote_insn (loop_end))
-                        && reg_mentioned_p (bivreg, PATTERN (p)))
+               else if (!reg_mentioned_p (bivreg, PATTERN (p)))
+                 /* An insn that doesn't mention the biv is okay.  */
+                 ;
+               else if (p == prev_nonnote_insn (prev_nonnote_insn (loop_end))
+                        || p == prev_nonnote_insn (loop_end))
                  {
                    /* If either of these insns uses the biv and sets a pseudo
                       that has more than one usage, then the biv has uses
@@ -8160,7 +8173,7 @@ check_dbra_loop (loop, insn_count)
                        break;
                      }
                  }
-               else if (reg_mentioned_p (bivreg, PATTERN (p)))
+               else
                  {
                    no_use_except_counting = 0;
                    break;
@@ -8257,7 +8270,8 @@ check_dbra_loop (loop, insn_count)
              /* for constants, LE gets turned into LT */
              && (GET_CODE (comparison) == LT
                  || (GET_CODE (comparison) == LE
-                     && no_use_except_counting)))
+                     && no_use_except_counting) 
+                 || GET_CODE (comparison) == LTU))
            {
              HOST_WIDE_INT add_val, add_adjust, comparison_val = 0;
              rtx initial_value, comparison_value;
@@ -8265,6 +8279,7 @@ check_dbra_loop (loop, insn_count)
              enum rtx_code cmp_code;
              int comparison_const_width;
              unsigned HOST_WIDE_INT comparison_sign_mask;
+             bool keep_first_compare;
 
              add_val = INTVAL (bl->biv->add_val);
              comparison_value = XEXP (comparison, 1);
@@ -8382,6 +8397,7 @@ check_dbra_loop (loop, insn_count)
 
              /* Save some info needed to produce the new insns.  */
              reg = bl->biv->dest_reg;
+             mode = GET_MODE (reg);
              jump_label = condjump_label (PREV_INSN (loop_end));
              new_add_val = GEN_INT (-INTVAL (bl->biv->add_val));
 
@@ -8393,12 +8409,12 @@ check_dbra_loop (loop, insn_count)
              if (initial_value == const0_rtx
                  && GET_CODE (comparison_value) == CONST_INT)
                {
-                 start_value = GEN_INT (comparison_val - add_adjust);
+                 start_value
+                   = gen_int_mode (comparison_val - add_adjust, mode);
                  loop_insn_hoist (loop, gen_move_insn (reg, start_value));
                }
              else if (GET_CODE (initial_value) == CONST_INT)
                {
-                 enum machine_mode mode = GET_MODE (reg);
                  rtx offset = GEN_INT (-INTVAL (initial_value) - add_adjust);
                  rtx add_insn = gen_add3_insn (reg, comparison_value, offset);
 
@@ -8414,7 +8430,6 @@ check_dbra_loop (loop, insn_count)
                }
              else if (! add_adjust)
                {
-                 enum machine_mode mode = GET_MODE (reg);
                  rtx sub_insn = gen_sub3_insn (reg, comparison_value,
                                                initial_value);
 
@@ -8433,7 +8448,7 @@ check_dbra_loop (loop, insn_count)
                 create a sequence to hold all the insns from expand_inc.  */
              start_sequence ();
              expand_inc (reg, new_add_val);
-             tem = gen_sequence ();
+             tem = get_insns ();
              end_sequence ();
 
              p = loop_insn_emit_before (loop, 0, bl->biv->insn, tem);
@@ -8457,13 +8472,26 @@ check_dbra_loop (loop, insn_count)
                 not delete the label.  */
              LABEL_NUSES (XEXP (jump_label, 0))++;
 
+             /* If we have a separate comparison insn that does more
+                than just set cc0, the result of the comparison might
+                be used outside the loop.  */
+             keep_first_compare = (compare_and_branch == 2
+#ifdef HAVE_CC0
+                                   && sets_cc0_p (first_compare) <= 0
+#endif
+                                   );
+
              /* Emit an insn after the end of the loop to set the biv's
                 proper exit value if it is used anywhere outside the loop.  */
-             if ((REGNO_LAST_UID (bl->regno) != INSN_UID (first_compare))
+             if (keep_first_compare
+                 || (REGNO_LAST_UID (bl->regno) != INSN_UID (first_compare))
                  || ! bl->init_insn
                  || REGNO_FIRST_UID (bl->regno) != INSN_UID (bl->init_insn))
                loop_insn_sink (loop, gen_load_of_final_value (reg, final_value));
 
+             if (keep_first_compare)
+               loop_insn_sink (loop, PATTERN (first_compare));
+
              /* Delete compare/branch at end of loop.  */
              delete_related_insns (PREV_INSN (loop_end));
              if (compare_and_branch == 2)
@@ -8472,14 +8500,14 @@ check_dbra_loop (loop, insn_count)
              /* Add new compare/branch insn at end of loop.  */
              start_sequence ();
              emit_cmp_and_jump_insns (reg, const0_rtx, cmp_code, NULL_RTX,
-                                      GET_MODE (reg), 0,
+                                      mode, 0,
                                       XEXP (jump_label, 0));
-             tem = gen_sequence ();
+             tem = get_insns ();
              end_sequence ();
              emit_jump_insn_before (tem, loop_end);
 
              for (tem = PREV_INSN (loop_end);
-                  tem && GET_CODE (tem) != JUMP_INSN;
+                  tem && !JUMP_P (tem);
                   tem = PREV_INSN (tem))
                ;
 
@@ -8518,7 +8546,7 @@ check_dbra_loop (loop, insn_count)
                    /* If this is a set of a GIV based on the reversed biv, any
                       REG_EQUAL notes should still be correct.  */
                    if (! set
-                       || GET_CODE (SET_DEST (set)) != REG
+                       || !REG_P (SET_DEST (set))
                        || (size_t) REGNO (SET_DEST (set)) >= ivs->n_regs
                        || REG_IV_TYPE (ivs, REGNO (SET_DEST (set))) != GENERAL_INDUCT
                        || REG_IV_INFO (ivs, REGNO (SET_DEST (set)))->src_reg != bl->biv->src_reg)
@@ -8559,18 +8587,15 @@ check_dbra_loop (loop, insn_count)
 /* Verify whether the biv BL appears to be eliminable,
    based on the insns in the loop that refer to it.
 
-   If ELIMINATE_P is non-zero, actually do the elimination.
+   If ELIMINATE_P is nonzero, actually do the elimination.
 
    THRESHOLD and INSN_COUNT are from loop_optimize and are used to
    determine whether invariant insns should be placed inside or at the
    start of the loop.  */
 
 static int
-maybe_eliminate_biv (loop, bl, eliminate_p, threshold, insn_count)
-     const struct loop *loop;
-     struct iv_class *bl;
-     int eliminate_p;
-     int threshold, insn_count;
+maybe_eliminate_biv (const struct loop *loop, struct iv_class *bl,
+                    int eliminate_p, int threshold, int insn_count)
 {
   struct loop_ivs *ivs = LOOP_IVS (loop);
   rtx reg = bl->biv->dest_reg;
@@ -8584,18 +8609,19 @@ maybe_eliminate_biv (loop, bl, eliminate_p, threshold, insn_count)
       enum rtx_code code = GET_CODE (p);
       basic_block where_bb = 0;
       rtx where_insn = threshold >= insn_count ? 0 : p;
+      rtx note;
 
       /* If this is a libcall that sets a giv, skip ahead to its end.  */
-      if (GET_RTX_CLASS (code) == 'i')
+      if (INSN_P (p))
        {
-         rtx note = find_reg_note (p, REG_LIBCALL, NULL_RTX);
+         note = find_reg_note (p, REG_LIBCALL, NULL_RTX);
 
          if (note)
            {
              rtx last = XEXP (note, 0);
              rtx set = single_set (last);
 
-             if (set && GET_CODE (SET_DEST (set)) == REG)
+             if (set && REG_P (SET_DEST (set)))
                {
                  unsigned int regno = REGNO (SET_DEST (set));
 
@@ -8606,6 +8632,8 @@ maybe_eliminate_biv (loop, bl, eliminate_p, threshold, insn_count)
                }
            }
        }
+
+      /* Closely examine the insn if the biv is mentioned.  */
       if ((code == INSN || code == JUMP_INSN || code == CALL_INSN)
          && reg_mentioned_p (reg, PATTERN (p))
          && ! maybe_eliminate_biv_1 (loop, PATTERN (p), p, bl,
@@ -8617,6 +8645,12 @@ maybe_eliminate_biv (loop, bl, eliminate_p, threshold, insn_count)
                     bl->regno, INSN_UID (p));
          break;
        }
+
+      /* If we are eliminating, kill REG_EQUAL notes mentioning the biv.  */
+      if (eliminate_p
+         && (note = find_reg_note (p, REG_EQUAL, NULL_RTX)) != NULL_RTX
+         && reg_mentioned_p (reg, XEXP (note, 0)))
+       remove_note (p, note);
     }
 
   if (p == loop->end)
@@ -8631,11 +8665,10 @@ maybe_eliminate_biv (loop, bl, eliminate_p, threshold, insn_count)
 }
 \f
 /* INSN and REFERENCE are instructions in the same insn chain.
-   Return non-zero if INSN is first.  */
+   Return nonzero if INSN is first.  */
 
 int
-loop_insn_first_p (insn, reference)
-     rtx insn, reference;
+loop_insn_first_p (rtx insn, rtx reference)
 {
   rtx p, q;
 
@@ -8653,24 +8686,23 @@ loop_insn_first_p (insn, reference)
         P is a note.  */
       if (INSN_UID (p) < max_uid_for_loop
          && INSN_UID (q) < max_uid_for_loop
-         && GET_CODE (p) != NOTE)
+         && !NOTE_P (p))
        return INSN_LUID (p) <= INSN_LUID (q);
 
       if (INSN_UID (p) >= max_uid_for_loop
-         || GET_CODE (p) == NOTE)
+         || NOTE_P (p))
        p = NEXT_INSN (p);
       if (INSN_UID (q) >= max_uid_for_loop)
        q = NEXT_INSN (q);
     }
 }
 
-/* We are trying to eliminate BIV in INSN using GIV.  Return non-zero if
+/* We are trying to eliminate BIV in INSN using GIV.  Return nonzero if
    the offset that we have to take into account due to auto-increment /
    div derivation is zero.  */
 static int
-biv_elimination_giv_has_0_offset (biv, giv, insn)
-     struct induction *biv, *giv;
-     rtx insn;
+biv_elimination_giv_has_0_offset (struct induction *biv,
+                                 struct induction *giv, rtx insn)
 {
   /* If the giv V had the auto-inc address optimization applied
      to it, and INSN occurs between the giv insn and the biv
@@ -8691,20 +8723,16 @@ biv_elimination_giv_has_0_offset (biv, giv, insn)
 
    If BIV does not appear in X, return 1.
 
-   If ELIMINATE_P is non-zero, actually do the elimination.
+   If ELIMINATE_P is nonzero, actually do the elimination.
    WHERE_INSN/WHERE_BB indicate where extra insns should be added.
    Depending on how many items have been moved out of the loop, it
-   will either be before INSN (when WHERE_INSN is non-zero) or at the
+   will either be before INSN (when WHERE_INSN is nonzero) or at the
    start of the loop (when WHERE_INSN is zero).  */
 
 static int
-maybe_eliminate_biv_1 (loop, x, insn, bl, eliminate_p, where_bb, where_insn)
-     const struct loop *loop;
-     rtx x, insn;
-     struct iv_class *bl;
-     int eliminate_p;
-     basic_block where_bb;
-     rtx where_insn;
+maybe_eliminate_biv_1 (const struct loop *loop, rtx x, rtx insn,
+                      struct iv_class *bl, int eliminate_p,
+                      basic_block where_bb, rtx where_insn)
 {
   enum rtx_code code = GET_CODE (x);
   rtx reg = bl->biv->dest_reg;
@@ -8787,7 +8815,7 @@ maybe_eliminate_biv_1 (loop, x, insn, bl, eliminate_p, where_bb, where_insn)
                && (GET_CODE (v->add_val) == SYMBOL_REF
                    || GET_CODE (v->add_val) == LABEL_REF
                    || GET_CODE (v->add_val) == CONST
-                   || (GET_CODE (v->add_val) == REG
+                   || (REG_P (v->add_val)
                        && REG_POINTER (v->add_val))))
              {
                if (! biv_elimination_giv_has_0_offset (bl->biv, v, insn))
@@ -8852,7 +8880,7 @@ maybe_eliminate_biv_1 (loop, x, insn, bl, eliminate_p, where_bb, where_insn)
                && (GET_CODE (v->add_val) == SYMBOL_REF
                    || GET_CODE (v->add_val) == LABEL_REF
                    || GET_CODE (v->add_val) == CONST
-                   || (GET_CODE (v->add_val) == REG
+                   || (REG_P (v->add_val)
                        && REG_POINTER (v->add_val)))
                && ! v->ignore && ! v->maybe_dead && v->always_computable
                && v->mode == mode)
@@ -8941,7 +8969,7 @@ maybe_eliminate_biv_1 (loop, x, insn, bl, eliminate_p, where_bb, where_insn)
                  return 1;
              }
        }
-      else if (GET_CODE (arg) == REG || GET_CODE (arg) == MEM)
+      else if (REG_P (arg) || MEM_P (arg))
        {
          if (loop_invariant_p (loop, arg) == 1)
            {
@@ -8993,7 +9021,7 @@ maybe_eliminate_biv_1 (loop, x, insn, bl, eliminate_p, where_bb, where_insn)
 
 #if 0
          /* Otherwise the reg compared with had better be a biv.  */
-         if (GET_CODE (arg) != REG
+         if (!REG_P (arg)
              || REG_IV_TYPE (ivs, REGNO (arg)) != BASIC_INDUCT)
            return 0;
 
@@ -9073,13 +9101,11 @@ maybe_eliminate_biv_1 (loop, x, insn, bl, eliminate_p, where_bb, where_insn)
    is in an insn following INSN in the same basic block.  */
 
 static int
-last_use_this_basic_block (reg, insn)
-     rtx reg;
-     rtx insn;
+last_use_this_basic_block (rtx reg, rtx insn)
 {
   rtx n;
   for (n = insn;
-       n && GET_CODE (n) != CODE_LABEL && GET_CODE (n) != JUMP_INSN;
+       n && !LABEL_P (n) && !JUMP_P (n);
        n = NEXT_INSN (n))
     {
       if (REGNO_LAST_UID (REGNO (reg)) == INSN_UID (n))
@@ -9092,15 +9118,12 @@ last_use_this_basic_block (reg, insn)
    just record the location of the set and process it later.  */
 
 static void
-record_initial (dest, set, data)
-     rtx dest;
-     rtx set;
-     void *data ATTRIBUTE_UNUSED;
+record_initial (rtx dest, rtx set, void *data ATTRIBUTE_UNUSED)
 {
   struct loop_ivs *ivs = (struct loop_ivs *) data;
   struct iv_class *bl;
 
-  if (GET_CODE (dest) != REG
+  if (!REG_P (dest)
       || REGNO (dest) >= ivs->n_regs
       || REG_IV_TYPE (ivs, REGNO (dest)) != BASIC_INDUCT)
     return;
@@ -9121,9 +9144,7 @@ record_initial (dest, set, data)
    use it.  X must be a source expression only.  */
 
 static void
-update_reg_last_use (x, insn)
-     rtx x;
-     rtx insn;
+update_reg_last_use (rtx x, rtx insn)
 {
   /* Check for the case where INSN does not have a valid luid.  In this case,
      there is no need to modify the regno_last_uid, as this can only happen
@@ -9131,7 +9152,7 @@ update_reg_last_use (x, insn)
      and hence this insn will never be the last use of x.
      ???? This comment is not correct.  See for example loop_givs_reduce.
      This may insert an insn before another new insn.  */
-  if (GET_CODE (x) == REG && REGNO (x) < max_reg_before_loop
+  if (REG_P (x) && REGNO (x) < max_reg_before_loop
       && INSN_UID (insn) < max_uid_for_loop
       && REGNO_LAST_LUID (REGNO (x)) < INSN_LUID (insn))
     {
@@ -9164,24 +9185,21 @@ update_reg_last_use (x, insn)
    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 REVERSE is nonzero, then reverse the condition prior to canonizing it.
 
-   If EARLIEST is non-zero, it is a pointer to a place where the earliest
+   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 non-zero, we wish the condition to be relative to that
+   If WANT_REG is nonzero, we wish the condition to be relative to that
    register, if possible.  Therefore, do not canonicalize the condition
-   further.  */
+   further.  If ALLOW_CC_MODE is nonzero, allow the condition returned 
+   to be a compare to a CC mode register.  */
 
 rtx
-canonicalize_condition (insn, cond, reverse, earliest, want_reg)
-     rtx insn;
-     rtx cond;
-     int reverse;
-     rtx *earliest;
-     rtx want_reg;
+canonicalize_condition (rtx insn, rtx cond, int reverse, rtx *earliest,
+                       rtx want_reg, int allow_cc_mode)
 {
   enum rtx_code code;
   rtx prev = insn;
@@ -9209,11 +9227,12 @@ canonicalize_condition (insn, cond, reverse, earliest, want_reg)
      the same tests as a function of STORE_FLAG_VALUE as find_comparison_args
      in cse.c  */
 
-  while (GET_RTX_CLASS (code) == '<'
+  while ((GET_RTX_CLASS (code) == RTX_COMPARE
+         || GET_RTX_CLASS (code) == RTX_COMM_COMPARE)
         && op1 == CONST0_RTX (GET_MODE (op0))
         && op0 != want_reg)
     {
-      /* Set non-zero when we find something of interest.  */
+      /* Set nonzero when we find something of interest.  */
       rtx x = 0;
 
 #ifdef HAVE_cc0
@@ -9222,7 +9241,7 @@ canonicalize_condition (insn, cond, reverse, earliest, want_reg)
       if (op0 == cc0_rtx)
        {
          if ((prev = prev_nonnote_insn (prev)) == 0
-             || GET_CODE (prev) != INSN
+             || !NONJUMP_INSN_P (prev)
              || (set = single_set (prev)) == 0
              || SET_DEST (set) != cc0_rtx)
            return 0;
@@ -9241,7 +9260,7 @@ canonicalize_condition (insn, cond, reverse, earliest, want_reg)
          op0 = XEXP (op0, 0);
          continue;
        }
-      else if (GET_CODE (op0) != REG)
+      else if (!REG_P (op0))
        break;
 
       /* Go back to the previous insn.  Stop if it is not an INSN.  We also
@@ -9249,7 +9268,7 @@ canonicalize_condition (insn, cond, reverse, earliest, want_reg)
         we don't want to bother dealing with it.  */
 
       if ((prev = prev_nonnote_insn (prev)) == 0
-         || GET_CODE (prev) != INSN
+         || !NONJUMP_INSN_P (prev)
          || FIND_REG_INC_NOTE (prev, NULL_RTX))
        break;
 
@@ -9265,6 +9284,9 @@ canonicalize_condition (insn, cond, reverse, earliest, want_reg)
       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
@@ -9292,11 +9314,11 @@ canonicalize_condition (insn, cond, reverse, earliest, want_reg)
 #ifdef FLOAT_STORE_FLAG_VALUE
                     || (code == LT
                         && GET_MODE_CLASS (inner_mode) == MODE_FLOAT
-                        && (REAL_VALUE_NEGATIVE
-                            (FLOAT_STORE_FLAG_VALUE (inner_mode))))
+                        && (fsfv = FLOAT_STORE_FLAG_VALUE (inner_mode),
+                            REAL_VALUE_NEGATIVE (fsfv)))
 #endif
                     ))
-                  && GET_RTX_CLASS (GET_CODE (SET_SRC (set))) == '<'))
+                  && COMPARISON_P (SET_SRC (set))))
              && (((GET_MODE_CLASS (mode) == MODE_CC)
                   == (GET_MODE_CLASS (inner_mode) == MODE_CC))
                  || mode == VOIDmode || inner_mode == VOIDmode))
@@ -9312,11 +9334,11 @@ canonicalize_condition (insn, cond, reverse, earliest, want_reg)
 #ifdef FLOAT_STORE_FLAG_VALUE
                     || (code == GE
                         && GET_MODE_CLASS (inner_mode) == MODE_FLOAT
-                        && (REAL_VALUE_NEGATIVE
-                            (FLOAT_STORE_FLAG_VALUE (inner_mode))))
+                        && (fsfv = FLOAT_STORE_FLAG_VALUE (inner_mode),
+                            REAL_VALUE_NEGATIVE (fsfv)))
 #endif
                     ))
-                  && GET_RTX_CLASS (GET_CODE (SET_SRC (set))) == '<'
+                  && COMPARISON_P (SET_SRC (set))
                   && (((GET_MODE_CLASS (mode) == MODE_CC)
                        == (GET_MODE_CLASS (inner_mode) == MODE_CC))
                       || mode == VOIDmode || inner_mode == VOIDmode))
@@ -9335,7 +9357,7 @@ canonicalize_condition (insn, cond, reverse, earliest, want_reg)
 
       if (x)
        {
-         if (GET_RTX_CLASS (GET_CODE (x)) == '<')
+         if (COMPARISON_P (x))
            code = GET_CODE (x);
          if (reverse_code)
            {
@@ -9357,14 +9379,16 @@ canonicalize_condition (insn, cond, reverse, earliest, want_reg)
 
   /* If OP0 is the result of a comparison, we weren't able to find what
      was really being compared, so fail.  */
-  if (GET_MODE_CLASS (GET_MODE (op0)) == MODE_CC)
+  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_CODE (op1) == CONST_INT
+  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)
     {
@@ -9404,11 +9428,9 @@ canonicalize_condition (insn, cond, reverse, earliest, want_reg)
        }
     }
 
-#ifdef HAVE_cc0
   /* Never return CC0; return zero instead.  */
-  if (op0 == cc0_rtx)
+  if (CC0_P (op0))
     return 0;
-#endif
 
   return gen_rtx_fmt_ee (code, VOIDmode, op0, op1);
 }
@@ -9418,22 +9440,23 @@ canonicalize_condition (insn, cond, reverse, earliest, want_reg)
    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
+   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.  */
+   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 (jump, earliest)
-     rtx jump;
-     rtx *earliest;
+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 (GET_CODE (jump) != JUMP_INSN
+  if (!JUMP_P (jump)
       || ! any_condjump_p (jump))
     return 0;
   set = pc_set (jump);
@@ -9446,18 +9469,17 @@ get_condition (jump, earliest)
     = 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);
+  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
-get_condition_for_loop (loop, x)
-     const struct loop *loop;
-     rtx x;
+get_condition_for_loop (const struct loop *loop, rtx x)
 {
-  rtx comparison = get_condition (x, (rtx*) 0);
+  rtx comparison = get_condition (x, (rtx*) 0, false);
 
   if (comparison == 0
       || ! loop_invariant_p (loop, XEXP (comparison, 0))
@@ -9473,8 +9495,7 @@ get_condition_for_loop (loop, x)
    This is taken mostly from flow.c; similar code exists elsewhere
    in the compiler.  It may be useful to put this into rtlanal.c.  */
 static int
-indirect_jump_in_function_p (start)
-     rtx start;
+indirect_jump_in_function_p (rtx start)
 {
   rtx insn;
 
@@ -9490,9 +9511,7 @@ indirect_jump_in_function_p (start)
    This function is called from prescan_loop via for_each_rtx.  */
 
 static int
-insert_loop_mem (mem, data)
-     rtx *mem;
-     void *data ATTRIBUTE_UNUSED;
+insert_loop_mem (rtx *mem, void *data ATTRIBUTE_UNUSED)
 {
   struct loop_info *loop_info = data;
   int i;
@@ -9528,6 +9547,8 @@ insert_loop_mem (mem, data)
   for (i = 0; i < loop_info->mems_idx; ++i)
     if (rtx_equal_p (m, loop_info->mems[i].mem))
       {
+       if (MEM_VOLATILE_P (m) && !MEM_VOLATILE_P (loop_info->mems[i].mem))
+         loop_info->mems[i].mem = m;
        if (GET_MODE (m) != GET_MODE (loop_info->mems[i].mem))
          /* The modes of the two memory accesses are different.  If
             this happens, something tricky is going on, and we just
@@ -9545,9 +9566,8 @@ insert_loop_mem (mem, data)
       else
        loop_info->mems_allocated = 32;
 
-      loop_info->mems = (loop_mem_info *)
-       xrealloc (loop_info->mems,
-                 loop_info->mems_allocated * sizeof (loop_mem_info));
+      loop_info->mems = xrealloc (loop_info->mems,
+                                 loop_info->mems_allocated * sizeof (loop_mem_info));
     }
 
   /* Actually insert the MEM.  */
@@ -9580,9 +9600,7 @@ insert_loop_mem (mem, data)
    optimize register I.  */
 
 static void
-loop_regs_scan (loop, extra_size)
-     const struct loop *loop;
-     int extra_size;
+loop_regs_scan (const struct loop *loop, int extra_size)
 {
   struct loop_regs *regs = LOOP_REGS (loop);
   int old_nregs;
@@ -9600,8 +9618,7 @@ loop_regs_scan (loop, extra_size)
     {
       regs->size = regs->num + extra_size;
 
-      regs->array = (struct loop_reg *)
-       xrealloc (regs->array, regs->size * sizeof (*regs->array));
+      regs->array = xrealloc (regs->array, regs->size * sizeof (*regs->array));
 
       /* Zero the new elements.  */
       memset (regs->array + old_nregs, 0,
@@ -9616,7 +9633,7 @@ loop_regs_scan (loop, extra_size)
       regs->array[i].single_usage = NULL_RTX;
     }
 
-  last_set = (rtx *) xcalloc (regs->num, sizeof (rtx));
+  last_set = xcalloc (regs->num, sizeof (rtx));
 
   /* Scan the loop, recording register usage.  */
   for (insn = loop->top ? loop->top : loop->start; insn != loop->end;
@@ -9643,8 +9660,27 @@ loop_regs_scan (loop, extra_size)
            }
        }
 
-      if (GET_CODE (insn) == CODE_LABEL || GET_CODE (insn) == JUMP_INSN)
+      if (LABEL_P (insn) || JUMP_P (insn))
        memset (last_set, 0, regs->num * sizeof (rtx));
+
+      /* Invalidate all registers used for function argument passing.
+        We check rtx_varies_p for the same reason as below, to allow
+        optimizing PIC calculations.  */
+      if (CALL_P (insn))
+       {
+         rtx link;
+         for (link = CALL_INSN_FUNCTION_USAGE (insn);
+              link;
+              link = XEXP (link, 1))
+           {
+             rtx op, reg;
+
+             if (GET_CODE (op = XEXP (link, 0)) == USE
+                 && REG_P (reg = XEXP (op, 0))
+                 && rtx_varies_p (reg, 1))
+               regs->array[REGNO (reg)].may_not_optimize = 1;
+           }
+       }
     }
 
   /* Invalidate all hard registers clobbered by calls.  With one exception:
@@ -9654,7 +9690,7 @@ loop_regs_scan (loop, extra_size)
   if (LOOP_INFO (loop)->has_call)
     for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
       if (TEST_HARD_REG_BIT (regs_invalidated_by_call, i)
-         && rtx_varies_p (gen_rtx_REG (Pmode, i), /*for_alias=*/1))
+         && rtx_varies_p (regno_reg_rtx[i], 1))
        {
          regs->array[i].may_not_optimize = 1;
          regs->array[i].set_in_loop = 1;
@@ -9678,8 +9714,7 @@ loop_regs_scan (loop, extra_size)
 /* Returns the number of real INSNs in the LOOP.  */
 
 static int
-count_insns_in_loop (loop)
-     const struct loop *loop;
+count_insns_in_loop (const struct loop *loop)
 {
   int count = 0;
   rtx insn;
@@ -9695,8 +9730,7 @@ count_insns_in_loop (loop)
 /* Move MEMs into registers for the duration of the loop.  */
 
 static void
-load_mems (loop)
-     const struct loop *loop;
+load_mems (const struct loop *loop)
 {
   struct loop_info *loop_info = LOOP_INFO (loop);
   struct loop_regs *regs = LOOP_REGS (loop);
@@ -9714,7 +9748,7 @@ load_mems (loop)
 
   /* We cannot use next_label here because it skips over normal insns.  */
   end_label = next_nonnote_insn (loop->end);
-  if (end_label && GET_CODE (end_label) != CODE_LABEL)
+  if (end_label && !LABEL_P (end_label))
     end_label = NULL_RTX;
 
   /* Check to see if it's possible that some instructions in the loop are
@@ -9724,16 +9758,16 @@ load_mems (loop)
        p != NULL_RTX;
        p = next_insn_in_loop (loop, p))
     {
-      if (GET_CODE (p) == CODE_LABEL)
+      if (LABEL_P (p))
        maybe_never = 1;
-      else if (GET_CODE (p) == JUMP_INSN
+      else if (JUMP_P (p)
               /* If we enter the loop in the middle, and scan
                  around to the beginning, don't set maybe_never
                  for that.  This must be an unconditional jump,
                  otherwise the code at the top of the loop might
                  never be executed.  Unconditional jumps are
                  followed a by barrier then loop end.  */
-              && ! (GET_CODE (p) == JUMP_INSN
+              && ! (JUMP_P (p)
                     && JUMP_LABEL (p) == loop->top
                     && NEXT_INSN (NEXT_INSN (p)) == loop->end
                     && any_uncondjump_p (p)))
@@ -9764,12 +9798,12 @@ load_mems (loop)
 
   /* Find start of the extended basic block that enters the loop.  */
   for (p = loop->start;
-       PREV_INSN (p) && GET_CODE (p) != CODE_LABEL;
+       PREV_INSN (p) && !LABEL_P (p);
        p = PREV_INSN (p))
     ;
   prev_ebb_head = p;
 
-  cselib_init ();
+  cselib_init (true);
 
   /* Build table of mems that get set to constant values before the
      loop.  */
@@ -9876,7 +9910,7 @@ load_mems (loop)
              if (set
                  /* @@@ This test is _way_ too conservative.  */
                  && ! maybe_never
-                 && GET_CODE (SET_DEST (set)) == REG
+                 && REG_P (SET_DEST (set))
                  && REGNO (SET_DEST (set)) >= FIRST_PSEUDO_REGISTER
                  && REGNO (SET_DEST (set)) < last_max_reg
                  && regs->array[REGNO (SET_DEST (set))].n_times_set == 1
@@ -9890,7 +9924,7 @@ load_mems (loop)
                 to untangle things for the BIV detection code.  */
              if (set
                  && ! maybe_never
-                 && GET_CODE (SET_SRC (set)) == REG
+                 && REG_P (SET_SRC (set))
                  && REGNO (SET_SRC (set)) >= FIRST_PSEUDO_REGISTER
                  && REGNO (SET_SRC (set)) < last_max_reg
                  && regs->array[REGNO (SET_SRC (set))].n_times_set == 1
@@ -9899,7 +9933,7 @@ load_mems (loop)
 
              /* If this is a call which uses / clobbers this memory
                 location, we must not change the interface here.  */
-             if (GET_CODE (p) == CALL_INSN
+             if (CALL_P (p)
                  && reg_mentioned_p (loop_info->mems[i].mem,
                                      CALL_INSN_FUNCTION_USAGE (p)))
                {
@@ -9910,11 +9944,11 @@ load_mems (loop)
              else
                /* Replace the memory reference with the shadow register.  */
                replace_loop_mems (p, loop_info->mems[i].mem,
-                                  loop_info->mems[i].reg);
+                                  loop_info->mems[i].reg, written);
            }
 
-         if (GET_CODE (p) == CODE_LABEL
-             || GET_CODE (p) == JUMP_INSN)
+         if (LABEL_P (p)
+             || JUMP_P (p))
            maybe_never = 1;
        }
 
@@ -9941,7 +9975,7 @@ load_mems (loop)
                {
                  if (CONSTANT_P (equiv->loc))
                    const_equiv = equiv;
-                 else if (GET_CODE (equiv->loc) == REG
+                 else if (REG_P (equiv->loc)
                           /* Extending hard register lifetimes causes crash
                              on SRC targets.  Doing so on non-SRC is
                              probably also not good idea, since we most
@@ -10025,28 +10059,12 @@ load_mems (loop)
        }
     }
 
+  /* Now, we need to replace all references to the previous exit
+     label with the new one.  */
   if (label != NULL_RTX && end_label != NULL_RTX)
-    {
-      /* Now, we need to replace all references to the previous exit
-        label with the new one.  */
-      rtx_pair rr;
-      rr.r1 = end_label;
-      rr.r2 = label;
-
-      for (p = loop->start; p != loop->end; p = NEXT_INSN (p))
-       {
-         for_each_rtx (&p, replace_label, &rr);
-
-         /* If this is a JUMP_INSN, then we also need to fix the JUMP_LABEL
-            field.  This is not handled by for_each_rtx because it doesn't
-            handle unprinted ('0') fields.  We need to update JUMP_LABEL
-            because the immediately following unroll pass will use it.
-            replace_label would not work anyways, because that only handles
-            LABEL_REFs.  */
-         if (GET_CODE (p) == JUMP_INSN && JUMP_LABEL (p) == end_label)
-           JUMP_LABEL (p) = label;
-       }
-    }
+    for (p = loop->start; p != loop->end; p = NEXT_INSN (p))
+      if (JUMP_P (p) && JUMP_LABEL (p) == end_label)
+       redirect_jump (p, label, false);
 
   cselib_finish ();
 }
@@ -10061,9 +10079,7 @@ struct note_reg_stored_arg
 /* Called via note_stores, record in SET_SEEN whether X, which is written,
    is equal to ARG.  */
 static void
-note_reg_stored (x, setter, arg)
-     rtx x, setter ATTRIBUTE_UNUSED;
-     void *arg;
+note_reg_stored (rtx x, rtx setter ATTRIBUTE_UNUSED, void *arg)
 {
   struct note_reg_stored_arg *t = (struct note_reg_stored_arg *) arg;
   if (t->reg == x)
@@ -10076,10 +10092,7 @@ note_reg_stored (x, setter, arg)
    is not used after the loop.  */
 
 static void
-try_copy_prop (loop, replacement, regno)
-     const struct loop *loop;
-     rtx replacement;
-     unsigned int regno;
+try_copy_prop (const struct loop *loop, rtx replacement, unsigned int regno)
 {
   /* This is the reg that we are copying from.  */
   rtx reg_rtx = regno_reg_rtx[regno];
@@ -10097,7 +10110,7 @@ try_copy_prop (loop, replacement, regno)
 
       /* Only substitute within one extended basic block from the initializing
          insn.  */
-      if (GET_CODE (insn) == CODE_LABEL && init_insn)
+      if (LABEL_P (insn) && init_insn)
        break;
 
       if (! INSN_P (insn))
@@ -10106,7 +10119,7 @@ try_copy_prop (loop, replacement, regno)
       /* Is this the initializing insn?  */
       set = single_set (insn);
       if (set
-         && GET_CODE (SET_DEST (set)) == REG
+         && REG_P (SET_DEST (set))
          && REGNO (SET_DEST (set)) == regno)
        {
          if (init_insn)
@@ -10176,9 +10189,7 @@ try_copy_prop (loop, replacement, regno)
    with NOTE_INSN_DELETED notes.  */
 
 static void
-loop_delete_insns (first, last)
-     rtx first;
-     rtx last;
+loop_delete_insns (rtx first, rtx last)
 {
   while (1)
     {
@@ -10202,10 +10213,8 @@ loop_delete_insns (first, last)
    this pseudo followed immediately by a move insn that sets
    REPLACEMENT with REGNO.  */
 static void
-try_swap_copy_prop (loop, replacement, regno)
-     const struct loop *loop;
-     rtx replacement;
-     unsigned int regno;
+try_swap_copy_prop (const struct loop *loop, rtx replacement,
+                   unsigned int regno)
 {
   rtx insn;
   rtx set = NULL_RTX;
@@ -10220,9 +10229,9 @@ try_swap_copy_prop (loop, replacement, regno)
       /* Search for the insn that copies REGNO to NEW_REGNO?  */
       if (INSN_P (insn)
          && (set = single_set (insn))
-         && GET_CODE (SET_DEST (set)) == REG
+         && REG_P (SET_DEST (set))
          && REGNO (SET_DEST (set)) == new_regno
-         && GET_CODE (SET_SRC (set)) == REG
+         && REG_P (SET_SRC (set))
          && REGNO (SET_SRC (set)) == regno)
        break;
     }
@@ -10240,7 +10249,7 @@ try_swap_copy_prop (loop, replacement, regno)
 
       if (INSN_P (insn)
          && (prev_set = single_set (prev_insn))
-         && GET_CODE (SET_DEST (prev_set)) == REG
+         && REG_P (SET_DEST (prev_set))
          && REGNO (SET_DEST (prev_set)) == regno)
        {
          /* We have:
@@ -10283,15 +10292,37 @@ try_swap_copy_prop (loop, replacement, regno)
     }
 }
 
+/* Worker function for find_mem_in_note, called via for_each_rtx.  */
+
+static int
+find_mem_in_note_1 (rtx *x, void *data)
+{
+  if (*x != NULL_RTX && MEM_P (*x))
+    {
+      rtx *res = (rtx *) data;
+      *res = *x;
+      return 1;
+    }
+  return 0;
+}
+
+/* Returns the first MEM found in NOTE by depth-first search.  */
+
+static rtx
+find_mem_in_note (rtx note)
+{
+  if (note && for_each_rtx (&note, find_mem_in_note_1, &note))
+    return note;
+  return NULL_RTX;
+}
+
 /* Replace MEM with its associated pseudo register.  This function is
    called from load_mems via for_each_rtx.  DATA is actually a pointer
    to a structure describing the instruction currently being scanned
    and the MEM we are currently replacing.  */
 
 static int
-replace_loop_mem (mem, data)
-     rtx *mem;
-     void *data;
+replace_loop_mem (rtx *mem, void *data)
 {
   loop_replace_args *args = (loop_replace_args *) data;
   rtx m = *mem;
@@ -10325,10 +10356,7 @@ replace_loop_mem (mem, data)
 }
 
 static void
-replace_loop_mems (insn, mem, reg)
-     rtx insn;
-     rtx mem;
-     rtx reg;
+replace_loop_mems (rtx insn, rtx mem, rtx reg, int written)
 {
   loop_replace_args args;
 
@@ -10337,6 +10365,26 @@ replace_loop_mems (insn, mem, reg)
   args.replacement = reg;
 
   for_each_rtx (&insn, replace_loop_mem, &args);
+
+  /* If we hoist a mem write out of the loop, then REG_EQUAL
+     notes referring to the mem are no longer valid.  */
+  if (written)
+    {
+      rtx note, sub;
+      rtx *link;
+
+      for (link = &REG_NOTES (insn); (note = *link); link = &XEXP (note, 1))
+       {
+         if (REG_NOTE_KIND (note) == REG_EQUAL
+             && (sub = find_mem_in_note (note))
+             && true_dependence (mem, VOIDmode, sub, rtx_varies_p))
+           {
+             /* Remove the note.  */
+             validate_change (NULL_RTX, link, XEXP (note, 1), 1);
+             break;
+           }
+       }
+    }
 }
 
 /* Replace one register with another.  Called through for_each_rtx; PX points
@@ -10344,9 +10392,7 @@ replace_loop_mems (insn, mem, reg)
    a structure of arguments.  */
 
 static int
-replace_loop_reg (px, data)
-     rtx *px;
-     void *data;
+replace_loop_reg (rtx *px, void *data)
 {
   rtx x = *px;
   loop_replace_args *args = (loop_replace_args *) data;
@@ -10361,10 +10407,7 @@ replace_loop_reg (px, data)
 }
 
 static void
-replace_loop_regs (insn, reg, replacement)
-     rtx insn;
-     rtx reg;
-     rtx replacement;
+replace_loop_regs (rtx insn, rtx reg, rtx replacement)
 {
   loop_replace_args args;
 
@@ -10374,60 +10417,27 @@ replace_loop_regs (insn, reg, replacement)
 
   for_each_rtx (&insn, replace_loop_reg, &args);
 }
-
-/* Replace occurrences of the old exit label for the loop with the new
-   one.  DATA is an rtx_pair containing the old and new labels,
-   respectively.  */
-
-static int
-replace_label (x, data)
-     rtx *x;
-     void *data;
-{
-  rtx l = *x;
-  rtx old_label = ((rtx_pair *) data)->r1;
-  rtx new_label = ((rtx_pair *) data)->r2;
-
-  if (l == NULL_RTX)
-    return 0;
-
-  if (GET_CODE (l) != LABEL_REF)
-    return 0;
-
-  if (XEXP (l, 0) != old_label)
-    return 0;
-
-  XEXP (l, 0) = new_label;
-  ++LABEL_NUSES (new_label);
-  --LABEL_NUSES (old_label);
-
-  return 0;
-}
 \f
 /* Emit insn for PATTERN after WHERE_INSN in basic block WHERE_BB
    (ignored in the interim).  */
 
 static rtx
-loop_insn_emit_after (loop, where_bb, where_insn, pattern)
-     const struct loop *loop ATTRIBUTE_UNUSED;
-     basic_block where_bb ATTRIBUTE_UNUSED;
-     rtx where_insn;
-     rtx pattern;
+loop_insn_emit_after (const struct loop *loop ATTRIBUTE_UNUSED,
+                     basic_block where_bb ATTRIBUTE_UNUSED, rtx where_insn,
+                     rtx pattern)
 {
   return emit_insn_after (pattern, where_insn);
 }
 
 
-/* If WHERE_INSN is non-zero emit insn for PATTERN before WHERE_INSN
+/* If WHERE_INSN is nonzero emit insn for PATTERN before WHERE_INSN
    in basic block WHERE_BB (ignored in the interim) within the loop
    otherwise hoist PATTERN into the loop pre-header.  */
 
 rtx
-loop_insn_emit_before (loop, where_bb, where_insn, pattern)
-     const struct loop *loop;
-     basic_block where_bb ATTRIBUTE_UNUSED;
-     rtx where_insn;
-     rtx pattern;
+loop_insn_emit_before (const struct loop *loop,
+                      basic_block where_bb ATTRIBUTE_UNUSED,
+                      rtx where_insn, rtx pattern)
 {
   if (! where_insn)
     return loop_insn_hoist (loop, pattern);
@@ -10439,11 +10449,9 @@ loop_insn_emit_before (loop, where_bb, where_insn, pattern)
    WHERE_BB (ignored in the interim) within the loop.  */
 
 static rtx
-loop_call_insn_emit_before (loop, where_bb, where_insn, pattern)
-     const struct loop *loop ATTRIBUTE_UNUSED;
-     basic_block where_bb ATTRIBUTE_UNUSED;
-     rtx where_insn;
-     rtx pattern;
+loop_call_insn_emit_before (const struct loop *loop ATTRIBUTE_UNUSED,
+                           basic_block where_bb ATTRIBUTE_UNUSED,
+                           rtx where_insn, rtx pattern)
 {
   return emit_call_insn_before (pattern, where_insn);
 }
@@ -10452,9 +10460,7 @@ loop_call_insn_emit_before (loop, where_bb, where_insn, pattern)
 /* Hoist insn for PATTERN into the loop pre-header.  */
 
 rtx
-loop_insn_hoist (loop, pattern)
-     const struct loop *loop;
-     rtx pattern;
+loop_insn_hoist (const struct loop *loop, rtx pattern)
 {
   return loop_insn_emit_before (loop, 0, loop->start, pattern);
 }
@@ -10463,9 +10469,7 @@ loop_insn_hoist (loop, pattern)
 /* Hoist call insn for PATTERN into the loop pre-header.  */
 
 static rtx
-loop_call_insn_hoist (loop, pattern)
-     const struct loop *loop;
-     rtx pattern;
+loop_call_insn_hoist (const struct loop *loop, rtx pattern)
 {
   return loop_call_insn_emit_before (loop, 0, loop->start, pattern);
 }
@@ -10474,25 +10478,22 @@ loop_call_insn_hoist (loop, pattern)
 /* Sink insn for PATTERN after the loop end.  */
 
 rtx
-loop_insn_sink (loop, pattern)
-     const struct loop *loop;
-     rtx pattern;
+loop_insn_sink (const struct loop *loop, rtx pattern)
 {
   return loop_insn_emit_before (loop, 0, loop->sink, pattern);
 }
 
-/* bl->final_value can be eighter general_operand or PLUS of general_operand
-   and constant.  Emit sequence of intructions to load it into REG  */
+/* bl->final_value can be either general_operand or PLUS of general_operand
+   and constant.  Emit sequence of instructions to load it into REG.  */
 static rtx
-gen_load_of_final_value (reg, final_value)
-     rtx reg, final_value;
+gen_load_of_final_value (rtx reg, rtx final_value)
 {
   rtx seq;
   start_sequence ();
   final_value = force_operand (final_value, reg);
   if (final_value != reg)
     emit_move_insn (reg, final_value);
-  seq = gen_sequence ();
+  seq = get_insns ();
   end_sequence ();
   return seq;
 }
@@ -10503,9 +10504,7 @@ gen_load_of_final_value (reg, final_value)
    since this is slightly more efficient.  */
 
 static rtx
-loop_insn_sink_or_swim (loop, pattern)
-     const struct loop *loop;
-     rtx pattern;
+loop_insn_sink_or_swim (const struct loop *loop, rtx pattern)
 {
   if (loop->exit_count)
     return loop_insn_hoist (loop, pattern);
@@ -10514,10 +10513,7 @@ loop_insn_sink_or_swim (loop, pattern)
 }
 \f
 static void
-loop_ivs_dump (loop, file, verbose)
-     const struct loop *loop;
-     FILE *file;
-     int verbose;
+loop_ivs_dump (const struct loop *loop, FILE *file, int verbose)
 {
   struct iv_class *bl;
   int iv_num = 0;
@@ -10539,10 +10535,8 @@ loop_ivs_dump (loop, file, verbose)
 
 
 static void
-loop_iv_class_dump (bl, file, verbose)
-     const struct iv_class *bl;
-     FILE *file;
-     int verbose ATTRIBUTE_UNUSED;
+loop_iv_class_dump (const struct iv_class *bl, FILE *file,
+                   int verbose ATTRIBUTE_UNUSED)
 {
   struct induction *v;
   rtx incr;
@@ -10604,10 +10598,7 @@ loop_iv_class_dump (bl, file, verbose)
 
 
 static void
-loop_biv_dump (v, file, verbose)
-     const struct induction *v;
-     FILE *file;
-     int verbose;
+loop_biv_dump (const struct induction *v, FILE *file, int verbose)
 {
   if (! v || ! file)
     return;
@@ -10630,10 +10621,7 @@ loop_biv_dump (v, file, verbose)
 
 
 static void
-loop_giv_dump (v, file, verbose)
-     const struct induction *v;
-     FILE *file;
-     int verbose;
+loop_giv_dump (const struct induction *v, FILE *file, int verbose)
 {
   if (! v || ! file)
     return;
@@ -10694,32 +10682,28 @@ loop_giv_dump (v, file, verbose)
 
 
 void
-debug_ivs (loop)
-     const struct loop *loop;
+debug_ivs (const struct loop *loop)
 {
   loop_ivs_dump (loop, stderr, 1);
 }
 
 
 void
-debug_iv_class (bl)
-     const struct iv_class *bl;
+debug_iv_class (const struct iv_class *bl)
 {
   loop_iv_class_dump (bl, stderr, 1);
 }
 
 
 void
-debug_biv (v)
-     const struct induction *v;
+debug_biv (const struct induction *v)
 {
   loop_biv_dump (v, stderr, 1);
 }
 
 
 void
-debug_giv (v)
-     const struct induction *v;
+debug_giv (const struct induction *v)
 {
   loop_giv_dump (v, stderr, 1);
 }
@@ -10730,7 +10714,7 @@ debug_giv (v)
 
 /* The notes do not have an assigned block, so look at the next insn.  */
 #define LOOP_BLOCK_NUM(INSN) \
-((INSN) ? (GET_CODE (INSN) == NOTE \
+((INSN) ? (NOTE_P (INSN) \
             ? LOOP_BLOCK_NUM_1 (next_nonnote_insn (INSN)) \
             : LOOP_BLOCK_NUM_1 (INSN)) \
         : -1)
@@ -10738,10 +10722,8 @@ debug_giv (v)
 #define LOOP_INSN_UID(INSN) ((INSN) ? INSN_UID (INSN) : -1)
 
 static void
-loop_dump_aux (loop, file, verbose)
-     const struct loop *loop;
-     FILE *file;
-     int verbose ATTRIBUTE_UNUSED;
+loop_dump_aux (const struct loop *loop, FILE *file,
+              int verbose ATTRIBUTE_UNUSED)
 {
   rtx label;
 
@@ -10750,18 +10732,18 @@ loop_dump_aux (loop, file, verbose)
 
   /* Print diagnostics to compare our concept of a loop with
      what the loop notes say.  */
-  if (! PREV_INSN (loop->first->head)
-      || GET_CODE (PREV_INSN (loop->first->head)) != NOTE
-      || NOTE_LINE_NUMBER (PREV_INSN (loop->first->head))
+  if (! PREV_INSN (BB_HEAD (loop->first))
+      || !NOTE_P (PREV_INSN (BB_HEAD (loop->first)))
+      || NOTE_LINE_NUMBER (PREV_INSN (BB_HEAD (loop->first)))
       != NOTE_INSN_LOOP_BEG)
     fprintf (file, ";;  No NOTE_INSN_LOOP_BEG at %d\n",
-            INSN_UID (PREV_INSN (loop->first->head)));
-  if (! NEXT_INSN (loop->last->end)
-      || GET_CODE (NEXT_INSN (loop->last->end)) != NOTE
-      || NOTE_LINE_NUMBER (NEXT_INSN (loop->last->end))
+            INSN_UID (PREV_INSN (BB_HEAD (loop->first))));
+  if (! NEXT_INSN (BB_END (loop->last))
+      || !NOTE_P (NEXT_INSN (BB_END (loop->last)))
+      || NOTE_LINE_NUMBER (NEXT_INSN (BB_END (loop->last)))
       != NOTE_INSN_LOOP_END)
     fprintf (file, ";;  No NOTE_INSN_LOOP_END at %d\n",
-            INSN_UID (NEXT_INSN (loop->last->end)));
+            INSN_UID (NEXT_INSN (BB_END (loop->last))));
 
   if (loop->start)
     {
@@ -10805,8 +10787,7 @@ loop_dump_aux (loop, file, verbose)
 /* Call this function from the debugger to dump LOOP.  */
 
 void
-debug_loop (loop)
-     const struct loop *loop;
+debug_loop (const struct loop *loop)
 {
   flow_loop_dump (loop, stderr, loop_dump_aux, 1);
 }
@@ -10814,8 +10795,7 @@ debug_loop (loop)
 /* Call this function from the debugger to dump LOOPS.  */
 
 void
-debug_loops (loops)
-     const struct loops *loops;
+debug_loops (const struct loops *loops)
 {
   flow_loops_dump (loops, stderr, loop_dump_aux, 1);
 }