OSDN Git Service

[pf3gnuchains/gcc-fork.git] / gcc / combine.c
index a96e4f7..bd0a225 100644 (file)
@@ -1,5 +1,5 @@
 /* Optimize by combining instructions for GNU compiler.
-   Copyright (C) 1987, 88, 92-96, 1997 Free Software Foundation, Inc.
+   Copyright (C) 1987, 88, 92-97, 1998 Free Software Foundation, Inc.
 
 This file is part of GNU CC.
 
@@ -75,27 +75,21 @@ Boston, MA 02111-1307, USA.  */
    combine anyway.  */
 
 #include "config.h"
-#ifdef __STDC__
-#include <stdarg.h>
-#else
-#include <varargs.h>
-#endif
-
-/* Must precede rtl.h for FFS.  */
-#include <stdio.h>
-
-#include "rtl.h"
+#include "system.h"
+#include "rtl.h" /* stdio.h must precede rtl.h for FFS.  */
 #include "flags.h"
 #include "regs.h"
 #include "hard-reg-set.h"
-#include "expr.h"
 #include "basic-block.h"
 #include "insn-config.h"
+/* Include expr.h after insn-config.h so we get HAVE_conditional_move. */
+#include "expr.h"
 #include "insn-flags.h"
 #include "insn-codes.h"
 #include "insn-attr.h"
 #include "recog.h"
 #include "real.h"
+#include "toplev.h"
 
 /* It is not safe to use ordinary gen_lowpart in combine.
    Use gen_lowpart_for_combine instead.  See comments there.  */
@@ -399,6 +393,7 @@ static void init_reg_last_arrays    PROTO((void));
 static void setup_incoming_promotions   PROTO((void));
 static void set_nonzero_bits_and_sign_copies  PROTO((rtx, rtx));
 static int can_combine_p       PROTO((rtx, rtx, rtx, rtx, rtx *, rtx *));
+static int sets_function_arg_p PROTO((rtx));
 static int combinable_i3pat    PROTO((rtx, rtx *, rtx, rtx, int, rtx *));
 static rtx try_combine         PROTO((rtx, rtx, rtx));
 static void undo_all           PROTO((void));
@@ -431,7 +426,7 @@ static int merge_outer_ops  PROTO((enum rtx_code *, HOST_WIDE_INT *,
                                       enum machine_mode, int *));
 static rtx simplify_shift_const        PROTO((rtx, enum rtx_code, enum machine_mode,
                                       rtx, int));
-static int recog_for_combine   PROTO((rtx *, rtx, rtx *, int *));
+static int recog_for_combine   PROTO((rtx *, rtx, rtx *));
 static rtx gen_lowpart_for_combine  PROTO((enum machine_mode, rtx));
 static rtx gen_rtx_combine PVPROTO((enum rtx_code code, enum machine_mode mode,
                                  ...));
@@ -465,7 +460,10 @@ combine_instructions (f, nregs)
      rtx f;
      int nregs;
 {
-  register rtx insn, next, prev;
+  register rtx insn, next;
+#ifdef HAVE_cc0
+  register rtx prev;
+#endif
   register int i;
   register rtx links, nextlinks;
 
@@ -676,6 +674,9 @@ combine_instructions (f, nregs)
   total_successes += combine_successes;
 
   nonzero_sign_valid = 0;
+
+  /* Make recognizer allow volatile MEMs again.  */
+  init_recog ();
 }
 
 /* Wipe the reg_last_xxx arrays in preparation for another pass.  */
@@ -711,10 +712,13 @@ setup_incoming_promotions ()
   for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
     if (FUNCTION_ARG_REGNO_P (regno)
        && (reg = promoted_input_arg (regno, &mode, &unsignedp)) != 0)
-      record_value_for_reg (reg, first,
-                           gen_rtx (unsignedp ? ZERO_EXTEND : SIGN_EXTEND,
-                                    GET_MODE (reg),
-                                    gen_rtx (CLOBBER, mode, const0_rtx)));
+      {
+       record_value_for_reg
+         (reg, first, gen_rtx_fmt_e ((unsignedp ? ZERO_EXTEND
+                                      : SIGN_EXTEND),
+                                     GET_MODE (reg),
+                                     gen_rtx_CLOBBER (mode, const0_rtx)));
+      }
 #endif
 }
 \f
@@ -815,12 +819,16 @@ static int
 can_combine_p (insn, i3, pred, succ, pdest, psrc)
      rtx insn;
      rtx i3;
-     rtx pred, succ;
+     rtx pred ATTRIBUTE_UNUSED;
+     rtx succ;
      rtx *pdest, *psrc;
 {
   int i;
   rtx set = 0, src, dest;
-  rtx p, link;
+  rtx p;
+#ifdef AUTO_INC_DEC
+  rtx link;
+#endif
   int all_adjacent = (succ ? (next_active_insn (insn) == succ
                              && next_active_insn (succ) == i3)
                      : next_active_insn (insn) == i3);
@@ -851,6 +859,43 @@ can_combine_p (insn, i3, pred, succ, pdest, psrc)
 
          switch (GET_CODE (elt))
            {
+           /* This is important to combine floating point insns
+              for the SH4 port.  */
+           case USE:
+             /* Combining an isolated USE doesn't make sense.
+                We depend here on combinable_i3_pat to reject them.  */
+             /* The code below this loop only verifies that the inputs of
+                the SET in INSN do not change.  We call reg_set_between_p
+                to verify that the REG in the USE does not change betweeen
+                I3 and INSN.
+                If the USE in INSN was for a pseudo register, the matching
+                insn pattern will likely match any register; combining this
+                with any other USE would only be safe if we knew that the
+                used registers have identical values, or if there was
+                something to tell them apart, e.g. different modes.  For
+                now, we forgo such compilcated tests and simply disallow
+                combining of USES of pseudo registers with any other USE.  */
+             if (GET_CODE (XEXP (elt, 0)) == REG
+                 && GET_CODE (PATTERN (i3)) == PARALLEL)
+               {
+                 rtx i3pat = PATTERN (i3);
+                 int i = XVECLEN (i3pat, 0) - 1;
+                 int regno = REGNO (XEXP (elt, 0));
+                 do
+                   {
+                     rtx i3elt = XVECEXP (i3pat, 0, i);
+                     if (GET_CODE (i3elt) == USE
+                         && GET_CODE (XEXP (i3elt, 0)) == REG
+                         && (REGNO (XEXP (i3elt, 0)) == regno
+                             ? reg_set_between_p (XEXP (elt, 0),
+                                                  PREV_INSN (insn), i3)
+                             : regno >= FIRST_PSEUDO_REGISTER))
+                       return 0;
+                   }
+                 while (--i >= 0);
+               }
+             break;
+
              /* We can ignore CLOBBERs.  */
            case CLOBBER:
              break;
@@ -909,8 +954,14 @@ can_combine_p (insn, i3, pred, succ, pdest, psrc)
       /* Don't substitute into an incremented register.  */
       || FIND_REG_INC_NOTE (i3, dest)
       || (succ && FIND_REG_INC_NOTE (succ, dest))
+#if 0
       /* Don't combine the end of a libcall into anything.  */
+      /* ??? This gives worse code, and appears to be unnecessary, since no
+        pass after flow uses REG_LIBCALL/REG_RETVAL notes.  Local-alloc does
+        use REG_RETVAL notes for noconflict blocks, but other code here
+        makes sure that those insns don't disappear.  */
       || find_reg_note (insn, REG_RETVAL, NULL_RTX)
+#endif
       /* Make sure that DEST is not used after SUCC but before I3.  */
       || (succ && ! all_adjacent
          && reg_used_between_p (dest, succ, i3))
@@ -991,14 +1042,19 @@ can_combine_p (insn, i3, pred, succ, pdest, psrc)
        return 0;
 
   /* If INSN contains anything volatile, or is an `asm' (whether volatile
-     or not), reject, unless nothing volatile comes between it and I3,
-     with the exception of SUCC.  */
+     or not), reject, unless nothing volatile comes between it and I3 */
 
   if (GET_CODE (src) == ASM_OPERANDS || volatile_refs_p (src))
-    for (p = NEXT_INSN (insn); p != i3; p = NEXT_INSN (p))
-      if (GET_RTX_CLASS (GET_CODE (p)) == 'i'
-         && p != succ && volatile_refs_p (PATTERN (p)))
-       return 0;
+    {
+      /* Make sure succ doesn't contain a volatile reference.  */
+      if (succ != 0 && volatile_refs_p (PATTERN (succ)))
+        return 0;
+  
+      for (p = NEXT_INSN (insn); p != i3; p = NEXT_INSN (p))
+        if (GET_RTX_CLASS (GET_CODE (p)) == 'i'
+         && p != succ && volatile_refs_p (PATTERN (p)))
+       return 0;
+    }
 
   /* If INSN is an asm, and DEST is a hard register, reject, since it has
      to be an explicit register variable, and was chosen for a reason.  */
@@ -1087,6 +1143,9 @@ sets_function_arg_p (pat)
       return (GET_CODE (inner_dest) == REG
              && REGNO (inner_dest) < FIRST_PSEUDO_REGISTER
              && FUNCTION_ARG_REGNO_P (REGNO (inner_dest)));
+
+    default:
+      break;
     }
 
   return 0;
@@ -1149,7 +1208,11 @@ combinable_i3pat (i3, loc, i2dest, i1dest, i1_not_in_src, pi3dest_killed)
       rtx set = expand_field_assignment (x);
       rtx dest = SET_DEST (set);
       rtx src = SET_SRC (set);
-      rtx inner_dest = dest, inner_src = src;
+      rtx inner_dest = dest;
+#if 0
+      rtx inner_src = src;
+#endif
 
       SUBST (*loc, set);
 
@@ -1293,8 +1356,6 @@ try_combine (i3, i2, i1)
   int i3_subst_into_i2 = 0;
   /* Notes that I1, I2 or I3 is a MULT operation.  */
   int have_mult = 0;
-  /* Number of clobbers of SCRATCH we had to add.  */
-  int i3_scratches = 0, i2_scratches = 0, other_scratches = 0;
 
   int maxreg;
   rtx temp;
@@ -1310,7 +1371,12 @@ try_combine (i3, i2, i1)
   if (GET_RTX_CLASS (GET_CODE (i3)) != 'i'
       || GET_RTX_CLASS (GET_CODE (i2)) != 'i'
       || (i1 && GET_RTX_CLASS (GET_CODE (i1)) != 'i')
-      || find_reg_note (i3, REG_LIBCALL, NULL_RTX))
+#if 0
+      /* ??? This gives worse code, and appears to be unnecessary, since no
+        pass after flow uses REG_LIBCALL/REG_RETVAL notes.  */
+      || find_reg_note (i3, REG_LIBCALL, NULL_RTX)
+#endif
+)
     return 0;
 
   combine_attempts++;
@@ -1446,8 +1512,9 @@ try_combine (i3, i2, i1)
             as I2 will not cause a problem.  */
 
          subst_prev_insn = i1
-           = gen_rtx (INSN, VOIDmode, INSN_UID (i2), NULL_RTX, i2,
-                      XVECEXP (PATTERN (i2), 0, 1), -1, NULL_RTX, NULL_RTX);
+           = gen_rtx_INSN (VOIDmode, INSN_UID (i2), NULL_RTX, i2,
+                           XVECEXP (PATTERN (i2), 0, 1), -1, NULL_RTX,
+                           NULL_RTX);
 
          SUBST (PATTERN (i2), XVECEXP (PATTERN (i2), 0, 0));
          SUBST (XEXP (SET_SRC (PATTERN (i2)), 0),
@@ -1544,7 +1611,7 @@ try_combine (i3, i2, i1)
      I2DEST.  */
 
   i2pat = (GET_CODE (PATTERN (i2)) == PARALLEL
-          ? gen_rtx (SET, VOIDmode, i2dest, i2src)
+          ? gen_rtx_SET (VOIDmode, i2dest, i2src)
           : PATTERN (i2));
 
   if (added_sets_2)
@@ -1608,8 +1675,10 @@ try_combine (i3, i2, i1)
       && XEXP (SET_SRC (PATTERN (i3)), 1) == const0_rtx
       && rtx_equal_p (XEXP (SET_SRC (PATTERN (i3)), 0), i2dest))
     {
+#ifdef EXTRA_CC_MODES
       rtx *cc_use;
       enum machine_mode compare_mode;
+#endif
 
       newpat = PATTERN (i3);
       SUBST (XEXP (SET_SRC (newpat), 0), i2src);
@@ -1630,7 +1699,7 @@ try_combine (i3, i2, i1)
              != GET_MODE (SET_DEST (newpat))))
        {
          int regno = REGNO (SET_DEST (newpat));
-         rtx new_dest = gen_rtx (REG, compare_mode, regno);
+         rtx new_dest = gen_rtx_REG (compare_mode, regno);
 
          if (regno < FIRST_PSEUDO_REGISTER
              || (REG_N_SETS (regno) == 1 && ! added_sets_2
@@ -1724,7 +1793,7 @@ try_combine (i3, i2, i1)
        {
          rtvec old = XVEC (newpat, 0);
          total_sets = XVECLEN (newpat, 0) + added_sets_1 + added_sets_2;
-         newpat = gen_rtx (PARALLEL, VOIDmode, rtvec_alloc (total_sets));
+         newpat = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (total_sets));
          bcopy ((char *) &old->elem[0], (char *) XVEC (newpat, 0)->elem,
                 sizeof (old->elem[0]) * old->num_elem);
        }
@@ -1732,14 +1801,14 @@ try_combine (i3, i2, i1)
        {
          rtx old = newpat;
          total_sets = 1 + added_sets_1 + added_sets_2;
-         newpat = gen_rtx (PARALLEL, VOIDmode, rtvec_alloc (total_sets));
+         newpat = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (total_sets));
          XVECEXP (newpat, 0, 0) = old;
        }
 
      if (added_sets_1)
        XVECEXP (newpat, 0, --total_sets)
         = (GET_CODE (PATTERN (i1)) == PARALLEL
-           ? gen_rtx (SET, VOIDmode, i1dest, i1src) : PATTERN (i1));
+           ? gen_rtx_SET (VOIDmode, i1dest, i1src) : PATTERN (i1));
 
      if (added_sets_2)
        {
@@ -1763,8 +1832,7 @@ try_combine (i3, i2, i1)
   mark_used_regs_combine (newpat);
 
   /* Is the result of combination a valid instruction?  */
-  insn_code_number
-    = recog_for_combine (&newpat, i3, &new_i3_notes, &i3_scratches);
+  insn_code_number = recog_for_combine (&newpat, i3, &new_i3_notes);
 
   /* If the result isn't valid, see if it is a PARALLEL of two SETs where
      the second SET's destination is a register that is unused.  In that case,
@@ -1785,8 +1853,7 @@ try_combine (i3, i2, i1)
       && asm_noperands (newpat) < 0)
     {
       newpat = XVECEXP (newpat, 0, 0);
-      insn_code_number
-       = recog_for_combine (&newpat, i3, &new_i3_notes, &i3_scratches);
+      insn_code_number = recog_for_combine (&newpat, i3, &new_i3_notes);
     }
 
   else if (insn_code_number < 0 && GET_CODE (newpat) == PARALLEL
@@ -1799,8 +1866,7 @@ try_combine (i3, i2, i1)
           && asm_noperands (newpat) < 0)
     {
       newpat = XVECEXP (newpat, 0, 1);
-      insn_code_number
-       = recog_for_combine (&newpat, i3, &new_i3_notes, &i3_scratches);
+      insn_code_number = recog_for_combine (&newpat, i3, &new_i3_notes);
     }
 
   /* If we were combining three insns and the result is a simple SET
@@ -1838,15 +1904,15 @@ try_combine (i3, i2, i1)
              && (REGNO (i2dest) < FIRST_PSEUDO_REGISTER
                  || (REG_N_SETS (REGNO (i2dest)) == 1 && ! added_sets_2
                      && ! REG_USERVAR_P (i2dest))))
-           ni2dest = gen_rtx (REG, GET_MODE (SET_DEST (newpat)),
+           ni2dest = gen_rtx_REG (GET_MODE (SET_DEST (newpat)),
                               REGNO (i2dest));
 
-         m_split = split_insns (gen_rtx (PARALLEL, VOIDmode,
-                                         gen_rtvec (2, newpat,
-                                                    gen_rtx (CLOBBER,
-                                                             VOIDmode,
-                                                             ni2dest))),
-                                i3);
+         m_split = split_insns
+           (gen_rtx_PARALLEL (VOIDmode,
+                              gen_rtvec (2, newpat,
+                                         gen_rtx_CLOBBER (VOIDmode,
+                                                          ni2dest))),
+            i3);
        }
 
       if (m_split && GET_CODE (m_split) == SEQUENCE
@@ -1869,8 +1935,7 @@ try_combine (i3, i2, i1)
          if (REGNO (i2dest) >= FIRST_PSEUDO_REGISTER)
            SUBST (regno_reg_rtx[REGNO (i2dest)], ni2dest);
 
-         i2_code_number = recog_for_combine (&newi2pat, i2, &new_i2_notes,
-                                             &i2_scratches);
+         i2_code_number = recog_for_combine (&newi2pat, i2, &new_i2_notes);
 
          /* If I2 or I3 has multiple SETs, we won't know how to track
             register status, so don't use these insns.  If I2's destination
@@ -1879,8 +1944,8 @@ try_combine (i3, i2, i1)
          if (i2_code_number >= 0 && i2set && i3set
              && (next_real_insn (i2) == i3
                  || ! reg_used_between_p (SET_DEST (i2set), i2, i3)))
-           insn_code_number = recog_for_combine (&newi3pat, i3, &new_i3_notes,
-                                                 &i3_scratches); 
+           insn_code_number = recog_for_combine (&newi3pat, i3,
+                                                 &new_i3_notes);
          if (insn_code_number >= 0)
            newpat = newi3pat;
 
@@ -1937,7 +2002,7 @@ try_combine (i3, i2, i1)
             validated that we can do this.  */
          if (GET_MODE (i2dest) != split_mode && split_mode != VOIDmode)
            {
-             newdest = gen_rtx (REG, split_mode, REGNO (i2dest));
+             newdest = gen_rtx_REG (split_mode, REGNO (i2dest));
 
              if (REGNO (i2dest) >= FIRST_PSEUDO_REGISTER)
                SUBST (regno_reg_rtx[REGNO (i2dest)], newdest);
@@ -1967,14 +2032,12 @@ try_combine (i3, i2, i1)
 
          newi2pat = gen_rtx_combine (SET, VOIDmode, newdest, *split);
          SUBST (*split, newdest);
-         i2_code_number
-           = recog_for_combine (&newi2pat, i2, &new_i2_notes, &i2_scratches);
+         i2_code_number = recog_for_combine (&newi2pat, i2, &new_i2_notes);
 
          /* If the split point was a MULT and we didn't have one before,
             don't use one now.  */
          if (i2_code_number >= 0 && ! (split_code == MULT && ! have_mult))
-           insn_code_number
-             = recog_for_combine (&newpat, i3, &new_i3_notes, &i3_scratches);
+           insn_code_number = recog_for_combine (&newpat, i3, &new_i3_notes);
        }
     }
 
@@ -2028,12 +2091,10 @@ try_combine (i3, i2, i1)
       newpat = XVECEXP (newpat, 0, 1);
       SUBST (SET_SRC (newpat),
             gen_lowpart_for_combine (GET_MODE (SET_SRC (newpat)), ni2dest));
-      i2_code_number
-       = recog_for_combine (&newi2pat, i2, &new_i2_notes, &i2_scratches);
+      i2_code_number = recog_for_combine (&newi2pat, i2, &new_i2_notes);
 
       if (i2_code_number >= 0)
-       insn_code_number
-         = recog_for_combine (&newpat, i3, &new_i3_notes, &i3_scratches);
+       insn_code_number = recog_for_combine (&newpat, i3, &new_i3_notes);
 
       if (insn_code_number >= 0)
        {
@@ -2050,7 +2111,7 @@ try_combine (i3, i2, i1)
             that destination.  */
 
          PATTERN (i3) = newpat;
-         distribute_links (gen_rtx (INSN_LIST, VOIDmode, i3, NULL_RTX));
+         distribute_links (gen_rtx_INSN_LIST (VOIDmode, i3, NULL_RTX));
 
          /* I3 now uses what used to be its destination and which is
             now I2's destination.  That means we need a LOG_LINK from
@@ -2120,12 +2181,10 @@ try_combine (i3, i2, i1)
          newpat = XVECEXP (newpat, 0, 0);
        }
 
-      i2_code_number
-       = recog_for_combine (&newi2pat, i2, &new_i2_notes, &i2_scratches);
+      i2_code_number = recog_for_combine (&newi2pat, i2, &new_i2_notes);
 
       if (i2_code_number >= 0)
-       insn_code_number
-         = recog_for_combine (&newpat, i3, &new_i3_notes, &i3_scratches);
+       insn_code_number = recog_for_combine (&newpat, i3, &new_i3_notes);
     }
 
   /* If it still isn't recognized, fail and change things back the way they
@@ -2147,9 +2206,8 @@ try_combine (i3, i2, i1)
 
       CLEAR_HARD_REG_SET (newpat_used_regs);
 
-      other_code_number
-       = recog_for_combine (&other_pat, undobuf.other_insn,
-                            &new_other_notes, &other_scratches);
+      other_code_number = recog_for_combine (&other_pat, undobuf.other_insn,
+                                            &new_other_notes);
 
       if (other_code_number < 0 && ! check_asm_operands (other_pat))
        {
@@ -2361,12 +2419,12 @@ try_combine (i3, i2, i1)
          REG_N_DEATHS (REGNO (i3dest_killed))++;
 
        if (newi2pat && reg_set_p (i3dest_killed, newi2pat))
-         distribute_notes (gen_rtx (EXPR_LIST, REG_DEAD, i3dest_killed,
-                                    NULL_RTX),
+         distribute_notes (gen_rtx_EXPR_LIST (REG_DEAD, i3dest_killed,
+                                              NULL_RTX),
                            NULL_RTX, i2, NULL_RTX, elim_i2, elim_i1);
        else
-         distribute_notes (gen_rtx (EXPR_LIST, REG_DEAD, i3dest_killed,
-                                    NULL_RTX),
+         distribute_notes (gen_rtx_EXPR_LIST (REG_DEAD, i3dest_killed,
+                                              NULL_RTX),
                            NULL_RTX, i3, newi2pat ? i2 : NULL_RTX,
                            elim_i2, elim_i1);
       }
@@ -2377,10 +2435,10 @@ try_combine (i3, i2, i1)
          REG_N_DEATHS (REGNO (i2dest))++;
 
        if (newi2pat && reg_set_p (i2dest, newi2pat))
-         distribute_notes (gen_rtx (EXPR_LIST, REG_DEAD, i2dest, NULL_RTX),
+         distribute_notes (gen_rtx_EXPR_LIST (REG_DEAD, i2dest, NULL_RTX),
                            NULL_RTX, i2, NULL_RTX, NULL_RTX, NULL_RTX);
        else
-         distribute_notes (gen_rtx (EXPR_LIST, REG_DEAD, i2dest, NULL_RTX),
+         distribute_notes (gen_rtx_EXPR_LIST (REG_DEAD, i2dest, NULL_RTX),
                            NULL_RTX, i3, newi2pat ? i2 : NULL_RTX,
                            NULL_RTX, NULL_RTX);
       }
@@ -2391,10 +2449,10 @@ try_combine (i3, i2, i1)
          REG_N_DEATHS (REGNO (i1dest))++;
 
        if (newi2pat && reg_set_p (i1dest, newi2pat))
-         distribute_notes (gen_rtx (EXPR_LIST, REG_DEAD, i1dest, NULL_RTX),
+         distribute_notes (gen_rtx_EXPR_LIST (REG_DEAD, i1dest, NULL_RTX),
                            NULL_RTX, i2, NULL_RTX, NULL_RTX, NULL_RTX);
        else
-         distribute_notes (gen_rtx (EXPR_LIST, REG_DEAD, i1dest, NULL_RTX),
+         distribute_notes (gen_rtx_EXPR_LIST (REG_DEAD, i1dest, NULL_RTX),
                            NULL_RTX, i3, newi2pat ? i2 : NULL_RTX,
                            NULL_RTX, NULL_RTX);
       }
@@ -2466,12 +2524,6 @@ try_combine (i3, i2, i1)
     if (newi2pat)
       note_stores (newi2pat, set_nonzero_bits_and_sign_copies);
 
-    /* If we added any (clobber (scratch)), add them to the max for a
-       block.  This is a very pessimistic calculation, since we might
-       have had them already and this might not be the worst block, but
-       it's not worth doing any better.  */
-    max_scratch += i3_scratches + i2_scratches + other_scratches;
-
     /* If I3 is now an unconditional jump, ensure that it has a 
        BARRIER following it since it may have initially been a
        conditional jump.  It may also be the last nonnote insn.  */
@@ -2578,7 +2630,7 @@ find_split_point (loc, insn)
          && ! memory_address_p (GET_MODE (x), XEXP (x, 0)))
        {
          rtx reg = regno_reg_rtx[FIRST_PSEUDO_REGISTER];
-         rtx seq = split_insns (gen_rtx (SET, VOIDmode, reg, XEXP (x, 0)),
+         rtx seq = split_insns (gen_rtx_SET (VOIDmode, reg, XEXP (x, 0)),
                                 subst_insn);
 
          /* This should have produced two insns, each of which sets our
@@ -2683,7 +2735,7 @@ find_split_point (loc, insn)
          if (BITS_BIG_ENDIAN)
            pos = GET_MODE_BITSIZE (mode) - len - pos;
 
-         if (src == mask)
+         if ((unsigned HOST_WIDE_INT) src == mask)
            SUBST (SET_SRC (x),
                   gen_binary (IOR, mode, dest, GEN_INT (src << pos)));
          else
@@ -2980,7 +3032,7 @@ subst (x, from, to, in_dest, unique_copy)
      So force this insn not to match in this (rare) case.  */
   if (! in_dest && code == REG && GET_CODE (from) == REG
       && REGNO (x) == REGNO (from))
-    return gen_rtx (CLOBBER, GET_MODE (x), const0_rtx);
+    return gen_rtx_CLOBBER (GET_MODE (x), const0_rtx);
 
   /* If this is an object, we are done unless it is a MEM or LO_SUM, both
      of which may contain things that can be combined.  */
@@ -2996,103 +3048,154 @@ subst (x, from, to, in_dest, unique_copy)
   if (COMBINE_RTX_EQUAL_P (x, to))
     return to;
 
-  len = GET_RTX_LENGTH (code);
-  fmt = GET_RTX_FORMAT (code);
+  /* Parallel asm_operands need special attention because all of the
+     inputs are shared across the arms.  Furthermore, unsharing the
+     rtl results in recognition failures.  Failure to handle this case
+     specially can result in circular rtl.
 
-  /* We don't need to process a SET_DEST that is a register, CC0, or PC, so
-     set up to skip this common case.  All other cases where we want to
-     suppress replacing something inside a SET_SRC are handled via the
-     IN_DEST operand.  */
-  if (code == SET
-      && (GET_CODE (SET_DEST (x)) == REG
-        || GET_CODE (SET_DEST (x)) == CC0
-        || GET_CODE (SET_DEST (x)) == PC))
-    fmt = "ie";
-
-  /* Get the mode of operand 0 in case X is now a SIGN_EXTEND of a
-     constant.  */
-  if (fmt[0] == 'e')
-    op0_mode = GET_MODE (XEXP (x, 0));
+     Solve this by doing a normal pass across the first entry of the
+     parallel, and only processing the SET_DESTs of the subsequent
+     entries.  Ug.  */
 
-  for (i = 0; i < len; i++)
+  if (code == PARALLEL
+      && GET_CODE (XVECEXP (x, 0, 0)) == SET
+      && GET_CODE (SET_SRC (XVECEXP (x, 0, 0))) == ASM_OPERANDS)
     {
-      if (fmt[i] == 'E')
+      new = subst (XVECEXP (x, 0, 0), from, to, 0, unique_copy);
+
+      /* If this substitution failed, this whole thing fails.  */
+      if (GET_CODE (new) == CLOBBER
+         && XEXP (new, 0) == const0_rtx)
+       return new;
+
+      SUBST (XVECEXP (x, 0, 0), new);
+
+      for (i = XVECLEN (x, 0) - 1; i >= 1; i--)
        {
-         register int j;
-         for (j = XVECLEN (x, i) - 1; j >= 0; j--)
+         rtx dest = SET_DEST (XVECEXP (x, 0, i));
+         
+         if (GET_CODE (dest) != REG
+             && GET_CODE (dest) != CC0
+             && GET_CODE (dest) != PC)
            {
-             if (COMBINE_RTX_EQUAL_P (XVECEXP (x, i, j), from))
-               {
-                 new = (unique_copy && n_occurrences ? copy_rtx (to) : to);
-                 n_occurrences++;
-               }
-             else
-               {
-                 new = subst (XVECEXP (x, i, j), from, to, 0, unique_copy);
+             new = subst (dest, from, to, 0, unique_copy);
 
-                 /* If this substitution failed, this whole thing fails.  */
-                 if (GET_CODE (new) == CLOBBER && XEXP (new, 0) == const0_rtx)
-                   return new;
-               }
+             /* If this substitution failed, this whole thing fails.  */
+             if (GET_CODE (new) == CLOBBER
+                 && XEXP (new, 0) == const0_rtx)
+               return new;
 
-             SUBST (XVECEXP (x, i, j), new);
+             SUBST (SET_DEST (XVECEXP (x, 0, i)), new);
            }
        }
-      else if (fmt[i] == 'e')
+    }
+  else
+    {
+      len = GET_RTX_LENGTH (code);
+      fmt = GET_RTX_FORMAT (code);
+
+      /* We don't need to process a SET_DEST that is a register, CC0,
+        or PC, so set up to skip this common case.  All other cases
+        where we want to suppress replacing something inside a
+        SET_SRC are handled via the IN_DEST operand.  */
+      if (code == SET
+         && (GET_CODE (SET_DEST (x)) == REG
+             || GET_CODE (SET_DEST (x)) == CC0
+             || GET_CODE (SET_DEST (x)) == PC))
+       fmt = "ie";
+
+      /* Get the mode of operand 0 in case X is now a SIGN_EXTEND of a
+        constant.  */
+      if (fmt[0] == 'e')
+       op0_mode = GET_MODE (XEXP (x, 0));
+
+      for (i = 0; i < len; i++)
        {
-         if (COMBINE_RTX_EQUAL_P (XEXP (x, i), from))
+         if (fmt[i] == 'E')
            {
-             /* In general, don't install a subreg involving two modes not
-                tieable.  It can worsen register allocation, and can even
-                make invalid reload insns, since the reg inside may need to
-                be copied from in the outside mode, and that may be invalid
-                if it is an fp reg copied in integer mode.
-
-                We allow two exceptions to this: It is valid if it is inside
-                another SUBREG and the mode of that SUBREG and the mode of
-                the inside of TO is tieable and it is valid if X is a SET
-                that copies FROM to CC0.  */
-             if (GET_CODE (to) == SUBREG
-                 && ! MODES_TIEABLE_P (GET_MODE (to),
-                                       GET_MODE (SUBREG_REG (to)))
-                 && ! (code == SUBREG
-                       && MODES_TIEABLE_P (GET_MODE (x),
-                                           GET_MODE (SUBREG_REG (to))))
+             register int j;
+             for (j = XVECLEN (x, i) - 1; j >= 0; j--)
+               {
+                 if (COMBINE_RTX_EQUAL_P (XVECEXP (x, i, j), from))
+                   {
+                     new = (unique_copy && n_occurrences
+                            ? copy_rtx (to) : to);
+                     n_occurrences++;
+                   }
+                 else
+                   {
+                     new = subst (XVECEXP (x, i, j), from, to, 0,
+                                  unique_copy);
+
+                     /* If this substitution failed, this whole thing
+                        fails.  */
+                     if (GET_CODE (new) == CLOBBER
+                         && XEXP (new, 0) == const0_rtx)
+                       return new;
+                   }
+
+                 SUBST (XVECEXP (x, i, j), new);
+               }
+           }
+         else if (fmt[i] == 'e')
+           {
+             if (COMBINE_RTX_EQUAL_P (XEXP (x, i), from))
+               {
+                 /* In general, don't install a subreg involving two
+                    modes not tieable.  It can worsen register
+                    allocation, and can even make invalid reload
+                    insns, since the reg inside may need to be copied
+                    from in the outside mode, and that may be invalid
+                    if it is an fp reg copied in integer mode.
+
+                    We allow two exceptions to this: It is valid if
+                    it is inside another SUBREG and the mode of that
+                    SUBREG and the mode of the inside of TO is
+                    tieable and it is valid if X is a SET that copies
+                    FROM to CC0.  */
+
+                 if (GET_CODE (to) == SUBREG
+                     && ! MODES_TIEABLE_P (GET_MODE (to),
+                                           GET_MODE (SUBREG_REG (to)))
+                     && ! (code == SUBREG
+                           && MODES_TIEABLE_P (GET_MODE (x),
+                                               GET_MODE (SUBREG_REG (to))))
 #ifdef HAVE_cc0
-                 && ! (code == SET && i == 1 && XEXP (x, 0) == cc0_rtx)
+                     && ! (code == SET && i == 1 && XEXP (x, 0) == cc0_rtx)
 #endif
-                 )
-               return gen_rtx (CLOBBER, VOIDmode, const0_rtx);
+                     )
+                   return gen_rtx_CLOBBER (VOIDmode, const0_rtx);
 
-             new = (unique_copy && n_occurrences ? copy_rtx (to) : to);
-             n_occurrences++;
+                 new = (unique_copy && n_occurrences ? copy_rtx (to) : to);
+                 n_occurrences++;
+               }
+             else
+               /* If we are in a SET_DEST, suppress most cases unless we
+                  have gone inside a MEM, in which case we want to
+                  simplify the address.  We assume here that things that
+                  are actually part of the destination have their inner
+                  parts in the first expression.  This is true for SUBREG, 
+                  STRICT_LOW_PART, and ZERO_EXTRACT, which are the only
+                  things aside from REG and MEM that should appear in a
+                  SET_DEST.  */
+               new = subst (XEXP (x, i), from, to,
+                            (((in_dest
+                               && (code == SUBREG || code == STRICT_LOW_PART
+                                   || code == ZERO_EXTRACT))
+                              || code == SET)
+                             && i == 0), unique_copy);
+
+             /* If we found that we will have to reject this combination,
+                indicate that by returning the CLOBBER ourselves, rather than
+                an expression containing it.  This will speed things up as
+                well as prevent accidents where two CLOBBERs are considered
+                to be equal, thus producing an incorrect simplification.  */
+
+             if (GET_CODE (new) == CLOBBER && XEXP (new, 0) == const0_rtx)
+               return new;
+
+             SUBST (XEXP (x, i), new);
            }
-         else
-           /* If we are in a SET_DEST, suppress most cases unless we
-              have gone inside a MEM, in which case we want to
-              simplify the address.  We assume here that things that
-              are actually part of the destination have their inner
-              parts in the first expression.  This is true for SUBREG, 
-              STRICT_LOW_PART, and ZERO_EXTRACT, which are the only
-              things aside from REG and MEM that should appear in a
-              SET_DEST.  */
-           new = subst (XEXP (x, i), from, to,
-                        (((in_dest
-                           && (code == SUBREG || code == STRICT_LOW_PART
-                               || code == ZERO_EXTRACT))
-                          || code == SET)
-                         && i == 0), unique_copy);
-
-         /* If we found that we will have to reject this combination,
-            indicate that by returning the CLOBBER ourselves, rather than
-            an expression containing it.  This will speed things up as
-            well as prevent accidents where two CLOBBERs are considered
-            to be equal, thus producing an incorrect simplification.  */
-
-         if (GET_CODE (new) == CLOBBER && XEXP (new, 0) == const0_rtx)
-           return new;
-
-         SUBST (XEXP (x, i), new);
        }
     }
 
@@ -3264,9 +3367,10 @@ simplify_rtx (x, op0_mode, last, in_dest)
                           gen_binary (reverse_condition (cond_code), 
                                       mode, cond, cop1));
          else
-           return gen_rtx (IF_THEN_ELSE, mode,
-                           gen_binary (cond_code, VOIDmode, cond, cop1),
-                           true, false);
+           return gen_rtx_IF_THEN_ELSE (mode,
+                                        gen_binary (cond_code, VOIDmode,
+                                                    cond, cop1),
+                                        true, false);
 
          code = GET_CODE (x);
          op0_mode = VOIDmode;
@@ -3382,7 +3486,7 @@ simplify_rtx (x, op0_mode, last, in_dest)
             if that would change the meaning of the address.  */
          if (MEM_VOLATILE_P (SUBREG_REG (x))
              || mode_dependent_address_p (XEXP (inner, 0)))
-           return gen_rtx (CLOBBER, mode, const0_rtx);
+           return gen_rtx_CLOBBER (mode, const0_rtx);
 
          if (BYTES_BIG_ENDIAN)
            {
@@ -3394,10 +3498,10 @@ simplify_rtx (x, op0_mode, last, in_dest)
            }
          /* Note if the plus_constant doesn't make a valid address
             then this combination won't be accepted.  */
-         x = gen_rtx (MEM, mode,
-                      plus_constant (XEXP (inner, 0),
-                                     (SUBREG_WORD (x) * UNITS_PER_WORD
-                                      + endian_offset)));
+         x = gen_rtx_MEM (mode,
+                          plus_constant (XEXP (inner, 0),
+                                         (SUBREG_WORD (x) * UNITS_PER_WORD
+                                          + endian_offset)));
          MEM_VOLATILE_P (x) = MEM_VOLATILE_P (inner);
          RTX_UNCHANGING_P (x) = RTX_UNCHANGING_P (inner);
          MEM_IN_STRUCT_P (x) = MEM_IN_STRUCT_P (inner);
@@ -3439,10 +3543,10 @@ simplify_rtx (x, op0_mode, last, in_dest)
        {
          if (HARD_REGNO_MODE_OK (REGNO (SUBREG_REG (x)) + SUBREG_WORD (x),
                                  mode))
-           return gen_rtx (REG, mode,
-                           REGNO (SUBREG_REG (x)) + SUBREG_WORD (x));
+           return gen_rtx_REG (mode,
+                               REGNO (SUBREG_REG (x)) + SUBREG_WORD (x));
          else
-           return gen_rtx (CLOBBER, mode, const0_rtx);
+           return gen_rtx_CLOBBER (mode, const0_rtx);
        }
 
       /* For a constant, try to pick up the part we want.  Handle a full
@@ -3516,8 +3620,8 @@ simplify_rtx (x, op0_mode, last, in_dest)
         but this doesn't seem common enough to bother with.  */
       if (GET_CODE (XEXP (x, 0)) == ASHIFT
          && XEXP (XEXP (x, 0), 0) == const1_rtx)
-       return gen_rtx (ROTATE, mode, gen_unary (NOT, mode, mode, const1_rtx),
-                       XEXP (XEXP (x, 0), 1));
+       return gen_rtx_ROTATE (mode, gen_unary (NOT, mode, mode, const1_rtx),
+                              XEXP (XEXP (x, 0), 1));
                                            
       if (GET_CODE (XEXP (x, 0)) == SUBREG
          && subreg_lowpart_p (XEXP (x, 0))
@@ -3528,9 +3632,10 @@ simplify_rtx (x, op0_mode, last, in_dest)
        {
          enum machine_mode inner_mode = GET_MODE (SUBREG_REG (XEXP (x, 0)));
 
-         x = gen_rtx (ROTATE, inner_mode,
-                      gen_unary (NOT, inner_mode, inner_mode, const1_rtx),
-                      XEXP (SUBREG_REG (XEXP (x, 0)), 1));
+         x = gen_rtx_ROTATE (inner_mode,
+                             gen_unary (NOT, inner_mode, inner_mode,
+                                        const1_rtx),
+                             XEXP (SUBREG_REG (XEXP (x, 0)), 1));
          return gen_lowpart_for_combine (mode, x);
        }
                                            
@@ -3673,7 +3778,9 @@ simplify_rtx (x, op0_mode, last, in_dest)
       if (GET_MODE_CLASS (mode) == MODE_PARTIAL_INT)
        break;
 
-      if (GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT)
+      if (GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT
+         && TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (mode),
+                                   GET_MODE_BITSIZE (GET_MODE (XEXP (x, 0)))))
        SUBST (XEXP (x, 0),
               force_to_mode (XEXP (x, 0), GET_MODE (XEXP (x, 0)),
                              GET_MODE_MASK (mode), NULL_RTX, 0));
@@ -3702,10 +3809,12 @@ simplify_rtx (x, op0_mode, last, in_dest)
        return SUBREG_REG (XEXP (x, 0));
 
       /* If we know that the value is already truncated, we can
-         replace the TRUNCATE with a SUBREG.  */
-      if (GET_MODE_BITSIZE (GET_MODE (XEXP (x, 0))) <= HOST_BITS_PER_WIDE_INT
-         && (nonzero_bits (XEXP (x, 0), GET_MODE (XEXP (x, 0)))
-             &~ GET_MODE_MASK (mode)) == 0)
+         replace the TRUNCATE with a SUBREG if TRULY_NOOP_TRUNCATION is
+        nonzero for the corresponding modes.  */
+      if (TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (mode),
+                                GET_MODE_BITSIZE (GET_MODE (XEXP (x, 0))))
+         && num_sign_bit_copies (XEXP (x, 0), GET_MODE (XEXP (x, 0)))
+            >= GET_MODE_BITSIZE (mode) + 1)
        return gen_lowpart_for_combine (mode, XEXP (x, 0));
 
       /* A truncate of a comparison can be replaced with a subreg if
@@ -4046,7 +4155,7 @@ simplify_rtx (x, op0_mode, last, in_dest)
          if (new_code == NE && GET_MODE_CLASS (mode) == MODE_INT
              && GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT
              && ((STORE_FLAG_VALUE & GET_MODE_MASK (mode))
-                 == (HOST_WIDE_INT) 1 << (GET_MODE_BITSIZE (mode) - 1))
+                 == (unsigned HOST_WIDE_INT) 1 << (GET_MODE_BITSIZE(mode)-1))
              && op1 == const0_rtx
              && mode == GET_MODE (op0)
              && (i = exact_log2 (nonzero_bits (op0, mode))) >= 0)
@@ -4092,11 +4201,16 @@ simplify_rtx (x, op0_mode, last, in_dest)
     case XOR:
       return simplify_logical (x, last);
 
-    case ABS:
+    case ABS:      
       /* (abs (neg <foo>)) -> (abs <foo>) */
       if (GET_CODE (XEXP (x, 0)) == NEG)
        SUBST (XEXP (x, 0), XEXP (XEXP (x, 0), 0));
 
+      /* If the mode of the operand is VOIDmode (i.e. if it is ASM_OPERANDS),
+         do nothing.  */
+      if (GET_MODE (XEXP (x, 0)) == VOIDmode)
+       break;
+
       /* If operand is something known to be positive, ignore the ABS.  */
       if (GET_CODE (XEXP (x, 0)) == FFS || GET_CODE (XEXP (x, 0)) == ABS
          || ((GET_MODE_BITSIZE (GET_MODE (XEXP (x, 0)))
@@ -4530,7 +4644,7 @@ simplify_set (x)
       if (compare_mode != GET_MODE (dest))
        {
          int regno = REGNO (dest);
-         rtx new_dest = gen_rtx (REG, compare_mode, regno);
+         rtx new_dest = gen_rtx_REG (compare_mode, regno);
 
          if (regno < FIRST_PSEUDO_REGISTER
              || (REG_N_SETS (regno) == 1 && ! REG_USERVAR_P (dest)))
@@ -4569,9 +4683,8 @@ simplify_set (x)
              && exact_log2 (mask = nonzero_bits (op0, GET_MODE (op0))) >= 0)
            {
              rtx pat = PATTERN (other_insn), note = 0;
-             int scratches;
 
-             if ((recog_for_combine (&pat, other_insn, &note, &scratches) < 0
+             if ((recog_for_combine (&pat, other_insn, &note) < 0
                   && ! check_asm_operands (pat)))
                {
                  PUT_CODE (*cc_use, old_code);
@@ -4629,7 +4742,7 @@ simplify_set (x)
      we only care about the low bits of the result.
 
      However, on machines without WORD_REGISTER_OPERATIONS defined, we cannot
-     perform a narrower operation that requested since the high-order bits will
+     perform a narrower operation than requested since the high-order bits will
      be undefined.  On machine where it is defined, this transformation is safe
      as long as M1 and M2 have the same number of words.  */
  
@@ -4917,9 +5030,9 @@ simplify_logical (x, last)
          && GET_CODE (XEXP (op1, 1)) == CONST_INT
          && (INTVAL (XEXP (op0, 1)) + INTVAL (XEXP (op1, 1))
              == GET_MODE_BITSIZE (mode)))
-       return gen_rtx (ROTATE, mode, XEXP (op0, 0),
-                       (GET_CODE (op0) == ASHIFT
-                        ? XEXP (op0, 1) : XEXP (op1, 1)));
+       return gen_rtx_ROTATE (mode, XEXP (op0, 0),
+                              (GET_CODE (op0) == ASHIFT
+                               ? XEXP (op0, 1) : XEXP (op1, 1)));
 
       /* If OP0 is (ashiftrt (plus ...) C), it might actually be
         a (sign_extend (plus ...)).  If so, OP1 is a CONST_INT, and the PLUS
@@ -5008,7 +5121,7 @@ simplify_logical (x, last)
         when STORE_FLAG_VALUE is the sign bit.  */
       if (GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT
          && ((STORE_FLAG_VALUE & GET_MODE_MASK (mode))
-             == (HOST_WIDE_INT) 1 << (GET_MODE_BITSIZE (mode) - 1))
+             == (unsigned HOST_WIDE_INT) 1 << (GET_MODE_BITSIZE (mode) - 1))
          && op1 == const_true_rtx
          && GET_RTX_CLASS (GET_CODE (op0)) == '<'
          && reversible_comparison_p (op0))
@@ -5101,7 +5214,7 @@ expand_compound_operation (x)
         with a (use (mem ...)) construct that only combine understands
         and is used only for this purpose.  */
       if (len + pos > GET_MODE_BITSIZE (GET_MODE (XEXP (x, 0))))
-       SUBST (XEXP (x, 0), gen_rtx (USE, GET_MODE (x), XEXP (x, 0)));
+       SUBST (XEXP (x, 0), gen_rtx_USE (GET_MODE (x), XEXP (x, 0)));
 
       if (BITS_BIG_ENDIAN)
        pos = GET_MODE_BITSIZE (GET_MODE (XEXP (x, 0))) - len - pos;
@@ -5131,7 +5244,7 @@ expand_compound_operation (x)
          && subreg_lowpart_p (XEXP (x, 0))
          && GET_MODE_BITSIZE (GET_MODE (x)) <= HOST_BITS_PER_WIDE_INT
          && (nonzero_bits (SUBREG_REG (XEXP (x, 0)), GET_MODE (x))
-             & ~ GET_MODE_MASK (GET_MODE (SUBREG_REG (x)))) == 0)
+             & ~ GET_MODE_MASK (GET_MODE (XEXP (x, 0)))) == 0)
        return SUBREG_REG (XEXP (x, 0));
 
       /* (zero_extend:DI (truncate:SI foo:DI)) is just foo:DI when foo
@@ -5177,7 +5290,7 @@ expand_compound_operation (x)
                            >> 1))
                      == 0))))
        {
-         rtx temp = gen_rtx (SIGN_EXTEND, GET_MODE (x), XEXP (x, 0));
+         rtx temp = gen_rtx_SIGN_EXTEND (GET_MODE (x), XEXP (x, 0));
 
          if (rtx_cost (temp, SET) < rtx_cost (x, SET))
            return expand_compound_operation (temp);
@@ -5267,7 +5380,7 @@ expand_field_assignment (x)
             surround INNER  with a USE to indicate this.  */
          if (GET_CODE (pos) == CONST_INT
              && INTVAL (pos) + len > GET_MODE_BITSIZE (GET_MODE (inner)))
-           inner = gen_rtx (USE, GET_MODE (SET_DEST (x)), inner);
+           inner = gen_rtx_USE (GET_MODE (SET_DEST (x)), inner);
 
          if (BITS_BIG_ENDIAN)
            {
@@ -5296,9 +5409,9 @@ expand_field_assignment (x)
                   == ((GET_MODE_SIZE (GET_MODE (SUBREG_REG (SET_DEST (x))))
                        + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD)))
        {
-         x = gen_rtx (SET, VOIDmode, SUBREG_REG (SET_DEST (x)),
-                      gen_lowpart_for_combine (GET_MODE (SUBREG_REG (SET_DEST (x))),
-                                               SET_SRC (x)));
+         x = gen_rtx_SET (VOIDmode, SUBREG_REG (SET_DEST (x)),
+                          gen_lowpart_for_combine (GET_MODE (SUBREG_REG (SET_DEST (x))),
+                                                   SET_SRC (x)));
          continue;
        }
       else
@@ -5309,6 +5422,24 @@ expand_field_assignment (x)
 
       compute_mode = GET_MODE (inner);
 
+      /* Don't attempt bitwise arithmetic on non-integral modes.  */
+      if (! INTEGRAL_MODE_P (compute_mode))
+       {
+         enum machine_mode imode;
+
+         /* Something is probably seriously wrong if this matches.  */
+         if (! FLOAT_MODE_P (compute_mode))
+           break;
+
+         /* Try to find an integral mode to pun with.  */
+         imode = mode_for_size (GET_MODE_BITSIZE (compute_mode), MODE_INT, 0);
+         if (imode == BLKmode)
+           break;
+
+         compute_mode = imode;
+         inner = gen_lowpart_for_combine (imode, inner);
+       }
+
       /* Compute a mask of LEN bits, if we can do this on the host machine.  */
       if (len < HOST_BITS_PER_WIDE_INT)
        mask = GEN_INT (((HOST_WIDE_INT) 1 << len) - 1);
@@ -5318,22 +5449,22 @@ expand_field_assignment (x)
       /* Now compute the equivalent expression.  Make a copy of INNER
         for the SET_DEST in case it is a MEM into which we will substitute;
         we don't want shared RTL in that case.  */
-      x = gen_rtx (SET, VOIDmode, copy_rtx (inner),
-                  gen_binary (IOR, compute_mode,
-                              gen_binary (AND, compute_mode,
-                                          gen_unary (NOT, compute_mode,
-                                                     compute_mode,
-                                                     gen_binary (ASHIFT,
-                                                                 compute_mode,
-                                                                 mask, pos)),
-                                          inner),
-                              gen_binary (ASHIFT, compute_mode,
-                                          gen_binary (AND, compute_mode,
-                                                      gen_lowpart_for_combine
-                                                      (compute_mode,
-                                                       SET_SRC (x)),
-                                                      mask),
-                                          pos)));
+      x = gen_rtx_SET (VOIDmode, copy_rtx (inner),
+                      gen_binary (IOR, compute_mode,
+                                  gen_binary (AND, compute_mode,
+                                              gen_unary (NOT, compute_mode,
+                                                         compute_mode,
+                                                         gen_binary (ASHIFT,
+                                                                     compute_mode,
+                                                                     mask, pos)),
+                                              inner),
+                                  gen_binary (ASHIFT, compute_mode,
+                                              gen_binary (AND, compute_mode,
+                                                          gen_lowpart_for_combine
+                                                          (compute_mode,
+                                                           SET_SRC (x)),
+                                                          mask),
+                                              pos)));
     }
 
   return x;
@@ -5463,7 +5594,7 @@ make_extraction (mode, inner, pos, pos_rtx, len,
          else
            offset = pos / BITS_PER_UNIT;
 
-         new = gen_rtx (MEM, tmode, plus_constant (XEXP (inner, 0), offset));
+         new = gen_rtx_MEM (tmode, plus_constant (XEXP (inner, 0), offset));
          RTX_UNCHANGING_P (new) = RTX_UNCHANGING_P (inner);
          MEM_VOLATILE_P (new) = MEM_VOLATILE_P (inner);
          MEM_IN_STRUCT_P (new) = MEM_IN_STRUCT_P (inner);
@@ -5473,14 +5604,14 @@ make_extraction (mode, inner, pos, pos_rtx, len,
          /* We can't call gen_lowpart_for_combine here since we always want
             a SUBREG and it would sometimes return a new hard register.  */
          if (tmode != inner_mode)
-           new = gen_rtx (SUBREG, tmode, inner,
-                          (WORDS_BIG_ENDIAN
-                           && GET_MODE_SIZE (inner_mode) > UNITS_PER_WORD
-                           ? (((GET_MODE_SIZE (inner_mode)
-                                - GET_MODE_SIZE (tmode))
-                               / UNITS_PER_WORD)
-                              - pos / BITS_PER_WORD)
-                           : pos / BITS_PER_WORD));
+           new = gen_rtx_SUBREG (tmode, inner,
+                                 (WORDS_BIG_ENDIAN
+                                  && GET_MODE_SIZE (inner_mode) > UNITS_PER_WORD
+                                  ? (((GET_MODE_SIZE (inner_mode)
+                                       - GET_MODE_SIZE (tmode))
+                                      / UNITS_PER_WORD)
+                                     - pos / BITS_PER_WORD)
+                                  : pos / BITS_PER_WORD));
          else
            new = inner;
        }
@@ -5497,7 +5628,7 @@ make_extraction (mode, inner, pos, pos_rtx, len,
       if (in_dest)
        return (GET_CODE (new) == MEM ? new
                : (GET_CODE (new) != SUBREG
-                  ? gen_rtx (CLOBBER, tmode, const0_rtx)
+                  ? gen_rtx_CLOBBER (tmode, const0_rtx)
                   : gen_rtx_combine (STRICT_LOW_PART, VOIDmode, new)));
 
       /* Otherwise, sign- or zero-extend unless we already are in the
@@ -5530,27 +5661,45 @@ make_extraction (mode, inner, pos, pos_rtx, len,
 #ifdef HAVE_insv
   if (in_dest)
     {
-      wanted_inner_reg_mode = insn_operand_mode[(int) CODE_FOR_insv][0];
-      pos_mode = insn_operand_mode[(int) CODE_FOR_insv][2];
-      extraction_mode = insn_operand_mode[(int) CODE_FOR_insv][3];
+      wanted_inner_reg_mode
+       = (insn_operand_mode[(int) CODE_FOR_insv][0] == VOIDmode
+          ? word_mode
+          : insn_operand_mode[(int) CODE_FOR_insv][0]);
+      pos_mode = (insn_operand_mode[(int) CODE_FOR_insv][2] == VOIDmode
+                 ? word_mode : insn_operand_mode[(int) CODE_FOR_insv][2]);
+      extraction_mode = (insn_operand_mode[(int) CODE_FOR_insv][3] == VOIDmode
+                        ? word_mode
+                        : insn_operand_mode[(int) CODE_FOR_insv][3]);
     }
 #endif
 
 #ifdef HAVE_extzv
   if (! in_dest && unsignedp)
     {
-      wanted_inner_reg_mode = insn_operand_mode[(int) CODE_FOR_extzv][1];
-      pos_mode = insn_operand_mode[(int) CODE_FOR_extzv][3];
-      extraction_mode = insn_operand_mode[(int) CODE_FOR_extzv][0];
+      wanted_inner_reg_mode
+       = (insn_operand_mode[(int) CODE_FOR_extzv][1] == VOIDmode
+          ? word_mode
+          : insn_operand_mode[(int) CODE_FOR_extzv][1]);
+      pos_mode = (insn_operand_mode[(int) CODE_FOR_extzv][3] == VOIDmode
+                 ? word_mode : insn_operand_mode[(int) CODE_FOR_extzv][3]);
+      extraction_mode = (insn_operand_mode[(int) CODE_FOR_extzv][0] == VOIDmode
+                        ? word_mode
+                        : insn_operand_mode[(int) CODE_FOR_extzv][0]);
     }
 #endif
 
 #ifdef HAVE_extv
   if (! in_dest && ! unsignedp)
     {
-      wanted_inner_reg_mode = insn_operand_mode[(int) CODE_FOR_extv][1];
-      pos_mode = insn_operand_mode[(int) CODE_FOR_extv][3];
-      extraction_mode = insn_operand_mode[(int) CODE_FOR_extv][0];
+      wanted_inner_reg_mode
+       = (insn_operand_mode[(int) CODE_FOR_extv][1] == VOIDmode
+          ? word_mode
+          : insn_operand_mode[(int) CODE_FOR_extv][1]);
+      pos_mode = (insn_operand_mode[(int) CODE_FOR_extv][3] == VOIDmode
+                 ? word_mode : insn_operand_mode[(int) CODE_FOR_extv][3]);
+      extraction_mode = (insn_operand_mode[(int) CODE_FOR_extv][0] == VOIDmode
+                        ? word_mode
+                        : insn_operand_mode[(int) CODE_FOR_extv][0]);
     }
 #endif
 
@@ -5637,8 +5786,8 @@ make_extraction (mode, inner, pos, pos_rtx, len,
 
       if (offset != 0 || inner_mode != wanted_inner_mode)
        {
-         rtx newmem = gen_rtx (MEM, wanted_inner_mode,
-                               plus_constant (XEXP (inner, 0), offset));
+         rtx newmem = gen_rtx_MEM (wanted_inner_mode,
+                                   plus_constant (XEXP (inner, 0), offset));
          RTX_UNCHANGING_P (newmem) = RTX_UNCHANGING_P (inner);
          MEM_VOLATILE_P (newmem) = MEM_VOLATILE_P (inner);
          MEM_IN_STRUCT_P (newmem) = MEM_IN_STRUCT_P (inner);
@@ -5725,7 +5874,7 @@ extract_left_shift (x, count)
       /* If we can safely shift this constant and we find the inner shift,
         make a new operation.  */
       if (GET_CODE (XEXP (x,1)) == CONST_INT
-         && (INTVAL (XEXP (x, 1)) & (((HOST_WIDE_INT) 1 << count)) - 1) == 0
+         && (INTVAL (XEXP (x, 1)) & ((((HOST_WIDE_INT) 1 << count)) - 1)) == 0
          && (tem = extract_left_shift (XEXP (x, 0), count)) != 0)
        return gen_binary (code, mode, tem, 
                           GEN_INT (INTVAL (XEXP (x, 1)) >> count));
@@ -5837,10 +5986,10 @@ make_compound_operation (x, in_code)
        {
          /* Apply the distributive law, and then try to make extractions.  */
          new = gen_rtx_combine (GET_CODE (XEXP (x, 0)), mode,
-                                gen_rtx (AND, mode, XEXP (XEXP (x, 0), 0),
-                                         XEXP (x, 1)),
-                                gen_rtx (AND, mode, XEXP (XEXP (x, 0), 1),
-                                         XEXP (x, 1)));
+                                gen_rtx_AND (mode, XEXP (XEXP (x, 0), 0),
+                                             XEXP (x, 1)),
+                                gen_rtx_AND (mode, XEXP (XEXP (x, 0), 1),
+                                             XEXP (x, 1)));
          new = make_compound_operation (new, in_code);
        }
 
@@ -5975,6 +6124,23 @@ make_compound_operation (x, in_code)
 
          return newer;
        }
+
+      /* If this is a paradoxical subreg, and the new code is a sign or
+        zero extension, omit the subreg and widen the extension.  If it
+        is a regular subreg, we can still get rid of the subreg by not
+        widening so much, or in fact removing the extension entirely.  */
+      if ((GET_CODE (tem) == SIGN_EXTEND
+          || GET_CODE (tem) == ZERO_EXTEND)
+         && subreg_lowpart_p (x))
+       {
+         if (GET_MODE_SIZE (mode) > GET_MODE_SIZE (GET_MODE (tem))
+             || (GET_MODE_SIZE (mode) >
+                 GET_MODE_SIZE (GET_MODE (XEXP (tem, 0)))))
+           tem = gen_rtx_combine (GET_CODE (tem), mode, XEXP (tem, 0));
+         else
+           tem = gen_lowpart_for_combine (mode, XEXP (tem, 0));
+         return tem;
+       }
       break;
       
     default:
@@ -6059,8 +6225,11 @@ force_to_mode (x, mode, mask, reg, just_select)
 
   /* If this is a CALL or ASM_OPERANDS, don't do anything.  Some of the
      code below will do the wrong thing since the mode of such an
-     expression is VOIDmode.  */
-  if (code == CALL || code == ASM_OPERANDS)
+     expression is VOIDmode. 
+
+     Also do nothing if X is a CLOBBER; this can happen if X was
+     the return value from a call to gen_lowpart_for_combine.  */
+  if (code == CALL || code == ASM_OPERANDS || code == CLOBBER)
     return x;
 
   /* We want to perform the operation is its present mode unless we know
@@ -6185,7 +6354,7 @@ force_to_mode (x, mode, mask, reg, just_select)
             need it.  */
 
          if (GET_CODE (x) == AND && GET_CODE (XEXP (x, 1)) == CONST_INT
-             && INTVAL (XEXP (x, 1)) == mask)
+             && (unsigned HOST_WIDE_INT) INTVAL (XEXP (x, 1)) == mask)
            x = XEXP (x, 0);
 
          /* If it remains an AND, try making another AND with the bits
@@ -6236,12 +6405,32 @@ force_to_mode (x, mode, mask, reg, just_select)
          smask |= (HOST_WIDE_INT) -1 << width;
 
        if (GET_CODE (XEXP (x, 1)) == CONST_INT
-           && exact_log2 (- smask) >= 0
-           && (nonzero_bits (XEXP (x, 0), mode) & ~ mask) == 0
-           && (INTVAL (XEXP (x, 1)) & ~ mask) != 0)
-         return force_to_mode (plus_constant (XEXP (x, 0),
-                                              INTVAL (XEXP (x, 1)) & mask),
-                               mode, mask, reg, next_select);
+           && exact_log2 (- smask) >= 0)
+         {
+#ifdef STACK_BIAS
+           if (STACK_BIAS
+               && (XEXP (x, 0) == stack_pointer_rtx
+                   || XEXP (x, 0) == frame_pointer_rtx))
+             {
+                int sp_alignment = STACK_BOUNDARY / BITS_PER_UNIT;
+                unsigned HOST_WIDE_INT sp_mask = GET_MODE_MASK (mode);
+          
+               sp_mask &= ~ (sp_alignment - 1);
+               if ((sp_mask & ~ mask) == 0
+                   && ((INTVAL (XEXP (x, 1)) - STACK_BIAS) & ~ mask) != 0)
+                 return force_to_mode (plus_constant (XEXP (x, 0),
+                                                      ((INTVAL (XEXP (x, 1)) -
+                                                        STACK_BIAS) & mask)
+                                                      + STACK_BIAS),
+                                       mode, mask, reg, next_select);
+              }
+#endif
+           if ((nonzero_bits (XEXP (x, 0), mode) & ~ mask) == 0
+               && (INTVAL (XEXP (x, 1)) & ~ mask) != 0)
+             return force_to_mode (plus_constant (XEXP (x, 0),
+                                                  INTVAL (XEXP (x, 1)) & mask),
+                                   mode, mask, reg, next_select);
+         }
       }
 
       /* ... fall through ...  */
@@ -6386,7 +6575,7 @@ force_to_mode (x, mode, mask, reg, just_select)
       /* If we are just looking for the sign bit, we don't need this shift at
         all, even if it has a variable count.  */
       if (GET_MODE_BITSIZE (GET_MODE (x)) <= HOST_BITS_PER_WIDE_INT
-         && (mask == ((HOST_WIDE_INT) 1
+         && (mask == ((unsigned HOST_WIDE_INT) 1
                       << (GET_MODE_BITSIZE (GET_MODE (x)) - 1))))
        return force_to_mode (XEXP (x, 0), mode, mask, reg, next_select);
 
@@ -6840,8 +7029,6 @@ rtx_equal_for_field_assignment_p (x, y)
      rtx x;
      rtx y;
 {
-  rtx last_x, last_y;
-
   if (x == y || rtx_equal_p (x, y))
     return 1;
 
@@ -6863,19 +7050,12 @@ rtx_equal_for_field_assignment_p (x, y)
                      gen_lowpart_for_combine (GET_MODE (SUBREG_REG (x)), y)))
     return 1;
 
-  last_x = get_last_value (x);
-  last_y = get_last_value (y);
-
-  return ((last_x != 0
-          && GET_CODE (last_x) != CLOBBER
-          && rtx_equal_for_field_assignment_p (last_x, y))
-         || (last_y != 0
-             && GET_CODE (last_y) != CLOBBER
-             && rtx_equal_for_field_assignment_p (x, last_y))
-         || (last_x != 0 && last_y != 0
-             && GET_CODE (last_x) != CLOBBER
-             && GET_CODE (last_y) != CLOBBER
-             && rtx_equal_for_field_assignment_p (last_x, last_y)));
+  /* We used to see if get_last_value of X and Y were the same but that's
+     not correct.  In one direction, we'll cause the assignment to have
+     the wrong destination and in the case, we'll import a register into this
+     insn that might have already have been dead.   So fail if none of the
+     above cases are true.  */
+  return 0;
 }
 \f
 /* See if X, a SET operation, can be rewritten as a bit-field assignment.
@@ -6909,7 +7089,7 @@ make_field_assignment (x)
       assign = make_extraction (VOIDmode, dest, 0, XEXP (XEXP (src, 0), 1),
                                1, 1, 1, 0);
       if (assign != 0)
-       return gen_rtx (SET, VOIDmode, assign, const0_rtx);
+       return gen_rtx_SET (VOIDmode, assign, const0_rtx);
       return x;
     }
 
@@ -6925,7 +7105,7 @@ make_field_assignment (x)
                                XEXP (SUBREG_REG (XEXP (src, 0)), 1),
                                1, 1, 1, 0);
       if (assign != 0)
-       return gen_rtx (SET, VOIDmode, assign, const0_rtx);
+       return gen_rtx_SET (VOIDmode, assign, const0_rtx);
       return x;
     }
 
@@ -6938,7 +7118,7 @@ make_field_assignment (x)
       assign = make_extraction (VOIDmode, dest, 0, XEXP (XEXP (src, 0), 1),
                                1, 1, 1, 0);
       if (assign != 0)
-       return gen_rtx (SET, VOIDmode, assign, const1_rtx);
+       return gen_rtx_SET (VOIDmode, assign, const1_rtx);
       return x;
     }
 
@@ -6969,8 +7149,8 @@ make_field_assignment (x)
 
   pos = get_pos_from_mask ((~ c1) & GET_MODE_MASK (GET_MODE (dest)), &len);
   if (pos < 0 || pos + len > GET_MODE_BITSIZE (GET_MODE (dest))
-      || (GET_MODE_BITSIZE (GET_MODE (other)) <= HOST_BITS_PER_WIDE_INT
-         && (c1 & nonzero_bits (other, GET_MODE (other))) != 0))
+      || GET_MODE_BITSIZE (GET_MODE (dest)) > HOST_BITS_PER_WIDE_INT
+      || (c1 & nonzero_bits (other, GET_MODE (dest))) != 0)
     return x;
 
   assign = make_extraction (VOIDmode, dest, pos, NULL_RTX, len, 1, 1, 0);
@@ -7222,7 +7402,7 @@ simplify_and_const_int (x, mode, varop, constop)
   else
     {
       if (GET_CODE (XEXP (x, 1)) != CONST_INT
-         || INTVAL (XEXP (x, 1)) != constop)
+         || (unsigned HOST_WIDE_INT) INTVAL (XEXP (x, 1)) != constop)
        SUBST (XEXP (x, 1), GEN_INT (constop));
 
       SUBST (XEXP (x, 0), varop);
@@ -7314,10 +7494,15 @@ nonzero_bits (x, mode)
         In particular, in the Irix6 n64 ABI, the stack has 128 bit
         alignment but the argument pointer has only 64 bit alignment.  */
 
-      if (x == stack_pointer_rtx || x == frame_pointer_rtx
-         || x == hard_frame_pointer_rtx
-         || (REGNO (x) >= FIRST_VIRTUAL_REGISTER
-             && REGNO (x) <= LAST_VIRTUAL_REGISTER))
+      if ((x == frame_pointer_rtx
+          || x == stack_pointer_rtx
+          || x == hard_frame_pointer_rtx
+          || (REGNO (x) >= FIRST_VIRTUAL_REGISTER
+              && REGNO (x) <= LAST_VIRTUAL_REGISTER))
+#ifdef STACK_BIAS
+         && !STACK_BIAS
+#endif       
+             )
        {
          int sp_alignment = STACK_BOUNDARY / BITS_PER_UNIT;
 
@@ -7498,6 +7683,22 @@ nonzero_bits (x, mode)
        switch (code)
          {
          case PLUS:
+#ifdef STACK_BIAS
+           if (STACK_BIAS
+               && (XEXP (x, 0) == stack_pointer_rtx
+                   || XEXP (x, 0) == frame_pointer_rtx)
+               && GET_CODE (XEXP (x, 1)) == CONST_INT)
+             {
+               int sp_alignment = STACK_BOUNDARY / BITS_PER_UNIT;
+
+               nz0 = (GET_MODE_MASK (mode) & ~ (sp_alignment - 1));
+               nz1 = INTVAL (XEXP (x, 1)) - STACK_BIAS;
+               width0 = floor_log2 (nz0) + 1;
+               width1 = floor_log2 (nz1) + 1;
+               low0 = floor_log2 (nz0 & -nz0);
+               low1 = floor_log2 (nz1 & -nz1);
+             }
+#endif   
            result_width = MAX (width0, width1) + 1;
            result_low = MIN (low0, low1);
            break;
@@ -7560,15 +7761,23 @@ nonzero_bits (x, mode)
        {
          nonzero &= nonzero_bits (SUBREG_REG (x), mode);
 
-#ifndef WORD_REGISTER_OPERATIONS
-         /* On many CISC machines, accessing an object in a wider mode
-            causes the high-order bits to become undefined.  So they are
-            not known to be zero.  */
-         if (GET_MODE_SIZE (GET_MODE (x))
-             > GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))))
-           nonzero |= (GET_MODE_MASK (GET_MODE (x))
-                       & ~ GET_MODE_MASK (GET_MODE (SUBREG_REG (x))));
+#if defined (WORD_REGISTER_OPERATIONS) && defined (LOAD_EXTEND_OP)
+         /* If this is a typical RISC machine, we only have to worry
+            about the way loads are extended.  */
+         if (LOAD_EXTEND_OP (GET_MODE (SUBREG_REG (x))) == SIGN_EXTEND
+             ? (nonzero
+                & (1L << (GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (x))) - 1)))
+             : LOAD_EXTEND_OP (GET_MODE (SUBREG_REG (x))) != ZERO_EXTEND)
 #endif
+           {
+             /* On many CISC machines, accessing an object in a wider mode
+                causes the high-order bits to become undefined.  So they are
+                not known to be zero.  */
+             if (GET_MODE_SIZE (GET_MODE (x))
+                 > GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))))
+               nonzero |= (GET_MODE_MASK (GET_MODE (x))
+                           & ~ GET_MODE_MASK (GET_MODE (SUBREG_REG (x))));
+           }
        }
       break;
 
@@ -8068,7 +8277,7 @@ merge_outer_ops (pop0, pconst0, op1, const1, mode, pcomp_p)
          op0 = SET;
        else /* op1 == XOR */
          /* (a ^ b) | b == a | b */
-         ;
+         {;}
        break;
 
       case XOR:
@@ -8099,7 +8308,8 @@ merge_outer_ops (pop0, pconst0, op1, const1, mode, pcomp_p)
     op0 = NIL;
   else if (const0 == 0 && op0 == AND)
     op0 = SET;
-  else if (const0 == GET_MODE_MASK (mode) && op0 == AND)
+  else if ((unsigned HOST_WIDE_INT) const0 == GET_MODE_MASK (mode)
+          && op0 == AND)
     op0 = NIL;
 
   /* If this would be an entire word for the target, but is not for
@@ -8158,7 +8368,7 @@ simplify_shift_const (x, code, result_mode, varop, count)
       if (x)
        return x;
 
-      return gen_rtx (code, mode, varop, GEN_INT (count));
+      return gen_rtx_fmt_ee (code, mode, varop, GEN_INT (count));
     }
 
   /* Unless one of the branches of the `if' in this loop does a `continue',
@@ -8276,11 +8486,11 @@ simplify_shift_const (x, code, result_mode, varop, count)
                                         MODE_INT, 1)) != BLKmode)
            {
              if (BYTES_BIG_ENDIAN)
-               new = gen_rtx (MEM, tmode, XEXP (varop, 0));
+               new = gen_rtx_MEM (tmode, XEXP (varop, 0));
              else
-               new = gen_rtx (MEM, tmode,
-                              plus_constant (XEXP (varop, 0),
-                                             count / BITS_PER_UNIT));
+               new = gen_rtx_MEM (tmode,
+                                  plus_constant (XEXP (varop, 0),
+                                                 count / BITS_PER_UNIT));
              RTX_UNCHANGING_P (new) = RTX_UNCHANGING_P (varop);
              MEM_VOLATILE_P (new) = MEM_VOLATILE_P (varop);
              MEM_IN_STRUCT_P (new) = MEM_IN_STRUCT_P (varop);
@@ -8723,6 +8933,29 @@ simplify_shift_const (x, code, result_mode, varop, count)
              continue;
            }
          break;
+
+       case TRUNCATE:
+         /* Change (lshiftrt (truncate (lshiftrt))) to (truncate (lshiftrt))
+            if the truncate does not affect the value.  */
+         if (code == LSHIFTRT
+             && GET_CODE (XEXP (varop, 0)) == LSHIFTRT
+             && GET_CODE (XEXP (XEXP (varop, 0), 1)) == CONST_INT
+             && (INTVAL (XEXP (XEXP (varop, 0), 1))
+                 >= (GET_MODE_BITSIZE (GET_MODE (XEXP (varop, 0)))
+                     - GET_MODE_BITSIZE (GET_MODE (varop)))))
+           {
+             rtx varop_inner = XEXP (varop, 0);
+
+             varop_inner = gen_rtx_combine (LSHIFTRT,
+                                            GET_MODE (varop_inner),
+                                            XEXP (varop_inner, 0),
+                                            GEN_INT (count + INTVAL (XEXP (varop_inner, 1))));
+             varop = gen_rtx_combine (TRUNCATE, GET_MODE (varop),
+                                      varop_inner);
+             count = 0;
+             continue;
+           }
+         break;
          
        default:
          break;
@@ -8850,18 +9083,14 @@ simplify_shift_const (x, code, result_mode, varop, count)
    PNOTES is a pointer to a location where any REG_UNUSED notes added for
    the CLOBBERs are placed.
 
-   PADDED_SCRATCHES is set to the number of (clobber (scratch)) patterns
-   we had to add.
-
    The value is the final insn code from the pattern ultimately matched,
    or -1.  */
 
 static int
-recog_for_combine (pnewpat, insn, pnotes, padded_scratches)
+recog_for_combine (pnewpat, insn, pnotes)
      rtx *pnewpat;
      rtx insn;
      rtx *pnotes;
-     int *padded_scratches;
 {
   register rtx pat = *pnewpat;
   int insn_code_number;
@@ -8869,8 +9098,6 @@ recog_for_combine (pnewpat, insn, pnotes, padded_scratches)
   int i;
   rtx notes = 0;
 
-  *padded_scratches = 0;
-
   /* If PAT is a PARALLEL, check to see if it contains the CLOBBER
      we use to indicate that something didn't match.  If we find such a
      thing, force rejection.  */
@@ -8913,10 +9140,10 @@ recog_for_combine (pnewpat, insn, pnotes, padded_scratches)
      them.  Then check to make sure that all of them are dead.  */
   if (num_clobbers_to_add)
     {
-      rtx newpat = gen_rtx (PARALLEL, VOIDmode,
-                           gen_rtvec (GET_CODE (pat) == PARALLEL
-                                      ? XVECLEN (pat, 0) + num_clobbers_to_add
-                                      : num_clobbers_to_add + 1));
+      rtx newpat = gen_rtx_PARALLEL (VOIDmode,
+                                    gen_rtvec (GET_CODE (pat) == PARALLEL
+                                               ? XVECLEN (pat, 0) + num_clobbers_to_add
+                                               : num_clobbers_to_add + 1));
 
       if (GET_CODE (pat) == PARALLEL)
        for (i = 0; i < XVECLEN (pat, 0); i++)
@@ -8932,10 +9159,8 @@ recog_for_combine (pnewpat, insn, pnotes, padded_scratches)
          if (GET_CODE (XEXP (XVECEXP (newpat, 0, i), 0)) == REG
              && ! reg_dead_at_p (XEXP (XVECEXP (newpat, 0, i), 0), insn))
            return -1;
-         else if (GET_CODE (XEXP (XVECEXP (newpat, 0, i), 0)) == SCRATCH)
-           (*padded_scratches)++;
-         notes = gen_rtx (EXPR_LIST, REG_UNUSED,
-                          XEXP (XVECEXP (newpat, 0, i), 0), notes);
+         notes = gen_rtx_EXPR_LIST (REG_UNUSED,
+                                    XEXP (XVECEXP (newpat, 0, i), 0), notes);
        }
       pat = newpat;
     }
@@ -8975,7 +9200,7 @@ gen_lowpart_for_combine (mode, x)
             && (GET_CODE (x) == CONST_INT
                 || GET_CODE (x) == CONST_DOUBLE))
            || GET_MODE_SIZE (GET_MODE (x)) == GET_MODE_SIZE (mode)))
-    return gen_rtx (CLOBBER, GET_MODE (x), const0_rtx);
+    return gen_rtx_CLOBBER (GET_MODE (x), const0_rtx);
 
   /* X might be a paradoxical (subreg (mem)).  In that case, gen_lowpart
      won't know what to do.  So we will strip off the SUBREG here and
@@ -9007,13 +9232,13 @@ gen_lowpart_for_combine (mode, x)
       /* Refuse to work on a volatile memory ref or one with a mode-dependent
         address.  */
       if (MEM_VOLATILE_P (x) || mode_dependent_address_p (XEXP (x, 0)))
-       return gen_rtx (CLOBBER, GET_MODE (x), const0_rtx);
+       return gen_rtx_CLOBBER (GET_MODE (x), const0_rtx);
 
       /* If we want to refer to something bigger than the original memref,
         generate a perverse subreg instead.  That will force a reload
         of the original memref X.  */
       if (GET_MODE_SIZE (GET_MODE (x)) < GET_MODE_SIZE (mode))
-       return gen_rtx (SUBREG, mode, x, 0);
+       return gen_rtx_SUBREG (mode, x, 0);
 
       if (WORDS_BIG_ENDIAN)
        offset = (MAX (GET_MODE_SIZE (GET_MODE (x)), UNITS_PER_WORD)
@@ -9025,7 +9250,7 @@ gen_lowpart_for_combine (mode, x)
          offset -= (MIN (UNITS_PER_WORD, GET_MODE_SIZE (mode))
                     - MIN (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (x))));
        }
-      new = gen_rtx (MEM, mode, plus_constant (XEXP (x, 0), offset));
+      new = gen_rtx_MEM (mode, plus_constant (XEXP (x, 0), offset));
       RTX_UNCHANGING_P (new) = RTX_UNCHANGING_P (x);
       MEM_VOLATILE_P (new) = MEM_VOLATILE_P (x);
       MEM_IN_STRUCT_P (new) = MEM_IN_STRUCT_P (x);
@@ -9048,7 +9273,7 @@ gen_lowpart_for_combine (mode, x)
        word = ((GET_MODE_SIZE (GET_MODE (x))
                 - MAX (GET_MODE_SIZE (mode), UNITS_PER_WORD))
                / UNITS_PER_WORD);
-      return gen_rtx (SUBREG, mode, x, word);
+      return gen_rtx_SUBREG (mode, x, word);
     }
 }
 \f
@@ -9063,21 +9288,21 @@ gen_lowpart_for_combine (mode, x)
 static rtx
 gen_rtx_combine VPROTO((enum rtx_code code, enum machine_mode mode, ...))
 {
-#ifndef __STDC__
+#ifndef ANSI_PROTOTYPES
   enum rtx_code code;
   enum machine_mode mode;
 #endif
   va_list p;
   int n_args;
   rtx args[3];
-  int i, j;
+  int j;
   char *fmt;
   rtx rt;
   struct undo *undo;
 
   VA_START (p, mode);
 
-#ifndef __STDC__
+#ifndef ANSI_PROTOTYPES
   code = va_arg (p, enum rtx_code);
   mode = va_arg (p, enum machine_mode);
 #endif
@@ -9177,6 +9402,13 @@ gen_binary (code, mode, op0, op1)
              && GET_RTX_CLASS (GET_CODE (op1)) != 'o')))
     return gen_rtx_combine (code, mode, op1, op0);
 
+  /* If we are turning off bits already known off in OP0, we need not do
+     an AND.  */
+  else if (code == AND && GET_CODE (op1) == CONST_INT
+          && GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT
+          && (nonzero_bits (op0, mode) & ~ INTVAL (op1)) == 0)
+    return op0;
+
   return gen_rtx_combine (code, mode, op0, op1);
 }
 
@@ -9309,10 +9541,10 @@ simplify_comparison (code, pop0, pop1)
                  > GET_MODE_SIZE (GET_MODE (SUBREG_REG (inner_op0))))
              && (GET_MODE (SUBREG_REG (inner_op0))
                  == GET_MODE (SUBREG_REG (inner_op1)))
-             && (GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (op0)))
+             && (GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (inner_op0)))
                  <= HOST_BITS_PER_WIDE_INT)
              && (0 == ((~c0) & nonzero_bits (SUBREG_REG (inner_op0),
-                                            GET_MODE (SUBREG_REG (op0)))))
+                                            GET_MODE (SUBREG_REG (inner_op0)))))
              && (0 == ((~c1) & nonzero_bits (SUBREG_REG (inner_op1),
                                             GET_MODE (SUBREG_REG (inner_op1))))))
            {
@@ -9330,7 +9562,7 @@ simplify_comparison (code, pop0, pop1)
            for (tmode = GET_CLASS_NARROWEST_MODE
                 (GET_MODE_CLASS (GET_MODE (op0)));
                 tmode != GET_MODE (op0); tmode = GET_MODE_WIDER_MODE (tmode))
-             if (c0 == GET_MODE_MASK (tmode))
+             if ((unsigned HOST_WIDE_INT) c0 == GET_MODE_MASK (tmode))
                {
                  op0 = gen_lowpart_for_combine (tmode, inner_op0);
                  op1 = gen_lowpart_for_combine (tmode, inner_op1);
@@ -9405,7 +9637,7 @@ simplify_comparison (code, pop0, pop1)
              || code == LT || code == LTU)
          && mode_width <= HOST_BITS_PER_WIDE_INT
          && exact_log2 (const_op) >= 0
-         && nonzero_bits (op0, mode) == const_op)
+         && nonzero_bits (op0, mode) == (unsigned HOST_WIDE_INT) const_op)
        {
          code = (code == EQ || code == GE || code == GEU ? NE : EQ);
          op1 = const0_rtx, const_op = 0;
@@ -9597,12 +9829,16 @@ simplify_comparison (code, pop0, pop1)
              && (i = exact_log2 (INTVAL (XEXP (op0, 0)))) >= 0)
            {
              if (BITS_BIG_ENDIAN)
+               {
 #ifdef HAVE_extzv
-               i = (GET_MODE_BITSIZE
-                    (insn_operand_mode[(int) CODE_FOR_extzv][1]) - 1 - i);
+                 mode = insn_operand_mode[(int) CODE_FOR_extzv][1];
+                 if (mode == VOIDmode)
+                   mode = word_mode;
+                 i = (GET_MODE_BITSIZE (mode) - 1 - i);
 #else
-               i = BITS_PER_WORD - 1 - i;
+                 i = BITS_PER_WORD - 1 - i;
 #endif
+               }
 
              op0 = XEXP (op0, 2);
              op1 = GEN_INT (i);
@@ -9730,7 +9966,7 @@ simplify_comparison (code, pop0, pop1)
              && (GET_MODE_BITSIZE (GET_MODE (XEXP (op0, 0)))
                  <= HOST_BITS_PER_WIDE_INT)
              && ((unsigned HOST_WIDE_INT) const_op
-                 < (((HOST_WIDE_INT) 1
+                 < (((unsigned HOST_WIDE_INT) 1
                      << (GET_MODE_BITSIZE (GET_MODE (XEXP (op0, 0))) - 1)))))
            {
              op0 = XEXP (op0, 0);
@@ -9754,7 +9990,7 @@ simplify_comparison (code, pop0, pop1)
              && GET_CODE (XEXP (SUBREG_REG (op0), 1)) == CONST_INT
              && INTVAL (XEXP (SUBREG_REG (op0), 1)) < 0
              && (- INTVAL (XEXP (SUBREG_REG (op0), 1))
-                 < GET_MODE_MASK (mode) / 2)
+                 < (HOST_WIDE_INT)(GET_MODE_MASK (mode) / 2))
              && (unsigned HOST_WIDE_INT) const_op < GET_MODE_MASK (mode) / 2
              && (0 == (nonzero_bits (XEXP (SUBREG_REG (op0), 0),
                                      GET_MODE (SUBREG_REG (op0)))
@@ -9958,7 +10194,7 @@ simplify_comparison (code, pop0, pop1)
              && GET_CODE (XEXP (op0, 1)) == CONST_INT
              && mode_width <= HOST_BITS_PER_WIDE_INT
              && ((INTVAL (XEXP (op0, 1)) & GET_MODE_MASK (mode))
-                 == (HOST_WIDE_INT) 1 << (mode_width - 1)))
+                 == (unsigned HOST_WIDE_INT) 1 << (mode_width - 1)))
            {
              op0 = XEXP (op0, 0);
              code = (code == EQ ? GE : LT);
@@ -9980,6 +10216,48 @@ simplify_comparison (code, pop0, pop1)
              op0 = gen_lowpart_for_combine (tmode, XEXP (op0, 0));
              continue;
            }
+
+         /* If this is (and:M1 (subreg:M2 X 0) (const_int C1)) where C1 fits
+            in both M1 and M2 and the SUBREG is either paradoxical or
+            represents the low part, permute the SUBREG and the AND and
+            try again.  */
+         if (GET_CODE (XEXP (op0, 0)) == SUBREG
+             && ((mode_width
+                  >= GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (XEXP (op0, 0)))))
+#ifdef WORD_REGISTER_OPERATIONS
+                 || subreg_lowpart_p (XEXP (op0, 0))
+#endif
+                 )
+#ifndef WORD_REGISTER_OPERATIONS
+             /* It is unsafe to commute the AND into the SUBREG if the SUBREG
+                is paradoxical and WORD_REGISTER_OPERATIONS is not defined.
+                As originally written the upper bits have a defined value
+                due to the AND operation.  However, if we commute the AND
+                inside the SUBREG then they no longer have defined values
+                and the meaning of the code has been changed.  */
+             && (GET_MODE_SIZE (GET_MODE (XEXP (op0, 0)))
+                 <= GET_MODE_SIZE (GET_MODE (SUBREG_REG (XEXP (op0, 0)))))
+#endif
+             && GET_CODE (XEXP (op0, 1)) == CONST_INT
+             && mode_width <= HOST_BITS_PER_WIDE_INT
+             && (GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (XEXP (op0, 0))))
+                 <= HOST_BITS_PER_WIDE_INT)
+             && (INTVAL (XEXP (op0, 1)) & ~ mask) == 0
+             && 0 == (~ GET_MODE_MASK (GET_MODE (SUBREG_REG (XEXP (op0, 0))))
+                      & INTVAL (XEXP (op0, 1)))
+             && (unsigned HOST_WIDE_INT) INTVAL (XEXP (op0, 1)) != mask
+             && ((unsigned HOST_WIDE_INT) INTVAL (XEXP (op0, 1))
+                 != GET_MODE_MASK (GET_MODE (SUBREG_REG (XEXP (op0, 0))))))
+                      
+           {
+             op0
+               = gen_lowpart_for_combine
+                 (mode,
+                  gen_binary (AND, GET_MODE (SUBREG_REG (XEXP (op0, 0))),
+                              SUBREG_REG (XEXP (op0, 0)), XEXP (op0, 1)));
+             continue;
+           }
+
          break;
 
        case ASHIFT:
@@ -10102,7 +10380,7 @@ simplify_comparison (code, pop0, pop1)
     }
 
   /* Now make any compound operations involved in this comparison.  Then,
-     check for an outmost SUBREG on OP0 that isn't doing anything or is
+     check for an outmost SUBREG on OP0 that is not doing anything or is
      paradoxical.  The latter case can only occur when it is known that the
      "extra" bits will be zero.  Therefore, it is safe to remove the SUBREG.
      We can never remove a SUBREG for a non-equality comparison because the
@@ -10484,7 +10762,7 @@ get_last_value_validate (loc, insn, tick, replace)
                && reg_last_set_label[j] > tick))
          {
            if (replace)
-             *loc = gen_rtx (CLOBBER, GET_MODE (x), const0_rtx);
+             *loc = gen_rtx_CLOBBER (GET_MODE (x), const0_rtx);
            return replace;
          }
 
@@ -10497,7 +10775,7 @@ get_last_value_validate (loc, insn, tick, replace)
           && INSN_CUID (insn) <= mem_last_set)
     {
       if (replace)
-       *loc = gen_rtx (CLOBBER, GET_MODE (x), const0_rtx);
+       *loc = gen_rtx_CLOBBER (GET_MODE (x), const0_rtx);
       return replace;
     }
 
@@ -10590,7 +10868,7 @@ get_last_value (x)
 
          if (reg_mentioned_p (x, value))
            value = replace_rtx (copy_rtx (value), x,
-                                gen_rtx (CLOBBER, GET_MODE (x), const0_rtx));
+                                gen_rtx_CLOBBER (GET_MODE (x), const0_rtx));
 
          if (reg_overlap_mentioned_p (x, value))
            return 0;
@@ -10957,9 +11235,9 @@ move_deaths (x, maybe_kill_insn, from_cuid, to_insn, pnotes)
              for (i = deadregno; i < deadend; i++)
                if (i < regno || i >= ourend)
                  REG_NOTES (where_dead)
-                   = gen_rtx (EXPR_LIST, REG_DEAD,
-                              gen_rtx (REG, reg_raw_mode[i], i),
-                              REG_NOTES (where_dead));
+                   = gen_rtx_EXPR_LIST (REG_DEAD,
+                                        gen_rtx_REG (reg_raw_mode[i], i),
+                                        REG_NOTES (where_dead));
            }
          /* If we didn't find any note, or if we found a REG_DEAD note that
             covers only part of the given reg, and we have a multi-reg hard
@@ -10983,7 +11261,7 @@ move_deaths (x, maybe_kill_insn, from_cuid, to_insn, pnotes)
                offset = 1;
 
              for (i = regno + offset; i < ourend; i++)
-               move_deaths (gen_rtx (REG, reg_raw_mode[i], i),
+               move_deaths (gen_rtx_REG (reg_raw_mode[i], i),
                             maybe_kill_insn, from_cuid, to_insn, &oldnotes);
            }
 
@@ -10993,7 +11271,7 @@ move_deaths (x, maybe_kill_insn, from_cuid, to_insn, pnotes)
              *pnotes = note;
            }
          else
-           *pnotes = gen_rtx (EXPR_LIST, REG_DEAD, x, *pnotes);
+           *pnotes = gen_rtx_EXPR_LIST (REG_DEAD, x, *pnotes);
 
          REG_N_DEATHS (regno)++;
        }
@@ -11312,15 +11590,35 @@ distribute_notes (notes, from_insn, i3, i2, elim_i2, elim_i1)
                  if (reg_set_p (XEXP (note, 0), PATTERN (tem)))
                    {
                      rtx set = single_set (tem);
+                     rtx inner_dest = 0;
+#ifdef HAVE_cc0
+                     rtx cc0_setter = NULL_RTX;
+#endif
+
+                     if (set != 0)
+                       for (inner_dest = SET_DEST (set);
+                            GET_CODE (inner_dest) == STRICT_LOW_PART
+                            || GET_CODE (inner_dest) == SUBREG
+                            || GET_CODE (inner_dest) == ZERO_EXTRACT;
+                            inner_dest = XEXP (inner_dest, 0))
+                         ;
 
                      /* Verify that it was the set, and not a clobber that
-                        modified the register.  */
+                        modified the register. 
+
+                        CC0 targets must be careful to maintain setter/user
+                        pairs.  If we cannot delete the setter due to side
+                        effects, mark the user with an UNUSED note instead
+                        of deleting it.  */
 
                      if (set != 0 && ! side_effects_p (SET_SRC (set))
-                         && (rtx_equal_p (XEXP (note, 0), SET_DEST (set))
-                             || (GET_CODE (SET_DEST (set)) == SUBREG
-                                 && rtx_equal_p (XEXP (note, 0),
-                                                 XEXP (SET_DEST (set), 0)))))
+                         && rtx_equal_p (XEXP (note, 0), inner_dest)
+#ifdef HAVE_cc0
+                         && (! reg_mentioned_p (cc0_rtx, SET_SRC (set))
+                             || ((cc0_setter = prev_cc0_setter (tem)) != NULL
+                                 && sets_cc0_p (PATTERN (cc0_setter)) > 0))
+#endif
+                         )
                        {
                          /* Move the notes and links of TEM elsewhere.
                             This might delete other dead insns recursively. 
@@ -11336,6 +11634,38 @@ distribute_notes (notes, from_insn, i3, i2, elim_i2, elim_i1)
                          PUT_CODE (tem, NOTE);
                          NOTE_LINE_NUMBER (tem) = NOTE_INSN_DELETED;
                          NOTE_SOURCE_FILE (tem) = 0;
+
+#ifdef HAVE_cc0
+                         /* Delete the setter too.  */
+                         if (cc0_setter)
+                           {
+                             PATTERN (cc0_setter) = pc_rtx;
+
+                             distribute_notes (REG_NOTES (cc0_setter),
+                                               cc0_setter, cc0_setter,
+                                               NULL_RTX, NULL_RTX, NULL_RTX);
+                             distribute_links (LOG_LINKS (cc0_setter));
+
+                             PUT_CODE (cc0_setter, NOTE);
+                             NOTE_LINE_NUMBER (cc0_setter) = NOTE_INSN_DELETED;
+                             NOTE_SOURCE_FILE (cc0_setter) = 0;
+                           }
+#endif
+                       }
+                     /* If the register is both set and used here, put the
+                        REG_DEAD note here, but place a REG_UNUSED note
+                        here too unless there already is one.  */
+                     else if (reg_referenced_p (XEXP (note, 0),
+                                                PATTERN (tem)))
+                       {
+                         place = tem;
+
+                         if (! find_regno_note (tem, REG_UNUSED,
+                                                REGNO (XEXP (note, 0))))
+                           REG_NOTES (tem)
+                             = gen_rtx_EXPR_LIST (REG_UNUSED,
+                                                  XEXP (note, 0),
+                                                  REG_NOTES (tem));
                        }
                      else
                        {
@@ -11382,7 +11712,7 @@ distribute_notes (notes, from_insn, i3, i2, elim_i2, elim_i1)
              if (REG_NOTE_KIND (note) == REG_DEAD && place == 0 && tem != 0)
                {
                  place
-                   = emit_insn_after (gen_rtx (USE, VOIDmode, XEXP (note, 0)),
+                   = emit_insn_after (gen_rtx_USE (VOIDmode, XEXP (note, 0)),
                                       tem);
 
                  /* If this insn was emitted between blocks, then update
@@ -11393,13 +11723,12 @@ distribute_notes (notes, from_insn, i3, i2, elim_i2, elim_i1)
            }
 
          /* If the register is set or already dead at PLACE, we needn't do
-            anything with this note if it is still a REG_DEAD note.  
+            anything with this note if it is still a REG_DEAD note.
+            We can here if it is set at all, not if is it totally replace,
+            which is what `dead_or_set_p' checks, so also check for it being
+            set partially.  */
+
 
-            Note that we cannot use just `dead_or_set_p' here since we can
-            convert an assignment to a register into a bit-field assignment.
-            Therefore, we must also omit the note if the register is the 
-            target of a bitfield assignment.  */
-            
          if (place && REG_NOTE_KIND (note) == REG_DEAD)
            {
              int regno = REGNO (XEXP (note, 0));
@@ -11441,7 +11770,7 @@ distribute_notes (notes, from_insn, i3, i2, elim_i2, elim_i1)
                    if (! refers_to_regno_p (i, i + 1, PATTERN (place), 0)
                        && ! find_regno_fusage (place, USE, i))
                      {
-                       rtx piece = gen_rtx (REG, reg_raw_mode[i], i);
+                       rtx piece = gen_rtx_REG (reg_raw_mode[i], i);
                        rtx p;
 
                        /* See if we already placed a USE note for this
@@ -11460,12 +11789,12 @@ distribute_notes (notes, from_insn, i3, i2, elim_i2, elim_i1)
                        if (p)
                          {
                            rtx use_insn
-                             = emit_insn_before (gen_rtx (USE, VOIDmode,
-                                                          piece),
+                             = emit_insn_before (gen_rtx_USE (VOIDmode,
+                                                              piece),
                                                  p);
                            REG_NOTES (use_insn)
-                             = gen_rtx (EXPR_LIST, REG_DEAD, piece,
-                                        REG_NOTES (use_insn));
+                             = gen_rtx_EXPR_LIST (REG_DEAD, piece,
+                                                  REG_NOTES (use_insn));
                          }
 
                        all_used = 0;
@@ -11488,7 +11817,7 @@ distribute_notes (notes, from_insn, i3, i2, elim_i2, elim_i1)
 
                      for (i = regno; i < endregno; i++)
                        {
-                         rtx piece = gen_rtx (REG, reg_raw_mode[i], i);
+                         rtx piece = gen_rtx_REG (reg_raw_mode[i], i);
 
                          if ((reg_referenced_p (piece, PATTERN (place))
                               || (GET_CODE (place) == CALL_INSN
@@ -11496,9 +11825,9 @@ distribute_notes (notes, from_insn, i3, i2, elim_i2, elim_i1)
                              && ! dead_or_set_p (place, piece)
                              && ! reg_bitfield_target_p (piece,
                                                          PATTERN (place)))
-                           REG_NOTES (place) = gen_rtx (EXPR_LIST, REG_DEAD,
-                                                        piece,
-                                                        REG_NOTES (place));
+                           REG_NOTES (place)
+                             = gen_rtx_EXPR_LIST (REG_DEAD,
+                                                  piece, REG_NOTES (place));
                        }
 
                      place = 0;
@@ -11530,8 +11859,10 @@ distribute_notes (notes, from_insn, i3, i2, elim_i2, elim_i1)
              && GET_CODE (XEXP (note, 0)) == REG)
            REG_N_DEATHS (REGNO (XEXP (note, 0)))++;
 
-         REG_NOTES (place2) = gen_rtx (GET_CODE (note), REG_NOTE_KIND (note),
-                                       XEXP (note, 0), REG_NOTES (place2));
+         REG_NOTES (place2) = gen_rtx_fmt_ee (GET_CODE (note),
+                                              REG_NOTE_KIND (note),
+                                              XEXP (note, 0),
+                                              REG_NOTES (place2));
        }
     }
 }