OSDN Git Service

* cppinit.c (cpp_start_read): Free the imacros list as we
[pf3gnuchains/gcc-fork.git] / gcc / combine.c
index 55be324..78bf6ce 100644 (file)
@@ -1,24 +1,23 @@
 /* Optimize by combining instructions for GNU compiler.
    Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000 Free Software Foundation, Inc.
+   1999, 2000, 2001 Free Software Foundation, Inc.
 
-This file is part of GNU CC.
+This file is part of GCC.
 
-GNU CC is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
 
-GNU CC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
 
 You should have received a copy of the GNU General Public License
-along with GNU CC; see the file COPYING.  If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.  */
-
+along with GCC; see the file COPYING.  If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.  */
 
 /* This module is essentially the "combiner" phase of the U. of Arizona
    Portable Optimizer, but redone to work on our list-structured
@@ -59,7 +58,7 @@ Boston, MA 02111-1307, USA.  */
    - there are extremely rare cases (see distribute_regnotes) when a
      REG_DEAD note is lost
    - a LOG_LINKS entry that refers to an insn with multiple SETs may be
-     removed because there is no way to know which register it was 
+     removed because there is no way to know which register it was
      linking
 
    To simplify substitution, we combine only when the earlier insn(s)
@@ -85,28 +84,12 @@ Boston, MA 02111-1307, USA.  */
 #include "basic-block.h"
 #include "insn-config.h"
 #include "function.h"
-/* Include expr.h after insn-config.h so we get HAVE_conditional_move. */
+/* 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"
-#include "defaults.h"
-
-#ifndef ACCUMULATE_OUTGOING_ARGS
-#define ACCUMULATE_OUTGOING_ARGS 0
-#endif
-
-/* Supply a default definition for PUSH_ARGS.  */
-#ifndef PUSH_ARGS
-#ifdef PUSH_ROUNDING
-#define PUSH_ARGS      !ACCUMULATE_OUTGOING_ARGS
-#else
-#define PUSH_ARGS      0
-#endif
-#endif
 
 /* It is not safe to use ordinary gen_lowpart in combine.
    Use gen_lowpart_for_combine instead.  See comments there.  */
@@ -132,12 +115,6 @@ static int combine_successes;
 
 static int total_attempts, total_merges, total_extras, total_successes;
 
-/* Define a default value for REVERSIBLE_CC_MODE.
-   We can never assume that a condition code mode is safe to reverse unless
-   the md tells us so.  */
-#ifndef REVERSIBLE_CC_MODE
-#define REVERSIBLE_CC_MODE(MODE) 0
-#endif
 \f
 /* Vector mapping INSN_UIDs to cuids.
    The cuids are like uids but increase monotonically always.
@@ -154,6 +131,12 @@ static int max_uid_cuid;
 #define INSN_CUID(INSN) \
 (INSN_UID (INSN) > max_uid_cuid ? insn_cuid (INSN) : uid_cuid[INSN_UID (INSN)])
 
+/* In case BITS_PER_WORD == HOST_BITS_PER_WIDE_INT, shifting by
+   BITS_PER_WORD would invoke undefined behavior.  Work around it.  */
+
+#define UWIDE_SHIFT_LEFT_BY_BITS_PER_WORD(val) \
+  (((unsigned HOST_WIDE_INT)(val) << (BITS_PER_WORD - 1)) << 1)
+
 /* Maximum register number, which is the size of the tables below.  */
 
 static unsigned int combine_max_regno;
@@ -212,8 +195,8 @@ static rtx added_links_insn;
 /* Basic block number of the block in which we are performing combines.  */
 static int this_basic_block;
 
-/* A bitmap indicating which blocks had registers go dead at entry.  
-   After combine, we'll need to re-do global life analysis with 
+/* A bitmap indicating which blocks had registers go dead at entry.
+   After combine, we'll need to re-do global life analysis with
    those blocks as starting points.  */
 static sbitmap refresh_blocks;
 static int need_refresh;
@@ -331,30 +314,20 @@ struct undo
 {
   struct undo *next;
   int is_int;
-  union {rtx r; int i;} old_contents;
-  union {rtx *r; int *i;} where;
+  union {rtx r; unsigned int i;} old_contents;
+  union {rtx *r; unsigned int *i;} where;
 };
 
 /* Record a bunch of changes to be undone, up to MAX_UNDO of them.
    num_undo says how many are currently recorded.
 
-   storage is nonzero if we must undo the allocation of new storage.
-   The value of storage is what to pass to obfree.
-
    other_insn is nonzero if we have modified some other insn in the process
-   of working on subst_insn.  It must be verified too.
-
-   previous_undos is the value of undobuf.undos when we started processing
-   this substitution.  This will prevent gen_rtx_combine from re-used a piece
-   from the previous expression.  Doing so can produce circular rtl
-   structures.  */
+   of working on subst_insn.  It must be verified too.  */
 
 struct undobuf
 {
-  char *storage;
   struct undo *undos;
   struct undo *frees;
-  struct undo *previous_undos;
   rtx other_insn;
 };
 
@@ -366,10 +339,12 @@ static struct undobuf undobuf;
 static int n_occurrences;
 
 static void do_SUBST                   PARAMS ((rtx *, rtx));
-static void do_SUBST_INT               PARAMS ((int *, int));
+static void do_SUBST_INT               PARAMS ((unsigned int *,
+                                                unsigned int));
 static void init_reg_last_arrays       PARAMS ((void));
 static void setup_incoming_promotions   PARAMS ((void));
 static void set_nonzero_bits_and_sign_copies  PARAMS ((rtx, rtx, void *));
+static int cant_combine_insn_p PARAMS ((rtx));
 static int can_combine_p       PARAMS ((rtx, rtx, rtx, rtx, rtx *, rtx *));
 static int sets_function_arg_p PARAMS ((rtx));
 static int combinable_i3pat    PARAMS ((rtx, rtx *, rtx, rtx, int, rtx *));
@@ -410,14 +385,9 @@ static rtx simplify_shift_const    PARAMS ((rtx, enum rtx_code, enum machine_mode,
                                         rtx, int));
 static int recog_for_combine   PARAMS ((rtx *, rtx, rtx *));
 static rtx gen_lowpart_for_combine  PARAMS ((enum machine_mode, rtx));
-static rtx gen_rtx_combine PARAMS ((enum rtx_code code, enum machine_mode mode,
-                                   ...));
 static rtx gen_binary          PARAMS ((enum rtx_code, enum machine_mode,
                                         rtx, rtx));
-static rtx gen_unary           PARAMS ((enum rtx_code, enum machine_mode,
-                                        enum machine_mode, rtx));
 static enum rtx_code simplify_comparison  PARAMS ((enum rtx_code, rtx *, rtx *));
-static int reversible_comparison_p  PARAMS ((rtx));
 static void update_table_tick  PARAMS ((rtx));
 static void record_value_for_reg  PARAMS ((rtx, rtx, rtx));
 static void check_promoted_subreg PARAMS ((rtx, rtx));
@@ -435,6 +405,8 @@ static void distribute_links        PARAMS ((rtx));
 static void mark_used_regs_combine PARAMS ((rtx));
 static int insn_cuid           PARAMS ((rtx));
 static void record_promoted_value PARAMS ((rtx, rtx));
+static rtx reversed_comparison  PARAMS ((rtx, enum machine_mode, rtx, rtx));
+static enum rtx_code combine_reversed_comparison_code PARAMS ((rtx));
 \f
 /* Substitute NEWVAL, an rtx expression, into INTO, a place in some
    insn.  The substitution can be undone by undo_all.  If INTO is already
@@ -443,7 +415,7 @@ static void record_promoted_value PARAMS ((rtx, rtx));
    the undo table.  */
 
 static void
-do_SUBST(into, newval)
+do_SUBST (into, newval)
      rtx *into, newval;
 {
   struct undo *buf;
@@ -472,11 +444,11 @@ do_SUBST(into, newval)
    not safe.  */
 
 static void
-do_SUBST_INT(into, newval)
-     int *into, newval;
+do_SUBST_INT (into, newval)
+     unsigned int *into, newval;
 {
   struct undo *buf;
-  int oldval = *into;
+  unsigned int oldval = *into;
 
   if (oldval == newval)
     return;
@@ -497,7 +469,7 @@ do_SUBST_INT(into, newval)
 #define SUBST_INT(INTO, NEWVAL)  do_SUBST_INT(&(INTO), (NEWVAL))
 \f
 /* Main entry point for combiner.  F is the first insn of the function.
-   NREGS is the first unused pseudo-reg number. 
+   NREGS is the first unused pseudo-reg number.
 
    Return non-zero if the combiner has turned an indirect jump
    instruction into a direct jump.  */
@@ -522,7 +494,7 @@ combine_instructions (f, nregs)
 
   combine_max_regno = nregs;
 
-  reg_nonzero_bits = ((unsigned HOST_WIDE_INT *) 
+  reg_nonzero_bits = ((unsigned HOST_WIDE_INT *)
                      xcalloc (nregs, sizeof (unsigned HOST_WIDE_INT)));
   reg_sign_bit_copies
     = (unsigned char *) xcalloc (nregs, sizeof (unsigned char));
@@ -562,7 +534,7 @@ combine_instructions (f, nregs)
 
   /* Compute the mapping from uids to cuids.
      Cuids are numbers assigned to insns, like uids,
-     except that cuids increase monotonically through the code. 
+     except that cuids increase monotonically through the code.
 
      Scan all SETs and see if we can deduce anything about what
      bits are known to be zero for some registers and how many copies
@@ -589,9 +561,9 @@ combine_instructions (f, nregs)
       subst_low_cuid = i;
       subst_insn = insn;
 
-      if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
+      if (INSN_P (insn))
        {
-         note_stores (PATTERN (insn), set_nonzero_bits_and_sign_copies, 
+         note_stores (PATTERN (insn), set_nonzero_bits_and_sign_copies,
                       NULL);
          record_dead_and_set_regs (insn);
 
@@ -630,7 +602,7 @@ combine_instructions (f, nregs)
       if (GET_CODE (insn) == CODE_LABEL)
        label_tick++;
 
-      else if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
+      else if (INSN_P (insn))
        {
          /* See if we know about function return values before this
             insn based upon SUBREG flags.  */
@@ -639,7 +611,7 @@ combine_instructions (f, nregs)
          /* Try this insn with each insn it links back to.  */
 
          for (links = LOG_LINKS (insn); links; links = XEXP (links, 1))
-           if ((next = try_combine (insn, XEXP (links, 0), 
+           if ((next = try_combine (insn, XEXP (links, 0),
                                     NULL_RTX, &new_direct_jump_p)) != 0)
              goto retry;
 
@@ -676,7 +648,7 @@ combine_instructions (f, nregs)
              && GET_CODE (prev) == INSN
              && sets_cc0_p (PATTERN (prev)))
            {
-             if ((next = try_combine (insn, prev, 
+             if ((next = try_combine (insn, prev,
                                       NULL_RTX, &new_direct_jump_p)) != 0)
                goto retry;
 
@@ -696,7 +668,7 @@ combine_instructions (f, nregs)
              && GET_CODE (PATTERN (insn)) == SET
              && reg_mentioned_p (cc0_rtx, SET_SRC (PATTERN (insn))))
            {
-             if ((next = try_combine (insn, prev, 
+             if ((next = try_combine (insn, prev,
                                       NULL_RTX, &new_direct_jump_p)) != 0)
                goto retry;
 
@@ -718,7 +690,7 @@ combine_instructions (f, nregs)
                && (prev = prev_nonnote_insn (XEXP (links, 0))) != 0
                && GET_CODE (prev) == INSN
                && sets_cc0_p (PATTERN (prev))
-               && (next = try_combine (insn, XEXP (links, 0), 
+               && (next = try_combine (insn, XEXP (links, 0),
                                        prev, &new_direct_jump_p)) != 0)
              goto retry;
 #endif
@@ -741,11 +713,13 @@ combine_instructions (f, nregs)
        }
     }
 
+  delete_noop_moves (f);
+
   if (need_refresh)
     {
       compute_bb_for_insn (get_max_uid ());
       update_life_info (refresh_blocks, UPDATE_LIFE_GLOBAL_RM_NOTES,
-                       PROP_DEATH_NOTES);
+                       PROP_DEATH_NOTES);
     }
 
   /* Clean up.  */
@@ -793,15 +767,15 @@ init_reg_last_arrays ()
 {
   unsigned int nregs = combine_max_regno;
 
-  bzero ((char *) reg_last_death, nregs * sizeof (rtx));
-  bzero ((char *) reg_last_set, nregs * sizeof (rtx));
-  bzero ((char *) reg_last_set_value, nregs * sizeof (rtx));
-  bzero ((char *) reg_last_set_table_tick, nregs * sizeof (int));
-  bzero ((char *) reg_last_set_label, nregs * sizeof (int));
-  bzero (reg_last_set_invalid, nregs * sizeof (char));
-  bzero ((char *) reg_last_set_mode, nregs * sizeof (enum machine_mode));
-  bzero ((char *) reg_last_set_nonzero_bits, nregs * sizeof (HOST_WIDE_INT));
-  bzero (reg_last_set_sign_bit_copies, nregs * sizeof (char));
+  memset ((char *) reg_last_death, 0, nregs * sizeof (rtx));
+  memset ((char *) reg_last_set, 0, nregs * sizeof (rtx));
+  memset ((char *) reg_last_set_value, 0, nregs * sizeof (rtx));
+  memset ((char *) reg_last_set_table_tick, 0, nregs * sizeof (int));
+  memset ((char *) reg_last_set_label, 0, nregs * sizeof (int));
+  memset (reg_last_set_invalid, 0, nregs * sizeof (char));
+  memset ((char *) reg_last_set_mode, 0, nregs * sizeof (enum machine_mode));
+  memset ((char *) reg_last_set_nonzero_bits, 0, nregs * sizeof (HOST_WIDE_INT));
+  memset (reg_last_set_sign_bit_copies, 0, nregs * sizeof (char));
 }
 \f
 /* Set up any promoted values for incoming argument registers.  */
@@ -843,7 +817,7 @@ setup_incoming_promotions ()
    be happening.
 
    Similarly, set how many bits of X are known to be copies of the sign bit
-   at all locations in the function.  This is the smallest number implied 
+   at all locations in the function.  This is the smallest number implied
    by any set of X.  */
 
 static void
@@ -888,7 +862,7 @@ set_nonzero_bits_and_sign_copies (x, set, data)
             constant that would appear negative in the mode of X,
             sign-extend it for use in reg_nonzero_bits because some
             machines (maybe most) will actually do the sign-extension
-            and this is the conservative approach. 
+            and this is the conservative approach.
 
             ??? For 2.5, try to tighten up the MD files in this regard
             instead of this kludge.  */
@@ -925,7 +899,7 @@ set_nonzero_bits_and_sign_copies (x, set, data)
 
    Return 0 if the combination is not allowed for any reason.
 
-   If the combination is allowed, *PDEST will be set to the single 
+   If the combination is allowed, *PDEST will be set to the single
    destination of INSN and *PSRC to the single source, and this function
    will return 1.  */
 
@@ -948,20 +922,20 @@ can_combine_p (insn, i3, pred, succ, pdest, psrc)
                      : next_active_insn (insn) == i3);
 
   /* Can combine only if previous insn is a SET of a REG, a SUBREG or CC0.
-     or a PARALLEL consisting of such a SET and CLOBBERs. 
+     or a PARALLEL consisting of such a SET and CLOBBERs.
 
      If INSN has CLOBBER parallel parts, ignore them for our processing.
      By definition, these happen during the execution of the insn.  When it
      is merged with another insn, all bets are off.  If they are, in fact,
      needed and aren't also supplied in I3, they may be added by
-     recog_for_combine.  Otherwise, it won't match. 
+     recog_for_combine.  Otherwise, it won't match.
 
      We can also ignore a SET whose SET_DEST is mentioned in a REG_UNUSED
      note.
 
-     Get the source and destination of INSN.  If more than one, can't 
+     Get the source and destination of INSN.  If more than one, can't
      combine.  */
-     
+
   if (GET_CODE (PATTERN (insn)) == SET)
     set = PATTERN (insn);
   else if (GET_CODE (PATTERN (insn)) == PARALLEL
@@ -1059,6 +1033,8 @@ can_combine_p (insn, i3, pred, succ, pdest, psrc)
       /* Don't combine with an insn that sets a register to itself if it has
         a REG_EQUAL note.  This may be part of a REG_NO_CONFLICT sequence.  */
       || (rtx_equal_p (src, dest) && find_reg_note (insn, REG_EQUAL, NULL_RTX))
+      /* Can't merge an ASM_OPERANDS.  */
+      || GET_CODE (src) == ASM_OPERANDS
       /* Can't merge a function call.  */
       || GET_CODE (src) == CALL
       /* Don't eliminate a function call argument.  */
@@ -1118,12 +1094,7 @@ can_combine_p (insn, i3, pred, succ, pdest, psrc)
         insns.  Eliminate this problem by not combining with such an insn.
 
         Also, on some machines we don't want to extend the life of a hard
-        register.
-
-        This is the same test done in can_combine except that we don't test
-        if SRC is a CALL operation to permit a hard register with
-        SMALL_REGISTER_CLASSES, and that we have to take all_adjacent
-        into account.  */
+        register.  */
 
       if (GET_CODE (src) == REG
          && ((REGNO (dest) < FIRST_PSEUDO_REGISTER
@@ -1136,11 +1107,7 @@ can_combine_p (insn, i3, pred, succ, pdest, psrc)
                 reload can't handle a conflict with constraints of other
                 inputs.  */
              || (REGNO (src) < FIRST_PSEUDO_REGISTER
-                 && (! HARD_REGNO_MODE_OK (REGNO (src), GET_MODE (src))
-                     || (SMALL_REGISTER_CLASSES
-                         && ((! all_adjacent && ! REG_USERVAR_P (src))
-                             || (FUNCTION_VALUE_REGNO_P (REGNO (src))
-                                 && ! REG_USERVAR_P (src))))))))
+                 && ! HARD_REGNO_MODE_OK (REGNO (src), GET_MODE (src)))))
        return 0;
     }
   else if (GET_CODE (dest) != CC0)
@@ -1165,11 +1132,10 @@ can_combine_p (insn, i3, pred, succ, pdest, psrc)
       /* 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_P (p) && p != succ && volatile_refs_p (PATTERN (p)))
+       return 0;
     }
 
   /* If INSN is an asm, and DEST is a hard register, reject, since it has
@@ -1183,8 +1149,7 @@ can_combine_p (insn, i3, pred, succ, pdest, psrc)
      they might affect machine state.  */
 
   for (p = NEXT_INSN (insn); p != i3; p = NEXT_INSN (p))
-    if (GET_RTX_CLASS (GET_CODE (p)) == 'i'
-       && p != succ && volatile_insn_p (PATTERN (p)))
+    if (INSN_P (p) && p != succ && volatile_insn_p (PATTERN (p)))
       return 0;
 
   /* If INSN or I2 contains an autoincrement or autodecrement,
@@ -1282,10 +1247,10 @@ sets_function_arg_p (pat)
    This is NOT equivalent to:
 
          (parallel [(set (subreg:SI (reg:DI 100) 0) <foo>)
-                   (set (reg:DI 101) (reg:DI 100))])
+                   (set (reg:DI 101) (reg:DI 100))])
 
    Not only does this modify 100 (in which case it might still be valid
-   if 100 were dead in I2), it sets 101 to the ORIGINAL value of 100. 
+   if 100 were dead in I2), it sets 101 to the ORIGINAL value of 100.
 
    We can also run into a problem if I2 sets a register that I1
    uses and I1 gets directly substituted into I3 (not via I2).  In that
@@ -1295,10 +1260,6 @@ sets_function_arg_p (pat)
    If I1_NOT_IN_SRC is non-zero, it means that finding I1 in the source
    of a SET must prevent combination from occurring.
 
-   On machines where SMALL_REGISTER_CLASSES is non-zero, we don't combine
-   if the destination of a SET is a hard register that isn't a user
-   variable.
-
    Before doing the above check, we first try to expand a field assignment
    into a set of logical operations.
 
@@ -1325,7 +1286,7 @@ combinable_i3pat (i3, loc, i2dest, i1dest, i1_not_in_src, pi3dest_killed)
       rtx dest = SET_DEST (set);
       rtx src = SET_SRC (set);
       rtx inner_dest = dest;
+
 #if 0
       rtx inner_src = src;
 #endif
@@ -1367,32 +1328,25 @@ combinable_i3pat (i3, loc, i2dest, i1dest, i1_not_in_src, pi3dest_killed)
           && (reg_overlap_mentioned_p (i2dest, inner_dest)
               || (i1dest && reg_overlap_mentioned_p (i1dest, inner_dest))))
 
-         /* This is the same test done in can_combine_p except that we
-            allow a hard register with SMALL_REGISTER_CLASSES if SRC is a
-            CALL operation. Moreover, we can't test all_adjacent; we don't
-            have to, since this instruction will stay in place, thus we are
-            not considering increasing the lifetime of INNER_DEST.
+         /* This is the same test done in can_combine_p except we can't test
+            all_adjacent; we don't have to, since this instruction will stay
+            in place, thus we are not considering increasing the lifetime of
+            INNER_DEST.
 
             Also, if this insn sets a function argument, combining it with
             something that might need a spill could clobber a previous
             function argument; the all_adjacent test in can_combine_p also
             checks this; here, we do a more specific test for this case.  */
-            
+
          || (GET_CODE (inner_dest) == REG
              && REGNO (inner_dest) < FIRST_PSEUDO_REGISTER
              && (! HARD_REGNO_MODE_OK (REGNO (inner_dest),
-                                       GET_MODE (inner_dest))
-                || (SMALL_REGISTER_CLASSES && GET_CODE (src) != CALL
-                    && ! REG_USERVAR_P (inner_dest)
-                    && (FUNCTION_VALUE_REGNO_P (REGNO (inner_dest))
-                        || (FUNCTION_ARG_REGNO_P (REGNO (inner_dest))
-                            && i3 != 0
-                            && sets_function_arg_p (prev_nonnote_insn (i3)))))))
+                                       GET_MODE (inner_dest))))
          || (i1_not_in_src && reg_overlap_mentioned_p (i1dest, src)))
        return 0;
 
       /* If DEST is used in I3, it is being killed in this insn,
-        so record that for later. 
+        so record that for later.
         Never add REG_DEAD notes for the FRAME_POINTER_REGNUM or the
         STACK_POINTER_REGNUM, since these are always considered to be
         live.  Similarly for ARG_POINTER_REGNUM if it is fixed.  */
@@ -1459,19 +1413,62 @@ contains_muldiv (x)
     }
 }
 \f
+/* Determine whether INSN can be used in a combination.  Return nonzero if
+   not.  This is used in try_combine to detect early some cases where we
+   can't perform combinations.  */
+
+static int
+cant_combine_insn_p (insn)
+     rtx insn;
+{
+  rtx set;
+  rtx src, dest;
+
+  /* If this isn't really an insn, we can't do anything.
+     This can occur when flow deletes an insn that it has merged into an
+     auto-increment address.  */
+  if (! INSN_P (insn))
+    return 1;
+
+  /* Never combine loads and stores involving hard regs.  The register
+     allocator can usually handle such reg-reg moves by tying.  If we allow
+     the combiner to make substitutions of hard regs, we risk aborting in
+     reload on machines that have SMALL_REGISTER_CLASSES.
+     As an exception, we allow combinations involving fixed regs; these are
+     not available to the register allocator so there's no risk involved.  */
+
+  set = single_set (insn);
+  if (! set)
+    return 0;
+  src = SET_SRC (set);
+  dest = SET_DEST (set);
+  if (GET_CODE (src) == SUBREG)
+    src = SUBREG_REG (src);
+  if (GET_CODE (dest) == SUBREG)
+    dest = SUBREG_REG (dest);
+  if (REG_P (src) && REG_P (dest)
+      && ((REGNO (src) < FIRST_PSEUDO_REGISTER
+          && ! fixed_regs[REGNO (src)])
+         || (REGNO (dest) < FIRST_PSEUDO_REGISTER
+             && ! fixed_regs[REGNO (dest)])))
+    return 1;
+
+  return 0;
+}
+
 /* Try to combine the insns I1 and I2 into I3.
    Here I1 and I2 appear earlier than I3.
    I1 can be zero; then we combine just I2 into I3.
-   It we are combining three insns and the resulting insn is not recognized,
+
+   If we are combining three insns and the resulting insn is not recognized,
    try splitting it into two insns.  If that happens, I2 and I3 are retained
    and I1 is pseudo-deleted by turning it into a NOTE.  Otherwise, I1 and I2
    are pseudo-deleted.
 
-   Return 0 if the combination does not work.  Then nothing is changed. 
+   Return 0 if the combination does not work.  Then nothing is changed.
    If we did the combination, return the insn at which combine should
-   resume scanning.  
-   
+   resume scanning.
+
    Set NEW_DIRECT_JUMP_P to a non-zero value if try_combine creates a
    new direct jump instruction.  */
 
@@ -1513,30 +1510,25 @@ try_combine (i3, i2, i1, new_direct_jump_p)
   register rtx link;
   int i;
 
-  /* If any of I1, I2, and I3 isn't really an insn, we can't do anything.
-     This can occur when flow deletes an insn that it has merged into an
-     auto-increment address.  We also can't do anything if I3 has a
-     REG_LIBCALL note since we don't want to disrupt the contiguity of a
-     libcall.  */
-
-  if (GET_RTX_CLASS (GET_CODE (i3)) != 'i'
-      || GET_RTX_CLASS (GET_CODE (i2)) != 'i'
-      || (i1 && GET_RTX_CLASS (GET_CODE (i1)) != 'i')
+  /* Exit early if one of the insns involved can't be used for
+     combinations.  */
+  if (cant_combine_insn_p (i3)
+      || cant_combine_insn_p (i2)
+      || (i1 && cant_combine_insn_p (i1))
+      /* We also can't do anything if I3 has a
+        REG_LIBCALL note since we don't want to disrupt the contiguity of a
+        libcall.  */
 #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++;
   undobuf.other_insn = 0;
 
-  /* Save the current high-water-mark so we can free storage if we didn't
-     accept this combination.  */
-  undobuf.storage = (char *) oballoc (0);
-
   /* Reset the hard register usage information.  */
   CLEAR_HARD_REG_SET (newpat_used_regs);
 
@@ -1548,13 +1540,16 @@ try_combine (i3, i2, i1, new_direct_jump_p)
   added_links_insn = 0;
 
   /* First check for one important special-case that the code below will
-     not handle.  Namely, the case where I1 is zero, I2 has multiple sets,
+     not handle.  Namely, the case where I1 is zero, I2 is a PARALLEL
      and I3 is a SET whose SET_SRC is a SET_DEST in I2.  In that case,
      we may be able to replace that destination with the destination of I3.
      This occurs in the common code where we compute both a quotient and
      remainder into a structure, in which case we want to do the computation
      directly into the structure to avoid register-register copies.
 
+     Note that this case handles both multiple sets in I2 and also
+     cases where I2 has a number of CLOBBER or PARALLELs.
+
      We make very conservative checks below and only try to handle the
      most common cases of this.  For example, we only handle the case
      where I2 and I3 are adjacent to avoid making difficult register
@@ -1563,10 +1558,6 @@ try_combine (i3, i2, i1, new_direct_jump_p)
   if (i1 == 0 && GET_CODE (i3) == INSN && GET_CODE (PATTERN (i3)) == SET
       && GET_CODE (SET_SRC (PATTERN (i3))) == REG
       && REGNO (SET_SRC (PATTERN (i3))) >= FIRST_PSEUDO_REGISTER
-      && (! SMALL_REGISTER_CLASSES
-         || (GET_CODE (SET_DEST (PATTERN (i3))) != REG
-             || REGNO (SET_DEST (PATTERN (i3))) >= FIRST_PSEUDO_REGISTER
-             || REG_USERVAR_P (SET_DEST (PATTERN (i3)))))
       && find_reg_note (i3, REG_DEAD, SET_SRC (PATTERN (i3)))
       && GET_CODE (PATTERN (i2)) == PARALLEL
       && ! side_effects_p (SET_DEST (PATTERN (i3)))
@@ -1616,7 +1607,7 @@ try_combine (i3, i2, i1, new_direct_jump_p)
              /* Replace the dest in I2 with our dest and make the resulting
                 insn the new pattern for I3.  Then skip to where we
                 validate the pattern.  Everything was set up above.  */
-             SUBST (SET_DEST (XVECEXP (p2, 0, i)), 
+             SUBST (SET_DEST (XVECEXP (p2, 0, i)),
                     SET_DEST (PATTERN (i3)));
 
              newpat = p2;
@@ -1653,9 +1644,33 @@ try_combine (i3, i2, i1, new_direct_jump_p)
        }
 
       if (subreg_lowpart_p (SET_DEST (PATTERN (i3))))
-       lo = INTVAL (SET_SRC (PATTERN (i3)));
-      else
+       {
+         /* We don't handle the case of the target word being wider
+            than a host wide int.  */
+         if (HOST_BITS_PER_WIDE_INT < BITS_PER_WORD)
+           abort ();
+
+         lo &= ~(UWIDE_SHIFT_LEFT_BY_BITS_PER_WORD (1) - 1);
+         lo |= INTVAL (SET_SRC (PATTERN (i3)));
+       }
+      else if (HOST_BITS_PER_WIDE_INT == BITS_PER_WORD)
        hi = INTVAL (SET_SRC (PATTERN (i3)));
+      else if (HOST_BITS_PER_WIDE_INT >= 2 * BITS_PER_WORD)
+       {
+         int sign = -(int) ((unsigned HOST_WIDE_INT) lo
+                            >> (HOST_BITS_PER_WIDE_INT - 1));
+
+         lo &= ~ (UWIDE_SHIFT_LEFT_BY_BITS_PER_WORD
+                  (UWIDE_SHIFT_LEFT_BY_BITS_PER_WORD (1) - 1));
+         lo |= (UWIDE_SHIFT_LEFT_BY_BITS_PER_WORD
+                (INTVAL (SET_SRC (PATTERN (i3)))));
+         if (hi == sign)
+           hi = lo < 0 ? -1 : 0;
+       }
+      else
+       /* We don't handle the case of the higher word not fitting
+          entirely in either hi or lo.  */
+       abort ();
 
       combine_merges++;
       subst_insn = i3;
@@ -1667,7 +1682,6 @@ try_combine (i3, i2, i1, new_direct_jump_p)
             immed_double_const (lo, hi, GET_MODE (SET_DEST (temp))));
 
       newpat = PATTERN (i2);
-      i3_subst_into_i2 = 1;
       goto validate_replacement;
     }
 
@@ -1697,7 +1711,7 @@ try_combine (i3, i2, i1, new_direct_jump_p)
       && rtx_equal_p (XEXP (SET_SRC (XVECEXP (PATTERN (i2), 0, 0)), 0),
                      SET_SRC (XVECEXP (PATTERN (i2), 0, 1))))
     {
-      for (i =  XVECLEN (PATTERN (i2), 0) - 1; i >= 2; i--)
+      for (i = XVECLEN (PATTERN (i2), 0) - 1; i >= 2; i--)
        if (GET_CODE (XVECEXP (PATTERN (i2), 0, i)) != CLOBBER)
          break;
 
@@ -1759,7 +1773,7 @@ try_combine (i3, i2, i1, new_direct_jump_p)
   /* If I3 has an inc, then give up if I1 or I2 uses the reg that is inc'd.
      We used to do this EXCEPT in one case: I3 has a post-inc in an
      output operand.  However, that exception can give rise to insns like
-       mov r3,(r3)+
+       mov r3,(r3)+
      which is a famous insn on the PDP-11 where the value of r3 used as the
      source was model-dependent.  Avoid this sort of thing.  */
 
@@ -1851,8 +1865,6 @@ try_combine (i3, i2, i1, new_direct_jump_p)
          subst_low_cuid = INSN_CUID (i2);
          i2src = subst (i2src, pc_rtx, pc_rtx, 0, 0);
        }
-
-      undobuf.previous_undos = undobuf.undos;
     }
 
 #ifndef HAVE_cc0
@@ -1908,13 +1920,12 @@ try_combine (i3, i2, i1, new_direct_jump_p)
              SUBST (SET_DEST (newpat), new_dest);
              SUBST (XEXP (*cc_use, 0), new_dest);
              SUBST (SET_SRC (newpat),
-                    gen_rtx_combine (COMPARE, compare_mode,
-                                     i2src, const0_rtx));
+                    gen_rtx_COMPARE (compare_mode, i2src, const0_rtx));
            }
          else
            undobuf.other_insn = 0;
        }
-#endif   
+#endif
     }
   else
 #endif
@@ -1928,7 +1939,6 @@ try_combine (i3, i2, i1, new_direct_jump_p)
       subst_low_cuid = INSN_CUID (i2);
       newpat = subst (PATTERN (i3), i2dest, i2src, 0,
                      ! i1_feeds_i3 && i1dest_in_i1src);
-      undobuf.previous_undos = undobuf.undos;
 
       /* Record whether i2's body now appears within i3's body.  */
       i2_is_used = n_occurrences;
@@ -1944,7 +1954,7 @@ try_combine (i3, i2, i1, new_direct_jump_p)
         isn't mentioned in any SETs in NEWPAT that are field assignments.  */
 
       if (! combinable_i3pat (NULL_RTX, &newpat, i1dest, NULL_RTX,
-                             0, NULL_PTR))
+                             0, (rtx*)0))
        {
          undo_all ();
          return 0;
@@ -1953,7 +1963,6 @@ try_combine (i3, i2, i1, new_direct_jump_p)
       n_occurrences = 0;
       subst_low_cuid = INSN_CUID (i1);
       newpat = subst (newpat, i1dest, i1src, 0, 0);
-      undobuf.previous_undos = undobuf.undos;
     }
 
   /* Fail if an autoincrement side-effect has been duplicated.  Be careful
@@ -1991,8 +2000,8 @@ try_combine (i3, i2, i1, new_direct_jump_p)
          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));
-         bcopy ((char *) &old->elem[0], (char *) XVEC (newpat, 0)->elem,
-                sizeof (old->elem[0]) * old->num_elem);
+         memcpy (XVEC (newpat, 0)->elem, &old->elem[0],
+                 sizeof (old->elem[0]) * old->num_elem);
        }
       else
        {
@@ -2068,7 +2077,7 @@ try_combine (i3, i2, i1, new_direct_jump_p)
 
   /* If we were combining three insns and the result is a simple SET
      with no ASM_OPERANDS that wasn't recognized, try to split it into two
-     insns.  There are two ways to do this.  It can be split using a 
+     insns.  There are two ways to do this.  It can be split using a
      machine-specific method (like when you have an addition of a large
      constant) or by combine in the function find_split_point.  */
 
@@ -2110,13 +2119,31 @@ try_combine (i3, i2, i1, new_direct_jump_p)
                                             gen_rtx_CLOBBER (VOIDmode,
                                                              ni2dest))),
                                 i3);
+         /* If the split with the mode-changed register didn't work, try
+            the original register.  */
+         if (! m_split && ni2dest != i2dest)
+           {
+             ni2dest = i2dest;
+             m_split = split_insns (gen_rtx_PARALLEL
+                                    (VOIDmode,
+                                     gen_rtvec (2, newpat,
+                                                gen_rtx_CLOBBER (VOIDmode,
+                                                                 i2dest))),
+                                    i3);
+           }
        }
 
-      if (m_split && GET_CODE (m_split) == SEQUENCE
-         && XVECLEN (m_split, 0) == 2
-         && (next_real_insn (i2) == i3
-             || ! use_crosses_set_p (PATTERN (XVECEXP (m_split, 0, 0)),
-                                     INSN_CUID (i2))))
+      if (m_split && GET_CODE (m_split) != SEQUENCE)
+       {
+         insn_code_number = recog_for_combine (&m_split, i3, &new_i3_notes);
+         if (insn_code_number >= 0)
+           newpat = m_split;
+       }
+      else if (m_split && GET_CODE (m_split) == SEQUENCE
+              && XVECLEN (m_split, 0) == 2
+              && (next_real_insn (i2) == i3
+                  || ! use_crosses_set_p (PATTERN (XVECEXP (m_split, 0, 0)),
+                                          INSN_CUID (i2))))
        {
          rtx i2set, i3set;
          rtx newi3pat = PATTERN (XVECEXP (m_split, 0, 1));
@@ -2210,10 +2237,11 @@ try_combine (i3, i2, i1, new_direct_jump_p)
             appeared to be a memory address.  This is a kludge.  */
          if (split_code == MULT
              && GET_CODE (XEXP (*split, 1)) == CONST_INT
+             && INTVAL (XEXP (*split, 1)) > 0
              && (i = exact_log2 (INTVAL (XEXP (*split, 1)))) >= 0)
            {
-             SUBST (*split, gen_rtx_combine (ASHIFT, split_mode,
-                                             XEXP (*split, 0), GEN_INT (i)));
+             SUBST (*split, gen_rtx_ASHIFT (split_mode,
+                                            XEXP (*split, 0), GEN_INT (i)));
              /* Update split_code because we may not have a multiply
                 anymore.  */
              split_code = GET_CODE (*split);
@@ -2223,11 +2251,11 @@ try_combine (i3, i2, i1, new_direct_jump_p)
          /* If *SPLIT is a paradoxical SUBREG, when we split it, it should
             be written as a ZERO_EXTEND.  */
          if (split_code == SUBREG && GET_CODE (SUBREG_REG (*split)) == MEM)
-           SUBST (*split, gen_rtx_combine (ZERO_EXTEND, split_mode,
-                                           XEXP (*split, 0)));
+           SUBST (*split, gen_rtx_ZERO_EXTEND  (split_mode,
+                                                SUBREG_REG (*split)));
 #endif
 
-         newi2pat = gen_rtx_combine (SET, VOIDmode, newdest, *split);
+         newi2pat = gen_rtx_SET (VOIDmode, newdest, *split);
          SUBST (*split, newdest);
          i2_code_number = recog_for_combine (&newi2pat, i2, &new_i2_notes);
 
@@ -2324,8 +2352,7 @@ try_combine (i3, i2, i1, new_direct_jump_p)
                        || insn != BLOCK_HEAD (this_basic_block + 1));
               insn = NEXT_INSN (insn))
            {
-             if (GET_RTX_CLASS (GET_CODE (insn)) == 'i'
-                 && reg_referenced_p (ni2dest, PATTERN (insn)))
+             if (INSN_P (insn) && reg_referenced_p (ni2dest, PATTERN (insn)))
                {
                  for (link = LOG_LINKS (insn); link;
                       link = XEXP (link, 1))
@@ -2337,7 +2364,7 @@ try_combine (i3, i2, i1, new_direct_jump_p)
            }
        }
     }
-           
+
   /* Similarly, check for a case where we have a PARALLEL of two independent
      SETs but we started with three insns.  In this case, we can do the sets
      as two separate insns.  This case occurs when some SET allows two
@@ -2441,19 +2468,20 @@ try_combine (i3, i2, i1, new_direct_jump_p)
                        undobuf.other_insn, NULL_RTX, NULL_RTX, NULL_RTX);
     }
 #ifdef HAVE_cc0
-  /* If I2 is the setter CC0 and I3 is the user CC0 then check whether 
-     they are adjacent to each other or not. */
+  /* If I2 is the setter CC0 and I3 is the user CC0 then check whether
+     they are adjacent to each other or not.  */
   {
     rtx p = prev_nonnote_insn (i3);
-    if (p && p != i2 && GET_CODE (p) == INSN && newi2pat && sets_cc0_p (newi2pat))
+    if (p && p != i2 && GET_CODE (p) == INSN && newi2pat
+       && sets_cc0_p (newi2pat))
       {
-        undo_all ();
-        return 0;
+       undo_all ();
+       return 0;
       }
-    }
-#endif 
+  }
+#endif
 
-  /* We now know that we can do this combination.  Merge the insns and 
+  /* We now know that we can do this combination.  Merge the insns and
      update the status of registers and LOG_LINKS.  */
 
   {
@@ -2512,24 +2540,22 @@ try_combine (i3, i2, i1, new_direct_jump_p)
        actually came from I3, so that REG_UNUSED notes from I2 will be
        properly handled.  */
 
-    if (i3_subst_into_i2 && GET_CODE (PATTERN (i2)) == PARALLEL)
+    if (i3_subst_into_i2)
       {
-       if (GET_CODE (PATTERN (i2)) == PARALLEL)
-         {
-           for (i = 0; i < XVECLEN (PATTERN (i2), 0); i++)
-             if (GET_CODE (SET_DEST (XVECEXP (PATTERN (i2), 0, i))) == REG
-                 && SET_DEST (XVECEXP (PATTERN (i2), 0, i)) != i2dest
-                 && ! find_reg_note (i2, REG_UNUSED,
-                                     SET_DEST (XVECEXP (PATTERN (i2), 0, i))))
-               for (temp = NEXT_INSN (i2);
-                    temp && (this_basic_block == n_basic_blocks - 1
-                             || BLOCK_HEAD (this_basic_block) != temp);
-                    temp = NEXT_INSN (temp))
-                 if (temp != i3 && GET_RTX_CLASS (GET_CODE (temp)) == 'i')
-                   for (link = LOG_LINKS (temp); link; link = XEXP (link, 1))
-                     if (XEXP (link, 0) == i2)
-                       XEXP (link, 0) = i3;
-         }
+       for (i = 0; i < XVECLEN (PATTERN (i2), 0); i++)
+         if (GET_CODE (XVECEXP (PATTERN (i2), 0, i)) != USE
+             && GET_CODE (SET_DEST (XVECEXP (PATTERN (i2), 0, i))) == REG
+             && SET_DEST (XVECEXP (PATTERN (i2), 0, i)) != i2dest
+             && ! find_reg_note (i2, REG_UNUSED,
+                                 SET_DEST (XVECEXP (PATTERN (i2), 0, i))))
+           for (temp = NEXT_INSN (i2);
+                temp && (this_basic_block == n_basic_blocks - 1
+                         || BLOCK_HEAD (this_basic_block) != temp);
+                temp = NEXT_INSN (temp))
+             if (temp != i3 && INSN_P (temp))
+               for (link = LOG_LINKS (temp); link; link = XEXP (link, 1))
+                 if (XEXP (link, 0) == i2)
+                   XEXP (link, 0) = i3;
 
        if (i3notes)
          {
@@ -2570,7 +2596,7 @@ try_combine (i3, i2, i1, new_direct_jump_p)
       }
 
     /* Get death notes for everything that is now used in either I3 or
-       I2 and used to die in a previous insn.  If we built two new 
+       I2 and used to die in a previous insn.  If we built two new
        patterns, move from I1 to I2 then I2 to I3 so that we get the
        proper movement on registers that I2 modifies.  */
 
@@ -2599,7 +2625,7 @@ try_combine (i3, i2, i1, new_direct_jump_p)
 
     /* Distribute any notes added to I2 or I3 by recog_for_combine.  We
        know these are REG_UNUSED and want them to go to the desired insn,
-       so we always pass it as i3.  We have not counted the notes in 
+       so we always pass it as i3.  We have not counted the notes in
        reg_n_deaths yet, so we need to do so now.  */
 
     if (newi2pat && new_i2_notes)
@@ -2607,7 +2633,7 @@ try_combine (i3, i2, i1, new_direct_jump_p)
        for (temp = new_i2_notes; temp; temp = XEXP (temp, 1))
          if (GET_CODE (XEXP (temp, 0)) == REG)
            REG_N_DEATHS (REGNO (XEXP (temp, 0)))++;
-       
+
        distribute_notes (new_i2_notes, i2, i2, NULL_RTX, NULL_RTX, NULL_RTX);
       }
 
@@ -2616,7 +2642,7 @@ try_combine (i3, i2, i1, new_direct_jump_p)
        for (temp = new_i3_notes; temp; temp = XEXP (temp, 1))
          if (GET_CODE (XEXP (temp, 0)) == REG)
            REG_N_DEATHS (REGNO (XEXP (temp, 0)))++;
-       
+
        distribute_notes (new_i3_notes, i3, i3, NULL_RTX, NULL_RTX, NULL_RTX);
       }
 
@@ -2682,7 +2708,7 @@ try_combine (i3, i2, i1, new_direct_jump_p)
 
        /* The insn that used to set this register doesn't exist, and
           this life of the register may not exist either.  See if one of
-          I3's links points to an insn that sets I2DEST.  If it does, 
+          I3's links points to an insn that sets I2DEST.  If it does,
           that is now the last known value for I2DEST. If we don't update
           this and I2 set the register to a value that depended on its old
           contents, we will get confused.  If this insn is used, thing
@@ -2724,7 +2750,7 @@ try_combine (i3, i2, i1, new_direct_jump_p)
       }
 
     /* Update reg_nonzero_bits et al for any changes that may have been made
-       to this insn.  The order of set_nonzero_bits_and_sign_copies() is 
+       to this insn.  The order of set_nonzero_bits_and_sign_copies() is
        important.  Because newi2pat can affect nonzero_bits of newpat */
     if (newi2pat)
       note_stores (newi2pat, set_nonzero_bits_and_sign_copies, NULL);
@@ -2733,10 +2759,10 @@ try_combine (i3, i2, i1, new_direct_jump_p)
     /* Set new_direct_jump_p if a new return or simple jump instruction
        has been created.
 
-       If I3 is now an unconditional jump, ensure that it has a 
+       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.  */
-    
+
     if (GET_CODE (newpat) == RETURN || any_uncondjump_p (i3))
       {
        *new_direct_jump_p = 1;
@@ -2745,6 +2771,12 @@ try_combine (i3, i2, i1, new_direct_jump_p)
            || GET_CODE (temp) != BARRIER)
          emit_barrier_after (i3);
       }
+    /* An NOOP jump does not need barrier, but it does need cleaning up
+       of CFG.  */
+    if (GET_CODE (newpat) == SET
+       && SET_SRC (newpat) == pc_rtx
+       && SET_DEST (newpat) == pc_rtx)
+      *new_direct_jump_p = 1;
   }
 
   combine_successes++;
@@ -2781,8 +2813,7 @@ undo_all ()
       undobuf.frees = undo;
     }
 
-  obfree (undobuf.storage);
-  undobuf.undos = undobuf.previous_undos = 0;
+  undobuf.undos = 0;
 
   /* Clear this here, so that subsequent get_last_value calls are not
      affected.  */
@@ -2803,7 +2834,7 @@ undo_commit ()
       undo->next = undobuf.frees;
       undobuf.frees = undo;
     }
-  undobuf.undos = undobuf.previous_undos = 0;
+  undobuf.undos = 0;
 }
 
 \f
@@ -2847,9 +2878,9 @@ find_split_point (loc, insn)
          || GET_CODE (XEXP (x, 0)) == SYMBOL_REF)
        {
          SUBST (XEXP (x, 0),
-                gen_rtx_combine (LO_SUM, Pmode,
-                                 gen_rtx_combine (HIGH, Pmode, XEXP (x, 0)),
-                                 XEXP (x, 0)));
+                gen_rtx_LO_SUM (Pmode,
+                                gen_rtx_HIGH (Pmode, XEXP (x, 0)),
+                                XEXP (x, 0)));
          return &XEXP (XEXP (x, 0), 0);
        }
 #endif
@@ -2906,7 +2937,7 @@ find_split_point (loc, insn)
                  return split;
                }
            }
-         
+
          /* If that didn't work, perhaps the first operand is complex and
             needs to be computed separately, so make a split point there.
             This will occur on machines that just support REG + CONST
@@ -2975,8 +3006,8 @@ find_split_point (loc, insn)
          else
            SUBST (SET_SRC (x),
                   gen_binary (IOR, mode,
-                              gen_binary (AND, mode, dest, 
-                                          GEN_INT (~ (mask << pos)
+                              gen_binary (AND, mode, dest,
+                                          GEN_INT (~(mask << pos)
                                                    & GET_MODE_MASK (mode))),
                               GEN_INT (src << pos)));
 
@@ -3007,7 +3038,7 @@ find_split_point (loc, insn)
              && GET_CODE (XEXP (SET_SRC (x), 0)) == REG
              && (pos = exact_log2 (INTVAL (XEXP (SET_SRC (x), 1)))) >= 7
              && GET_CODE (SET_DEST (x)) == REG
-             && (split = find_single_use (SET_DEST (x), insn, NULL_PTR)) != 0
+             && (split = find_single_use (SET_DEST (x), insn, (rtx*)0)) != 0
              && (GET_CODE (*split) == EQ || GET_CODE (*split) == NE)
              && XEXP (*split, 0) == SET_DEST (x)
              && XEXP (*split, 1) == const0_rtx)
@@ -3025,7 +3056,7 @@ find_split_point (loc, insn)
 
        case NE:
          /* if STORE_FLAG_VALUE is -1, this is (NE X 0) and only one bit of X
-            is known to be on, this can be converted into a NEG of a shift. */
+            is known to be on, this can be converted into a NEG of a shift.  */
          if (STORE_FLAG_VALUE == -1 && XEXP (SET_SRC (x), 1) == const0_rtx
              && GET_MODE (SET_SRC (x)) == GET_MODE (XEXP (SET_SRC (x), 0))
              && 1 <= (pos = exact_log2
@@ -3035,10 +3066,10 @@ find_split_point (loc, insn)
              enum machine_mode mode = GET_MODE (XEXP (SET_SRC (x), 0));
 
              SUBST (SET_SRC (x),
-                    gen_rtx_combine (NEG, mode,
-                                     gen_rtx_combine (LSHIFTRT, mode,
-                                                      XEXP (SET_SRC (x), 0),
-                                                      GEN_INT (pos))));
+                    gen_rtx_NEG (mode,
+                                 gen_rtx_LSHIFTRT (mode,
+                                                   XEXP (SET_SRC (x), 0),
+                                                   GEN_INT (pos))));
 
              split = find_split_point (&SET_SRC (x), insn);
              if (split && split != &SET_SRC (x))
@@ -3093,12 +3124,11 @@ find_split_point (loc, insn)
          if (unsignedp && len <= 8)
            {
              SUBST (SET_SRC (x),
-                    gen_rtx_combine
-                    (AND, mode,
-                     gen_rtx_combine (LSHIFTRT, mode,
-                                      gen_lowpart_for_combine (mode, inner),
-                                      GEN_INT (pos)),
-                     GEN_INT (((HOST_WIDE_INT) 1 << len) - 1)));
+                    gen_rtx_AND (mode,
+                                 gen_rtx_LSHIFTRT
+                                 (mode, gen_lowpart_for_combine (mode, inner),
+                                  GEN_INT (pos)),
+                                 GEN_INT (((HOST_WIDE_INT) 1 << len) - 1)));
 
              split = find_split_point (&SET_SRC (x), insn);
              if (split && split != &SET_SRC (x))
@@ -3107,12 +3137,12 @@ find_split_point (loc, insn)
          else
            {
              SUBST (SET_SRC (x),
-                    gen_rtx_combine
+                    gen_rtx_fmt_ee
                     (unsignedp ? LSHIFTRT : ASHIFTRT, mode,
-                     gen_rtx_combine (ASHIFT, mode,
-                                      gen_lowpart_for_combine (mode, inner),
-                                      GEN_INT (GET_MODE_BITSIZE (mode)
-                                               - len - pos)),
+                     gen_rtx_ASHIFT (mode,
+                                     gen_lowpart_for_combine (mode, inner),
+                                     GEN_INT (GET_MODE_BITSIZE (mode)
+                                              - len - pos)),
                      GEN_INT (GET_MODE_BITSIZE (mode) - len)));
 
              split = find_split_point (&SET_SRC (x), insn);
@@ -3156,11 +3186,11 @@ find_split_point (loc, insn)
       if (GET_CODE (XEXP (x, 0)) == NOT && GET_CODE (XEXP (x, 1)) == NOT)
        {
          SUBST (*loc,
-                gen_rtx_combine (NOT, GET_MODE (x),
-                                 gen_rtx_combine (code == IOR ? AND : IOR,
-                                                  GET_MODE (x),
-                                                  XEXP (XEXP (x, 0), 0),
-                                                  XEXP (XEXP (x, 1), 0))));
+                gen_rtx_NOT (GET_MODE (x),
+                             gen_rtx_fmt_ee (code == IOR ? AND : IOR,
+                                             GET_MODE (x),
+                                             XEXP (XEXP (x, 0), 0),
+                                             XEXP (XEXP (x, 1), 0))));
          return find_split_point (loc, insn);
        }
 
@@ -3224,7 +3254,7 @@ find_split_point (loc, insn)
    the caller can tell whether the result is valid.
 
    `n_occurrences' is incremented each time FROM is replaced.
-   
+
    IN_DEST is non-zero if we are processing the SET_DEST of a SET.
 
    UNIQUE_COPY is non-zero if each substitution must be unique.  We do this
@@ -3258,7 +3288,7 @@ subst (x, from, to, in_dest, unique_copy)
     }
 
   /* If X and FROM are the same register but different modes, they will
-     not have been seen as equal above.  However, flow.c will make a 
+     not have been seen as equal above.  However, flow.c will make a
      LOG_LINKS entry for that case.  If we do nothing, we will try to
      rerecognize our original insn and, when it succeeds, we will
      delete the feeding insn, which is incorrect.
@@ -3307,7 +3337,7 @@ subst (x, from, to, in_dest, unique_copy)
       for (i = XVECLEN (x, 0) - 1; i >= 1; i--)
        {
          rtx dest = SET_DEST (XVECEXP (x, 0, i));
-         
+
          if (GET_CODE (dest) != REG
              && GET_CODE (dest) != CC0
              && GET_CODE (dest) != PC)
@@ -3373,7 +3403,16 @@ subst (x, from, to, in_dest, unique_copy)
            }
          else if (fmt[i] == 'e')
            {
-             if (COMBINE_RTX_EQUAL_P (XEXP (x, i), from))
+             /* If this is a register being set, ignore it.  */
+             new = XEXP (x, i);
+             if (in_dest
+                 && (code == SUBREG || code == STRICT_LOW_PART
+                     || code == ZERO_EXTRACT)
+                 && i == 0
+                 && GET_CODE (new) == REG)
+               ;
+
+             else 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
@@ -3420,7 +3459,7 @@ subst (x, from, to, in_dest, unique_copy)
                   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, 
+                  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.  */
@@ -3487,17 +3526,13 @@ combine_simplify_rtx (x, op0_mode, last, in_dest)
   enum rtx_code code = GET_CODE (x);
   enum machine_mode mode = GET_MODE (x);
   rtx temp;
+  rtx reversed;
   int i;
 
   /* If this is a commutative operation, put a constant last and a complex
      expression first.  We don't need to do this for comparisons here.  */
   if (GET_RTX_CLASS (code) == 'c'
-      && ((CONSTANT_P (XEXP (x, 0)) && GET_CODE (XEXP (x, 1)) != CONST_INT)
-         || (GET_RTX_CLASS (GET_CODE (XEXP (x, 0))) == 'o'
-             && GET_RTX_CLASS (GET_CODE (XEXP (x, 1))) != 'o')
-         || (GET_CODE (XEXP (x, 0)) == SUBREG
-             && GET_RTX_CLASS (GET_CODE (SUBREG_REG (XEXP (x, 0)))) == 'o'
-             && GET_RTX_CLASS (GET_CODE (XEXP (x, 1))) != 'o')))
+      && swap_commutative_operands_p (XEXP (x, 0), XEXP (x, 1)))
     {
       temp = XEXP (x, 0);
       SUBST (XEXP (x, 0), XEXP (x, 1));
@@ -3545,7 +3580,7 @@ combine_simplify_rtx (x, op0_mode, last, in_dest)
       SUBST (XEXP (x, 0), gen_binary (PLUS, mode, new, temp));
     }
 
-  /* If this is a simple operation applied to an IF_THEN_ELSE, try 
+  /* If this is a simple operation applied to an IF_THEN_ELSE, try
      applying it to the arms of the IF_THEN_ELSE.  This often simplifies
      things.  Check for cases where both arms are testing the same
      condition.
@@ -3568,15 +3603,15 @@ combine_simplify_rtx (x, op0_mode, last, in_dest)
                     && (GET_RTX_CLASS (GET_CODE (SUBREG_REG (XEXP (x, 0))))
                         == 'o'))))))
     {
-      rtx cond, true, false;
+      rtx cond, true_rtx, false_rtx;
 
-      cond = if_then_else_cond (x, &true, &false);
+      cond = if_then_else_cond (x, &true_rtx, &false_rtx);
       if (cond != 0
          /* If everything is a comparison, what we have is highly unlikely
             to be simpler, so don't use it.  */
          && ! (GET_RTX_CLASS (code) == '<'
-               && (GET_RTX_CLASS (GET_CODE (true)) == '<'
-                   || GET_RTX_CLASS (GET_CODE (false)) == '<')))
+               && (GET_RTX_CLASS (GET_CODE (true_rtx)) == '<'
+                   || GET_RTX_CLASS (GET_CODE (false_rtx)) == '<')))
        {
          rtx cop1 = const0_rtx;
          enum rtx_code cond_code = simplify_comparison (NE, &cond, &cop1);
@@ -3584,45 +3619,50 @@ combine_simplify_rtx (x, op0_mode, last, in_dest)
          if (cond_code == NE && GET_RTX_CLASS (GET_CODE (cond)) == '<')
            return x;
 
-         /* Simplify the alternative arms; this may collapse the true and 
+         /* Simplify the alternative arms; this may collapse the true and
             false arms to store-flag values.  */
-         true = subst (true, pc_rtx, pc_rtx, 0, 0);
-         false = subst (false, pc_rtx, pc_rtx, 0, 0);
+         true_rtx = subst (true_rtx, pc_rtx, pc_rtx, 0, 0);
+         false_rtx = subst (false_rtx, pc_rtx, pc_rtx, 0, 0);
 
-         /* If true and false are not general_operands, an if_then_else
+         /* If true_rtx and false_rtx are not general_operands, an if_then_else
             is unlikely to be simpler.  */
-         if (general_operand (true, VOIDmode)
-             && general_operand (false, VOIDmode))
+         if (general_operand (true_rtx, VOIDmode)
+             && general_operand (false_rtx, VOIDmode))
            {
              /* Restarting if we generate a store-flag expression will cause
                 us to loop.  Just drop through in this case.  */
 
              /* If the result values are STORE_FLAG_VALUE and zero, we can
                 just make the comparison operation.  */
-             if (true == const_true_rtx && false == const0_rtx)
+             if (true_rtx == const_true_rtx && false_rtx == const0_rtx)
                x = gen_binary (cond_code, mode, cond, cop1);
-             else if (true == const0_rtx && false == const_true_rtx)
+             else if (true_rtx == const0_rtx && false_rtx == const_true_rtx
+                      && reverse_condition (cond_code) != UNKNOWN)
                x = gen_binary (reverse_condition (cond_code),
                                mode, cond, cop1);
 
              /* Likewise, we can make the negate of a comparison operation
                 if the result values are - STORE_FLAG_VALUE and zero.  */
-             else if (GET_CODE (true) == CONST_INT
-                      && INTVAL (true) == - STORE_FLAG_VALUE
-                      && false == const0_rtx)
-               x = gen_unary (NEG, mode, mode,
-                              gen_binary (cond_code, mode, cond, cop1));
-             else if (GET_CODE (false) == CONST_INT
-                      && INTVAL (false) == - STORE_FLAG_VALUE
-                      && true == const0_rtx)
-               x = gen_unary (NEG, mode, mode,
-                              gen_binary (reverse_condition (cond_code), 
-                                          mode, cond, cop1));
+             else if (GET_CODE (true_rtx) == CONST_INT
+                      && INTVAL (true_rtx) == - STORE_FLAG_VALUE
+                      && false_rtx == const0_rtx)
+               x = simplify_gen_unary (NEG, mode,
+                                       gen_binary (cond_code, mode, cond,
+                                                   cop1),
+                                       mode);
+             else if (GET_CODE (false_rtx) == CONST_INT
+                      && INTVAL (false_rtx) == - STORE_FLAG_VALUE
+                      && true_rtx == const0_rtx)
+               x = simplify_gen_unary (NEG, mode,
+                                       gen_binary (reverse_condition
+                                                   (cond_code),
+                                                   mode, cond, cop1),
+                                       mode);
              else
                return gen_rtx_IF_THEN_ELSE (mode,
                                             gen_binary (cond_code, VOIDmode,
                                                         cond, cop1),
-                                            true, false);
+                                            true_rtx, false_rtx);
 
              code = GET_CODE (x);
              op0_mode = VOIDmode;
@@ -3642,7 +3682,11 @@ combine_simplify_rtx (x, op0_mode, last, in_dest)
       {
        enum machine_mode cmp_mode = GET_MODE (XEXP (x, 0));
        if (cmp_mode == VOIDmode)
-         cmp_mode = GET_MODE (XEXP (x, 1));
+         {
+           cmp_mode = GET_MODE (XEXP (x, 1));
+           if (cmp_mode == VOIDmode)
+             cmp_mode = op0_mode;
+         }
        temp = simplify_relational_operation (code, cmp_mode,
                                              XEXP (x, 0), XEXP (x, 1));
       }
@@ -3668,7 +3712,12 @@ combine_simplify_rtx (x, op0_mode, last, in_dest)
     }
 
   if (temp)
-    x = temp, code = GET_CODE (temp);
+    {
+      x = temp;
+      code = GET_CODE (temp);
+      op0_mode = VOIDmode;
+      mode = GET_MODE (temp);
+    }
 
   /* First see if we can apply the inverse distributive law.  */
   if (code == PLUS || code == MINUS
@@ -3676,16 +3725,17 @@ combine_simplify_rtx (x, op0_mode, last, in_dest)
     {
       x = apply_distributive_law (x);
       code = GET_CODE (x);
+      op0_mode = VOIDmode;
     }
 
   /* If CODE is an associative operation not otherwise handled, see if we
      can associate some operands.  This can win if they are constants or
-     if they are logically related (i.e. (a & b) & a.  */
-  if ((code == PLUS || code == MINUS
-       || code == MULT || code == AND || code == IOR || code == XOR
-       || code == DIV || code == UDIV
+     if they are logically related (i.e. (a & b) & a).  */
+  if ((code == PLUS || code == MINUS || code == MULT || code == DIV
+       || code == AND || code == IOR || code == XOR
        || code == SMAX || code == SMIN || code == UMAX || code == UMIN)
-      && INTEGRAL_MODE_P (mode))
+      && ((INTEGRAL_MODE_P (mode) && code != DIV)
+         || (flag_unsafe_math_optimizations && FLOAT_MODE_P (mode))))
     {
       if (GET_CODE (XEXP (x, 0)) == code)
        {
@@ -3693,7 +3743,7 @@ combine_simplify_rtx (x, op0_mode, last, in_dest)
          rtx inner_op0 = XEXP (XEXP (x, 0), 1);
          rtx inner_op1 = XEXP (x, 1);
          rtx inner;
-         
+
          /* Make sure we pass the constant operand if any as the second
             one if this is a commutative operation.  */
          if (CONSTANT_P (inner_op0) && GET_RTX_CLASS (code) == 'c')
@@ -3704,7 +3754,6 @@ combine_simplify_rtx (x, op0_mode, last, in_dest)
            }
          inner = simplify_binary_operation (code == MINUS ? PLUS
                                             : code == DIV ? MULT
-                                            : code == UDIV ? MULT
                                             : code,
                                             mode, inner_op0, inner_op1);
 
@@ -3734,125 +3783,21 @@ combine_simplify_rtx (x, op0_mode, last, in_dest)
       break;
 
     case SUBREG:
-      /* (subreg:A (mem:B X) N) becomes a modified MEM unless the SUBREG
-        is paradoxical.  If we can't do that safely, then it becomes
-        something nonsensical so that this combination won't take place.  */
-
-      if (GET_CODE (SUBREG_REG (x)) == MEM
-         && (GET_MODE_SIZE (mode)
-             <= GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)))))
-       {
-         rtx inner = SUBREG_REG (x);
-         int endian_offset = 0;
-         /* Don't change the mode of the MEM
-            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);
-
-         if (BYTES_BIG_ENDIAN)
-           {
-             if (GET_MODE_SIZE (mode) < UNITS_PER_WORD)
-               endian_offset += UNITS_PER_WORD - GET_MODE_SIZE (mode);
-             if (GET_MODE_SIZE (GET_MODE (inner)) < UNITS_PER_WORD)
-               endian_offset -= (UNITS_PER_WORD
-                                 - GET_MODE_SIZE (GET_MODE (inner)));
-           }
-         /* 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)));
-         MEM_COPY_ATTRIBUTES (x, inner);
-         return x;
-       }
-
-      /* If we are in a SET_DEST, these other cases can't apply.  */
-      if (in_dest)
-       return x;
+      if (op0_mode == VOIDmode)
+       op0_mode = GET_MODE (SUBREG_REG (x));
 
-      /* Changing mode twice with SUBREG => just change it once,
-        or not at all if changing back to starting mode.  */
-      if (GET_CODE (SUBREG_REG (x)) == SUBREG)
-       {
-         if (mode == GET_MODE (SUBREG_REG (SUBREG_REG (x)))
-             && SUBREG_WORD (x) == 0 && SUBREG_WORD (SUBREG_REG (x)) == 0)
-           return SUBREG_REG (SUBREG_REG (x));
-
-         SUBST_INT (SUBREG_WORD (x),
-                    SUBREG_WORD (x) + SUBREG_WORD (SUBREG_REG (x)));
-         SUBST (SUBREG_REG (x), SUBREG_REG (SUBREG_REG (x)));
-       }
-
-      /* SUBREG of a hard register => just change the register number
-        and/or mode.  If the hard register is not valid in that mode,
-        suppress this combination.  If the hard register is the stack,
-        frame, or argument pointer, leave this as a SUBREG.  */
-
-      if (GET_CODE (SUBREG_REG (x)) == REG
-         && REGNO (SUBREG_REG (x)) < FIRST_PSEUDO_REGISTER
-         && REGNO (SUBREG_REG (x)) != FRAME_POINTER_REGNUM
-#if HARD_FRAME_POINTER_REGNUM != FRAME_POINTER_REGNUM
-         && REGNO (SUBREG_REG (x)) != HARD_FRAME_POINTER_REGNUM
-#endif
-#if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
-         && REGNO (SUBREG_REG (x)) != ARG_POINTER_REGNUM
-#endif
-         && REGNO (SUBREG_REG (x)) != STACK_POINTER_REGNUM)
-       {
-         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));
-         else
-           return gen_rtx_CLOBBER (mode, const0_rtx);
-       }
-
-      /* For a constant, try to pick up the part we want.  Handle a full
-        word and low-order part.  Only do this if we are narrowing
-        the constant; if it is being widened, we have no idea what
-        the extra bits will have been set to.  */
-
-      if (CONSTANT_P (SUBREG_REG (x)) && op0_mode != VOIDmode
-         && GET_MODE_SIZE (mode) == UNITS_PER_WORD
-         && GET_MODE_SIZE (op0_mode) > UNITS_PER_WORD
-         && GET_MODE_CLASS (mode) == MODE_INT)
-       {
-         temp = operand_subword (SUBREG_REG (x), SUBREG_WORD (x),
-                                 0, op0_mode);
-         if (temp)
-           return temp;
-       }
-       
-      /* If we want a subreg of a constant, at offset 0,
-        take the low bits.  On a little-endian machine, that's
-        always valid.  On a big-endian machine, it's valid
-        only if the constant's mode fits in one word.   Note that we
-        cannot use subreg_lowpart_p since SUBREG_REG may be VOIDmode.  */
+      /* simplify_subreg can't use gen_lowpart_for_combine.  */
       if (CONSTANT_P (SUBREG_REG (x))
-         && ((GET_MODE_SIZE (op0_mode) <= UNITS_PER_WORD
-             || ! WORDS_BIG_ENDIAN)
-             ? SUBREG_WORD (x) == 0
-             : (SUBREG_WORD (x)
-                == ((GET_MODE_SIZE (op0_mode)
-                     - MAX (GET_MODE_SIZE (mode), UNITS_PER_WORD))
-                    / UNITS_PER_WORD)))
-         && GET_MODE_SIZE (mode) <= GET_MODE_SIZE (op0_mode)
-         && (! WORDS_BIG_ENDIAN
-             || GET_MODE_BITSIZE (op0_mode) <= BITS_PER_WORD))
+         && subreg_lowpart_offset (mode, op0_mode) == SUBREG_BYTE (x))
        return gen_lowpart_for_combine (mode, SUBREG_REG (x));
 
-      /* A paradoxical SUBREG of a VOIDmode constant is the same constant,
-        since we are saying that the high bits don't matter.  */
-      if (CONSTANT_P (SUBREG_REG (x)) && GET_MODE (SUBREG_REG (x)) == VOIDmode
-         && GET_MODE_SIZE (mode) > GET_MODE_SIZE (op0_mode))
-       {
-         if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))) > UNITS_PER_WORD
-             && (WORDS_BIG_ENDIAN || SUBREG_WORD (x) != 0))
-           return operand_subword (SUBREG_REG (x), SUBREG_WORD (x), 0, mode);
-         return SUBREG_REG (x);
-       }
+      {
+       rtx temp;
+       temp = simplify_subreg (mode, SUBREG_REG (x), op0_mode,
+                               SUBREG_BYTE (x));
+       if (temp)
+         return temp;
+      }
 
       /* Note that we cannot do any narrowing for non-constants since
         we might have been counting on using the fact that some bits were
@@ -3864,30 +3809,30 @@ combine_simplify_rtx (x, op0_mode, last, in_dest)
       /* (not (plus X -1)) can become (neg X).  */
       if (GET_CODE (XEXP (x, 0)) == PLUS
          && XEXP (XEXP (x, 0), 1) == constm1_rtx)
-       return gen_rtx_combine (NEG, mode, XEXP (XEXP (x, 0), 0));
+       return gen_rtx_NEG (mode, XEXP (XEXP (x, 0), 0));
 
       /* Similarly, (not (neg X)) is (plus X -1).  */
       if (GET_CODE (XEXP (x, 0)) == NEG)
-       return gen_rtx_combine (PLUS, mode, XEXP (XEXP (x, 0), 0),
-                               constm1_rtx);
+       return gen_rtx_PLUS (mode, XEXP (XEXP (x, 0), 0), constm1_rtx);
 
-      /* (not (xor X C)) for C constant is (xor X D) with D = ~ C.  */
+      /* (not (xor X C)) for C constant is (xor X D) with D = ~C.  */
       if (GET_CODE (XEXP (x, 0)) == XOR
          && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
          && (temp = simplify_unary_operation (NOT, mode,
                                               XEXP (XEXP (x, 0), 1),
                                               mode)) != 0)
        return gen_binary (XOR, mode, XEXP (XEXP (x, 0), 0), temp);
-             
+
       /* (not (ashift 1 X)) is (rotate ~1 X).  We used to do this for operands
         other than 1, but that is not valid.  We could do a similar
         simplification for (not (lshiftrt C X)) where C is just the sign bit,
         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),
+       return gen_rtx_ROTATE (mode, simplify_gen_unary (NOT, mode,
+                                                        const1_rtx, mode),
                               XEXP (XEXP (x, 0), 1));
-                                           
+
       if (GET_CODE (XEXP (x, 0)) == SUBREG
          && subreg_lowpart_p (XEXP (x, 0))
          && (GET_MODE_SIZE (GET_MODE (XEXP (x, 0)))
@@ -3898,70 +3843,64 @@ combine_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),
+                             simplify_gen_unary (NOT, inner_mode, const1_rtx,
+                                                 inner_mode),
                              XEXP (SUBREG_REG (XEXP (x, 0)), 1));
          return gen_lowpart_for_combine (mode, x);
        }
-                                           
+
       /* If STORE_FLAG_VALUE is -1, (not (comparison foo bar)) can be done by
         reversing the comparison code if valid.  */
       if (STORE_FLAG_VALUE == -1
          && GET_RTX_CLASS (GET_CODE (XEXP (x, 0))) == '<'
-         && reversible_comparison_p (XEXP (x, 0)))
-       return gen_rtx_combine (reverse_condition (GET_CODE (XEXP (x, 0))),
-                               mode, XEXP (XEXP (x, 0), 0),
-                               XEXP (XEXP (x, 0), 1));
+         && (reversed = reversed_comparison (x, mode, XEXP (XEXP (x, 0), 0),
+                                             XEXP (XEXP (x, 0), 1))))
+       return reversed;
 
-      /* (ashiftrt foo C) where C is the number of bits in FOO minus 1
-        is (lt foo (const_int 0)) if STORE_FLAG_VALUE is -1, so we can
+      /* (not (ashiftrt foo C)) where C is the number of bits in FOO minus 1
+        is (ge foo (const_int 0)) if STORE_FLAG_VALUE is -1, so we can
         perform the above simplification.  */
 
       if (STORE_FLAG_VALUE == -1
          && GET_CODE (XEXP (x, 0)) == ASHIFTRT
-         && XEXP (x, 1) == const1_rtx
          && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
          && INTVAL (XEXP (XEXP (x, 0), 1)) == GET_MODE_BITSIZE (mode) - 1)
-       return gen_rtx_combine (GE, mode, XEXP (XEXP (x, 0), 0), const0_rtx);
+       return gen_rtx_GE (mode, XEXP (XEXP (x, 0), 0), const0_rtx);
 
       /* Apply De Morgan's laws to reduce number of patterns for machines
-        with negating logical insns (and-not, nand, etc.).  If result has
-        only one NOT, put it first, since that is how the patterns are
-        coded.  */
+        with negating logical insns (and-not, nand, etc.).  If result has
+        only one NOT, put it first, since that is how the patterns are
+        coded.  */
 
       if (GET_CODE (XEXP (x, 0)) == IOR || GET_CODE (XEXP (x, 0)) == AND)
-       {
-        rtx in1 = XEXP (XEXP (x, 0), 0), in2 = XEXP (XEXP (x, 0), 1);
-
-        if (GET_CODE (in1) == NOT)
-          in1 = XEXP (in1, 0);
-        else
-          in1 = gen_rtx_combine (NOT, GET_MODE (in1), in1);
-
-        if (GET_CODE (in2) == NOT)
-          in2 = XEXP (in2, 0);
-        else if (GET_CODE (in2) == CONST_INT
-                 && GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT)
-          in2 = GEN_INT (GET_MODE_MASK (mode) & ~ INTVAL (in2));
-        else
-          in2 = gen_rtx_combine (NOT, GET_MODE (in2), in2);
+       {
+         rtx in1 = XEXP (XEXP (x, 0), 0), in2 = XEXP (XEXP (x, 0), 1);
+         enum machine_mode op_mode;
+
+         op_mode = GET_MODE (in1);
+         in1 = simplify_gen_unary (NOT, op_mode, in1, op_mode);
 
-        if (GET_CODE (in2) == NOT)
-          {
-            rtx tem = in2;
-            in2 = in1; in1 = tem;
-          }
+         op_mode = GET_MODE (in2);
+         if (op_mode == VOIDmode)
+           op_mode = mode;
+         in2 = simplify_gen_unary (NOT, op_mode, in2, op_mode);
+
+         if (GET_CODE (in2) == NOT && GET_CODE (in1) != NOT)
+           {
+             rtx tem = in2;
+             in2 = in1; in1 = tem;
+           }
 
-        return gen_rtx_combine (GET_CODE (XEXP (x, 0)) == IOR ? AND : IOR,
+         return gen_rtx_fmt_ee (GET_CODE (XEXP (x, 0)) == IOR ? AND : IOR,
                                 mode, in1, in2);
-       } 
+       }
       break;
 
     case NEG:
       /* (neg (plus X 1)) can become (not X).  */
       if (GET_CODE (XEXP (x, 0)) == PLUS
          && XEXP (XEXP (x, 0), 1) == const1_rtx)
-       return gen_rtx_combine (NOT, mode, XEXP (XEXP (x, 0), 0));
+       return gen_rtx_NOT (mode, XEXP (XEXP (x, 0), 0));
 
       /* Similarly, (neg (not X)) is (plus X 1).  */
       if (GET_CODE (XEXP (x, 0)) == NOT)
@@ -3972,7 +3911,7 @@ combine_simplify_rtx (x, op0_mode, last, in_dest)
          && (! FLOAT_MODE_P (mode)
              /* x-y != -(y-x) with IEEE floating point.  */
              || TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT
-             || flag_fast_math))
+             || flag_unsafe_math_optimizations))
        return gen_binary (MINUS, mode, XEXP (XEXP (x, 0), 1),
                           XEXP (XEXP (x, 0), 0));
 
@@ -3990,16 +3929,13 @@ combine_simplify_rtx (x, op0_mode, last, in_dest)
          temp = simplify_unary_operation (NEG, mode,
                                           XEXP (XEXP (x, 0), 0), mode);
          if (temp)
-           {
-             SUBST (XEXP (XEXP (x, 0), 0), temp);
-             return XEXP (x, 0);
-           }
+           return gen_binary (ASHIFT, mode, temp, XEXP (XEXP (x, 0), 1));
        }
 
       temp = expand_compound_operation (XEXP (x, 0));
 
       /* For C equal to the width of MODE minus 1, (neg (ashiftrt X C)) can be
-        replaced by (lshiftrt X C).  This will convert
+        replaced by (lshiftrt X C).  This will convert
         (neg (sign_extract X 1 Y)) to (zero_extract X 1 Y).  */
 
       if (GET_CODE (temp) == ASHIFTRT
@@ -4063,8 +3999,8 @@ combine_simplify_rtx (x, op0_mode, last, in_dest)
          && (GET_CODE (XEXP (XEXP (x, 0), 0)) == SIGN_EXTEND
              || GET_CODE (XEXP (XEXP (x, 0), 0)) == ZERO_EXTEND)
          && GET_MODE (XEXP (XEXP (XEXP (x, 0), 0), 0)) == mode)
-       return gen_unary (GET_CODE (XEXP (x, 0)), mode, mode,
-                         XEXP (XEXP (XEXP (x, 0), 0), 0));
+       return simplify_gen_unary (GET_CODE (XEXP (x, 0)), mode,
+                                  XEXP (XEXP (XEXP (x, 0), 0), 0), mode);
 
       /* (truncate:SI (subreg:DI (truncate:SI X) 0)) is
         (truncate:SI x).  */
@@ -4083,7 +4019,7 @@ combine_simplify_rtx (x, op0_mode, last, in_dest)
          && num_sign_bit_copies (XEXP (x, 0), GET_MODE (XEXP (x, 0)))
             >= GET_MODE_BITSIZE (mode) + 1
          && ! (GET_CODE (XEXP (x, 0)) == LSHIFTRT
-               && GET_CODE (XEXP (XEXP (x, 0), 0)) == MULT))
+               && GET_CODE (XEXP (XEXP (x, 0), 0)) == MULT))
        return gen_lowpart_for_combine (mode, XEXP (x, 0));
 
       /* A truncate of a comparison can be replaced with a subreg if
@@ -4092,14 +4028,14 @@ combine_simplify_rtx (x, op0_mode, last, in_dest)
          than HOST_BITS_PER_WIDE_INT.  */
       if (GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT
          && GET_RTX_CLASS (GET_CODE (XEXP (x, 0))) == '<'
-         && ((HOST_WIDE_INT) STORE_FLAG_VALUE &GET_MODE_MASK (mode)) == 0)
+         && ((HOST_WIDE_INT) STORE_FLAG_VALUE & ~GET_MODE_MASK (mode)) == 0)
        return gen_lowpart_for_combine (mode, XEXP (x, 0));
 
       /* Similarly, a truncate of a register whose value is a
          comparison can be replaced with a subreg if STORE_FLAG_VALUE
          permits.  */
       if (GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT
-         && ((HOST_WIDE_INT) STORE_FLAG_VALUE &GET_MODE_MASK (mode)) == 0
+         && ((HOST_WIDE_INT) STORE_FLAG_VALUE & ~GET_MODE_MASK (mode)) == 0
          && (temp = get_last_value (XEXP (x, 0)))
          && GET_RTX_CLASS (GET_CODE (temp)) == '<')
        return gen_lowpart_for_combine (mode, XEXP (x, 0));
@@ -4110,7 +4046,7 @@ combine_simplify_rtx (x, op0_mode, last, in_dest)
       /* (float_truncate:SF (float_extend:DF foo:SF)) = foo:SF.  */
       if (GET_CODE (XEXP (x, 0)) == FLOAT_EXTEND
          && GET_MODE (XEXP (XEXP (x, 0), 0)) == mode)
-       return XEXP (XEXP (x, 0), 0);
+       return XEXP (XEXP (x, 0), 0);
 
       /* (float_truncate:SF (OP:DF (float_extend:DF foo:sf))) is
         (OP:SF foo:SF) if OP is NEG or ABS.  */
@@ -4118,8 +4054,8 @@ combine_simplify_rtx (x, op0_mode, last, in_dest)
           || GET_CODE (XEXP (x, 0)) == NEG)
          && GET_CODE (XEXP (XEXP (x, 0), 0)) == FLOAT_EXTEND
          && GET_MODE (XEXP (XEXP (XEXP (x, 0), 0), 0)) == mode)
-       return gen_unary (GET_CODE (XEXP (x, 0)), mode, mode,
-                         XEXP (XEXP (XEXP (x, 0), 0), 0));
+       return simplify_gen_unary (GET_CODE (XEXP (x, 0)), mode,
+                                  XEXP (XEXP (XEXP (x, 0), 0), 0), mode);
 
       /* (float_truncate:SF (subreg:DF (float_truncate:SF X) 0))
         is (float_truncate:SF x).  */
@@ -4127,7 +4063,7 @@ combine_simplify_rtx (x, op0_mode, last, in_dest)
          && subreg_lowpart_p (XEXP (x, 0))
          && GET_CODE (SUBREG_REG (XEXP (x, 0))) == FLOAT_TRUNCATE)
        return SUBREG_REG (XEXP (x, 0));
-      break;  
+      break;
 
 #ifdef HAVE_cc0
     case COMPARE:
@@ -4140,7 +4076,7 @@ combine_simplify_rtx (x, op0_mode, last, in_dest)
       /* In IEEE floating point, x-0 is not the same as x.  */
       if ((TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT
           || ! FLOAT_MODE_P (GET_MODE (XEXP (x, 0)))
-          || flag_fast_math)
+          || flag_unsafe_math_optimizations)
          && XEXP (x, 1) == CONST0_RTX (GET_MODE (XEXP (x, 0))))
        return XEXP (x, 0);
       break;
@@ -4185,7 +4121,7 @@ combine_simplify_rtx (x, op0_mode, last, in_dest)
       if (GET_CODE (XEXP (x, 0)) == XOR
          && GET_CODE (XEXP (x, 1)) == CONST_INT
          && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
-         && INTVAL (XEXP (x, 1)) == - INTVAL (XEXP (XEXP (x, 0), 1))
+         && INTVAL (XEXP (x, 1)) == -INTVAL (XEXP (XEXP (x, 0), 1))
          && ((i = exact_log2 (INTVAL (XEXP (XEXP (x, 0), 1)))) >= 0
              || (i = exact_log2 (INTVAL (XEXP (x, 1)))) >= 0)
          && GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT
@@ -4208,14 +4144,13 @@ combine_simplify_rtx (x, op0_mode, last, in_dest)
         is 1.  This produces better code than the alternative immediately
         below.  */
       if (GET_RTX_CLASS (GET_CODE (XEXP (x, 0))) == '<'
-         && reversible_comparison_p (XEXP (x, 0))
          && ((STORE_FLAG_VALUE == -1 && XEXP (x, 1) == const1_rtx)
-             || (STORE_FLAG_VALUE == 1 && XEXP (x, 1) == constm1_rtx)))
+             || (STORE_FLAG_VALUE == 1 && XEXP (x, 1) == constm1_rtx))
+         && (reversed = reversed_comparison (XEXP (x, 0), mode,
+                                             XEXP (XEXP (x, 0), 0),
+                                             XEXP (XEXP (x, 0), 1))))
        return
-         gen_unary (NEG, mode, mode,
-                    gen_binary (reverse_condition (GET_CODE (XEXP (x, 0))),
-                                mode, XEXP (XEXP (x, 0), 0),
-                                XEXP (XEXP (x, 0), 1)));
+         simplify_gen_unary (NEG, mode, reversed, mode);
 
       /* If only the low-order bit of X is possibly nonzero, (plus x -1)
         can become (ashiftrt (ashift (xor x 1) C) C) where C is
@@ -4228,8 +4163,7 @@ combine_simplify_rtx (x, op0_mode, last, in_dest)
          && nonzero_bits (XEXP (x, 0), mode) == 1)
        return simplify_shift_const (NULL_RTX, ASHIFTRT, mode,
           simplify_shift_const (NULL_RTX, ASHIFT, mode,
-                                gen_rtx_combine (XOR, mode,
-                                                 XEXP (x, 0), const1_rtx),
+                                gen_rtx_XOR (mode, XEXP (x, 0), const1_rtx),
                                 GET_MODE_BITSIZE (mode) - 1),
           GET_MODE_BITSIZE (mode) - 1);
 
@@ -4260,19 +4194,19 @@ combine_simplify_rtx (x, op0_mode, last, in_dest)
       if (STORE_FLAG_VALUE == 1
          && XEXP (x, 0) == const1_rtx
          && GET_RTX_CLASS (GET_CODE (XEXP (x, 1))) == '<'
-         && reversible_comparison_p (XEXP (x, 1)))
-       return gen_binary (reverse_condition (GET_CODE (XEXP (x, 1))),
-                          mode, XEXP (XEXP (x, 1), 0),
-                               XEXP (XEXP (x, 1), 1));
+         && (reversed = reversed_comparison (XEXP (x, 1), mode,
+                                             XEXP (XEXP (x, 1), 0),
+                                             XEXP (XEXP (x, 1), 1))))
+       return reversed;
 
       /* (minus <foo> (and <foo> (const_int -pow2))) becomes
         (and <foo> (const_int pow2-1))  */
       if (GET_CODE (XEXP (x, 1)) == AND
          && GET_CODE (XEXP (XEXP (x, 1), 1)) == CONST_INT
-         && exact_log2 (- INTVAL (XEXP (XEXP (x, 1), 1))) >= 0
+         && exact_log2 (-INTVAL (XEXP (XEXP (x, 1), 1))) >= 0
          && rtx_equal_p (XEXP (XEXP (x, 1), 0), XEXP (x, 0)))
        return simplify_and_const_int (NULL_RTX, mode, XEXP (x, 0),
-                                      - INTVAL (XEXP (XEXP (x, 1), 1)) - 1);
+                                      -INTVAL (XEXP (XEXP (x, 1), 1)) - 1);
 
       /* Canonicalize (minus A (plus B C)) to (minus (minus A B) C) for
         integers.  */
@@ -4301,6 +4235,16 @@ combine_simplify_rtx (x, op0_mode, last, in_dest)
          if (GET_CODE (x) != MULT)
            return x;
        }
+      /* Try simplify a*(b/c) as (a*b)/c.  */
+      if (FLOAT_MODE_P (mode) && flag_unsafe_math_optimizations
+         && GET_CODE (XEXP (x, 0)) == DIV)
+       {
+         rtx tem = simplify_binary_operation (MULT, mode,
+                                              XEXP (XEXP (x, 0), 0),
+                                              XEXP (x, 1));
+         if (tem)
+           return gen_binary (DIV, mode, tem, XEXP (XEXP (x, 0), 1));
+       }
       break;
 
     case UDIV:
@@ -4319,6 +4263,10 @@ combine_simplify_rtx (x, op0_mode, last, in_dest)
     case EQ:  case NE:
     case GT:  case GTU:  case GE:  case GEU:
     case LT:  case LTU:  case LE:  case LEU:
+    case UNEQ:  case LTGT:
+    case UNGT:  case UNGE:
+    case UNLT:  case UNLE:
+    case UNORDERED: case ORDERED:
       /* If the first operand is a condition code, we can't do anything
         with it.  */
       if (GET_CODE (XEXP (x, 0)) == COMPARE
@@ -4326,7 +4274,7 @@ combine_simplify_rtx (x, op0_mode, last, in_dest)
 #ifdef HAVE_cc0
              && XEXP (x, 0) != cc0_rtx
 #endif
-              ))
+             ))
        {
          rtx op0 = XEXP (x, 0);
          rtx op1 = XEXP (x, 1);
@@ -4352,24 +4300,29 @@ combine_simplify_rtx (x, op0_mode, last, in_dest)
 
          if (STORE_FLAG_VALUE == 1
              && new_code == NE && GET_MODE_CLASS (mode) == MODE_INT
-             && op1 == const0_rtx && nonzero_bits (op0, mode) == 1)
+             && op1 == const0_rtx
+             && mode == GET_MODE (op0)
+             && nonzero_bits (op0, mode) == 1)
            return gen_lowpart_for_combine (mode,
                                            expand_compound_operation (op0));
 
          else if (STORE_FLAG_VALUE == 1
                   && new_code == NE && GET_MODE_CLASS (mode) == MODE_INT
                   && op1 == const0_rtx
+                  && mode == GET_MODE (op0)
                   && (num_sign_bit_copies (op0, mode)
                       == GET_MODE_BITSIZE (mode)))
            {
              op0 = expand_compound_operation (op0);
-             return gen_unary (NEG, mode, mode,
-                               gen_lowpart_for_combine (mode, op0));
+             return simplify_gen_unary (NEG, mode,
+                                        gen_lowpart_for_combine (mode, op0),
+                                        mode);
            }
 
          else if (STORE_FLAG_VALUE == 1
                   && new_code == EQ && GET_MODE_CLASS (mode) == MODE_INT
                   && op1 == const0_rtx
+                  && mode == GET_MODE (op0)
                   && nonzero_bits (op0, mode) == 1)
            {
              op0 = expand_compound_operation (op0);
@@ -4381,6 +4334,7 @@ combine_simplify_rtx (x, op0_mode, last, in_dest)
          else if (STORE_FLAG_VALUE == 1
                   && new_code == EQ && GET_MODE_CLASS (mode) == MODE_INT
                   && op1 == const0_rtx
+                  && mode == GET_MODE (op0)
                   && (num_sign_bit_copies (op0, mode)
                       == GET_MODE_BITSIZE (mode)))
            {
@@ -4401,28 +4355,33 @@ combine_simplify_rtx (x, op0_mode, last, in_dest)
          else if (STORE_FLAG_VALUE == -1
                   && new_code == NE && GET_MODE_CLASS (mode) == MODE_INT
                   && op1 == const0_rtx
+                  && mode == GET_MODE (op0)
                   && nonzero_bits (op0, mode) == 1)
            {
              op0 = expand_compound_operation (op0);
-             return gen_unary (NEG, mode, mode,
-                               gen_lowpart_for_combine (mode, op0));
+             return simplify_gen_unary (NEG, mode,
+                                        gen_lowpart_for_combine (mode, op0),
+                                        mode);
            }
 
          else if (STORE_FLAG_VALUE == -1
                   && new_code == EQ && GET_MODE_CLASS (mode) == MODE_INT
                   && op1 == const0_rtx
+                  && mode == GET_MODE (op0)
                   && (num_sign_bit_copies (op0, mode)
                       == GET_MODE_BITSIZE (mode)))
            {
              op0 = expand_compound_operation (op0);
-             return gen_unary (NOT, mode, mode,
-                               gen_lowpart_for_combine (mode, op0));
+             return simplify_gen_unary (NOT, mode,
+                                        gen_lowpart_for_combine (mode, op0),
+                                        mode);
            }
 
          /* If X is 0/1, (eq X 0) is X-1.  */
          else if (STORE_FLAG_VALUE == -1
                   && new_code == EQ && GET_MODE_CLASS (mode) == MODE_INT
                   && op1 == const0_rtx
+                  && mode == GET_MODE (op0)
                   && nonzero_bits (op0, mode) == 1)
            {
              op0 = expand_compound_operation (op0);
@@ -4453,15 +4412,15 @@ combine_simplify_rtx (x, op0_mode, last, in_dest)
 
          /* If the code changed, return a whole new comparison.  */
          if (new_code != code)
-           return gen_rtx_combine (new_code, mode, op0, op1);
+           return gen_rtx_fmt_ee (new_code, mode, op0, op1);
 
-         /* Otherwise, keep this operation, but maybe change its operands.  
+         /* Otherwise, keep this operation, but maybe change its operands.
             This also converts (ne (compare FOO BAR) 0) to (ne FOO BAR).  */
          SUBST (XEXP (x, 0), op0);
          SUBST (XEXP (x, 1), op1);
        }
       break;
-         
+
     case IF_THEN_ELSE:
       return simplify_if_then_else (x);
 
@@ -4483,7 +4442,7 @@ combine_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));
@@ -4503,10 +4462,9 @@ combine_simplify_rtx (x, op0_mode, last, in_dest)
                  == 0)))
        return XEXP (x, 0);
 
-
       /* If operand is known to be only -1 or 0, convert ABS to NEG.  */
       if (num_sign_bit_copies (XEXP (x, 0), mode) == GET_MODE_BITSIZE (mode))
-       return gen_rtx_combine (NEG, mode, XEXP (x, 0));
+       return gen_rtx_NEG (mode, XEXP (x, 0));
 
       break;
 
@@ -4530,14 +4488,14 @@ combine_simplify_rtx (x, op0_mode, last, in_dest)
     case ROTATERT:
       /* If this is a shift by a constant amount, simplify it.  */
       if (GET_CODE (XEXP (x, 1)) == CONST_INT)
-       return simplify_shift_const (x, code, mode, XEXP (x, 0), 
+       return simplify_shift_const (x, code, mode, XEXP (x, 0),
                                     INTVAL (XEXP (x, 1)));
 
 #ifdef SHIFT_COUNT_TRUNCATED
       else if (SHIFT_COUNT_TRUNCATED && GET_CODE (XEXP (x, 1)) != REG)
        SUBST (XEXP (x, 1),
               force_to_mode (XEXP (x, 1), GET_MODE (x),
-                             ((HOST_WIDE_INT) 1 
+                             ((HOST_WIDE_INT) 1
                               << exact_log2 (GET_MODE_BITSIZE (GET_MODE (x))))
                              - 1,
                              NULL_RTX, 0));
@@ -4545,6 +4503,45 @@ combine_simplify_rtx (x, op0_mode, last, in_dest)
 
       break;
 
+    case VEC_SELECT:
+      {
+       rtx op0 = XEXP (x, 0);
+       rtx op1 = XEXP (x, 1);
+       int len;
+
+       if (GET_CODE (op1) != PARALLEL)
+         abort ();
+       len = XVECLEN (op1, 0);
+       if (len == 1
+           && GET_CODE (XVECEXP (op1, 0, 0)) == CONST_INT
+           && GET_CODE (op0) == VEC_CONCAT)
+         {
+           int offset = INTVAL (XVECEXP (op1, 0, 0)) * GET_MODE_SIZE (GET_MODE (x));
+
+           /* Try to find the element in the VEC_CONCAT.  */
+           for (;;)
+             {
+               if (GET_MODE (op0) == GET_MODE (x))
+                 return op0;
+               if (GET_CODE (op0) == VEC_CONCAT)
+                 {
+                   HOST_WIDE_INT op0_size = GET_MODE_SIZE (GET_MODE (XEXP (op0, 0)));
+                   if (op0_size < offset)
+                     op0 = XEXP (op0, 0);
+                   else
+                     {
+                       offset -= op0_size;
+                       op0 = XEXP (op0, 1);
+                     }
+                 }
+               else
+                 break;
+             }
+         }
+      }
+
+      break;
+
     default:
       break;
     }
@@ -4560,33 +4557,37 @@ simplify_if_then_else (x)
 {
   enum machine_mode mode = GET_MODE (x);
   rtx cond = XEXP (x, 0);
-  rtx true = XEXP (x, 1);
-  rtx false = XEXP (x, 2);
+  rtx true_rtx = XEXP (x, 1);
+  rtx false_rtx = XEXP (x, 2);
   enum rtx_code true_code = GET_CODE (cond);
   int comparison_p = GET_RTX_CLASS (true_code) == '<';
   rtx temp;
   int i;
+  enum rtx_code false_code;
+  rtx reversed;
 
   /* Simplify storing of the truth value.  */
-  if (comparison_p && true == const_true_rtx && false == const0_rtx)
+  if (comparison_p && true_rtx == const_true_rtx && false_rtx == const0_rtx)
     return gen_binary (true_code, mode, XEXP (cond, 0), XEXP (cond, 1));
-      
+
   /* Also when the truth value has to be reversed.  */
-  if (comparison_p && reversible_comparison_p (cond)
-      && true == const0_rtx && false == const_true_rtx)
-    return gen_binary (reverse_condition (true_code),
-                      mode, XEXP (cond, 0), XEXP (cond, 1));
+  if (comparison_p
+      && true_rtx == const0_rtx && false_rtx == const_true_rtx
+      && (reversed = reversed_comparison (cond, mode, XEXP (cond, 0),
+                                         XEXP (cond, 1))))
+    return reversed;
 
   /* Sometimes we can simplify the arm of an IF_THEN_ELSE if a register used
      in it is being compared against certain values.  Get the true and false
      comparisons and see if that says anything about the value of each arm.  */
 
-  if (comparison_p && reversible_comparison_p (cond)
+  if (comparison_p
+      && ((false_code = combine_reversed_comparison_code (cond))
+         != UNKNOWN)
       && GET_CODE (XEXP (cond, 0)) == REG)
     {
       HOST_WIDE_INT nzb;
       rtx from = XEXP (cond, 0);
-      enum rtx_code false_code = reverse_condition (true_code);
       rtx true_val = XEXP (cond, 1);
       rtx false_val = true_val;
       int swapped = 0;
@@ -4596,7 +4597,7 @@ simplify_if_then_else (x)
       if (false_code == EQ)
        {
          swapped = 1, true_code = EQ, false_code = NE;
-         temp = true, true = false, false = temp;
+         temp = true_rtx, true_rtx = false_rtx, false_rtx = temp;
        }
 
       /* If we are comparing against zero and the expression being tested has
@@ -4615,18 +4616,21 @@ simplify_if_then_else (x)
         branch and it is used in the arm.  Be careful due to the potential
         of locally-shared RTL.  */
 
-      if (reg_mentioned_p (from, true))
-       true = subst (known_cond (copy_rtx (true), true_code, from, true_val),
+      if (reg_mentioned_p (from, true_rtx))
+       true_rtx = subst (known_cond (copy_rtx (true_rtx), true_code,
+                                     from, true_val),
                      pc_rtx, pc_rtx, 0, 0);
-      if (reg_mentioned_p (from, false))
-       false = subst (known_cond (copy_rtx (false), false_code,
+      if (reg_mentioned_p (from, false_rtx))
+       false_rtx = subst (known_cond (copy_rtx (false_rtx), false_code,
                                   from, false_val),
                       pc_rtx, pc_rtx, 0, 0);
 
-      SUBST (XEXP (x, 1), swapped ? false : true);
-      SUBST (XEXP (x, 2), swapped ? true : false);
+      SUBST (XEXP (x, 1), swapped ? false_rtx : true_rtx);
+      SUBST (XEXP (x, 2), swapped ? true_rtx : false_rtx);
 
-      true = XEXP (x, 1), false = XEXP (x, 2), true_code = GET_CODE (cond);
+      true_rtx = XEXP (x, 1);
+      false_rtx = XEXP (x, 2);
+      true_code = GET_CODE (cond);
     }
 
   /* If we have (if_then_else FOO (pc) (label_ref BAR)) and FOO can be
@@ -4635,28 +4639,30 @@ simplify_if_then_else (x)
      arm, the false arm is the same as the first operand of the comparison, or
      the false arm is more complicated than the true arm.  */
 
-  if (comparison_p && reversible_comparison_p (cond)
-      && (true == pc_rtx 
-         || (CONSTANT_P (true)
-             && GET_CODE (false) != CONST_INT && false != pc_rtx)
-         || true == const0_rtx
-         || (GET_RTX_CLASS (GET_CODE (true)) == 'o'
-             && GET_RTX_CLASS (GET_CODE (false)) != 'o')
-         || (GET_CODE (true) == SUBREG
-             && GET_RTX_CLASS (GET_CODE (SUBREG_REG (true))) == 'o'
-             && GET_RTX_CLASS (GET_CODE (false)) != 'o')
-         || reg_mentioned_p (true, false)
-         || rtx_equal_p (false, XEXP (cond, 0))))
-    {
-      true_code = reverse_condition (true_code);
+  if (comparison_p
+      && combine_reversed_comparison_code (cond) != UNKNOWN
+      && (true_rtx == pc_rtx
+         || (CONSTANT_P (true_rtx)
+             && GET_CODE (false_rtx) != CONST_INT && false_rtx != pc_rtx)
+         || true_rtx == const0_rtx
+         || (GET_RTX_CLASS (GET_CODE (true_rtx)) == 'o'
+             && GET_RTX_CLASS (GET_CODE (false_rtx)) != 'o')
+         || (GET_CODE (true_rtx) == SUBREG
+             && GET_RTX_CLASS (GET_CODE (SUBREG_REG (true_rtx))) == 'o'
+             && GET_RTX_CLASS (GET_CODE (false_rtx)) != 'o')
+         || reg_mentioned_p (true_rtx, false_rtx)
+         || rtx_equal_p (false_rtx, XEXP (cond, 0))))
+    {
+      true_code = reversed_comparison_code (cond, NULL);
       SUBST (XEXP (x, 0),
-            gen_binary (true_code, GET_MODE (cond), XEXP (cond, 0),
-                        XEXP (cond, 1)));
+            reversed_comparison (cond, GET_MODE (cond), XEXP (cond, 0),
+                                 XEXP (cond, 1)));
 
-      SUBST (XEXP (x, 1), false);
-      SUBST (XEXP (x, 2), true);
+      SUBST (XEXP (x, 1), false_rtx);
+      SUBST (XEXP (x, 2), true_rtx);
 
-      temp = true, true = false, false = temp, cond = XEXP (x, 0);
+      temp = true_rtx, true_rtx = false_rtx, false_rtx = temp;
+      cond = XEXP (x, 0);
 
       /* It is possible that the conditional has been simplified out.  */
       true_code = GET_CODE (cond);
@@ -4665,64 +4671,69 @@ simplify_if_then_else (x)
 
   /* If the two arms are identical, we don't need the comparison.  */
 
-  if (rtx_equal_p (true, false) && ! side_effects_p (cond))
-    return true;
+  if (rtx_equal_p (true_rtx, false_rtx) && ! side_effects_p (cond))
+    return true_rtx;
 
   /* Convert a == b ? b : a to "a".  */
   if (true_code == EQ && ! side_effects_p (cond)
-      && rtx_equal_p (XEXP (cond, 0), false)
-      && rtx_equal_p (XEXP (cond, 1), true))
-    return false;
+      && (! FLOAT_MODE_P (mode) || flag_unsafe_math_optimizations)
+      && rtx_equal_p (XEXP (cond, 0), false_rtx)
+      && rtx_equal_p (XEXP (cond, 1), true_rtx))
+    return false_rtx;
   else if (true_code == NE && ! side_effects_p (cond)
-          && rtx_equal_p (XEXP (cond, 0), true)
-          && rtx_equal_p (XEXP (cond, 1), false))
-    return true;
+          && (! FLOAT_MODE_P (mode) || flag_unsafe_math_optimizations)
+          && rtx_equal_p (XEXP (cond, 0), true_rtx)
+          && rtx_equal_p (XEXP (cond, 1), false_rtx))
+    return true_rtx;
 
   /* Look for cases where we have (abs x) or (neg (abs X)).  */
 
   if (GET_MODE_CLASS (mode) == MODE_INT
-      && GET_CODE (false) == NEG
-      && rtx_equal_p (true, XEXP (false, 0))
+      && GET_CODE (false_rtx) == NEG
+      && rtx_equal_p (true_rtx, XEXP (false_rtx, 0))
       && comparison_p
-      && rtx_equal_p (true, XEXP (cond, 0))
-      && ! side_effects_p (true))
+      && rtx_equal_p (true_rtx, XEXP (cond, 0))
+      && ! side_effects_p (true_rtx))
     switch (true_code)
       {
       case GT:
       case GE:
-       return gen_unary (ABS, mode, mode, true);
+       return simplify_gen_unary (ABS, mode, true_rtx, mode);
       case LT:
       case LE:
-       return gen_unary (NEG, mode, mode, gen_unary (ABS, mode, mode, true));
+       return
+         simplify_gen_unary (NEG, mode,
+                             simplify_gen_unary (ABS, mode, true_rtx, mode),
+                             mode);
     default:
       break;
       }
 
   /* Look for MIN or MAX.  */
 
-  if ((! FLOAT_MODE_P (mode) || flag_fast_math)
+  if ((! FLOAT_MODE_P (mode) || flag_unsafe_math_optimizations)
       && comparison_p
-      && rtx_equal_p (XEXP (cond, 0), true)
-      && rtx_equal_p (XEXP (cond, 1), false)
+      && rtx_equal_p (XEXP (cond, 0), true_rtx)
+      && rtx_equal_p (XEXP (cond, 1), false_rtx)
       && ! side_effects_p (cond))
     switch (true_code)
       {
       case GE:
       case GT:
-       return gen_binary (SMAX, mode, true, false);
+       return gen_binary (SMAX, mode, true_rtx, false_rtx);
       case LE:
       case LT:
-       return gen_binary (SMIN, mode, true, false);
+       return gen_binary (SMIN, mode, true_rtx, false_rtx);
       case GEU:
       case GTU:
-       return gen_binary (UMAX, mode, true, false);
+       return gen_binary (UMAX, mode, true_rtx, false_rtx);
       case LEU:
       case LTU:
-       return gen_binary (UMIN, mode, true, false);
+       return gen_binary (UMIN, mode, true_rtx, false_rtx);
       default:
        break;
       }
-  
+
   /* If we have (if_then_else COND (OP Z C1) Z) and OP is an identity when its
      second operand is zero, this can be done as (OP Z (mult COND C2)) where
      C2 = C1 * STORE_FLAG_VALUE. Similarly if OP has an outer ZERO_EXTEND or
@@ -4733,8 +4744,8 @@ simplify_if_then_else (x)
   if ((STORE_FLAG_VALUE == 1 || STORE_FLAG_VALUE == -1)
       && comparison_p && mode != VOIDmode && ! side_effects_p (x))
     {
-      rtx t = make_compound_operation (true, SET);
-      rtx f = make_compound_operation (false, SET);
+      rtx t = make_compound_operation (true_rtx, SET);
+      rtx f = make_compound_operation (false_rtx, SET);
       rtx cond_op0 = XEXP (cond, 0);
       rtx cond_op1 = XEXP (cond, 1);
       enum rtx_code op = NIL, extend_op = NIL;
@@ -4801,7 +4812,7 @@ simplify_if_then_else (x)
               && subreg_lowpart_p (XEXP (XEXP (t, 0), 0))
               && rtx_equal_p (SUBREG_REG (XEXP (XEXP (t, 0), 0)), f)
               && ((nonzero_bits (f, GET_MODE (f))
-                   & ~ GET_MODE_MASK (GET_MODE (XEXP (XEXP (t, 0), 0))))
+                   & ~GET_MODE_MASK (GET_MODE (XEXP (XEXP (t, 0), 0))))
                   == 0))
        {
          c1 = XEXP (XEXP (t, 0), 1); z = f; op = GET_CODE (XEXP (t, 0));
@@ -4817,14 +4828,14 @@ simplify_if_then_else (x)
               && subreg_lowpart_p (XEXP (XEXP (t, 0), 1))
               && rtx_equal_p (SUBREG_REG (XEXP (XEXP (t, 0), 1)), f)
               && ((nonzero_bits (f, GET_MODE (f))
-                   & ~ GET_MODE_MASK (GET_MODE (XEXP (XEXP (t, 0), 1))))
+                   & ~GET_MODE_MASK (GET_MODE (XEXP (XEXP (t, 0), 1))))
                   == 0))
        {
          c1 = XEXP (XEXP (t, 0), 0); z = f; op = GET_CODE (XEXP (t, 0));
          extend_op = ZERO_EXTEND;
          m = GET_MODE (XEXP (t, 0));
        }
-      
+
       if (z)
        {
          temp = subst (gen_binary (true_code, m, cond_op0, cond_op1),
@@ -4835,7 +4846,7 @@ simplify_if_then_else (x)
          temp = gen_binary (op, m, gen_lowpart_for_combine (m, z), temp);
 
          if (extend_op != NIL)
-           temp = gen_unary (extend_op, mode, m, temp);
+           temp = simplify_gen_unary (extend_op, mode, temp, m);
 
          return temp;
        }
@@ -4847,12 +4858,12 @@ simplify_if_then_else (x)
      can actually do this more generally, but it doesn't seem worth it.  */
 
   if (true_code == NE && XEXP (cond, 1) == const0_rtx
-      && false == const0_rtx && GET_CODE (true) == CONST_INT
+      && false_rtx == const0_rtx && GET_CODE (true_rtx) == CONST_INT
       && ((1 == nonzero_bits (XEXP (cond, 0), mode)
-          && (i = exact_log2 (INTVAL (true))) >= 0)
+          && (i = exact_log2 (INTVAL (true_rtx))) >= 0)
          || ((num_sign_bit_copies (XEXP (cond, 0), mode)
               == GET_MODE_BITSIZE (mode))
-             && (i = exact_log2 (- INTVAL (true))) >= 0)))
+             && (i = exact_log2 (-INTVAL (true_rtx))) >= 0)))
     return
       simplify_shift_const (NULL_RTX, ASHIFT, mode,
                            gen_lowpart_for_combine (mode, XEXP (cond, 0)), i);
@@ -4883,7 +4894,7 @@ simplify_set (x)
 
   if (GET_MODE_CLASS (mode) == MODE_INT)
     {
-      src = force_to_mode (src, mode, GET_MODE_MASK (mode), NULL_RTX, 0);
+      src = force_to_mode (src, mode, ~(HOST_WIDE_INT) 0, NULL_RTX, 0);
       SUBST (SET_SRC (x), src);
     }
 
@@ -4952,8 +4963,8 @@ simplify_set (x)
        {
          unsigned HOST_WIDE_INT mask;
 
-         SUBST (*cc_use, gen_rtx_combine (new_code, GET_MODE (*cc_use),
-                                          dest, const0_rtx));
+         SUBST (*cc_use, gen_rtx_fmt_ee (new_code, GET_MODE (*cc_use),
+                                         dest, const0_rtx));
 
          /* If the only change we made was to change an EQ into an NE or
             vice versa, OP0 has only one bit that might be nonzero, and OP1
@@ -5000,8 +5011,7 @@ simplify_set (x)
         correct mode, we need one.  */
       if (GET_CODE (src) != COMPARE || GET_MODE (src) != compare_mode)
        {
-         SUBST (SET_SRC (x),
-                gen_rtx_combine (COMPARE, compare_mode, op0, op1));
+         SUBST (SET_SRC (x), gen_rtx_COMPARE (compare_mode, op0, op1));
          src = SET_SRC (x);
        }
       else
@@ -5021,7 +5031,7 @@ simplify_set (x)
 
   /* If we have (set x (subreg:m1 (op:m2 ...) 0)) with OP being some operation,
      and X being a REG or (subreg (reg)), we may be able to convert this to
-     (set (subreg:m2 x) (op)). 
+     (set (subreg:m2 x) (op)).
 
      We can always do this if M1 is narrower than M2 because that means that
      we only care about the low bits of the result.
@@ -5030,7 +5040,7 @@ simplify_set (x)
      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.  */
+
   if (GET_CODE (src) == SUBREG && subreg_lowpart_p (src)
       && GET_RTX_CLASS (GET_CODE (SUBREG_REG (src))) != 'o'
       && (((GET_MODE_SIZE (GET_MODE (src)) + (UNITS_PER_WORD - 1))
@@ -5048,7 +5058,7 @@ simplify_set (x)
                 REGNO (dest)))
            && CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (src),
                                           GET_MODE (SUBREG_REG (src))))
-#endif                           
+#endif
       && (GET_CODE (dest) == REG
          || (GET_CODE (dest) == SUBREG
              && GET_CODE (SUBREG_REG (dest)) == REG)))
@@ -5068,14 +5078,14 @@ simplify_set (x)
 
   if (GET_CODE (src) == SUBREG && subreg_lowpart_p (src)
       && LOAD_EXTEND_OP (GET_MODE (SUBREG_REG (src))) != NIL
-      && SUBREG_WORD (src) == 0
+      && SUBREG_BYTE (src) == 0
       && (GET_MODE_SIZE (GET_MODE (src))
          > GET_MODE_SIZE (GET_MODE (SUBREG_REG (src))))
       && GET_CODE (SUBREG_REG (src)) == MEM)
     {
       SUBST (SET_SRC (x),
-            gen_rtx_combine (LOAD_EXTEND_OP (GET_MODE (SUBREG_REG (src))),
-                             GET_MODE (src), XEXP (src, 0)));
+            gen_rtx (LOAD_EXTEND_OP (GET_MODE (SUBREG_REG (src))),
+                     GET_MODE (src), SUBREG_REG (src)));
 
       src = SET_SRC (x);
     }
@@ -5101,29 +5111,32 @@ simplify_set (x)
          == GET_MODE_BITSIZE (GET_MODE (XEXP (XEXP (src, 0), 0))))
       && ! side_effects_p (src))
     {
-      rtx true = (GET_CODE (XEXP (src, 0)) == NE
+      rtx true_rtx = (GET_CODE (XEXP (src, 0)) == NE
                      ? XEXP (src, 1) : XEXP (src, 2));
-      rtx false = (GET_CODE (XEXP (src, 0)) == NE
+      rtx false_rtx = (GET_CODE (XEXP (src, 0)) == NE
                   ? XEXP (src, 2) : XEXP (src, 1));
       rtx term1 = const0_rtx, term2, term3;
 
-      if (GET_CODE (true) == IOR && rtx_equal_p (XEXP (true, 0), false))
-       term1 = false, true = XEXP (true, 1), false = const0_rtx;
-      else if (GET_CODE (true) == IOR
-              && rtx_equal_p (XEXP (true, 1), false))
-       term1 = false, true = XEXP (true, 0), false = const0_rtx;
-      else if (GET_CODE (false) == IOR
-              && rtx_equal_p (XEXP (false, 0), true))
-       term1 = true, false = XEXP (false, 1), true = const0_rtx;
-      else if (GET_CODE (false) == IOR
-              && rtx_equal_p (XEXP (false, 1), true))
-       term1 = true, false = XEXP (false, 0), true = const0_rtx;
-
-      term2 = gen_binary (AND, GET_MODE (src), XEXP (XEXP (src, 0), 0), true);
+      if (GET_CODE (true_rtx) == IOR
+         && rtx_equal_p (XEXP (true_rtx, 0), false_rtx))
+       term1 = false_rtx, true_rtx = XEXP(true_rtx, 1), false_rtx = const0_rtx;
+      else if (GET_CODE (true_rtx) == IOR
+              && rtx_equal_p (XEXP (true_rtx, 1), false_rtx))
+       term1 = false_rtx, true_rtx = XEXP(true_rtx, 0), false_rtx = const0_rtx;
+      else if (GET_CODE (false_rtx) == IOR
+              && rtx_equal_p (XEXP (false_rtx, 0), true_rtx))
+       term1 = true_rtx, false_rtx = XEXP(false_rtx, 1), true_rtx = const0_rtx;
+      else if (GET_CODE (false_rtx) == IOR
+              && rtx_equal_p (XEXP (false_rtx, 1), true_rtx))
+       term1 = true_rtx, false_rtx = XEXP(false_rtx, 0), true_rtx = const0_rtx;
+
+      term2 = gen_binary (AND, GET_MODE (src),
+                         XEXP (XEXP (src, 0), 0), true_rtx);
       term3 = gen_binary (AND, GET_MODE (src),
-                         gen_unary (NOT, GET_MODE (src), GET_MODE (src),
-                                    XEXP (XEXP (src, 0), 0)),
-                         false);
+                         simplify_gen_unary (NOT, GET_MODE (src),
+                                             XEXP (XEXP (src, 0), 0),
+                                             GET_MODE (src)),
+                         false_rtx);
 
       SUBST (SET_SRC (x),
             gen_binary (IOR, GET_MODE (src),
@@ -5133,68 +5146,6 @@ simplify_set (x)
       src = SET_SRC (x);
     }
 
-#ifdef HAVE_conditional_arithmetic
-  /* If we have conditional arithmetic and the operand of a SET is
-     a conditional expression, replace this with an IF_THEN_ELSE.
-     We can either have a conditional expression or a MULT of that expression
-     with a constant.  */
-  if ((GET_RTX_CLASS (GET_CODE (src)) == '1'
-       || GET_RTX_CLASS (GET_CODE (src)) == '2'
-       || GET_RTX_CLASS (GET_CODE (src)) == 'c')
-      && (GET_RTX_CLASS (GET_CODE (XEXP (src, 0))) == '<'
-         || (GET_CODE (XEXP (src, 0)) == MULT
-             && GET_RTX_CLASS (GET_CODE (XEXP (XEXP (src, 0), 0))) == '<'
-             && GET_CODE (XEXP (XEXP (src, 0), 1)) == CONST_INT)))
-    {
-      rtx cond = XEXP (src, 0);
-      rtx true_val = const1_rtx;
-      rtx false_arm, true_arm;
-
-      if (GET_CODE (cond) == MULT)
-       {
-         true_val = XEXP (cond, 1);
-         cond = XEXP (cond, 0);
-       }
-
-      if (GET_RTX_CLASS (GET_CODE (src)) == '1')
-       {
-         true_arm = gen_unary (GET_CODE (src), GET_MODE (src),
-                               GET_MODE (XEXP (src, 0)), true_val);
-         false_arm = gen_unary (GET_CODE (src), GET_MODE (src),
-                                GET_MODE (XEXP (src, 0)), const0_rtx);
-       }
-      else
-       {
-         true_arm = gen_binary (GET_CODE (src), GET_MODE (src),
-                                true_val, XEXP (src, 1));
-         false_arm = gen_binary (GET_CODE (src), GET_MODE (src),
-                                 const0_rtx, XEXP (src, 1));
-       }
-
-      /* Canonicalize if true_arm is the simpler one.  */
-      if (GET_RTX_CLASS (GET_CODE (true_arm)) == 'o'
-         && GET_RTX_CLASS (GET_CODE (false_arm)) != 'o'
-         && reversible_comparison_p (cond))
-       {
-         rtx temp = true_arm;
-
-         true_arm = false_arm;
-         false_arm = temp;
-
-         cond = gen_rtx_combine (reverse_condition (GET_CODE (cond)),
-                                 GET_MODE (cond), XEXP (cond, 0),
-                                 XEXP (cond, 1));
-       }
-
-      src = gen_rtx_combine (IF_THEN_ELSE, GET_MODE (src),
-                            gen_rtx_combine (GET_CODE (cond), VOIDmode,
-                                             XEXP (cond, 0),
-                                             XEXP (cond, 1)),
-                            true_arm, false_arm);
-      SUBST (SET_SRC (x), src);
-    }
-#endif
-
   /* If either SRC or DEST is a CLOBBER of (const_int 0), make this
      whole thing fail.  */
   if (GET_CODE (src) == CLOBBER && XEXP (src, 0) == const0_rtx)
@@ -5217,25 +5168,28 @@ simplify_logical (x, last)
   enum machine_mode mode = GET_MODE (x);
   rtx op0 = XEXP (x, 0);
   rtx op1 = XEXP (x, 1);
+  rtx reversed;
 
   switch (GET_CODE (x))
     {
     case AND:
-      /* Convert (A ^ B) & A to A & (~ B) since the latter is often a single
+      /* Convert (A ^ B) & A to A & (~B) since the latter is often a single
         insn (and may simplify more).  */
       if (GET_CODE (op0) == XOR
          && rtx_equal_p (XEXP (op0, 0), op1)
          && ! side_effects_p (op1))
        x = gen_binary (AND, mode,
-                       gen_unary (NOT, mode, mode, XEXP (op0, 1)), op1);
+                       simplify_gen_unary (NOT, mode, XEXP (op0, 1), mode),
+                       op1);
 
       if (GET_CODE (op0) == XOR
          && rtx_equal_p (XEXP (op0, 1), op1)
          && ! side_effects_p (op1))
        x = gen_binary (AND, mode,
-                       gen_unary (NOT, mode, mode, XEXP (op0, 0)), op1);
+                       simplify_gen_unary (NOT, mode, XEXP (op0, 0), mode),
+                       op1);
 
-      /* Similarly for (~ (A ^ B)) & A.  */
+      /* Similarly for (~(A ^ B)) & A.  */
       if (GET_CODE (op0) == NOT
          && GET_CODE (XEXP (op0, 0)) == XOR
          && rtx_equal_p (XEXP (XEXP (op0, 0), 0), op1)
@@ -5267,12 +5221,12 @@ simplify_logical (x, last)
            return gen_binary (IOR, mode,
                               gen_binary (AND, mode, XEXP (op0, 0),
                                           GEN_INT (INTVAL (XEXP (op0, 1))
-                                                   & ~ INTVAL (op1))), op1);
+                                                   & ~INTVAL (op1))), op1);
 
          if (GET_CODE (x) != AND)
            return x;
 
-         if (GET_RTX_CLASS (GET_CODE (x)) == 'c' 
+         if (GET_RTX_CLASS (GET_CODE (x)) == 'c'
              || GET_RTX_CLASS (GET_CODE (x)) == '2')
            op0 = XEXP (x, 0), op1 = XEXP (x, 1);
        }
@@ -5295,7 +5249,7 @@ simplify_logical (x, last)
         For example, (and (ior A B) (not B)) can occur as the result of
         expanding a bit field assignment.  When we apply the distributive
         law to this, we get (ior (and (A (not B))) (and (B (not B)))),
-        which then simplifies to (and (A (not B))). 
+        which then simplifies to (and (A (not B))).
 
         If we have (and (ior A B) C), apply the distributive law and then
         the inverse distributive law to see if things simplify.  */
@@ -5327,7 +5281,7 @@ simplify_logical (x, last)
                       gen_binary (IOR, mode, XEXP (op0, 0), XEXP (op1, 0)),
                       gen_binary (IOR, mode, copy_rtx (XEXP (op0, 0)),
                                   XEXP (op1, 1))));
-                                                           
+
       else if (GET_CODE (op1) == NOT && GET_CODE (op0) == XOR)
        return apply_distributive_law
          (gen_binary (XOR, mode,
@@ -5339,7 +5293,7 @@ simplify_logical (x, last)
       /* (ior A C) is C if all bits of A that might be nonzero are on in C.  */
       if (GET_CODE (op1) == CONST_INT
          && GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT
-         && (nonzero_bits (op0, mode) & ~ INTVAL (op1)) == 0)
+         && (nonzero_bits (op0, mode) & ~INTVAL (op1)) == 0)
        return op1;
 
       /* Convert (A & B) | A to A.  */
@@ -5442,7 +5396,9 @@ simplify_logical (x, last)
            SUBST (XEXP (x, 1), op1);
          }
        else if (num_negated == 1)
-         return gen_unary (NOT, mode, mode, gen_binary (XOR, mode, op0, op1));
+         return
+           simplify_gen_unary (NOT, mode, gen_binary (XOR, mode, op0, op1),
+                               mode);
       }
 
       /* Convert (xor (and A B) B) to (and (not A) B).  The latter may
@@ -5453,14 +5409,14 @@ simplify_logical (x, last)
          && rtx_equal_p (XEXP (op0, 1), op1)
          && ! side_effects_p (op1))
        return gen_binary (AND, mode,
-                          gen_unary (NOT, mode, mode, XEXP (op0, 0)),
+                          simplify_gen_unary (NOT, mode, XEXP (op0, 0), mode),
                           op1);
 
       else if (GET_CODE (op0) == AND
               && rtx_equal_p (XEXP (op0, 0), op1)
               && ! side_effects_p (op1))
        return gen_binary (AND, mode,
-                          gen_unary (NOT, mode, mode, XEXP (op0, 1)),
+                          simplify_gen_unary (NOT, mode, XEXP (op0, 1), mode),
                           op1);
 
       /* (xor (comparison foo bar) (const_int 1)) can become the reversed
@@ -5468,9 +5424,9 @@ simplify_logical (x, last)
       if (STORE_FLAG_VALUE == 1
          && op1 == const1_rtx
          && GET_RTX_CLASS (GET_CODE (op0)) == '<'
-         && reversible_comparison_p (op0))
-       return gen_rtx_combine (reverse_condition (GET_CODE (op0)),
-                               mode, XEXP (op0, 0), XEXP (op0, 1));
+         && (reversed = reversed_comparison (op0, mode, XEXP (op0, 0),
+                                             XEXP (op0, 1))))
+       return reversed;
 
       /* (lshiftrt foo C) where C is the number of bits in FOO minus 1
         is (lt foo (const_int 0)), so we can perform the above
@@ -5481,7 +5437,7 @@ simplify_logical (x, last)
          && GET_CODE (op0) == LSHIFTRT
          && GET_CODE (XEXP (op0, 1)) == CONST_INT
          && INTVAL (XEXP (op0, 1)) == GET_MODE_BITSIZE (mode) - 1)
-       return gen_rtx_combine (GE, mode, XEXP (op0, 0), const0_rtx);
+       return gen_rtx_GE (mode, XEXP (op0, 0), const0_rtx);
 
       /* (xor (comparison foo bar) (const_int sign-bit))
         when STORE_FLAG_VALUE is the sign bit.  */
@@ -5490,9 +5446,9 @@ simplify_logical (x, last)
              == (unsigned HOST_WIDE_INT) 1 << (GET_MODE_BITSIZE (mode) - 1))
          && op1 == const_true_rtx
          && GET_RTX_CLASS (GET_CODE (op0)) == '<'
-         && reversible_comparison_p (op0))
-       return gen_rtx_combine (reverse_condition (GET_CODE (op0)),
-                               mode, XEXP (op0, 0), XEXP (op0, 1));
+         && (reversed = reversed_comparison (op0, mode, XEXP (op0, 0),
+                                             XEXP (op0, 1))))
+       return reversed;
 
       break;
 
@@ -5509,7 +5465,7 @@ simplify_logical (x, last)
    an AND operation, which is simpler, though only one operation.
 
    The function expand_compound_operation is called with an rtx expression
-   and will convert it to the appropriate shifts and AND operations, 
+   and will convert it to the appropriate shifts and AND operations,
    simplifying at each stage.
 
    The function make_compound_operation is called to convert an expression
@@ -5549,7 +5505,7 @@ expand_compound_operation (x)
         Reject MODEs bigger than a word, because we might not be able
         to reference a two-register group starting with an arbitrary register
         (and currently gen_lowpart might crash for a SUBREG).  */
-  
+
       if (GET_MODE_SIZE (GET_MODE (XEXP (x, 0))) > UNITS_PER_WORD)
        return x;
 
@@ -5597,7 +5553,7 @@ expand_compound_operation (x)
   if (GET_CODE (x) == SIGN_EXTEND
       && (GET_MODE_BITSIZE (GET_MODE (x)) <= HOST_BITS_PER_WIDE_INT
          && ((nonzero_bits (XEXP (x, 0), GET_MODE (XEXP (x, 0)))
-               & ~ (((unsigned HOST_WIDE_INT)
+               & ~(((unsigned HOST_WIDE_INT)
                      GET_MODE_MASK (GET_MODE (XEXP (x, 0))))
                     >> 1))
               == 0)))
@@ -5616,7 +5572,7 @@ expand_compound_operation (x)
          && GET_MODE (XEXP (XEXP (x, 0), 0)) == GET_MODE (x)
          && GET_MODE_BITSIZE (GET_MODE (x)) <= HOST_BITS_PER_WIDE_INT
          && (nonzero_bits (XEXP (XEXP (x, 0), 0), GET_MODE (x))
-             & ~ GET_MODE_MASK (GET_MODE (XEXP (x, 0)))) == 0)
+             & ~GET_MODE_MASK (GET_MODE (XEXP (x, 0)))) == 0)
        return XEXP (XEXP (x, 0), 0);
 
       /* Likewise for (zero_extend:DI (subreg:SI foo:DI 0)).  */
@@ -5625,7 +5581,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 (XEXP (x, 0)))) == 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
@@ -5637,8 +5593,8 @@ expand_compound_operation (x)
          && GET_RTX_CLASS (GET_CODE (XEXP (XEXP (x, 0), 0))) == '<'
          && (GET_MODE_BITSIZE (GET_MODE (XEXP (x, 0)))
              <= HOST_BITS_PER_WIDE_INT)
-         && ((HOST_WIDE_INT) STORE_FLAG_VALUE
-             & ~ GET_MODE_MASK (GET_MODE (XEXP (x, 0)))) == 0)
+         && ((HOST_WIDE_INT) STORE_FLAG_VALUE
+             & ~GET_MODE_MASK (GET_MODE (XEXP (x, 0)))) == 0)
        return XEXP (XEXP (x, 0), 0);
 
       /* Likewise for (zero_extend:DI (subreg:SI foo:DI 0)).  */
@@ -5649,7 +5605,7 @@ expand_compound_operation (x)
          && (GET_MODE_BITSIZE (GET_MODE (XEXP (x, 0)))
              <= HOST_BITS_PER_WIDE_INT)
          && ((HOST_WIDE_INT) STORE_FLAG_VALUE
-             & ~ GET_MODE_MASK (GET_MODE (XEXP (x, 0)))) == 0)
+             & ~GET_MODE_MASK (GET_MODE (XEXP (x, 0)))) == 0)
        return SUBREG_REG (XEXP (x, 0));
 
     }
@@ -5665,7 +5621,7 @@ expand_compound_operation (x)
      We must check for the case where the left shift would have a negative
      count.  This can happen in a case like (x >> 31) & 255 on machines
      that can't shift by a constant.  On those machines, we would first
-     combine the shift with the AND to produce a variable-position 
+     combine the shift with the AND to produce a variable-position
      extraction.  Then the constant of 31 would be substituted in to produce
      a such a position.  */
 
@@ -5688,7 +5644,6 @@ expand_compound_operation (x)
   else
     /* Any other cases we can't handle.  */
     return x;
-    
 
   /* If we couldn't do this for some reason, return the original
      expression.  */
@@ -5722,9 +5677,11 @@ expand_field_assignment (x)
       if (GET_CODE (SET_DEST (x)) == STRICT_LOW_PART
          && GET_CODE (XEXP (SET_DEST (x), 0)) == SUBREG)
        {
+         int byte_offset = SUBREG_BYTE (XEXP (SET_DEST (x), 0));
+
          inner = SUBREG_REG (XEXP (SET_DEST (x), 0));
          len = GET_MODE_BITSIZE (GET_MODE (XEXP (SET_DEST (x), 0)));
-         pos = GEN_INT (BITS_PER_WORD * SUBREG_WORD (XEXP (SET_DEST (x), 0)));
+         pos = GEN_INT (BITS_PER_WORD * (byte_offset / UNITS_PER_WORD));
        }
       else if (GET_CODE (SET_DEST (x)) == ZERO_EXTRACT
               && GET_CODE (XEXP (SET_DEST (x), 1)) == CONST_INT)
@@ -5813,11 +5770,11 @@ expand_field_assignment (x)
        (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)),
+                                simplify_gen_unary (NOT, compute_mode,
+                                                    gen_binary (ASHIFT,
+                                                                compute_mode,
+                                                                mask, pos),
+                                                    compute_mode),
                                 inner),
                     gen_binary (ASHIFT, compute_mode,
                                 gen_binary (AND, compute_mode,
@@ -5841,7 +5798,7 @@ expand_field_assignment (x)
    code that understands the USE is this routine.  If it is not removed,
    it will cause the resulting insn not to match.
 
-   UNSIGNEDP is non-zero for an unsigned reference and zero for a 
+   UNSIGNEDP is non-zero for an unsigned reference and zero for a
    signed reference.
 
    IN_DEST is non-zero if this is a reference in the destination of a
@@ -5925,8 +5882,7 @@ make_extraction (mode, inner, pos, pos_rtx, len,
           && GET_CODE (inner) != MEM
           && (! in_dest
               || (GET_CODE (inner) == REG
-                  && (movstrict_optab->handlers[(int) tmode].insn_code
-                      != CODE_FOR_nothing))))
+                  && have_insn_for (STRICT_LOW_PART, tmode))))
          || (GET_CODE (inner) == MEM && pos_rtx == 0
              && (pos
                  % (STRICT_ALIGNMENT ? GET_MODE_ALIGNMENT (tmode)
@@ -5940,55 +5896,63 @@ make_extraction (mode, inner, pos, pos_rtx, len,
     {
       /* If INNER is a MEM, make a new MEM that encompasses just the desired
         field.  If the original and current mode are the same, we need not
-        adjust the offset.  Otherwise, we do if bytes big endian.  
+        adjust the offset.  Otherwise, we do if bytes big endian.
 
         If INNER is not a MEM, get a piece consisting of just the field
         of interest (in this case POS % BITS_PER_WORD must be 0).  */
 
       if (GET_CODE (inner) == MEM)
        {
-         int offset;
+         HOST_WIDE_INT offset;
+
          /* POS counts from lsb, but make OFFSET count in memory order.  */
          if (BYTES_BIG_ENDIAN)
            offset = (GET_MODE_BITSIZE (is_mode) - len - pos) / BITS_PER_UNIT;
          else
            offset = pos / BITS_PER_UNIT;
 
-         new = gen_rtx_MEM (tmode, plus_constant (XEXP (inner, 0), offset));
-         MEM_COPY_ATTRIBUTES (new, inner);
+         new = adjust_address_nv (inner, tmode, offset);
        }
       else if (GET_CODE (inner) == REG)
        {
          /* 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));
+           {
+             HOST_WIDE_INT final_word = pos / BITS_PER_WORD;
+
+             if (WORDS_BIG_ENDIAN
+                 && GET_MODE_SIZE (inner_mode) > UNITS_PER_WORD)
+               final_word = ((GET_MODE_SIZE (inner_mode)
+                              - GET_MODE_SIZE (tmode))
+                             / UNITS_PER_WORD) - final_word;
+
+             final_word *= UNITS_PER_WORD;
+             if (BYTES_BIG_ENDIAN &&
+                 GET_MODE_SIZE (inner_mode) > GET_MODE_SIZE (tmode))
+               final_word += (GET_MODE_SIZE (inner_mode)
+                              - GET_MODE_SIZE (tmode)) % UNITS_PER_WORD;
+
+             new = gen_rtx_SUBREG (tmode, inner, final_word);
+           }
          else
            new = inner;
        }
       else
        new = force_to_mode (inner, tmode,
                             len >= HOST_BITS_PER_WIDE_INT
-                            ? GET_MODE_MASK (tmode)
+                            ? ~(unsigned HOST_WIDE_INT) 0
                             : ((unsigned HOST_WIDE_INT) 1 << len) - 1,
                             NULL_RTX, 0);
 
-      /* If this extraction is going into the destination of a SET, 
+      /* If this extraction is going into the destination of a SET,
         make a STRICT_LOW_PART unless we made a MEM.  */
 
       if (in_dest)
        return (GET_CODE (new) == MEM ? new
                : (GET_CODE (new) != SUBREG
                   ? gen_rtx_CLOBBER (tmode, const0_rtx)
-                  : gen_rtx_combine (STRICT_LOW_PART, VOIDmode, new)));
+                  : gen_rtx_STRICT_LOW_PART (VOIDmode, new)));
 
       if (mode == tmode)
        return new;
@@ -5999,9 +5963,9 @@ make_extraction (mode, inner, pos, pos_rtx, len,
       if (flag_expensive_optimizations
          && (GET_MODE_BITSIZE (tmode) <= HOST_BITS_PER_WIDE_INT
              && ((nonzero_bits (new, tmode)
-                  & ~ (((unsigned HOST_WIDE_INT)
-                        GET_MODE_MASK (tmode))
-                       >> 1))
+                  & ~(((unsigned HOST_WIDE_INT)
+                       GET_MODE_MASK (tmode))
+                      >> 1))
                  == 0)))
        {
          rtx temp = gen_rtx_ZERO_EXTEND (mode, new);
@@ -6009,7 +5973,7 @@ make_extraction (mode, inner, pos, pos_rtx, len,
 
          /* Prefer ZERO_EXTENSION, since it gives more information to
             backends.  */
-         if (rtx_cost (temp, SET) < rtx_cost (temp1, SET))
+         if (rtx_cost (temp, SET) <= rtx_cost (temp1, SET))
            return temp;
          return temp1;
        }
@@ -6017,8 +5981,8 @@ make_extraction (mode, inner, pos, pos_rtx, len,
       /* Otherwise, sign- or zero-extend unless we already are in the
         proper mode.  */
 
-      return (gen_rtx_combine (unsignedp ? ZERO_EXTEND : SIGN_EXTEND,
-                              mode, new));
+      return (gen_rtx_fmt_e (unsignedp ? ZERO_EXTEND : SIGN_EXTEND,
+                            mode, new));
     }
 
   /* Unless this is a COMPARE or we have a funny memory reference,
@@ -6040,59 +6004,28 @@ make_extraction (mode, inner, pos, pos_rtx, len,
 
   /* Get the mode to use should INNER not be a MEM, the mode for the position,
      and the mode for the result.  */
-#ifdef HAVE_insv
-  if (in_dest)
+  if (in_dest && mode_for_extraction(EP_insv, -1) != MAX_MACHINE_MODE)
     {
-      wanted_inner_reg_mode
-       = insn_data[(int) CODE_FOR_insv].operand[0].mode;
-      if (wanted_inner_reg_mode == VOIDmode)
-       wanted_inner_reg_mode = word_mode;
-
-      pos_mode = insn_data[(int) CODE_FOR_insv].operand[2].mode;
-      if (pos_mode == VOIDmode)
-       pos_mode = word_mode;
-
-      extraction_mode = insn_data[(int) CODE_FOR_insv].operand[3].mode;
-      if (extraction_mode == VOIDmode)
-       extraction_mode = word_mode;
+      wanted_inner_reg_mode = mode_for_extraction (EP_insv, 0);
+      pos_mode = mode_for_extraction (EP_insv, 2);
+      extraction_mode = mode_for_extraction (EP_insv, 3);
     }
-#endif
 
-#ifdef HAVE_extzv
-  if (! in_dest && unsignedp)
+  if (! in_dest && unsignedp
+      && mode_for_extraction (EP_extzv, -1) != MAX_MACHINE_MODE)
     {
-      wanted_inner_reg_mode
-       = insn_data[(int) CODE_FOR_extzv].operand[1].mode;
-      if (wanted_inner_reg_mode == VOIDmode)
-       wanted_inner_reg_mode = word_mode;
-
-      pos_mode = insn_data[(int) CODE_FOR_extzv].operand[3].mode;
-      if (pos_mode == VOIDmode)
-       pos_mode = word_mode;
-
-      extraction_mode = insn_data[(int) CODE_FOR_extzv].operand[0].mode;
-      if (extraction_mode == VOIDmode)
-       extraction_mode = word_mode;
+      wanted_inner_reg_mode = mode_for_extraction (EP_extzv, 1);
+      pos_mode = mode_for_extraction (EP_extzv, 3);
+      extraction_mode = mode_for_extraction (EP_extzv, 0);
     }
-#endif
 
-#ifdef HAVE_extv
-  if (! in_dest && ! unsignedp)
+  if (! in_dest && ! unsignedp
+      && mode_for_extraction (EP_extv, -1) != MAX_MACHINE_MODE)
     {
-      wanted_inner_reg_mode
-       = insn_data[(int) CODE_FOR_extv].operand[1].mode;
-      if (wanted_inner_reg_mode == VOIDmode)
-       wanted_inner_reg_mode = word_mode;
-
-      pos_mode = insn_data[(int) CODE_FOR_extv].operand[3].mode;
-      if (pos_mode == VOIDmode)
-       pos_mode = word_mode;
-
-      extraction_mode = insn_data[(int) CODE_FOR_extv].operand[0].mode;
-      if (extraction_mode == VOIDmode)
-       extraction_mode = word_mode;
+      wanted_inner_reg_mode = mode_for_extraction (EP_extv, 1);
+      pos_mode = mode_for_extraction (EP_extv, 3);
+      extraction_mode = mode_for_extraction (EP_extv, 0);
     }
-#endif
 
   /* Never narrow an object, since that might not be safe.  */
 
@@ -6133,8 +6066,7 @@ make_extraction (mode, inner, pos, pos_rtx, len,
        pos = width - len - pos;
       else
        pos_rtx
-         = gen_rtx_combine (MINUS, GET_MODE (pos_rtx),
-                            GEN_INT (width - len), pos_rtx);
+         = gen_rtx_MINUS (GET_MODE (pos_rtx), GEN_INT (width - len), pos_rtx);
       /* POS may be less than 0 now, but we check for that below.
         Note that it can only be less than 0 if GET_CODE (inner) != MEM.  */
     }
@@ -6154,7 +6086,7 @@ make_extraction (mode, inner, pos, pos_rtx, len,
       /* The computations below will be correct if the machine is big
         endian in both bits and bytes or little endian in bits and bytes.
         If it is mixed, we must adjust.  */
-            
+
       /* If bytes are big endian and we had a paradoxical SUBREG, we must
         adjust OFFSET to compensate.  */
       if (BYTES_BIG_ENDIAN
@@ -6176,13 +6108,7 @@ make_extraction (mode, inner, pos, pos_rtx, len,
                  - GET_MODE_SIZE (wanted_inner_mode) - offset);
 
       if (offset != 0 || inner_mode != wanted_inner_mode)
-       {
-         rtx newmem = gen_rtx_MEM (wanted_inner_mode,
-                                   plus_constant (XEXP (inner, 0), offset));
-
-         MEM_COPY_ATTRIBUTES (newmem, inner);
-         inner = newmem;
-       }
+       inner = adjust_address_nv (inner, wanted_inner_mode, offset);
     }
 
   /* If INNER is not memory, we can always get it into the proper mode.  If we
@@ -6198,7 +6124,7 @@ make_extraction (mode, inner, pos, pos_rtx, len,
       inner = force_to_mode (inner, wanted_inner_mode,
                             pos_rtx
                             || len + orig_pos >= HOST_BITS_PER_WIDE_INT
-                            ? GET_MODE_MASK (wanted_inner_mode)
+                            ? ~(unsigned HOST_WIDE_INT) 0
                             : ((((unsigned HOST_WIDE_INT) 1 << len) - 1)
                                << orig_pos),
                             NULL_RTX, 0);
@@ -6209,7 +6135,7 @@ make_extraction (mode, inner, pos, pos_rtx, len,
   if (pos_rtx != 0
       && GET_MODE_SIZE (pos_mode) > GET_MODE_SIZE (GET_MODE (pos_rtx)))
     {
-      rtx temp = gen_rtx_combine (ZERO_EXTEND, pos_mode, pos_rtx);
+      rtx temp = gen_rtx_ZERO_EXTEND (pos_mode, pos_rtx);
 
       /* If we know that no extraneous bits are set, and that the high
         bit is not set, convert extraction to cheaper one - eighter
@@ -6218,14 +6144,14 @@ make_extraction (mode, inner, pos, pos_rtx, len,
       if (flag_expensive_optimizations
          && (GET_MODE_BITSIZE (GET_MODE (pos_rtx)) <= HOST_BITS_PER_WIDE_INT
              && ((nonzero_bits (pos_rtx, GET_MODE (pos_rtx))
-                  & ~ (((unsigned HOST_WIDE_INT)
-                        GET_MODE_MASK (GET_MODE (pos_rtx)))
-                       >> 1))
+                  & ~(((unsigned HOST_WIDE_INT)
+                       GET_MODE_MASK (GET_MODE (pos_rtx)))
+                      >> 1))
                  == 0)))
        {
          rtx temp1 = gen_rtx_SIGN_EXTEND (pos_mode, pos_rtx);
 
-         /* Preffer ZERO_EXTENSION, since it gives more information to
+         /* Prefer ZERO_EXTENSION, since it gives more information to
             backends.  */
          if (rtx_cost (temp1, SET) < rtx_cost (temp, SET))
            temp = temp1;
@@ -6246,7 +6172,7 @@ make_extraction (mode, inner, pos, pos_rtx, len,
     pos_rtx = GEN_INT (pos);
 
   /* Make the required operation.  See if we can use existing rtx.  */
-  new = gen_rtx_combine (unsignedp ? ZERO_EXTRACT : SIGN_EXTRACT,
+  new = gen_rtx_fmt_eee (unsignedp ? ZERO_EXTRACT : SIGN_EXTRACT,
                         extraction_mode, inner, GEN_INT (len), pos_rtx);
   if (! in_dest)
     new = gen_lowpart_for_combine (mode, new);
@@ -6280,7 +6206,7 @@ extract_left_shift (x, count)
 
     case NEG:  case NOT:
       if ((tem = extract_left_shift (XEXP (x, 0), count)) != 0)
-       return gen_unary (code, mode, mode, tem);
+       return simplify_gen_unary (code, mode, tem, mode);
 
       break;
 
@@ -6290,11 +6216,11 @@ extract_left_shift (x, count)
       if (GET_CODE (XEXP (x,1)) == CONST_INT
          && (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, 
+       return gen_binary (code, mode, tem,
                           GEN_INT (INTVAL (XEXP (x, 1)) >> count));
 
       break;
-      
+
     default:
       break;
     }
@@ -6308,7 +6234,7 @@ extract_left_shift (x, count)
 
    Return the new rtx, usually just X.
 
-   Also, for machines like the Vax that don't have logical shift insns,
+   Also, for machines like the VAX that don't have logical shift insns,
    try to convert logical to arithmetic shift operations in cases where
    they are equivalent.  This undoes the canonicalizations to logical
    shifts done elsewhere.
@@ -6357,9 +6283,9 @@ make_compound_operation (x, in_code)
          && INTVAL (XEXP (x, 1)) >= 0)
        {
          new = make_compound_operation (XEXP (x, 0), next_code);
-         new = gen_rtx_combine (MULT, mode, new,
-                                GEN_INT ((HOST_WIDE_INT) 1
-                                         << INTVAL (XEXP (x, 1))));
+         new = gen_rtx_MULT (mode, new,
+                             GEN_INT ((HOST_WIDE_INT) 1
+                                      << INTVAL (XEXP (x, 1))));
        }
       break;
 
@@ -6399,11 +6325,11 @@ make_compound_operation (x, in_code)
               && (i = exact_log2 (INTVAL (XEXP (x, 1)) + 1)) >= 0)
        {
          /* 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)));
+         new = gen_rtx_fmt_ee (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)));
          new = make_compound_operation (new, in_code);
        }
 
@@ -6425,10 +6351,9 @@ make_compound_operation (x, in_code)
       /* On machines without logical shifts, if the operand of the AND is
         a logical shift and our mask turns off all the propagated sign
         bits, we can replace the logical shift with an arithmetic shift.  */
-      else if (ashr_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing
-              && (lshr_optab->handlers[(int) mode].insn_code
-                  == CODE_FOR_nothing)
-              && GET_CODE (XEXP (x, 0)) == LSHIFTRT
+      else if (GET_CODE (XEXP (x, 0)) == LSHIFTRT
+              && !have_insn_for (LSHIFTRT, mode)
+              && have_insn_for (ASHIFTRT, mode)
               && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
               && INTVAL (XEXP (XEXP (x, 0), 1)) >= 0
               && INTVAL (XEXP (XEXP (x, 0), 1)) < HOST_BITS_PER_WIDE_INT
@@ -6439,10 +6364,10 @@ make_compound_operation (x, in_code)
          mask >>= INTVAL (XEXP (XEXP (x, 0), 1));
          if ((INTVAL (XEXP (x, 1)) & ~mask) == 0)
            SUBST (XEXP (x, 0),
-                  gen_rtx_combine (ASHIFTRT, mode,
-                                   make_compound_operation (XEXP (XEXP (x, 0), 0),
-                                                            next_code),
-                                   XEXP (XEXP (x, 0), 1)));
+                  gen_rtx_ASHIFTRT (mode,
+                                    make_compound_operation
+                                    (XEXP (XEXP (x, 0), 0), next_code),
+                                    XEXP (XEXP (x, 0), 1)));
        }
 
       /* If the constant is one less than a power of two, this might be
@@ -6469,15 +6394,15 @@ make_compound_operation (x, in_code)
     case LSHIFTRT:
       /* If the sign bit is known to be zero, replace this with an
         arithmetic shift.  */
-      if (ashr_optab->handlers[(int) mode].insn_code == CODE_FOR_nothing
-         && lshr_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing
+      if (have_insn_for (ASHIFTRT, mode)
+         && ! have_insn_for (LSHIFTRT, mode)
          && mode_width <= HOST_BITS_PER_WIDE_INT
          && (nonzero_bits (XEXP (x, 0), mode) & (1 << (mode_width - 1))) == 0)
        {
-         new = gen_rtx_combine (ASHIFTRT, mode,
-                                make_compound_operation (XEXP (x, 0),
-                                                         next_code),
-                                XEXP (x, 1));
+         new = gen_rtx_ASHIFTRT (mode,
+                                 make_compound_operation (XEXP (x, 0),
+                                                          next_code),
+                                 XEXP (x, 1));
          break;
        }
 
@@ -6499,13 +6424,14 @@ make_compound_operation (x, in_code)
                                 INTVAL (rhs) - INTVAL (XEXP (lhs, 1)),
                                 NULL_RTX, mode_width - INTVAL (rhs),
                                 code == LSHIFTRT, 0, in_code == COMPARE);
+         break;
        }
 
       /* See if we have operations between an ASHIFTRT and an ASHIFT.
         If so, try to merge the shifts into a SIGN_EXTEND.  We could
         also do this for some cases of SIGN_EXTRACT, but it doesn't
         seem worth the effort; the case checked for occurs on Alpha.  */
-      
+
       if (GET_RTX_CLASS (GET_CODE (lhs)) != 'o'
          && ! (GET_CODE (lhs) == SUBREG
                && (GET_RTX_CLASS (GET_CODE (SUBREG_REG (lhs))) == 'o'))
@@ -6515,7 +6441,7 @@ make_compound_operation (x, in_code)
        new = make_extraction (mode, make_compound_operation (new, next_code),
                               0, NULL_RTX, mode_width - INTVAL (rhs),
                               code == LSHIFTRT, 0, in_code == COMPARE);
-       
+
       break;
 
     case SUBREG:
@@ -6528,8 +6454,8 @@ make_compound_operation (x, in_code)
          && GET_MODE_SIZE (mode) < GET_MODE_SIZE (GET_MODE (tem))
          && subreg_lowpart_p (x))
        {
-         rtx newer = force_to_mode (tem, mode,
-                                    GET_MODE_MASK (mode), NULL_RTX, 0);
+         rtx newer = force_to_mode (tem, mode, ~(HOST_WIDE_INT) 0,
+                                    NULL_RTX, 0);
 
          /* If we have something other than a SUBREG, we might have
             done an expansion, so rerun outselves.  */
@@ -6550,13 +6476,13 @@ make_compound_operation (x, in_code)
          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));
+           tem = gen_rtx_fmt_e (GET_CODE (tem), mode, XEXP (tem, 0));
          else
            tem = gen_lowpart_for_combine (mode, XEXP (tem, 0));
          return tem;
        }
       break;
-      
+
     default:
       break;
     }
@@ -6580,9 +6506,9 @@ make_compound_operation (x, in_code)
 }
 \f
 /* Given M see if it is a value that would select a field of bits
-    within an item, but not the entire word.  Return -1 if not.
-    Otherwise, return the starting position of the field, where 0 is the
-    low-order bit.
+   within an item, but not the entire word.  Return -1 if not.
+   Otherwise, return the starting position of the field, where 0 is the
+   low-order bit.
 
    *PLEN is set to the length of the field.  */
 
@@ -6592,7 +6518,7 @@ get_pos_from_mask (m, plen)
      unsigned HOST_WIDE_INT *plen;
 {
   /* Get the bit number of the first 1 bit from the right, -1 if none.  */
-  int pos = exact_log2 (m & - m);
+  int pos = exact_log2 (m & -m);
   int len;
 
   if (pos < 0)
@@ -6618,7 +6544,7 @@ get_pos_from_mask (m, plen)
    Return a possibly simplified expression, but always convert X to
    MODE.  If X is a CONST_INT, AND the CONST_INT with MASK.
 
-   Also, if REG is non-zero and X is a register equal in value to REG, 
+   Also, if REG is non-zero and X is a register equal in value to REG,
    replace X with REG.
 
    If JUST_SELECT is nonzero, don't optimize by noticing that bits in MASK
@@ -6641,7 +6567,7 @@ 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. 
+     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.  */
@@ -6652,9 +6578,7 @@ force_to_mode (x, mode, mask, reg, just_select)
      that the operation is valid in MODE, in which case we do the operation
      in MODE.  */
   op_mode = ((GET_MODE_CLASS (mode) == GET_MODE_CLASS (GET_MODE (x))
-             && code_to_optab[(int) code] != 0
-             && (code_to_optab[(int) code]->handlers[(int) mode].insn_code
-                 != CODE_FOR_nothing))
+             && have_insn_for (code, mode))
             ? mode : GET_MODE (x));
 
   /* It is not valid to do a right-shift in a narrower mode
@@ -6676,7 +6600,7 @@ force_to_mode (x, mode, mask, reg, just_select)
                   : (((unsigned HOST_WIDE_INT) 1 << (floor_log2 (mask) + 1))
                      - 1));
   else
-    fuller_mask = ~ (HOST_WIDE_INT) 0;
+    fuller_mask = ~(HOST_WIDE_INT) 0;
 
   /* Determine what bits of X are guaranteed to be (non)zero.  */
   nonzero = nonzero_bits (x, mode);
@@ -6697,19 +6621,19 @@ force_to_mode (x, mode, mask, reg, just_select)
       if (width > 0 && width < HOST_BITS_PER_WIDE_INT
          && (cval & ((HOST_WIDE_INT) 1 << (width - 1))) != 0)
        cval |= (HOST_WIDE_INT) -1 << width;
-       
+
       return GEN_INT (cval);
     }
 
   /* If X is narrower than MODE and we want all the bits in X's mode, just
      get X in the proper mode.  */
   if (GET_MODE_SIZE (GET_MODE (x)) < GET_MODE_SIZE (mode)
-      && (GET_MODE_MASK (GET_MODE (x)) & ~ mask) == 0)
+      && (GET_MODE_MASK (GET_MODE (x)) & ~mask) == 0)
     return gen_lowpart_for_combine (mode, x);
 
   /* If we aren't changing the mode, X is not a SUBREG, and all zero bits in
      MASK are already known to be zero in X, we need not do anything.  */
-  if (GET_MODE (x) == mode && code != SUBREG && (~ mask & nonzero) == 0)
+  if (GET_MODE (x) == mode && code != SUBREG && (~mask & nonzero) == 0)
     return x;
 
   switch (code)
@@ -6724,7 +6648,7 @@ force_to_mode (x, mode, mask, reg, just_select)
         spanned the boundary of the MEM.  If we are now masking so it is
         within that boundary, we don't need the USE any more.  */
       if (! BITS_BIG_ENDIAN
-         && (mask & ~ GET_MODE_MASK (GET_MODE (XEXP (x, 0)))) == 0)
+         && (mask & ~GET_MODE_MASK (GET_MODE (XEXP (x, 0)))) == 0)
        return force_to_mode (XEXP (x, 0), mode, mask, reg, next_select);
       break;
 
@@ -6752,7 +6676,7 @@ force_to_mode (x, mode, mask, reg, just_select)
               < GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))))
              || (0 == (mask
                        & GET_MODE_MASK (GET_MODE (x))
-                       & ~ GET_MODE_MASK (GET_MODE (SUBREG_REG (x)))))))
+                       & ~GET_MODE_MASK (GET_MODE (SUBREG_REG (x)))))))
        return force_to_mode (SUBREG_REG (x), mode, mask, reg, next_select);
       break;
 
@@ -6784,7 +6708,7 @@ force_to_mode (x, mode, mask, reg, just_select)
              && GET_MODE_BITSIZE (GET_MODE (x)) <= HOST_BITS_PER_WIDE_INT)
            {
              HOST_WIDE_INT cval = (INTVAL (XEXP (x, 1))
-                                   | (GET_MODE_MASK (GET_MODE (x)) & ~ mask));
+                                   | (GET_MODE_MASK (GET_MODE (x)) & ~mask));
              int width = GET_MODE_BITSIZE (GET_MODE (x));
              rtx y;
 
@@ -6829,23 +6753,23 @@ force_to_mode (x, mode, mask, reg, just_select)
                && (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 & ~ smask) == 0
-                   && ((INTVAL (XEXP (x, 1)) - STACK_BIAS) & ~ smask) != 0)
+               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 & ~smask) == 0
+                   && ((INTVAL (XEXP (x, 1)) - STACK_BIAS) & ~smask) != 0)
                  return force_to_mode (plus_constant (XEXP (x, 0),
-                                                      ((INTVAL (XEXP (x, 1)) -
+                                                      ((INTVAL (XEXP (x, 1)) -
                                                         STACK_BIAS) & smask)
                                                       + STACK_BIAS),
-                                       mode, smask, reg, next_select);
-              }
+                                       mode, smask, reg, next_select);
+             }
 #endif
-           if ((nonzero_bits (XEXP (x, 0), mode) & ~ smask) == 0
-               && (INTVAL (XEXP (x, 1)) & ~ smask) != 0)
+           if ((nonzero_bits (XEXP (x, 0), mode) & ~smask) == 0
+               && (INTVAL (XEXP (x, 1)) & ~smask) != 0)
              return force_to_mode (plus_constant (XEXP (x, 0),
-                                                  (INTVAL (XEXP (x, 1))
+                                                  (INTVAL (XEXP (x, 1))
                                                    & smask)),
                                    mode, smask, reg, next_select);
          }
@@ -6864,18 +6788,23 @@ force_to_mode (x, mode, mask, reg, just_select)
       /* If X is (minus C Y) where C's least set bit is larger than any bit
         in the mask, then we may replace with (neg Y).  */
       if (GET_CODE (XEXP (x, 0)) == CONST_INT
-         && (INTVAL (XEXP (x, 0)) & -INTVAL (XEXP (x, 0))) > mask)
+         && (((unsigned HOST_WIDE_INT) (INTVAL (XEXP (x, 0))
+                                       & -INTVAL (XEXP (x, 0))))
+             > mask))
        {
-         x = gen_unary (NEG, GET_MODE (x), GET_MODE (x), XEXP (x, 1));
+         x = simplify_gen_unary (NEG, GET_MODE (x), XEXP (x, 1),
+                                 GET_MODE (x));
          return force_to_mode (x, mode, mask, reg, next_select);
        }
 
       /* Similarly, if C contains every bit in the mask, then we may
         replace with (not Y).  */
       if (GET_CODE (XEXP (x, 0)) == CONST_INT
-          && (INTVAL (XEXP (x, 0)) | mask) == INTVAL (XEXP (x, 0)))
+         && ((INTVAL (XEXP (x, 0)) | (HOST_WIDE_INT) mask)
+             == INTVAL (XEXP (x, 0))))
        {
-         x = gen_unary (NOT, GET_MODE (x), GET_MODE (x), XEXP (x, 1));
+         x = simplify_gen_unary (NOT, GET_MODE (x),
+                                 XEXP (x, 1), GET_MODE (x));
          return force_to_mode (x, mode, mask, reg, next_select);
        }
 
@@ -6898,10 +6827,10 @@ force_to_mode (x, mode, mask, reg, just_select)
               + floor_log2 (INTVAL (XEXP (x, 1))))
              < GET_MODE_BITSIZE (GET_MODE (x)))
          && (INTVAL (XEXP (x, 1))
-             & ~ nonzero_bits (XEXP (x, 0), GET_MODE (x))) == 0)
+             & ~nonzero_bits (XEXP (x, 0), GET_MODE (x))) == 0)
        {
          temp = GEN_INT ((INTVAL (XEXP (x, 1)) & mask)
-                             << INTVAL (XEXP (XEXP (x, 0), 1)));
+                         << INTVAL (XEXP (XEXP (x, 0), 1)));
          temp = gen_binary (GET_CODE (x), GET_MODE (x),
                             XEXP (XEXP (x, 0), 0), temp);
          x = gen_binary (LSHIFTRT, GET_MODE (x), temp,
@@ -6927,7 +6856,7 @@ force_to_mode (x, mode, mask, reg, just_select)
       if (GET_CODE (op1) == CONST_INT && (code == IOR || code == XOR)
          && (INTVAL (op1) & mask) != 0)
        op1 = GEN_INT (INTVAL (op1) & mask);
-        
+
       if (op_mode != GET_MODE (x) || op0 != XEXP (x, 0) || op1 != XEXP (x, 1))
        x = gen_binary (code, op_mode, op0, op1);
       break;
@@ -6946,7 +6875,7 @@ force_to_mode (x, mode, mask, reg, just_select)
                && (nonzero_bits (XEXP (x, 1), GET_MODE (XEXP (x, 1)))
                    < (unsigned HOST_WIDE_INT) GET_MODE_BITSIZE (mode))))
        break;
-       
+
       /* If the shift count is a constant and we can do arithmetic in
         the mode of the shift, refine which bits we need.  Otherwise, use the
         conservative form of the mask.  */
@@ -6963,7 +6892,7 @@ force_to_mode (x, mode, mask, reg, just_select)
                                                    mask, reg, next_select));
 
       if (op_mode != GET_MODE (x) || op0 != XEXP (x, 0))
-       x =  gen_binary (code, op_mode, op0, XEXP (x, 1));
+       x = gen_binary (code, op_mode, op0, XEXP (x, 1));
       break;
 
     case LSHIFTRT:
@@ -6985,7 +6914,7 @@ force_to_mode (x, mode, mask, reg, just_select)
             in the mode of the shift and INNER_MASK is no wider than the
             width of OP_MODE.  */
          if (GET_MODE_BITSIZE (op_mode) > HOST_BITS_PER_WIDE_INT
-             || (inner_mask & ~ GET_MODE_MASK (op_mode)) != 0)
+             || (inner_mask & ~GET_MODE_MASK (op_mode)) != 0)
            op_mode = GET_MODE (x);
 
          inner = force_to_mode (inner, op_mode, inner_mask, reg, next_select);
@@ -7045,7 +6974,7 @@ force_to_mode (x, mode, mask, reg, just_select)
 
          if (GET_MODE_BITSIZE (GET_MODE (x)) > HOST_BITS_PER_WIDE_INT)
            {
-             nonzero = ~ (HOST_WIDE_INT) 0;
+             nonzero = ~(HOST_WIDE_INT) 0;
 
              /* GET_MODE_BITSIZE (GET_MODE (x)) - INTVAL (XEXP (x, 1))
                 is the number of bits a full-width mask would have set.
@@ -7064,7 +6993,7 @@ force_to_mode (x, mode, mask, reg, just_select)
              nonzero >>= INTVAL (XEXP (x, 1));
            }
 
-         if ((mask & ~ nonzero) == 0
+         if ((mask & ~nonzero) == 0
              || (i = exact_log2 (mask)) >= 0)
            {
              x = simplify_shift_const
@@ -7119,7 +7048,7 @@ force_to_mode (x, mode, mask, reg, just_select)
                                  INTVAL (temp), reg, next_select));
        }
       break;
-       
+
     case NEG:
       /* If we just want the low-order bit, the NEG isn't needed since it
         won't change the low-order bit.    */
@@ -7160,14 +7089,14 @@ force_to_mode (x, mode, mask, reg, just_select)
                                     force_to_mode (XEXP (x, 0), mode, mask,
                                                    reg, next_select));
       if (op_mode != GET_MODE (x) || op0 != XEXP (x, 0))
-       x = gen_unary (code, op_mode, op_mode, op0);
+       x = simplify_gen_unary (code, op_mode, op0, op_mode);
       break;
 
     case NE:
       /* (and (ne FOO 0) CONST) can be (and FOO CONST) if CONST is included
         in STORE_FLAG_VALUE and FOO has a single bit that might be nonzero,
         which is equal to STORE_FLAG_VALUE.  */
-      if ((mask & ~ STORE_FLAG_VALUE) == 0 && XEXP (x, 1) == const0_rtx
+      if ((mask & ~STORE_FLAG_VALUE) == 0 && XEXP (x, 1) == const0_rtx
          && exact_log2 (nonzero_bits (XEXP (x, 0), mode)) >= 0
          && nonzero_bits (XEXP (x, 0), mode) == STORE_FLAG_VALUE)
        return force_to_mode (XEXP (x, 0), mode, mask, reg, next_select);
@@ -7187,7 +7116,7 @@ force_to_mode (x, mode, mask, reg, just_select)
                                      force_to_mode (XEXP (x, 2), mode,
                                                     mask, reg,next_select)));
       break;
-      
+
     default:
       break;
     }
@@ -7227,8 +7156,9 @@ if_then_else_cond (x, ptrue, pfalse)
   else if (GET_RTX_CLASS (code) == '1'
           && (cond0 = if_then_else_cond (XEXP (x, 0), &true0, &false0)) != 0)
     {
-      *ptrue = gen_unary (code, mode, GET_MODE (XEXP (x, 0)), true0);
-      *pfalse = gen_unary (code, mode, GET_MODE (XEXP (x, 0)), false0);
+      *ptrue = simplify_gen_unary (code, mode, true0, GET_MODE (XEXP (x, 0)));
+      *pfalse = simplify_gen_unary (code, mode, false0,
+                                   GET_MODE (XEXP (x, 0)));
       return cond0;
     }
 
@@ -7268,7 +7198,7 @@ if_then_else_cond (x, ptrue, pfalse)
 
       if ((STORE_FLAG_VALUE == 1 || STORE_FLAG_VALUE == -1)
          && (code == PLUS || code == IOR || code == XOR || code == MINUS
-          || code == UMAX)
+             || code == UMAX)
          && GET_CODE (XEXP (x, 0)) == MULT && GET_CODE (XEXP (x, 1)) == MULT)
        {
          rtx op0 = XEXP (XEXP (x, 0), 1);
@@ -7279,20 +7209,21 @@ if_then_else_cond (x, ptrue, pfalse)
 
          if (GET_RTX_CLASS (GET_CODE (cond0)) == '<'
              && GET_RTX_CLASS (GET_CODE (cond1)) == '<'
-             && reversible_comparison_p (cond1)
-             && ((GET_CODE (cond0) == reverse_condition (GET_CODE (cond1))
+             && ((GET_CODE (cond0) == combine_reversed_comparison_code (cond1)
                   && rtx_equal_p (XEXP (cond0, 0), XEXP (cond1, 0))
                   && rtx_equal_p (XEXP (cond0, 1), XEXP (cond1, 1)))
                  || ((swap_condition (GET_CODE (cond0))
-                      == reverse_condition (GET_CODE (cond1)))
+                      == combine_reversed_comparison_code (cond1))
                      && rtx_equal_p (XEXP (cond0, 0), XEXP (cond1, 1))
                      && rtx_equal_p (XEXP (cond0, 1), XEXP (cond1, 0))))
              && ! side_effects_p (x))
            {
              *ptrue = gen_binary (MULT, mode, op0, const_true_rtx);
-             *pfalse = gen_binary (MULT, mode, 
-                                   (code == MINUS 
-                                    ? gen_unary (NEG, mode, mode, op1) : op1),
+             *pfalse = gen_binary (MULT, mode,
+                                   (code == MINUS
+                                    ? simplify_gen_unary (NEG, mode, op1,
+                                                          mode)
+                                    : op1),
                                    const_true_rtx);
              return cond0;
            }
@@ -7309,12 +7240,11 @@ if_then_else_cond (x, ptrue, pfalse)
 
          if (GET_RTX_CLASS (GET_CODE (cond0)) == '<'
              && GET_RTX_CLASS (GET_CODE (cond1)) == '<'
-             && reversible_comparison_p (cond1)
-             && ((GET_CODE (cond0) == reverse_condition (GET_CODE (cond1))
+             && ((GET_CODE (cond0) == combine_reversed_comparison_code (cond1)
                   && rtx_equal_p (XEXP (cond0, 0), XEXP (cond1, 0))
                   && rtx_equal_p (XEXP (cond0, 1), XEXP (cond1, 1)))
                  || ((swap_condition (GET_CODE (cond0))
-                      == reverse_condition (GET_CODE (cond1)))
+                      == combine_reversed_comparison_code (cond1))
                      && rtx_equal_p (XEXP (cond0, 0), XEXP (cond1, 1))
                      && rtx_equal_p (XEXP (cond0, 1), XEXP (cond1, 0))))
              && ! side_effects_p (x))
@@ -7342,27 +7272,16 @@ if_then_else_cond (x, ptrue, pfalse)
        return cond0;
     }
 
-  /* If X is a normal SUBREG with both inner and outer modes integral,
-     we can narrow both the true and false values of the inner expression,
-     if there is a condition.  */
-  else if (code == SUBREG && GET_MODE_CLASS (mode) == MODE_INT
-          && GET_MODE_CLASS (GET_MODE (SUBREG_REG (x))) == MODE_INT
-          && GET_MODE_SIZE (mode) <= GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)))
+  /* If X is a SUBREG, we can narrow both the true and false values
+     if the inner expression, if there is a condition.  */
+  else if (code == SUBREG
           && 0 != (cond0 = if_then_else_cond (SUBREG_REG (x),
                                               &true0, &false0)))
     {
-      if ((GET_CODE (SUBREG_REG (x)) == REG
-          || GET_CODE (SUBREG_REG (x)) == MEM
-          || CONSTANT_P (SUBREG_REG (x)))
-         && GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))) > UNITS_PER_WORD
-         && (WORDS_BIG_ENDIAN || SUBREG_WORD (x) != 0))
-       {
-         true0 = operand_subword (true0, SUBREG_WORD (x), 0, mode);
-         false0 = operand_subword (false0, SUBREG_WORD (x), 0, mode);
-       }
-      *ptrue = force_to_mode (true0, mode, ~(HOST_WIDE_INT) 0, NULL_RTX, 0);
-      *pfalse
-       = force_to_mode (false0, mode, ~(HOST_WIDE_INT) 0, NULL_RTX, 0);
+      *ptrue = simplify_gen_subreg (mode, true0,
+                                   GET_MODE (SUBREG_REG (x)), SUBREG_BYTE (x));
+      *pfalse = simplify_gen_subreg (mode, false0,
+                                    GET_MODE (SUBREG_REG (x)), SUBREG_BYTE (x));
 
       return cond0;
     }
@@ -7373,7 +7292,15 @@ if_then_else_cond (x, ptrue, pfalse)
           || ((cond0 = get_last_value (x)) != 0 && CONSTANT_P (cond0)))
     ;
 
-  /* If X is known to be either 0 or -1, those are the true and 
+  /* If we're in BImode, canonicalize on 0 and STORE_FLAG_VALUE, as that
+     will be least confusing to the rest of the compiler.  */
+  else if (mode == BImode)
+    {
+      *ptrue = GEN_INT (STORE_FLAG_VALUE), *pfalse = const0_rtx;
+      return x;
+    }
+
+  /* If X is known to be either 0 or -1, those are the true and
      false values when testing X.  */
   else if (x == constm1_rtx || x == const0_rtx
           || (mode != VOIDmode
@@ -7419,7 +7346,9 @@ known_cond (x, cond, reg, val)
   if (side_effects_p (x))
     return x;
 
-  if (cond == EQ && rtx_equal_p (x, reg))
+  if (cond == EQ && rtx_equal_p (x, reg) && !FLOAT_MODE_P (cond))
+    return val;
+  if (cond == UNEQ && rtx_equal_p (x, reg))
     return val;
 
   /* If X is (abs REG) and we know something about REG's relationship
@@ -7431,8 +7360,9 @@ known_cond (x, cond, reg, val)
       case GE:  case GT:  case EQ:
        return XEXP (x, 0);
       case LT:  case LE:
-       return gen_unary (NEG, GET_MODE (XEXP (x, 0)), GET_MODE (XEXP (x, 0)),
-                         XEXP (x, 0));
+       return simplify_gen_unary (NEG, GET_MODE (XEXP (x, 0)),
+                                  XEXP (x, 0),
+                                  GET_MODE (XEXP (x, 0)));
       default:
        break;
       }
@@ -7452,7 +7382,7 @@ known_cond (x, cond, reg, val)
              if (comparison_dominates_p (cond, code))
                return const_true_rtx;
 
-             code = reverse_condition (code);
+             code = combine_reversed_comparison_code (x);
              if (code != UNKNOWN
                  && comparison_dominates_p (cond, code))
                return const0_rtx;
@@ -7464,7 +7394,12 @@ known_cond (x, cond, reg, val)
            {
              int unsignedp = (code == UMIN || code == UMAX);
 
-             if (code == SMAX || code == UMAX)
+             /* Do not reverse the condition when it is NE or EQ.
+                This is because we cannot conclude anything about
+                the value of 'SMAX (x, y)' when x is not equal to y,
+                but we can when x equals y.  */
+             if ((code == SMAX || code == UMAX)
+                 && ! (cond == EQ || cond == NE))
                cond = reverse_condition (cond);
 
              switch (cond)
@@ -7573,7 +7508,7 @@ make_field_assignment (x)
 
   else if (GET_CODE (src) == AND && GET_CODE (XEXP (src, 0)) == SUBREG
           && subreg_lowpart_p (XEXP (src, 0))
-          && (GET_MODE_SIZE (GET_MODE (XEXP (src, 0))) 
+          && (GET_MODE_SIZE (GET_MODE (XEXP (src, 0)))
               < GET_MODE_SIZE (GET_MODE (SUBREG_REG (XEXP (src, 0)))))
           && GET_CODE (SUBREG_REG (XEXP (src, 0))) == ROTATE
           && INTVAL (XEXP (SUBREG_REG (XEXP (src, 0)), 0)) == -2
@@ -7625,7 +7560,7 @@ make_field_assignment (x)
   else
     return x;
 
-  pos = get_pos_from_mask ((~ c1) & GET_MODE_MASK (GET_MODE (dest)), &len);
+  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 (dest)) > HOST_BITS_PER_WIDE_INT
       || (c1 & nonzero_bits (other, GET_MODE (dest))) != 0)
@@ -7637,7 +7572,7 @@ make_field_assignment (x)
 
   /* The mode to use for the source is the mode of the assignment, or of
      what is inside a possible STRICT_LOW_PART.  */
-  mode = (GET_CODE (assign) == STRICT_LOW_PART 
+  mode = (GET_CODE (assign) == STRICT_LOW_PART
          ? GET_MODE (XEXP (assign, 0)) : GET_MODE (assign));
 
   /* Shift OTHER right POS places and make it the source, restricting it
@@ -7647,11 +7582,11 @@ make_field_assignment (x)
                                             GET_MODE (src), other, pos),
                       mode,
                       GET_MODE_BITSIZE (mode) >= HOST_BITS_PER_WIDE_INT
-                      ? GET_MODE_MASK (mode)
+                      ? ~(unsigned HOST_WIDE_INT) 0
                       : ((unsigned HOST_WIDE_INT) 1 << len) - 1,
                       dest, 0);
 
-  return gen_rtx_combine (SET, VOIDmode, assign, src);
+  return gen_rtx_SET (VOIDmode, assign, src);
 }
 \f
 /* See if X is of the form (+ (* a c) (* b c)) and convert to (* (+ a b) c)
@@ -7714,7 +7649,7 @@ apply_distributive_law (x)
 
     case SUBREG:
       /* Non-paradoxical SUBREGs distributes over all operations, provided
-        the inner modes and word numbers are the same, this is an extraction
+        the inner modes and byte offsets are the same, this is an extraction
         of a low-order part, we don't convert an fp operation to int or
         vice versa, and we would not be converting a single-word
         operation into a multi-word operation.  The latter test is not
@@ -7725,7 +7660,7 @@ apply_distributive_law (x)
         We produce the result slightly differently in this case.  */
 
       if (GET_MODE (SUBREG_REG (lhs)) != GET_MODE (SUBREG_REG (rhs))
-         || SUBREG_WORD (lhs) != SUBREG_WORD (rhs)
+         || SUBREG_BYTE (lhs) != SUBREG_BYTE (rhs)
          || ! subreg_lowpart_p (lhs)
          || (GET_MODE_CLASS (GET_MODE (lhs))
              != GET_MODE_CLASS (GET_MODE (SUBREG_REG (lhs))))
@@ -7768,7 +7703,7 @@ apply_distributive_law (x)
   if (code == XOR && inner_code == IOR)
     {
       inner_code = AND;
-      other = gen_unary (NOT, GET_MODE (x), GET_MODE (x), other);
+      other = simplify_gen_unary (NOT, GET_MODE (x), other, GET_MODE (x));
     }
 
   /* We may be able to continuing distributing the result, so call
@@ -7825,7 +7760,7 @@ simplify_and_const_int (x, mode, varop, constop)
   if (GET_CODE (varop) == NEG && nonzero_bits (XEXP (varop, 0), mode) == 1
       && (i = exact_log2 (constop)) >= 0)
     return simplify_shift_const (NULL_RTX, ASHIFT, mode, XEXP (varop, 0), i);
-                                
+
   /* If VAROP is an IOR or XOR, apply the AND to both branches of the IOR
      or XOR, then try to apply the distributive law.  This may eliminate
      operations if either branch can be simplified because of the AND.
@@ -7919,7 +7854,7 @@ nonzero_bits (x, mode)
 
 #ifndef WORD_REGISTER_OPERATIONS
   /* If MODE is wider than X, but both are a single word for both the host
-     and target machines, we can compute this from which bits of the 
+     and target machines, we can compute this from which bits of the
      object might be nonzero in its own mode, taking into account the fact
      that on many CISC machines, accessing an object in a wider mode
      causes the high-order bits to become undefined.  So they are
@@ -7931,7 +7866,7 @@ nonzero_bits (x, mode)
       && GET_MODE_BITSIZE (mode) > GET_MODE_BITSIZE (GET_MODE (x)))
     {
       nonzero &= nonzero_bits (x, GET_MODE (x));
-      nonzero |= GET_MODE_MASK (mode) & ~ GET_MODE_MASK (GET_MODE (x));
+      nonzero |= GET_MODE_MASK (mode) & ~GET_MODE_MASK (GET_MODE (x));
       return nonzero;
     }
 #endif
@@ -7940,11 +7875,11 @@ nonzero_bits (x, mode)
   switch (code)
     {
     case REG:
-#ifdef POINTERS_EXTEND_UNSIGNED
+#if defined(POINTERS_EXTEND_UNSIGNED) && !defined(HAVE_ptr_extend)
       /* If pointers extend unsigned and this is a pointer in Pmode, say that
         all the bits above ptr_mode are known to be zero.  */
       if (POINTERS_EXTEND_UNSIGNED && GET_MODE (x) == Pmode
-         && REGNO_POINTER_FLAG (REGNO (x)))
+         && REG_POINTER (x))
        nonzero &= GET_MODE_MASK (ptr_mode);
 #endif
 
@@ -7966,7 +7901,7 @@ nonzero_bits (x, mode)
               && REGNO (x) <= LAST_VIRTUAL_REGISTER))
 #ifdef STACK_BIAS
          && !STACK_BIAS
-#endif       
+#endif
              )
        {
          int sp_alignment = STACK_BOUNDARY / BITS_PER_UNIT;
@@ -7979,7 +7914,7 @@ nonzero_bits (x, mode)
          /* We must return here, otherwise we may get a worse result from
             one of the choices below.  There is nothing useful below as
             far as the stack pointer is concerned.  */
-         return nonzero &= ~ (sp_alignment - 1);
+         return nonzero &= ~(sp_alignment - 1);
        }
 #endif
 
@@ -7993,7 +7928,7 @@ nonzero_bits (x, mode)
          && (reg_last_set_label[REGNO (x)] == label_tick
              || (REGNO (x) >= FIRST_PSEUDO_REGISTER
                  && REG_N_SETS (REGNO (x)) == 1
-                 && ! REGNO_REG_SET_P (BASIC_BLOCK (0)->global_live_at_start, 
+                 && ! REGNO_REG_SET_P (BASIC_BLOCK (0)->global_live_at_start,
                                        REGNO (x))))
          && INSN_CUID (reg_last_set[REGNO (x)]) < subst_low_cuid)
        return reg_last_set_nonzero_bits[REGNO (x)];
@@ -8007,7 +7942,7 @@ nonzero_bits (x, mode)
             constant that would appear negative in the mode of X,
             sign-extend it for use in reg_nonzero_bits because some
             machines (maybe most) will actually do the sign-extension
-            and this is the conservative approach. 
+            and this is the conservative approach.
 
             ??? For 2.5, try to tighten up the MD files in this regard
             instead of this kludge.  */
@@ -8050,10 +7985,12 @@ nonzero_bits (x, mode)
       break;
 
     case EQ:  case NE:
-    case GT:  case GTU:
-    case LT:  case LTU:
-    case GE:  case GEU:
-    case LE:  case LEU:
+    case UNEQ:  case LTGT:
+    case GT:  case GTU:  case UNGT:
+    case LT:  case LTU:  case UNLT:
+    case GE:  case GEU:  case UNGE:
+    case LE:  case LEU:  case UNLE:
+    case UNORDERED: case ORDERED:
 
       /* If this produces an integer result, we know which bits are set.
         Code here used to clear bits outside the mode of X, but that is
@@ -8074,7 +8011,7 @@ nonzero_bits (x, mode)
 #endif
 
       if (GET_MODE_SIZE (GET_MODE (x)) < mode_width)
-       nonzero |= (GET_MODE_MASK (mode) & ~ GET_MODE_MASK (GET_MODE (x)));
+       nonzero |= (GET_MODE_MASK (mode) & ~GET_MODE_MASK (GET_MODE (x)));
       break;
 
     case ABS:
@@ -8109,7 +8046,7 @@ nonzero_bits (x, mode)
              & (((HOST_WIDE_INT) 1
                  << (GET_MODE_BITSIZE (GET_MODE (XEXP (x, 0))) - 1))))
            inner_nz |= (GET_MODE_MASK (mode)
-                         & ~ GET_MODE_MASK (GET_MODE (XEXP (x, 0))));
+                        & ~GET_MODE_MASK (GET_MODE (XEXP (x, 0))));
        }
 
       nonzero &= inner_nz;
@@ -8153,20 +8090,20 @@ nonzero_bits (x, mode)
          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)
+               && (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);
+               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   
+#endif
            result_width = MAX (width0, width1) + 1;
            result_low = MIN (low0, low1);
            break;
@@ -8178,18 +8115,26 @@ nonzero_bits (x, mode)
            result_low = low0 + low1;
            break;
          case DIV:
+           if (width1 == 0)
+             break;
            if (! op0_maybe_minusp && ! op1_maybe_minusp)
              result_width = width0;
            break;
          case UDIV:
+           if (width1 == 0)
+             break;
            result_width = width0;
            break;
          case MOD:
+           if (width1 == 0)
+             break;
            if (! op0_maybe_minusp && ! op1_maybe_minusp)
              result_width = MIN (width0, width1);
            result_low = MIN (low0, low1);
            break;
          case UMOD:
+           if (width1 == 0)
+             break;
            result_width = MIN (width0, width1);
            result_low = MIN (low0, low1);
            break;
@@ -8201,7 +8146,17 @@ nonzero_bits (x, mode)
          nonzero &= ((HOST_WIDE_INT) 1 << result_width) - 1;
 
        if (result_low > 0)
-         nonzero &= ~ (((HOST_WIDE_INT) 1 << result_low) - 1);
+         nonzero &= ~(((HOST_WIDE_INT) 1 << result_low) - 1);
+
+#ifdef POINTERS_EXTEND_UNSIGNED
+       /* If pointers extend unsigned and this is an addition or subtraction
+          to a pointer in Pmode, all the bits above ptr_mode are known to be
+          zero.  */
+       if (POINTERS_EXTEND_UNSIGNED > 0 && GET_MODE (x) == Pmode
+           && (code == PLUS || code == MINUS)
+           && GET_CODE (XEXP (x, 0)) == REG && REG_POINTER (XEXP (x, 0)))
+         nonzero &= GET_MODE_MASK (ptr_mode);
+#endif
       }
       break;
 
@@ -8246,7 +8201,7 @@ nonzero_bits (x, mode)
              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))));
+                           & ~GET_MODE_MASK (GET_MODE (SUBREG_REG (x))));
            }
        }
       break;
@@ -8274,7 +8229,7 @@ nonzero_bits (x, mode)
          unsigned HOST_WIDE_INT outer = 0;
 
          if (mode_width > width)
-           outer = (op_nonzero & nonzero & ~ mode_mask);
+           outer = (op_nonzero & nonzero & ~mode_mask);
 
          if (code == LSHIFTRT)
            inner >>= count;
@@ -8307,7 +8262,7 @@ nonzero_bits (x, mode)
       nonzero &= (nonzero_bits (XEXP (x, 1), mode)
                  | nonzero_bits (XEXP (x, 2), mode));
       break;
-      
+
     default:
       break;
     }
@@ -8353,7 +8308,7 @@ num_sign_bit_copies (x, mode)
       return MAX (1,
                  num0 - (int) (GET_MODE_BITSIZE (GET_MODE (x)) - bitwidth));
     }
-     
+
   if (GET_MODE (x) != VOIDmode && bitwidth > GET_MODE_BITSIZE (GET_MODE (x)))
     {
 #ifndef WORD_REGISTER_OPERATIONS
@@ -8378,11 +8333,11 @@ num_sign_bit_copies (x, mode)
     {
     case REG:
 
-#ifdef POINTERS_EXTEND_UNSIGNED
+#if defined(POINTERS_EXTEND_UNSIGNED) && !defined(HAVE_ptr_extend)
       /* If pointers extend signed and this is a pointer in Pmode, say that
         all the bits above ptr_mode are known to be sign bit copies.  */
       if (! POINTERS_EXTEND_UNSIGNED && GET_MODE (x) == Pmode && mode == Pmode
-         && REGNO_POINTER_FLAG (REGNO (x)))
+         && REG_POINTER (x))
        return GET_MODE_BITSIZE (Pmode) - GET_MODE_BITSIZE (ptr_mode) + 1;
 #endif
 
@@ -8396,7 +8351,7 @@ num_sign_bit_copies (x, mode)
          && INSN_CUID (reg_last_set[REGNO (x)]) < subst_low_cuid)
        return reg_last_set_sign_bit_copies[REGNO (x)];
 
-      tem =  get_last_value (x);
+      tem = get_last_value (x);
       if (tem != 0)
        return num_sign_bit_copies (tem, mode);
 
@@ -8419,7 +8374,7 @@ num_sign_bit_copies (x, mode)
       nonzero = INTVAL (x) & GET_MODE_MASK (mode);
       if (bitwidth <= HOST_BITS_PER_WIDE_INT
          && (nonzero & ((HOST_WIDE_INT) 1 << (bitwidth - 1))) != 0)
-       nonzero = (~ nonzero) & GET_MODE_MASK (mode);
+       nonzero = (~nonzero) & GET_MODE_MASK (mode);
 
       return (nonzero == 0 ? bitwidth : bitwidth - floor_log2 (nonzero) - 1);
 
@@ -8435,7 +8390,7 @@ num_sign_bit_copies (x, mode)
                      - (int) GET_MODE_BITSIZE (GET_MODE (x)) + 1,
                      num0);
        }
-                
+
       /* For a smaller object, just ignore the high bits.  */
       if (bitwidth <= GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (x))))
        {
@@ -8470,7 +8425,7 @@ num_sign_bit_copies (x, mode)
        return MAX (1, (int) bitwidth - INTVAL (XEXP (x, 1)));
       break;
 
-    case SIGN_EXTEND: 
+    case SIGN_EXTEND:
       return (bitwidth - GET_MODE_BITSIZE (GET_MODE (XEXP (x, 0)))
              + num_sign_bit_copies (XEXP (x, 0), VOIDmode));
 
@@ -8488,7 +8443,8 @@ num_sign_bit_copies (x, mode)
         of sign bit copies, we can just subtract that amount from the
         number.  */
       if (GET_CODE (XEXP (x, 1)) == CONST_INT
-         && INTVAL (XEXP (x, 1)) >= 0 && INTVAL (XEXP (x, 1)) < bitwidth)
+         && INTVAL (XEXP (x, 1)) >= 0
+         && INTVAL (XEXP (x, 1)) < (int) bitwidth)
        {
          num0 = num_sign_bit_copies (XEXP (x, 0), mode);
          return MAX (1, num0 - (code == ROTATE ? INTVAL (XEXP (x, 1))
@@ -8540,8 +8496,21 @@ num_sign_bit_copies (x, mode)
 
       num0 = num_sign_bit_copies (XEXP (x, 0), mode);
       num1 = num_sign_bit_copies (XEXP (x, 1), mode);
-      return MAX (1, MIN (num0, num1) - 1);
-      
+      result = MAX (1, MIN (num0, num1) - 1);
+
+#ifdef POINTERS_EXTEND_UNSIGNED
+      /* If pointers extend signed and this is an addition or subtraction
+        to a pointer in Pmode, all the bits above ptr_mode are known to be
+        sign bit copies.  */
+      if (! POINTERS_EXTEND_UNSIGNED && GET_MODE (x) == Pmode
+         && (code == PLUS || code == MINUS)
+         && GET_CODE (XEXP (x, 0)) == REG && REG_POINTER (XEXP (x, 0)))
+       result = MAX ((GET_MODE_BITSIZE (Pmode)
+                      - GET_MODE_BITSIZE (ptr_mode) + 1),
+                     result);
+#endif
+      return result;
+
     case MULT:
       /* The number of bits of the product is the sum of the number of
         bits of both terms.  However, unless one of the terms if known
@@ -8573,7 +8542,7 @@ num_sign_bit_copies (x, mode)
        return 1;
       else
        return num_sign_bit_copies (XEXP (x, 0), mode);
-                                   
+
     case UMOD:
       /* The result must be <= the scond operand.  */
       return num_sign_bit_copies (XEXP (x, 1), mode);
@@ -8607,7 +8576,7 @@ num_sign_bit_copies (x, mode)
       num0 = num_sign_bit_copies (XEXP (x, 0), mode);
       if (GET_CODE (XEXP (x, 1)) == CONST_INT
          && INTVAL (XEXP (x, 1)) > 0)
-       num0 = MIN (bitwidth, num0 + INTVAL (XEXP (x, 1)));
+       num0 = MIN ((int) bitwidth, num0 + INTVAL (XEXP (x, 1)));
 
       return num0;
 
@@ -8615,7 +8584,7 @@ num_sign_bit_copies (x, mode)
       /* Left shifts destroy copies.  */
       if (GET_CODE (XEXP (x, 1)) != CONST_INT
          || INTVAL (XEXP (x, 1)) < 0
-         || INTVAL (XEXP (x, 1)) >= bitwidth)
+         || INTVAL (XEXP (x, 1)) >= (int) bitwidth)
        return 1;
 
       num0 = num_sign_bit_copies (XEXP (x, 0), mode);
@@ -8627,11 +8596,19 @@ num_sign_bit_copies (x, mode)
       return MIN (num0, num1);
 
     case EQ:  case NE:  case GE:  case GT:  case LE:  case LT:
+    case UNEQ:  case LTGT:  case UNGE:  case UNGT:  case UNLE:  case UNLT:
     case GEU: case GTU: case LEU: case LTU:
-      if (STORE_FLAG_VALUE == -1)
-       return bitwidth;
+    case UNORDERED: case ORDERED:
+      /* If the constant is negative, take its 1's complement and remask.
+        Then see how many zero bits we have.  */
+      nonzero = STORE_FLAG_VALUE;
+      if (bitwidth <= HOST_BITS_PER_WIDE_INT
+         && (nonzero & ((HOST_WIDE_INT) 1 << (bitwidth - 1))) != 0)
+       nonzero = (~nonzero) & GET_MODE_MASK (mode);
+
+      return (nonzero == 0 ? bitwidth : bitwidth - floor_log2 (nonzero) - 1);
       break;
-      
+
     default:
       break;
     }
@@ -8684,7 +8661,7 @@ extended_count (x, mode, unsignedp)
    (with *POP0 being done last).
 
    Return 1 if we can do the operation and update *POP0 and *PCONST0 with
-   the resulting operation.  *PCOMP_P is set to 1 if we would need to 
+   the resulting operation.  *PCOMP_P is set to 1 if we would need to
    complement the innermost operand, otherwise it is unchanged.
 
    MODE is the mode in which the operation will be done.  No bits outside
@@ -8777,7 +8754,7 @@ merge_outer_ops (pop0, pconst0, op1, const1, mode, pcomp_p)
          op0 = AND, *pcomp_p = 1;
        else /* op1 == IOR */
          /* (a | b) ^ b == a & ~b */
-         op0 = AND, *pconst0 = ~ const0;
+         op0 = AND, *pconst0 = ~const0;
        break;
 
       case AND:
@@ -8858,6 +8835,14 @@ simplify_shift_const (x, code, result_mode, varop, input_count)
 
   count = input_count;
 
+  /* Make sure and truncate the "natural" shift on the way in.  We don't
+     want to do this inside the loop as it makes it more difficult to
+     combine shifts.  */
+#ifdef SHIFT_COUNT_TRUNCATED
+  if (SHIFT_COUNT_TRUNCATED)
+    count %= GET_MODE_BITSIZE (mode);
+#endif
+
   /* Unless one of the branches of the `if' in this loop does a `continue',
      we will `break' the loop after the `if'.  */
 
@@ -8894,7 +8879,7 @@ simplify_shift_const (x, code, result_mode, varop, input_count)
         Since these shifts are being produced by the compiler by combining
         multiple operations, each of which are defined, we know what the
         result is supposed to be.  */
-        
+
       if (count > GET_MODE_BITSIZE (shift_mode) - 1)
        {
          if (code == ASHIFTRT)
@@ -8934,7 +8919,7 @@ simplify_shift_const (x, code, result_mode, varop, input_count)
       /* We simplify the tests below and elsewhere by converting
         ASHIFTRT to LSHIFTRT if we know the sign bit is clear.
         `make_compound_operation' will convert it to a ASHIFTRT for
-        those machines (such as Vax) that don't have a LSHIFTRT.  */
+        those machines (such as VAX) that don't have a LSHIFTRT.  */
       if (GET_MODE_BITSIZE (shift_mode) <= HOST_BITS_PER_WIDE_INT
          && code == ASHIFTRT
          && ((nonzero_bits (varop, shift_mode)
@@ -8966,16 +8951,12 @@ simplify_shift_const (x, code, result_mode, varop, input_count)
              && (tmode = mode_for_size (GET_MODE_BITSIZE (mode) - count,
                                         MODE_INT, 1)) != BLKmode)
            {
-             if (BYTES_BIG_ENDIAN)
-               new = gen_rtx_MEM (tmode, XEXP (varop, 0));
-             else
-               new = gen_rtx_MEM (tmode,
-                                  plus_constant (XEXP (varop, 0),
-                                                 count / BITS_PER_UNIT));
+             new = adjust_address_nv (varop, tmode,
+                                      BYTES_BIG_ENDIAN ? 0
+                                      : count / BITS_PER_UNIT);
 
-             MEM_COPY_ATTRIBUTES (new, varop);
-             varop = gen_rtx_combine (code == ASHIFTRT ? SIGN_EXTEND
-                                      : ZERO_EXTEND, mode, new);
+             varop = gen_rtx_fmt_e (code == ASHIFTRT ? SIGN_EXTEND
+                                    : ZERO_EXTEND, mode, new);
              count = 0;
              continue;
            }
@@ -8996,13 +8977,13 @@ simplify_shift_const (x, code, result_mode, varop, input_count)
              else
                {
                  new = copy_rtx (XEXP (varop, 0));
-                 SUBST (XEXP (new, 0), 
+                 SUBST (XEXP (new, 0),
                         plus_constant (XEXP (new, 0),
                                        count / BITS_PER_UNIT));
                }
 
-             varop = gen_rtx_combine (code == ASHIFTRT ? SIGN_EXTEND
-                                      : ZERO_EXTEND, mode, new);
+             varop = gen_rtx_fmt_e (code == ASHIFTRT ? SIGN_EXTEND
+                                    : ZERO_EXTEND, mode, new);
              count = 0;
              continue;
            }
@@ -9053,9 +9034,14 @@ simplify_shift_const (x, code, result_mode, varop, input_count)
          break;
 
        case ASHIFTRT:
-         /* If we are extracting just the sign bit of an arithmetic right 
-            shift, that shift is not needed.  */
-         if (code == LSHIFTRT && count == GET_MODE_BITSIZE (result_mode) - 1)
+         /* If we are extracting just the sign bit of an arithmetic
+            right shift, that shift is not needed.  However, the sign
+            bit of a wider mode may be different from what would be
+            interpreted as the sign bit in a narrower mode, so, if
+            the result is narrower, don't discard the shift.  */
+         if (code == LSHIFTRT && count == GET_MODE_BITSIZE (result_mode) - 1
+             && (GET_MODE_BITSIZE (result_mode)
+                 >= GET_MODE_BITSIZE (GET_MODE (varop))))
            {
              varop = XEXP (varop, 0);
              continue;
@@ -9091,9 +9077,9 @@ simplify_shift_const (x, code, result_mode, varop, input_count)
                      - GET_MODE_BITSIZE (GET_MODE (varop))) == count)
                {
                  /* C3 has the low-order C1 bits zero.  */
-                 
+
                  mask = (GET_MODE_MASK (mode)
-                         & ~ (((HOST_WIDE_INT) 1 << first_count) - 1));
+                         & ~(((HOST_WIDE_INT) 1 << first_count) - 1));
 
                  varop = simplify_and_const_int (NULL_RTX, result_mode,
                                                  XEXP (varop, 0), mask);
@@ -9103,11 +9089,11 @@ simplify_shift_const (x, code, result_mode, varop, input_count)
                  code = ASHIFTRT;
                  continue;
                }
-             
+
              /* If this was (ashiftrt (ashift foo C1) C2) and FOO has more
                 than C1 high-order bits equal to the sign bit, we can convert
                 this to either an ASHIFT or a ASHIFTRT depending on the
-                two counts. 
+                two counts.
 
                 We cannot do this if VAROP's mode is not SHIFT_MODE.  */
 
@@ -9120,7 +9106,7 @@ simplify_shift_const (x, code, result_mode, varop, input_count)
 
                  signed_count = count - first_count;
                  if (signed_count < 0)
-                   count = - signed_count, code = ASHIFT;
+                   count = -signed_count, code = ASHIFT;
                  else
                    count = signed_count;
 
@@ -9164,7 +9150,7 @@ simplify_shift_const (x, code, result_mode, varop, input_count)
                break;
 
              /* To compute the mask to apply after the shift, shift the
-                nonzero bits of the inner shift the same way the 
+                nonzero bits of the inner shift the same way the
                 outer shift will.  */
 
              mask_rtx = GEN_INT (nonzero_bits (varop, GET_MODE (varop)));
@@ -9172,7 +9158,7 @@ simplify_shift_const (x, code, result_mode, varop, input_count)
              mask_rtx
                = simplify_binary_operation (code, result_mode, mask_rtx,
                                             GEN_INT (count));
-                                 
+
              /* Give up if we can't compute an outer operation to use.  */
              if (mask_rtx == 0
                  || GET_CODE (mask_rtx) != CONST_INT
@@ -9190,7 +9176,7 @@ simplify_shift_const (x, code, result_mode, varop, input_count)
              else
                signed_count -= first_count;
 
-             /* If COUNT is positive, the new shift is usually CODE, 
+             /* If COUNT is positive, the new shift is usually CODE,
                 except for the two exceptions below, in which case it is
                 FIRST_CODE.  If the count is negative, FIRST_CODE should
                 always be used  */
@@ -9199,7 +9185,7 @@ simplify_shift_const (x, code, result_mode, varop, input_count)
                      || (first_code == ASHIFTRT && code == LSHIFTRT)))
                code = first_code, count = signed_count;
              else if (signed_count < 0)
-               code = first_code, count = - signed_count;
+               code = first_code, count = -signed_count;
              else
                count = signed_count;
 
@@ -9218,7 +9204,7 @@ simplify_shift_const (x, code, result_mode, varop, input_count)
                                                         XEXP (varop, 0),
                                                         GEN_INT (count))))
            {
-             varop = gen_rtx_combine (code, mode, new, XEXP (varop, 1));
+             varop = gen_rtx_fmt_ee (code, mode, new, XEXP (varop, 1));
              count = 0;
              continue;
            }
@@ -9226,8 +9212,8 @@ simplify_shift_const (x, code, result_mode, varop, input_count)
 
        case NOT:
          /* Make this fit the case below.  */
-         varop = gen_rtx_combine (XOR, mode, XEXP (varop, 0),
-                                  GEN_INT (GET_MODE_MASK (mode)));
+         varop = gen_rtx_XOR (mode, XEXP (varop, 0),
+                              GEN_INT (GET_MODE_MASK (mode)));
          continue;
 
        case IOR:
@@ -9248,11 +9234,11 @@ simplify_shift_const (x, code, result_mode, varop, input_count)
              && rtx_equal_p (XEXP (XEXP (varop, 0), 0), XEXP (varop, 1)))
            {
              count = 0;
-             varop = gen_rtx_combine (LE, GET_MODE (varop), XEXP (varop, 1),
-                                      const0_rtx);
+             varop = gen_rtx_LE (GET_MODE (varop), XEXP (varop, 1),
+                                 const0_rtx);
 
              if (STORE_FLAG_VALUE == 1 ? code == ASHIFTRT : code == LSHIFTRT)
-               varop = gen_rtx_combine (NEG, GET_MODE (varop), varop);
+               varop = gen_rtx_NEG (GET_MODE (varop), varop);
 
              continue;
            }
@@ -9267,7 +9253,7 @@ simplify_shift_const (x, code, result_mode, varop, input_count)
              && (new = simplify_binary_operation (code, result_mode,
                                                   XEXP (varop, 1),
                                                   GEN_INT (count))) != 0
-             && GET_CODE(new) == CONST_INT
+             && GET_CODE (new) == CONST_INT
              && merge_outer_ops (&outer_op, &outer_const, GET_CODE (varop),
                                  INTVAL (new), result_mode, &complement_p))
            {
@@ -9302,7 +9288,7 @@ simplify_shift_const (x, code, result_mode, varop, input_count)
              && count == GET_MODE_BITSIZE (result_mode) - 1
              && GET_MODE_BITSIZE (result_mode) <= HOST_BITS_PER_WIDE_INT
              && ((STORE_FLAG_VALUE
-                  & ((HOST_WIDE_INT) 1 
+                  & ((HOST_WIDE_INT) 1
                      < (GET_MODE_BITSIZE (result_mode) - 1))))
              && nonzero_bits (XEXP (varop, 0), result_mode) == 1
              && merge_outer_ops (&outer_op, &outer_const, XOR,
@@ -9414,11 +9400,11 @@ simplify_shift_const (x, code, result_mode, varop, input_count)
              && rtx_equal_p (XEXP (XEXP (varop, 0), 0), XEXP (varop, 1)))
            {
              count = 0;
-             varop = gen_rtx_combine (GT, GET_MODE (varop), XEXP (varop, 1),
-                                      const0_rtx);
+             varop = gen_rtx_GT (GET_MODE (varop), XEXP (varop, 1),
+                                 const0_rtx);
 
              if (STORE_FLAG_VALUE == 1 ? code == ASHIFTRT : code == LSHIFTRT)
-               varop = gen_rtx_combine (NEG, GET_MODE (varop), varop);
+               varop = gen_rtx_NEG (GET_MODE (varop), varop);
 
              continue;
            }
@@ -9437,17 +9423,16 @@ simplify_shift_const (x, code, result_mode, varop, input_count)
              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);
+               = gen_rtx_LSHIFTRT (GET_MODE (varop_inner),
+                                   XEXP (varop_inner, 0),
+                                   GEN_INT
+                                   (count + INTVAL (XEXP (varop_inner, 1))));
+             varop = gen_rtx_TRUNCATE (GET_MODE (varop), varop_inner);
              count = 0;
              continue;
            }
          break;
-         
+
        default:
          break;
        }
@@ -9497,7 +9482,7 @@ simplify_shift_const (x, code, result_mode, varop, input_count)
   else
     {
       if (x == 0 || GET_CODE (x) != code || GET_MODE (x) != shift_mode)
-       x = gen_rtx_combine (code, shift_mode, varop, const_rtx);
+       x = gen_rtx_fmt_ee (code, shift_mode, varop, const_rtx);
 
       SUBST (XEXP (x, 0), varop);
       SUBST (XEXP (x, 1), const_rtx);
@@ -9518,14 +9503,14 @@ simplify_shift_const (x, code, result_mode, varop, input_count)
   if (orig_code == LSHIFTRT && result_mode != shift_mode)
     x = simplify_and_const_int (NULL_RTX, shift_mode, x,
                                GET_MODE_MASK (result_mode) >> orig_count);
-      
+
   /* Do the remainder of the processing in RESULT_MODE.  */
   x = gen_lowpart_for_combine (result_mode, x);
 
   /* If COMPLEMENT_P is set, we have to complement X before doing the outer
      operation.  */
   if (complement_p)
-    x = gen_unary (NOT, result_mode, result_mode, x);
+    x =simplify_gen_unary (NOT, result_mode, x, result_mode);
 
   if (outer_op != NIL)
     {
@@ -9539,13 +9524,13 @@ simplify_shift_const (x, code, result_mode, varop, input_count)
           equivalent to a constant.  This should be rare.  */
        x = GEN_INT (outer_const);
       else if (GET_RTX_CLASS (outer_op) == '1')
-       x = gen_unary (outer_op, result_mode, result_mode, x);
+       x = simplify_gen_unary (outer_op, result_mode, x, result_mode);
       else
        x = gen_binary (outer_op, result_mode, x, GEN_INT (outer_const));
     }
 
   return x;
-}  
+}
 \f
 /* Like recog, but we receive the address of a pointer to a new pattern.
    We try to match the rtx that the pointer points to.
@@ -9571,6 +9556,7 @@ recog_for_combine (pnewpat, insn, pnotes)
   int num_clobbers_to_add = 0;
   int i;
   rtx notes = 0;
+  rtx old_notes;
 
   /* 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
@@ -9581,7 +9567,10 @@ recog_for_combine (pnewpat, insn, pnotes)
          && XEXP (XVECEXP (pat, 0, i), 0) == const0_rtx)
        return -1;
 
-  /* Is the result of combination a valid instruction?  */
+  /* Remove the old notes prior to trying to recognize the new pattern.  */
+  old_notes = REG_NOTES (insn);
+  REG_NOTES (insn) = 0;
+
   insn_code_number = recog (pat, insn, &num_clobbers_to_add);
 
   /* If it isn't, there is the possibility that we previously had an insn
@@ -9610,15 +9599,21 @@ recog_for_combine (pnewpat, insn, pnotes)
       insn_code_number = recog (pat, insn, &num_clobbers_to_add);
     }
 
+  /* Recognize all noop sets, these will be killed by followup pass.  */
+  if (insn_code_number < 0 && GET_CODE (pat) == SET && set_noop_p (pat))
+    insn_code_number = NOOP_MOVE_INSN_CODE, num_clobbers_to_add = 0;
+
+  REG_NOTES (insn) = old_notes;
+
   /* If we had any clobbers to add, make a new pattern than contains
      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));
+                                    rtvec_alloc (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++)
@@ -9704,7 +9699,6 @@ gen_lowpart_for_combine (mode, x)
   if (GET_CODE (x) == MEM)
     {
       register int offset = 0;
-      rtx new;
 
       /* Refuse to work on a volatile memory ref or one with a mode-dependent
         address.  */
@@ -9728,108 +9722,31 @@ 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));
-      MEM_COPY_ATTRIBUTES (new, x);
-      return new;
+
+      return adjust_address_nv (x, mode, offset);
     }
 
   /* If X is a comparison operator, rewrite it in a new mode.  This
      probably won't match, but may allow further simplifications.  */
   else if (GET_RTX_CLASS (GET_CODE (x)) == '<')
-    return gen_rtx_combine (GET_CODE (x), mode, XEXP (x, 0), XEXP (x, 1));
+    return gen_rtx_fmt_ee (GET_CODE (x), mode, XEXP (x, 0), XEXP (x, 1));
 
   /* If we couldn't simplify X any other way, just enclose it in a
      SUBREG.  Normally, this SUBREG won't match, but some patterns may
      include an explicit SUBREG or we may simplify it further in combine.  */
   else
     {
-      int word = 0;
+      int offset = 0;
+      rtx res;
 
-      if (WORDS_BIG_ENDIAN && GET_MODE_SIZE (GET_MODE (x)) > UNITS_PER_WORD)
-       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);
+      offset = subreg_lowpart_offset (mode, GET_MODE (x));
+      res = simplify_gen_subreg (mode, x, GET_MODE (x), offset);
+      if (res)
+       return res;
+      return gen_rtx_CLOBBER (GET_MODE (x), const0_rtx);
     }
 }
 \f
-/* Make an rtx expression.  This is a subset of gen_rtx and only supports
-   expressions of 1, 2, or 3 operands, each of which are rtx expressions.
-
-   If the identical expression was previously in the insn (in the undobuf),
-   it will be returned.  Only if it is not found will a new expression
-   be made.  */
-
-/*VARARGS2*/
-static rtx
-gen_rtx_combine VPARAMS ((enum rtx_code code, enum machine_mode mode, ...))
-{
-#ifndef ANSI_PROTOTYPES
-  enum rtx_code code;
-  enum machine_mode mode;
-#endif
-  va_list p;
-  int n_args;
-  rtx args[3];
-  int j;
-  const char *fmt;
-  rtx rt;
-  struct undo *undo;
-
-  VA_START (p, mode);
-
-#ifndef ANSI_PROTOTYPES
-  code = va_arg (p, enum rtx_code);
-  mode = va_arg (p, enum machine_mode);
-#endif
-
-  n_args = GET_RTX_LENGTH (code);
-  fmt = GET_RTX_FORMAT (code);
-
-  if (n_args == 0 || n_args > 3)
-    abort ();
-
-  /* Get each arg and verify that it is supposed to be an expression.  */
-  for (j = 0; j < n_args; j++)
-    {
-      if (*fmt++ != 'e')
-       abort ();
-
-      args[j] = va_arg (p, rtx);
-    }
-
-  va_end (p);
-
-  /* See if this is in undobuf.  Be sure we don't use objects that came
-     from another insn; this could produce circular rtl structures.  */
-
-  for (undo = undobuf.undos; undo != undobuf.previous_undos; undo = undo->next)
-    if (!undo->is_int
-       && GET_CODE (undo->old_contents.r) == code
-       && GET_MODE (undo->old_contents.r) == mode)
-      {
-       for (j = 0; j < n_args; j++)
-         if (XEXP (undo->old_contents.r, j) != args[j])
-           break;
-
-       if (j == n_args)
-         return undo->old_contents.r;
-      }
-
-  /* Otherwise make a new rtx.  We know we have 1, 2, or 3 args.
-     Use rtx_alloc instead of gen_rtx because it's faster on RISC.  */
-  rt = rtx_alloc (code);
-  PUT_MODE (rt, mode);
-  XEXP (rt, 0) = args[0];
-  if (n_args > 1)
-    {
-      XEXP (rt, 1) = args[1];
-      if (n_args > 2)
-       XEXP (rt, 2) = args[2];
-    }
-  return rt;
-}
-
 /* These routines make binary and unary operations by first seeing if they
    fold; if not, a new expression is allocated.  */
 
@@ -9843,15 +9760,14 @@ gen_binary (code, mode, op0, op1)
   rtx tem;
 
   if (GET_RTX_CLASS (code) == 'c'
-      && (GET_CODE (op0) == CONST_INT
-         || (CONSTANT_P (op0) && GET_CODE (op1) != CONST_INT)))
+      && swap_commutative_operands_p (op0, op1))
     tem = op0, op0 = op1, op1 = tem;
 
-  if (GET_RTX_CLASS (code) == '<') 
+  if (GET_RTX_CLASS (code) == '<')
     {
       enum machine_mode op_mode = GET_MODE (op0);
 
-      /* Strip the COMPARE from (REL_OP (compare X Y) 0) to get 
+      /* Strip the COMPARE from (REL_OP (compare X Y) 0) to get
         just (REL_OP X Y).  */
       if (GET_CODE (op0) == COMPARE && op1 == const0_rtx)
        {
@@ -9872,36 +9788,17 @@ gen_binary (code, mode, op0, op1)
 
   /* Put complex operands first and constants second.  */
   if (GET_RTX_CLASS (code) == 'c'
-      && ((CONSTANT_P (op0) && GET_CODE (op1) != CONST_INT)
-         || (GET_RTX_CLASS (GET_CODE (op0)) == 'o'
-             && GET_RTX_CLASS (GET_CODE (op1)) != 'o')
-         || (GET_CODE (op0) == SUBREG
-             && GET_RTX_CLASS (GET_CODE (SUBREG_REG (op0))) == 'o'
-             && GET_RTX_CLASS (GET_CODE (op1)) != 'o')))
-    return gen_rtx_combine (code, mode, op1, op0);
+      && swap_commutative_operands_p (op0, op1))
+    return gen_rtx_fmt_ee (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)
+          && (nonzero_bits (op0, mode) & ~INTVAL (op1)) == 0)
     return op0;
 
-  return gen_rtx_combine (code, mode, op0, op1);
-}
-
-static rtx
-gen_unary (code, mode, op0_mode, op0)
-     enum rtx_code code;
-     enum machine_mode mode, op0_mode;
-     rtx op0;
-{
-  rtx result = simplify_unary_operation (code, mode, op0, op0_mode);
-
-  if (result)
-    return result;
-
-  return gen_rtx_combine (code, mode, op0);
+  return gen_rtx_fmt_ee (code, mode, op0, op1);
 }
 \f
 /* Simplify a comparison between *POP0 and *POP1 where CODE is the
@@ -9969,7 +9866,7 @@ simplify_comparison (code, pop0, pop1)
                  && (code != GT && code != LT && code != GE && code != LE))
              || (GET_CODE (op0) == ASHIFTRT
                  && (code != GTU && code != LTU
-                     && code != GEU && code != GEU)))
+                     && code != GEU && code != LEU)))
          && GET_CODE (XEXP (op0, 1)) == CONST_INT
          && INTVAL (XEXP (op0, 1)) >= 0
          && INTVAL (XEXP (op0, 1)) < HOST_BITS_PER_WIDE_INT
@@ -9984,8 +9881,8 @@ simplify_comparison (code, pop0, pop1)
          else if (GET_CODE (op0) == ASHIFT)
            mask = (mask & (mask << shift_count)) >> shift_count;
 
-         if ((nonzero_bits (XEXP (op0, 0), mode) & ~ mask) == 0
-             && (nonzero_bits (XEXP (op1, 0), mode) & ~ mask) == 0)
+         if ((nonzero_bits (XEXP (op0, 0), mode) & ~mask) == 0
+             && (nonzero_bits (XEXP (op1, 0), mode) & ~mask) == 0)
            op0 = XEXP (op0, 0), op1 = XEXP (op1, 0);
          else
            break;
@@ -10004,16 +9901,16 @@ simplify_comparison (code, pop0, pop1)
         operations from some narrower mode even though a SUBREG is not
         present.  */
 
-      else if  (GET_CODE (op0) == AND && GET_CODE (op1) == AND
-               && GET_CODE (XEXP (op0, 1)) == CONST_INT
-               && GET_CODE (XEXP (op1, 1)) == CONST_INT)
+      else if (GET_CODE (op0) == AND && GET_CODE (op1) == AND
+              && GET_CODE (XEXP (op0, 1)) == CONST_INT
+              && GET_CODE (XEXP (op1, 1)) == CONST_INT)
        {
          rtx inner_op0 = XEXP (op0, 0);
          rtx inner_op1 = XEXP (op1, 0);
          HOST_WIDE_INT c0 = INTVAL (XEXP (op0, 1));
          HOST_WIDE_INT c1 = INTVAL (XEXP (op1, 1));
          int changed = 0;
-               
+
          if (GET_CODE (inner_op0) == SUBREG && GET_CODE (inner_op1) == SUBREG
              && (GET_MODE_SIZE (GET_MODE (inner_op0))
                  > GET_MODE_SIZE (GET_MODE (SUBREG_REG (inner_op0))))
@@ -10064,11 +9961,11 @@ simplify_comparison (code, pop0, pop1)
       else
        break;
     }
-     
+
   /* If the first operand is a constant, swap the operands and adjust the
      comparison code appropriately, but don't do this if the second operand
      is already a constant integer.  */
-  if (CONSTANT_P (op0) && GET_CODE (op1) != CONST_INT)
+  if (swap_commutative_operands_p (op0, op1))
     {
       tem = op0, op0 = op1, op1 = tem;
       code = swap_condition (code);
@@ -10103,6 +10000,7 @@ simplify_comparison (code, pop0, pop1)
       /* Get the constant we are comparing against and turn off all bits
         not on in our mode.  */
       const_op = trunc_int_for_mode (INTVAL (op1), mode);
+      op1 = GEN_INT (const_op);
 
       /* If we are comparing against a constant power of two and the value
         being compared can only have that single bit nonzero (e.g., it was
@@ -10132,7 +10030,7 @@ simplify_comparison (code, pop0, pop1)
        }
 
       /* Do some canonicalizations based on the comparison code.  We prefer
-        comparisons against zero and then prefer equality comparisons.  
+        comparisons against zero and then prefer equality comparisons.
         If we can reduce the size of a constant, we will do that too.  */
 
       switch (code)
@@ -10180,7 +10078,7 @@ simplify_comparison (code, pop0, pop1)
            break;
 
        case GT:
-         /* > C is equivalent to >= (C + 1); we do this for C < 0*/
+         /* > C is equivalent to >= (C + 1); we do this for C < 0.  */
          if (const_op < 0)
            {
              const_op += 1;
@@ -10296,7 +10194,7 @@ simplify_comparison (code, pop0, pop1)
        case ZERO_EXTRACT:
          /* If we are extracting a single bit from a variable position in
             a constant that has only a single bit set and are comparing it
-            with zero, we can convert this into an equality comparison 
+            with zero, we can convert this into an equality comparison
             between the position and the location of the single bit.  */
 
          if (GET_CODE (XEXP (op0, 0)) == CONST_INT
@@ -10306,14 +10204,15 @@ simplify_comparison (code, pop0, pop1)
            {
              if (BITS_BIG_ENDIAN)
                {
-#ifdef HAVE_extzv
-                 mode = insn_data[(int) CODE_FOR_extzv].operand[1].mode;
-                 if (mode == VOIDmode)
-                   mode = word_mode;
-                 i = (GET_MODE_BITSIZE (mode) - 1 - i);
-#else
-                 i = BITS_PER_WORD - 1 - i;
-#endif
+                 enum machine_mode new_mode
+                   = mode_for_extraction (EP_extzv, 1);
+                 if (new_mode == MAX_MACHINE_MODE)
+                   i = BITS_PER_WORD - 1 - i;
+                 else
+                   {
+                     mode = new_mode;
+                     i = (GET_MODE_BITSIZE (mode) - 1 - i);
+                   }
                }
 
              op0 = XEXP (op0, 2);
@@ -10421,7 +10320,7 @@ simplify_comparison (code, pop0, pop1)
              continue;
            }
 
-         /* ... fall through ...  */
+         /* Fall through.  */
 
        case ABS:
          /* ABS is ignorable inside an equality comparison with zero.  */
@@ -10431,11 +10330,10 @@ simplify_comparison (code, pop0, pop1)
              continue;
            }
          break;
-         
 
        case SIGN_EXTEND:
          /* Can simplify (compare (zero/sign_extend FOO) CONST)
-            to (compare FOO CONST) if CONST fits in FOO's mode and we 
+            to (compare FOO CONST) if CONST fits in FOO's mode and we
             are either testing inequality or have an unsigned comparison
             with ZERO_EXTEND or a signed comparison with SIGN_EXTEND.  */
          if (! unsigned_comparison_p
@@ -10465,12 +10363,12 @@ simplify_comparison (code, pop0, pop1)
              && GET_CODE (SUBREG_REG (op0)) == PLUS
              && GET_CODE (XEXP (SUBREG_REG (op0), 1)) == CONST_INT
              && INTVAL (XEXP (SUBREG_REG (op0), 1)) < 0
-             && (- INTVAL (XEXP (SUBREG_REG (op0), 1))
-                 < (HOST_WIDE_INT)(GET_MODE_MASK (mode) / 2))
+             && (-INTVAL (XEXP (SUBREG_REG (op0), 1))
+                 < (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)))
-                       & ~ GET_MODE_MASK (mode))
+                       & ~GET_MODE_MASK (mode))
                  || (num_sign_bit_copies (XEXP (SUBREG_REG (op0), 0),
                                           GET_MODE (SUBREG_REG (op0)))
                      > (GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (op0)))
@@ -10580,8 +10478,10 @@ simplify_comparison (code, pop0, pop1)
          break;
 
        case EQ:  case NE:
-       case LT:  case LTU:  case LE:  case LEU:
-       case GT:  case GTU:  case GE:  case GEU:
+       case UNEQ:  case LTGT:
+       case LT:  case LTU:  case UNLT:  case LE:  case LEU:  case UNLE:
+       case GT:  case GTU:  case UNGT:  case GE:  case GEU:  case UNGE:
+        case UNORDERED: case ORDERED:
          /* We can't do anything if OP0 is a condition code value, rather
             than an actual data value.  */
          if (const_op != 0
@@ -10599,20 +10499,27 @@ simplify_comparison (code, pop0, pop1)
 
          /* Check for the cases where we simply want the result of the
             earlier test or the opposite of that result.  */
-         if (code == NE
-             || (code == EQ && reversible_comparison_p (op0))
+         if (code == NE || code == EQ
              || (GET_MODE_BITSIZE (GET_MODE (op0)) <= HOST_BITS_PER_WIDE_INT
                  && GET_MODE_CLASS (GET_MODE (op0)) == MODE_INT
                  && (STORE_FLAG_VALUE
                      & (((HOST_WIDE_INT) 1
                          << (GET_MODE_BITSIZE (GET_MODE (op0)) - 1))))
-                 && (code == LT
-                     || (code == GE && reversible_comparison_p (op0)))))
+                 && (code == LT || code == GE)))
            {
-             code = (code == LT || code == NE
-                     ? GET_CODE (op0) : reverse_condition (GET_CODE (op0)));
-             op0 = tem, op1 = tem1;
-             continue;
+             enum rtx_code new_code;
+             if (code == LT || code == NE)
+               new_code = GET_CODE (op0);
+             else
+               new_code = combine_reversed_comparison_code (op0);
+
+             if (new_code != UNKNOWN)
+               {
+                 code = new_code;
+                 op0 = tem;
+                 op1 = tem1;
+                 continue;
+               }
            }
          break;
 
@@ -10637,9 +10544,9 @@ simplify_comparison (code, pop0, pop1)
              && XEXP (XEXP (op0, 0), 0) == const1_rtx)
            {
              op0 = simplify_and_const_int
-               (op0, mode, gen_rtx_combine (LSHIFTRT, mode,
-                                            XEXP (op0, 1),
-                                            XEXP (XEXP (op0, 0), 1)),
+               (op0, mode, gen_rtx_LSHIFTRT (mode,
+                                             XEXP (op0, 1),
+                                             XEXP (XEXP (op0, 0), 1)),
                 (HOST_WIDE_INT) 1);
              continue;
            }
@@ -10657,7 +10564,7 @@ simplify_comparison (code, pop0, pop1)
            {
              mask = ((INTVAL (XEXP (op0, 1)) & GET_MODE_MASK (mode))
                      << INTVAL (XEXP (XEXP (op0, 0), 1)));
-             if ((~ STORE_FLAG_VALUE & mask) == 0
+             if ((~STORE_FLAG_VALUE & mask) == 0
                  && (GET_RTX_CLASS (GET_CODE (XEXP (XEXP (op0, 0), 0))) == '<'
                      || ((tem = get_last_value (XEXP (XEXP (op0, 0), 0))) != 0
                          && GET_RTX_CLASS (GET_CODE (tem)) == '<')))
@@ -10728,13 +10635,13 @@ simplify_comparison (code, pop0, pop1)
              && 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)) & ~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
@@ -10744,6 +10651,21 @@ simplify_comparison (code, pop0, pop1)
              continue;
            }
 
+         /* Convert (ne (and (lshiftrt (not X)) 1) 0) to
+            (eq (and (lshiftrt X) 1) 0).  */
+         if (const_op == 0 && equality_comparison_p
+             && XEXP (op0, 1) == const1_rtx
+             && GET_CODE (XEXP (op0, 0)) == LSHIFTRT
+             && GET_CODE (XEXP (XEXP (op0, 0), 0)) == NOT)
+           {
+             op0 = simplify_and_const_int
+               (op0, mode,
+                gen_rtx_LSHIFTRT (mode, XEXP (XEXP (XEXP (op0, 0), 0), 0),
+                                  XEXP (XEXP (op0, 0), 1)),
+                (HOST_WIDE_INT) 1);
+             code = (code == NE ? EQ : NE);
+             continue;
+           }
          break;
 
        case ASHIFT:
@@ -10760,13 +10682,13 @@ simplify_comparison (code, pop0, pop1)
                   & (((HOST_WIDE_INT) 1 << INTVAL (XEXP (op0, 1))) - 1)) == 0)
              && mode_width <= HOST_BITS_PER_WIDE_INT
              && (nonzero_bits (XEXP (op0, 0), mode)
-                 & ~ (mask >> (INTVAL (XEXP (op0, 1))
-                               + ! equality_comparison_p))) == 0)
+                 & ~(mask >> (INTVAL (XEXP (op0, 1))
+                              + ! equality_comparison_p))) == 0)
            {
              /* We must perform a logical shift, not an arithmetic one,
                 as we want the top N bits of C to be zero.  */
              unsigned HOST_WIDE_INT temp = const_op & GET_MODE_MASK (mode);
-             
+
              temp >>= INTVAL (XEXP (op0, 1));
              op1 = GEN_INT (trunc_int_for_mode (temp, mode));
              op0 = XEXP (op0, 0);
@@ -10820,7 +10742,7 @@ simplify_comparison (code, pop0, pop1)
              && (tmode = mode_for_size (mode_width - INTVAL (XEXP (op0, 1)),
                                         MODE_INT, 1)) != BLKmode
              && ((unsigned HOST_WIDE_INT) const_op <= GET_MODE_MASK (tmode)
-                 || ((unsigned HOST_WIDE_INT) - const_op
+                 || ((unsigned HOST_WIDE_INT) -const_op
                      <= GET_MODE_MASK (tmode))))
            {
              op0 = gen_lowpart_for_combine (tmode, XEXP (XEXP (op0, 0), 0));
@@ -10839,7 +10761,7 @@ simplify_comparison (code, pop0, pop1)
              && (tmode = mode_for_size (mode_width - INTVAL (XEXP (op0, 1)),
                                         MODE_INT, 1)) != BLKmode
              && ((unsigned HOST_WIDE_INT) const_op <= GET_MODE_MASK (tmode)
-                 || ((unsigned HOST_WIDE_INT) - const_op
+                 || ((unsigned HOST_WIDE_INT) -const_op
                      <= GET_MODE_MASK (tmode))))
            {
              rtx inner = XEXP (XEXP (XEXP (op0, 0), 0), 0);
@@ -10887,7 +10809,7 @@ simplify_comparison (code, pop0, pop1)
              continue;
            }
          break;
-         
+
        default:
          break;
        }
@@ -10907,6 +10829,7 @@ simplify_comparison (code, pop0, pop1)
 
   if (GET_CODE (op0) == SUBREG && subreg_lowpart_p (op0)
       && GET_MODE_CLASS (GET_MODE (op0)) == MODE_INT
+      && GET_MODE_CLASS (GET_MODE (SUBREG_REG (op0))) == MODE_INT
       && (code == NE || code == EQ)
       && ((GET_MODE_SIZE (GET_MODE (op0))
           > GET_MODE_SIZE (GET_MODE (SUBREG_REG (op0))))))
@@ -10917,15 +10840,16 @@ simplify_comparison (code, pop0, pop1)
 
   else if (GET_CODE (op0) == SUBREG && subreg_lowpart_p (op0)
           && GET_MODE_CLASS (GET_MODE (op0)) == MODE_INT
+          && GET_MODE_CLASS (GET_MODE (SUBREG_REG (op0))) == MODE_INT
           && (code == NE || code == EQ)
           && (GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (op0)))
               <= HOST_BITS_PER_WIDE_INT)
           && (nonzero_bits (SUBREG_REG (op0), GET_MODE (SUBREG_REG (op0)))
-              & ~ GET_MODE_MASK (GET_MODE (op0))) == 0
+              & ~GET_MODE_MASK (GET_MODE (op0))) == 0
           && (tem = gen_lowpart_for_combine (GET_MODE (SUBREG_REG (op0)),
                                              op1),
               (nonzero_bits (tem, GET_MODE (SUBREG_REG (op0)))
-               & ~ GET_MODE_MASK (GET_MODE (op0))) == 0))
+               & ~GET_MODE_MASK (GET_MODE (op0))) == 0))
     op0 = SUBREG_REG (op0), op1 = tem;
 
   /* We now do the opposite procedure: Some machines don't have compare
@@ -10937,12 +10861,12 @@ simplify_comparison (code, pop0, pop1)
   mode = GET_MODE (op0);
   if (mode != VOIDmode && GET_MODE_CLASS (mode) == MODE_INT
       && GET_MODE_SIZE (mode) < UNITS_PER_WORD
-      && cmp_optab->handlers[(int) mode].insn_code == CODE_FOR_nothing)
+      && ! have_insn_for (COMPARE, mode))
     for (tmode = GET_MODE_WIDER_MODE (mode);
         (tmode != VOIDmode
          && GET_MODE_BITSIZE (tmode) <= HOST_BITS_PER_WIDE_INT);
         tmode = GET_MODE_WIDER_MODE (tmode))
-      if (cmp_optab->handlers[(int) tmode].insn_code != CODE_FOR_nothing)
+      if (have_insn_for (COMPARE, tmode))
        {
          /* If the only nonzero bits in OP0 and OP1 are those in the
             narrower mode and this is an equality or unsigned comparison,
@@ -10950,8 +10874,8 @@ simplify_comparison (code, pop0, pop1)
             values, in which case it is true for all comparisons.  */
          if (((code == EQ || code == NE
                || code == GEU || code == GTU || code == LEU || code == LTU)
-              && (nonzero_bits (op0, tmode) & ~ GET_MODE_MASK (mode)) == 0
-              && (nonzero_bits (op1, tmode) & ~ GET_MODE_MASK (mode)) == 0)
+              && (nonzero_bits (op0, tmode) & ~GET_MODE_MASK (mode)) == 0
+              && (nonzero_bits (op1, tmode) & ~GET_MODE_MASK (mode)) == 0)
              || ((num_sign_bit_copies (op0, tmode)
                   > GET_MODE_BITSIZE (tmode) - GET_MODE_BITSIZE (mode))
                  && (num_sign_bit_copies (op1, tmode)
@@ -10960,8 +10884,7 @@ simplify_comparison (code, pop0, pop1)
              /* If OP0 is an AND and we don't have an AND in MODE either,
                 make a new AND in the proper mode.  */
              if (GET_CODE (op0) == AND
-                 && (add_optab->handlers[(int) mode].insn_code
-                     == CODE_FOR_nothing))
+                 && !have_insn_for (AND, mode))
                op0 = gen_binary (AND, tmode,
                                  gen_lowpart_for_combine (tmode,
                                                           XEXP (op0, 0)),
@@ -11000,42 +10923,38 @@ simplify_comparison (code, pop0, pop1)
   return code;
 }
 \f
-/* Return 1 if we know that X, a comparison operation, is not operating
-   on a floating-point value or is EQ or NE, meaning that we can safely
-   reverse it.  */
-
-static int
-reversible_comparison_p (x)
-     rtx x;
+/* Like jump.c' reversed_comparison_code, but use combine infrastructure for
+   searching backward.  */
+static enum rtx_code
+combine_reversed_comparison_code (exp)
+     rtx exp;
 {
-  if (TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT
-      || flag_fast_math
-      || GET_CODE (x) == NE || GET_CODE (x) == EQ
-      || GET_CODE (x) == UNORDERED || GET_CODE (x) == ORDERED)
-    return 1;
-
-  switch (GET_MODE_CLASS (GET_MODE (XEXP (x, 0))))
-    {
-    case MODE_INT:
-    case MODE_PARTIAL_INT:
-    case MODE_COMPLEX_INT:
-      return 1;
-
-    case MODE_CC:
-      /* If the mode of the condition codes tells us that this is safe,
-        we need look no further.  */
-      if (REVERSIBLE_CC_MODE (GET_MODE (XEXP (x, 0))))
-       return 1;
-
-      /* Otherwise try and find where the condition codes were last set and
-        use that.  */
-      x = get_last_value (XEXP (x, 0));
-      return (x && GET_CODE (x) == COMPARE
-             && ! FLOAT_MODE_P (GET_MODE (XEXP (x, 0))));
-      
-    default:
-      return 0;
-    }
+   enum rtx_code code1 = reversed_comparison_code (exp, NULL);
+   rtx x;
+
+   if (code1 != UNKNOWN
+       || GET_MODE_CLASS (GET_MODE (XEXP (exp, 0))) != MODE_CC)
+     return code1;
+   /* Otherwise try and find where the condition codes were last set and
+      use that.  */
+   x = get_last_value (XEXP (exp, 0));
+   if (!x || GET_CODE (x) != COMPARE)
+     return UNKNOWN;
+   return reversed_comparison_code_parts (GET_CODE (exp),
+                                         XEXP (x, 0), XEXP (x, 1), NULL);
+}
+/* Return comparison with reversed code of EXP and operands OP0 and OP1.
+   Return NULL_RTX in case we fail to do the reversal.  */
+static rtx
+reversed_comparison (exp, mode, op0, op1)
+     rtx exp, op0, op1;
+     enum machine_mode mode;
+{
+  enum rtx_code reversed_code = combine_reversed_comparison_code (exp);
+  if (reversed_code == UNKNOWN)
+    return NULL_RTX;
+  else
+    return gen_binary (reversed_code, mode, op0, op1);
 }
 \f
 /* Utility function for following routine.  Called when X is part of a value
@@ -11063,7 +10982,7 @@ update_table_tick (x)
 
       return;
     }
-  
+
   for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
     /* Note that we can't have an "E" in values stored; see
        get_last_value_validate.  */
@@ -11097,7 +11016,7 @@ record_value_for_reg (reg, insn, value)
       /* Set things up so get_last_value is allowed to see anything set up to
         our insn.  */
       subst_low_cuid = INSN_CUID (insn);
-      tem = get_last_value (reg);      
+      tem = get_last_value (reg);
 
       /* If TEM is simply a binary operation with two CLOBBERs as operands,
         it isn't going to be useful and will take a lot of time to process,
@@ -11280,8 +11199,8 @@ record_dead_and_set_regs (insn)
 
 static void
 record_promoted_value (insn, subreg)
-    rtx insn;
-    rtx subreg;
+     rtx insn;
+     rtx subreg;
 {
   rtx links, set;
   unsigned int regno = REGNO (SUBREG_REG (subreg));
@@ -11290,7 +11209,7 @@ record_promoted_value (insn, subreg)
   if (GET_MODE_BITSIZE (mode) > HOST_BITS_PER_WIDE_INT)
     return;
 
-  for (links = LOG_LINKS (insn); links; )
+  for (links = LOG_LINKS (insn); links;)
     {
       insn = XEXP (links, 0);
       set = single_set (insn);
@@ -11303,11 +11222,11 @@ record_promoted_value (insn, subreg)
          continue;
        }
 
-      if (reg_last_set [regno] == insn)
-        {
+      if (reg_last_set[regno] == insn)
+       {
          if (SUBREG_PROMOTED_UNSIGNED_P (subreg))
-           reg_last_set_nonzero_bits [regno] &= GET_MODE_MASK (mode);
-        }
+           reg_last_set_nonzero_bits[regno] &= GET_MODE_MASK (mode);
+       }
 
       if (GET_CODE (SET_SRC (set)) == REG)
        {
@@ -11324,8 +11243,8 @@ record_promoted_value (insn, subreg)
 
 static void
 check_promoted_subreg (insn, x)
-    rtx insn;
-    rtx x;
+     rtx insn;
+     rtx x;
 {
   if (GET_CODE (x) == SUBREG && SUBREG_PROMOTED_VAR_P (x)
       && GET_CODE (SUBREG_REG (x)) == REG)
@@ -11336,7 +11255,7 @@ check_promoted_subreg (insn, x)
       int i, j;
 
       for (i = 0; i < GET_RTX_LENGTH (GET_CODE (x)); i++)
-       switch (format [i])
+       switch (format[i])
          {
          case 'e':
            check_promoted_subreg (insn, XEXP (x, i));
@@ -11385,7 +11304,7 @@ get_last_value_validate (loc, insn, tick, replace)
        if (reg_last_set_invalid[j]
            /* If this is a pseudo-register that was only set once and not
               live at the beginning of the function, it is always valid.  */
-           || (! (regno >= FIRST_PSEUDO_REGISTER 
+           || (! (regno >= FIRST_PSEUDO_REGISTER
                   && REG_N_SETS (regno) == 1
                   && (! REGNO_REG_SET_P
                       (BASIC_BLOCK (0)->global_live_at_start, regno)))
@@ -11449,9 +11368,9 @@ get_last_value (x)
 
   /* If we don't have a value, or if it isn't for this basic block and
      it's either a hard register, set more than once, or it's a live
-     at the beginning of the function, return 0.  
+     at the beginning of the function, return 0.
 
-     Because if it's not live at the beginnning of the function then the reg 
+     Because if it's not live at the beginnning of the function then the reg
      is always set before being used (is never used without being set).
      And, if it's set only once, and it's always set before use, then all
      uses must have the same last value, even if it's not from this basic
@@ -11502,8 +11421,8 @@ use_crosses_set_p (x, from_cuid)
     {
       unsigned int regno = REGNO (x);
       unsigned endreg = regno + (regno < FIRST_PSEUDO_REGISTER
-                           ? HARD_REGNO_NREGS (regno, GET_MODE (x)) : 1);
-      
+                                ? HARD_REGNO_NREGS (regno, GET_MODE (x)) : 1);
+
 #ifdef PUSH_ROUNDING
       /* Don't allow uses of the stack pointer to be moved,
         because we don't know whether the move crosses a push insn.  */
@@ -11546,7 +11465,7 @@ static int reg_dead_flag;
 
 /* Function called via note_stores from reg_dead_at_p.
 
-   If DEST is within [reg_dead_regno, reg_dead_endregno), set 
+   If DEST is within [reg_dead_regno, reg_dead_endregno), set
    reg_dead_flag to 1 if X is a CLOBBER and to -1 it is a SET.  */
 
 static void
@@ -11561,7 +11480,7 @@ reg_dead_at_p_1 (dest, x, data)
     return;
 
   regno = REGNO (dest);
-  endregno = regno + (regno < FIRST_PSEUDO_REGISTER 
+  endregno = regno + (regno < FIRST_PSEUDO_REGISTER
                      ? HARD_REGNO_NREGS (regno, GET_MODE (dest)) : 1);
 
   if (reg_dead_endregno > regno && reg_dead_regno < endregno)
@@ -11725,19 +11644,18 @@ mark_used_regs_combine (x)
 
     for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
       {
-        if (fmt[i] == 'e')
+       if (fmt[i] == 'e')
          mark_used_regs_combine (XEXP (x, i));
-        else if (fmt[i] == 'E')
-          {
-            register int j;
+       else if (fmt[i] == 'E')
+         {
+           register int j;
 
-            for (j = 0; j < XVECLEN (x, i); j++)
-              mark_used_regs_combine (XVECEXP (x, i, j));
-          }
+           for (j = 0; j < XVECLEN (x, i); j++)
+             mark_used_regs_combine (XVECEXP (x, i, j));
+         }
       }
   }
 }
-
 \f
 /* Remove register number REGNO from the dead registers list of INSN.
 
@@ -11762,7 +11680,7 @@ remove_death (regno, insn)
 /* For each register (hardware or pseudo) used within expression X, if its
    death is in an instruction with cuid between FROM_CUID (inclusive) and
    TO_INSN (exclusive), put a REG_DEAD note for that register in the
-   list headed by PNOTES. 
+   list headed by PNOTES.
 
    That said, don't move registers killed by maybe_kill_insn.
 
@@ -11890,6 +11808,7 @@ move_deaths (x, maybe_kill_insn, from_cuid, to_insn, pnotes)
         that accesses one word of a multi-word item, some
         piece of everything register in the expression is used by
         this insn, so remove any old death.  */
+      /* ??? So why do we test for equality of the sizes?  */
 
       if (GET_CODE (dest) == ZERO_EXTRACT
          || GET_CODE (dest) == STRICT_LOW_PART
@@ -11983,7 +11902,7 @@ reg_bitfield_target_p (x, body)
        return 1;
 
   return 0;
-}      
+}
 \f
 /* Given a chain of REG_NOTES originally from FROM_INSN, try to place them
    as appropriate.  I3 and I2 are the insns resulting from the combination
@@ -12020,6 +11939,7 @@ distribute_notes (notes, from_insn, i3, i2, elim_i2, elim_i1)
       switch (REG_NOTE_KIND (note))
        {
        case REG_BR_PROB:
+       case REG_BR_PRED:
        case REG_EXEC_COUNT:
          /* Doesn't matter much where we put this, as long as it's somewhere.
             It is preferable to keep these notes on branches, which is most
@@ -12027,11 +11947,40 @@ distribute_notes (notes, from_insn, i3, i2, elim_i2, elim_i1)
          place = i3;
          break;
 
+       case REG_NON_LOCAL_GOTO:
+         if (GET_CODE (i3) == JUMP_INSN)
+           place = i3;
+         else if (i2 && GET_CODE (i2) == JUMP_INSN)
+           place = i2;
+         else
+           abort();
+         break;
+
        case REG_EH_REGION:
-       case REG_EH_RETHROW:
+         /* These notes must remain with the call or trapping instruction.  */
+         if (GET_CODE (i3) == CALL_INSN)
+           place = i3;
+         else if (i2 && GET_CODE (i2) == CALL_INSN)
+           place = i2;
+         else if (flag_non_call_exceptions)
+           {
+             if (may_trap_p (i3))
+               place = i3;
+             else if (i2 && may_trap_p (i2))
+               place = i2;
+             /* ??? Otherwise assume we've combined things such that we
+                can now prove that the instructions can't trap.  Drop the
+                note in this case.  */
+           }
+         else
+           abort ();
+         break;
+
+       case REG_NORETURN:
+       case REG_SETJMP:
          /* These notes must remain with the call.  It should not be
             possible for both I2 and I3 to be a call.  */
-         if (GET_CODE (i3) == CALL_INSN) 
+         if (GET_CODE (i3) == CALL_INSN)
            place = i3;
          else if (i2 && GET_CODE (i2) == CALL_INSN)
            place = i2;
@@ -12083,7 +12032,6 @@ distribute_notes (notes, from_insn, i3, i2, elim_i2, elim_i1)
 
        case REG_EQUAL:
        case REG_EQUIV:
-       case REG_NONNEG:
        case REG_NOALIAS:
          /* These notes say something about results of an insn.  We can
             only support them if they used to be on I3 in which case they
@@ -12130,7 +12078,7 @@ distribute_notes (notes, from_insn, i3, i2, elim_i2, elim_i1)
 
          if (i2
              && (reg_mentioned_p (XEXP (note, 0), PATTERN (i2))
-                 || ((tem = find_reg_note (i2, REG_EQUAL, NULL_RTX))
+                 || ((tem = find_reg_note (i2, REG_EQUAL, NULL_RTX))
                      && GET_CODE (XEXP (tem, 0)) == LABEL_REF
                      && XEXP (XEXP (tem, 0), 0) == XEXP (note, 0))))
            {
@@ -12141,9 +12089,12 @@ distribute_notes (notes, from_insn, i3, i2, elim_i2, elim_i1)
            }
          break;
 
+       case REG_NONNEG:
        case REG_WAS_0:
-         /* It is too much trouble to try to see if this note is still
-            correct in all situations.  It is better to simply delete it.  */
+         /* These notes say something about the value of a register prior
+            to the execution of an insn.  It is too much trouble to see
+            if the note is still correct in all situations.  It is better
+            to simply delete it.  */
          break;
 
        case REG_RETVAL:
@@ -12158,6 +12109,10 @@ distribute_notes (notes, from_insn, i3, i2, elim_i2, elim_i1)
              place = prev_real_insn (from_insn);
              if (tem && place)
                XEXP (tem, 0) = place;
+             /* If we're deleting the last remaining instruction of a
+                libcall sequence, don't add the notes.  */
+             else if (XEXP (note, 0) == from_insn)
+               tem = place = 0;
            }
          break;
 
@@ -12171,6 +12126,10 @@ distribute_notes (notes, from_insn, i3, i2, elim_i2, elim_i1)
              place = next_real_insn (from_insn);
              if (tem && place)
                XEXP (tem, 0) = place;
+             /* If we're deleting the last remaining instruction of a
+                libcall sequence, don't add the notes.  */
+             else if (XEXP (note, 0) == from_insn)
+               tem = place = 0;
            }
          break;
 
@@ -12191,7 +12150,7 @@ distribute_notes (notes, from_insn, i3, i2, elim_i2, elim_i1)
 
          if (from_insn
              && GET_CODE (from_insn) == CALL_INSN
-              && find_reg_fusage (from_insn, USE, XEXP (note, 0)))
+             && find_reg_fusage (from_insn, USE, XEXP (note, 0)))
            place = from_insn;
          else if (reg_referenced_p (XEXP (note, 0), PATTERN (i3)))
            place = i3;
@@ -12199,7 +12158,8 @@ distribute_notes (notes, from_insn, i3, i2, elim_i2, elim_i1)
                   && reg_referenced_p (XEXP (note, 0), PATTERN (i2)))
            place = i2;
 
-         if (XEXP (note, 0) == elim_i2 || XEXP (note, 0) == elim_i1)
+         if (rtx_equal_p (XEXP (note, 0), elim_i2)
+             || rtx_equal_p (XEXP (note, 0), elim_i1))
            break;
 
          if (place == 0)
@@ -12208,7 +12168,7 @@ distribute_notes (notes, from_insn, i3, i2, elim_i2, elim_i1)
 
              for (tem = PREV_INSN (i3); place == 0; tem = PREV_INSN (tem))
                {
-                 if (GET_RTX_CLASS (GET_CODE (tem)) != 'i')
+                 if (! INSN_P (tem))
                    {
                      if (tem == bb->head)
                        break;
@@ -12228,14 +12188,14 @@ distribute_notes (notes, from_insn, i3, i2, elim_i2, elim_i1)
 
                      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;
+                            (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
@@ -12252,7 +12212,7 @@ distribute_notes (notes, from_insn, i3, i2, elim_i2, elim_i1)
                          )
                        {
                          /* Move the notes and links of TEM elsewhere.
-                            This might delete other dead insns recursively. 
+                            This might delete other dead insns recursively.
                             First set the pattern to something that won't use
                             any register.  */
 
@@ -12301,7 +12261,7 @@ distribute_notes (notes, from_insn, i3, i2, elim_i2, elim_i1)
                      else
                        {
                          PUT_REG_NOTE_KIND (note, REG_UNUSED);
-                         
+
                          /*  If there isn't already a REG_UNUSED note, put one
                              here.  */
                          if (! find_regno_note (tem, REG_UNUSED,
@@ -12324,7 +12284,8 @@ distribute_notes (notes, from_insn, i3, i2, elim_i2, elim_i1)
                         i2.  */
                      if (i2 && INSN_UID (place) <= max_uid_cuid
                          && INSN_CUID (place) > INSN_CUID (i2)
-                         && from_insn && INSN_CUID (from_insn) > INSN_CUID (i2)
+                         && from_insn
+                         && INSN_CUID (from_insn) > INSN_CUID (i2)
                          && reg_referenced_p (XEXP (note, 0), PATTERN (i2)))
                        {
                          rtx links = LOG_LINKS (place);
@@ -12337,7 +12298,7 @@ distribute_notes (notes, from_insn, i3, i2, elim_i2, elim_i1)
                  if (tem == bb->head)
                    break;
                }
-             
+
              /* We haven't found an insn for the death note and it
                 is still a REG_DEAD note, but we have hit the beginning
                 of the block.  If the existing life info says the reg
@@ -12362,6 +12323,15 @@ distribute_notes (notes, from_insn, i3, i2, elim_i2, elim_i1)
            {
              unsigned int regno = REGNO (XEXP (note, 0));
 
+             /* Similarly, if the instruction on which we want to place
+                the note is a noop, we'll need do a global live update
+                after we remove them in delete_noop_moves.  */
+             if (noop_move_p (place))
+               {
+                 SET_BIT (refresh_blocks, this_basic_block);
+                 need_refresh = 1;
+               }
+
              if (dead_or_set_p (place, XEXP (note, 0))
                  || reg_bitfield_target_p (XEXP (note, 0), PATTERN (place)))
                {
@@ -12378,13 +12348,11 @@ distribute_notes (notes, from_insn, i3, i2, elim_i2, elim_i1)
              /* If this is a death note for a hard reg that is occupying
                 multiple registers, ensure that we are still using all
                 parts of the object.  If we find a piece of the object
-                that is unused, we must add a USE for that piece before
-                PLACE and put the appropriate REG_DEAD note on it.
-
-                An alternative would be to put a REG_UNUSED for the pieces
-                on the insn that set the register, but that can't be done if
-                it is not in the same block.  It is simpler, though less
-                efficient, to add the USE insns.  */
+                that is unused, we must arrange for an appropriate REG_DEAD
+                note to be added for it.  However, we can't just emit a USE
+                and tag the note to it, since the register might actually
+                be dead; so we recourse, and the recursive call then finds
+                the previous insn that used this register.  */
 
              if (place && regno < FIRST_PSEUDO_REGISTER
                  && HARD_REGNO_NREGS (regno, GET_MODE (XEXP (note, 0))) > 1)
@@ -12396,67 +12364,60 @@ distribute_notes (notes, from_insn, i3, i2, elim_i2, elim_i1)
                  unsigned int i;
 
                  for (i = regno; i < endregno; i++)
-                   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 p;
-
-                       /* See if we already placed a USE note for this
-                          register in front of PLACE.  */
-                       for (p = place;
-                            GET_CODE (PREV_INSN (p)) == INSN
-                            && GET_CODE (PATTERN (PREV_INSN (p))) == USE;
-                            p = PREV_INSN (p))
-                         if (rtx_equal_p (piece,
-                                          XEXP (PATTERN (PREV_INSN (p)), 0)))
-                           {
-                             p = 0;
-                             break;
-                           }
-
-                       if (p)
-                         {
-                           rtx use_insn
-                             = emit_insn_before (gen_rtx_USE (VOIDmode,
-                                                              piece),
-                                                 p);
-                           REG_NOTES (use_insn)
-                             = gen_rtx_EXPR_LIST (REG_DEAD, piece,
-                                                  REG_NOTES (use_insn));
-                         }
-
-                       all_used = 0;
-                     }
-
-                 /* Check for the case where the register dying partially
-                    overlaps the register set by this insn.  */
-                 if (all_used)
-                   for (i = regno; i < endregno; i++)
-                     if (dead_or_set_regno_p (place, i))
-                         {
-                           all_used = 0;
-                           break;
-                         }
+                   if ((! refers_to_regno_p (i, i + 1, PATTERN (place), 0)
+                        && ! find_regno_fusage (place, USE, i))
+                       || dead_or_set_regno_p (place, i))
+                     all_used = 0;
 
                  if (! all_used)
                    {
                      /* Put only REG_DEAD notes for pieces that are
-                        still used and that are not already dead or set.  */
+                        not already dead or set.  */
 
-                     for (i = regno; i < endregno; i++)
+                     for (i = regno; i < endregno;
+                          i += HARD_REGNO_NREGS (i, reg_raw_mode[i]))
                        {
                          rtx piece = gen_rtx_REG (reg_raw_mode[i], i);
+                         basic_block bb = BASIC_BLOCK (this_basic_block);
 
-                         if ((reg_referenced_p (piece, PATTERN (place))
-                              || (GET_CODE (place) == CALL_INSN
-                                  && find_reg_fusage (place, USE, piece)))
-                             && ! dead_or_set_p (place, piece)
+                         if (! 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));
+                           {
+                             rtx new_note
+                               = gen_rtx_EXPR_LIST (REG_DEAD, piece, NULL_RTX);
+
+                             distribute_notes (new_note, place, place,
+                                               NULL_RTX, NULL_RTX, NULL_RTX);
+                           }
+                         else if (! refers_to_regno_p (i, i + 1,
+                                                       PATTERN (place), 0)
+                                  && ! find_regno_fusage (place, USE, i))
+                           for (tem = PREV_INSN (place); ;
+                                tem = PREV_INSN (tem))
+                             {
+                               if (! INSN_P (tem))
+                                 {
+                                   if (tem == bb->head)
+                                     {
+                                       SET_BIT (refresh_blocks,
+                                                this_basic_block);
+                                       need_refresh = 1;
+                                       break;
+                                     }
+                                   continue;
+                                 }
+                               if (dead_or_set_p (tem, piece)
+                                   || reg_bitfield_target_p (piece,
+                                                             PATTERN (tem)))
+                                 {
+                                   REG_NOTES (tem)
+                                     = gen_rtx_EXPR_LIST (REG_UNUSED, piece,
+                                                          REG_NOTES (tem));
+                                   break;
+                                 }
+                             }
+
                        }
 
                      place = 0;
@@ -12516,7 +12477,7 @@ distribute_links (links)
 
       /* If the insn that this link points to is a NOTE or isn't a single
         set, ignore it.  In the latter case, it isn't clear what we
-        can do other than ignore the link, since we can't tell which 
+        can do other than ignore the link, since we can't tell which
         register it was for.  Such links wouldn't be used by combine
         anyway.
 
@@ -12548,15 +12509,14 @@ distribute_links (links)
           (insn && (this_basic_block == n_basic_blocks - 1
                     || BLOCK_HEAD (this_basic_block + 1) != insn));
           insn = NEXT_INSN (insn))
-       if (GET_RTX_CLASS (GET_CODE (insn)) == 'i'
-           && reg_overlap_mentioned_p (reg, PATTERN (insn)))
+       if (INSN_P (insn) && reg_overlap_mentioned_p (reg, PATTERN (insn)))
          {
            if (reg_referenced_p (reg, PATTERN (insn)))
              place = insn;
            break;
          }
        else if (GET_CODE (insn) == CALL_INSN
-             && find_reg_fusage (insn, USE, reg))
+                && find_reg_fusage (insn, USE, reg))
          {
            place = insn;
            break;
@@ -12580,7 +12540,7 @@ distribute_links (links)
 
              /* Set added_links_insn to the earliest insn we added a
                 link to.  */
-             if (added_links_insn == 0 
+             if (added_links_insn == 0
                  || INSN_CUID (added_links_insn) > INSN_CUID (place))
                added_links_insn = place;
            }