OSDN Git Service

* cpppch.c (cpp_valid_state): Unconditionally initialize nl.
[pf3gnuchains/gcc-fork.git] / gcc / loop.c
index d6b3a80..d7ae3ea 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 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -36,6 +36,8 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 
 #include "config.h"
 #include "system.h"
+#include "coretypes.h"
+#include "tm.h"
 #include "rtl.h"
 #include "tm_p.h"
 #include "function.h"
@@ -54,6 +56,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "predict.h"
 #include "insn-flags.h"
 #include "optabs.h"
+#include "cfgloop.h"
 
 /* Not really meaningful values, but at least something.  */
 #ifndef SIMULTANEOUS_PREFETCHES
@@ -80,7 +83,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #define PREFETCH_BLOCKS_BEFORE_LOOP_MIN  2
 
 /* 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.  */
@@ -169,10 +172,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.  */
 
@@ -205,6 +204,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 */
@@ -221,9 +223,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;
@@ -326,17 +328,18 @@ 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 int find_mem_in_note_1 PARAMS ((rtx *, void *));
+static rtx find_mem_in_note PARAMS ((rtx));
 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 void replace_loop_mems PARAMS ((rtx, rtx, rtx, int));
 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));
@@ -361,12 +364,6 @@ 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;
-
 typedef struct loop_replace_args
 {
   rtx match;
@@ -497,7 +494,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
@@ -522,7 +519,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
@@ -616,8 +613,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;
@@ -685,24 +680,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 (GET_CODE (p) == JUMP_INSN
       /* 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
@@ -772,6 +763,7 @@ scan_loop (loop, flags)
              int tem1 = 0;
              int tem2 = 0;
              int move_insn = 0;
+             int insert_temp = 0;
              rtx src = SET_SRC (set);
              rtx dependencies = 0;
 
@@ -801,7 +793,7 @@ scan_loop (loop, flags)
                    }
                }
 
-             /* For parallels, add any possible uses to the depencies, as
+             /* For parallels, add any possible uses to the dependencies, as
                 we can't move the insn without resolving them first.  */
              if (GET_CODE (PATTERN (p)) == PARALLEL)
                {
@@ -815,34 +807,49 @@ scan_loop (loop, flags)
                    }
                }
 
+             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).  */
+                  ! reg_in_basic_block_p (p, SET_DEST (set))
+                  /* 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...
+
+                     ??? 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.  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 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
-                         than the one where it is set (meaning that
-                         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 once
-                         the loop starts, or the value before the set is
-                         needed before the set occurs...
-
-                         ??? 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.  */
+             /* 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)))
+                          || GET_CODE (SET_SRC (set)) == REG
+                          || (CONSTANT_P (SET_SRC (set))
+                              && LEGITIMATE_CONSTANT_P (SET_SRC (set)))))
                ;
              else if ((tem = loop_invariant_p (loop, src))
                       && (dependencies == 0
@@ -933,6 +940,7 @@ scan_loop (loop, flags)
                  m->partial = 0;
                  m->move_insn = move_insn;
                  m->move_insn_first = 0;
+                 m->insert_temp = insert_temp;
                  m->is_equiv = (find_reg_note (p, REG_EQUIV, NULL_RTX) != 0);
                  m->savemode = VOIDmode;
                  m->regno = regno;
@@ -1017,6 +1025,7 @@ scan_loop (loop, flags)
                      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.
@@ -1115,10 +1124,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);
 
@@ -1470,6 +1481,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;
@@ -1482,6 +1494,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.  */
@@ -1885,6 +1898,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.  */
 
@@ -1955,10 +1972,22 @@ move_movables (loop, movables, threshold, insn_count)
                         insn stream.  */
                      while (p && GET_CODE (p) == NOTE)
                        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);
+                 emit_move_insn (m->insert_temp ? newreg : m->set_dest, 
+                                 m->set_src);
                  seq = get_insns ();
                  end_sequence ();
 
@@ -2128,6 +2157,16 @@ move_movables (loop, movables, threshold, insn_count)
                            set_unique_reg_note (i1, m->is_equiv ? REG_EQUIV
                                                     : REG_EQUAL, m->set_src);
                        }
+                     else if (m->insert_temp)
+                       {
+                         rtx *reg_map2 = (rtx *) 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));
 
@@ -2176,40 +2215,55 @@ move_movables (loop, movables, threshold, insn_count)
                         insn stream.  */
                      while (p && GET_CODE (p) == NOTE)
                        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.  */
 
@@ -2475,7 +2529,7 @@ 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. */
+  /* 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;
@@ -2884,7 +2938,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
@@ -3250,7 +3304,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;
@@ -3273,6 +3327,13 @@ 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 have always been created by the unroller and are set in
+        the loop, hence are never invariant.  */
+
+      if (REGNO (x) >= (unsigned) regs->num)
+       return 0;
+
       if (regs->array[REGNO (x)].set_in_loop < 0)
        return 2;
 
@@ -3621,7 +3682,7 @@ check_store (x, pat, data)
 \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.  */
@@ -4197,7 +4258,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);
@@ -4754,6 +4823,9 @@ 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 = NEXT_INSN (tv->insn);
              else if (auto_inc_opt == 1)
@@ -5538,7 +5610,7 @@ 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)
@@ -5661,6 +5733,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.  */
@@ -5698,6 +5771,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;
@@ -5743,7 +5827,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
@@ -5828,7 +5912,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
@@ -5863,6 +5950,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
@@ -5938,12 +6026,8 @@ check_final_value (loop, v)
      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.  */
 
@@ -5974,6 +6058,7 @@ check_final_value (loop, v)
       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
@@ -6686,7 +6771,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 intermost nodes.  */
          else if (GET_CODE (arg0) == PLUS)
            {
              /* (invar_0 + invar_1) * invar_2.  Distribute.  */
@@ -7332,21 +7417,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;
 }
@@ -7372,7 +7444,7 @@ check_ext_dependent_givs (bl, loop_info)
      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.  */
+     value is also amenable to optimization.  Not implemented.  */
   if (loop_info->n_iterations > 0
       && bl->initial_value
       && GET_CODE (bl->initial_value) == CONST_INT
@@ -7394,7 +7466,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;
@@ -7407,7 +7479,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)
@@ -7425,7 +7497,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)
@@ -8612,11 +8684,12 @@ 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')
        {
-         rtx note = find_reg_note (p, REG_LIBCALL, NULL_RTX);
+         note = find_reg_note (p, REG_LIBCALL, NULL_RTX);
 
          if (note)
            {
@@ -8634,6 +8707,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,
@@ -8645,6 +8720,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)
@@ -9435,11 +9516,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);
 }
@@ -9676,6 +9755,25 @@ loop_regs_scan (loop, extra_size)
 
       if (GET_CODE (insn) == CODE_LABEL || GET_CODE (insn) == JUMP_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 (GET_CODE (insn) == CALL_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
+                 && GET_CODE (reg = XEXP (op, 0)) == REG
+                 && rtx_varies_p (reg, 1))
+               regs->array[REGNO (reg)].may_not_optimize = 1;
+           }
+       }
     }
 
   /* Invalidate all hard registers clobbered by calls.  With one exception:
@@ -9941,7 +10039,7 @@ 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
@@ -10060,22 +10158,14 @@ load_mems (loop)
     {
       /* Now, we need to replace all references to the previous exit
         label with the new one.  */
-      rtx_pair rr;
+      replace_label_data rr;
       rr.r1 = end_label;
       rr.r2 = label;
+      rr.update_label_nuses = true;
 
       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;
        }
     }
 
@@ -10314,6 +10404,33 @@ 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 (x, data)
+     rtx *x;
+     void *data;
+{
+  if (*x != NULL_RTX && GET_CODE (*x) == MEM)
+    {
+      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 (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
@@ -10356,10 +10473,11 @@ replace_loop_mem (mem, data)
 }
 
 static void
-replace_loop_mems (insn, mem, reg)
+replace_loop_mems (insn, mem, reg, written)
      rtx insn;
      rtx mem;
      rtx reg;
+     int written;
 {
   loop_replace_args args;
 
@@ -10368,6 +10486,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
@@ -10405,35 +10543,6 @@ 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).  */
@@ -10513,7 +10622,7 @@ loop_insn_sink (loop, 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  */
+   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;