OSDN Git Service

Fix bad regexp
[pf3gnuchains/gcc-fork.git] / gcc / loop.c
index 990826a..5f18773 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 Free Software Foundation, Inc.
+   1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -53,6 +53,92 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "except.h"
 #include "toplev.h"
 #include "predict.h"
+#include "insn-flags.h"
+#include "optabs.h"
+
+/* Not really meaningful values, but at least something.  */
+#ifndef SIMULTANEOUS_PREFETCHES
+#define SIMULTANEOUS_PREFETCHES 3
+#endif
+#ifndef PREFETCH_BLOCK
+#define PREFETCH_BLOCK 32
+#endif
+#ifndef HAVE_prefetch
+#define HAVE_prefetch 0
+#define CODE_FOR_prefetch 0
+#define gen_prefetch(a,b,c) (abort(), NULL_RTX)
+#endif
+
+/* Give up the prefetch optimizations once we exceed a given threshhold.
+   It is unlikely that we would be able to optimize something in a loop
+   with so many detected prefetches.  */
+#define MAX_PREFETCHES 100
+/* The number of prefetch blocks that are beneficial to fetch at once before
+   a loop with a known (and low) iteration count.  */
+#define PREFETCH_BLOCKS_BEFORE_LOOP_MAX  6
+/* 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
+   defined in target-dependent files.  */
+
+/* Prefetch is worthwhile only when loads/stores are dense.  */
+#ifndef PREFETCH_ONLY_DENSE_MEM
+#define PREFETCH_ONLY_DENSE_MEM 1
+#endif
+
+/* Define what we mean by "dense" loads and stores; This value divided by 256
+   is the minimum percentage of memory references that worth prefetching.  */
+#ifndef PREFETCH_DENSE_MEM
+#define PREFETCH_DENSE_MEM 220
+#endif
+
+/* Do not prefetch for a loop whose iteration count is known to be low.  */
+#ifndef PREFETCH_NO_LOW_LOOPCNT
+#define PREFETCH_NO_LOW_LOOPCNT 1
+#endif
+
+/* Define what we mean by a "low" iteration count.  */
+#ifndef PREFETCH_LOW_LOOPCNT
+#define PREFETCH_LOW_LOOPCNT 32
+#endif
+
+/* Do not prefetch for a loop that contains a function call; such a loop is
+   probably not an internal loop.  */
+#ifndef PREFETCH_NO_CALL
+#define PREFETCH_NO_CALL 1
+#endif
+
+/* Do not prefetch accesses with an extreme stride.  */
+#ifndef PREFETCH_NO_EXTREME_STRIDE
+#define PREFETCH_NO_EXTREME_STRIDE 1
+#endif
+
+/* Define what we mean by an "extreme" stride.  */
+#ifndef PREFETCH_EXTREME_STRIDE
+#define PREFETCH_EXTREME_STRIDE 4096
+#endif
+
+/* Do not handle reversed order prefetches (negative stride).  */
+#ifndef PREFETCH_NO_REVERSE_ORDER
+#define PREFETCH_NO_REVERSE_ORDER 1
+#endif
+
+/* Prefetch even if the GIV is not always executed.  */
+#ifndef PREFETCH_NOT_ALWAYS
+#define PREFETCH_NOT_ALWAYS 0
+#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)))
@@ -61,6 +147,10 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 ((REGNO_LAST_LUID (REGNO) > INSN_LUID ((LOOP)->end) \
  || REGNO_FIRST_LUID (REGNO) < INSN_LUID ((LOOP)->start)))
 
+#define LOOP_REGNO_NREGS(REGNO, SET_DEST) \
+((REGNO) < FIRST_PSEUDO_REGISTER \
+ ? HARD_REGNO_NREGS ((REGNO), GET_MODE (SET_DEST)) : 1)
+
 
 /* Vector mapping INSN_UIDs to luids.
    The luids are like uids but increase monotonically always.
@@ -145,6 +235,7 @@ 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 *));
@@ -208,7 +299,7 @@ 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_dependant_givs PARAMS ((struct iv_class *,
+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,
@@ -262,6 +353,8 @@ 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 *));
@@ -356,8 +449,8 @@ loop_optimize (f, dumpfile, flags)
      FILE *dumpfile;
      int flags;
 {
-  register rtx insn;
-  register int i;
+  rtx insn;
+  int i;
   struct loops loops_data;
   struct loops *loops = &loops_data;
   struct loop_info *loops_info;
@@ -522,7 +615,7 @@ scan_loop (loop, flags)
 {
   struct loop_info *loop_info = LOOP_INFO (loop);
   struct loop_regs *regs = LOOP_REGS (loop);
-  register int i;
+  int i;
   rtx loop_start = loop->start;
   rtx loop_end = loop->end;
   rtx p;
@@ -671,6 +764,9 @@ scan_loop (loop, flags)
       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)
        {
          int tem1 = 0;
@@ -727,7 +823,7 @@ scan_loop (loop, flags)
                      something after this point in the loop might
                      depend on its value before the set).  */
                   ! reg_in_basic_block_p (p, SET_DEST (set))
-                  /* And the set is not guaranteed to be executed one
+                  /* And the set is not guaranteed to be executed once
                      the loop starts, or the value before the set is
                      needed before the set occurs...
 
@@ -761,8 +857,8 @@ scan_loop (loop, flags)
                   && ! ((maybe_never || call_passed)
                         && may_trap_p (src)))
            {
-             register struct movable *m;
-             register int regno = REGNO (SET_DEST (set));
+             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
@@ -807,10 +903,9 @@ scan_loop (loop, flags)
                    = replace_rtx (REG_NOTES (regs->array[regno].single_usage),
                                   SET_DEST (set), copy_rtx (SET_SRC (set)));
 
-                 PUT_CODE (p, NOTE);
-                 NOTE_LINE_NUMBER (p) = NOTE_INSN_DELETED;
-                 NOTE_SOURCE_FILE (p) = 0;
-                 regs->array[regno].set_in_loop = 0;
+                 delete_insn (p);
+                 for (i = 0; i < LOOP_REGNO_NREGS (regno, SET_DEST (set)); i++)
+                   regs->array[regno+i].set_in_loop = 0;
                  continue;
                }
 
@@ -840,7 +935,8 @@ scan_loop (loop, flags)
              m->savings = regs->array[regno].n_times_set;
              if (find_reg_note (p, REG_RETVAL, NULL_RTX))
                m->savings += libcall_benefit (p);
-             regs->array[regno].set_in_loop = move_insn ? -2 : -1;
+             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);
 
@@ -894,10 +990,10 @@ scan_loop (loop, flags)
                       == SET_DEST (set))
                   && !reg_mentioned_p (SET_DEST (set), SET_SRC (set1)))
            {
-             register int regno = REGNO (SET_DEST (set));
+             int regno = REGNO (SET_DEST (set));
              if (regs->array[regno].set_in_loop == 2)
                {
-                 register struct movable *m;
+                 struct movable *m;
                  m = (struct movable *) xmalloc (sizeof (struct movable));
                  m->next = 0;
                  m->insn = p;
@@ -941,7 +1037,8 @@ scan_loop (loop, flags)
                  m->match = 0;
                  m->lifetime = LOOP_REG_LIFETIME (loop, regno);
                  m->savings = 1;
-                 regs->array[regno].set_in_loop = -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);
                }
@@ -963,7 +1060,7 @@ scan_loop (loop, flags)
                  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.  */
+                 followed by a barrier then the loop_end.  */
                && ! (GET_CODE (p) == JUMP_INSN && JUMP_LABEL (p) == loop->top
                     && NEXT_INSN (NEXT_INSN (p)) == loop_end
                     && any_uncondjump_p (p)))
@@ -1007,7 +1104,25 @@ scan_loop (loop, flags)
      optimizing for code size.  */
 
   if (! optimize_size)
-    move_movables (loop, movables, threshold, insn_count);
+    {
+      move_movables (loop, movables, threshold, insn_count);
+
+      /* Recalculate regs->array if move_movables has created new
+        registers.  */
+      if (max_reg_num () > regs->num)
+       {
+         loop_regs_scan (loop, 0);
+         for (update_start = loop_start;
+              PREV_INSN (update_start)
+              && GET_CODE (PREV_INSN (update_start)) != CODE_LABEL;
+              update_start = PREV_INSN (update_start))
+           ;
+         update_end = NEXT_INSN (loop_end);
+
+         reg_scan_update (update_start, update_end, loop_max_reg);
+         loop_max_reg = max_reg_num ();
+       }
+    }
 
   /* Now candidates that still are negative are those not moved.
      Change regs->array[I].set_in_loop to indicate that those are not actually
@@ -1047,7 +1162,7 @@ scan_loop (loop, flags)
 
       if (update_end && GET_CODE (update_end) == CODE_LABEL
          && --LABEL_NUSES (update_end) == 0)
-       delete_insn (update_end);
+       delete_related_insns (update_end);
     }
 
 
@@ -1254,7 +1369,7 @@ static void
 ignore_some_movables (movables)
      struct loop_movables *movables;
 {
-  register struct movable *m, *m1;
+  struct movable *m, *m1;
 
   for (m = movables->head; m; m = m->next)
     {
@@ -1286,7 +1401,8 @@ static void
 force_movables (movables)
      struct loop_movables *movables;
 {
-  register struct movable *m, *m1;
+  struct movable *m, *m1;
+
   for (m1 = movables->head; m1; m1 = m1->next)
     /* Omit this if moving just the (SET (REG) 0) of a zero-extend.  */
     if (!m1->partial && !m1->done)
@@ -1326,19 +1442,22 @@ combine_movables (movables, regs)
      struct loop_movables *movables;
      struct loop_regs *regs;
 {
-  register struct movable *m;
+  struct movable *m;
   char *matched_regs = (char *) xmalloc (regs->num);
   enum machine_mode mode;
 
   /* Regs that are set more than once are not allowed to match
      or be matched.  I'm no longer sure why not.  */
+  /* Only pseudo registers are allowed to match or be matched,
+     since move_movables does not validate the change.  */
   /* Perhaps testing m->consec_sets would be more appropriate here?  */
 
   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->partial)
       {
-       register struct movable *m1;
+       struct movable *m1;
        int regno = m->regno;
 
        memset (matched_regs, 0, regs->num);
@@ -1349,6 +1468,7 @@ combine_movables (movables, regs)
        for (m1 = m->next; m1; m1 = m1->next)
          if (m != m1 && m1->match == 0
              && regs->array[m1->regno].n_times_set == 1
+             && m1->regno >= FIRST_PSEUDO_REGISTER
              /* A reg used outside the loop mustn't be eliminated.  */
              && !m1->global
              /* A reg used for zero-extending mustn't be eliminated.  */
@@ -1391,7 +1511,7 @@ combine_movables (movables, regs)
   for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT); mode != VOIDmode;
        mode = GET_MODE_WIDER_MODE (mode))
     {
-      register struct movable *m0 = 0;
+      struct movable *m0 = 0;
 
       /* Combine all the registers for extension from mode MODE.
         Don't combine any that are used outside this loop.  */
@@ -1399,7 +1519,8 @@ combine_movables (movables, regs)
        if (m->partial && ! m->global
            && mode == GET_MODE (SET_SRC (PATTERN (NEXT_INSN (m->insn)))))
          {
-           register struct movable *m1;
+           struct movable *m1;
+
            int first = REGNO_FIRST_LUID (m->regno);
            int last = REGNO_LAST_LUID (m->regno);
 
@@ -1493,11 +1614,11 @@ rtx_equal_for_loop_p (x, y, movables, regs)
      struct loop_movables *movables;
      struct loop_regs *regs;
 {
-  register int i;
-  register int j;
-  register struct movable *m;
-  register enum rtx_code code;
-  register const char *fmt;
+  int i;
+  int j;
+  struct movable *m;
+  enum rtx_code code;
+  const char *fmt;
 
   if (x == y)
     return 1;
@@ -1658,8 +1779,8 @@ move_movables (loop, movables, threshold, insn_count)
   struct loop_regs *regs = LOOP_REGS (loop);
   int nregs = regs->num;
   rtx new_start = 0;
-  register struct movable *m;
-  register rtx p;
+  struct movable *m;
+  rtx p;
   rtx loop_start = loop->start;
   rtx loop_end = loop->end;
   /* Map of pseudo-register replacements to handle combining
@@ -1710,8 +1831,8 @@ move_movables (loop, movables, threshold, insn_count)
                                                       m->insn))))
          && (! m->forces || m->forces->done))
        {
-         register int regno;
-         register rtx p;
+         int regno;
+         rtx p;
          int savings = m->savings;
 
          /* We have an insn that is safe to move.
@@ -1747,7 +1868,7 @@ move_movables (loop, movables, threshold, insn_count)
                  && regs->array[m->forces->regno].n_times_set == 1))
            {
              int count;
-             register struct movable *m1;
+             struct movable *m1;
              rtx first = NULL_RTX;
 
              /* Now move the insns that set the reg.  */
@@ -1831,9 +1952,9 @@ move_movables (loop, movables, threshold, insn_count)
 
                  i1 = loop_insn_hoist (loop, seq);
                  if (! find_reg_note (i1, REG_EQUAL, NULL_RTX))
-                   REG_NOTES (i1)
-                     = gen_rtx_EXPR_LIST (m->is_equiv ? REG_EQUIV : REG_EQUAL,
-                                          m->set_src, REG_NOTES (i1));
+                   set_unique_reg_note (i1,
+                                        m->is_equiv ? REG_EQUIV : REG_EQUAL,
+                                        m->set_src);
 
                  if (loop_dump_stream)
                    fprintf (loop_dump_stream, " moved to %d", INSN_UID (i1));
@@ -1936,6 +2057,7 @@ move_movables (loop, movables, threshold, insn_count)
                              if (temp == fn_address_insn)
                                fn_address_insn = i1;
                              REG_NOTES (i1) = REG_NOTES (temp);
+                             REG_NOTES (temp) = NULL;
                              delete_insn (temp);
                            }
                          if (new_start == 0)
@@ -1990,10 +2112,8 @@ move_movables (loop, movables, threshold, insn_count)
 
                          i1 = loop_insn_hoist (loop, seq);
                          if (! find_reg_note (i1, REG_EQUAL, NULL_RTX))
-                           REG_NOTES (i1)
-                             = gen_rtx_EXPR_LIST ((m->is_equiv ? REG_EQUIV
-                                                   : REG_EQUAL),
-                                                  m->set_src, REG_NOTES (i1));
+                           set_unique_reg_note (i1, m->is_equiv ? REG_EQUIV
+                                                    : REG_EQUAL, m->set_src);
                        }
                      else
                        i1 = loop_insn_hoist (loop, PATTERN (p));
@@ -2001,6 +2121,7 @@ move_movables (loop, movables, threshold, insn_count)
                      if (REG_NOTES (i1) == 0)
                        {
                          REG_NOTES (i1) = REG_NOTES (p);
+                         REG_NOTES (p) = NULL;
 
                          /* If there is a REG_EQUAL note present whose value
                             is not loop invariant, then delete it, since it
@@ -2057,7 +2178,11 @@ move_movables (loop, movables, threshold, insn_count)
 
              /* The reg set here is now invariant.  */
              if (! m->partial)
-               regs->array[regno].set_in_loop = 0;
+               {
+                 int i;
+                 for (i = 0; i < LOOP_REGNO_NREGS (regno, m->set_dest); i++)
+                   regs->array[regno+i].set_in_loop = 0;
+               }
 
              m->done = 1;
 
@@ -2103,16 +2228,12 @@ move_movables (loop, movables, threshold, insn_count)
                         and prevent further processing of it.  */
                      m1->done = 1;
 
-                     /* if library call, delete all insn except last, which
-                        is deleted below */
+                     /* if library call, delete all insns.  */
                      if ((temp = find_reg_note (m1->insn, REG_RETVAL,
                                                 NULL_RTX)))
-                       {
-                         for (temp = XEXP (temp, 0); temp != m1->insn;
-                              temp = NEXT_INSN (temp))
-                           delete_insn (temp);
-                       }
-                     delete_insn (m1->insn);
+                       delete_insn_chain (XEXP (temp, 0), m1->insn);
+                     else
+                       delete_insn (m1->insn);
 
                      /* Any other movable that loads the same register
                         MUST be moved.  */
@@ -2121,7 +2242,13 @@ move_movables (loop, movables, threshold, insn_count)
                      /* The reg merged here is now invariant,
                         if the reg it matches is invariant.  */
                      if (! m->partial)
-                       regs->array[m1->regno].set_in_loop = 0;
+                       {
+                         int i;
+                         for (i = 0;
+                              i < LOOP_REGNO_NREGS (regno, m1->set_dest);
+                              i++)
+                           regs->array[m1->regno+i].set_in_loop = 0;
+                       }
                    }
            }
          else if (loop_dump_stream)
@@ -2189,9 +2316,9 @@ static void
 replace_call_address (x, reg, addr)
      rtx x, reg, addr;
 {
-  register enum rtx_code code;
-  register int i;
-  register const char *fmt;
+  enum rtx_code code;
+  int i;
+  const char *fmt;
 
   if (x == 0)
     return;
@@ -2237,7 +2364,7 @@ replace_call_address (x, reg, addr)
        replace_call_address (XEXP (x, i), reg, addr);
       else if (fmt[i] == 'E')
        {
-         register int j;
+         int j;
          for (j = 0; j < XVECLEN (x, i); j++)
            replace_call_address (XVECEXP (x, i, j), reg, addr);
        }
@@ -2253,9 +2380,9 @@ count_nonfixed_reads (loop, x)
      const struct loop *loop;
      rtx x;
 {
-  register enum rtx_code code;
-  register int i;
-  register const char *fmt;
+  enum rtx_code code;
+  int i;
+  const char *fmt;
   int value;
 
   if (x == 0)
@@ -2290,7 +2417,7 @@ count_nonfixed_reads (loop, x)
        value += count_nonfixed_reads (loop, XEXP (x, i));
       if (fmt[i] == 'E')
        {
-         register int j;
+         int j;
          for (j = 0; j < XVECLEN (x, i); j++)
            value += count_nonfixed_reads (loop, XVECEXP (x, i, j));
        }
@@ -2308,7 +2435,7 @@ static void
 prescan_loop (loop)
      struct loop *loop;
 {
-  register int level = 1;
+  int level = 1;
   rtx insn;
   struct loop_info *loop_info = LOOP_INFO (loop);
   rtx start = loop->start;
@@ -2349,8 +2476,9 @@ prescan_loop (loop)
   for (insn = NEXT_INSN (start); insn != NEXT_INSN (end);
        insn = NEXT_INSN (insn))
     {
-      if (GET_CODE (insn) == NOTE)
+      switch (GET_CODE (insn))
        {
+       case NOTE:
          if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG)
            {
              ++level;
@@ -2358,24 +2486,76 @@ prescan_loop (loop)
              loop->level++;
            }
          else if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_END)
-           {
-             --level;
-           }
-       }
-      else if (GET_CODE (insn) == CALL_INSN)
-       {
+           --level;
+         break;
+
+       case CALL_INSN:
          if (! CONST_OR_PURE_CALL_P (insn))
            {
              loop_info->unknown_address_altered = 1;
              loop_info->has_nonconst_call = 1;
            }
+         else if (pure_call_p (insn))
+           loop_info->has_nonconst_call = 1;
          loop_info->has_call = 1;
-       }
-      else if (GET_CODE (insn) == INSN || GET_CODE (insn) == JUMP_INSN)
-       {
-         rtx label1 = NULL_RTX;
-         rtx label2 = NULL_RTX;
+         if (can_throw_internal (insn))
+           loop_info->has_multiple_exit_targets = 1;
+         break;
+
+       case JUMP_INSN:
+         if (! loop_info->has_multiple_exit_targets)
+           {
+             rtx set = pc_set (insn);
+
+             if (set)
+               {
+                 rtx src = SET_SRC (set);
+                 rtx label1, label2;
+
+                 if (GET_CODE (src) == IF_THEN_ELSE)
+                   {
+                     label1 = XEXP (src, 1);
+                     label2 = XEXP (src, 2);
+                   }
+                 else
+                   {
+                     label1 = src;
+                     label2 = NULL_RTX;
+                   }
+
+                 do
+                   {
+                     if (label1 && label1 != pc_rtx)
+                       {
+                         if (GET_CODE (label1) != LABEL_REF)
+                           {
+                             /* Something tricky.  */
+                             loop_info->has_multiple_exit_targets = 1;
+                             break;
+                           }
+                         else if (XEXP (label1, 0) != exit_target
+                                  && LABEL_OUTSIDE_LOOP_P (label1))
+                           {
+                             /* A jump outside the current loop.  */
+                             loop_info->has_multiple_exit_targets = 1;
+                             break;
+                           }
+                       }
+
+                     label1 = label2;
+                     label2 = NULL_RTX;
+                   }
+                 while (label1);
+               }
+             else
+               {
+                 /* A return, or something tricky.  */
+                 loop_info->has_multiple_exit_targets = 1;
+               }
+           }
+         /* FALLTHRU */
 
+       case INSN:
          if (volatile_refs_p (PATTERN (insn)))
            loop_info->has_volatile = 1;
 
@@ -2388,48 +2568,13 @@ prescan_loop (loop)
          if (! loop_info->first_loop_store_insn && loop_info->store_mems)
            loop_info->first_loop_store_insn = insn;
 
-         if (! loop_info->has_multiple_exit_targets
-             && GET_CODE (insn) == JUMP_INSN
-             && GET_CODE (PATTERN (insn)) == SET
-             && SET_DEST (PATTERN (insn)) == pc_rtx)
-           {
-             if (GET_CODE (SET_SRC (PATTERN (insn))) == IF_THEN_ELSE)
-               {
-                 label1 = XEXP (SET_SRC (PATTERN (insn)), 1);
-                 label2 = XEXP (SET_SRC (PATTERN (insn)), 2);
-               }
-             else
-               {
-                 label1 = SET_SRC (PATTERN (insn));
-               }
-
-             do
-               {
-                 if (label1 && label1 != pc_rtx)
-                   {
-                     if (GET_CODE (label1) != LABEL_REF)
-                       {
-                         /* Something tricky.  */
-                         loop_info->has_multiple_exit_targets = 1;
-                         break;
-                       }
-                     else if (XEXP (label1, 0) != exit_target
-                              && LABEL_OUTSIDE_LOOP_P (label1))
-                       {
-                         /* A jump outside the current loop.  */
-                         loop_info->has_multiple_exit_targets = 1;
-                         break;
-                       }
-                   }
+         if (flag_non_call_exceptions && can_throw_internal (insn))
+           loop_info->has_multiple_exit_targets = 1;
+         break;
 
-                 label1 = label2;
-                 label2 = NULL_RTX;
-               }
-             while (label1);
-           }
+       default:
+         break;
        }
-      else if (GET_CODE (insn) == RETURN)
-       loop_info->has_multiple_exit_targets = 1;
     }
 
   /* Now, rescan the loop, setting up the LOOP_MEMS array.  */
@@ -2468,6 +2613,17 @@ prescan_loop (loop)
     }
 }
 \f
+/* Invalidate all loops containing LABEL.  */
+
+static void
+invalidate_loops_containing_label (label)
+     rtx label;
+{
+  struct loop *loop;
+  for (loop = uid_loop[INSN_UID (label)]; loop; loop = loop->outer)
+    loop->invalid = 1;
+}
+
 /* Scan the function looking for loops.  Record the start and end of each loop.
    Also mark as invalid loops any loops that contain a setjmp or are branched
    to from outside the loop.  */
@@ -2554,23 +2710,12 @@ find_and_verify_loops (f, loops)
 
   /* Any loop containing a label used in an initializer must be invalidated,
      because it can be jumped into from anywhere.  */
-
   for (label = forced_labels; label; label = XEXP (label, 1))
-    {
-      for (loop = uid_loop[INSN_UID (XEXP (label, 0))];
-          loop; loop = loop->outer)
-       loop->invalid = 1;
-    }
+    invalidate_loops_containing_label (XEXP (label, 0));
 
   /* Any loop containing a label used for an exception handler must be
      invalidated, because it can be jumped into from anywhere.  */
-
-  for (label = exception_handler_labels; label; label = XEXP (label, 1))
-    {
-      for (loop = uid_loop[INSN_UID (XEXP (label, 0))];
-          loop; loop = loop->outer)
-       loop->invalid = 1;
-    }
+  for_each_eh_label (invalidate_loops_containing_label);
 
   /* Now scan all insn's in the function.  If any JUMP_INSN branches into a
      loop that it is not contained within, that loop is marked invalid.
@@ -2594,11 +2739,7 @@ find_and_verify_loops (f, loops)
          {
            rtx note = find_reg_note (insn, REG_LABEL, NULL_RTX);
            if (note)
-             {
-               for (loop = uid_loop[INSN_UID (XEXP (note, 0))];
-                    loop; loop = loop->outer)
-                 loop->invalid = 1;
-             }
+             invalidate_loops_containing_label (XEXP (note, 0));
          }
 
        if (GET_CODE (insn) != JUMP_INSN)
@@ -2729,7 +2870,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
-                          and a add a BARRIER before TARGET.
+                          and add a BARRIER before TARGET.
 
                           This creates an extra unconditional jump outside
                           the loop.  However, the benefits of removing rarely
@@ -2749,7 +2890,8 @@ find_and_verify_loops (f, loops)
 
                        /* Include the BARRIER after INSN and copy the
                           block after LOC.  */
-                       squeeze_notes (&new_label, &last_insn_to_move);
+                       if (squeeze_notes (&new_label, &last_insn_to_move))
+                         abort ();
                        reorder_insns (new_label, last_insn_to_move, loc);
 
                        /* All those insns are now in TARGET_LOOP.  */
@@ -2799,7 +2941,7 @@ find_and_verify_loops (f, loops)
                        if (JUMP_LABEL (insn) != 0
                            && (next_real_insn (JUMP_LABEL (insn))
                                == next_real_insn (insn)))
-                         delete_insn (insn);
+                         delete_related_insns (insn);
                      }
 
                    /* Continue the loop after where the conditional
@@ -2809,7 +2951,7 @@ find_and_verify_loops (f, loops)
                    insn = NEXT_INSN (cond_label);
 
                    if (--LABEL_NUSES (cond_label) == 0)
-                     delete_insn (cond_label);
+                     delete_related_insns (cond_label);
 
                    /* This loop will be continued with NEXT_INSN (insn).  */
                    insn = PREV_INSN (insn);
@@ -3062,13 +3204,13 @@ note_set_pseudo_multiple_uses (x, y, data)
 int
 loop_invariant_p (loop, x)
      const struct loop *loop;
-     register rtx x;
+     rtx x;
 {
   struct loop_info *loop_info = LOOP_INFO (loop);
   struct loop_regs *regs = LOOP_REGS (loop);
-  register int i;
-  register enum rtx_code code;
-  register const char *fmt;
+  int i;
+  enum rtx_code code;
+  const char *fmt;
   int conditional = 0;
   rtx mem_list_entry;
 
@@ -3108,7 +3250,7 @@ loop_invariant_p (loop, x)
         since the reg might be set by initialization within the loop.  */
 
       if ((x == frame_pointer_rtx || x == hard_frame_pointer_rtx
-          || x == arg_pointer_rtx)
+          || x == arg_pointer_rtx || x == pic_offset_table_rtx)
          && ! current_function_has_nonlocal_goto)
        return 1;
 
@@ -3166,7 +3308,7 @@ loop_invariant_p (loop, x)
        }
       else if (fmt[i] == 'E')
        {
-         register int j;
+         int j;
          for (j = 0; j < XVECLEN (x, i); j++)
            {
              int tem = loop_invariant_p (loop, XVECEXP (x, i, j));
@@ -3216,7 +3358,7 @@ consec_sets_invariant_p (loop, reg, n_sets, insn)
 
   while (count > 0)
     {
-      register enum rtx_code code;
+      enum rtx_code code;
       rtx set;
 
       p = NEXT_INSN (p);
@@ -3273,12 +3415,12 @@ all_sets_invariant_p (reg, insn, table)
      rtx reg, insn;
      short *table;
 {
-  register rtx p = insn;
-  register int regno = REGNO (reg);
+  rtx p = insn;
+  int regno = REGNO (reg);
 
   while (1)
     {
-      register enum rtx_code code;
+      enum rtx_code code;
       p = NEXT_INSN (p);
       code = GET_CODE (p);
       if (code == CODE_LABEL || code == JUMP_INSN)
@@ -3360,23 +3502,27 @@ count_one_set (regs, insn, x, last_set)
        dest = XEXP (dest, 0);
       if (GET_CODE (dest) == REG)
        {
-         register int regno = REGNO (dest);
-         /* If this is the first setting of this reg
-            in current basic block, and it was set before,
-            it must be set in two basic blocks, so it cannot
-            be moved out of the loop.  */
-         if (regs->array[regno].set_in_loop > 0
-             && last_set == 0)
-           regs->array[regno].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.
-            If so, neither one can be moved.  */
-         if (last_set[regno] != 0
-             && reg_used_between_p (dest, last_set[regno], insn))
-           regs->array[regno].may_not_optimize = 1;
-         if (regs->array[regno].set_in_loop < 127)
-           ++regs->array[regno].set_in_loop;
-         last_set[regno] = insn;
+         int i;
+         int regno = REGNO (dest);
+         for (i = 0; i < LOOP_REGNO_NREGS (regno, dest); i++)
+           {
+             /* If this is the first setting of this reg
+                in current basic block, and it was set before,
+                it must be set in two basic blocks, so it cannot
+                be moved out of the loop.  */
+             if (regs->array[regno].set_in_loop > 0
+                 && last_set == 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.
+                If so, neither one can be moved.  */
+             if (last_set[regno] != 0
+                 && reg_used_between_p (dest, last_set[regno], insn))
+               regs->array[regno+i].may_not_optimize = 1;
+             if (regs->array[regno+i].set_in_loop < 127)
+               ++regs->array[regno+i].set_in_loop;
+             last_set[regno+i] = insn;
+           }
        }
     }
 }
@@ -3412,6 +3558,553 @@ loop_reg_used_before_p (loop, set, insn)
   return 0;
 }
 \f
+
+/* Information we collect about arrays that we might want to prefetch.  */
+struct prefetch_info
+{
+  struct iv_class *class;      /* Class this prefetch is based on.  */
+  struct induction *giv;       /* GIV this prefetch is based on.  */
+  rtx base_address;            /* Start prefetching from this address plus
+                                  index.  */
+  HOST_WIDE_INT index;
+  HOST_WIDE_INT stride;                /* Prefetch stride in bytes in each
+                                  iteration.  */
+  unsigned int bytes_accesed;  /* Sum of sizes of all acceses 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
+                                  iteration counts and is 0xffffffff
+                                  otherwise.  */
+  unsigned int write : 1;      /* 1 for read/write prefetches.  */
+  unsigned int prefetch_in_loop : 1;
+                               /* 1 for those chosen for prefetching.  */
+  unsigned int prefetch_before_loop : 1;
+                               /* 1 for those chosen for prefetching.  */
+};
+
+/* Data used by check_store function.  */
+struct check_store_data
+{
+  rtx mem_address;
+  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));
+
+/* 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;
+{
+  struct check_store_data *d = (struct check_store_data *) data;
+
+  if ((GET_CODE (x) == MEM) && 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.
+
+   ??? 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;
+{
+  int i;
+  int j;
+  enum rtx_code code = GET_CODE (x);
+  const char *fmt;
+
+  if (x == y)
+    return 1;
+  if (code != GET_CODE (y))
+    return 0;
+
+  code = GET_CODE (x);
+
+  if (GET_RTX_CLASS (code) == 'c')
+    {
+      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.  */
+
+  fmt = GET_RTX_FORMAT (code);
+  for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
+    {
+      switch (fmt[i])
+       {
+       case 'w':
+         if (XWINT (x, i) != XWINT (y, i))
+           return 0;
+         break;
+
+       case 'i':
+         if (XINT (x, i) != XINT (y, i))
+           return 0;
+         break;
+
+       case 'E':
+         /* Two vectors must have the same length.  */
+         if (XVECLEN (x, i) != XVECLEN (y, i))
+           return 0;
+
+         /* And the corresponding elements must match.  */
+         for (j = 0; j < XVECLEN (x, i); j++)
+           if (rtx_equal_for_prefetch_p (XVECEXP (x, i, j),
+                                         XVECEXP (y, i, j)) == 0)
+             return 0;
+         break;
+
+       case 'e':
+         if (rtx_equal_for_prefetch_p (XEXP (x, i), XEXP (y, i)) == 0)
+           return 0;
+         break;
+
+       case 's':
+         if (strcmp (XSTR (x, i), XSTR (y, i)))
+           return 0;
+         break;
+
+       case 'u':
+         /* These are just backpointers, so they don't matter.  */
+         break;
+
+       case '0':
+         break;
+
+         /* It is believed that rtx's at this level will never
+            contain anything but integers and other rtx's,
+            except for within LABEL_REFs and SYMBOL_REFs.  */
+       default:
+         abort ();
+       }
+    }
+  return 1;
+}
+\f
+/* Remove constant addition value from the expression X (when present)
+   and return it.  */
+
+static HOST_WIDE_INT
+remove_constant_addition (x)
+     rtx *x;
+{
+  HOST_WIDE_INT addval = 0;
+  rtx exp = *x;
+
+  /* Avoid clobbering a shared CONST expression.  */
+  if (GET_CODE (exp) == CONST)
+    {
+      if (GET_CODE (XEXP (exp, 0)) == PLUS
+         && GET_CODE (XEXP (XEXP (exp, 0), 0)) == SYMBOL_REF
+         && GET_CODE (XEXP (XEXP (exp, 0), 1)) == CONST_INT)
+       {
+         *x = XEXP (XEXP (exp, 0), 0);
+         return INTVAL (XEXP (XEXP (exp, 0), 1));
+       }
+      return 0;
+    }
+
+  if (GET_CODE (exp) == CONST_INT)
+    {
+      addval = INTVAL (exp);
+      *x = const0_rtx;
+    }
+
+  /* For plus expression recurse on ourself.  */
+  else if (GET_CODE (exp) == PLUS)
+    {
+      addval += remove_constant_addition (&XEXP (exp, 0));
+      addval += remove_constant_addition (&XEXP (exp, 1));
+
+      /* In case our parameter was constant, remove extra zero from the
+        expression.  */
+      if (XEXP (exp, 0) == const0_rtx)
+        *x = XEXP (exp, 1);
+      else if (XEXP (exp, 1) == const0_rtx)
+        *x = XEXP (exp, 0);
+    }
+
+  return addval;
+}
+
+/* Attempt to identify accesses to arrays that are most likely to cause cache
+   misses, and emit prefetch instructions a few prefetch blocks forward.
+
+   To detect the arrays we use the GIV information that was collected by the
+   strength reduction pass.
+
+   The prefetch instructions are generated after the GIV information is done
+   and before the strength reduction process. The new GIVs are injected into
+   the strength reduction tables, so the prefetch addresses are optimized as
+   well.
+
+   GIVs are split into base address, stride, and constant addition values.
+   GIVs with the same address, stride and close addition values are combined
+   into a single prefetch.  Also writes to GIVs are detected, so that prefetch
+   for write instructions can be used for the block we write to, on machines
+   that support write prefetches.
+
+   Several heuristics are used to determine when to prefetch.  They are
+   controlled by defined symbols that can be overridden for each target.  */
+
+static void
+emit_prefetch_instructions (loop)
+     struct loop *loop;
+{
+  int num_prefetches = 0;
+  int num_real_prefetches = 0;
+  int num_real_write_prefetches = 0;
+  int ahead;
+  int i;
+  struct iv_class *bl;
+  struct induction *iv;
+  struct prefetch_info info[MAX_PREFETCHES];
+  struct loop_ivs *ivs = LOOP_IVS (loop);
+
+  if (!HAVE_prefetch)
+    return;
+
+  /* Consider only loops w/o calls.  When a call is done, the loop is probably
+     slow enough to read the memory.  */
+  if (PREFETCH_NO_CALL && LOOP_INFO (loop)->has_call)
+    {
+      if (loop_dump_stream)
+       fprintf (loop_dump_stream, "Prefetch: ignoring loop - has call.\n");
+
+      return;
+    }
+
+  if (PREFETCH_NO_LOW_LOOPCNT
+      && LOOP_INFO (loop)->n_iterations
+      && LOOP_INFO (loop)->n_iterations <= PREFETCH_LOW_LOOPCNT)
+    {
+      if (loop_dump_stream)
+       fprintf (loop_dump_stream,
+                "Prefetch: ignoring loop - not enought iterations.\n");
+      return;
+    }
+
+  /* Search all induction variables and pick those interesting for the prefetch
+     machinery.  */
+  for (bl = ivs->list; bl; bl = bl->next)
+    {
+      struct induction *biv = bl->biv, *biv1;
+      int basestride = 0;
+
+      biv1 = biv;
+
+      /* Expect all BIVs to be executed in each iteration.  This makes our
+        analysis more conservative.  */
+      while (biv1)
+       {
+         /* Discard non-constant additions that we can't handle well yet, and
+            BIVs that are executed multiple times; such BIVs ought to be
+            handled in the nested loop.  We accept not_every_iteration BIVs,
+            since these only result in larger strides and make our
+            heuristics more conservative.
+            ??? What does the last sentence mean?  */
+         if (GET_CODE (biv->add_val) != CONST_INT)
+           {
+             if (loop_dump_stream)
+               {
+                 fprintf (loop_dump_stream,
+                          "Prefetch: biv %i ignored: non-constant addition at insn %i:",
+                          REGNO (biv->src_reg), INSN_UID (biv->insn));
+                 print_rtl (loop_dump_stream, biv->add_val);
+                 fprintf (loop_dump_stream, "\n");
+               }
+             break;
+           }
+
+         if (biv->maybe_multiple)
+           {
+             if (loop_dump_stream)
+               {
+                 fprintf (loop_dump_stream,
+                          "Prefetch: biv %i ignored: maybe_multiple at insn %i:",
+                          REGNO (biv->src_reg), INSN_UID (biv->insn));
+                 print_rtl (loop_dump_stream, biv->add_val);
+                 fprintf (loop_dump_stream, "\n");
+               }
+             break;
+           }
+
+         basestride += INTVAL (biv1->add_val);
+         biv1 = biv1->next_iv;
+       }
+
+      if (biv1 || !basestride)
+       continue;
+
+      for (iv = bl->giv; iv; iv = iv->next_iv)
+       {
+         rtx address;
+         rtx temp;
+         HOST_WIDE_INT index = 0;
+         int add = 1;
+         HOST_WIDE_INT stride;
+         struct check_store_data d;
+         int size = GET_MODE_SIZE (GET_MODE (iv));
+
+         /* There are several reasons why an induction variable is not
+            interesting to us.  */
+         if (iv->giv_type != DEST_ADDR
+             /* We are interested only in constant stride memory references
+                in order to be able to compute density easily.  */
+             || GET_CODE (iv->mult_val) != CONST_INT
+             /* Don't handle reversed order prefetches, since they are usually
+                ineffective.  Later we may be able to reverse such BIVs.  */
+             || (PREFETCH_NO_REVERSE_ORDER
+                 && (stride = INTVAL (iv->mult_val) * basestride) < 0)
+             /* Prefetching of accesses with such an extreme stride is probably
+                not worthwhile, either.  */
+             || (PREFETCH_NO_EXTREME_STRIDE
+                 && stride > PREFETCH_EXTREME_STRIDE)
+             /* Ignore GIVs with varying add values; we can't predict the
+                value for the next iteration.  */
+             || !loop_invariant_p (loop, iv->add_val)
+             /* Ignore GIVs in the nested loops; they ought to have been
+                handled already.  */
+             || iv->maybe_multiple)
+           {
+             if (loop_dump_stream)
+               fprintf (loop_dump_stream, "Prefetch: Ignoring giv at %i\n",
+                        INSN_UID (iv->insn));
+             continue;
+           }
+
+         /* Determine the pointer to the basic array we are examining.  It is
+            the sum of the BIV's initial value and the GIV's add_val.  */
+         index = 0;
+
+         address = copy_rtx (iv->add_val);
+         temp = copy_rtx (bl->initial_value);
+
+         address = simplify_gen_binary (PLUS, Pmode, temp, address);
+         index = remove_constant_addition (&address);
+
+         index += size;
+         d.mem_write = 0;
+         d.mem_address = *iv->location;
+
+         /* When the GIV is not always executed, we might be better off by
+            not dirtying the cache pages.  */
+         if (PREFETCH_NOT_ALWAYS || iv->always_executed)
+           note_stores (PATTERN (iv->insn), check_store, &d);
+
+         /* Attempt to find another prefetch to the same array and see if we
+            can merge this one.  */
+         for (i = 0; i < num_prefetches; i++)
+           if (rtx_equal_for_prefetch_p (address, info[i].base_address)
+               && stride == info[i].stride)
+             {
+               /* In case both access same array (same location
+                  just with small difference in constant indexes), merge
+                  the prefetches.  Just do the later and the earlier will
+                  get prefetched from previous iteration.
+                  4096 is artificial threshold.  It should not be too small,
+                  but also not bigger than small portion of memory usually
+                  traversed by single loop.  */
+               if (index >= info[i].index && index - info[i].index < 4096)
+                 {
+                   info[i].write |= d.mem_write;
+                   info[i].bytes_accesed += size;
+                   info[i].index = index;
+                   info[i].giv = iv;
+                   info[i].class = bl;
+                   info[num_prefetches].base_address = address;
+                   add = 0;
+                   break;
+                 }
+
+               if (index < info[i].index && info[i].index - index < 4096)
+                 {
+                   info[i].write |= d.mem_write;
+                   info[i].bytes_accesed += size;
+                   add = 0;
+                   break;
+                 }
+             }
+
+         /* Merging failed.  */
+         if (add)
+           {
+             info[num_prefetches].giv = iv;
+             info[num_prefetches].class = bl;
+             info[num_prefetches].index = index;
+             info[num_prefetches].stride = stride;
+             info[num_prefetches].base_address = address;
+             info[num_prefetches].write = d.mem_write;
+             info[num_prefetches].bytes_accesed = size;
+             num_prefetches++;
+             if (num_prefetches >= MAX_PREFETCHES)
+               {
+                 if (loop_dump_stream)
+                   fprintf (loop_dump_stream,
+                            "Maximal number of prefetches exceeded.\n");
+                 return;
+               }
+           }
+       }
+    }
+
+  for (i = 0; i < num_prefetches; i++)
+    {
+      /* Attempt to calculate the number of bytes fetched by the loop.
+        Avoid overflow.  */
+      if (LOOP_INFO (loop)->n_iterations
+          && ((unsigned HOST_WIDE_INT) (0xffffffff / info[i].stride)
+             >= LOOP_INFO (loop)->n_iterations))
+       info[i].total_bytes = info[i].stride * LOOP_INFO (loop)->n_iterations;
+      else
+       info[i].total_bytes = 0xffffffff;
+
+      /* Prefetch is worthwhile only when the loads/stores are dense.  */
+      if (PREFETCH_ONLY_DENSE_MEM
+         && info[i].bytes_accesed * 256 / info[i].stride > PREFETCH_DENSE_MEM
+         && (info[i].total_bytes / PREFETCH_BLOCK
+             >= PREFETCH_BLOCKS_BEFORE_LOOP_MIN))
+       {
+         info[i].prefetch_before_loop = 1;
+         info[i].prefetch_in_loop
+           = (info[i].total_bytes / PREFETCH_BLOCK
+              > PREFETCH_BLOCKS_BEFORE_LOOP_MAX);
+       }
+      else
+        info[i].prefetch_in_loop = 0, info[i].prefetch_before_loop = 0;
+
+      if (info[i].prefetch_in_loop)
+       {
+         num_real_prefetches += ((info[i].stride + PREFETCH_BLOCK - 1)
+                                 / PREFETCH_BLOCK);
+         if (info[i].write)
+           num_real_write_prefetches
+             += (info[i].stride + PREFETCH_BLOCK - 1) / PREFETCH_BLOCK;
+       }
+    }
+
+  if (loop_dump_stream)
+    {
+      for (i = 0; i < num_prefetches; i++)
+       {
+         fprintf (loop_dump_stream, "Prefetch insn %i address: ",
+                  INSN_UID (info[i].giv->insn));
+         print_rtl (loop_dump_stream, info[i].base_address);
+         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,
+                  " density: %i%% total_bytes: %u%sin loop: %s before: %s\n",
+                  (int) (info[i].bytes_accesed * 100 / info[i].stride),
+                  info[i].total_bytes,
+                  info[i].write ? " read/write " : " read only ",
+                  info[i].prefetch_in_loop ? "yes" : "no",
+                  info[i].prefetch_before_loop ? "yes" : "no");
+       }
+
+      fprintf (loop_dump_stream, "Real prefetches needed: %i (write: %i)\n",
+              num_real_prefetches, num_real_write_prefetches);
+    }
+
+  if (!num_real_prefetches)
+    return;
+
+  ahead = SIMULTANEOUS_PREFETCHES / num_real_prefetches;
+
+  if (!ahead)
+    return;
+
+  for (i = 0; i < num_prefetches; i++)
+    {
+      if (info[i].prefetch_in_loop)
+       {
+         int y;
+
+         for (y = 0; y < ((info[i].stride + PREFETCH_BLOCK - 1)
+                          / PREFETCH_BLOCK); y++)
+           {
+             rtx loc = copy_rtx (*info[i].giv->location);
+             rtx insn;
+             int bytes_ahead = PREFETCH_BLOCK * (ahead + y);
+             rtx before_insn = info[i].giv->insn;
+             rtx prev_insn = PREV_INSN (info[i].giv->insn);
+
+             /* We can save some effort by offsetting the address on
+                architectures with offsettable memory references.  */
+             if (offsettable_address_p (0, VOIDmode, loc))
+               loc = plus_constant (loc, bytes_ahead);
+             else
+               {
+                 rtx reg = gen_reg_rtx (Pmode);
+                 loop_iv_add_mult_emit_before (loop, loc, const1_rtx,
+                                               GEN_INT (bytes_ahead), reg,
+                                               0, before_insn);
+                 loc = reg;
+               }
+
+             /* Make sure the address operand is valid for prefetch.  */
+             if (! (*insn_data[(int)CODE_FOR_prefetch].operand[0].predicate)
+                   (loc,
+                    insn_data[(int)CODE_FOR_prefetch].operand[0].mode))
+               loc = force_reg (Pmode, loc);
+             emit_insn_before (gen_prefetch (loc, GEN_INT (info[i].write),
+                                             GEN_INT (3)),
+                               before_insn);
+
+             /* Check all insns emitted and record the new GIV
+                information.  */
+             insn = NEXT_INSN (prev_insn);
+             while (insn != before_insn)
+               {
+                 insn = check_insn_for_givs (loop, insn,
+                                             info[i].giv->always_executed,
+                                             info[i].giv->maybe_multiple);
+                 insn = NEXT_INSN (insn);
+               }
+           }
+       }
+
+      if (info[i].prefetch_before_loop)
+       {
+         int y;
+
+         /* Emit INSNs before the loop to fetch the first cache lines.  */
+         for (y = 0;
+              (!info[i].prefetch_in_loop || y < ahead)
+              && y * PREFETCH_BLOCK < (int) info[i].total_bytes; y ++)
+           {
+             rtx reg = gen_reg_rtx (Pmode);
+             rtx loop_start = loop->start;
+             rtx add_val = simplify_gen_binary (PLUS, Pmode,
+                                                info[i].giv->add_val,
+                                                GEN_INT (y * PREFETCH_BLOCK));
+
+             loop_iv_add_mult_emit_before (loop, info[i].class->initial_value,
+                                           info[i].giv->mult_val,
+                                           add_val, reg, 0, loop_start);
+             emit_insn_before (gen_prefetch (reg, GEN_INT (info[i].write),
+                                             GEN_INT (3)),
+                               loop_start);
+           }
+       }
+    }
+
+  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
@@ -3779,7 +4472,7 @@ loop_givs_find (loop)
 
 /* For each giv for which we still don't know whether or not it is
    replaceable, check to see if it is replaceable because its final value
-   can be calculated.   */
+   can be calculated.  */
 
 static void
 loop_givs_check (loop)
@@ -4106,7 +4799,8 @@ loop_givs_rescan (loop, bl, reg_map)
                               v->mult_val, v->add_val, v->dest_reg);
       else if (v->final_value)
        loop_insn_sink_or_swim (loop,
-                               gen_move_insn (v->dest_reg, v->final_value));
+                               gen_load_of_final_value (v->dest_reg,
+                                                        v->final_value));
 
       if (loop_dump_stream)
        {
@@ -4298,6 +4992,11 @@ strength_reduce (loop, flags)
      fail if the iteration variable is a giv.  */
   loop_iterations (loop);
 
+#ifdef HAVE_prefetch
+  if (flags & LOOP_PREFETCH)
+    emit_prefetch_instructions (loop);
+#endif
+
   /* Now for each giv for which we still don't know whether or not it is
      replaceable, check to see if it is replaceable because its final value
      can be calculated.  This must be done after loop_iterations is called,
@@ -4334,7 +5033,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_dependant_givs (bl, loop_info);
+      check_ext_dependent_givs (bl, loop_info);
 
       /* Combine all giv's for this iv_class.  */
       combine_givs (regs, bl);
@@ -4458,13 +5157,19 @@ strength_reduce (loop, flags)
             value, so we don't need another one.  We can't calculate the
             proper final value for such a biv here anyways.  */
          if (bl->final_value && ! bl->reversed)
-             loop_insn_sink_or_swim (loop, gen_move_insn
-                                     (bl->biv->dest_reg, bl->final_value));
+             loop_insn_sink_or_swim (loop,
+                                     gen_load_of_final_value (bl->biv->dest_reg,
+                                                              bl->final_value));
 
          if (loop_dump_stream)
            fprintf (loop_dump_stream, "Reg %d: biv eliminated\n",
                     bl->regno);
        }
+      /* See above note wrt final_value.  But since we couldn't eliminate
+        the biv, we must set the value after the loop instead of before.  */
+      else if (bl->final_value && ! bl->reversed)
+       loop_insn_sink (loop, gen_load_of_final_value (bl->biv->dest_reg,
+                                                      bl->final_value));
     }
 
   /* Go through all the instructions in the loop, making all the
@@ -4511,7 +5216,8 @@ strength_reduce (loop, flags)
      collected.  Always unroll loops that would be as small or smaller
      unrolled than when rolled.  */
   if ((flags & LOOP_UNROLL)
-      || (loop_info->n_iterations > 0
+      || (!(flags & LOOP_FIRST_PASS)
+         && loop_info->n_iterations > 0
          && unrolled_insn_copies <= insn_count))
     unroll_loop (loop, insn_count, 1);
 
@@ -4523,13 +5229,13 @@ strength_reduce (loop, flags)
   /* 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)
-      && loop_info->n_iterations / loop_info->unroll_number > 1)
+  if (flags & LOOP_BCT)
     {
-      int n = loop_info->n_iterations / loop_info->unroll_number;
-      predict_insn (PREV_INSN (loop->end),
-                   PRED_LOOP_ITERATIONS,
-                   REG_BR_PROB_BASE - REG_BR_PROB_BASE / n);
+      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)
@@ -4652,7 +5358,7 @@ check_insn_for_givs (loop, p, not_every_iteration, maybe_multiple)
 
          record_giv (loop, v, p, src_reg, dest_reg, mult_val, add_val,
                      ext_val, benefit, DEST_REG, not_every_iteration,
-                     maybe_multiple, (rtx*)0);
+                     maybe_multiple, (rtx*) 0);
 
        }
     }
@@ -4726,9 +5432,9 @@ find_mem_givs (loop, x, insn, not_every_iteration, maybe_multiple)
      rtx insn;
      int not_every_iteration, maybe_multiple;
 {
-  register int i, j;
-  register enum rtx_code code;
-  register const char *fmt;
+  int i, j;
+  enum rtx_code code;
+  const char *fmt;
 
   if (x == 0)
     return;
@@ -4761,7 +5467,7 @@ find_mem_givs (loop, x, insn, not_every_iteration, maybe_multiple)
        /* This code used to disable creating GIVs with mult_val == 1 and
           add_val == 0.  However, this leads to lost optimizations when
           it comes time to combine a set of related DEST_ADDR GIVs, since
-          this one would not be seen.   */
+          this one would not be seen.  */
 
        if (general_induction_var (loop, XEXP (x, 0), &src_reg, &add_val,
                                   &mult_val, &ext_val, 1, &benefit,
@@ -4834,7 +5540,7 @@ record_biv (loop, v, insn, dest_reg, inc_val, mult_val, location,
   v->dest_reg = dest_reg;
   v->mult_val = mult_val;
   v->add_val = inc_val;
-  v->ext_dependant = NULL_RTX;
+  v->ext_dependent = NULL_RTX;
   v->location = location;
   v->mode = GET_MODE (dest_reg);
   v->always_computable = ! not_every_iteration;
@@ -4936,7 +5642,7 @@ record_giv (loop, v, insn, src_reg, dest_reg, mult_val, add_val, ext_val,
   v->dest_reg = dest_reg;
   v->mult_val = mult_val;
   v->add_val = add_val;
-  v->ext_dependant = ext_val;
+  v->ext_dependent = ext_val;
   v->benefit = benefit;
   v->location = location;
   v->cant_derive = 0;
@@ -5400,7 +6106,7 @@ update_giv_derive (loop, p)
 static int
 basic_induction_var (loop, x, mode, dest_reg, p, inc_val, mult_val, location)
      const struct loop *loop;
-     register rtx x;
+     rtx x;
      enum machine_mode mode;
      rtx dest_reg;
      rtx p;
@@ -5408,7 +6114,7 @@ basic_induction_var (loop, x, mode, dest_reg, p, inc_val, mult_val, location)
      rtx *mult_val;
      rtx **location;
 {
-  register enum rtx_code code;
+  enum rtx_code code;
   rtx *argp, arg;
   rtx insn, set = 0;
 
@@ -5444,13 +6150,13 @@ basic_induction_var (loop, x, mode, dest_reg, p, inc_val, mult_val, location)
       return 1;
 
     case SUBREG:
-      /* If this is a SUBREG for a promoted variable, check the inner
-        value.  */
-      if (SUBREG_PROMOTED_VAR_P (x))
-       return basic_induction_var (loop, SUBREG_REG (x),
-                                   GET_MODE (SUBREG_REG (x)),
-                                   dest_reg, p, inc_val, mult_val, location);
-      return 0;
+      /* If what's inside the SUBREG is a BIV, then the SUBREG.  This will
+        handle addition of promoted variables.
+        ??? The comment at the start of this function is wrong: promoted
+        variable increments don't look like it says they do.  */
+      return basic_induction_var (loop, SUBREG_REG (x),
+                                 GET_MODE (SUBREG_REG (x)),
+                                 dest_reg, p, inc_val, mult_val, location);
 
     case REG:
       /* If this register is assigned in a previous insn, look at its
@@ -5512,10 +6218,11 @@ basic_induction_var (loop, x, mode, dest_reg, p, inc_val, mult_val, location)
     case CONST:
       /* convert_modes aborts if we try to convert to or from CCmode, so just
          exclude that case.  It is very unlikely that a condition code value
-        would be a useful iterator anyways.  */
+        would be a useful iterator anyways.  convert_modes aborts if we try to
+        convert a float mode to non-float or vice versa too.  */
       if (loop->level == 1
-         && GET_MODE_CLASS (mode) != MODE_CC
-         && GET_MODE_CLASS (GET_MODE (dest_reg)) != MODE_CC)
+         && GET_MODE_CLASS (mode) == GET_MODE_CLASS (GET_MODE (dest_reg))
+         && 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);
@@ -5780,13 +6487,13 @@ simplify_giv_expr (loop, x, ext_val, benefit)
        tem = arg0, arg0 = arg1, arg1 = tem;
 
       if (GET_CODE (arg1) == PLUS)
-         return
-           simplify_giv_expr (loop,
-                              gen_rtx_PLUS (mode,
-                                            gen_rtx_PLUS (mode, arg0,
-                                                          XEXP (arg1, 0)),
-                                            XEXP (arg1, 1)),
-                              ext_val, benefit);
+       return
+         simplify_giv_expr (loop,
+                            gen_rtx_PLUS (mode,
+                                          gen_rtx_PLUS (mode, arg0,
+                                                        XEXP (arg1, 0)),
+                                          XEXP (arg1, 1)),
+                            ext_val, benefit);
 
       /* Now must have MULT + MULT.  Distribute if same biv, else not giv.  */
       if (GET_CODE (arg0) != MULT || GET_CODE (arg1) != MULT)
@@ -5997,12 +6704,12 @@ simplify_giv_expr (loop, x, ext_val, benefit)
            arg0 = simplify_giv_expr (loop, tem, ext_val, benefit);
            if (*ext_val)
              {
-               if (!v->ext_dependant)
+               if (!v->ext_dependent)
                  return arg0;
              }
            else
              {
-               *ext_val = v->ext_dependant;
+               *ext_val = v->ext_dependent;
                return arg0;
              }
            return 0;
@@ -6219,7 +6926,7 @@ consec_sets_giv (loop, first_benefit, p, src_reg, dest_reg,
   v->benefit = first_benefit;
   v->cant_derive = 0;
   v->derive_adjustment = 0;
-  v->ext_dependant = NULL_RTX;
+  v->ext_dependent = NULL_RTX;
 
   REG_IV_TYPE (ivs, REGNO (dest_reg)) = GENERAL_INDUCT;
   REG_IV_INFO (ivs, REGNO (dest_reg)) = v;
@@ -6482,7 +7189,7 @@ combine_givs_p (g1, g2)
 {
   rtx comb, ret;
 
-  /* With the introduction of ext dependant givs, we must care for modes.
+  /* With the introduction of ext dependent givs, we must care for modes.
      G2 must not use a wider mode than G1.  */
   if (GET_MODE_SIZE (g1->mode) < GET_MODE_SIZE (g2->mode))
     return NULL_RTX;
@@ -6528,12 +7235,12 @@ combine_givs_p (g1, g2)
   return NULL_RTX;
 }
 \f
-/* Check each extension dependant giv in this class to see if its
+/* Check each extension dependent giv in this class to see if its
    root biv is safe from wrapping in the interior mode, which would
    make the giv illegal.  */
 
 static void
-check_ext_dependant_givs (bl, loop_info)
+check_ext_dependent_givs (bl, loop_info)
      struct iv_class *bl;
      struct loop_info *loop_info;
 {
@@ -6618,9 +7325,9 @@ check_ext_dependant_givs (bl, loop_info)
 
   /* Invalidate givs that fail the tests.  */
   for (v = bl->giv; v; v = v->next_iv)
-    if (v->ext_dependant)
+    if (v->ext_dependent)
       {
-       enum rtx_code code = GET_CODE (v->ext_dependant);
+       enum rtx_code code = GET_CODE (v->ext_dependent);
        int ok = 0;
 
        switch (code)
@@ -6640,7 +7347,7 @@ check_ext_dependant_givs (bl, loop_info)
               derived GIV.  */
            if (se_ok && ze_ok)
              {
-               enum machine_mode outer_mode = GET_MODE (v->ext_dependant);
+               enum machine_mode outer_mode = GET_MODE (v->ext_dependent);
                unsigned HOST_WIDE_INT max = GET_MODE_MASK (outer_mode) >> 1;
 
                /* We know from the above that both endpoints are nonnegative,
@@ -6660,7 +7367,7 @@ check_ext_dependant_givs (bl, loop_info)
            if (loop_dump_stream)
              {
                fprintf (loop_dump_stream,
-                        "Verified ext dependant giv at %d of reg %d\n",
+                        "Verified ext dependent giv at %d of reg %d\n",
                         INSN_UID (v->insn), bl->regno);
              }
          }
@@ -6683,7 +7390,7 @@ check_ext_dependant_givs (bl, loop_info)
                  }
 
                fprintf (loop_dump_stream,
-                        "Failed ext dependant giv at %d, %s\n",
+                        "Failed ext dependent giv at %d, %s\n",
                         INSN_UID (v->insn), why);
              }
            v->ignore = 1;
@@ -6699,12 +7406,12 @@ extend_value_for_giv (v, value)
      struct induction *v;
      rtx value;
 {
-  rtx ext_dep = v->ext_dependant;
+  rtx ext_dep = v->ext_dependent;
 
   if (! ext_dep)
     return value;
 
-  /* Recall that check_ext_dependant_givs verified that the known bounds
+  /* Recall that check_ext_dependent_givs verified that the known bounds
      of a biv did not overflow or wrap with respect to the extension for
      the giv.  Therefore, constants need no additional adjustment.  */
   if (CONSTANT_P (value) && GET_MODE (value) == VOIDmode)
@@ -6851,6 +7558,13 @@ restart:
 
              g2->new_reg = can_combine[i * giv_count + j];
              g2->same = g1;
+             /* For destination, we now may replace by mem expression instead
+                of register.  This changes the costs considerably, so add the
+                compensation.  */
+             if (g2->giv_type == DEST_ADDR)
+               g2->benefit = (g2->benefit + reg_address_cost
+                              - address_cost (g2->new_reg,
+                              GET_MODE (g2->mem)));
              g1->combined_with++;
              g1->lifetime += g2->lifetime;
 
@@ -6952,9 +7666,9 @@ loop_regs_update (loop, seq)
     }
   else
     {
-      rtx set = single_set (seq);
-      if (set && GET_CODE (SET_DEST (set)) == REG)
-       record_base_value (REGNO (SET_DEST (set)), SET_SRC (set), 0);
+      if (GET_CODE (seq) == SET
+         && GET_CODE (SET_DEST (seq)) == REG)
+       record_base_value (REGNO (SET_DEST (seq)), SET_SRC (seq), 0);
     }
 }
 
@@ -6980,7 +7694,7 @@ loop_iv_add_mult_emit_before (loop, b, m, a, reg, before_bb, before_insn)
     }
 
   /* Use copy_rtx to prevent unexpected sharing of these rtx.  */
-  seq = gen_add_mult (copy_rtx (b), m, copy_rtx (a), reg);
+  seq = gen_add_mult (copy_rtx (b), copy_rtx (m), copy_rtx (a), reg);
 
   /* Increase the lifetime of any invariants moved further in code.  */
   update_reg_last_use (a, before_insn);
@@ -7008,7 +7722,7 @@ loop_iv_add_mult_sink (loop, b, m, a, reg)
   rtx seq;
 
   /* Use copy_rtx to prevent unexpected sharing of these rtx.  */
-  seq = gen_add_mult (copy_rtx (b), m, copy_rtx (a), reg);
+  seq = gen_add_mult (copy_rtx (b), copy_rtx (m), copy_rtx (a), reg);
 
   /* Increase the lifetime of any invariants moved further in code.
      ???? Is this really necessary?  */
@@ -7037,7 +7751,7 @@ loop_iv_add_mult_hoist (loop, b, m, a, reg)
   rtx seq;
 
   /* Use copy_rtx to prevent unexpected sharing of these rtx.  */
-  seq = gen_add_mult (copy_rtx (b), m, copy_rtx (a), reg);
+  seq = gen_add_mult (copy_rtx (b), copy_rtx (m), copy_rtx (a), reg);
 
   loop_insn_hoist (loop, seq);
 
@@ -7313,7 +8027,9 @@ check_dbra_loop (loop, insn_count)
         which is reversible.  */
       int reversible_mem_store = 1;
 
-      if (bl->giv_count == 0 && ! loop->exit_count)
+      if (bl->giv_count == 0
+         && !loop->exit_count
+         && !loop_info->has_multiple_exit_targets)
        {
          rtx bivreg = regno_reg_rtx[bl->regno];
          struct iv_class *blt;
@@ -7354,9 +8070,11 @@ check_dbra_loop (loop, insn_count)
                  }
              }
 
-         /* A biv has uses besides counting if it is used to set another biv.  */
+         /* A biv has uses besides counting if it is used to set
+            another biv.  */
          for (blt = ivs->list; blt; blt = blt->next)
-           if (blt->init_set && reg_mentioned_p (bivreg, SET_SRC (blt->init_set)))
+           if (blt->init_set
+               && reg_mentioned_p (bivreg, SET_SRC (blt->init_set)))
              {
                no_use_except_counting = 0;
                break;
@@ -7646,17 +8364,17 @@ check_dbra_loop (loop, insn_count)
              if ((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_move_insn (reg, final_value));
+               loop_insn_sink (loop, gen_load_of_final_value (reg, final_value));
 
              /* Delete compare/branch at end of loop.  */
-             delete_insn (PREV_INSN (loop_end));
+             delete_related_insns (PREV_INSN (loop_end));
              if (compare_and_branch == 2)
-               delete_insn (first_compare);
+               delete_related_insns (first_compare);
 
              /* Add new compare/branch insn at end of loop.  */
              start_sequence ();
              emit_cmp_and_jump_insns (reg, const0_rtx, cmp_code, NULL_RTX,
-                                      GET_MODE (reg), 0, 0,
+                                      GET_MODE (reg), 0,
                                       XEXP (jump_label, 0));
              tem = gen_sequence ();
              end_sequence ();
@@ -8308,8 +9026,8 @@ update_reg_last_use (x, insn)
     }
   else
     {
-      register int i, j;
-      register const char *fmt = GET_RTX_FORMAT (GET_CODE (x));
+      int i, j;
+      const char *fmt = GET_RTX_FORMAT (GET_CODE (x));
       for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--)
        {
          if (fmt[i] == 'e')
@@ -8419,7 +9137,7 @@ canonicalize_condition (insn, cond, reverse, earliest, want_reg)
 
       if ((prev = prev_nonnote_insn (prev)) == 0
          || GET_CODE (prev) != INSN
-         || FIND_REG_INC_NOTE (prev, 0))
+         || FIND_REG_INC_NOTE (prev, NULL_RTX))
        break;
 
       set = set_of (op0, prev);
@@ -8546,7 +9264,7 @@ canonicalize_condition (insn, cond, reverse, earliest, want_reg)
        {
        case LE:
          if ((unsigned HOST_WIDE_INT) const_val != max_val >> 1)
-           code = LT, op1 = GEN_INT (const_val + 1);
+           code = LT, op1 = gen_int_mode (const_val + 1, GET_MODE (op0));
          break;
 
        /* When cross-compiling, const_val might be sign-extended from
@@ -8555,17 +9273,17 @@ canonicalize_condition (insn, cond, reverse, earliest, want_reg)
          if ((HOST_WIDE_INT) (const_val & max_val)
              != (((HOST_WIDE_INT) 1
                   << (GET_MODE_BITSIZE (GET_MODE (op0)) - 1))))
-           code = GT, op1 = GEN_INT (const_val - 1);
+           code = GT, op1 = gen_int_mode (const_val - 1, GET_MODE (op0));
          break;
 
        case LEU:
          if (uconst_val < max_val)
-           code = LTU, op1 = GEN_INT (uconst_val + 1);
+           code = LTU, op1 = gen_int_mode (uconst_val + 1, GET_MODE (op0));
          break;
 
        case GEU:
          if (uconst_val != 0)
-           code = GTU, op1 = GEN_INT (uconst_val - 1);
+           code = GTU, op1 = gen_int_mode (uconst_val - 1, GET_MODE (op0));
          break;
 
        default:
@@ -8626,7 +9344,7 @@ get_condition_for_loop (loop, x)
      const struct loop *loop;
      rtx x;
 {
-  rtx comparison = get_condition (x, (rtx*)0);
+  rtx comparison = get_condition (x, (rtx*) 0);
 
   if (comparison == 0
       || ! loop_invariant_p (loop, XEXP (comparison, 0))
@@ -8805,7 +9523,7 @@ loop_regs_scan (loop, extra_size)
            count_one_set (regs, insn, PATTERN (insn), last_set);
          else if (GET_CODE (PATTERN (insn)) == PARALLEL)
            {
-             register int i;
+             int i;
              for (i = XVECLEN (PATTERN (insn), 0) - 1; i >= 0; i--)
                count_one_set (regs, insn, XVECEXP (PATTERN (insn), 0, i),
                               last_set);
@@ -8816,11 +9534,18 @@ loop_regs_scan (loop, extra_size)
        memset (last_set, 0, regs->num * sizeof (rtx));
     }
 
-  for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
-    {
-      regs->array[i].may_not_optimize = 1;
-      regs->array[i].set_in_loop = 1;
-    }
+  /* Invalidate all hard registers clobbered by calls.  With one exception:
+     a call-clobbered PIC register is still function-invariant for our
+     purposes, since we can hoist any PIC calculations out of the loop.
+     Thus the call to rtx_varies_p.  */
+  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))
+        {
+          regs->array[i].may_not_optimize = 1;
+          regs->array[i].set_in_loop = 1;
+        }
 
 #ifdef AVOID_CCMODE_COPIES
   /* Don't try to move insns which set CC registers if we should not
@@ -9059,9 +9784,20 @@ load_mems (loop)
                  && rtx_equal_p (SET_DEST (set), mem))
                SET_REGNO_REG_SET (&store_copies, REGNO (SET_SRC (set)));
 
-             /* Replace the memory reference with the shadow register.  */
-             replace_loop_mems (p, loop_info->mems[i].mem,
-                                loop_info->mems[i].reg);
+             /* If this is a call which uses / clobbers this memory
+                location, we must not change the interface here.  */
+             if (GET_CODE (p) == CALL_INSN
+                 && reg_mentioned_p (loop_info->mems[i].mem,
+                                     CALL_INSN_FUNCTION_USAGE (p)))
+               {
+                 cancel_changes (0);
+                 loop_info->mems[i].optimize = 0;
+                 break;
+               }
+             else
+               /* Replace the memory reference with the shadow register.  */
+               replace_loop_mems (p, loop_info->mems[i].mem,
+                                  loop_info->mems[i].reg);
            }
 
          if (GET_CODE (p) == CODE_LABEL
@@ -9069,7 +9805,9 @@ load_mems (loop)
            maybe_never = 1;
        }
 
-      if (! apply_change_group ())
+      if (! loop_info->mems[i].optimize)
+       ; /* We found we couldn't do the replacement, so do nothing.  */
+      else if (! apply_change_group ())
        /* We couldn't replace all occurrences of the MEM.  */
        loop_info->mems[i].optimize = 0;
       else
@@ -9131,9 +9869,7 @@ load_mems (loop)
            }
 
          if (const_equiv)
-           REG_NOTES (set) = gen_rtx_EXPR_LIST (REG_EQUAL,
-                                                copy_rtx (const_equiv->loc),
-                                                REG_NOTES (set));
+           set_unique_reg_note (set, REG_EQUAL, copy_rtx (const_equiv->loc));
 
          if (written)
            {
@@ -9333,11 +10069,10 @@ loop_delete_insns (first, last)
 {
   while (1)
     {
-      PUT_CODE (first, NOTE);
-      NOTE_LINE_NUMBER (first) = NOTE_INSN_DELETED;
       if (loop_dump_stream)
        fprintf (loop_dump_stream, ", deleting init_insn (%d)",
                 INSN_UID (first));
+      delete_insn (first);
 
       /* If this was the LAST instructions we're supposed to delete,
         we're done.  */
@@ -9633,6 +10368,21 @@ loop_insn_sink (loop, 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  */
+static rtx
+gen_load_of_final_value (reg, final_value)
+     rtx reg, 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 ();
+  end_sequence ();
+  return seq;
+}
 
 /* If the loop has multiple exits, emit insn for PATTERN before the
    loop to ensure that it will always be executed no matter how the
@@ -9793,9 +10543,9 @@ loop_giv_dump (v, file, verbose)
   if (v->no_const_addval)
     fprintf (file, " ncav");
 
-  if (v->ext_dependant)
+  if (v->ext_dependent)
     {
-      switch (GET_CODE (v->ext_dependant))
+      switch (GET_CODE (v->ext_dependent))
        {
        case SIGN_EXTEND:
          fprintf (file, " ext se");
@@ -9805,7 +10555,7 @@ loop_giv_dump (v, file, verbose)
          break;
        case TRUNCATE:
          fprintf (file, " ext tr");
-             break;
+         break;
        default:
          abort ();
        }