OSDN Git Service

* reload1.c (move2add_last_cc0): New.
[pf3gnuchains/gcc-fork.git] / gcc / combine.c
index 9415728..f7c9852 100644 (file)
@@ -1,6 +1,6 @@
 /* Optimize by combining instructions for GNU compiler.
    Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+   1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -76,6 +76,8 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 
 #include "config.h"
 #include "system.h"
+#include "coretypes.h"
+#include "tm.h"
 #include "rtl.h"
 #include "tm_p.h"
 #include "flags.h"
@@ -137,6 +139,12 @@ static int max_uid_cuid;
 #define UWIDE_SHIFT_LEFT_BY_BITS_PER_WORD(val) \
   (((unsigned HOST_WIDE_INT) (val) << (BITS_PER_WORD - 1)) << 1)
 
+#define nonzero_bits(X, M) \
+  cached_nonzero_bits (X, M, NULL_RTX, VOIDmode, 0)
+
+#define num_sign_bit_copies(X, M) \
+  cached_num_sign_bit_copies (X, M, NULL_RTX, VOIDmode, 0)
+
 /* Maximum register number, which is the size of the tables below.  */
 
 static unsigned int combine_max_regno;
@@ -167,11 +175,6 @@ static int last_call_cuid;
 
 static rtx subst_insn;
 
-/* This is an insn that belongs before subst_insn, but is not currently
-   on the insn chain.  */
-
-static rtx subst_prev_insn;
-
 /* This is the lowest CUID that `subst' is currently dealing with.
    get_last_value will not return a value if the register was set at or
    after this CUID.  If not for this mechanism, we could get confused if
@@ -192,17 +195,16 @@ static HARD_REG_SET newpat_used_regs;
 
 static rtx added_links_insn;
 
-/* Basic block number of the block in which we are performing combines.  */
-static int this_basic_block;
+/* Basic block in which we are performing combines.  */
+static basic_block 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
    those blocks as starting points.  */
 static sbitmap refresh_blocks;
-static int need_refresh;
 \f
 /* The next group of arrays allows the recording of the last value assigned
-   to (hard or pseudo) register n.  We use this information to see if a
+   to (hard or pseudo) register n.  We use this information to see if an
    operation being processed is redundant given a prior operation performed
    on the register.  For example, an `and' with a constant is redundant if
    all the zero bits are already known to be turned off.
@@ -221,7 +223,7 @@ static int need_refresh;
                                register was assigned
    reg_last_set_table_tick     records the value of label_tick when a
                                value using the register is assigned
-   reg_last_set_invalid                set to non-zero when it is not valid
+   reg_last_set_invalid                set to nonzero when it is not valid
                                to use the value of this register in some
                                register's value
 
@@ -230,7 +232,7 @@ static int need_refresh;
    and the register being validly contained in some other expression in the
    table.
 
-   Entry I in reg_last_set_value is valid if it is non-zero, and either
+   Entry I in reg_last_set_value is valid if it is nonzero, and either
    reg_n_sets[i] is 1 or reg_last_set_label[i] == label_tick.
 
    Register I may validly appear in any expression returned for the value
@@ -242,7 +244,7 @@ static int need_refresh;
    not validly appear in an expression, the register is replaced by
    something that won't match, (clobber (const_int 0)).
 
-   reg_last_set_invalid[i] is set non-zero when register I is being assigned
+   reg_last_set_invalid[i] is set nonzero when register I is being assigned
    to and reg_last_set_table_tick[i] == label_tick.  */
 
 /* Record last value assigned to (hard or pseudo) register n.  */
@@ -259,7 +261,7 @@ static int *reg_last_set_label;
 
 static int *reg_last_set_table_tick;
 
-/* Set non-zero if references to register n in expressions should not be
+/* Set nonzero if references to register n in expressions should not be
    used.  */
 
 static char *reg_last_set_invalid;
@@ -314,8 +316,8 @@ struct undo
 {
   struct undo *next;
   int is_int;
-  union {rtx r; unsigned int i;} old_contents;
-  union {rtx *r; unsigned int *i;} where;
+  union {rtx r; int i;} old_contents;
+  union {rtx *r; int *i;} where;
 };
 
 /* Record a bunch of changes to be undone, up to MAX_UNDO of them.
@@ -339,8 +341,7 @@ static struct undobuf undobuf;
 static int n_occurrences;
 
 static void do_SUBST                   PARAMS ((rtx *, rtx));
-static void do_SUBST_INT               PARAMS ((unsigned int *,
-                                                unsigned int));
+static void do_SUBST_INT               PARAMS ((int *, 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 *));
@@ -376,8 +377,20 @@ static rtx make_field_assignment  PARAMS ((rtx));
 static rtx apply_distributive_law  PARAMS ((rtx));
 static rtx simplify_and_const_int  PARAMS ((rtx, enum machine_mode, rtx,
                                            unsigned HOST_WIDE_INT));
-static unsigned HOST_WIDE_INT nonzero_bits  PARAMS ((rtx, enum machine_mode));
-static unsigned int num_sign_bit_copies  PARAMS ((rtx, enum machine_mode));
+static unsigned HOST_WIDE_INT cached_nonzero_bits
+                               PARAMS ((rtx, enum machine_mode, rtx,
+                                        enum machine_mode,
+                                        unsigned HOST_WIDE_INT));
+static unsigned HOST_WIDE_INT nonzero_bits1
+                               PARAMS ((rtx, enum machine_mode, rtx,
+                                        enum machine_mode,
+                                        unsigned HOST_WIDE_INT));
+static unsigned int cached_num_sign_bit_copies
+                               PARAMS ((rtx, enum machine_mode, rtx,
+                                        enum machine_mode, unsigned int));
+static unsigned int num_sign_bit_copies1
+                               PARAMS ((rtx, enum machine_mode, rtx,
+                                        enum machine_mode, unsigned int));
 static int merge_outer_ops     PARAMS ((enum rtx_code *, HOST_WIDE_INT *,
                                         enum rtx_code, HOST_WIDE_INT,
                                         enum machine_mode, int *));
@@ -449,7 +462,7 @@ do_SUBST (into, newval)
          || (GET_CODE (oldval) == ZERO_EXTEND
              && GET_CODE (XEXP (oldval, 0)) == CONST_INT))
        abort ();
-     }
+    }
 
   if (undobuf.frees)
     buf = undobuf.frees, undobuf.frees = buf->next;
@@ -472,10 +485,10 @@ do_SUBST (into, newval)
 
 static void
 do_SUBST_INT (into, newval)
-     unsigned int *into, newval;
+     int *into, newval;
 {
   struct undo *buf;
-  unsigned int oldval = *into;
+  int oldval = *into;
 
   if (oldval == newval)
     return;
@@ -498,7 +511,7 @@ do_SUBST_INT (into, newval)
 /* Main entry point for combiner.  F is the first insn of the function.
    NREGS is the first unused pseudo-reg number.
 
-   Return non-zero if the combiner has turned an indirect jump
+   Return nonzero if the combiner has turned an indirect jump
    instruction into a direct jump.  */
 int
 combine_instructions (f, nregs)
@@ -572,15 +585,10 @@ combine_instructions (f, nregs)
 
   label_tick = 1;
 
-  /* We need to initialize it here, because record_dead_and_set_regs may call
-     get_last_value.  */
-  subst_prev_insn = NULL_RTX;
-
   setup_incoming_promotions ();
 
-  refresh_blocks = sbitmap_alloc (n_basic_blocks);
+  refresh_blocks = sbitmap_alloc (last_basic_block);
   sbitmap_zero (refresh_blocks);
-  need_refresh = 0;
 
   for (insn = f, i = 0; insn; insn = NEXT_INSN (insn))
     {
@@ -610,139 +618,138 @@ combine_instructions (f, nregs)
 
   /* Now scan all the insns in forward order.  */
 
-  this_basic_block = -1;
   label_tick = 1;
   last_call_cuid = 0;
   mem_last_set = 0;
   init_reg_last_arrays ();
   setup_incoming_promotions ();
 
-  for (insn = f; insn; insn = next ? next : NEXT_INSN (insn))
+  FOR_EACH_BB (this_basic_block)
     {
-      next = 0;
-
-      /* If INSN starts a new basic block, update our basic block number.  */
-      if (this_basic_block + 1 < n_basic_blocks
-         && BLOCK_HEAD (this_basic_block + 1) == insn)
-       this_basic_block++;
-
-      if (GET_CODE (insn) == CODE_LABEL)
-       label_tick++;
-
-      else if (INSN_P (insn))
+      for (insn = this_basic_block->head;
+           insn != NEXT_INSN (this_basic_block->end);
+          insn = next ? next : NEXT_INSN (insn))
        {
-         /* See if we know about function return values before this
-            insn based upon SUBREG flags.  */
-         check_promoted_subreg (insn, PATTERN (insn));
+         next = 0;
 
-         /* Try this insn with each insn it links back to.  */
+         if (GET_CODE (insn) == CODE_LABEL)
+           label_tick++;
 
-         for (links = LOG_LINKS (insn); links; links = XEXP (links, 1))
-           if ((next = try_combine (insn, XEXP (links, 0),
-                                    NULL_RTX, &new_direct_jump_p)) != 0)
-             goto retry;
-
-         /* Try each sequence of three linked insns ending with this one.  */
-
-         for (links = LOG_LINKS (insn); links; links = XEXP (links, 1))
+         else if (INSN_P (insn))
            {
-             rtx link = XEXP (links, 0);
+             /* See if we know about function return values before this
+                insn based upon SUBREG flags.  */
+             check_promoted_subreg (insn, PATTERN (insn));
 
-             /* If the linked insn has been replaced by a note, then there
-                is no point in pursuing this chain any further.  */
-             if (GET_CODE (link) == NOTE)
-               continue;
+             /* Try this insn with each insn it links back to.  */
 
-             for (nextlinks = LOG_LINKS (link);
-                  nextlinks;
-                  nextlinks = XEXP (nextlinks, 1))
-               if ((next = try_combine (insn, link,
-                                        XEXP (nextlinks, 0),
-                                        &new_direct_jump_p)) != 0)
+             for (links = LOG_LINKS (insn); links; links = XEXP (links, 1))
+               if ((next = try_combine (insn, XEXP (links, 0),
+                                        NULL_RTX, &new_direct_jump_p)) != 0)
                  goto retry;
-           }
+
+             /* Try each sequence of three linked insns ending with this one.  */
+
+             for (links = LOG_LINKS (insn); links; links = XEXP (links, 1))
+               {
+                 rtx link = XEXP (links, 0);
+
+                 /* If the linked insn has been replaced by a note, then there
+                    is no point in pursuing this chain any further.  */
+                 if (GET_CODE (link) == NOTE)
+                   continue;
+
+                 for (nextlinks = LOG_LINKS (link);
+                      nextlinks;
+                      nextlinks = XEXP (nextlinks, 1))
+                   if ((next = try_combine (insn, link,
+                                            XEXP (nextlinks, 0),
+                                            &new_direct_jump_p)) != 0)
+                     goto retry;
+               }
 
 #ifdef HAVE_cc0
-         /* Try to combine a jump insn that uses CC0
-            with a preceding insn that sets CC0, and maybe with its
-            logical predecessor as well.
-            This is how we make decrement-and-branch insns.
-            We need this special code because data flow connections
-            via CC0 do not get entered in LOG_LINKS.  */
-
-         if (GET_CODE (insn) == JUMP_INSN
-             && (prev = prev_nonnote_insn (insn)) != 0
-             && GET_CODE (prev) == INSN
-             && sets_cc0_p (PATTERN (prev)))
-           {
-             if ((next = try_combine (insn, prev,
-                                      NULL_RTX, &new_direct_jump_p)) != 0)
-               goto retry;
-
-             for (nextlinks = LOG_LINKS (prev); nextlinks;
-                  nextlinks = XEXP (nextlinks, 1))
-               if ((next = try_combine (insn, prev,
-                                        XEXP (nextlinks, 0),
-                                        &new_direct_jump_p)) != 0)
-                 goto retry;
-           }
+             /* Try to combine a jump insn that uses CC0
+                with a preceding insn that sets CC0, and maybe with its
+                logical predecessor as well.
+                This is how we make decrement-and-branch insns.
+                We need this special code because data flow connections
+                via CC0 do not get entered in LOG_LINKS.  */
+
+             if (GET_CODE (insn) == JUMP_INSN
+                 && (prev = prev_nonnote_insn (insn)) != 0
+                 && GET_CODE (prev) == INSN
+                 && sets_cc0_p (PATTERN (prev)))
+               {
+                 if ((next = try_combine (insn, prev,
+                                          NULL_RTX, &new_direct_jump_p)) != 0)
+                   goto retry;
+
+                 for (nextlinks = LOG_LINKS (prev); nextlinks;
+                      nextlinks = XEXP (nextlinks, 1))
+                   if ((next = try_combine (insn, prev,
+                                            XEXP (nextlinks, 0),
+                                            &new_direct_jump_p)) != 0)
+                     goto retry;
+               }
 
-         /* Do the same for an insn that explicitly references CC0.  */
-         if (GET_CODE (insn) == INSN
-             && (prev = prev_nonnote_insn (insn)) != 0
-             && GET_CODE (prev) == INSN
-             && sets_cc0_p (PATTERN (prev))
-             && GET_CODE (PATTERN (insn)) == SET
-             && reg_mentioned_p (cc0_rtx, SET_SRC (PATTERN (insn))))
-           {
-             if ((next = try_combine (insn, prev,
-                                      NULL_RTX, &new_direct_jump_p)) != 0)
-               goto retry;
+             /* Do the same for an insn that explicitly references CC0.  */
+             if (GET_CODE (insn) == INSN
+                 && (prev = prev_nonnote_insn (insn)) != 0
+                 && GET_CODE (prev) == INSN
+                 && sets_cc0_p (PATTERN (prev))
+                 && GET_CODE (PATTERN (insn)) == SET
+                 && reg_mentioned_p (cc0_rtx, SET_SRC (PATTERN (insn))))
+               {
+                 if ((next = try_combine (insn, prev,
+                                          NULL_RTX, &new_direct_jump_p)) != 0)
+                   goto retry;
+
+                 for (nextlinks = LOG_LINKS (prev); nextlinks;
+                      nextlinks = XEXP (nextlinks, 1))
+                   if ((next = try_combine (insn, prev,
+                                            XEXP (nextlinks, 0),
+                                            &new_direct_jump_p)) != 0)
+                     goto retry;
+               }
 
-             for (nextlinks = LOG_LINKS (prev); nextlinks;
-                  nextlinks = XEXP (nextlinks, 1))
-               if ((next = try_combine (insn, prev,
-                                        XEXP (nextlinks, 0),
-                                        &new_direct_jump_p)) != 0)
+             /* Finally, see if any of the insns that this insn links to
+                explicitly references CC0.  If so, try this insn, that insn,
+                and its predecessor if it sets CC0.  */
+             for (links = LOG_LINKS (insn); links; links = XEXP (links, 1))
+               if (GET_CODE (XEXP (links, 0)) == INSN
+                   && GET_CODE (PATTERN (XEXP (links, 0))) == SET
+                   && reg_mentioned_p (cc0_rtx, SET_SRC (PATTERN (XEXP (links, 0))))
+                   && (prev = prev_nonnote_insn (XEXP (links, 0))) != 0
+                   && GET_CODE (prev) == INSN
+                   && sets_cc0_p (PATTERN (prev))
+                   && (next = try_combine (insn, XEXP (links, 0),
+                                           prev, &new_direct_jump_p)) != 0)
                  goto retry;
-           }
-
-         /* Finally, see if any of the insns that this insn links to
-            explicitly references CC0.  If so, try this insn, that insn,
-            and its predecessor if it sets CC0.  */
-         for (links = LOG_LINKS (insn); links; links = XEXP (links, 1))
-           if (GET_CODE (XEXP (links, 0)) == INSN
-               && GET_CODE (PATTERN (XEXP (links, 0))) == SET
-               && reg_mentioned_p (cc0_rtx, SET_SRC (PATTERN (XEXP (links, 0))))
-               && (prev = prev_nonnote_insn (XEXP (links, 0))) != 0
-               && GET_CODE (prev) == INSN
-               && sets_cc0_p (PATTERN (prev))
-               && (next = try_combine (insn, XEXP (links, 0),
-                                       prev, &new_direct_jump_p)) != 0)
-             goto retry;
 #endif
 
-         /* Try combining an insn with two different insns whose results it
-            uses.  */
-         for (links = LOG_LINKS (insn); links; links = XEXP (links, 1))
-           for (nextlinks = XEXP (links, 1); nextlinks;
-                nextlinks = XEXP (nextlinks, 1))
-             if ((next = try_combine (insn, XEXP (links, 0),
-                                      XEXP (nextlinks, 0),
-                                      &new_direct_jump_p)) != 0)
-               goto retry;
+             /* Try combining an insn with two different insns whose results it
+                uses.  */
+             for (links = LOG_LINKS (insn); links; links = XEXP (links, 1))
+               for (nextlinks = XEXP (links, 1); nextlinks;
+                    nextlinks = XEXP (nextlinks, 1))
+                 if ((next = try_combine (insn, XEXP (links, 0),
+                                          XEXP (nextlinks, 0),
+                                          &new_direct_jump_p)) != 0)
+                   goto retry;
 
-         if (GET_CODE (insn) != NOTE)
-           record_dead_and_set_regs (insn);
+             if (GET_CODE (insn) != NOTE)
+               record_dead_and_set_regs (insn);
 
-       retry:
-         ;
+           retry:
+             ;
+           }
        }
     }
   clear_bb_flags ();
 
-  EXECUTE_IF_SET_IN_SBITMAP (refresh_blocks, 0, this_basic_block,
-                            BASIC_BLOCK (this_basic_block)->flags |= BB_DIRTY);
+  EXECUTE_IF_SET_IN_SBITMAP (refresh_blocks, 0, i,
+                            BASIC_BLOCK (i)->flags |= BB_DIRTY);
   new_direct_jump_p |= purge_all_dead_edges (0);
   delete_noop_moves (f);
 
@@ -860,7 +867,7 @@ set_nonzero_bits_and_sign_copies (x, set, data)
       && REGNO (x) >= FIRST_PSEUDO_REGISTER
       /* If this register is undefined at the start of the file, we can't
         say what its contents were.  */
-      && ! REGNO_REG_SET_P (BASIC_BLOCK (0)->global_live_at_start, REGNO (x))
+      && ! REGNO_REG_SET_P (ENTRY_BLOCK_PTR->next_bb->global_live_at_start, REGNO (x))
       && GET_MODE_BITSIZE (GET_MODE (x)) <= HOST_BITS_PER_WIDE_INT)
     {
       if (set == 0 || GET_CODE (set) == CLOBBER)
@@ -1058,8 +1065,6 @@ can_combine_p (insn, i3, pred, succ, pdest, psrc)
 
   /* Don't eliminate a store in the stack pointer.  */
   if (dest == stack_pointer_rtx
-      /* If we couldn't eliminate a field assignment, we can't combine.  */
-      || GET_CODE (dest) == ZERO_EXTRACT || GET_CODE (dest) == STRICT_LOW_PART
       /* 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))
@@ -1287,13 +1292,13 @@ sets_function_arg_p (pat)
    case, we would be getting the wrong value of I2DEST into I3, so we
    must reject the combination.  This case occurs when I2 and I1 both
    feed into I3, rather than when I1 feeds into I2, which feeds into I3.
-   If I1_NOT_IN_SRC is non-zero, it means that finding I1 in the source
+   If I1_NOT_IN_SRC is nonzero, it means that finding I1 in the source
    of a SET must prevent combination from occurring.
 
    Before doing the above check, we first try to expand a field assignment
    into a set of logical operations.
 
-   If PI3_DEST_KILLED is non-zero, it is a pointer to a location in which
+   If PI3_DEST_KILLED is nonzero, it is a pointer to a location in which
    we place a register that is both set and used within I3.  If more than one
    such register is detected, we fail.
 
@@ -1312,46 +1317,16 @@ combinable_i3pat (i3, loc, i2dest, i1dest, i1_not_in_src, pi3dest_killed)
 
   if (GET_CODE (x) == SET)
     {
-      rtx set = expand_field_assignment (x);
+      rtx set = ;
       rtx dest = SET_DEST (set);
       rtx src = SET_SRC (set);
       rtx inner_dest = dest;
 
-#if 0
-      rtx inner_src = src;
-#endif
-
-      SUBST (*loc, set);
-
       while (GET_CODE (inner_dest) == STRICT_LOW_PART
             || GET_CODE (inner_dest) == SUBREG
             || GET_CODE (inner_dest) == ZERO_EXTRACT)
        inner_dest = XEXP (inner_dest, 0);
 
-  /* We probably don't need this any more now that LIMIT_RELOAD_CLASS
-     was added.  */
-#if 0
-      while (GET_CODE (inner_src) == STRICT_LOW_PART
-            || GET_CODE (inner_src) == SUBREG
-            || GET_CODE (inner_src) == ZERO_EXTRACT)
-       inner_src = XEXP (inner_src, 0);
-
-      /* If it is better that two different modes keep two different pseudos,
-        avoid combining them.  This avoids producing the following pattern
-        on a 386:
-         (set (subreg:SI (reg/v:QI 21) 0)
-              (lshiftrt:SI (reg/v:SI 20)
-                  (const_int 24)))
-        If that were made, reload could not handle the pair of
-        reg 20/21, since it would try to get any GENERAL_REGS
-        but some of them don't handle QImode.  */
-
-      if (rtx_equal_p (inner_src, i2dest)
-         && GET_CODE (inner_dest) == REG
-         && ! MODES_TIEABLE_P (GET_MODE (i2dest), GET_MODE (inner_dest)))
-       return 0;
-#endif
-
       /* Check for the case where I3 modifies its output, as
         discussed above.  */
       if ((inner_dest != dest
@@ -1460,10 +1435,10 @@ cant_combine_insn_p (insn)
   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.
+  /* Never combine loads and stores involving hard regs that are likely
+     to be spilled.  The register allocator can usually handle such
+     reg-reg moves by tying.  If we allow the combiner to make 
+     substitutions of likely-spilled regs, we may abort in reload.
      As an exception, we allow combinations involving fixed regs; these are
      not available to the register allocator so there's no risk involved.  */
 
@@ -1478,9 +1453,11 @@ cant_combine_insn_p (insn)
     dest = SUBREG_REG (dest);
   if (REG_P (src) && REG_P (dest)
       && ((REGNO (src) < FIRST_PSEUDO_REGISTER
-          && ! fixed_regs[REGNO (src)])
+          && ! fixed_regs[REGNO (src)]
+          && CLASS_LIKELY_SPILLED_P (REGNO_REG_CLASS (REGNO (src))))
          || (REGNO (dest) < FIRST_PSEUDO_REGISTER
-             && ! fixed_regs[REGNO (dest)])))
+             && ! fixed_regs[REGNO (dest)]
+             && CLASS_LIKELY_SPILLED_P (REGNO_REG_CLASS (REGNO (dest))))))
     return 1;
 
   return 0;
@@ -1499,7 +1476,7 @@ cant_combine_insn_p (insn)
    If we did the combination, return the insn at which combine should
    resume scanning.
 
-   Set NEW_DIRECT_JUMP_P to a non-zero value if try_combine creates a
+   Set NEW_DIRECT_JUMP_P to a nonzero value if try_combine creates a
    new direct jump instruction.  */
 
 static rtx
@@ -1682,7 +1659,7 @@ try_combine (i3, i2, i1, new_direct_jump_p)
            abort ();
 
          lo &= ~(UWIDE_SHIFT_LEFT_BY_BITS_PER_WORD (1) - 1);
-         lo |= (INTVAL (SET_SRC (PATTERN (i3))) 
+         lo |= (INTVAL (SET_SRC (PATTERN (i3)))
                 & (UWIDE_SHIFT_LEFT_BY_BITS_PER_WORD (1) - 1));
        }
       else if (HOST_BITS_PER_WIDE_INT == BITS_PER_WORD)
@@ -1754,10 +1731,10 @@ try_combine (i3, i2, i1, new_direct_jump_p)
             never appear in the insn stream so giving it the same INSN_UID
             as I2 will not cause a problem.  */
 
-         subst_prev_insn = i1
-           = gen_rtx_INSN (VOIDmode, INSN_UID (i2), NULL_RTX, i2,
-                           XVECEXP (PATTERN (i2), 0, 1), -1, NULL_RTX,
-                           NULL_RTX);
+         i1 = gen_rtx_INSN (VOIDmode, INSN_UID (i2), NULL_RTX, i2,
+                            BLOCK_FOR_INSN (i2), INSN_SCOPE (i2),
+                            XVECEXP (PATTERN (i2), 0, 1), -1, NULL_RTX,
+                            NULL_RTX);
 
          SUBST (PATTERN (i2), XVECEXP (PATTERN (i2), 0, 0));
          SUBST (XEXP (SET_SRC (PATTERN (i2)), 0),
@@ -2167,30 +2144,23 @@ try_combine (i3, i2, i1, new_direct_jump_p)
            }
        }
 
-      /* If we've split a jump pattern, we'll wind up with a sequence even
-        with one instruction.  We can handle that below, so extract it.  */
-      if (m_split && GET_CODE (m_split) == SEQUENCE
-         && XVECLEN (m_split, 0) == 1)
-       m_split = PATTERN (XVECEXP (m_split, 0, 0));
-
-      if (m_split && GET_CODE (m_split) != SEQUENCE)
+      if (m_split && NEXT_INSN (m_split) == NULL_RTX)
        {
+         m_split = PATTERN (m_split);
          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
+      else if (m_split && NEXT_INSN (NEXT_INSN (m_split)) == NULL_RTX
               && (next_real_insn (i2) == i3
-                  || ! use_crosses_set_p (PATTERN (XVECEXP (m_split, 0, 0)),
-                                          INSN_CUID (i2))))
+                  || ! use_crosses_set_p (PATTERN (m_split), INSN_CUID (i2))))
        {
          rtx i2set, i3set;
-         rtx newi3pat = PATTERN (XVECEXP (m_split, 0, 1));
-         newi2pat = PATTERN (XVECEXP (m_split, 0, 0));
+         rtx newi3pat = PATTERN (NEXT_INSN (m_split));
+         newi2pat = PATTERN (m_split);
 
-         i3set = single_set (XVECEXP (m_split, 0, 1));
-         i2set = single_set (XVECEXP (m_split, 0, 0));
+         i3set = single_set (NEXT_INSN (m_split));
+         i2set = single_set (m_split);
 
          /* In case we changed the mode of I2DEST, replace it in the
             pseudo-register table here.  We can't do it above in case this
@@ -2291,8 +2261,19 @@ 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_ZERO_EXTEND  (split_mode,
-                                                SUBREG_REG (*split)));
+           {
+#ifdef LOAD_EXTEND_OP
+             /* Or as a SIGN_EXTEND if LOAD_EXTEND_OP says that that's
+                what it really is.  */
+             if (LOAD_EXTEND_OP (GET_MODE (SUBREG_REG (*split)))
+                 == SIGN_EXTEND)
+               SUBST (*split, gen_rtx_SIGN_EXTEND (split_mode,
+                                                   SUBREG_REG (*split)));
+             else
+#endif
+               SUBST (*split, gen_rtx_ZERO_EXTEND (split_mode,
+                                                   SUBREG_REG (*split)));
+           }
 #endif
 
          newi2pat = gen_rtx_SET (VOIDmode, newdest, *split);
@@ -2313,6 +2294,10 @@ try_combine (i3, i2, i1, new_direct_jump_p)
      copy.  This saves at least one insn, more if register allocation can
      eliminate the copy.
 
+     We cannot do this if the destination of the first assignment is a
+     condition code register or cc0.  We eliminate this case by making sure
+     the SET_DEST and SET_SRC have the same mode.
+
      We cannot do this if the destination of the second assignment is
      a register that we have already assumed is zero-extended.  Similarly
      for a SUBREG of such a register.  */
@@ -2322,6 +2307,8 @@ try_combine (i3, i2, i1, new_direct_jump_p)
           && XVECLEN (newpat, 0) == 2
           && GET_CODE (XVECEXP (newpat, 0, 0)) == SET
           && GET_CODE (SET_SRC (XVECEXP (newpat, 0, 0))) == SIGN_EXTEND
+          && (GET_MODE (SET_DEST (XVECEXP (newpat, 0, 0)))
+              == GET_MODE (SET_SRC (XVECEXP (newpat, 0, 0))))
           && GET_CODE (XVECEXP (newpat, 0, 1)) == SET
           && rtx_equal_p (SET_SRC (XVECEXP (newpat, 0, 1)),
                           XEXP (SET_SRC (XVECEXP (newpat, 0, 0)), 0))
@@ -2388,8 +2375,8 @@ try_combine (i3, i2, i1, new_direct_jump_p)
             which we know will be a NOTE.  */
 
          for (insn = NEXT_INSN (i3);
-              insn && (this_basic_block == n_basic_blocks - 1
-                       || insn != BLOCK_HEAD (this_basic_block + 1));
+              insn && (this_basic_block->next_bb == EXIT_BLOCK_PTR
+                       || insn != this_basic_block->next_bb->head);
               insn = NEXT_INSN (insn))
            {
              if (INSN_P (insn) && reg_referenced_p (ni2dest, PATTERN (insn)))
@@ -2606,8 +2593,8 @@ try_combine (i3, i2, i1, new_direct_jump_p)
              && ! 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 && (this_basic_block->next_bb == EXIT_BLOCK_PTR
+                         || this_basic_block->head != temp);
                 temp = NEXT_INSN (temp))
              if (temp != i3 && INSN_P (temp))
                for (link = LOG_LINKS (temp); link; link = XEXP (link, 1))
@@ -2820,7 +2807,7 @@ try_combine (i3, i2, i1, new_direct_jump_p)
        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))
+    if (returnjump_p (i3) || any_uncondjump_p (i3))
       {
        *new_direct_jump_p = 1;
 
@@ -2828,6 +2815,18 @@ try_combine (i3, i2, i1, new_direct_jump_p)
            || GET_CODE (temp) != BARRIER)
          emit_barrier_after (i3);
       }
+
+    if (undobuf.other_insn != NULL_RTX
+       && (returnjump_p (undobuf.other_insn)
+           || any_uncondjump_p (undobuf.other_insn)))
+      {
+       *new_direct_jump_p = 1;
+
+       if ((temp = next_nonnote_insn (undobuf.other_insn)) == NULL_RTX
+           || GET_CODE (temp) != BARRIER)
+         emit_barrier_after (undobuf.other_insn);
+      }
+
     /* An NOOP jump does not need barrier, but it does need cleaning up
        of CFG.  */
     if (GET_CODE (newpat) == SET
@@ -2839,10 +2838,6 @@ try_combine (i3, i2, i1, new_direct_jump_p)
   combine_successes++;
   undo_commit ();
 
-  /* Clear this here, so that subsequent get_last_value calls are not
-     affected.  */
-  subst_prev_insn = NULL_RTX;
-
   if (added_links_insn
       && (newi2pat == 0 || INSN_CUID (added_links_insn) < INSN_CUID (i2))
       && INSN_CUID (added_links_insn) < INSN_CUID (i3))
@@ -2871,10 +2866,6 @@ undo_all ()
     }
 
   undobuf.undos = 0;
-
-  /* Clear this here, so that subsequent get_last_value calls are not
-     affected.  */
-  subst_prev_insn = NULL_RTX;
 }
 
 /* We've committed to accepting the changes we made.  Move all
@@ -2960,20 +2951,22 @@ find_split_point (loc, insn)
             we can make put both sources together and make a split point
             in the middle.  */
 
-         if (seq && XVECLEN (seq, 0) == 2
-             && GET_CODE (XVECEXP (seq, 0, 0)) == INSN
-             && GET_CODE (PATTERN (XVECEXP (seq, 0, 0))) == SET
-             && SET_DEST (PATTERN (XVECEXP (seq, 0, 0))) == reg
+         if (seq
+             && NEXT_INSN (seq) != NULL_RTX
+             && NEXT_INSN (NEXT_INSN (seq)) == NULL_RTX
+             && GET_CODE (seq) == INSN
+             && GET_CODE (PATTERN (seq)) == SET
+             && SET_DEST (PATTERN (seq)) == reg
              && ! reg_mentioned_p (reg,
-                                   SET_SRC (PATTERN (XVECEXP (seq, 0, 0))))
-             && GET_CODE (XVECEXP (seq, 0, 1)) == INSN
-             && GET_CODE (PATTERN (XVECEXP (seq, 0, 1))) == SET
-             && SET_DEST (PATTERN (XVECEXP (seq, 0, 1))) == reg
+                                   SET_SRC (PATTERN (seq)))
+             && GET_CODE (NEXT_INSN (seq)) == INSN
+             && GET_CODE (PATTERN (NEXT_INSN (seq))) == SET
+             && SET_DEST (PATTERN (NEXT_INSN (seq))) == reg
              && memory_address_p (GET_MODE (x),
-                                  SET_SRC (PATTERN (XVECEXP (seq, 0, 1)))))
+                                  SET_SRC (PATTERN (NEXT_INSN (seq)))))
            {
-             rtx src1 = SET_SRC (PATTERN (XVECEXP (seq, 0, 0)));
-             rtx src2 = SET_SRC (PATTERN (XVECEXP (seq, 0, 1)));
+             rtx src1 = SET_SRC (PATTERN (seq));
+             rtx src2 = SET_SRC (PATTERN (NEXT_INSN (seq)));
 
              /* Replace the placeholder in SRC2 with SRC1.  If we can
                 find where in SRC2 it was placed, that can become our
@@ -3084,7 +3077,7 @@ find_split_point (loc, insn)
        case AND:
          /* If we are AND'ing with a large constant that is only a single
             bit and the result is only being used in a context where we
-            need to know if it is zero or non-zero, replace it with a bit
+            need to know if it is zero or nonzero, replace it with a bit
             extraction.  This will avoid the large constant, which might
             have taken more than one insn to make.  If the constant were
             not a valid argument to the AND but took only one insn to make,
@@ -3312,10 +3305,10 @@ find_split_point (loc, insn)
 
    `n_occurrences' is incremented each time FROM is replaced.
 
-   IN_DEST is non-zero if we are processing the SET_DEST of a SET.
+   IN_DEST is nonzero if we are processing the SET_DEST of a SET.
 
-   UNIQUE_COPY is non-zero if each substitution must be unique.  We do this
-   by copying if `n_occurrences' is non-zero.  */
+   UNIQUE_COPY is nonzero if each substitution must be unique.  We do this
+   by copying if `n_occurrences' is nonzero.  */
 
 static rtx
 subst (x, from, to, in_dest, unique_copy)
@@ -3496,15 +3489,13 @@ subst (x, from, to, in_dest, unique_copy)
                      )
                    return gen_rtx_CLOBBER (VOIDmode, const0_rtx);
 
-#ifdef CLASS_CANNOT_CHANGE_MODE
+#ifdef CANNOT_CHANGE_MODE_CLASS
                  if (code == SUBREG
                      && GET_CODE (to) == REG
                      && REGNO (to) < FIRST_PSEUDO_REGISTER
-                     && (TEST_HARD_REG_BIT
-                         (reg_class_contents[(int) CLASS_CANNOT_CHANGE_MODE],
-                          REGNO (to)))
-                     && CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (to),
-                                                    GET_MODE (x)))
+                     && REG_CANNOT_CHANGE_MODE_P (REGNO (to),
+                                                  GET_MODE (to),
+                                                  GET_MODE (x)))
                    return gen_rtx_CLOBBER (VOIDmode, const0_rtx);
 #endif
 
@@ -3538,14 +3529,13 @@ subst (x, from, to, in_dest, unique_copy)
 
              if (GET_CODE (new) == CONST_INT && GET_CODE (x) == SUBREG)
                {
-                 if (VECTOR_MODE_P (GET_MODE (x)))
-                   return gen_rtx_CLOBBER (VOIDmode, const0_rtx);
+                 enum machine_mode mode = GET_MODE (x);
 
                  x = simplify_subreg (GET_MODE (x), new,
                                       GET_MODE (SUBREG_REG (x)),
                                       SUBREG_BYTE (x));
                  if (! x)
-                   abort ();
+                   x = gen_rtx_CLOBBER (mode, const0_rtx);
                }
              else if (GET_CODE (new) == CONST_INT
                       && GET_CODE (x) == ZERO_EXTEND)
@@ -3706,6 +3696,8 @@ combine_simplify_rtx (x, op0_mode, last, in_dest)
          if (general_operand (true_rtx, VOIDmode)
              && general_operand (false_rtx, VOIDmode))
            {
+             enum rtx_code reversed;
+
              /* Restarting if we generate a store-flag expression will cause
                 us to loop.  Just drop through in this case.  */
 
@@ -3714,9 +3706,10 @@ combine_simplify_rtx (x, op0_mode, last, in_dest)
              if (true_rtx == const_true_rtx && false_rtx == const0_rtx)
                x = gen_binary (cond_code, mode, cond, cop1);
              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);
+                      && ((reversed = reversed_comparison_code_parts
+                                       (cond_code, cond, cop1, NULL))
+                          != UNKNOWN))
+               x = gen_binary (reversed, mode, cond, cop1);
 
              /* Likewise, we can make the negate of a comparison operation
                 if the result values are - STORE_FLAG_VALUE and zero.  */
@@ -3729,11 +3722,13 @@ combine_simplify_rtx (x, op0_mode, last, in_dest)
                                        mode);
              else if (GET_CODE (false_rtx) == CONST_INT
                       && INTVAL (false_rtx) == - STORE_FLAG_VALUE
-                      && true_rtx == const0_rtx)
+                      && true_rtx == const0_rtx
+                      && ((reversed = reversed_comparison_code_parts
+                                       (cond_code, cond, cop1, NULL))
+                          != UNKNOWN))
                x = simplify_gen_unary (NEG, mode,
-                                       gen_binary (reverse_condition
-                                                   (cond_code),
-                                                   mode, cond, cop1),
+                                       gen_binary (reversed, mode,
+                                                   cond, cop1),
                                        mode);
              else
                return gen_rtx_IF_THEN_ELSE (mode,
@@ -3866,7 +3861,12 @@ combine_simplify_rtx (x, op0_mode, last, in_dest)
 
       /* simplify_subreg can't use gen_lowpart_for_combine.  */
       if (CONSTANT_P (SUBREG_REG (x))
-         && subreg_lowpart_offset (mode, op0_mode) == SUBREG_BYTE (x))
+         && subreg_lowpart_offset (mode, op0_mode) == SUBREG_BYTE (x)
+            /* Don't call gen_lowpart_for_combine if the inner mode
+               is VOIDmode and we cannot simplify it, as SUBREG without
+               inner mode is invalid.  */
+         && (GET_MODE (SUBREG_REG (x)) != VOIDmode
+             || gen_lowpart_common (mode, SUBREG_REG (x))))
        return gen_lowpart_for_combine (mode, SUBREG_REG (x));
 
       if (GET_MODE_CLASS (GET_MODE (SUBREG_REG (x))) == MODE_CC)
@@ -4004,6 +4004,24 @@ combine_simplify_rtx (x, op0_mode, last, in_dest)
        return gen_binary (MINUS, mode, XEXP (XEXP (x, 0), 1),
                           XEXP (XEXP (x, 0), 0));
 
+      /* (neg (plus A B)) is canonicalized to (minus (neg A) B).  */
+      if (GET_CODE (XEXP (x, 0)) == PLUS
+         && !HONOR_SIGNED_ZEROS (mode)
+         && !HONOR_SIGN_DEPENDENT_ROUNDING (mode))
+       {
+         temp = simplify_gen_unary (NEG, mode, XEXP (XEXP (x, 0), 0), mode);
+         temp = combine_simplify_rtx (temp, mode, last, in_dest);
+         return gen_binary (MINUS, mode, temp, XEXP (XEXP (x, 0), 1));
+       }
+
+      /* (neg (mult A B)) becomes (mult (neg A) B).
+         This works even for floating-point values.  */
+      if (GET_CODE (XEXP (x, 0)) == MULT)
+       {
+         temp = simplify_gen_unary (NEG, mode, XEXP (XEXP (x, 0), 0), mode);
+         return gen_binary (MULT, mode, temp, XEXP (XEXP (x, 0), 1));
+       }
+
       /* (neg (xor A 1)) is (plus A -1) if A is known to be either 0 or 1.  */
       if (GET_CODE (XEXP (x, 0)) == XOR && XEXP (XEXP (x, 0), 1) == const1_rtx
          && nonzero_bits (XEXP (XEXP (x, 0), 0), mode) == 1)
@@ -4106,7 +4124,7 @@ combine_simplify_rtx (x, op0_mode, last, in_dest)
       if (TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (mode),
                                 GET_MODE_BITSIZE (GET_MODE (XEXP (x, 0))))
          && num_sign_bit_copies (XEXP (x, 0), GET_MODE (XEXP (x, 0)))
-            >= GET_MODE_BITSIZE (mode) + 1
+            >= (unsigned int) (GET_MODE_BITSIZE (mode) + 1)
          && ! (GET_CODE (XEXP (x, 0)) == LSHIFTRT
                && GET_CODE (XEXP (XEXP (x, 0), 0)) == MULT))
        return gen_lowpart_for_combine (mode, XEXP (x, 0));
@@ -4137,6 +4155,36 @@ combine_simplify_rtx (x, op0_mode, last, in_dest)
          && GET_MODE (XEXP (XEXP (x, 0), 0)) == mode)
        return XEXP (XEXP (x, 0), 0);
 
+      /* (float_truncate:SF (float_truncate:DF foo:XF))
+         = (float_truncate:SF foo:XF).
+        This may elliminate double rounding, so it is unsafe.
+
+         (float_truncate:SF (float_extend:XF foo:DF))
+         = (float_truncate:SF foo:DF).
+
+         (float_truncate:DF (float_extend:XF foo:SF))
+         = (float_extend:SF foo:DF).  */
+      if ((GET_CODE (XEXP (x, 0)) == FLOAT_TRUNCATE
+          && flag_unsafe_math_optimizations)
+         || GET_CODE (XEXP (x, 0)) == FLOAT_EXTEND)
+       return simplify_gen_unary (GET_MODE_SIZE (GET_MODE (XEXP (XEXP (x, 0),
+                                                           0)))
+                                  > GET_MODE_SIZE (mode)
+                                  ? FLOAT_TRUNCATE : FLOAT_EXTEND,
+                                  mode,
+                                  XEXP (XEXP (x, 0), 0), mode);
+
+      /*  (float_truncate (float x)) is (float x)  */
+      if (GET_CODE (XEXP (x, 0)) == FLOAT
+         && (flag_unsafe_math_optimizations
+             || ((unsigned)significand_size (GET_MODE (XEXP (x, 0)))
+                 >= (GET_MODE_BITSIZE (GET_MODE (XEXP (XEXP (x, 0), 0)))
+                     - num_sign_bit_copies (XEXP (XEXP (x, 0), 0),
+                                            GET_MODE (XEXP (XEXP (x, 0), 0)))))))
+       return simplify_gen_unary (FLOAT, mode,
+                                  XEXP (XEXP (x, 0), 0),
+                                  GET_MODE (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.  */
       if ((GET_CODE (XEXP (x, 0)) == ABS
@@ -4153,7 +4201,23 @@ combine_simplify_rtx (x, op0_mode, last, in_dest)
          && GET_CODE (SUBREG_REG (XEXP (x, 0))) == FLOAT_TRUNCATE)
        return SUBREG_REG (XEXP (x, 0));
       break;
+    case FLOAT_EXTEND:
+      /*  (float_extend (float_extend x)) is (float_extend x)
 
+         (float_extend (float x)) is (float x) assuming that double
+         rounding can't happen.
+          */
+      if (GET_CODE (XEXP (x, 0)) == FLOAT_EXTEND
+         || (GET_CODE (XEXP (x, 0)) == FLOAT
+             && ((unsigned)significand_size (GET_MODE (XEXP (x, 0)))
+                 >= (GET_MODE_BITSIZE (GET_MODE (XEXP (XEXP (x, 0), 0)))
+                     - num_sign_bit_copies (XEXP (XEXP (x, 0), 0),
+                                            GET_MODE (XEXP (XEXP (x, 0), 0)))))))
+       return simplify_gen_unary (GET_CODE (XEXP (x, 0)), mode,
+                                  XEXP (XEXP (x, 0), 0),
+                                  GET_MODE (XEXP (XEXP (x, 0), 0)));
+
+      break;
 #ifdef HAVE_cc0
     case COMPARE:
       /* Convert (compare FOO (const_int 0)) to FOO unless we aren't
@@ -4192,6 +4256,19 @@ combine_simplify_rtx (x, op0_mode, last, in_dest)
 #endif
 
     case PLUS:
+      /* Canonicalize (plus (mult (neg B) C) A) to (minus A (mult B C)).
+       */
+      if (GET_CODE (XEXP (x, 0)) == MULT
+         && GET_CODE (XEXP (XEXP (x, 0), 0)) == NEG)
+       {
+         rtx in1, in2;
+
+         in1 = XEXP (XEXP (XEXP (x, 0), 0), 0);
+         in2 = XEXP (XEXP (x, 0), 1);
+         return gen_binary (MINUS, mode, XEXP (x, 1),
+                            gen_binary (MULT, mode, in1, in2));
+       }
+
       /* If we have (plus (plus (A const) B)), associate it so that CONST is
         outermost.  That's because that's the way indexed addresses are
         supposed to appear.  This code used to check many more cases, but
@@ -4248,7 +4325,7 @@ combine_simplify_rtx (x, op0_mode, last, in_dest)
         "a = (b & 8) == 0;"  */
       if (XEXP (x, 1) == constm1_rtx
          && GET_CODE (XEXP (x, 0)) != REG
-         && ! (GET_CODE (XEXP (x,0)) == SUBREG
+         && ! (GET_CODE (XEXP (x, 0)) == SUBREG
                && GET_CODE (SUBREG_REG (XEXP (x, 0))) == REG)
          && nonzero_bits (XEXP (x, 0), mode) == 1)
        return simplify_shift_const (NULL_RTX, ASHIFTRT, mode,
@@ -4298,6 +4375,32 @@ combine_simplify_rtx (x, op0_mode, last, in_dest)
        return simplify_and_const_int (NULL_RTX, mode, XEXP (x, 0),
                                       -INTVAL (XEXP (XEXP (x, 1), 1)) - 1);
 
+      /* Canonicalize (minus A (mult (neg B) C)) to (plus (mult B C) A).
+       */
+      if (GET_CODE (XEXP (x, 1)) == MULT
+         && GET_CODE (XEXP (XEXP (x, 1), 0)) == NEG)
+       {
+         rtx in1, in2;
+
+         in1 = XEXP (XEXP (XEXP (x, 1), 0), 0);
+         in2 = XEXP (XEXP (x, 1), 1);
+         return gen_binary (PLUS, mode, gen_binary (MULT, mode, in1, in2),
+                            XEXP (x, 0));
+       }
+
+      /* Canonicalize (minus (neg A) (mult B C)) to
+        (minus (mult (neg B) C) A).  */
+      if (GET_CODE (XEXP (x, 1)) == MULT
+         && GET_CODE (XEXP (x, 0)) == NEG)
+       {
+         rtx in1, in2;
+
+         in1 = simplify_gen_unary (NEG, mode, XEXP (XEXP (x, 1), 0), mode);
+         in2 = XEXP (XEXP (x, 1), 1);
+         return gen_binary (MINUS, mode, gen_binary (MULT, mode, in1, in2),
+                            XEXP (XEXP (x, 0), 0));
+       }
+
       /* Canonicalize (minus A (plus B C)) to (minus (minus A B) C) for
         integers.  */
       if (GET_CODE (XEXP (x, 1)) == PLUS && INTEGRAL_MODE_P (mode))
@@ -4361,10 +4464,7 @@ combine_simplify_rtx (x, op0_mode, last, in_dest)
         with it.  */
       if (GET_CODE (XEXP (x, 0)) == COMPARE
          || (GET_MODE_CLASS (GET_MODE (XEXP (x, 0))) != MODE_CC
-#ifdef HAVE_cc0
-             && XEXP (x, 0) != cc0_rtx
-#endif
-             ))
+             && ! CC0_P (XEXP (x, 0))))
        {
          rtx op0 = XEXP (x, 0);
          rtx op1 = XEXP (x, 1);
@@ -4486,7 +4586,7 @@ combine_simplify_rtx (x, op0_mode, last, in_dest)
          if (new_code == NE && GET_MODE_CLASS (mode) == MODE_INT
              && GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT
              && ((STORE_FLAG_VALUE & GET_MODE_MASK (mode))
-                 == (unsigned HOST_WIDE_INT) 1 << (GET_MODE_BITSIZE(mode)-1))
+                 == (unsigned HOST_WIDE_INT) 1 << (GET_MODE_BITSIZE (mode) - 1))
              && op1 == const0_rtx
              && mode == GET_MODE (op0)
              && (i = exact_log2 (nonzero_bits (op0, mode))) >= 0)
@@ -4565,6 +4665,13 @@ combine_simplify_rtx (x, op0_mode, last, in_dest)
        SUBST (XEXP (x, 0), XEXP (XEXP (x, 0), 0));
       break;
 
+    case POPCOUNT:
+    case PARITY:
+      /* (pop* (zero_extend <X>)) = (pop* <X>) */
+      if (GET_CODE (XEXP (x, 0)) == ZERO_EXTEND)
+       SUBST (XEXP (x, 0), XEXP (XEXP (x, 0), 0));
+      break;
+
     case FLOAT:
       /* (float (sign_extend <X>)) = (float <X>).  */
       if (GET_CODE (XEXP (x, 0)) == SIGN_EXTEND)
@@ -4584,7 +4691,7 @@ combine_simplify_rtx (x, op0_mode, last, in_dest)
 #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),
+              force_to_mode (XEXP (x, 1), GET_MODE (XEXP (x, 1)),
                              ((HOST_WIDE_INT) 1
                               << exact_log2 (GET_MODE_BITSIZE (GET_MODE (x))))
                              - 1,
@@ -4766,12 +4873,12 @@ simplify_if_then_else (x)
 
   /* Convert a == b ? b : a to "a".  */
   if (true_code == EQ && ! side_effects_p (cond)
-      && (! FLOAT_MODE_P (mode) || flag_unsafe_math_optimizations)
+      && !HONOR_NANS (mode)
       && 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)
-          && (! FLOAT_MODE_P (mode) || flag_unsafe_math_optimizations)
+          && !HONOR_NANS (mode)
           && rtx_equal_p (XEXP (cond, 0), true_rtx)
           && rtx_equal_p (XEXP (cond, 1), false_rtx))
     return true_rtx;
@@ -4832,7 +4939,9 @@ simplify_if_then_else (x)
      neither 1 or -1, but it isn't worth checking for.  */
 
   if ((STORE_FLAG_VALUE == 1 || STORE_FLAG_VALUE == -1)
-      && comparison_p && mode != VOIDmode && ! side_effects_p (x))
+      && comparison_p
+      && GET_MODE_CLASS (mode) == MODE_INT
+      && ! side_effects_p (x))
     {
       rtx t = make_compound_operation (true_rtx, SET);
       rtx f = make_compound_operation (false_rtx, SET);
@@ -4867,7 +4976,8 @@ simplify_if_then_else (x)
               && subreg_lowpart_p (XEXP (XEXP (t, 0), 0))
               && rtx_equal_p (SUBREG_REG (XEXP (XEXP (t, 0), 0)), f)
               && (num_sign_bit_copies (f, GET_MODE (f))
-                  > (GET_MODE_BITSIZE (mode)
+                  > (unsigned int)
+                    (GET_MODE_BITSIZE (mode)
                      - GET_MODE_BITSIZE (GET_MODE (XEXP (XEXP (t, 0), 0))))))
        {
          c1 = XEXP (XEXP (t, 0), 1); z = f; op = GET_CODE (XEXP (t, 0));
@@ -4882,7 +4992,8 @@ simplify_if_then_else (x)
               && subreg_lowpart_p (XEXP (XEXP (t, 0), 1))
               && rtx_equal_p (SUBREG_REG (XEXP (XEXP (t, 0), 1)), f)
               && (num_sign_bit_copies (f, GET_MODE (f))
-                  > (GET_MODE_BITSIZE (mode)
+                  > (unsigned int)
+                    (GET_MODE_BITSIZE (mode)
                      - GET_MODE_BITSIZE (GET_MODE (XEXP (XEXP (t, 0), 1))))))
        {
          c1 = XEXP (XEXP (t, 0), 0); z = f; op = GET_CODE (XEXP (t, 0));
@@ -4982,7 +5093,8 @@ simplify_set (x)
      simplify the expression for the object knowing that we only need the
      low-order bits.  */
 
-  if (GET_MODE_CLASS (mode) == MODE_INT)
+  if (GET_MODE_CLASS (mode) == MODE_INT
+      && GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT)
     {
       src = force_to_mode (src, mode, ~(HOST_WIDE_INT) 0, NULL_RTX, 0);
       SUBST (SET_SRC (x), src);
@@ -4991,11 +5103,9 @@ simplify_set (x)
   /* If we are setting CC0 or if the source is a COMPARE, look for the use of
      the comparison result and try to simplify it unless we already have used
      undobuf.other_insn.  */
-  if ((GET_CODE (src) == COMPARE
-#ifdef HAVE_cc0
-       || dest == cc0_rtx
-#endif
-       )
+  if ((GET_MODE_CLASS (mode) == MODE_CC
+       || GET_CODE (src) == COMPARE
+       || CC0_P (dest))
       && (cc_use = find_single_use (dest, subst_insn, &other_insn)) != 0
       && (undobuf.other_insn == 0 || other_insn == undobuf.other_insn)
       && GET_RTX_CLASS (GET_CODE (*cc_use)) == '<'
@@ -5003,15 +5113,44 @@ simplify_set (x)
     {
       enum rtx_code old_code = GET_CODE (*cc_use);
       enum rtx_code new_code;
-      rtx op0, op1;
+      rtx op0, op1, tmp;
       int other_changed = 0;
       enum machine_mode compare_mode = GET_MODE (dest);
+      enum machine_mode tmp_mode;
 
       if (GET_CODE (src) == COMPARE)
        op0 = XEXP (src, 0), op1 = XEXP (src, 1);
       else
        op0 = src, op1 = const0_rtx;
 
+      /* Check whether the comparison is known at compile time.  */
+      if (GET_MODE (op0) != VOIDmode)
+       tmp_mode = GET_MODE (op0);
+      else if (GET_MODE (op1) != VOIDmode)
+       tmp_mode = GET_MODE (op1);
+      else
+       tmp_mode = compare_mode;
+      tmp = simplify_relational_operation (old_code, tmp_mode, op0, op1);
+      if (tmp != NULL_RTX)
+       {
+         rtx pat = PATTERN (other_insn);
+         undobuf.other_insn = other_insn;
+         SUBST (*cc_use, tmp);
+
+         /* Attempt to simplify CC user.  */
+         if (GET_CODE (pat) == SET)
+           {
+             rtx new = simplify_rtx (SET_SRC (pat));
+             if (new != NULL_RTX)
+               SUBST (SET_SRC (pat), new);
+           }
+
+         /* Convert X into a no-op move.  */
+         SUBST (SET_DEST (x), pc_rtx);
+         SUBST (SET_SRC (x), pc_rtx);
+         return x;
+       }
+
       /* Simplify our comparison, if possible.  */
       new_code = simplify_comparison (old_code, &op0, &op1);
 
@@ -5141,13 +5280,11 @@ simplify_set (x)
       && (GET_MODE_SIZE (GET_MODE (src))
          < GET_MODE_SIZE (GET_MODE (SUBREG_REG (src))))
 #endif
-#ifdef CLASS_CANNOT_CHANGE_MODE
+#ifdef CANNOT_CHANGE_MODE_CLASS
       && ! (GET_CODE (dest) == REG && REGNO (dest) < FIRST_PSEUDO_REGISTER
-           && (TEST_HARD_REG_BIT
-               (reg_class_contents[(int) CLASS_CANNOT_CHANGE_MODE],
-                REGNO (dest)))
-           && CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (src),
-                                          GET_MODE (SUBREG_REG (src))))
+           && REG_CANNOT_CHANGE_MODE_P (REGNO (dest),
+                                        GET_MODE (SUBREG_REG (src)),
+                                        GET_MODE (src)))
 #endif
       && (GET_CODE (dest) == REG
          || (GET_CODE (dest) == SUBREG
@@ -5161,6 +5298,30 @@ simplify_set (x)
       src = SET_SRC (x), dest = SET_DEST (x);
     }
 
+#ifdef HAVE_cc0
+  /* If we have (set (cc0) (subreg ...)), we try to remove the subreg
+     in SRC.  */
+  if (dest == cc0_rtx
+      && GET_CODE (src) == SUBREG
+      && subreg_lowpart_p (src)
+      && (GET_MODE_BITSIZE (GET_MODE (src))
+         < GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (src)))))
+    {
+      rtx inner = SUBREG_REG (src);
+      enum machine_mode inner_mode = GET_MODE (inner);
+
+      /* Here we make sure that we don't have a sign bit on.  */
+      if (GET_MODE_BITSIZE (inner_mode) <= HOST_BITS_PER_WIDE_INT
+         && (nonzero_bits (inner, inner_mode)
+             < ((unsigned HOST_WIDE_INT) 1
+                << (GET_MODE_BITSIZE (GET_MODE (src)) - 1))))
+       {
+         SUBST (SET_SRC (x), inner);
+         src = SET_SRC (x);
+       }
+    }
+#endif
+
 #ifdef LOAD_EXTEND_OP
   /* If we have (set FOO (subreg:M (mem:N BAR) 0)) with M wider than N, this
      would require a paradoxical subreg.  Replace the subreg with a
@@ -5209,16 +5370,16 @@ simplify_set (x)
 
       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;
+       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;
+       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;
+       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;
+       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);
@@ -5599,6 +5760,12 @@ expand_compound_operation (x)
       if (GET_MODE_SIZE (GET_MODE (XEXP (x, 0))) > UNITS_PER_WORD)
        return x;
 
+      /* Reject MODEs that aren't scalar integers because turning vector
+        or complex modes into shifts causes problems.  */
+
+      if (! SCALAR_INT_MODE_P (GET_MODE (XEXP (x, 0))))
+       return x;
+
       len = GET_MODE_BITSIZE (GET_MODE (XEXP (x, 0)));
       /* If the inner object has VOIDmode (the only way this can happen
         is if it is an ASM_OPERANDS), we can't do anything since we don't
@@ -5620,6 +5787,12 @@ expand_compound_operation (x)
          || GET_MODE (XEXP (x, 0)) == VOIDmode)
        return x;
 
+      /* Reject MODEs that aren't scalar integers because turning vector
+        or complex modes into shifts causes problems.  */
+
+      if (! SCALAR_INT_MODE_P (GET_MODE (XEXP (x, 0))))
+       return x;
+
       len = INTVAL (XEXP (x, 1));
       pos = INTVAL (XEXP (x, 2));
 
@@ -5827,12 +6000,12 @@ expand_field_assignment (x)
 
       compute_mode = GET_MODE (inner);
 
-      /* Don't attempt bitwise arithmetic on non-integral modes.  */
-      if (! INTEGRAL_MODE_P (compute_mode))
+      /* Don't attempt bitwise arithmetic on non scalar integer modes.  */
+      if (! SCALAR_INT_MODE_P (compute_mode))
        {
          enum machine_mode imode;
 
-         /* Something is probably seriously wrong if this matches.  */
+         /* Don't do anything for vector or complex integral types.  */
          if (! FLOAT_MODE_P (compute_mode))
            break;
 
@@ -5886,15 +6059,15 @@ 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 nonzero 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
-   SET.  This is used when a ZERO_ or SIGN_EXTRACT isn't needed.  If non-zero,
+   IN_DEST is nonzero if this is a reference in the destination of a
+   SET.  This is used when a ZERO_ or SIGN_EXTRACT isn't needed.  If nonzero,
    a STRICT_LOW_PART will be used, if zero, ZERO_EXTEND or SIGN_EXTEND will
    be used.
 
-   IN_COMPARE is non-zero if we are in a COMPARE.  This means that a
+   IN_COMPARE is nonzero if we are in a COMPARE.  This means that a
    ZERO_EXTRACT should be built even for bits starting at bit 0.
 
    MODE is the desired mode of the result (if IN_DEST == 0).
@@ -5945,6 +6118,21 @@ make_extraction (mode, inner, pos, pos_rtx, len,
        is_mode = GET_MODE (SUBREG_REG (inner));
       inner = SUBREG_REG (inner);
     }
+  else if (GET_CODE (inner) == ASHIFT
+          && GET_CODE (XEXP (inner, 1)) == CONST_INT
+          && pos_rtx == 0 && pos == 0
+          && len > (unsigned HOST_WIDE_INT) INTVAL (XEXP (inner, 1)))
+    {
+      /* We're extracting the least significant bits of an rtx
+        (ashift X (const_int C)), where LEN > C.  Extract the
+        least significant (LEN - C) bits of X, giving an rtx
+        whose mode is MODE, then shift it left C times.  */
+      new = make_extraction (mode, XEXP (inner, 0),
+                            0, 0, len - INTVAL (XEXP (inner, 1)),
+                            unsignedp, in_dest, in_compare);
+      if (new != 0)
+       return gen_rtx_ASHIFT (mode, new, XEXP (inner, 1));
+    }
 
   inner_mode = GET_MODE (inner);
 
@@ -6021,6 +6209,11 @@ make_extraction (mode, inner, pos, pos_rtx, len,
                final_word += (GET_MODE_SIZE (inner_mode)
                               - GET_MODE_SIZE (tmode)) % UNITS_PER_WORD;
 
+             /* Avoid creating invalid subregs, for example when
+                simplifying (x>>32)&255.  */
+             if (final_word >= GET_MODE_SIZE (inner_mode))
+               return NULL_RTX;
+
              new = gen_rtx_SUBREG (tmode, inner, final_word);
            }
          else
@@ -6304,7 +6497,7 @@ extract_left_shift (x, count)
     case PLUS:  case IOR:  case XOR:  case AND:
       /* If we can safely shift this constant and we find the inner shift,
         make a new operation.  */
-      if (GET_CODE (XEXP (x,1)) == CONST_INT
+      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,
@@ -6362,7 +6555,7 @@ make_compound_operation (x, in_code)
               : in_code == COMPARE ? SET : in_code);
 
   /* Process depending on the code of this operation.  If NEW is set
-     non-zero, it will be returned.  */
+     nonzero, it will be returned.  */
 
   switch (code)
     {
@@ -6567,7 +6760,11 @@ 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_fmt_e (GET_CODE (tem), mode, XEXP (tem, 0));
+           {
+             if (! SCALAR_INT_MODE_P (mode))
+               break;
+             tem = gen_rtx_fmt_e (GET_CODE (tem), mode, XEXP (tem, 0));
+           }
          else
            tem = gen_lowpart_for_combine (mode, XEXP (tem, 0));
          return tem;
@@ -6635,7 +6832,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 nonzero 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
@@ -6698,22 +6895,19 @@ force_to_mode (x, mode, mask, reg, just_select)
 
   /* If none of the bits in X are needed, return a zero.  */
   if (! just_select && (nonzero & mask) == 0)
-    return const0_rtx;
+    x = const0_rtx;
 
   /* If X is a CONST_INT, return a new one.  Do this here since the
      test below will fail.  */
   if (GET_CODE (x) == CONST_INT)
     {
-      HOST_WIDE_INT cval = INTVAL (x) & mask;
-      int width = GET_MODE_BITSIZE (mode);
-
-      /* If MODE is narrower that HOST_WIDE_INT and CVAL is a negative
-        number, sign extend it.  */
-      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 (SCALAR_INT_MODE_P (mode))
+        return gen_int_mode (INTVAL (x) & mask, mode);
+      else
+       {
+         x = GEN_INT (INTVAL (x) & mask);
+         return gen_lowpart_common (mode, x);
+       }
     }
 
   /* If X is narrower than MODE and we want all the bits in X's mode, just
@@ -6787,7 +6981,7 @@ force_to_mode (x, mode, mask, reg, just_select)
 
          if (GET_CODE (x) == AND && GET_CODE (XEXP (x, 1)) == CONST_INT
              && ((INTVAL (XEXP (x, 1)) & GET_MODE_MASK (GET_MODE (x)))
-                 == (HOST_WIDE_INT) mask))
+                 == mask))
            x = XEXP (x, 0);
 
          /* If it remains an AND, try making another AND with the bits
@@ -6868,10 +7062,10 @@ force_to_mode (x, mode, mask, reg, just_select)
          return force_to_mode (x, mode, mask, reg, next_select);
        }
 
-      /* Similarly, if C contains every bit in the mask, then we may
+      /* Similarly, if C contains every bit in the fuller_mask, then we may
         replace with (not Y).  */
       if (GET_CODE (XEXP (x, 0)) == CONST_INT
-         && ((INTVAL (XEXP (x, 0)) | (HOST_WIDE_INT) mask)
+         && ((INTVAL (XEXP (x, 0)) | (HOST_WIDE_INT) fuller_mask)
              == INTVAL (XEXP (x, 0))))
        {
          x = simplify_gen_unary (NOT, GET_MODE (x),
@@ -6920,14 +7114,6 @@ force_to_mode (x, mode, mask, reg, just_select)
                                     force_to_mode (XEXP (x, 1), mode, mask,
                                                    reg, next_select));
 
-      /* If OP1 is a CONST_INT and X is an IOR or XOR, clear bits outside
-        MASK since OP1 might have been sign-extended but we never want
-        to turn on extra bits, since combine might have previously relied
-        on them being off.  */
-      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;
@@ -7113,7 +7299,7 @@ force_to_mode (x, mode, mask, reg, just_select)
          temp = simplify_binary_operation (code == ROTATE ? ROTATERT : ROTATE,
                                            GET_MODE (x), GEN_INT (mask),
                                            XEXP (x, 1));
-         if (temp && GET_CODE(temp) == CONST_INT)
+         if (temp && GET_CODE (temp) == CONST_INT)
            SUBST (XEXP (x, 0),
                   force_to_mode (XEXP (x, 0), GET_MODE (x),
                                  INTVAL (temp), reg, next_select));
@@ -7144,7 +7330,8 @@ force_to_mode (x, mode, mask, reg, just_select)
              < GET_MODE_BITSIZE (GET_MODE (x)))
          && INTVAL (XEXP (XEXP (x, 0), 1)) < HOST_BITS_PER_WIDE_INT)
        {
-         temp = GEN_INT (mask << INTVAL (XEXP (XEXP (x, 0), 1)));
+         temp = gen_int_mode (mask << INTVAL (XEXP (XEXP (x, 0), 1)),
+                              GET_MODE (x));
          temp = gen_binary (XOR, GET_MODE (x), XEXP (XEXP (x, 0), 0), temp);
          x = gen_binary (LSHIFTRT, GET_MODE (x), temp, XEXP (XEXP (x, 0), 1));
 
@@ -7169,7 +7356,8 @@ force_to_mode (x, mode, mask, reg, just_select)
         which is equal to STORE_FLAG_VALUE.  */
       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)
+         && (nonzero_bits (XEXP (x, 0), mode)
+             == (unsigned HOST_WIDE_INT) STORE_FLAG_VALUE))
        return force_to_mode (XEXP (x, 0), mode, mask, reg, next_select);
 
       break;
@@ -7185,7 +7373,7 @@ force_to_mode (x, mode, mask, reg, just_select)
       SUBST (XEXP (x, 2),
             gen_lowpart_for_combine (GET_MODE (x),
                                      force_to_mode (XEXP (x, 2), mode,
-                                                    mask, reg,next_select)));
+                                                    mask, reg, next_select)));
       break;
 
     default:
@@ -7264,7 +7452,7 @@ if_then_else_cond (x, ptrue, pfalse)
        }
 
       /* See if we have PLUS, IOR, XOR, MINUS or UMAX, where one of the
-        operands is zero when the other is non-zero, and vice-versa,
+        operands is zero when the other is nonzero, and vice-versa,
         and STORE_FLAG_VALUE is 1 or -1.  */
 
       if ((STORE_FLAG_VALUE == 1 || STORE_FLAG_VALUE == -1)
@@ -7707,6 +7895,17 @@ make_field_assignment (x)
                       : ((unsigned HOST_WIDE_INT) 1 << len) - 1,
                       dest, 0);
 
+  /* If SRC is masked by an AND that does not make a difference in
+     the value being stored, strip it.  */
+  if (GET_CODE (assign) == ZERO_EXTRACT
+      && GET_CODE (XEXP (assign, 1)) == CONST_INT
+      && INTVAL (XEXP (assign, 1)) < HOST_BITS_PER_WIDE_INT
+      && GET_CODE (src) == AND
+      && GET_CODE (XEXP (src, 1)) == CONST_INT
+      && ((unsigned HOST_WIDE_INT) INTVAL (XEXP (src, 1))
+         == ((unsigned HOST_WIDE_INT) 1 << INTVAL (XEXP (assign, 1))) - 1))
+    src = XEXP (src, 0);
+
   return gen_rtx_SET (VOIDmode, assign, src);
 }
 \f
@@ -7961,23 +8160,76 @@ simplify_and_const_int (x, mode, varop, constop)
   return x;
 }
 \f
+#define nonzero_bits_with_known(X, MODE) \
+  cached_nonzero_bits (X, MODE, known_x, known_mode, known_ret)
+
+/* The function cached_nonzero_bits is a wrapper around nonzero_bits1.
+   It avoids exponential behavior in nonzero_bits1 when X has
+   identical subexpressions on the first or the second level.  */
+
+static unsigned HOST_WIDE_INT
+cached_nonzero_bits (x, mode, known_x, known_mode, known_ret)
+     rtx x;
+     enum machine_mode mode;
+     rtx known_x;
+     enum machine_mode known_mode;
+     unsigned HOST_WIDE_INT known_ret;
+{
+  if (x == known_x && mode == known_mode)
+    return known_ret;
+
+  /* Try to find identical subexpressions.  If found call
+     nonzero_bits1 on X with the subexpressions as KNOWN_X and the
+     precomputed value for the subexpression as KNOWN_RET.  */
+
+  if (GET_RTX_CLASS (GET_CODE (x)) == '2'
+      || GET_RTX_CLASS (GET_CODE (x)) == 'c')
+    {
+      rtx x0 = XEXP (x, 0);
+      rtx x1 = XEXP (x, 1);
+
+      /* Check the first level.  */
+      if (x0 == x1)
+       return nonzero_bits1 (x, mode, x0, mode,
+                             nonzero_bits_with_known (x0, mode));
+
+      /* Check the second level.  */
+      if ((GET_RTX_CLASS (GET_CODE (x0)) == '2'
+          || GET_RTX_CLASS (GET_CODE (x0)) == 'c')
+         && (x1 == XEXP (x0, 0) || x1 == XEXP (x0, 1)))
+       return nonzero_bits1 (x, mode, x1, mode,
+                             nonzero_bits_with_known (x1, mode));
+
+      if ((GET_RTX_CLASS (GET_CODE (x1)) == '2'
+          || GET_RTX_CLASS (GET_CODE (x1)) == 'c')
+         && (x0 == XEXP (x1, 0) || x0 == XEXP (x1, 1)))
+       return nonzero_bits1 (x, mode, x0, mode,
+                        nonzero_bits_with_known (x0, mode));
+    }
+
+  return nonzero_bits1 (x, mode, known_x, known_mode, known_ret);
+}
+
 /* We let num_sign_bit_copies recur into nonzero_bits as that is useful.
    We don't let nonzero_bits recur into num_sign_bit_copies, because that
    is less useful.  We can't allow both, because that results in exponential
    run time recursion.  There is a nullstone testcase that triggered
    this.  This macro avoids accidental uses of num_sign_bit_copies.  */
-#define num_sign_bit_copies()
+#define cached_num_sign_bit_copies()
 
-/* Given an expression, X, compute which bits in X can be non-zero.
+/* Given an expression, X, compute which bits in X can be nonzero.
    We don't care about bits outside of those defined in MODE.
 
    For most X this is simply GET_MODE_MASK (GET_MODE (MODE)), but if X is
    a shift, AND, or zero_extract, we can do better.  */
 
 static unsigned HOST_WIDE_INT
-nonzero_bits (x, mode)
+nonzero_bits1 (x, mode, known_x, known_mode, known_ret)
      rtx x;
      enum machine_mode mode;
+     rtx known_x;
+     enum machine_mode known_mode;
+     unsigned HOST_WIDE_INT known_ret;
 {
   unsigned HOST_WIDE_INT nonzero = GET_MODE_MASK (mode);
   unsigned HOST_WIDE_INT inner_nz;
@@ -8015,7 +8267,7 @@ nonzero_bits (x, mode)
       && GET_MODE_BITSIZE (GET_MODE (x)) <= HOST_BITS_PER_WIDE_INT
       && GET_MODE_BITSIZE (mode) > GET_MODE_BITSIZE (GET_MODE (x)))
     {
-      nonzero &= nonzero_bits (x, GET_MODE (x));
+      nonzero &= nonzero_bits_with_known (x, GET_MODE (x));
       nonzero |= GET_MODE_MASK (mode) & ~GET_MODE_MASK (GET_MODE (x));
       return nonzero;
     }
@@ -8068,7 +8320,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 (ENTRY_BLOCK_PTR->next_bb->global_live_at_start,
                                        REGNO (x))))
          && INSN_CUID (reg_last_set[REGNO (x)]) < subst_low_cuid)
        return reg_last_set_nonzero_bits[REGNO (x)] & nonzero;
@@ -8097,7 +8349,7 @@ nonzero_bits (x, mode)
                           | ((HOST_WIDE_INT) (-1)
                              << GET_MODE_BITSIZE (GET_MODE (x))));
 #endif
-         return nonzero_bits (tem, mode) & nonzero;
+         return nonzero_bits_with_known (tem, mode) & nonzero;
        }
       else if (nonzero_sign_valid && reg_nonzero_bits[REGNO (x)])
        {
@@ -8172,11 +8424,12 @@ nonzero_bits (x, mode)
       break;
 
     case TRUNCATE:
-      nonzero &= (nonzero_bits (XEXP (x, 0), mode) & GET_MODE_MASK (mode));
+      nonzero &= (nonzero_bits_with_known (XEXP (x, 0), mode)
+                 & GET_MODE_MASK (mode));
       break;
 
     case ZERO_EXTEND:
-      nonzero &= nonzero_bits (XEXP (x, 0), mode);
+      nonzero &= nonzero_bits_with_known (XEXP (x, 0), mode);
       if (GET_MODE (XEXP (x, 0)) != VOIDmode)
        nonzero &= GET_MODE_MASK (GET_MODE (XEXP (x, 0)));
       break;
@@ -8184,8 +8437,8 @@ nonzero_bits (x, mode)
     case SIGN_EXTEND:
       /* If the sign bit is known clear, this is the same as ZERO_EXTEND.
         Otherwise, show all the bits in the outer mode but not the inner
-        may be non-zero.  */
-      inner_nz = nonzero_bits (XEXP (x, 0), mode);
+        may be nonzero.  */
+      inner_nz = nonzero_bits_with_known (XEXP (x, 0), mode);
       if (GET_MODE (XEXP (x, 0)) != VOIDmode)
        {
          inner_nz &= GET_MODE_MASK (GET_MODE (XEXP (x, 0)));
@@ -8200,19 +8453,21 @@ nonzero_bits (x, mode)
       break;
 
     case AND:
-      nonzero &= (nonzero_bits (XEXP (x, 0), mode)
-                 & nonzero_bits (XEXP (x, 1), mode));
+      nonzero &= (nonzero_bits_with_known (XEXP (x, 0), mode)
+                 & nonzero_bits_with_known (XEXP (x, 1), mode));
       break;
 
     case XOR:   case IOR:
     case UMIN:  case UMAX:  case SMIN:  case SMAX:
       {
-       unsigned HOST_WIDE_INT nonzero0 = nonzero_bits (XEXP (x, 0), mode);
+       unsigned HOST_WIDE_INT nonzero0 =
+         nonzero_bits_with_known (XEXP (x, 0), mode);
 
        /* Don't call nonzero_bits for the second time if it cannot change
           anything.  */
        if ((nonzero & nonzero0) != nonzero)
-         nonzero &= (nonzero0 | nonzero_bits (XEXP (x, 1), mode));
+         nonzero &= (nonzero0
+                     | nonzero_bits_with_known (XEXP (x, 1), mode));
       }
       break;
 
@@ -8222,19 +8477,22 @@ nonzero_bits (x, mode)
     case MOD:   case UMOD:
       /* We can apply the rules of arithmetic to compute the number of
         high- and low-order zero bits of these operations.  We start by
-        computing the width (position of the highest-order non-zero bit)
+        computing the width (position of the highest-order nonzero bit)
         and the number of low-order zero bits for each value.  */
       {
-       unsigned HOST_WIDE_INT nz0 = nonzero_bits (XEXP (x, 0), mode);
-       unsigned HOST_WIDE_INT nz1 = nonzero_bits (XEXP (x, 1), mode);
+       unsigned HOST_WIDE_INT nz0 =
+         nonzero_bits_with_known (XEXP (x, 0), mode);
+       unsigned HOST_WIDE_INT nz1 =
+         nonzero_bits_with_known (XEXP (x, 1), mode);
+       int sign_index = GET_MODE_BITSIZE (GET_MODE (x)) - 1;
        int width0 = floor_log2 (nz0) + 1;
        int width1 = floor_log2 (nz1) + 1;
        int low0 = floor_log2 (nz0 & -nz0);
        int low1 = floor_log2 (nz1 & -nz1);
        HOST_WIDE_INT op0_maybe_minusp
-         = (nz0 & ((HOST_WIDE_INT) 1 << (mode_width - 1)));
+         = (nz0 & ((HOST_WIDE_INT) 1 << sign_index));
        HOST_WIDE_INT op1_maybe_minusp
-         = (nz1 & ((HOST_WIDE_INT) 1 << (mode_width - 1)));
+         = (nz1 & ((HOST_WIDE_INT) 1 << sign_index));
        unsigned int result_width = mode_width;
        int result_low = 0;
 
@@ -8310,7 +8568,7 @@ nonzero_bits (x, mode)
 
       if (SUBREG_PROMOTED_VAR_P (x) && SUBREG_PROMOTED_UNSIGNED_P (x) > 0)
        nonzero = (GET_MODE_MASK (GET_MODE (x))
-                  & nonzero_bits (SUBREG_REG (x), GET_MODE (x)));
+                  & nonzero_bits_with_known (SUBREG_REG (x), GET_MODE (x)));
 
       /* If the inner mode is a single word for both the host and target
         machines, we can compute this from which bits of the inner
@@ -8319,17 +8577,18 @@ nonzero_bits (x, mode)
          && (GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (x)))
              <= HOST_BITS_PER_WIDE_INT))
        {
-         nonzero &= nonzero_bits (SUBREG_REG (x), mode);
+         nonzero &= nonzero_bits_with_known (SUBREG_REG (x), mode);
 
 #if defined (WORD_REGISTER_OPERATIONS) && defined (LOAD_EXTEND_OP)
          /* If this is a typical RISC machine, we only have to worry
             about the way loads are extended.  */
-         if (LOAD_EXTEND_OP (GET_MODE (SUBREG_REG (x))) == SIGN_EXTEND
-             ? (((nonzero
-                  & (((unsigned HOST_WIDE_INT) 1
-                      << (GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (x))) - 1))))
-                 != 0))
-             : LOAD_EXTEND_OP (GET_MODE (SUBREG_REG (x))) != ZERO_EXTEND)
+         if ((LOAD_EXTEND_OP (GET_MODE (SUBREG_REG (x))) == SIGN_EXTEND
+              ? (((nonzero
+                   & (((unsigned HOST_WIDE_INT) 1
+                       << (GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (x))) - 1))))
+                  != 0))
+              : LOAD_EXTEND_OP (GET_MODE (SUBREG_REG (x))) != ZERO_EXTEND)
+             || GET_CODE (SUBREG_REG (x)) != MEM)
 #endif
            {
              /* On many CISC machines, accessing an object in a wider mode
@@ -8361,7 +8620,8 @@ nonzero_bits (x, mode)
          unsigned int width = GET_MODE_BITSIZE (inner_mode);
          int count = INTVAL (XEXP (x, 1));
          unsigned HOST_WIDE_INT mode_mask = GET_MODE_MASK (inner_mode);
-         unsigned HOST_WIDE_INT op_nonzero = nonzero_bits (XEXP (x, 0), mode);
+         unsigned HOST_WIDE_INT op_nonzero =
+           nonzero_bits_with_known (XEXP (x, 0), mode);
          unsigned HOST_WIDE_INT inner = op_nonzero & mode_mask;
          unsigned HOST_WIDE_INT outer = 0;
 
@@ -8391,13 +8651,36 @@ nonzero_bits (x, mode)
       break;
 
     case FFS:
+    case POPCOUNT:
       /* This is at most the number of bits in the mode.  */
-      nonzero = ((HOST_WIDE_INT) 1 << (floor_log2 (mode_width) + 1)) - 1;
+      nonzero = ((HOST_WIDE_INT) 2 << (floor_log2 (mode_width))) - 1;
+      break;
+
+    case CLZ:
+      /* If CLZ has a known value at zero, then the nonzero bits are
+        that value, plus the number of bits in the mode minus one.  */
+      if (CLZ_DEFINED_VALUE_AT_ZERO (mode, nonzero))
+       nonzero |= ((HOST_WIDE_INT) 1 << (floor_log2 (mode_width))) - 1;
+      else
+       nonzero = -1;
+      break;
+
+    case CTZ:
+      /* If CTZ has a known value at zero, then the nonzero bits are
+        that value, plus the number of bits in the mode minus one.  */
+      if (CTZ_DEFINED_VALUE_AT_ZERO (mode, nonzero))
+       nonzero |= ((HOST_WIDE_INT) 1 << (floor_log2 (mode_width))) - 1;
+      else
+       nonzero = -1;
+      break;
+
+    case PARITY:
+      nonzero = 1;
       break;
 
     case IF_THEN_ELSE:
-      nonzero &= (nonzero_bits (XEXP (x, 1), mode)
-                 | nonzero_bits (XEXP (x, 2), mode));
+      nonzero &= (nonzero_bits_with_known (XEXP (x, 1), mode)
+                 | nonzero_bits_with_known (XEXP (x, 2), mode));
       break;
 
     default:
@@ -8408,17 +8691,74 @@ nonzero_bits (x, mode)
 }
 
 /* See the macro definition above.  */
-#undef num_sign_bit_copies
+#undef cached_num_sign_bit_copies
 \f
+#define num_sign_bit_copies_with_known(X, M) \
+  cached_num_sign_bit_copies (X, M, known_x, known_mode, known_ret)
+
+/* The function cached_num_sign_bit_copies is a wrapper around
+   num_sign_bit_copies1.  It avoids exponential behavior in
+   num_sign_bit_copies1 when X has identical subexpressions on the
+   first or the second level.  */
+
+static unsigned int
+cached_num_sign_bit_copies (x, mode, known_x, known_mode, known_ret)
+     rtx x;
+     enum machine_mode mode;
+     rtx known_x;
+     enum machine_mode known_mode;
+     unsigned int known_ret;
+{
+  if (x == known_x && mode == known_mode)
+    return known_ret;
+
+  /* Try to find identical subexpressions.  If found call
+     num_sign_bit_copies1 on X with the subexpressions as KNOWN_X and
+     the precomputed value for the subexpression as KNOWN_RET.  */
+
+  if (GET_RTX_CLASS (GET_CODE (x)) == '2'
+      || GET_RTX_CLASS (GET_CODE (x)) == 'c')
+    {
+      rtx x0 = XEXP (x, 0);
+      rtx x1 = XEXP (x, 1);
+
+      /* Check the first level.  */
+      if (x0 == x1)
+       return
+         num_sign_bit_copies1 (x, mode, x0, mode,
+                               num_sign_bit_copies_with_known (x0, mode));
+
+      /* Check the second level.  */
+      if ((GET_RTX_CLASS (GET_CODE (x0)) == '2'
+          || GET_RTX_CLASS (GET_CODE (x0)) == 'c')
+         && (x1 == XEXP (x0, 0) || x1 == XEXP (x0, 1)))
+       return
+         num_sign_bit_copies1 (x, mode, x1, mode,
+                               num_sign_bit_copies_with_known (x1, mode));
+
+      if ((GET_RTX_CLASS (GET_CODE (x1)) == '2'
+          || GET_RTX_CLASS (GET_CODE (x1)) == 'c')
+         && (x0 == XEXP (x1, 0) || x0 == XEXP (x1, 1)))
+       return
+         num_sign_bit_copies1 (x, mode, x0, mode,
+                               num_sign_bit_copies_with_known (x0, mode));
+    }
+
+  return num_sign_bit_copies1 (x, mode, known_x, known_mode, known_ret);
+}
+
 /* Return the number of bits at the high-order end of X that are known to
    be equal to the sign bit.  X will be used in mode MODE; if MODE is
    VOIDmode, X will be used in its own mode.  The returned value  will always
    be between 1 and the number of bits in MODE.  */
 
 static unsigned int
-num_sign_bit_copies (x, mode)
+num_sign_bit_copies1 (x, mode, known_x, known_mode, known_ret)
      rtx x;
      enum machine_mode mode;
+     rtx known_x;
+     enum machine_mode known_mode;
+     unsigned int known_ret;
 {
   enum rtx_code code = GET_CODE (x);
   unsigned int bitwidth;
@@ -8441,7 +8781,7 @@ num_sign_bit_copies (x, mode)
   /* For a smaller object, just ignore the high bits.  */
   if (bitwidth < GET_MODE_BITSIZE (GET_MODE (x)))
     {
-      num0 = num_sign_bit_copies (x, GET_MODE (x));
+      num0 = num_sign_bit_copies_with_known (x, GET_MODE (x));
       return MAX (1,
                  num0 - (int) (GET_MODE_BITSIZE (GET_MODE (x)) - bitwidth));
     }
@@ -8483,14 +8823,14 @@ num_sign_bit_copies (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 (ENTRY_BLOCK_PTR->next_bb->global_live_at_start,
                                        REGNO (x))))
          && INSN_CUID (reg_last_set[REGNO (x)]) < subst_low_cuid)
        return reg_last_set_sign_bit_copies[REGNO (x)];
 
       tem = get_last_value (x);
       if (tem != 0)
-       return num_sign_bit_copies (tem, mode);
+       return num_sign_bit_copies_with_known (tem, mode);
 
       if (nonzero_sign_valid && reg_sign_bit_copies[REGNO (x)] != 0
          && GET_MODE_BITSIZE (GET_MODE (x)) == bitwidth)
@@ -8523,7 +8863,7 @@ num_sign_bit_copies (x, mode)
 
       if (SUBREG_PROMOTED_VAR_P (x) && ! SUBREG_PROMOTED_UNSIGNED_P (x))
        {
-         num0 = num_sign_bit_copies (SUBREG_REG (x), mode);
+         num0 = num_sign_bit_copies_with_known (SUBREG_REG (x), mode);
          return MAX ((int) bitwidth
                      - (int) GET_MODE_BITSIZE (GET_MODE (x)) + 1,
                      num0);
@@ -8532,7 +8872,7 @@ num_sign_bit_copies (x, mode)
       /* For a smaller object, just ignore the high bits.  */
       if (bitwidth <= GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (x))))
        {
-         num0 = num_sign_bit_copies (SUBREG_REG (x), VOIDmode);
+         num0 = num_sign_bit_copies_with_known (SUBREG_REG (x), VOIDmode);
          return MAX (1, (num0
                          - (int) (GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (x)))
                                   - bitwidth)));
@@ -8552,8 +8892,9 @@ num_sign_bit_copies (x, mode)
 
       if ((GET_MODE_SIZE (GET_MODE (x))
           > GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))))
-         && LOAD_EXTEND_OP (GET_MODE (SUBREG_REG (x))) == SIGN_EXTEND)
-       return num_sign_bit_copies (SUBREG_REG (x), mode);
+         && LOAD_EXTEND_OP (GET_MODE (SUBREG_REG (x))) == SIGN_EXTEND
+         && GET_CODE (SUBREG_REG (x)) == MEM)
+       return num_sign_bit_copies_with_known (SUBREG_REG (x), mode);
 #endif
 #endif
       break;
@@ -8565,16 +8906,16 @@ num_sign_bit_copies (x, mode)
 
     case SIGN_EXTEND:
       return (bitwidth - GET_MODE_BITSIZE (GET_MODE (XEXP (x, 0)))
-             + num_sign_bit_copies (XEXP (x, 0), VOIDmode));
+             + num_sign_bit_copies_with_known (XEXP (x, 0), VOIDmode));
 
     case TRUNCATE:
       /* For a smaller object, just ignore the high bits.  */
-      num0 = num_sign_bit_copies (XEXP (x, 0), VOIDmode);
+      num0 = num_sign_bit_copies_with_known (XEXP (x, 0), VOIDmode);
       return MAX (1, (num0 - (int) (GET_MODE_BITSIZE (GET_MODE (XEXP (x, 0)))
                                    - bitwidth)));
 
     case NOT:
-      return num_sign_bit_copies (XEXP (x, 0), mode);
+      return num_sign_bit_copies_with_known (XEXP (x, 0), mode);
 
     case ROTATE:       case ROTATERT:
       /* If we are rotating left by a number of bits less than the number
@@ -8584,7 +8925,7 @@ num_sign_bit_copies (x, mode)
          && INTVAL (XEXP (x, 1)) >= 0
          && INTVAL (XEXP (x, 1)) < (int) bitwidth)
        {
-         num0 = num_sign_bit_copies (XEXP (x, 0), mode);
+         num0 = num_sign_bit_copies_with_known (XEXP (x, 0), mode);
          return MAX (1, num0 - (code == ROTATE ? INTVAL (XEXP (x, 1))
                                 : (int) bitwidth - INTVAL (XEXP (x, 1))));
        }
@@ -8595,7 +8936,7 @@ num_sign_bit_copies (x, mode)
         is known to be positive, the number of sign bit copies is the
         same as that of the input.  Finally, if the input has just one bit
         that might be nonzero, all the bits are copies of the sign bit.  */
-      num0 = num_sign_bit_copies (XEXP (x, 0), mode);
+      num0 = num_sign_bit_copies_with_known (XEXP (x, 0), mode);
       if (bitwidth > HOST_BITS_PER_WIDE_INT)
        return num0 > 1 ? num0 - 1 : 1;
 
@@ -8613,8 +8954,8 @@ num_sign_bit_copies (x, mode)
     case SMIN:  case SMAX:  case UMIN:  case UMAX:
       /* Logical operations will preserve the number of sign-bit copies.
         MIN and MAX operations always return one of the operands.  */
-      num0 = num_sign_bit_copies (XEXP (x, 0), mode);
-      num1 = num_sign_bit_copies (XEXP (x, 1), mode);
+      num0 = num_sign_bit_copies_with_known (XEXP (x, 0), mode);
+      num1 = num_sign_bit_copies_with_known (XEXP (x, 1), mode);
       return MIN (num0, num1);
 
     case PLUS:  case MINUS:
@@ -8632,8 +8973,8 @@ num_sign_bit_copies (x, mode)
                    : bitwidth - floor_log2 (nonzero) - 1);
        }
 
-      num0 = num_sign_bit_copies (XEXP (x, 0), mode);
-      num1 = num_sign_bit_copies (XEXP (x, 1), mode);
+      num0 = num_sign_bit_copies_with_known (XEXP (x, 0), mode);
+      num1 = num_sign_bit_copies_with_known (XEXP (x, 1), mode);
       result = MAX (1, MIN (num0, num1) - 1);
 
 #ifdef POINTERS_EXTEND_UNSIGNED
@@ -8655,8 +8996,8 @@ num_sign_bit_copies (x, mode)
         to be positive, we must allow for an additional bit since negating
         a negative number can remove one sign bit copy.  */
 
-      num0 = num_sign_bit_copies (XEXP (x, 0), mode);
-      num1 = num_sign_bit_copies (XEXP (x, 1), mode);
+      num0 = num_sign_bit_copies_with_known (XEXP (x, 0), mode);
+      num1 = num_sign_bit_copies_with_known (XEXP (x, 1), mode);
 
       result = bitwidth - (bitwidth - num0) - (bitwidth - num1);
       if (result > 0
@@ -8679,17 +9020,17 @@ num_sign_bit_copies (x, mode)
                & ((HOST_WIDE_INT) 1 << (bitwidth - 1))) != 0)
        return 1;
       else
-       return num_sign_bit_copies (XEXP (x, 0), mode);
+       return num_sign_bit_copies_with_known (XEXP (x, 0), mode);
 
     case UMOD:
       /* The result must be <= the second operand.  */
-      return num_sign_bit_copies (XEXP (x, 1), mode);
+      return num_sign_bit_copies_with_known (XEXP (x, 1), mode);
 
     case DIV:
       /* Similar to unsigned division, except that we have to worry about
         the case where the divisor is negative, in which case we have
         to add 1.  */
-      result = num_sign_bit_copies (XEXP (x, 0), mode);
+      result = num_sign_bit_copies_with_known (XEXP (x, 0), mode);
       if (result > 1
          && (bitwidth > HOST_BITS_PER_WIDE_INT
              || (nonzero_bits (XEXP (x, 1), mode)
@@ -8699,7 +9040,7 @@ num_sign_bit_copies (x, mode)
       return result;
 
     case MOD:
-      result = num_sign_bit_copies (XEXP (x, 1), mode);
+      result = num_sign_bit_copies_with_known (XEXP (x, 1), mode);
       if (result > 1
          && (bitwidth > HOST_BITS_PER_WIDE_INT
              || (nonzero_bits (XEXP (x, 1), mode)
@@ -8711,7 +9052,7 @@ num_sign_bit_copies (x, mode)
     case ASHIFTRT:
       /* Shifts by a constant add to the number of bits equal to the
         sign bit.  */
-      num0 = num_sign_bit_copies (XEXP (x, 0), mode);
+      num0 = num_sign_bit_copies_with_known (XEXP (x, 0), mode);
       if (GET_CODE (XEXP (x, 1)) == CONST_INT
          && INTVAL (XEXP (x, 1)) > 0)
        num0 = MIN ((int) bitwidth, num0 + INTVAL (XEXP (x, 1)));
@@ -8725,12 +9066,12 @@ num_sign_bit_copies (x, mode)
          || INTVAL (XEXP (x, 1)) >= (int) bitwidth)
        return 1;
 
-      num0 = num_sign_bit_copies (XEXP (x, 0), mode);
+      num0 = num_sign_bit_copies_with_known (XEXP (x, 0), mode);
       return MAX (1, num0 - INTVAL (XEXP (x, 1)));
 
     case IF_THEN_ELSE:
-      num0 = num_sign_bit_copies (XEXP (x, 1), mode);
-      num1 = num_sign_bit_copies (XEXP (x, 2), mode);
+      num0 = num_sign_bit_copies_with_known (XEXP (x, 1), mode);
+      num1 = num_sign_bit_copies_with_known (XEXP (x, 2), mode);
       return MIN (num0, num1);
 
     case EQ:  case NE:  case GE:  case GT:  case LE:  case LT:
@@ -8786,8 +9127,8 @@ extended_count (x, mode, unsignedp)
 
   return (unsignedp
          ? (GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT
-            ? (GET_MODE_BITSIZE (mode) - 1
-               - floor_log2 (nonzero_bits (x, mode)))
+            ? (unsigned int) (GET_MODE_BITSIZE (mode) - 1
+                              - floor_log2 (nonzero_bits (x, mode)))
             : 0)
          : num_sign_bit_copies (x, mode) - 1);
 }
@@ -8892,7 +9233,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, const0 = ~const0;
        break;
 
       case AND:
@@ -8930,7 +9271,7 @@ merge_outer_ops (pop0, pconst0, op1, const1, mode, pcomp_p)
 }
 \f
 /* Simplify a shift of VAROP by COUNT bits.  CODE says what kind of shift.
-   The result of the shift is RESULT_MODE.  X, if non-zero, is an expression
+   The result of the shift is RESULT_MODE.  X, if nonzero, is an expression
    that we started with.
 
    The shift is normally computed in the widest mode we find in VAROP, as
@@ -8997,7 +9338,14 @@ simplify_shift_const (x, code, result_mode, varop, orig_count)
 
       /* Convert ROTATERT to ROTATE.  */
       if (code == ROTATERT)
-       code = ROTATE, count = GET_MODE_BITSIZE (result_mode) - count;
+       {
+         unsigned int bitsize = GET_MODE_BITSIZE (result_mode);;
+         code = ROTATE;
+         if (VECTOR_MODE_P (result_mode))
+           count = bitsize / GET_MODE_NUNITS (result_mode) - count;
+         else
+           count = bitsize - count;
+       }
 
       /* We need to determine what mode we will do the shift in.  If the
         shift is a right shift or a ROTATE, we must always do it in the mode
@@ -9017,7 +9365,7 @@ simplify_shift_const (x, code, result_mode, varop, orig_count)
         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 (count > (unsigned int) (GET_MODE_BITSIZE (shift_mode) - 1))
        {
          if (code == ASHIFTRT)
            count = GET_MODE_BITSIZE (shift_mode) - 1;
@@ -9064,6 +9412,16 @@ simplify_shift_const (x, code, result_mode, varop, orig_count)
              == 0))
        code = LSHIFTRT;
 
+      if (code == LSHIFTRT
+         && GET_MODE_BITSIZE (shift_mode) <= HOST_BITS_PER_WIDE_INT
+         && !(nonzero_bits (varop, shift_mode) >> count))
+       varop = const0_rtx;
+      if (code == ASHIFT
+         && GET_MODE_BITSIZE (shift_mode) <= HOST_BITS_PER_WIDE_INT
+         && !((nonzero_bits (varop, shift_mode) << count)
+              & GET_MODE_MASK (shift_mode)))
+       varop = const0_rtx;
+
       switch (GET_CODE (varop))
        {
        case SIGN_EXTEND:
@@ -9133,9 +9491,9 @@ simplify_shift_const (x, code, result_mode, varop, orig_count)
          if (subreg_lowpart_p (varop)
              && (GET_MODE_SIZE (GET_MODE (SUBREG_REG (varop)))
                  > GET_MODE_SIZE (GET_MODE (varop)))
-             && (((GET_MODE_SIZE (GET_MODE (SUBREG_REG (varop)))
-                   + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD)
-                 == mode_words))
+             && (unsigned int) ((GET_MODE_SIZE (GET_MODE (SUBREG_REG (varop)))
+                                 + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD)
+                == mode_words)
            {
              varop = SUBREG_REG (varop);
              if (GET_MODE_SIZE (GET_MODE (varop)) > GET_MODE_SIZE (mode))
@@ -9176,7 +9534,8 @@ simplify_shift_const (x, code, result_mode, varop, orig_count)
             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
+         if (code == LSHIFTRT
+             && count == (unsigned int) (GET_MODE_BITSIZE (result_mode) - 1)
              && (GET_MODE_BITSIZE (result_mode)
                  >= GET_MODE_BITSIZE (GET_MODE (varop))))
            {
@@ -9210,8 +9569,9 @@ simplify_shift_const (x, code, result_mode, varop, orig_count)
                 (ashiftrt:M1 (ashift:M1 (and:M1 (subreg:M1 FOO 0 C2) C3) C1).
                 This simplifies certain SIGN_EXTEND operations.  */
              if (code == ASHIFT && first_code == ASHIFTRT
-                 && (GET_MODE_BITSIZE (result_mode)
-                     - GET_MODE_BITSIZE (GET_MODE (varop))) == count)
+                 && count == (unsigned int)
+                             (GET_MODE_BITSIZE (result_mode)
+                              - GET_MODE_BITSIZE (GET_MODE (varop))))
                {
                  /* C3 has the low-order C1 bits zero.  */
 
@@ -9367,7 +9727,8 @@ simplify_shift_const (x, code, result_mode, varop, orig_count)
              && XEXP (XEXP (varop, 0), 1) == constm1_rtx
              && (STORE_FLAG_VALUE == 1 || STORE_FLAG_VALUE == -1)
              && (code == LSHIFTRT || code == ASHIFTRT)
-             && count == GET_MODE_BITSIZE (GET_MODE (varop)) - 1
+             && count == (unsigned int)
+                         (GET_MODE_BITSIZE (GET_MODE (varop)) - 1)
              && rtx_equal_p (XEXP (XEXP (varop, 0), 0), XEXP (varop, 1)))
            {
              count = 0;
@@ -9422,7 +9783,7 @@ simplify_shift_const (x, code, result_mode, varop, orig_count)
          if (code == LSHIFTRT
              && XEXP (varop, 1) == const0_rtx
              && GET_MODE (XEXP (varop, 0)) == result_mode
-             && count == GET_MODE_BITSIZE (result_mode) - 1
+             && count == (unsigned int) (GET_MODE_BITSIZE (result_mode) - 1)
              && GET_MODE_BITSIZE (result_mode) <= HOST_BITS_PER_WIDE_INT
              && ((STORE_FLAG_VALUE
                   & ((HOST_WIDE_INT) 1
@@ -9441,7 +9802,8 @@ simplify_shift_const (x, code, result_mode, varop, orig_count)
        case NEG:
          /* (lshiftrt (neg A) C) where A is either 0 or 1 and C is one less
             than the number of bits in the mode is equivalent to A.  */
-         if (code == LSHIFTRT && count == GET_MODE_BITSIZE (result_mode) - 1
+         if (code == LSHIFTRT
+             && count == (unsigned int) (GET_MODE_BITSIZE (result_mode) - 1)
              && nonzero_bits (XEXP (varop, 0), result_mode) == 1)
            {
              varop = XEXP (varop, 0);
@@ -9465,7 +9827,8 @@ simplify_shift_const (x, code, result_mode, varop, orig_count)
          /* (lshiftrt (plus A -1) C) where A is either 0 or 1 and C
             is one less than the number of bits in the mode is
             equivalent to (xor A 1).  */
-         if (code == LSHIFTRT && count == GET_MODE_BITSIZE (result_mode) - 1
+         if (code == LSHIFTRT
+             && count == (unsigned int) (GET_MODE_BITSIZE (result_mode) - 1)
              && XEXP (varop, 1) == constm1_rtx
              && nonzero_bits (XEXP (varop, 0), result_mode) == 1
              && merge_outer_ops (&outer_op, &outer_const, XOR,
@@ -9530,10 +9893,12 @@ simplify_shift_const (x, code, result_mode, varop, orig_count)
 
          if ((STORE_FLAG_VALUE == 1 || STORE_FLAG_VALUE == -1)
              && GET_CODE (XEXP (varop, 0)) == ASHIFTRT
-             && count == GET_MODE_BITSIZE (GET_MODE (varop)) - 1
+             && count == (unsigned int)
+                         (GET_MODE_BITSIZE (GET_MODE (varop)) - 1)
              && (code == LSHIFTRT || code == ASHIFTRT)
              && GET_CODE (XEXP (XEXP (varop, 0), 1)) == CONST_INT
-             && INTVAL (XEXP (XEXP (varop, 0), 1)) == count
+             && (unsigned HOST_WIDE_INT) INTVAL (XEXP (XEXP (varop, 0), 1))
+                == count
              && rtx_equal_p (XEXP (XEXP (varop, 0), 0), XEXP (varop, 1)))
            {
              count = 0;
@@ -9597,7 +9962,7 @@ simplify_shift_const (x, code, result_mode, varop, orig_count)
 
   if (x && GET_RTX_CLASS (GET_CODE (x)) == '2'
       && GET_CODE (XEXP (x, 1)) == CONST_INT
-      && INTVAL (XEXP (x, 1)) == count)
+      && (unsigned HOST_WIDE_INT) INTVAL (XEXP (x, 1)) == count)
     const_rtx = XEXP (x, 1);
   else
     const_rtx = GEN_INT (count);
@@ -9641,7 +10006,7 @@ simplify_shift_const (x, code, result_mode, varop, orig_count)
   /* If COMPLEMENT_P is set, we have to complement X before doing the outer
      operation.  */
   if (complement_p)
-    x =simplify_gen_unary (NOT, result_mode, x, result_mode);
+    x = simplify_gen_unary (NOT, result_mode, x, result_mode);
 
   if (outer_op != NIL)
     {
@@ -9804,12 +10169,6 @@ gen_lowpart_for_combine (mode, x)
            || GET_MODE_SIZE (GET_MODE (x)) == GET_MODE_SIZE (mode)))
     return gen_rtx_CLOBBER (GET_MODE (x), const0_rtx);
 
-  /* simplify_gen_subreg does not know how to handle the case where we try
-     to convert an integer constant to a vector.
-     ??? We could try to teach it to generate CONST_VECTORs.  */
-  if (GET_MODE (x) == VOIDmode && VECTOR_MODE_P (mode))
-    return gen_rtx_CLOBBER (GET_MODE (x), const0_rtx);
-
   /* X might be a paradoxical (subreg (mem)).  In that case, gen_lowpart
      won't know what to do.  So we will strip off the SUBREG here and
      process normally.  */
@@ -9821,14 +10180,14 @@ gen_lowpart_for_combine (mode, x)
     }
 
   result = gen_lowpart_common (mode, x);
-#ifdef CLASS_CANNOT_CHANGE_MODE
+#ifdef CANNOT_CHANGE_MODE_CLASS
   if (result != 0
       && GET_CODE (result) == SUBREG
       && GET_CODE (SUBREG_REG (result)) == REG
-      && REGNO (SUBREG_REG (result)) >= FIRST_PSEUDO_REGISTER
-      && CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (result),
-                                    GET_MODE (SUBREG_REG (result))))
-    REG_CHANGES_MODE (REGNO (SUBREG_REG (result))) = 1;
+      && REGNO (SUBREG_REG (result)) >= FIRST_PSEUDO_REGISTER)
+    bitmap_set_bit (&subregs_of_mode, REGNO (SUBREG_REG (result))
+                                     * MAX_MACHINE_MODE
+                                     + GET_MODE (result));
 #endif
 
   if (result)
@@ -9876,9 +10235,15 @@ gen_lowpart_for_combine (mode, x)
     {
       int offset = 0;
       rtx res;
+      enum machine_mode sub_mode = GET_MODE (x);
 
-      offset = subreg_lowpart_offset (mode, GET_MODE (x));
-      res = simplify_gen_subreg (mode, x, GET_MODE (x), offset);
+      offset = subreg_lowpart_offset (mode, sub_mode);
+      if (sub_mode == VOIDmode)
+       {
+         sub_mode = int_mode_for_mode (mode);
+         x = gen_lowpart_common (sub_mode, x);
+       }
+      res = simplify_gen_subreg (mode, x, sub_mode, offset);
       if (res)
        return res;
       return gen_rtx_CLOBBER (GET_MODE (x), const0_rtx);
@@ -10137,7 +10502,9 @@ 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);
+      const_op = INTVAL (op1);
+      if (mode != VOIDmode)
+       const_op = trunc_int_for_mode (const_op, mode);
       op1 = GEN_INT (const_op);
 
       /* If we are comparing against a constant power of two and the value
@@ -10296,7 +10663,7 @@ simplify_comparison (code, pop0, pop1)
 
          /* (unsigned) > 0x7fffffff is equivalent to < 0.  */
          else if ((mode_width <= HOST_BITS_PER_WIDE_INT)
-                   && (const_op == ((HOST_WIDE_INT) 1 << (mode_width - 1)) - 1))
+                  && (const_op == ((HOST_WIDE_INT) 1 << (mode_width - 1)) - 1))
            {
              const_op = 0, op1 = const0_rtx;
              code = LT;
@@ -10509,7 +10876,8 @@ simplify_comparison (code, pop0, pop1)
                        & ~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)))
+                     > (unsigned int)
+                       (GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (op0)))
                         - GET_MODE_BITSIZE (mode)))))
            {
              op0 = SUBREG_REG (op0);
@@ -10593,7 +10961,8 @@ simplify_comparison (code, pop0, pop1)
             of bits in X minus 1, is one iff X > 0.  */
          if (sign_bit_comparison_p && GET_CODE (XEXP (op0, 0)) == ASHIFTRT
              && GET_CODE (XEXP (XEXP (op0, 0), 1)) == CONST_INT
-             && INTVAL (XEXP (XEXP (op0, 0), 1)) == mode_width - 1
+             && (unsigned HOST_WIDE_INT) INTVAL (XEXP (XEXP (op0, 0), 1))
+                == mode_width - 1
              && rtx_equal_p (XEXP (XEXP (op0, 0), 0), XEXP (op0, 1)))
            {
              op0 = XEXP (op0, 1);
@@ -10623,9 +10992,7 @@ simplify_comparison (code, pop0, pop1)
          /* We can't do anything if OP0 is a condition code value, rather
             than an actual data value.  */
          if (const_op != 0
-#ifdef HAVE_cc0
-             || XEXP (op0, 0) == cc0_rtx
-#endif
+             || CC0_P (XEXP (op0, 0))
              || GET_MODE_CLASS (GET_MODE (XEXP (op0, 0))) == MODE_CC)
            break;
 
@@ -10662,7 +11029,7 @@ simplify_comparison (code, pop0, pop1)
          break;
 
        case IOR:
-         /* The sign bit of (ior (plus X (const_int -1)) X) is non-zero
+         /* The sign bit of (ior (plus X (const_int -1)) X) is nonzero
             iff X <= 0.  */
          if (sign_bit_comparison_p && GET_CODE (XEXP (op0, 0)) == PLUS
              && XEXP (XEXP (op0, 0), 1) == constm1_rtx
@@ -10743,50 +11110,45 @@ simplify_comparison (code, pop0, pop1)
              continue;
            }
 
-         /* If this is (and:M1 (subreg:M2 X 0) (const_int C1)) where C1 fits
-            in both M1 and M2 and the SUBREG is either paradoxical or
-            represents the low part, permute the SUBREG and the AND and
-            try again.  */
-         if (GET_CODE (XEXP (op0, 0)) == SUBREG
-             && (0
+         /* If this is (and:M1 (subreg:M2 X 0) (const_int C1)) where C1
+            fits in both M1 and M2 and the SUBREG is either paradoxical
+            or represents the low part, permute the SUBREG and the AND
+            and try again.  */
+         if (GET_CODE (XEXP (op0, 0)) == SUBREG)
+           {
+             unsigned HOST_WIDE_INT c1;
+             tmode = GET_MODE (SUBREG_REG (XEXP (op0, 0)));
+             /* Require an integral mode, to avoid creating something like
+                (AND:SF ...).  */
+             if (SCALAR_INT_MODE_P (tmode)
+                 /* It is unsafe to commute the AND into the SUBREG if the
+                    SUBREG is paradoxical and WORD_REGISTER_OPERATIONS is
+                    not defined.  As originally written the upper bits
+                    have a defined value due to the AND operation.
+                    However, if we commute the AND inside the SUBREG then
+                    they no longer have defined values and the meaning of
+                    the code has been changed.  */
+                 && (0
 #ifdef WORD_REGISTER_OPERATIONS
-                 || ((mode_width
-                      > (GET_MODE_BITSIZE
-                          (GET_MODE (SUBREG_REG (XEXP (op0, 0))))))
-                     && mode_width <= BITS_PER_WORD)
-#endif
-                 || ((mode_width
-                      <= (GET_MODE_BITSIZE
-                          (GET_MODE (SUBREG_REG (XEXP (op0, 0))))))
-                     && subreg_lowpart_p (XEXP (op0, 0))))
-#ifndef WORD_REGISTER_OPERATIONS
-             /* It is unsafe to commute the AND into the SUBREG if the SUBREG
-                is paradoxical and WORD_REGISTER_OPERATIONS is not defined.
-                As originally written the upper bits have a defined value
-                due to the AND operation.  However, if we commute the AND
-                inside the SUBREG then they no longer have defined values
-                and the meaning of the code has been changed.  */
-             && (GET_MODE_SIZE (GET_MODE (XEXP (op0, 0)))
-                 <= GET_MODE_SIZE (GET_MODE (SUBREG_REG (XEXP (op0, 0)))))
+                     || (mode_width > GET_MODE_BITSIZE (tmode)
+                         && mode_width <= BITS_PER_WORD)
 #endif
-             && GET_CODE (XEXP (op0, 1)) == CONST_INT
-             && mode_width <= HOST_BITS_PER_WIDE_INT
-             && (GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (XEXP (op0, 0))))
-                 <= HOST_BITS_PER_WIDE_INT)
-             && (INTVAL (XEXP (op0, 1)) & ~mask) == 0
-             && 0 == (~GET_MODE_MASK (GET_MODE (SUBREG_REG (XEXP (op0, 0))))
-                      & INTVAL (XEXP (op0, 1)))
-             && (unsigned HOST_WIDE_INT) INTVAL (XEXP (op0, 1)) != mask
-             && ((unsigned HOST_WIDE_INT) INTVAL (XEXP (op0, 1))
-                 != GET_MODE_MASK (GET_MODE (SUBREG_REG (XEXP (op0, 0))))))
-
-           {
-             op0
-               = gen_lowpart_for_combine
-                 (mode,
-                  gen_binary (AND, GET_MODE (SUBREG_REG (XEXP (op0, 0))),
-                              SUBREG_REG (XEXP (op0, 0)), XEXP (op0, 1)));
-             continue;
+                     || (mode_width <= GET_MODE_BITSIZE (tmode)
+                         && subreg_lowpart_p (XEXP (op0, 0))))
+                 && GET_CODE (XEXP (op0, 1)) == CONST_INT
+                 && mode_width <= HOST_BITS_PER_WIDE_INT
+                 && GET_MODE_BITSIZE (tmode) <= HOST_BITS_PER_WIDE_INT
+                 && ((c1 = INTVAL (XEXP (op0, 1))) & ~mask) == 0
+                 && (c1 & ~GET_MODE_MASK (tmode)) == 0
+                 && c1 != mask
+                 && c1 != GET_MODE_MASK (tmode))
+               {
+                 op0 = gen_binary (AND, tmode,
+                                   SUBREG_REG (XEXP (op0, 0)),
+                                   gen_int_mode (c1, tmode));
+                 op0 = gen_lowpart_for_combine (mode, op0);
+                 continue;
+               }
            }
 
          /* Convert (ne (and (lshiftrt (not X)) 1) 0) to
@@ -10851,7 +11213,8 @@ simplify_comparison (code, pop0, pop1)
             low-order bit.  */
          if (const_op == 0 && equality_comparison_p
              && GET_CODE (XEXP (op0, 1)) == CONST_INT
-             && INTVAL (XEXP (op0, 1)) == mode_width - 1)
+             && (unsigned HOST_WIDE_INT) INTVAL (XEXP (op0, 1))
+                == mode_width - 1)
            {
              op0 = simplify_and_const_int (NULL_RTX, mode, XEXP (op0, 0),
                                            (HOST_WIDE_INT) 1);
@@ -10948,7 +11311,8 @@ simplify_comparison (code, pop0, pop1)
          if (const_op == 0
              && (equality_comparison_p || sign_bit_comparison_p)
              && GET_CODE (XEXP (op0, 1)) == CONST_INT
-             && INTVAL (XEXP (op0, 1)) == mode_width - 1)
+             && (unsigned HOST_WIDE_INT) INTVAL (XEXP (op0, 1))
+                == mode_width - 1)
            {
              op0 = XEXP (op0, 0);
              code = (code == NE || code == GT ? LT : GE);
@@ -11049,9 +11413,11 @@ simplify_comparison (code, pop0, pop1)
 
          if (zero_extended
              || ((num_sign_bit_copies (op0, tmode)
-                  > GET_MODE_BITSIZE (tmode) - GET_MODE_BITSIZE (mode))
+                  > (unsigned int) (GET_MODE_BITSIZE (tmode)
+                                    - GET_MODE_BITSIZE (mode)))
                  && (num_sign_bit_copies (op1, tmode)
-                     > GET_MODE_BITSIZE (tmode) - GET_MODE_BITSIZE (mode))))
+                     > (unsigned int) (GET_MODE_BITSIZE (tmode)
+                                       - GET_MODE_BITSIZE (mode)))))
            {
              /* If OP0 is an AND and we don't have an AND in MODE either,
                 make a new AND in the proper mode.  */
@@ -11117,6 +11483,7 @@ combine_reversed_comparison_code (exp)
   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
@@ -11161,7 +11528,45 @@ update_table_tick (x)
     /* Note that we can't have an "E" in values stored; see
        get_last_value_validate.  */
     if (fmt[i] == 'e')
-      update_table_tick (XEXP (x, i));
+      {
+       /* Check for identical subexpressions.  If x contains
+          identical subexpression we only have to traverse one of
+          them.  */
+       if (i == 0
+           && (GET_RTX_CLASS (code) == '2'
+               || GET_RTX_CLASS (code) == 'c'))
+         {
+           /* Note that at this point x1 has already been
+              processed.  */
+           rtx x0 = XEXP (x, 0);
+           rtx x1 = XEXP (x, 1);
+
+           /* If x0 and x1 are identical then there is no need to
+              process x0.  */
+           if (x0 == x1)
+             break;
+
+           /* If x0 is identical to a subexpression of x1 then while
+              processing x1, x0 has already been processed.  Thus we
+              are done with x.  */
+           if ((GET_RTX_CLASS (GET_CODE (x1)) == '2'
+                || GET_RTX_CLASS (GET_CODE (x1)) == 'c')
+               && (x0 == XEXP (x1, 0) || x0 == XEXP (x1, 1)))
+             break;
+
+           /* If x1 is identical to a subexpression of x0 then we
+              still have to process the rest of x0.  */
+           if ((GET_RTX_CLASS (GET_CODE (x0)) == '2'
+                || GET_RTX_CLASS (GET_CODE (x0)) == 'c')
+               && (x1 == XEXP (x0, 0) || x1 == XEXP (x0, 1)))
+             {
+               update_table_tick (XEXP (x0, x1 == XEXP (x0, 0) ? 1 : 0));
+               break;
+             }
+         }
+
+       update_table_tick (XEXP (x, i));
+      }
 }
 
 /* Record that REG is set to VALUE in insn INSN.  If VALUE is zero, we
@@ -11459,7 +11864,7 @@ check_promoted_subreg (insn, x)
    mentioned in *LOC are valid when *LOC was part of a value set when
    label_tick == TICK.  Return 0 if some are not.
 
-   If REPLACE is non-zero, replace the invalid reference with
+   If REPLACE is nonzero, replace the invalid reference with
    (clobber (const_int 0)) and return 1.  This replacement is useful because
    we often can get useful information about the form of a value (e.g., if
    it was produced by a shift that always produces -1 or 0) even though
@@ -11492,7 +11897,7 @@ get_last_value_validate (loc, insn, tick, replace)
            || (! (regno >= FIRST_PSEUDO_REGISTER
                   && REG_N_SETS (regno) == 1
                   && (! REGNO_REG_SET_P
-                      (BASIC_BLOCK (0)->global_live_at_start, regno)))
+                      (ENTRY_BLOCK_PTR->next_bb->global_live_at_start, regno)))
                && reg_last_set_label[j] > tick))
          {
            if (replace)
@@ -11514,11 +11919,52 @@ get_last_value_validate (loc, insn, tick, replace)
     }
 
   for (i = 0; i < len; i++)
-    if ((fmt[i] == 'e'
-        && get_last_value_validate (&XEXP (x, i), insn, tick, replace) == 0)
-       /* Don't bother with these.  They shouldn't occur anyway.  */
-       || fmt[i] == 'E')
-      return 0;
+    {
+      if (fmt[i] == 'e')
+       {
+         /* Check for identical subexpressions.  If x contains
+            identical subexpression we only have to traverse one of
+            them.  */
+         if (i == 1
+             && (GET_RTX_CLASS (GET_CODE (x)) == '2'
+                 || GET_RTX_CLASS (GET_CODE (x)) == 'c'))
+           {
+             /* Note that at this point x0 has already been checked
+                and found valid.  */
+             rtx x0 = XEXP (x, 0);
+             rtx x1 = XEXP (x, 1);
+
+             /* If x0 and x1 are identical then x is also valid.  */
+             if (x0 == x1)
+               return 1;
+
+             /* If x1 is identical to a subexpression of x0 then
+                while checking x0, x1 has already been checked.  Thus
+                it is valid and so as x.  */
+             if ((GET_RTX_CLASS (GET_CODE (x0)) == '2'
+                  || GET_RTX_CLASS (GET_CODE (x0)) == 'c')
+                 && (x1 == XEXP (x0, 0) || x1 == XEXP (x0, 1)))
+               return 1;
+
+             /* If x0 is identical to a subexpression of x1 then x is
+                valid iff the rest of x1 is valid.  */
+             if ((GET_RTX_CLASS (GET_CODE (x1)) == '2'
+                  || GET_RTX_CLASS (GET_CODE (x1)) == 'c')
+                 && (x0 == XEXP (x1, 0) || x0 == XEXP (x1, 1)))
+               return
+                 get_last_value_validate (&XEXP (x1,
+                                                 x0 == XEXP (x1, 0) ? 1 : 0),
+                                          insn, tick, replace);
+           }
+
+         if (get_last_value_validate (&XEXP (x, i), insn, tick,
+                                      replace) == 0)
+           return 0;
+       }
+      /* Don't bother with these.  They shouldn't occur anyway.  */
+      else if (fmt[i] == 'E')
+       return 0;
+    }
 
   /* If we haven't found a reason for it to be invalid, it is valid.  */
   return 1;
@@ -11566,7 +12012,7 @@ get_last_value (x)
          && (regno < FIRST_PSEUDO_REGISTER
              || REG_N_SETS (regno) != 1
              || (REGNO_REG_SET_P
-                 (BASIC_BLOCK (0)->global_live_at_start, regno)))))
+                 (ENTRY_BLOCK_PTR->next_bb->global_live_at_start, regno)))))
     return 0;
 
   /* If the value was set in a later insn than the ones we are processing,
@@ -11672,7 +12118,7 @@ reg_dead_at_p_1 (dest, x, data)
     reg_dead_flag = (GET_CODE (x) == CLOBBER) ? 1 : -1;
 }
 
-/* Return non-zero if REG is known to be dead at INSN.
+/* Return nonzero if REG is known to be dead at INSN.
 
    We scan backwards from INSN.  If we hit a REG_DEAD note or a CLOBBER
    referencing REG, it is dead.  If we hit a SET referencing REG, it is
@@ -11685,7 +12131,7 @@ reg_dead_at_p (reg, insn)
      rtx reg;
      rtx insn;
 {
-  int block;
+  basic_block block;
   unsigned int i;
 
   /* Set variables for reg_dead_at_p_1.  */
@@ -11718,21 +12164,21 @@ reg_dead_at_p (reg, insn)
        return 1;
     }
 
-  /* Get the basic block number that we were in.  */
+  /* Get the basic block that we were in.  */
   if (insn == 0)
-    block = 0;
+    block = ENTRY_BLOCK_PTR->next_bb;
   else
     {
-      for (block = 0; block < n_basic_blocks; block++)
-       if (insn == BLOCK_HEAD (block))
+      FOR_EACH_BB (block)
+       if (insn == block->head)
          break;
 
-      if (block == n_basic_blocks)
+      if (block == EXIT_BLOCK_PTR)
        return 0;
     }
 
   for (i = reg_dead_regno; i < reg_dead_endregno; i++)
-    if (REGNO_REG_SET_P (BASIC_BLOCK (block)->global_live_at_start, i))
+    if (REGNO_REG_SET_P (block->global_live_at_start, i))
       return 0;
 
   return 1;
@@ -11783,7 +12229,7 @@ mark_used_regs_combine (x)
        {
          unsigned int endregno, r;
 
-         /* None of this applies to the stack, frame or arg pointers */
+         /* None of this applies to the stack, frame or arg pointers */
          if (regno == STACK_POINTER_REGNUM
 #if FRAME_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
              || regno == HARD_FRAME_POINTER_REGNUM
@@ -11891,7 +12337,7 @@ move_deaths (x, maybe_kill_insn, from_cuid, to_insn, pnotes)
       rtx where_dead = reg_last_death[regno];
       rtx before_dead, after_dead;
 
-      /* Don't move the register if it gets killed in between from and to */
+      /* Don't move the register if it gets killed in between from and to */
       if (maybe_kill_insn && reg_set_p (x, maybe_kill_insn)
          && ! reg_referenced_p (x, maybe_kill_insn))
        return;
@@ -11939,7 +12385,7 @@ move_deaths (x, maybe_kill_insn, from_cuid, to_insn, pnotes)
                if (i < regno || i >= ourend)
                  REG_NOTES (where_dead)
                    = gen_rtx_EXPR_LIST (REG_DEAD,
-                                        gen_rtx_REG (reg_raw_mode[i], i),
+                                        regno_reg_rtx[i],
                                         REG_NOTES (where_dead));
            }
 
@@ -11966,7 +12412,7 @@ move_deaths (x, maybe_kill_insn, from_cuid, to_insn, pnotes)
                offset = 1;
 
              for (i = regno + offset; i < ourend; i++)
-               move_deaths (gen_rtx_REG (reg_raw_mode[i], i),
+               move_deaths (regno_reg_rtx[i],
                             maybe_kill_insn, from_cuid, to_insn, &oldnotes);
            }
 
@@ -12126,7 +12572,6 @@ distribute_notes (notes, from_insn, i3, i2, elim_i2, elim_i1)
        {
        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
             likely to be i3.  */
@@ -12346,7 +12791,7 @@ distribute_notes (notes, from_insn, i3, i2, elim_i2, elim_i1)
 
        case REG_DEAD:
          /* If the register is used as an input in I3, it dies there.
-            Similarly for I2, if it is non-zero and adjacent to I3.
+            Similarly for I2, if it is nonzero and adjacent to I3.
 
             If the register is not used as an input in either I3 or I2
             and it is not one of the registers we were supposed to eliminate,
@@ -12375,7 +12820,7 @@ distribute_notes (notes, from_insn, i3, i2, elim_i2, elim_i1)
 
          if (place == 0)
            {
-             basic_block bb = BASIC_BLOCK (this_basic_block);
+             basic_block bb = this_basic_block;
 
              for (tem = PREV_INSN (i3); place == 0; tem = PREV_INSN (tem))
                {
@@ -12518,10 +12963,7 @@ distribute_notes (notes, from_insn, i3, i2, elim_i2, elim_i1)
              if (REG_NOTE_KIND (note) == REG_DEAD && place == 0
                  && REGNO_REG_SET_P (bb->global_live_at_start,
                                      REGNO (XEXP (note, 0))))
-               {
-                 SET_BIT (refresh_blocks, this_basic_block);
-                 need_refresh = 1;
-               }
+               SET_BIT (refresh_blocks, this_basic_block->index);
            }
 
          /* If the register is set or already dead at PLACE, we needn't do
@@ -12538,10 +12980,7 @@ distribute_notes (notes, from_insn, i3, i2, elim_i2, elim_i1)
                 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;
-               }
+               SET_BIT (refresh_blocks, this_basic_block->index);
 
              if (dead_or_set_p (place, XEXP (note, 0))
                  || reg_bitfield_target_p (XEXP (note, 0), PATTERN (place)))
@@ -12588,8 +13027,8 @@ distribute_notes (notes, from_insn, i3, i2, elim_i2, elim_i1)
                      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);
+                         rtx piece = regno_reg_rtx[i];
+                         basic_block bb = this_basic_block;
 
                          if (! dead_or_set_p (place, piece)
                              && ! reg_bitfield_target_p (piece,
@@ -12612,8 +13051,7 @@ distribute_notes (notes, from_insn, i3, i2, elim_i2, elim_i1)
                                    if (tem == bb->head)
                                      {
                                        SET_BIT (refresh_blocks,
-                                                this_basic_block);
-                                       need_refresh = 1;
+                                                this_basic_block->index);
                                        break;
                                      }
                                    continue;
@@ -12717,8 +13155,8 @@ distribute_links (links)
         since most links don't point very far away.  */
 
       for (insn = NEXT_INSN (XEXP (link, 0));
-          (insn && (this_basic_block == n_basic_blocks - 1
-                    || BLOCK_HEAD (this_basic_block + 1) != insn));
+          (insn && (this_basic_block->next_bb == EXIT_BLOCK_PTR
+                    || this_basic_block->next_bb->head != insn));
           insn = NEXT_INSN (insn))
        if (INSN_P (insn) && reg_overlap_mentioned_p (reg, PATTERN (insn)))
          {