OSDN Git Service

2004-05-13 Benjamin Kosnik <bkoz@redhat.com>
[pf3gnuchains/gcc-fork.git] / gcc / rtlanal.c
index 030682e..a52f614 100644 (file)
@@ -1,6 +1,6 @@
 /* Analyze RTL for C-Compiler
    Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+   1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -29,19 +29,23 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "hard-reg-set.h"
 #include "insn-config.h"
 #include "recog.h"
+#include "target.h"
+#include "output.h"
 #include "tm_p.h"
 #include "flags.h"
 #include "basic-block.h"
 #include "real.h"
+#include "regs.h"
 
 /* Forward declarations */
-static int global_reg_mentioned_p_1 PARAMS ((rtx *, void *));
-static void set_of_1           PARAMS ((rtx, rtx, void *));
-static void insn_dependent_p_1 PARAMS ((rtx, rtx, void *));
-static int computed_jump_p_1   PARAMS ((rtx));
-static void parms_set          PARAMS ((rtx, rtx, void *));
-static bool hoist_test_store           PARAMS ((rtx, rtx, regset));
-static void hoist_update_store         PARAMS ((rtx, rtx *, rtx, rtx));
+static int global_reg_mentioned_p_1 (rtx *, void *);
+static void set_of_1 (rtx, rtx, void *);
+static void insn_dependent_p_1 (rtx, rtx, void *);
+static int rtx_referenced_p_1 (rtx *, void *);
+static int computed_jump_p_1 (rtx);
+static void parms_set (rtx, rtx, void *);
+static bool hoist_test_store (rtx, rtx, regset);
+static void hoist_update_store (rtx, rtx *, rtx, rtx);
 
 /* Bit flags that specify the machine subtype we are compiling for.
    Bits are tested using macros TARGET_... defined in the tm.h file
@@ -55,8 +59,7 @@ int target_flags;
    (within one function) and so is anything marked `unchanging'.  */
 
 int
-rtx_unstable_p (x)
-     rtx x;
+rtx_unstable_p (rtx x)
 {
   RTX_CODE code = GET_CODE (x);
   int i;
@@ -99,7 +102,7 @@ rtx_unstable_p (x)
       if (MEM_VOLATILE_P (x))
        return 1;
 
-      /* FALLTHROUGH */
+      /* Fall through.  */
 
     default:
       break;
@@ -131,14 +134,16 @@ rtx_unstable_p (x)
    The frame pointer and the arg pointer are considered constant.  */
 
 int
-rtx_varies_p (x, for_alias)
-     rtx x;
-     int for_alias;
+rtx_varies_p (rtx x, int for_alias)
 {
-  RTX_CODE code = GET_CODE (x);
+  RTX_CODE code;
   int i;
   const char *fmt;
 
+  if (!x)
+    return 0;
+
+  code = GET_CODE (x);
   switch (code)
     {
     case MEM:
@@ -191,7 +196,7 @@ rtx_varies_p (x, for_alias)
       if (MEM_VOLATILE_P (x))
        return 1;
 
-      /* FALLTHROUGH */
+      /* Fall through.  */
 
     default:
       break;
@@ -218,8 +223,7 @@ rtx_varies_p (x, for_alias)
 /* Return 0 if the use of X as an address in a MEM can cause a trap.  */
 
 int
-rtx_addr_can_trap_p (x)
-     rtx x;
+rtx_addr_can_trap_p (rtx x)
 {
   enum rtx_code code = GET_CODE (x);
 
@@ -282,8 +286,7 @@ rtx_addr_can_trap_p (x)
 /* Return true if X is an address that is known to not be zero.  */
 
 bool
-nonzero_address_p (x)
-     rtx x;
+nonzero_address_p (rtx x)
 {
   enum rtx_code code = GET_CODE (x);
 
@@ -370,9 +373,7 @@ nonzero_address_p (x)
    zero, we are slightly more conservative.  */
 
 int
-rtx_addr_varies_p (x, for_alias)
-     rtx x;
-     int for_alias;
+rtx_addr_varies_p (rtx x, int for_alias)
 {
   enum rtx_code code;
   int i;
@@ -408,8 +409,7 @@ rtx_addr_varies_p (x, for_alias)
    This is used in cse.c with the `related_value' field.  */
 
 HOST_WIDE_INT
-get_integer_term (x)
-     rtx x;
+get_integer_term (rtx x)
 {
   if (GET_CODE (x) == CONST)
     x = XEXP (x, 0);
@@ -428,8 +428,7 @@ get_integer_term (x)
    Only obvious integer terms are detected.  */
 
 rtx
-get_related_value (x)
-     rtx x;
+get_related_value (rtx x)
 {
   if (GET_CODE (x) != CONST)
     return 0;
@@ -451,12 +450,10 @@ get_related_value (x)
    insn used in locating the offset was found.  */
 
 rtx
-get_jump_table_offset (insn, earliest)
-     rtx insn;
-     rtx *earliest;
+get_jump_table_offset (rtx insn, rtx *earliest)
 {
-  rtx label;
-  rtx table;
+  rtx label = NULL;
+  rtx table = NULL;
   rtx set;
   rtx old_insn;
   rtx x;
@@ -465,13 +462,7 @@ get_jump_table_offset (insn, earliest)
   rtx old_y;
   int i;
 
-  if (GET_CODE (insn) != JUMP_INSN
-      || ! (label = JUMP_LABEL (insn))
-      || ! (table = NEXT_INSN (label))
-      || GET_CODE (table) != JUMP_INSN
-      || (GET_CODE (PATTERN (table)) != ADDR_VEC
-         && GET_CODE (PATTERN (table)) != ADDR_DIFF_VEC)
-      || ! (set = single_set (insn)))
+  if (!tablejump_p (insn, &label, &table) || !(set = single_set (insn)))
     return NULL_RTX;
 
   x = SET_SRC (set);
@@ -587,9 +578,7 @@ get_jump_table_offset (insn, earliest)
    a global register.  */
 
 static int
-global_reg_mentioned_p_1 (loc, data)
-     rtx *loc;
-     void *data ATTRIBUTE_UNUSED;
+global_reg_mentioned_p_1 (rtx *loc, void *data ATTRIBUTE_UNUSED)
 {
   int regno;
   rtx x = *loc;
@@ -638,10 +627,8 @@ global_reg_mentioned_p_1 (loc, data)
 /* Returns nonzero if X mentions a global register.  */
 
 int
-global_reg_mentioned_p (x)
-     rtx x;
+global_reg_mentioned_p (rtx x)
 {
-
   if (INSN_P (x))
     {
       if (GET_CODE (x) == CALL_INSN)
@@ -663,9 +650,7 @@ global_reg_mentioned_p (x)
    zero, we do not count occurrences inside the destination of a SET.  */
 
 int
-count_occurrences (x, find, count_dest)
-     rtx x, find;
-     int count_dest;
+count_occurrences (rtx x, rtx find, int count_dest)
 {
   int i, j;
   enum rtx_code code;
@@ -728,8 +713,7 @@ count_occurrences (x, find, count_dest)
    for a subexpression of IN that is Lisp "equal" to REG.  */
 
 int
-reg_mentioned_p (reg, in)
-     rtx reg, in;
+reg_mentioned_p (rtx reg, rtx in)
 {
   const char *fmt;
   int i;
@@ -760,8 +744,6 @@ reg_mentioned_p (reg, in)
       return 0;
 
     case CONST_INT:
-      return GET_CODE (reg) == CONST_INT && INTVAL (in) == INTVAL (reg);
-
     case CONST_VECTOR:
     case CONST_DOUBLE:
       /* These are kept unique for a given value.  */
@@ -796,8 +778,7 @@ reg_mentioned_p (reg, in)
    no CODE_LABEL insn.  */
 
 int
-no_labels_between_p (beg, end)
-     rtx beg, end;
+no_labels_between_p (rtx beg, rtx end)
 {
   rtx p;
   if (beg == end)
@@ -812,8 +793,7 @@ no_labels_between_p (beg, end)
    no JUMP_INSN insn.  */
 
 int
-no_jumps_between_p (beg, end)
-     rtx beg, end;
+no_jumps_between_p (rtx beg, rtx end)
 {
   rtx p;
   for (p = NEXT_INSN (beg); p != end; p = NEXT_INSN (p))
@@ -826,8 +806,7 @@ no_jumps_between_p (beg, end)
    FROM_INSN and TO_INSN (exclusive of those two).  */
 
 int
-reg_used_between_p (reg, from_insn, to_insn)
-     rtx reg, from_insn, to_insn;
+reg_used_between_p (rtx reg, rtx from_insn, rtx to_insn)
 {
   rtx insn;
 
@@ -849,9 +828,7 @@ reg_used_between_p (reg, from_insn, to_insn)
    we do not consider it a reference.  */
 
 int
-reg_referenced_p (x, body)
-     rtx x;
-     rtx body;
+reg_referenced_p (rtx x, rtx body)
 {
   int i;
 
@@ -928,8 +905,7 @@ reg_referenced_p (x, body)
    not count.  */
 
 int
-reg_referenced_between_p (reg, from_insn, to_insn)
-     rtx reg, from_insn, to_insn;
+reg_referenced_between_p (rtx reg, rtx from_insn, rtx to_insn)
 {
   rtx insn;
 
@@ -949,8 +925,7 @@ reg_referenced_between_p (reg, from_insn, to_insn)
    FROM_INSN and TO_INSN (exclusive of those two).  */
 
 int
-reg_set_between_p (reg, from_insn, to_insn)
-     rtx reg, from_insn, to_insn;
+reg_set_between_p (rtx reg, rtx from_insn, rtx to_insn)
 {
   rtx insn;
 
@@ -965,8 +940,7 @@ reg_set_between_p (reg, from_insn, to_insn)
 
 /* Internals of reg_set_between_p.  */
 int
-reg_set_p (reg, insn)
-     rtx reg, insn;
+reg_set_p (rtx reg, rtx insn)
 {
   /* We can be passed an insn or part of one.  If we are passed an insn,
      check if a side-effect of the insn clobbers REG.  */
@@ -993,9 +967,7 @@ reg_set_p (reg, insn)
    consider non-registers one way or the other.  */
 
 int
-regs_set_between_p (x, start, end)
-     rtx x;
-     rtx start, end;
+regs_set_between_p (rtx x, rtx start, rtx end)
 {
   enum rtx_code code = GET_CODE (x);
   const char *fmt;
@@ -1040,9 +1012,7 @@ regs_set_between_p (x, start, end)
    X contains a MEM; this routine does usememory aliasing.  */
 
 int
-modified_between_p (x, start, end)
-     rtx x;
-     rtx start, end;
+modified_between_p (rtx x, rtx start, rtx end)
 {
   enum rtx_code code = GET_CODE (x);
   const char *fmt;
@@ -1104,9 +1074,7 @@ modified_between_p (x, start, end)
    does use memory aliasing.  */
 
 int
-modified_in_p (x, insn)
-     rtx x;
-     rtx insn;
+modified_in_p (rtx x, rtx insn)
 {
   enum rtx_code code = GET_CODE (x);
   const char *fmt;
@@ -1162,8 +1130,7 @@ modified_in_p (x, insn)
    anything in insn Y.  */
 
 int
-insn_dependent_p (x, y)
-     rtx x, y;
+insn_dependent_p (rtx x, rtx y)
 {
   rtx tmp;
 
@@ -1186,10 +1153,7 @@ insn_dependent_p (x, y)
 /* A helper routine for insn_dependent_p called through note_stores.  */
 
 static void
-insn_dependent_p_1 (x, pat, data)
-     rtx x;
-     rtx pat ATTRIBUTE_UNUSED;
-     void *data;
+insn_dependent_p_1 (rtx x, rtx pat ATTRIBUTE_UNUSED, void *data)
 {
   rtx * pinsn = (rtx *) data;
 
@@ -1205,10 +1169,7 @@ struct set_of_data
   };
 
 static void
-set_of_1 (x, pat, data1)
-     rtx x;
-     rtx pat;
-     void *data1;
+set_of_1 (rtx x, rtx pat, void *data1)
 {
    struct set_of_data *data = (struct set_of_data *) (data1);
    if (rtx_equal_p (x, data->pat)
@@ -1219,8 +1180,7 @@ set_of_1 (x, pat, data1)
 /* Give an INSN, return a SET or CLOBBER expression that does modify PAT
    (either directly or via STRICT_LOW_PART and similar modifiers).  */
 rtx
-set_of (pat, insn)
-     rtx pat, insn;
+set_of (rtx pat, rtx insn)
 {
   struct set_of_data data;
   data.found = NULL_RTX;
@@ -1234,8 +1194,7 @@ set_of (pat, insn)
    will not be used, which we ignore.  */
 
 rtx
-single_set_2 (insn, pat)
-     rtx insn, pat;
+single_set_2 (rtx insn, rtx pat)
 {
   rtx set = NULL;
   int set_verified = 1;
@@ -1288,8 +1247,7 @@ single_set_2 (insn, pat)
    zero.  */
 
 int
-multiple_sets (insn)
-     rtx insn;
+multiple_sets (rtx insn)
 {
   int found;
   int i;
@@ -1320,25 +1278,22 @@ multiple_sets (insn)
    and there are no side effects.  */
 
 int
-set_noop_p (set)
-     rtx set;
+set_noop_p (rtx set)
 {
   rtx src = SET_SRC (set);
   rtx dst = SET_DEST (set);
 
-  if (side_effects_p (src) || side_effects_p (dst))
-    return 0;
-
-  if (GET_CODE (dst) == MEM && GET_CODE (src) == MEM)
-    return rtx_equal_p (dst, src);
-
   if (dst == pc_rtx && src == pc_rtx)
     return 1;
 
+  if (GET_CODE (dst) == MEM && GET_CODE (src) == MEM)
+    return rtx_equal_p (dst, src) && !side_effects_p (dst);
+
   if (GET_CODE (dst) == SIGN_EXTRACT
       || GET_CODE (dst) == ZERO_EXTRACT)
     return rtx_equal_p (XEXP (dst, 0), src)
-          && ! BYTES_BIG_ENDIAN && XEXP (dst, 2) == const0_rtx;
+          && ! BYTES_BIG_ENDIAN && XEXP (dst, 2) == const0_rtx
+          && !side_effects_p (src);
 
   if (GET_CODE (dst) == STRICT_LOW_PART)
     dst = XEXP (dst, 0);
@@ -1359,8 +1314,7 @@ set_noop_p (set)
    value to itself.  */
 
 int
-noop_move_p (insn)
-     rtx insn;
+noop_move_p (rtx insn)
 {
   rtx pat = PATTERN (insn);
 
@@ -1410,11 +1364,7 @@ noop_move_p (insn)
    be the src.  */
 
 rtx
-find_last_value (x, pinsn, valid_to, allow_hwreg)
-     rtx x;
-     rtx *pinsn;
-     rtx valid_to;
-     int allow_hwreg;
+find_last_value (rtx x, rtx *pinsn, rtx valid_to, int allow_hwreg)
 {
   rtx p;
 
@@ -1460,10 +1410,8 @@ find_last_value (x, pinsn, valid_to, allow_hwreg)
    LOC may be zero, meaning don't ignore anything.  */
 
 int
-refers_to_regno_p (regno, endregno, x, loc)
-     unsigned int regno, endregno;
-     rtx x;
-     rtx *loc;
+refers_to_regno_p (unsigned int regno, unsigned int endregno, rtx x,
+                  rtx *loc)
 {
   int i;
   unsigned int x_regno;
@@ -1496,7 +1444,7 @@ refers_to_regno_p (regno, endregno, x, loc)
 
       return (endregno > x_regno
              && regno < x_regno + (x_regno < FIRST_PSEUDO_REGISTER
-                                   ? HARD_REGNO_NREGS (x_regno, GET_MODE (x))
+                                   ? hard_regno_nregs[x_regno][GET_MODE (x)]
                              : 1));
 
     case SUBREG:
@@ -1508,7 +1456,7 @@ refers_to_regno_p (regno, endregno, x, loc)
          unsigned int inner_regno = subreg_regno (x);
          unsigned int inner_endregno
            = inner_regno + (inner_regno < FIRST_PSEUDO_REGISTER
-                            ? HARD_REGNO_NREGS (regno, GET_MODE (x)) : 1);
+                            ? hard_regno_nregs[inner_regno][GET_MODE (x)] : 1);
 
          return endregno > inner_regno && regno < inner_endregno;
        }
@@ -1558,7 +1506,7 @@ refers_to_regno_p (regno, endregno, x, loc)
       else if (fmt[i] == 'E')
        {
          int j;
-         for (j = XVECLEN (x, i) - 1; j >=0; j--)
+         for (j = XVECLEN (x, i) - 1; j >= 0; j--)
            if (loc != &XVECEXP (x, i, j)
                && refers_to_regno_p (regno, endregno, XVECEXP (x, i, j), loc))
              return 1;
@@ -1574,21 +1522,26 @@ refers_to_regno_p (regno, endregno, x, loc)
    conflict because we expect this to be a rare case.  */
 
 int
-reg_overlap_mentioned_p (x, in)
-     rtx x, in;
+reg_overlap_mentioned_p (rtx x, rtx in)
 {
   unsigned int regno, endregno;
 
-  /* Overly conservative.  */
-  if (GET_CODE (x) == STRICT_LOW_PART)
-    x = XEXP (x, 0);
-
-  /* If either argument is a constant, then modifying X can not affect IN.  */
-  if (CONSTANT_P (x) || CONSTANT_P (in))
+  /* If either argument is a constant, then modifying X can not
+     affect IN.  Here we look at IN, we can profitably combine
+     CONSTANT_P (x) with the switch statement below.  */
+  if (CONSTANT_P (in))
     return 0;
 
+ recurse:
   switch (GET_CODE (x))
     {
+    case STRICT_LOW_PART:
+    case ZERO_EXTRACT:
+    case SIGN_EXTRACT:
+      /* Overly conservative.  */
+      x = XEXP (x, 0);
+      goto recurse;
+
     case SUBREG:
       regno = REGNO (SUBREG_REG (x));
       if (regno < FIRST_PSEUDO_REGISTER)
@@ -1599,7 +1552,7 @@ reg_overlap_mentioned_p (x, in)
       regno = REGNO (x);
     do_reg:
       endregno = regno + (regno < FIRST_PSEUDO_REGISTER
-                         ? HARD_REGNO_NREGS (regno, GET_MODE (x)) : 1);
+                         ? hard_regno_nregs[regno][GET_MODE (x)] : 1);
       return refers_to_regno_p (regno, endregno, in, (rtx*) 0);
 
     case MEM:
@@ -1631,65 +1584,18 @@ reg_overlap_mentioned_p (x, in)
        for (i = XVECLEN (x, 0) - 1; i >= 0; i--)
          if (XEXP (XVECEXP (x, 0, i), 0) != 0
              && reg_overlap_mentioned_p (XEXP (XVECEXP (x, 0, i), 0), in))
-             return 1;
+           return 1;
        return 0;
       }
 
     default:
-      break;
-    }
-
-  abort ();
-}
-\f
-/* Return the last value to which REG was set prior to INSN.  If we can't
-   find it easily, return 0.
-
-   We only return a REG, SUBREG, or constant because it is too hard to
-   check if a MEM remains unchanged.  */
-
-rtx
-reg_set_last (x, insn)
-     rtx x;
-     rtx insn;
-{
-  rtx orig_insn = insn;
-
-  /* Scan backwards until reg_set_last_1 changed one of the above flags.
-     Stop when we reach a label or X is a hard reg and we reach a
-     CALL_INSN (if reg_set_last_last_regno is a hard reg).
-
-     If we find a set of X, ensure that its SET_SRC remains unchanged.  */
-
-  /* We compare with <= here, because reg_set_last_last_regno
-     is actually the number of the first reg *not* in X.  */
-  for (;
-       insn && GET_CODE (insn) != CODE_LABEL
-       && ! (GET_CODE (insn) == CALL_INSN
-            && REGNO (x) <= FIRST_PSEUDO_REGISTER);
-       insn = PREV_INSN (insn))
-    if (INSN_P (insn))
-      {
-       rtx set = set_of (x, insn);
-       /* OK, this function modify our register.  See if we understand it.  */
-       if (set)
-         {
-           rtx last_value;
-           if (GET_CODE (set) != SET || SET_DEST (set) != x)
-             return 0;
-           last_value = SET_SRC (x);
-           if (CONSTANT_P (last_value)
-               || ((GET_CODE (last_value) == REG
-                    || GET_CODE (last_value) == SUBREG)
-                   && ! reg_set_between_p (last_value,
-                                           insn, orig_insn)))
-             return last_value;
-           else
-             return 0;
-         }
-      }
+#ifdef ENABLE_CHECKING
+      if (!CONSTANT_P (x))
+       abort ();
+#endif
 
-  return 0;
+      return 0;
+    }
 }
 \f
 /* Call FUN on each register or MEM that is stored into or clobbered by X.
@@ -1702,10 +1608,7 @@ reg_set_last (x, insn)
   the SUBREG will be passed.  */
 
 void
-note_stores (x, fun, data)
-     rtx x;
-     void (*fun) PARAMS ((rtx, rtx, void *));
-     void *data;
+note_stores (rtx x, void (*fun) (rtx, rtx, void *), void *data)
 {
   int i;
 
@@ -1751,10 +1654,7 @@ note_stores (x, fun, data)
    partially set, while we do not.  */
 
 void
-note_uses (pbody, fun, data)
-     rtx *pbody;
-     void (*fun) PARAMS ((rtx *, void *));
-     void *data;
+note_uses (rtx *pbody, void (*fun) (rtx *, void *), void *data)
 {
   rtx body = *pbody;
   int i;
@@ -1846,9 +1746,7 @@ note_uses (pbody, fun, data)
    by INSN.  */
 
 int
-dead_or_set_p (insn, x)
-     rtx insn;
-     rtx x;
+dead_or_set_p (rtx insn, rtx x)
 {
   unsigned int regno, last_regno;
   unsigned int i;
@@ -1862,7 +1760,7 @@ dead_or_set_p (insn, x)
 
   regno = REGNO (x);
   last_regno = (regno >= FIRST_PSEUDO_REGISTER ? regno
-               : regno + HARD_REGNO_NREGS (regno, GET_MODE (x)) - 1);
+               : regno + hard_regno_nregs[regno][GET_MODE (x)] - 1);
 
   for (i = regno; i <= last_regno; i++)
     if (! dead_or_set_regno_p (insn, i))
@@ -1875,9 +1773,7 @@ dead_or_set_p (insn, x)
    called from flow.c.  */
 
 int
-dead_or_set_regno_p (insn, test_regno)
-     rtx insn;
-     unsigned int test_regno;
+dead_or_set_regno_p (rtx insn, unsigned int test_regno)
 {
   unsigned int regno, endregno;
   rtx pattern;
@@ -1914,7 +1810,7 @@ dead_or_set_regno_p (insn, test_regno)
 
       regno = REGNO (dest);
       endregno = (regno >= FIRST_PSEUDO_REGISTER ? regno + 1
-                 : regno + HARD_REGNO_NREGS (regno, GET_MODE (dest)));
+                 : regno + hard_regno_nregs[regno][GET_MODE (dest)]);
 
       return (test_regno >= regno && test_regno < endregno);
     }
@@ -1945,7 +1841,7 @@ dead_or_set_regno_p (insn, test_regno)
 
              regno = REGNO (dest);
              endregno = (regno >= FIRST_PSEUDO_REGISTER ? regno + 1
-                         : regno + HARD_REGNO_NREGS (regno, GET_MODE (dest)));
+                         : regno + hard_regno_nregs[regno][GET_MODE (dest)]);
 
              if (test_regno >= regno && test_regno < endregno)
                return 1;
@@ -1960,20 +1856,23 @@ dead_or_set_regno_p (insn, test_regno)
    If DATUM is nonzero, look for one whose datum is DATUM.  */
 
 rtx
-find_reg_note (insn, kind, datum)
-     rtx insn;
-     enum reg_note kind;
-     rtx datum;
+find_reg_note (rtx insn, enum reg_note kind, rtx datum)
 {
   rtx link;
 
   /* Ignore anything that is not an INSN, JUMP_INSN or CALL_INSN.  */
   if (! INSN_P (insn))
     return 0;
+  if (datum == 0)
+    {
+      for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
+       if (REG_NOTE_KIND (link) == kind)
+         return link;
+      return 0;
+    }
 
   for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
-    if (REG_NOTE_KIND (link) == kind
-       && (datum == 0 || datum == XEXP (link, 0)))
+    if (REG_NOTE_KIND (link) == kind && datum == XEXP (link, 0))
       return link;
   return 0;
 }
@@ -1984,10 +1883,7 @@ find_reg_note (insn, kind, datum)
    it might be the case that the note overlaps REGNO.  */
 
 rtx
-find_regno_note (insn, kind, regno)
-     rtx insn;
-     enum reg_note kind;
-     unsigned int regno;
+find_regno_note (rtx insn, enum reg_note kind, unsigned int regno)
 {
   rtx link;
 
@@ -2003,8 +1899,8 @@ find_regno_note (insn, kind, regno)
        && REGNO (XEXP (link, 0)) <= regno
        && ((REGNO (XEXP (link, 0))
             + (REGNO (XEXP (link, 0)) >= FIRST_PSEUDO_REGISTER ? 1
-               : HARD_REGNO_NREGS (REGNO (XEXP (link, 0)),
-                                   GET_MODE (XEXP (link, 0)))))
+               : hard_regno_nregs[REGNO (XEXP (link, 0))]
+                                 [GET_MODE (XEXP (link, 0))]))
            > regno))
       return link;
   return 0;
@@ -2014,27 +1910,28 @@ find_regno_note (insn, kind, regno)
    has such a note.  */
 
 rtx
-find_reg_equal_equiv_note (insn)
-     rtx insn;
+find_reg_equal_equiv_note (rtx insn)
 {
-  rtx note;
+  rtx link;
 
-  if (single_set (insn) == 0)
+  if (!INSN_P (insn))
     return 0;
-  else if ((note = find_reg_note (insn, REG_EQUIV, NULL_RTX)) != 0)
-    return note;
-  else
-    return find_reg_note (insn, REG_EQUAL, NULL_RTX);
+  for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
+    if (REG_NOTE_KIND (link) == REG_EQUAL
+       || REG_NOTE_KIND (link) == REG_EQUIV)
+      {
+       if (single_set (insn) == 0)
+         return 0;
+       return link;
+      }
+  return NULL;
 }
 
 /* Return true if DATUM, or any overlap of DATUM, of kind CODE is found
    in the CALL_INSN_FUNCTION_USAGE information of INSN.  */
 
 int
-find_reg_fusage (insn, code, datum)
-     rtx insn;
-     enum rtx_code code;
-     rtx datum;
+find_reg_fusage (rtx insn, enum rtx_code code, rtx datum)
 {
   /* If it's not a CALL_INSN, it can't possibly have a
      CALL_INSN_FUNCTION_USAGE field, so don't bother checking.  */
@@ -2065,7 +1962,7 @@ find_reg_fusage (insn, code, datum)
       if (regno < FIRST_PSEUDO_REGISTER)
        {
          unsigned int end_regno
-           = regno + HARD_REGNO_NREGS (regno, GET_MODE (datum));
+           = regno + hard_regno_nregs[regno][GET_MODE (datum)];
          unsigned int i;
 
          for (i = regno; i < end_regno; i++)
@@ -2081,10 +1978,7 @@ find_reg_fusage (insn, code, datum)
    in the CALL_INSN_FUNCTION_USAGE information of INSN.  */
 
 int
-find_regno_fusage (insn, code, regno)
-     rtx insn;
-     enum rtx_code code;
-     unsigned int regno;
+find_regno_fusage (rtx insn, enum rtx_code code, unsigned int regno)
 {
   rtx link;
 
@@ -2103,7 +1997,7 @@ find_regno_fusage (insn, code, regno)
       if (GET_CODE (op = XEXP (link, 0)) == code
          && GET_CODE (reg = XEXP (op, 0)) == REG
          && (regnote = REGNO (reg)) <= regno
-         && regnote + HARD_REGNO_NREGS (regnote, GET_MODE (reg)) > regno)
+         && regnote + hard_regno_nregs[regnote][GET_MODE (reg)] > regno)
        return 1;
     }
 
@@ -2113,8 +2007,7 @@ find_regno_fusage (insn, code, regno)
 /* Return true if INSN is a call to a pure function.  */
 
 int
-pure_call_p (insn)
-     rtx insn;
+pure_call_p (rtx insn)
 {
   rtx link;
 
@@ -2138,9 +2031,7 @@ pure_call_p (insn)
 /* Remove register note NOTE from the REG_NOTES of INSN.  */
 
 void
-remove_note (insn, note)
-     rtx insn;
-     rtx note;
+remove_note (rtx insn, rtx note)
 {
   rtx link;
 
@@ -2168,9 +2059,7 @@ remove_note (insn, note)
    NODE matches.  */
 
 int
-in_expr_list_p (listp, node)
-     rtx listp;
-     rtx node;
+in_expr_list_p (rtx listp, rtx node)
 {
   rtx x;
 
@@ -2187,9 +2076,7 @@ in_expr_list_p (listp, node)
    A simple equality test is used to determine if NODE matches.  */
 
 void
-remove_node_from_expr_list (node, listp)
-     rtx node;
-     rtx *listp;
+remove_node_from_expr_list (rtx node, rtx *listp)
 {
   rtx temp = *listp;
   rtx prev = NULL_RTX;
@@ -2218,8 +2105,7 @@ remove_node_from_expr_list (node, listp)
    only volatile asms and UNSPEC_VOLATILE instructions.  */
 
 int
-volatile_insn_p (x)
-     rtx x;
+volatile_insn_p (rtx x)
 {
   RTX_CODE code;
 
@@ -2285,8 +2171,7 @@ volatile_insn_p (x)
    UNSPEC_VOLATILE operations or volatile ASM_OPERANDS expressions.  */
 
 int
-volatile_refs_p (x)
-     rtx x;
+volatile_refs_p (rtx x)
 {
   RTX_CODE code;
 
@@ -2350,8 +2235,7 @@ volatile_refs_p (x)
    incrementing.  */
 
 int
-side_effects_p (x)
-     rtx x;
+side_effects_p (rtx x)
 {
   RTX_CODE code;
 
@@ -2427,8 +2311,7 @@ side_effects_p (x)
 /* Return nonzero if evaluating rtx X might cause a trap.  */
 
 int
-may_trap_p (x)
-     rtx x;
+may_trap_p (rtx x)
 {
   int i;
   enum rtx_code code;
@@ -2462,6 +2345,8 @@ may_trap_p (x)
 
       /* Memory ref can trap unless it's a static var or a stack slot.  */
     case MEM:
+      if (MEM_NOTRAP_P (x))
+       return 0;
       return rtx_addr_can_trap_p (XEXP (x, 0));
 
       /* Division by a non-constant might trap.  */
@@ -2475,9 +2360,7 @@ may_trap_p (x)
          || (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT
              && flag_trapping_math))
        return 1;
-      /* This was const0_rtx, but by not using that,
-        we can link this file into other programs.  */
-      if (GET_CODE (XEXP (x, 1)) == CONST_INT && INTVAL (XEXP (x, 1)) == 0)
+      if (XEXP (x, 1) == const0_rtx)
        return 1;
       break;
 
@@ -2517,6 +2400,12 @@ may_trap_p (x)
        return 1;
       break;
 
+    case FIX:
+      /* Conversion of floating point might trap.  */
+      if (flag_trapping_math && HONOR_NANS (GET_MODE (XEXP (x, 0))))
+       return 1;
+      break;
+
     case NEG:
     case ABS:
       /* These operations don't trap even with floating point.  */
@@ -2552,8 +2441,7 @@ may_trap_p (x)
    i.e., an inequality.  */
 
 int
-inequality_comparisons_p (x)
-     rtx x;
+inequality_comparisons_p (rtx x)
 {
   const char *fmt;
   int len, i;
@@ -2616,8 +2504,7 @@ inequality_comparisons_p (x)
    are to be modified.  */
 
 rtx
-replace_rtx (x, from, to)
-     rtx x, from, to;
+replace_rtx (rtx x, rtx from, rtx to)
 {
   int i, j;
   const char *fmt;
@@ -2694,11 +2581,7 @@ replace_rtx (x, from, to)
    otherwise, only sources are replaced.  */
 
 rtx
-replace_regs (x, reg_map, nregs, replace_dest)
-     rtx x;
-     rtx *reg_map;
-     unsigned int nregs;
-     int replace_dest;
+replace_regs (rtx x, rtx *reg_map, unsigned int nregs, int replace_dest)
 {
   enum rtx_code code;
   int i;
@@ -2785,13 +2668,130 @@ replace_regs (x, reg_map, nregs, replace_dest)
   return x;
 }
 
+/* Replace occurrences of the old label in *X with the new one.
+   DATA is a REPLACE_LABEL_DATA containing the old and new labels.  */
+
+int
+replace_label (rtx *x, void *data)
+{
+  rtx l = *x;
+  rtx old_label = ((replace_label_data *) data)->r1;
+  rtx new_label = ((replace_label_data *) data)->r2;
+  bool update_label_nuses = ((replace_label_data *) data)->update_label_nuses;
+
+  if (l == NULL_RTX)
+    return 0;
+
+  if (GET_CODE (l) == SYMBOL_REF
+      && CONSTANT_POOL_ADDRESS_P (l))
+    {
+      rtx c = get_pool_constant (l);
+      if (rtx_referenced_p (old_label, c))
+       {
+         rtx new_c, new_l;
+         replace_label_data *d = (replace_label_data *) data;
+
+         /* Create a copy of constant C; replace the label inside
+            but do not update LABEL_NUSES because uses in constant pool
+            are not counted.  */
+         new_c = copy_rtx (c);
+         d->update_label_nuses = false;
+         for_each_rtx (&new_c, replace_label, data);
+         d->update_label_nuses = update_label_nuses;
+
+         /* Add the new constant NEW_C to constant pool and replace
+            the old reference to constant by new reference.  */
+         new_l = XEXP (force_const_mem (get_pool_mode (l), new_c), 0);
+         *x = replace_rtx (l, l, new_l);
+       }
+      return 0;
+    }
+
+  /* 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.  */
+  if (GET_CODE (l) == JUMP_INSN && JUMP_LABEL (l) == old_label)
+    JUMP_LABEL (l) = new_label;
+
+  if ((GET_CODE (l) == LABEL_REF
+       || GET_CODE (l) == INSN_LIST)
+      && XEXP (l, 0) == old_label)
+    {
+      XEXP (l, 0) = new_label;
+      if (update_label_nuses)
+       {
+         ++LABEL_NUSES (new_label);
+         --LABEL_NUSES (old_label);
+       }
+      return 0;
+    }
+
+  return 0;
+}
+
+/* When *BODY is equal to X or X is directly referenced by *BODY
+   return nonzero, thus FOR_EACH_RTX stops traversing and returns nonzero
+   too, otherwise FOR_EACH_RTX continues traversing *BODY.  */
+
+static int
+rtx_referenced_p_1 (rtx *body, void *x)
+{
+  rtx y = (rtx) x;
+
+  if (*body == NULL_RTX)
+    return y == NULL_RTX;
+
+  /* Return true if a label_ref *BODY refers to label Y.  */
+  if (GET_CODE (*body) == LABEL_REF && GET_CODE (y) == CODE_LABEL)
+    return XEXP (*body, 0) == y;
+
+  /* If *BODY is a reference to pool constant traverse the constant.  */
+  if (GET_CODE (*body) == SYMBOL_REF
+      && CONSTANT_POOL_ADDRESS_P (*body))
+    return rtx_referenced_p (y, get_pool_constant (*body));
+
+  /* By default, compare the RTL expressions.  */
+  return rtx_equal_p (*body, y);
+}
+
+/* Return true if X is referenced in BODY.  */
+
+int
+rtx_referenced_p (rtx x, rtx body)
+{
+  return for_each_rtx (&body, rtx_referenced_p_1, x);
+}
+
+/* If INSN is a tablejump return true and store the label (before jump table) to
+   *LABELP and the jump table to *TABLEP.  LABELP and TABLEP may be NULL.  */
+
+bool
+tablejump_p (rtx insn, rtx *labelp, rtx *tablep)
+{
+  rtx label, table;
+
+  if (GET_CODE (insn) == JUMP_INSN
+      && (label = JUMP_LABEL (insn)) != NULL_RTX
+      && (table = next_active_insn (label)) != NULL_RTX
+      && GET_CODE (table) == JUMP_INSN
+      && (GET_CODE (PATTERN (table)) == ADDR_VEC
+         || GET_CODE (PATTERN (table)) == ADDR_DIFF_VEC))
+    {
+      if (labelp)
+       *labelp = label;
+      if (tablep)
+       *tablep = table;
+      return true;
+    }
+  return false;
+}
+
 /* A subroutine of computed_jump_p, return 1 if X contains a REG or MEM or
    constant that is not in the constant pool and not in the condition
    of an IF_THEN_ELSE.  */
 
 static int
-computed_jump_p_1 (x)
-     rtx x;
+computed_jump_p_1 (rtx x)
 {
   enum rtx_code code = GET_CODE (x);
   int i, j;
@@ -2845,8 +2845,7 @@ computed_jump_p_1 (x)
    we can recognize them by a (use (label_ref)).  */
 
 int
-computed_jump_p (insn)
-     rtx insn;
+computed_jump_p (rtx insn)
 {
   int i;
   if (GET_CODE (insn) == JUMP_INSN)
@@ -2895,10 +2894,7 @@ computed_jump_p (insn)
    implement many of the other routines in this file.  */
 
 int
-for_each_rtx (x, f, data)
-     rtx *x;
-     rtx_function f;
-     void *data;
+for_each_rtx (rtx *x, rtx_function f, void *data)
 {
   int result;
   int length;
@@ -2959,9 +2955,7 @@ for_each_rtx (x, f, data)
    reference found if any.  Otherwise, returns NULL_RTX.  */
 
 rtx
-regno_use_in (regno, x)
-     unsigned int regno;
-     rtx x;
+regno_use_in (unsigned int regno, rtx x)
 {
   const char *fmt;
   int i, j;
@@ -2994,43 +2988,69 @@ regno_use_in (regno, x)
    and positive values for the second operand.  */
 
 int
-commutative_operand_precedence (op)
-     rtx op;
+commutative_operand_precedence (rtx op)
 {
+  enum rtx_code code = GET_CODE (op);
+  
   /* Constants always come the second operand.  Prefer "nice" constants.  */
-  if (GET_CODE (op) == CONST_INT)
-    return -5;
-  if (GET_CODE (op) == CONST_DOUBLE)
-    return -4;
-  if (CONSTANT_P (op))
-    return -3;
-
-  /* SUBREGs of objects should come second.  */
-  if (GET_CODE (op) == SUBREG
-      && GET_RTX_CLASS (GET_CODE (SUBREG_REG (op))) == 'o')
-    return -2;
-
-  /* If only one operand is a `neg', `not',
-    `mult', `plus', or `minus' expression, it will be the first
-    operand.  */
-  if (GET_CODE (op) == NEG || GET_CODE (op) == NOT
-      || GET_CODE (op) == MULT || GET_CODE (op) == PLUS
-      || GET_CODE (op) == MINUS)
-    return 2;
-
-  /* Complex expressions should be the first, so decrease priority
-     of objects.  */
-  if (GET_RTX_CLASS (GET_CODE (op)) == 'o')
-    return -1;
-  return 0;
+  if (code == CONST_INT)
+    return -7;
+  if (code == CONST_DOUBLE)
+    return -6;
+  op = avoid_constant_pool_reference (op);
+
+  switch (GET_RTX_CLASS (code))
+    {
+    case RTX_CONST_OBJ:
+      if (code == CONST_INT)
+        return -5;
+      if (code == CONST_DOUBLE)
+        return -4;
+      return -3;
+
+    case RTX_EXTRA:
+      /* SUBREGs of objects should come second.  */
+      if (code == SUBREG && OBJECT_P (SUBREG_REG (op)))
+        return -2;
+
+      if (!CONSTANT_P (op))
+        return 0;
+      else
+       /* As for RTX_CONST_OBJ.  */
+       return -3;
+
+    case RTX_OBJ:
+      /* Complex expressions should be the first, so decrease priority
+         of objects.  */
+      return -1;
+
+    case RTX_COMM_ARITH:
+      /* Prefer operands that are themselves commutative to be first.
+         This helps to make things linear.  In particular,
+         (and (and (reg) (reg)) (not (reg))) is canonical.  */
+      return 4;
+
+    case RTX_BIN_ARITH:
+      /* If only one operand is a binary expression, it will be the first
+         operand.  In particular,  (plus (minus (reg) (reg)) (neg (reg)))
+         is canonical, although it will usually be further simplified.  */
+      return 2;
+  
+    case RTX_UNARY:
+      /* Then prefer NEG and NOT.  */
+      if (code == NEG || code == NOT)
+        return 1;
+
+    default:
+      return 0;
+    }
 }
 
 /* Return 1 iff it is necessary to swap operands of commutative operation
    in order to canonicalize expression.  */
 
 int
-swap_commutative_operands_p (x, y)
-     rtx x, y;
+swap_commutative_operands_p (rtx x, rtx y)
 {
   return (commutative_operand_precedence (x)
          < commutative_operand_precedence (y));
@@ -3039,8 +3059,7 @@ swap_commutative_operands_p (x, y)
 /* Return 1 if X is an autoincrement side effect and the register is
    not the stack pointer.  */
 int
-auto_inc_p (x)
-     rtx x;
+auto_inc_p (rtx x)
 {
   switch (GET_CODE (x))
     {
@@ -3070,10 +3089,7 @@ auto_inc_p (x)
    conditions as well.  */
 
 int
-insns_safe_to_move_p (from, to, new_to)
-     rtx from;
-     rtx to;
-     rtx *new_to;
+insns_safe_to_move_p (rtx from, rtx to, rtx *new_to)
 {
   int eh_region_count = 0;
   int past_to_p = 0;
@@ -3138,10 +3154,9 @@ insns_safe_to_move_p (from, to, new_to)
   return 0;
 }
 
-/* Return nonzero if IN contains a piece of rtl that has the address LOC */
+/* Return nonzero if IN contains a piece of rtl that has the address LOC */
 int
-loc_mentioned_in_p (loc, in)
-     rtx *loc, in;
+loc_mentioned_in_p (rtx *loc, rtx in)
 {
   enum rtx_code code = GET_CODE (in);
   const char *fmt = GET_RTX_FORMAT (code);
@@ -3149,7 +3164,7 @@ loc_mentioned_in_p (loc, in)
 
   for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
     {
-      if (loc == &in->fld[i].rtx)
+      if (loc == &in->u.fld[i].rtx)
        return 1;
       if (fmt[i] == 'e')
        {
@@ -3164,49 +3179,59 @@ loc_mentioned_in_p (loc, in)
   return 0;
 }
 
-/* Given a subreg X, return the bit offset where the subreg begins
-   (counting from the least significant bit of the reg).  */
+/* Helper function for subreg_lsb.  Given a subreg's OUTER_MODE, INNER_MODE,
+   and SUBREG_BYTE, return the bit offset where the subreg begins
+   (counting from the least significant bit of the operand).  */
 
 unsigned int
-subreg_lsb (x)
-     rtx x;
+subreg_lsb_1 (enum machine_mode outer_mode,
+             enum machine_mode inner_mode,
+             unsigned int subreg_byte)
 {
-  enum machine_mode inner_mode = GET_MODE (SUBREG_REG (x));
-  enum machine_mode mode = GET_MODE (x);
   unsigned int bitpos;
   unsigned int byte;
   unsigned int word;
 
   /* A paradoxical subreg begins at bit position 0.  */
-  if (GET_MODE_BITSIZE (mode) > GET_MODE_BITSIZE (inner_mode))
+  if (GET_MODE_BITSIZE (outer_mode) > GET_MODE_BITSIZE (inner_mode))
     return 0;
 
   if (WORDS_BIG_ENDIAN != BYTES_BIG_ENDIAN)
     /* If the subreg crosses a word boundary ensure that
        it also begins and ends on a word boundary.  */
-    if ((SUBREG_BYTE (x) % UNITS_PER_WORD
-        + GET_MODE_SIZE (mode)) > UNITS_PER_WORD
-       && (SUBREG_BYTE (x) % UNITS_PER_WORD
-           || GET_MODE_SIZE (mode) % UNITS_PER_WORD))
+    if ((subreg_byte % UNITS_PER_WORD
+        + GET_MODE_SIZE (outer_mode)) > UNITS_PER_WORD
+       && (subreg_byte % UNITS_PER_WORD
+           || GET_MODE_SIZE (outer_mode) % UNITS_PER_WORD))
        abort ();
 
   if (WORDS_BIG_ENDIAN)
     word = (GET_MODE_SIZE (inner_mode)
-           - (SUBREG_BYTE (x) + GET_MODE_SIZE (mode))) / UNITS_PER_WORD;
+           - (subreg_byte + GET_MODE_SIZE (outer_mode))) / UNITS_PER_WORD;
   else
-    word = SUBREG_BYTE (x) / UNITS_PER_WORD;
+    word = subreg_byte / UNITS_PER_WORD;
   bitpos = word * BITS_PER_WORD;
 
   if (BYTES_BIG_ENDIAN)
     byte = (GET_MODE_SIZE (inner_mode)
-           - (SUBREG_BYTE (x) + GET_MODE_SIZE (mode))) % UNITS_PER_WORD;
+           - (subreg_byte + GET_MODE_SIZE (outer_mode))) % UNITS_PER_WORD;
   else
-    byte = SUBREG_BYTE (x) % UNITS_PER_WORD;
+    byte = subreg_byte % UNITS_PER_WORD;
   bitpos += byte * BITS_PER_UNIT;
 
   return bitpos;
 }
 
+/* Given a subreg X, return the bit offset where the subreg begins
+   (counting from the least significant bit of the reg).  */
+
+unsigned int
+subreg_lsb (rtx x)
+{
+  return subreg_lsb_1 (GET_MODE (x), GET_MODE (SUBREG_REG (x)),
+                      SUBREG_BYTE (x));
+}
+
 /* This function returns the regno offset of a subreg expression.
    xregno - A regno of an inner hard subreg_reg (or what will become one).
    xmode  - The mode of xregno.
@@ -3214,11 +3239,8 @@ subreg_lsb (x)
    ymode  - The mode of a top level SUBREG (or what may become one).
    RETURN - The regno offset which would be used.  */
 unsigned int
-subreg_regno_offset (xregno, xmode, offset, ymode)
-     unsigned int xregno;
-     enum machine_mode xmode;
-     unsigned int offset;
-     enum machine_mode ymode;
+subreg_regno_offset (unsigned int xregno, enum machine_mode xmode,
+                    unsigned int offset, enum machine_mode ymode)
 {
   int nregs_xmode, nregs_ymode;
   int mode_multiple, nregs_multiple;
@@ -3227,8 +3249,8 @@ subreg_regno_offset (xregno, xmode, offset, ymode)
   if (xregno >= FIRST_PSEUDO_REGISTER)
     abort ();
 
-  nregs_xmode = HARD_REGNO_NREGS (xregno, xmode);
-  nregs_ymode = HARD_REGNO_NREGS (xregno, ymode);
+  nregs_xmode = hard_regno_nregs[xregno][xmode];
+  nregs_ymode = hard_regno_nregs[xregno][ymode];
 
   /* If this is a big endian paradoxical subreg, which uses more actual
      hard registers than the original register, we must return a negative
@@ -3252,10 +3274,74 @@ subreg_regno_offset (xregno, xmode, offset, ymode)
   return (y_offset / (mode_multiple / nregs_multiple)) * nregs_ymode;
 }
 
+/* This function returns true when the offset is representable via
+   subreg_offset in the given regno.
+   xregno - A regno of an inner hard subreg_reg (or what will become one).
+   xmode  - The mode of xregno.
+   offset - The byte offset.
+   ymode  - The mode of a top level SUBREG (or what may become one).
+   RETURN - The regno offset which would be used.  */
+bool
+subreg_offset_representable_p (unsigned int xregno, enum machine_mode xmode,
+                              unsigned int offset, enum machine_mode ymode)
+{
+  int nregs_xmode, nregs_ymode;
+  int mode_multiple, nregs_multiple;
+  int y_offset;
+
+  if (xregno >= FIRST_PSEUDO_REGISTER)
+    abort ();
+
+  nregs_xmode = hard_regno_nregs[xregno][xmode];
+  nregs_ymode = hard_regno_nregs[xregno][ymode];
+
+  /* Paradoxical subregs are always valid.  */
+  if (offset == 0
+      && nregs_ymode > nregs_xmode
+      && (GET_MODE_SIZE (ymode) > UNITS_PER_WORD
+         ? WORDS_BIG_ENDIAN : BYTES_BIG_ENDIAN))
+    return true;
+
+  /* Lowpart subregs are always valid.  */
+  if (offset == subreg_lowpart_offset (ymode, xmode))
+    return true;
+
+#ifdef ENABLE_CHECKING
+  /* This should always pass, otherwise we don't know how to verify the
+     constraint.  These conditions may be relaxed but subreg_offset would
+     need to be redesigned.  */
+  if (GET_MODE_SIZE (xmode) % GET_MODE_SIZE (ymode)
+      || GET_MODE_SIZE (ymode) % nregs_ymode
+      || nregs_xmode % nregs_ymode)
+    abort ();
+#endif
+
+  /* The XMODE value can be seen as a vector of NREGS_XMODE
+     values.  The subreg must represent a lowpart of given field.
+     Compute what field it is.  */
+  offset -= subreg_lowpart_offset (ymode,
+                                  mode_for_size (GET_MODE_BITSIZE (xmode)
+                                                 / nregs_xmode,
+                                                 MODE_INT, 0));
+
+  /* size of ymode must not be greater than the size of xmode.  */
+  mode_multiple = GET_MODE_SIZE (xmode) / GET_MODE_SIZE (ymode);
+  if (mode_multiple == 0)
+    abort ();
+
+  y_offset = offset / GET_MODE_SIZE (ymode);
+  nregs_multiple =  nregs_xmode / nregs_ymode;
+#ifdef ENABLE_CHECKING
+  if (offset % GET_MODE_SIZE (ymode)
+      || mode_multiple % nregs_multiple)
+    abort ();
+#endif
+  return (!(y_offset % (mode_multiple / nregs_multiple)));
+}
+
 /* Return the final regno that a subreg expression refers to.  */
 unsigned int
-subreg_regno (x)
-     rtx x;
+subreg_regno (rtx x)
 {
   unsigned int ret;
   rtx subreg = SUBREG_REG (x);
@@ -3276,9 +3362,7 @@ struct parms_set_data
 
 /* Helper function for noticing stores to parameter registers.  */
 static void
-parms_set (x, pat, data)
-       rtx x, pat ATTRIBUTE_UNUSED;
-       void *data;
+parms_set (rtx x, rtx pat ATTRIBUTE_UNUSED, void *data)
 {
   struct parms_set_data *d = data;
   if (REG_P (x) && REGNO (x) < FIRST_PSEUDO_REGISTER
@@ -3292,8 +3376,7 @@ parms_set (x, pat, data)
 /* Look backward for first parameter to be loaded.
    Do not skip BOUNDARY.  */
 rtx
-find_first_parameter_load (call_insn, boundary)
-     rtx call_insn, boundary;
+find_first_parameter_load (rtx call_insn, rtx boundary)
 {
   struct parms_set_data parm;
   rtx p, before;
@@ -3351,8 +3434,7 @@ find_first_parameter_load (call_insn, boundary)
    call instruction.  */
 
 bool
-keep_with_call_p (insn)
-     rtx insn;
+keep_with_call_p (rtx insn)
 {
   rtx set;
 
@@ -3386,9 +3468,7 @@ keep_with_call_p (insn)
    whose value will be used.  */
 
 static bool
-hoist_test_store (x, val, live)
-     rtx x, val;
-     regset live;
+hoist_test_store (rtx x, rtx val, regset live)
 {
   if (GET_CODE (x) == SCRATCH)
     return true;
@@ -3396,7 +3476,7 @@ hoist_test_store (x, val, live)
   if (rtx_equal_p (x, val))
     return true;
 
-  /* Allow subreg of X in case it is not writting just part of multireg pseudo.
+  /* Allow subreg of X in case it is not writing just part of multireg pseudo.
      Then we would need to update all users to care hoisting the store too.
      Caller may represent that by specifying whole subreg as val.  */
 
@@ -3417,15 +3497,15 @@ hoist_test_store (x, val, live)
   if (!REG_P (x))
     return false;
 
-  /* Pseudo registers can be allways replaced by another pseudo to avoid
+  /* Pseudo registers can be always replaced by another pseudo to avoid
      the side effect, for hard register we must ensure that they are dead.
      Eventually we may want to add code to try turn pseudos to hards, but it
-     is unlikely usefull.  */
+     is unlikely useful.  */
 
   if (REGNO (x) < FIRST_PSEUDO_REGISTER)
     {
       int regno = REGNO (x);
-      int n = HARD_REGNO_NREGS (regno, GET_MODE (x));
+      int n = hard_regno_nregs[regno][GET_MODE (x)];
 
       if (!live)
        return false;
@@ -3444,9 +3524,7 @@ hoist_test_store (x, val, live)
    and used by the hoisting pass.  */
 
 bool
-can_hoist_insn_p (insn, val, live)
-     rtx insn, val;
-     regset live;
+can_hoist_insn_p (rtx insn, rtx val, regset live)
 {
   rtx pat = PATTERN (insn);
   int i;
@@ -3489,7 +3567,7 @@ can_hoist_insn_p (insn, val, live)
              break;
            case USE:
              /* We need to fix callers to really ensure availability
-                of all values inisn uses, but for now it is safe to prohibit
+                of all values insn uses, but for now it is safe to prohibit
                 hoisting of any insn having such a hidden uses.  */
              return false;
              break;
@@ -3513,8 +3591,7 @@ can_hoist_insn_p (insn, val, live)
    be updated to NEW.  */
 
 static void
-hoist_update_store (insn, xp, val, new)
-     rtx insn, *xp, val, new;
+hoist_update_store (rtx insn, rtx *xp, rtx val, rtx new)
 {
   rtx x = *xp;
 
@@ -3551,8 +3628,7 @@ hoist_update_store (insn, xp, val, new)
    and each other side effect to pseudo register by new pseudo register.  */
 
 rtx
-hoist_insn_after (insn, after, val, new)
-     rtx insn, after, val, new;
+hoist_insn_after (rtx insn, rtx after, rtx val, rtx new)
 {
   rtx pat;
   int i;
@@ -3616,9 +3692,7 @@ hoist_insn_after (insn, after, val, new)
 }
 
 rtx
-hoist_insn_to_edge (insn, e, val, new)
-     rtx insn, val, new;
-     edge e;
+hoist_insn_to_edge (rtx insn, edge e, rtx val, rtx new)
 {
   rtx new_insn;
 
@@ -3629,17 +3703,149 @@ hoist_insn_to_edge (insn, e, val, new)
 
   /* Do not use emit_insn_on_edge as we want to preserve notes and similar
      stuff.  We also emit CALL_INSNS and firends.  */
-  if (e->insns == NULL_RTX)
+  if (e->insns.r == NULL_RTX)
     {
       start_sequence ();
-      emit_note (NULL, NOTE_INSN_DELETED);
+      emit_note (NOTE_INSN_DELETED);
     }
   else
-    push_to_sequence (e->insns);
+    push_to_sequence (e->insns.r);
 
   new_insn = hoist_insn_after (insn, get_last_insn (), val, new);
 
-  e->insns = get_insns ();
+  e->insns.r = get_insns ();
   end_sequence ();
   return new_insn;
 }
+
+/* Return true if LABEL is a target of JUMP_INSN.  This applies only
+   to non-complex jumps.  That is, direct unconditional, conditional,
+   and tablejumps, but not computed jumps or returns.  It also does
+   not apply to the fallthru case of a conditional jump.  */
+
+bool
+label_is_jump_target_p (rtx label, rtx jump_insn)
+{
+  rtx tmp = JUMP_LABEL (jump_insn);
+
+  if (label == tmp)
+    return true;
+
+  if (tablejump_p (jump_insn, NULL, &tmp))
+    {
+      rtvec vec = XVEC (PATTERN (tmp),
+                       GET_CODE (PATTERN (tmp)) == ADDR_DIFF_VEC);
+      int i, veclen = GET_NUM_ELEM (vec);
+
+      for (i = 0; i < veclen; ++i)
+       if (XEXP (RTVEC_ELT (vec, i), 0) == label)
+         return true;
+    }
+
+  return false;
+}
+
+\f
+/* Return an estimate of the cost of computing rtx X.
+   One use is in cse, to decide which expression to keep in the hash table.
+   Another is in rtl generation, to pick the cheapest way to multiply.
+   Other uses like the latter are expected in the future.  */
+
+int
+rtx_cost (rtx x, enum rtx_code outer_code ATTRIBUTE_UNUSED)
+{
+  int i, j;
+  enum rtx_code code;
+  const char *fmt;
+  int total;
+
+  if (x == 0)
+    return 0;
+
+  /* Compute the default costs of certain things.
+     Note that targetm.rtx_costs can override the defaults.  */
+
+  code = GET_CODE (x);
+  switch (code)
+    {
+    case MULT:
+      total = COSTS_N_INSNS (5);
+      break;
+    case DIV:
+    case UDIV:
+    case MOD:
+    case UMOD:
+      total = COSTS_N_INSNS (7);
+      break;
+    case USE:
+      /* Used in loop.c and combine.c as a marker.  */
+      total = 0;
+      break;
+    default:
+      total = COSTS_N_INSNS (1);
+    }
+
+  switch (code)
+    {
+    case REG:
+      return 0;
+
+    case SUBREG:
+      /* If we can't tie these modes, make this expensive.  The larger
+        the mode, the more expensive it is.  */
+      if (! MODES_TIEABLE_P (GET_MODE (x), GET_MODE (SUBREG_REG (x))))
+       return COSTS_N_INSNS (2
+                             + GET_MODE_SIZE (GET_MODE (x)) / UNITS_PER_WORD);
+      break;
+
+    default:
+      if (targetm.rtx_costs (x, code, outer_code, &total))
+       return total;
+      break;
+    }
+
+  /* Sum the costs of the sub-rtx's, plus cost of this operation,
+     which is already in total.  */
+
+  fmt = GET_RTX_FORMAT (code);
+  for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
+    if (fmt[i] == 'e')
+      total += rtx_cost (XEXP (x, i), code);
+    else if (fmt[i] == 'E')
+      for (j = 0; j < XVECLEN (x, i); j++)
+       total += rtx_cost (XVECEXP (x, i, j), code);
+
+  return total;
+}
+\f
+/* Return cost of address expression X.
+   Expect that X is properly formed address reference.  */
+
+int
+address_cost (rtx x, enum machine_mode mode)
+{
+  /* The address_cost target hook does not deal with ADDRESSOF nodes.  But,
+     during CSE, such nodes are present.  Using an ADDRESSOF node which
+     refers to the address of a REG is a good thing because we can then
+     turn (MEM (ADDRESSOF (REG))) into just plain REG.  */
+
+  if (GET_CODE (x) == ADDRESSOF && REG_P (XEXP ((x), 0)))
+    return -1;
+
+  /* We may be asked for cost of various unusual addresses, such as operands
+     of push instruction.  It is not worthwhile to complicate writing
+     of the target hook by such cases.  */
+
+  if (!memory_address_p (mode, x))
+    return 1000;
+
+  return targetm.address_cost (x);
+}
+
+/* If the target doesn't override, compute the cost as with arithmetic.  */
+
+int
+default_address_cost (rtx x)
+{
+  return rtx_cost (x, MEM);
+}