OSDN Git Service

Update.
[pf3gnuchains/gcc-fork.git] / gcc / sched.c
index 1fa338f..2cd9d12 100644 (file)
@@ -1,5 +1,5 @@
 /* Instruction scheduling pass.
-   Copyright (C) 1992, 93-96, 1997 Free Software Foundation, Inc.
+   Copyright (C) 1992, 93-97, 1998 Free Software Foundation, Inc.
    Contributed by Michael Tiemann (tiemann@cygnus.com)
    Enhanced by, and currently maintained by, Jim Wilson (wilson@cygnus.com)
 
@@ -117,8 +117,8 @@ Boston, MA 02111-1307, USA.  */
    other NOTE insns are grouped in their same relative order at the
    beginning of basic blocks that have been scheduled.  */
 \f
-#include <stdio.h>
 #include "config.h"
+#include "system.h"
 #include "rtl.h"
 #include "basic-block.h"
 #include "regs.h"
@@ -127,6 +127,9 @@ Boston, MA 02111-1307, USA.  */
 #include "insn-config.h"
 #include "insn-attr.h"
 
+extern char *reg_known_equiv_p;
+extern rtx *reg_known_value;
+
 #ifdef INSN_SCHEDULING
 /* Arrays set up by scheduling for the same respective purposes as
    similar-named arrays set up by flow analysis.  We work with these
@@ -176,7 +179,7 @@ static unsigned int *insn_blockage;
 #define UNIT_BLOCKED(B) ((B) >> (2 * BLOCKAGE_BITS))
 #define BLOCKAGE_RANGE(B) \
   (((((B) >> BLOCKAGE_BITS) & BLOCKAGE_MASK) << (HOST_BITS_PER_INT / 2)) \
-   | (B) & BLOCKAGE_MASK)
+   | ((B) & BLOCKAGE_MASK))
 
 /* Encodings of the `<name>_unit_blockage_range' function.  */
 #define MIN_BLOCKAGE_COST(R) ((R) >> (HOST_BITS_PER_INT / 2))
@@ -261,7 +264,7 @@ static rtx dead_notes;
    The transition (R->S) is implemented in the scheduling loop in
    `schedule_block' when the best insn to schedule is chosen.
    The transition (R->Q) is implemented in `schedule_select' when an
-   insn is found to to have a function unit conflict with the already
+   insn is found to have a function unit conflict with the already
    committed insns.
    The transitions (P->R and P->Q) are implemented in `schedule_insn' as
    insns move from the ready list to the scheduled list.
@@ -295,11 +298,6 @@ struct sometimes
 };
 
 /* Forward declarations.  */
-static rtx canon_rtx                   PROTO((rtx));
-static int rtx_equal_for_memref_p      PROTO((rtx, rtx));
-static rtx find_symbolic_term          PROTO((rtx));
-static int memrefs_conflict_p          PROTO((int, rtx, int, rtx,
-                                              HOST_WIDE_INT));
 static void add_dependence             PROTO((rtx, rtx, enum reg_note));
 static void remove_dependence          PROTO((rtx, rtx));
 static rtx find_insn_list              PROTO((rtx, rtx));
@@ -321,10 +319,10 @@ static void sched_analyze_2               PROTO((rtx, rtx));
 static void sched_analyze_insn         PROTO((rtx, rtx, rtx));
 static int sched_analyze               PROTO((rtx, rtx));
 static void sched_note_set             PROTO((int, rtx, int));
-static int rank_for_schedule           PROTO((rtx *, rtx *));
+static int rank_for_schedule           PROTO((const GENERIC_PTR, const GENERIC_PTR));
 static void swap_sort                  PROTO((rtx *, int));
 static void queue_insn                 PROTO((rtx, int));
-static int birthing_insn               PROTO((rtx));
+static int birthing_insn_p             PROTO((rtx));
 static void adjust_priority            PROTO((rtx));
 static int schedule_insn               PROTO((rtx, rtx *, int, int));
 static int schedule_select             PROTO((rtx *, int, int, FILE *));
@@ -349,567 +347,6 @@ void schedule_insns       PROTO((FILE *));
 \f
 #define SIZE_FOR_MODE(X) (GET_MODE_SIZE (GET_MODE (X)))
 
-/* Vector indexed by N giving the initial (unchanging) value known
-   for pseudo-register N.  */
-static rtx *reg_known_value;
-
-/* Vector recording for each reg_known_value whether it is due to a
-   REG_EQUIV note.  Future passes (viz., reload) may replace the
-   pseudo with the equivalent expression and so we account for the
-   dependences that would be introduced if that happens.  */
-/* ??? This is a problem only on the Convex.  The REG_EQUIV notes created in
-   assign_parms mention the arg pointer, and there are explicit insns in the
-   RTL that modify the arg pointer.  Thus we must ensure that such insns don't
-   get scheduled across each other because that would invalidate the REG_EQUIV
-   notes.  One could argue that the REG_EQUIV notes are wrong, but solving
-   the problem in the scheduler will likely give better code, so we do it
-   here.  */
-static char *reg_known_equiv_p;
-
-/* Indicates number of valid entries in reg_known_value.  */
-static int reg_known_value_size;
-
-static rtx
-canon_rtx (x)
-     rtx x;
-{
-  /* Recursively look for equivalences.  */
-  if (GET_CODE (x) == REG && REGNO (x) >= FIRST_PSEUDO_REGISTER
-      && REGNO (x) <= reg_known_value_size)
-    return reg_known_value[REGNO (x)] == x
-      ? x : canon_rtx (reg_known_value[REGNO (x)]);
-  else if (GET_CODE (x) == PLUS)
-    {
-      rtx x0 = canon_rtx (XEXP (x, 0));
-      rtx x1 = canon_rtx (XEXP (x, 1));
-
-      if (x0 != XEXP (x, 0) || x1 != XEXP (x, 1))
-       {
-         /* We can tolerate LO_SUMs being offset here; these
-            rtl are used for nothing other than comparisons.  */
-         if (GET_CODE (x0) == CONST_INT)
-           return plus_constant_for_output (x1, INTVAL (x0));
-         else if (GET_CODE (x1) == CONST_INT)
-           return plus_constant_for_output (x0, INTVAL (x1));
-         return gen_rtx (PLUS, GET_MODE (x), x0, x1);
-       }
-    }
-  /* This gives us much better alias analysis when called from
-     the loop optimizer.   Note we want to leave the original
-     MEM alone, but need to return the canonicalized MEM with
-     all the flags with their original values.  */
-  else if (GET_CODE (x) == MEM)
-    {
-      rtx copy = copy_rtx (x);
-      XEXP (copy, 0) = canon_rtx (XEXP (copy, 0));
-      x = copy;
-    }
-  return x;
-}
-
-/* Set up all info needed to perform alias analysis on memory references.  */
-
-void
-init_alias_analysis ()
-{
-  int maxreg = max_reg_num ();
-  rtx insn;
-  rtx note;
-  rtx set;
-
-  reg_known_value_size = maxreg;
-
-  reg_known_value
-    = (rtx *) oballoc ((maxreg-FIRST_PSEUDO_REGISTER) * sizeof (rtx))
-      - FIRST_PSEUDO_REGISTER;
-  bzero ((char *) (reg_known_value + FIRST_PSEUDO_REGISTER),
-        (maxreg-FIRST_PSEUDO_REGISTER) * sizeof (rtx));
-
-  reg_known_equiv_p
-    = (char *) oballoc ((maxreg -FIRST_PSEUDO_REGISTER) * sizeof (char))
-      - FIRST_PSEUDO_REGISTER;
-  bzero (reg_known_equiv_p + FIRST_PSEUDO_REGISTER,
-        (maxreg - FIRST_PSEUDO_REGISTER) * sizeof (char));
-
-  /* Fill in the entries with known constant values.  */
-  for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
-    if ((set = single_set (insn)) != 0
-       && GET_CODE (SET_DEST (set)) == REG
-       && REGNO (SET_DEST (set)) >= FIRST_PSEUDO_REGISTER
-       && (((note = find_reg_note (insn, REG_EQUAL, 0)) != 0
-            && REG_N_SETS (REGNO (SET_DEST (set))) == 1)
-           || (note = find_reg_note (insn, REG_EQUIV, NULL_RTX)) != 0)
-       && GET_CODE (XEXP (note, 0)) != EXPR_LIST)
-      {
-       int regno = REGNO (SET_DEST (set));
-       reg_known_value[regno] = XEXP (note, 0);
-       reg_known_equiv_p[regno] = REG_NOTE_KIND (note) == REG_EQUIV;
-      }
-
-  /* Fill in the remaining entries.  */
-  while (--maxreg >= FIRST_PSEUDO_REGISTER)
-    if (reg_known_value[maxreg] == 0)
-      reg_known_value[maxreg] = regno_reg_rtx[maxreg];
-}
-
-/* Return 1 if X and Y are identical-looking rtx's.
-
-   We use the data in reg_known_value above to see if two registers with
-   different numbers are, in fact, equivalent.  */
-
-static int
-rtx_equal_for_memref_p (x, y)
-     rtx x, y;
-{
-  register int i;
-  register int j;
-  register enum rtx_code code;
-  register char *fmt;
-
-  if (x == 0 && y == 0)
-    return 1;
-  if (x == 0 || y == 0)
-    return 0;
-  x = canon_rtx (x);
-  y = canon_rtx (y);
-
-  if (x == y)
-    return 1;
-
-  code = GET_CODE (x);
-  /* Rtx's of different codes cannot be equal.  */
-  if (code != GET_CODE (y))
-    return 0;
-
-  /* (MULT:SI x y) and (MULT:HI x y) are NOT equivalent.
-     (REG:SI x) and (REG:HI x) are NOT equivalent.  */
-
-  if (GET_MODE (x) != GET_MODE (y))
-    return 0;
-
-  /* REG, LABEL_REF, and SYMBOL_REF can be compared nonrecursively.  */
-
-  if (code == REG)
-    return REGNO (x) == REGNO (y);
-  if (code == LABEL_REF)
-    return XEXP (x, 0) == XEXP (y, 0);
-  if (code == SYMBOL_REF)
-    return XSTR (x, 0) == XSTR (y, 0);
-
-  /* For commutative operations, the RTX match if the operand match in any
-     order.  Also handle the simple binary and unary cases without a loop.  */
-  if (code == EQ || code == NE || GET_RTX_CLASS (code) == 'c')
-    return ((rtx_equal_for_memref_p (XEXP (x, 0), XEXP (y, 0))
-            && rtx_equal_for_memref_p (XEXP (x, 1), XEXP (y, 1)))
-           || (rtx_equal_for_memref_p (XEXP (x, 0), XEXP (y, 1))
-               && rtx_equal_for_memref_p (XEXP (x, 1), XEXP (y, 0))));
-  else if (GET_RTX_CLASS (code) == '<' || GET_RTX_CLASS (code) == '2')
-    return (rtx_equal_for_memref_p (XEXP (x, 0), XEXP (y, 0))
-           && rtx_equal_for_memref_p (XEXP (x, 1), XEXP (y, 1)));
-  else if (GET_RTX_CLASS (code) == '1')
-    return rtx_equal_for_memref_p (XEXP (x, 0), XEXP (y, 0));
-
-  /* Compare the elements.  If any pair of corresponding elements
-     fail to match, return 0 for the whole things.  */
-
-  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 'n':
-       case 'i':
-         if (XINT (x, i) != XINT (y, i))
-           return 0;
-         break;
-
-       case 'V':
-       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_memref_p (XVECEXP (x, i, j), XVECEXP (y, i, j)) == 0)
-             return 0;
-         break;
-
-       case 'e':
-         if (rtx_equal_for_memref_p (XEXP (x, i), XEXP (y, i)) == 0)
-           return 0;
-         break;
-
-       case 'S':
-       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;
-}
-
-/* Given an rtx X, find a SYMBOL_REF or LABEL_REF within
-   X and return it, or return 0 if none found.  */
-
-static rtx
-find_symbolic_term (x)
-     rtx x;
-{
-  register int i;
-  register enum rtx_code code;
-  register char *fmt;
-
-  code = GET_CODE (x);
-  if (code == SYMBOL_REF || code == LABEL_REF)
-    return x;
-  if (GET_RTX_CLASS (code) == 'o')
-    return 0;
-
-  fmt = GET_RTX_FORMAT (code);
-  for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
-    {
-      rtx t;
-
-      if (fmt[i] == 'e')
-       {
-         t = find_symbolic_term (XEXP (x, i));
-         if (t != 0)
-           return t;
-       }
-      else if (fmt[i] == 'E')
-       break;
-    }
-  return 0;
-}
-
-/* Return nonzero if X and Y (memory addresses) could reference the
-   same location in memory.  C is an offset accumulator.  When
-   C is nonzero, we are testing aliases between X and Y + C.
-   XSIZE is the size in bytes of the X reference,
-   similarly YSIZE is the size in bytes for Y.
-
-   If XSIZE or YSIZE is zero, we do not know the amount of memory being
-   referenced (the reference was BLKmode), so make the most pessimistic
-   assumptions.
-
-   We recognize the following cases of non-conflicting memory:
-
-       (1) addresses involving the frame pointer cannot conflict
-           with addresses involving static variables.
-       (2) static variables with different addresses cannot conflict.
-
-   Nice to notice that varying addresses cannot conflict with fp if no
-   local variables had their addresses taken, but that's too hard now.  */
-
-/* ??? In Fortran, references to a array parameter can never conflict with
-   another array parameter.  */
-
-static int
-memrefs_conflict_p (xsize, x, ysize, y, c)
-     rtx x, y;
-     int xsize, ysize;
-     HOST_WIDE_INT c;
-{
-  if (GET_CODE (x) == HIGH)
-    x = XEXP (x, 0);
-  else if (GET_CODE (x) == LO_SUM)
-    x = XEXP (x, 1);
-  else
-    x = canon_rtx (x);
-  if (GET_CODE (y) == HIGH)
-    y = XEXP (y, 0);
-  else if (GET_CODE (y) == LO_SUM)
-    y = XEXP (y, 1);
-  else
-    y = canon_rtx (y);
-
-  if (rtx_equal_for_memref_p (x, y))
-    return (xsize == 0 || ysize == 0
-           || (c >= 0 && xsize > c) || (c < 0 && ysize+c > 0));
-
-  if (y == frame_pointer_rtx || y == hard_frame_pointer_rtx
-      || y == stack_pointer_rtx)
-    {
-      rtx t = y;
-      int tsize = ysize;
-      y = x; ysize = xsize;
-      x = t; xsize = tsize;
-    }
-
-  if (x == frame_pointer_rtx || x == hard_frame_pointer_rtx
-      || x == stack_pointer_rtx)
-    {
-      rtx y1;
-
-      if (CONSTANT_P (y))
-       return 0;
-
-      if (GET_CODE (y) == PLUS
-         && canon_rtx (XEXP (y, 0)) == x
-         && (y1 = canon_rtx (XEXP (y, 1)))
-         && GET_CODE (y1) == CONST_INT)
-       {
-         c += INTVAL (y1);
-         return (xsize == 0 || ysize == 0
-                 || (c >= 0 && xsize > c) || (c < 0 && ysize+c > 0));
-       }
-
-      if (GET_CODE (y) == PLUS
-         && (y1 = canon_rtx (XEXP (y, 0)))
-         && CONSTANT_P (y1))
-       return 0;
-
-      return 1;
-    }
-
-  if (GET_CODE (x) == PLUS)
-    {
-      /* The fact that X is canonicalized means that this
-        PLUS rtx is canonicalized.  */
-      rtx x0 = XEXP (x, 0);
-      rtx x1 = XEXP (x, 1);
-
-      if (GET_CODE (y) == PLUS)
-       {
-         /* The fact that Y is canonicalized means that this
-            PLUS rtx is canonicalized.  */
-         rtx y0 = XEXP (y, 0);
-         rtx y1 = XEXP (y, 1);
-
-         if (rtx_equal_for_memref_p (x1, y1))
-           return memrefs_conflict_p (xsize, x0, ysize, y0, c);
-         if (rtx_equal_for_memref_p (x0, y0))
-           return memrefs_conflict_p (xsize, x1, ysize, y1, c);
-         if (GET_CODE (x1) == CONST_INT)
-           if (GET_CODE (y1) == CONST_INT)
-             return memrefs_conflict_p (xsize, x0, ysize, y0,
-                                        c - INTVAL (x1) + INTVAL (y1));
-           else
-             return memrefs_conflict_p (xsize, x0, ysize, y, c - INTVAL (x1));
-         else if (GET_CODE (y1) == CONST_INT)
-           return memrefs_conflict_p (xsize, x, ysize, y0, c + INTVAL (y1));
-
-         /* Handle case where we cannot understand iteration operators,
-            but we notice that the base addresses are distinct objects.  */
-         x = find_symbolic_term (x);
-         if (x == 0)
-           return 1;
-         y = find_symbolic_term (y);
-         if (y == 0)
-           return 1;
-         return rtx_equal_for_memref_p (x, y);
-       }
-      else if (GET_CODE (x1) == CONST_INT)
-       return memrefs_conflict_p (xsize, x0, ysize, y, c - INTVAL (x1));
-    }
-  else if (GET_CODE (y) == PLUS)
-    {
-      /* The fact that Y is canonicalized means that this
-        PLUS rtx is canonicalized.  */
-      rtx y0 = XEXP (y, 0);
-      rtx y1 = XEXP (y, 1);
-
-      if (GET_CODE (y1) == CONST_INT)
-       return memrefs_conflict_p (xsize, x, ysize, y0, c + INTVAL (y1));
-      else
-       return 1;
-    }
-
-  if (GET_CODE (x) == GET_CODE (y))
-    switch (GET_CODE (x))
-      {
-      case MULT:
-       {
-         /* Handle cases where we expect the second operands to be the
-            same, and check only whether the first operand would conflict
-            or not.  */
-         rtx x0, y0;
-         rtx x1 = canon_rtx (XEXP (x, 1));
-         rtx y1 = canon_rtx (XEXP (y, 1));
-         if (! rtx_equal_for_memref_p (x1, y1))
-           return 1;
-         x0 = canon_rtx (XEXP (x, 0));
-         y0 = canon_rtx (XEXP (y, 0));
-         if (rtx_equal_for_memref_p (x0, y0))
-           return (xsize == 0 || ysize == 0
-                   || (c >= 0 && xsize > c) || (c < 0 && ysize+c > 0));
-
-         /* Can't properly adjust our sizes.  */
-         if (GET_CODE (x1) != CONST_INT)
-           return 1;
-         xsize /= INTVAL (x1);
-         ysize /= INTVAL (x1);
-         c /= INTVAL (x1);
-         return memrefs_conflict_p (xsize, x0, ysize, y0, c);
-       }
-      }
-
-  if (CONSTANT_P (x))
-    {
-      if (GET_CODE (x) == CONST_INT && GET_CODE (y) == CONST_INT)
-       {
-         c += (INTVAL (y) - INTVAL (x));
-         return (xsize == 0 || ysize == 0
-                 || (c >= 0 && xsize > c) || (c < 0 && ysize+c > 0));
-       }
-
-      if (GET_CODE (x) == CONST)
-       {
-         if (GET_CODE (y) == CONST)
-           return memrefs_conflict_p (xsize, canon_rtx (XEXP (x, 0)),
-                                      ysize, canon_rtx (XEXP (y, 0)), c);
-         else
-           return memrefs_conflict_p (xsize, canon_rtx (XEXP (x, 0)),
-                                      ysize, y, c);
-       }
-      if (GET_CODE (y) == CONST)
-       return memrefs_conflict_p (xsize, x, ysize,
-                                  canon_rtx (XEXP (y, 0)), c);
-
-      if (CONSTANT_P (y))
-       return (rtx_equal_for_memref_p (x, y)
-               && (xsize == 0 || ysize == 0
-                   || (c >= 0 && xsize > c) || (c < 0 && ysize+c > 0)));
-
-      return 1;
-    }
-  return 1;
-}
-
-/* Functions to compute memory dependencies.
-
-   Since we process the insns in execution order, we can build tables
-   to keep track of what registers are fixed (and not aliased), what registers
-   are varying in known ways, and what registers are varying in unknown
-   ways.
-
-   If both memory references are volatile, then there must always be a
-   dependence between the two references, since their order can not be
-   changed.  A volatile and non-volatile reference can be interchanged
-   though. 
-
-   A MEM_IN_STRUCT reference at a non-QImode non-AND varying address can never
-   conflict with a non-MEM_IN_STRUCT reference at a fixed address.   We must
-   allow QImode aliasing because the ANSI C standard allows character
-   pointers to alias anything.  We are assuming that characters are
-   always QImode here.  We also must allow AND addresses, because they may
-   generate accesses outside the object being referenced.  This is used to
-   generate aligned addresses from unaligned addresses, for instance, the
-   alpha storeqi_unaligned pattern.  */
-
-/* Read dependence: X is read after read in MEM takes place.  There can
-   only be a dependence here if both reads are volatile.  */
-
-int
-read_dependence (mem, x)
-     rtx mem;
-     rtx x;
-{
-  return MEM_VOLATILE_P (x) && MEM_VOLATILE_P (mem);
-}
-
-/* True dependence: X is read after store in MEM takes place.  */
-
-int
-true_dependence (mem, x)
-     rtx mem;
-     rtx x;
-{
-  /* If X is an unchanging read, then it can't possibly conflict with any
-     non-unchanging store.  It may conflict with an unchanging write though,
-     because there may be a single store to this address to initialize it.
-     Just fall through to the code below to resolve the case where we have
-     both an unchanging read and an unchanging write.  This won't handle all
-     cases optimally, but the possible performance loss should be
-     negligible.  */
-  x = canon_rtx (x);
-  mem = canon_rtx (mem);
-  if (RTX_UNCHANGING_P (x) && ! RTX_UNCHANGING_P (mem))
-    return 0;
-
-  return ((MEM_VOLATILE_P (x) && MEM_VOLATILE_P (mem))
-         || (memrefs_conflict_p (SIZE_FOR_MODE (mem), XEXP (mem, 0),
-                                 SIZE_FOR_MODE (x), XEXP (x, 0), 0)
-             && ! (MEM_IN_STRUCT_P (mem) && rtx_addr_varies_p (mem)
-                   && GET_MODE (mem) != QImode
-                   && GET_CODE (XEXP (mem, 0)) != AND
-                   && ! MEM_IN_STRUCT_P (x) && ! rtx_addr_varies_p (x))
-             && ! (MEM_IN_STRUCT_P (x) && rtx_addr_varies_p (x)
-                   && GET_MODE (x) != QImode
-                   && GET_CODE (XEXP (x, 0)) != AND
-                   && ! MEM_IN_STRUCT_P (mem) && ! rtx_addr_varies_p (mem))));
-}
-
-/* Anti dependence: X is written after read in MEM takes place.  */
-
-int
-anti_dependence (mem, x)
-     rtx mem;
-     rtx x;
-{
-  /* If MEM is an unchanging read, then it can't possibly conflict with
-     the store to X, because there is at most one store to MEM, and it must
-     have occurred somewhere before MEM.  */
-  x = canon_rtx (x);
-  mem = canon_rtx (mem);
-  if (RTX_UNCHANGING_P (mem))
-    return 0;
-
-  return ((MEM_VOLATILE_P (x) && MEM_VOLATILE_P (mem))
-         || (memrefs_conflict_p (SIZE_FOR_MODE (mem), XEXP (mem, 0),
-                                 SIZE_FOR_MODE (x), XEXP (x, 0), 0)
-             && ! (MEM_IN_STRUCT_P (mem) && rtx_addr_varies_p (mem)
-                   && GET_MODE (mem) != QImode
-                   && GET_CODE (XEXP (mem, 0)) != AND
-                   && ! MEM_IN_STRUCT_P (x) && ! rtx_addr_varies_p (x))
-             && ! (MEM_IN_STRUCT_P (x) && rtx_addr_varies_p (x)
-                   && GET_MODE (x) != QImode
-                   && GET_CODE (XEXP (x, 0)) != AND
-                   && ! MEM_IN_STRUCT_P (mem) && ! rtx_addr_varies_p (mem))));
-}
-
-/* Output dependence: X is written after store in MEM takes place.  */
-
-int
-output_dependence (mem, x)
-     rtx mem;
-     rtx x;
-{
-  x = canon_rtx (x);
-  mem = canon_rtx (mem);
-  return ((MEM_VOLATILE_P (x) && MEM_VOLATILE_P (mem))
-         || (memrefs_conflict_p (SIZE_FOR_MODE (mem), XEXP (mem, 0),
-                                 SIZE_FOR_MODE (x), XEXP (x, 0), 0)
-             && ! (MEM_IN_STRUCT_P (mem) && rtx_addr_varies_p (mem)
-                   && GET_MODE (mem) != QImode
-                   && GET_CODE (XEXP (mem, 0)) != AND
-                   && ! MEM_IN_STRUCT_P (x) && ! rtx_addr_varies_p (x))
-             && ! (MEM_IN_STRUCT_P (x) && rtx_addr_varies_p (x)
-                   && GET_MODE (x) != QImode
-                   && GET_CODE (XEXP (x, 0)) != AND
-                   && ! MEM_IN_STRUCT_P (mem) && ! rtx_addr_varies_p (mem))));
-}
-\f
 /* Helper functions for instruction scheduling.  */
 
 /* Add ELEM wrapped in an INSN_LIST with reg note kind DEP_TYPE to the
@@ -994,17 +431,19 @@ remove_dependence (insn, elem)
   rtx prev, link;
   int found = 0;
 
-  for (prev = 0, link = LOG_LINKS (insn); link;
-       prev = link, link = XEXP (link, 1))
+  for (prev = 0, link = LOG_LINKS (insn); link; link = XEXP (link, 1))
     {
       if (XEXP (link, 0) == elem)
        {
+         RTX_INTEGRATED_P (link) = 1;
          if (prev)
            XEXP (prev, 1) = XEXP (link, 1);
          else
            LOG_LINKS (insn) = XEXP (link, 1);
          found = 1;
        }
+      else
+       prev = link;
     }
 
   if (! found)
@@ -1308,9 +747,9 @@ actual_hazard (unit, insn, clock, cost)
       int instance = unit;
       int best_cost = actual_hazard_this_instance (unit, instance, insn,
                                                   clock, cost);
+#if MAX_MULTIPLICITY > 1
       int this_cost;
 
-#if MAX_MULTIPLICITY > 1
       if (best_cost > cost)
        {
          for (i = function_units[unit].multiplicity - 1; i > 0; i--)
@@ -1482,6 +921,11 @@ priority (insn)
        {
          rtx x = XEXP (prev, 0);
 
+         /* If this was a duplicate of a dependence we already deleted,
+            ignore it.  */
+         if (RTX_INTEGRATED_P (prev))
+           continue;
+
          /* A dependence pointing to a note or deleted insn is always
             obsolete, because sched_analyze_insn will have created any
             necessary new dependences which replace it.  Notes and deleted
@@ -1889,8 +1333,8 @@ sched_analyze_2 (x, insn)
            while (--i >= 0)
              {
                reg_last_uses[regno + i]
-                 = gen_rtx (INSN_LIST, VOIDmode,
-                            insn, reg_last_uses[regno + i]);
+                 = gen_rtx_INSN_LIST (VOIDmode,
+                                      insn, reg_last_uses[regno + i]);
                if (reg_last_sets[regno + i])
                  add_dependence (insn, reg_last_sets[regno + i], 0);
                if ((call_used_regs[regno + i] || global_regs[regno + i])
@@ -1902,7 +1346,7 @@ sched_analyze_2 (x, insn)
        else
          {
            reg_last_uses[regno]
-             = gen_rtx (INSN_LIST, VOIDmode, insn, reg_last_uses[regno]);
+             = gen_rtx_INSN_LIST (VOIDmode, insn, reg_last_uses[regno]);
            if (reg_last_sets[regno])
              add_dependence (insn, reg_last_sets[regno], 0);
 
@@ -1948,7 +1392,8 @@ sched_analyze_2 (x, insn)
          {
            /* If a dependency already exists, don't create a new one.  */
            if (! find_insn_list (XEXP (pending, 0), LOG_LINKS (insn)))
-             if (true_dependence (XEXP (pending_mem, 0), x))
+             if (true_dependence (XEXP (pending_mem, 0), VOIDmode,
+                                  x, rtx_varies_p))
                add_dependence (insn, XEXP (pending, 0), 0);
 
            pending = XEXP (pending, 1);
@@ -2024,6 +1469,9 @@ sched_analyze_2 (x, insn)
       sched_analyze_2 (XEXP (x, 0), insn);
       sched_analyze_1 (x, insn);
       return;
+      
+    default:
+      break;
     }
 
   /* Other cases: walk the insn.  */
@@ -2128,10 +1576,11 @@ sched_analyze_insn (x, insn, loop_notes)
          sched_analyze_2 (XEXP (note, 0), insn);
     }
 
-  EXECUTE_IF_SET_AND_RESET_IN_REG_SET (reg_pending_sets, 0, i,
-                                      {
-                                        reg_last_sets[i] = insn;
-                                      });
+  EXECUTE_IF_SET_IN_REG_SET (reg_pending_sets, 0, i,
+                            {
+                              reg_last_sets[i] = insn;
+                            });
+  CLEAR_REG_SET (reg_pending_sets);
 
   if (reg_pending_sets_all)
     {
@@ -2234,14 +1683,14 @@ sched_analyze (head, tail)
 
              /* Add a pair of fake REG_NOTEs which we will later
                 convert back into a NOTE_INSN_SETJMP note.  See
-                reemit_notes for why we use a pair of of NOTEs.  */
-
-             REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_DEAD,
-                                         GEN_INT (0),
-                                         REG_NOTES (insn));
-             REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_DEAD,
-                                         GEN_INT (NOTE_INSN_SETJMP),
-                                         REG_NOTES (insn));
+                reemit_notes for why we use a pair of NOTEs.  */
+
+             REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_DEAD,
+                                                   GEN_INT (0),
+                                                   REG_NOTES (insn));
+             REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_DEAD,
+                                                   GEN_INT (NOTE_INSN_SETJMP),
+                                                   REG_NOTES (insn));
            }
          else
            {
@@ -2288,13 +1737,17 @@ sched_analyze (head, tail)
                   || NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_END
                   || NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_REGION_BEG
                   || NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_REGION_END
+                  || NOTE_LINE_NUMBER (insn) == NOTE_INSN_RANGE_START
+                  || NOTE_LINE_NUMBER (insn) == NOTE_INSN_RANGE_END
                   || (NOTE_LINE_NUMBER (insn) == NOTE_INSN_SETJMP
                       && GET_CODE (PREV_INSN (insn)) != CALL_INSN)))
        {
-         loop_notes = gen_rtx (EXPR_LIST, REG_DEAD,
-                               GEN_INT (NOTE_BLOCK_NUMBER (insn)), loop_notes);
-         loop_notes = gen_rtx (EXPR_LIST, REG_DEAD,
-                               GEN_INT (NOTE_LINE_NUMBER (insn)), loop_notes);
+         loop_notes = gen_rtx_EXPR_LIST (REG_DEAD,
+                                         GEN_INT (NOTE_BLOCK_NUMBER (insn)),
+                                         loop_notes);
+         loop_notes = gen_rtx_EXPR_LIST (REG_DEAD,
+                                         GEN_INT (NOTE_LINE_NUMBER (insn)),
+                                         loop_notes);
          CONST_CALL_P (loop_notes) = CONST_CALL_P (insn);
        }
 
@@ -2406,16 +1859,17 @@ sched_note_set (b, x, death)
 
 static int
 rank_for_schedule (x, y)
-     rtx *x, *y;
+     const GENERIC_PTR x;
+     const GENERIC_PTR y;
 {
-  rtx tmp = *y;
-  rtx tmp2 = *x;
+  rtx tmp = *(rtx *)y;
+  rtx tmp2 = *(rtx *)x;
   rtx link;
   int tmp_class, tmp2_class;
   int value;
 
   /* Choose the instruction with the highest priority, if different.  */
-  if (value = INSN_PRIORITY (tmp) - INSN_PRIORITY (tmp2))
+  if ((value = INSN_PRIORITY (tmp) - INSN_PRIORITY (tmp2)))
     return value;
 
   if (last_scheduled_insn)
@@ -2441,7 +1895,7 @@ rank_for_schedule (x, y)
       else
        tmp2_class = 2;
 
-      if (value = tmp_class - tmp2_class)
+      if ((value = tmp_class - tmp2_class))
        return value;
     }
 
@@ -2769,6 +2223,12 @@ create_reg_dead_note (reg, insn)
                                           GET_MODE (XEXP (link, 0))));
       while (reg_note_regs < regs_killed)
        {
+         /* LINK might be zero if we killed more registers after scheduling
+            than before, and the last hard register we kill is actually
+            multiple hard regs.  */
+         if (link == NULL_RTX)
+           abort ();
+  
          link = XEXP (link, 1);
          reg_note_regs += (REGNO (XEXP (link, 0)) >= FIRST_PSEUDO_REGISTER ? 1
                            : HARD_REGNO_NREGS (REGNO (XEXP (link, 0)),
@@ -2781,7 +2241,7 @@ create_reg_dead_note (reg, insn)
        {
          rtx temp_reg, temp_link;
 
-         temp_reg = gen_rtx (REG, word_mode, 0);
+         temp_reg = gen_rtx_REG (word_mode, 0);
          temp_link = rtx_alloc (EXPR_LIST);
          PUT_REG_NOTE_KIND (temp_link, REG_DEAD);
          XEXP (temp_link, 0) = temp_reg;
@@ -2885,12 +2345,7 @@ attach_deaths (x, insn, set_p)
 #endif
                && regno != STACK_POINTER_REGNUM)
              {
-               /* ??? It is perhaps a dead_or_set_p bug that it does
-                  not check for REG_UNUSED notes itself.  This is necessary
-                  for the case where the SET_DEST is a subreg of regno, as
-                  dead_or_set_p handles subregs specially.  */
-               if (! all_needed && ! dead_or_set_p (insn, x)
-                   && ! find_reg_note (insn, REG_UNUSED, x))
+               if (! all_needed && ! dead_or_set_p (insn, x))
                  {
                    /* Check for the case where the register dying partially
                       overlaps the register set by this insn.  */
@@ -2915,11 +2370,10 @@ attach_deaths (x, insn, set_p)
                           register that is set in the insn.  */
                        for (i = HARD_REGNO_NREGS (regno, GET_MODE (x)) - 1;
                             i >= 0; i--)
-                         if (REGNO_REG_SET_P (old_live_regs, regno + i)
+                         if (REGNO_REG_SET_P (old_live_regs, regno + i)
                              && ! dead_or_set_regno_p (insn, regno + i))
-                           create_reg_dead_note (gen_rtx (REG,
-                                                          reg_raw_mode[regno + i],
-                                                          regno + i),
+                           create_reg_dead_note (gen_rtx_REG (reg_raw_mode[regno + i],
+                                                              regno + i),
                                                  insn);
                      }
                  }
@@ -2949,17 +2403,20 @@ attach_deaths (x, insn, set_p)
       return;
 
     case SUBREG:
+      attach_deaths (SUBREG_REG (x), insn,
+                    set_p && ((GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)))
+                              <= UNITS_PER_WORD)
+                              || (GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)))
+                                  == GET_MODE_SIZE (GET_MODE ((x))))));
+      return;
+
     case STRICT_LOW_PART:
-      /* These two cases preserve the value of SET_P, so handle them
-        separately.  */
-      attach_deaths (XEXP (x, 0), insn, set_p);
+      attach_deaths (XEXP (x, 0), insn, 0);
       return;
 
     case ZERO_EXTRACT:
     case SIGN_EXTRACT:
-      /* This case preserves the value of SET_P for the first operand, but
-        clears it for the other two.  */
-      attach_deaths (XEXP (x, 0), insn, set_p);
+      attach_deaths (XEXP (x, 0), insn, 0);
       attach_deaths (XEXP (x, 1), insn, 0);
       attach_deaths (XEXP (x, 2), insn, 0);
       return;
@@ -3061,6 +2518,8 @@ unlink_notes (insn, tail)
       else if (NOTE_LINE_NUMBER (insn) != NOTE_INSN_SETJMP
               && NOTE_LINE_NUMBER (insn) != NOTE_INSN_LOOP_BEG
               && NOTE_LINE_NUMBER (insn) != NOTE_INSN_LOOP_END
+              && NOTE_LINE_NUMBER (insn) != NOTE_INSN_RANGE_START
+              && NOTE_LINE_NUMBER (insn) != NOTE_INSN_RANGE_END
               && NOTE_LINE_NUMBER (insn) != NOTE_INSN_EH_REGION_BEG
               && NOTE_LINE_NUMBER (insn) != NOTE_INSN_EH_REGION_END)
        {
@@ -3207,6 +2666,14 @@ schedule_block (b, file)
   reg_pending_sets_all = 0;
   clear_units ();
 
+#if 0
+  /* We used to have code to avoid getting parameters moved from hard
+     argument registers into pseudos.
+
+     However, it was removed when it proved to be of marginal benefit and
+     caused problems because of different notions of what the "head" insn
+     was.  */
+
   /* Remove certain insns at the beginning from scheduling,
      by advancing HEAD.  */
 
@@ -3237,6 +2704,7 @@ schedule_block (b, file)
          head = NEXT_INSN (head);
        }
     }
+#endif
 
   /* Don't include any notes or labels at the beginning of the
      basic block, or notes at the ends of basic blocks.  */
@@ -3254,7 +2722,7 @@ schedule_block (b, file)
      to schedule this block.  */
   if (head == tail
       && (GET_CODE (head) == NOTE || GET_CODE (head) == CODE_LABEL))
-    return;
+    goto ret;
 
 #if 0
   /* This short-cut doesn't work.  It does not count call insns crossed by
@@ -3267,7 +2735,7 @@ schedule_block (b, file)
      has one insn, so this won't slow down this pass by much.  */
 
   if (head == tail)
-    return;
+    goto ret;
 #endif
 
   /* Now HEAD through TAIL are the insns actually to be rearranged;
@@ -3292,7 +2760,7 @@ schedule_block (b, file)
   if (n_insns == 0)
     {
       free_pending_lists ();
-      return;
+      goto ret;
     }
 
   /* Allocate vector to hold insns to be rearranged (except those
@@ -3422,7 +2890,7 @@ schedule_block (b, file)
          finish_sometimes_live (regs_sometimes_live, sometimes_max);
        }
       free_pending_lists ();
-      return;
+      goto ret;
     }
 #endif
 
@@ -3436,9 +2904,8 @@ schedule_block (b, file)
 
   if (reload_completed == 0)
     {
-      bcopy ((char *) basic_block_live_at_start[b], (char *) bb_live_regs,
-            regset_bytes);
-      bzero ((char *) bb_dead_regs, regset_bytes);
+      COPY_REG_SET (bb_live_regs, basic_block_live_at_start[b]);
+      CLEAR_REG_SET (bb_dead_regs);
 
       if (b == 0)
        {
@@ -3726,7 +3193,7 @@ schedule_block (b, file)
          register int stalls;
 
          for (stalls = 1; stalls < INSN_QUEUE_SIZE; stalls++)
-           if (insn = insn_queue[NEXT_Q_AFTER (q_ptr, stalls)])
+           if ((insn = insn_queue[NEXT_Q_AFTER (q_ptr, stalls)]))
              {
                for (; insn; insn = NEXT_INSN (insn))
                  {
@@ -3857,12 +3324,13 @@ schedule_block (b, file)
              attach_deaths_insn (insn);
 
              /* Find registers now made live by that instruction.  */
-             EXECUTE_IF_SET_IN_REG_SET (bb_live_regs, 0, i,
-                                        {
-                                          sometimes_max
-                                            = new_sometimes_live (regs_sometimes_live,
-                                                                  i, sometimes_max);
-                                        });
+             EXECUTE_IF_AND_COMPL_IN_REG_SET (bb_live_regs, old_live_regs, 0, i,
+                                              {
+                                                sometimes_max
+                                                  = new_sometimes_live (regs_sometimes_live,
+                                                                        i, sometimes_max);
+                                              });
+             IOR_REG_SET (old_live_regs, bb_live_regs);
 
              /* Count lengths of all regs we are worrying about now,
                 and handle registers no longer live.  */
@@ -3874,7 +3342,7 @@ schedule_block (b, file)
 
                  p->live_length += 1;
 
-                 if (REGNO_REG_SET_P (bb_live_regs, p->regno))
+                 if (!REGNO_REG_SET_P (bb_live_regs, p->regno))
                    {
                      /* This is the end of one of this register's lifetime
                         segments.  Save the lifetime info collected so far,
@@ -4081,6 +3549,10 @@ schedule_block (b, file)
   /* Yow! We're done!  */
   free_pending_lists ();
 
+ret:
+  FREE_REG_SET (reg_pending_sets);
+  FREE_REG_SET (old_live_regs);
+
   return;
 }
 \f
@@ -4105,12 +3577,12 @@ regno_use_in (regno, x)
     {
       if (fmt[i] == 'e')
        {
-         if (tem = regno_use_in (regno, XEXP (x, i)))
+         if ((tem = regno_use_in (regno, XEXP (x, i))))
            return tem;
        }
       else if (fmt[i] == 'E')
        for (j = XVECLEN (x, i) - 1; j >= 0; j--)
-         if (tem = regno_use_in (regno , XVECEXP (x, i, j)))
+         if ((tem = regno_use_in (regno , XVECEXP (x, i, j))))
            return tem;
     }
 
@@ -4187,6 +3659,13 @@ new_insn_dead_notes (pat, insn, last, orig_insn)
 
   if (GET_CODE (dest) == REG)
     {
+      /* If the original insn already used this register, we may not add new
+         notes for it.  One example for a split that needs this test is
+        when a multi-word memory access with register-indirect addressing
+        is split into multiple memory accesses with auto-increment and
+        one adjusting add instruction for the address register.  */
+      if (reg_referenced_p (dest, PATTERN (orig_insn)))
+       return;
       for (tem = last; tem != insn; tem = PREV_INSN (tem))
        {
          if (GET_RTX_CLASS (GET_CODE (tem)) == 'i'
@@ -4358,6 +3837,7 @@ update_flow_info (notes, first, last, orig_insn)
                  /* ??? This won't handle multiple word registers correctly,
                     but should be good enough for now.  */
                  if (REG_NOTE_KIND (note) == REG_UNUSED
+                     && GET_CODE (XEXP (note, 0)) != SCRATCH
                      && ! dead_or_set_p (insn, XEXP (note, 0)))
                    PUT_REG_NOTE_KIND (note, REG_DEAD);
 
@@ -4390,6 +3870,14 @@ update_flow_info (notes, first, last, orig_insn)
          break;
 
        case REG_WAS_0:
+         /* If the insn that set the register to 0 was deleted, this
+            note cannot be relied on any longer.  The destination might
+            even have been moved to memory.
+             This was observed for SH4 with execute/920501-6.c compilation,
+            -O2 -fomit-frame-pointer -finline-functions .  */
+         if (GET_CODE (XEXP (note, 0)) == NOTE
+             || INSN_DELETED_P (XEXP (note, 0)))
+           break;
          /* This note applies to the dest of the original insn.  Find the
             first new insn that now has the same dest, and move the note
             there.  */
@@ -4535,8 +4023,9 @@ update_flow_info (notes, first, last, orig_insn)
          for (insn = first; insn != NEXT_INSN (last); insn = NEXT_INSN (insn))
            if (GET_RTX_CLASS (GET_CODE (insn)) == 'i'
                && reg_mentioned_p (XEXP (note, 0), PATTERN (insn)))
-             REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_LABEL,
-                                         XEXP (note, 0), REG_NOTES (insn));
+             REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_LABEL,
+                                                   XEXP (note, 0),
+                                                   REG_NOTES (insn));
          break;
 
        case REG_CC_SETTER:
@@ -4576,10 +4065,7 @@ update_flow_info (notes, first, last, orig_insn)
   /* If any insn, except the last, uses the register set by the last insn,
      then we need a new REG_DEAD note on that insn.  In this case, there
      would not have been a REG_DEAD note for this register in the original
-     insn because it was used and set within one insn.
-
-     There is no new REG_DEAD note needed if the last insn uses the register
-     that it is setting.  */
+     insn because it was used and set within one insn.  */
 
   set = single_set (last);
   if (set)
@@ -4595,10 +4081,31 @@ update_flow_info (notes, first, last, orig_insn)
          /* Global registers are always live, so the code below does not
             apply to them.  */
          && (REGNO (dest) >= FIRST_PSEUDO_REGISTER
-             || ! global_regs[REGNO (dest)])
-         && ! reg_overlap_mentioned_p (dest, SET_SRC (set)))
+             || ! global_regs[REGNO (dest)]))
        {
-         for (insn = PREV_INSN (last); ; insn = PREV_INSN (insn))
+         rtx stop_insn = PREV_INSN (first);
+
+         /* If the last insn uses the register that it is setting, then
+            we don't want to put a REG_DEAD note there.  Search backwards
+            to find the first insn that sets but does not use DEST.  */
+
+         insn = last;
+         if (reg_overlap_mentioned_p (dest, SET_SRC (set)))
+           {
+             for (insn = PREV_INSN (insn); insn != first;
+                  insn = PREV_INSN (insn))
+               {
+                 if ((set = single_set (insn))
+                     && reg_mentioned_p (dest, SET_DEST (set))
+                     && ! reg_overlap_mentioned_p (dest, SET_SRC (set)))
+                   break;
+               }
+           }
+
+         /* Now find the first insn that uses but does not set DEST.  */
+
+         for (insn = PREV_INSN (insn); insn != stop_insn;
+              insn = PREV_INSN (insn))
            {
              if (GET_RTX_CLASS (GET_CODE (insn)) == 'i'
                  && reg_mentioned_p (dest, PATTERN (insn))
@@ -4624,8 +4131,6 @@ update_flow_info (notes, first, last, orig_insn)
                      break;
                    }
                }
-             if (insn == first)
-               break;
            }
        }
     }
@@ -4649,21 +4154,29 @@ update_flow_info (notes, first, last, orig_insn)
 
       for (insn = first; ; insn = NEXT_INSN (insn))
        {
-         set = single_set (insn);
-         if (set)
+         rtx pat = PATTERN (insn);
+         int i = GET_CODE (pat) == PARALLEL ? XVECLEN (pat, 0) : 0;
+         set = pat;
+         for (;;)
            {
-             if (GET_CODE (SET_DEST (set)) == REG
-                 && REGNO (SET_DEST (set)) == REGNO (orig_dest))
-               {
-                 found_orig_dest = 1;
-                 break;
-               }
-             else if (GET_CODE (SET_DEST (set)) == SUBREG
-                      && SUBREG_REG (SET_DEST (set)) == orig_dest)
+             if (GET_CODE (set) == SET)
                {
-                 found_split_dest = 1;
-                 break;
+                 if (GET_CODE (SET_DEST (set)) == REG
+                     && REGNO (SET_DEST (set)) == REGNO (orig_dest))
+                   {
+                     found_orig_dest = 1;
+                     break;
+                   }
+                 else if (GET_CODE (SET_DEST (set)) == SUBREG
+                          && SUBREG_REG (SET_DEST (set)) == orig_dest)
+                   {
+                     found_split_dest = 1;
+                     break;
+                   }
                }
+             if (--i < 0)
+               break;
+             set = XVECEXP (pat, 0, i);
            }
 
          if (insn == last)
@@ -4752,7 +4265,6 @@ schedule_insns (dump_file)
 {
   int max_uid = MAX_INSNS_PER_SPLIT * (get_max_uid () + 1);
   int b;
-  int i;
   rtx insn;
 
   /* Taking care of this degenerate case makes the rest of
@@ -4762,8 +4274,8 @@ schedule_insns (dump_file)
 
   /* Create an insn here so that we can hang dependencies off of it later.  */
   sched_before_next_call
-    = gen_rtx (INSN, VOIDmode, 0, NULL_RTX, NULL_RTX,
-              NULL_RTX, 0, NULL_RTX, 0);
+    = gen_rtx_INSN (VOIDmode, 0, NULL_RTX, NULL_RTX,
+                   NULL_RTX, 0, NULL_RTX, NULL_RTX);
 
   /* Initialize the unused_*_lists.  We can't use the ones left over from
      the previous function, because gcc has freed that memory.  We can use
@@ -4798,7 +4310,6 @@ schedule_insns (dump_file)
       bb_live_regs = ALLOCA_REG_SET ();
       bzero ((char *) sched_reg_n_calls_crossed, max_regno * sizeof (int));
       bzero ((char *) sched_reg_live_length, max_regno * sizeof (int));
-      init_alias_analysis ();
     }
   else
     {
@@ -4806,9 +4317,8 @@ schedule_insns (dump_file)
       sched_reg_live_length = 0;
       bb_dead_regs = 0;
       bb_live_regs = 0;
-      if (! flag_schedule_insns)
-       init_alias_analysis ();
     }
+  init_alias_analysis ();
 
   if (write_symbols != NO_DEBUG)
     {
@@ -5050,5 +4560,12 @@ schedule_insns (dump_file)
              REG_N_CALLS_CROSSED (regno) = sched_reg_n_calls_crossed[regno];
          }
     }
+
+  if (reload_completed == 0)
+    {
+      FREE_REG_SET (bb_dead_regs);
+      FREE_REG_SET (bb_live_regs);
+    }
+
 }
 #endif /* INSN_SCHEDULING */