OSDN Git Service

* config/xtensa/xtensa.md: Remove unused type attributes.
[pf3gnuchains/gcc-fork.git] / gcc / combine.c
index f83990e..0f17559 100644 (file)
@@ -424,6 +424,33 @@ do_SUBST (into, newval)
   if (oldval == newval)
     return;
 
+  /* We'd like to catch as many invalid transformations here as
+     possible.  Unfortunately, there are way too many mode changes
+     that are perfectly valid, so we'd waste too much effort for
+     little gain doing the checks here.  Focus on catching invalid
+     transformations involving integer constants.  */
+  if (GET_MODE_CLASS (GET_MODE (oldval)) == MODE_INT
+      && GET_CODE (newval) == CONST_INT)
+    {
+      /* Sanity check that we're replacing oldval with a CONST_INT
+        that is a valid sign-extension for the original mode.  */
+      if (INTVAL (newval) != trunc_int_for_mode (INTVAL (newval),
+                                                GET_MODE (oldval)))
+       abort ();
+
+      /* Replacing the operand of a SUBREG or a ZERO_EXTEND with a
+        CONST_INT is not valid, because after the replacement, the
+        original mode would be gone.  Unfortunately, we can't tell
+        when do_SUBST is called to replace the operand thereof, so we
+        perform this test on oldval instead, checking whether an
+        invalid replacement took place before we got here.  */
+      if ((GET_CODE (oldval) == SUBREG
+          && GET_CODE (SUBREG_REG (oldval)) == CONST_INT)
+         || (GET_CODE (oldval) == ZERO_EXTEND
+             && GET_CODE (XEXP (oldval, 0)) == CONST_INT))
+       abort ();
+     }
+
   if (undobuf.frees)
     buf = undobuf.frees, undobuf.frees = buf->next;
   else
@@ -624,12 +651,12 @@ combine_instructions (f, nregs)
              /* 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)
-               break;
+               continue;
 
              for (nextlinks = LOG_LINKS (link);
                   nextlinks;
                   nextlinks = XEXP (nextlinks, 1))
-               if ((next = try_combine (insn, XEXP (links, 0),
+               if ((next = try_combine (insn, link,
                                         XEXP (nextlinks, 0),
                                         &new_direct_jump_p)) != 0)
                  goto retry;
@@ -712,14 +739,16 @@ combine_instructions (f, nregs)
          ;
        }
     }
+  clear_bb_flags ();
 
+  EXECUTE_IF_SET_IN_SBITMAP (refresh_blocks, 0, this_basic_block,
+                            BASIC_BLOCK (this_basic_block)->flags |= BB_DIRTY);
+  new_direct_jump_p |= purge_all_dead_edges (0);
   delete_noop_moves (f);
 
-  if (need_refresh)
-    {
-      update_life_info (refresh_blocks, UPDATE_LIFE_GLOBAL_RM_NOTES,
-                       PROP_DEATH_NOTES);
-    }
+  update_life_info_in_dirty_blocks (UPDATE_LIFE_GLOBAL_RM_NOTES,
+                                   PROP_DEATH_NOTES | PROP_SCAN_DEAD_CODE
+                                   | PROP_KILL_DEAD_CODE);
 
   /* Clean up.  */
   sbitmap_free (refresh_blocks);
@@ -950,7 +979,7 @@ can_combine_p (insn, i3, pred, succ, pdest, psrc)
               for the SH4 port.  */
            case USE:
              /* Combining an isolated USE doesn't make sense.
-                We depend here on combinable_i3_pat to reject them.  */
+                We depend here on combinable_i3pat to reject them.  */
              /* The code below this loop only verifies that the inputs of
                 the SET in INSN do not change.  We call reg_set_between_p
                 to verify that the REG in the USE does not change between
@@ -1134,7 +1163,7 @@ can_combine_p (insn, i3, pred, succ, pdest, psrc)
 
       for (p = NEXT_INSN (insn); p != i3; p = NEXT_INSN (p))
         if (INSN_P (p) && p != succ && volatile_refs_p (PATTERN (p)))
-       return 0;
+         return 0;
     }
 
   /* If INSN is an asm, and DEST is a hard register, reject, since it has
@@ -1478,6 +1507,7 @@ try_combine (i3, i2, i1, new_direct_jump_p)
 {
   /* New patterns for I3 and I2, respectively.  */
   rtx newpat, newi2pat = 0;
+  int substed_i2 = 0, substed_i1 = 0;
   /* Indicates need to preserve SET in I1 or I2 in I3 if it is not dead.  */
   int added_sets_1, added_sets_2;
   /* Total number of SETs to put into I3.  */
@@ -1939,6 +1969,7 @@ try_combine (i3, i2, i1, new_direct_jump_p)
       subst_low_cuid = INSN_CUID (i2);
       newpat = subst (PATTERN (i3), i2dest, i2src, 0,
                      ! i1_feeds_i3 && i1dest_in_i1src);
+      substed_i2 = 1;
 
       /* Record whether i2's body now appears within i3's body.  */
       i2_is_used = n_occurrences;
@@ -1954,7 +1985,7 @@ try_combine (i3, i2, i1, new_direct_jump_p)
         isn't mentioned in any SETs in NEWPAT that are field assignments.  */
 
       if (! combinable_i3pat (NULL_RTX, &newpat, i1dest, NULL_RTX,
-                             0, (rtx*)0))
+                             0, (rtx*) 0))
        {
          undo_all ();
          return 0;
@@ -1963,6 +1994,7 @@ try_combine (i3, i2, i1, new_direct_jump_p)
       n_occurrences = 0;
       subst_low_cuid = INSN_CUID (i1);
       newpat = subst (newpat, i1dest, i1src, 0, 0);
+      substed_i1 = 1;
     }
 
   /* Fail if an autoincrement side-effect has been duplicated.  Be careful
@@ -2011,23 +2043,23 @@ try_combine (i3, i2, i1, new_direct_jump_p)
          XVECEXP (newpat, 0, 0) = old;
        }
 
-     if (added_sets_1)
-       XVECEXP (newpat, 0, --total_sets)
-        = (GET_CODE (PATTERN (i1)) == PARALLEL
-           ? gen_rtx_SET (VOIDmode, i1dest, i1src) : PATTERN (i1));
+      if (added_sets_1)
+       XVECEXP (newpat, 0, --total_sets)
+         = (GET_CODE (PATTERN (i1)) == PARALLEL
+            ? gen_rtx_SET (VOIDmode, i1dest, i1src) : PATTERN (i1));
 
-     if (added_sets_2)
-       {
-        /* If there is no I1, use I2's body as is.  We used to also not do
-           the subst call below if I2 was substituted into I3,
-           but that could lose a simplification.  */
-        if (i1 == 0)
-          XVECEXP (newpat, 0, --total_sets) = i2pat;
-        else
-          /* See comment where i2pat is assigned.  */
-          XVECEXP (newpat, 0, --total_sets)
-            = subst (i2pat, i1dest, i1src, 0, 0);
-       }
+      if (added_sets_2)
+       {
+         /* If there is no I1, use I2's body as is.  We used to also not do
+            the subst call below if I2 was substituted into I3,
+            but that could lose a simplification.  */
+         if (i1 == 0)
+           XVECEXP (newpat, 0, --total_sets) = i2pat;
+         else
+           /* See comment where i2pat is assigned.  */
+           XVECEXP (newpat, 0, --total_sets)
+             = subst (i2pat, i1dest, i1src, 0, 0);
+       }
     }
 
   /* We come here when we are replacing a destination in I2 with the
@@ -2534,6 +2566,23 @@ try_combine (i3, i2, i1, new_direct_jump_p)
 
     INSN_CODE (i3) = insn_code_number;
     PATTERN (i3) = newpat;
+
+    if (GET_CODE (i3) == CALL_INSN && CALL_INSN_FUNCTION_USAGE (i3))
+      {
+       rtx call_usage = CALL_INSN_FUNCTION_USAGE (i3);
+
+       reset_used_flags (call_usage);
+       call_usage = copy_rtx (call_usage);
+
+       if (substed_i2)
+         replace_rtx (call_usage, i2dest, i2src);
+
+       if (substed_i1)
+         replace_rtx (call_usage, i1dest, i1src);
+
+       CALL_INSN_FUNCTION_USAGE (i3) = call_usage;
+      }
+
     if (undobuf.other_insn)
       INSN_CODE (undobuf.other_insn) = other_code_number;
 
@@ -2992,7 +3041,7 @@ find_split_point (loc, insn)
          && GET_CODE (XEXP (SET_DEST (x), 2)) == CONST_INT
          && GET_CODE (SET_SRC (x)) == CONST_INT
          && ((INTVAL (XEXP (SET_DEST (x), 1))
-             + INTVAL (XEXP (SET_DEST (x), 2)))
+              + INTVAL (XEXP (SET_DEST (x), 2)))
              <= GET_MODE_BITSIZE (GET_MODE (XEXP (SET_DEST (x), 0))))
          && ! side_effects_p (XEXP (SET_DEST (x), 0)))
        {
@@ -3044,7 +3093,7 @@ find_split_point (loc, insn)
              && GET_CODE (XEXP (SET_SRC (x), 0)) == REG
              && (pos = exact_log2 (INTVAL (XEXP (SET_SRC (x), 1)))) >= 7
              && GET_CODE (SET_DEST (x)) == REG
-             && (split = find_single_use (SET_DEST (x), insn, (rtx*)0)) != 0
+             && (split = find_single_use (SET_DEST (x), insn, (rtx*) 0)) != 0
              && (GET_CODE (*split) == EQ || GET_CODE (*split) == NE)
              && XEXP (*split, 0) == SET_DEST (x)
              && XEXP (*split, 1) == const0_rtx)
@@ -3485,7 +3534,24 @@ subst (x, from, to, in_dest, unique_copy)
              if (GET_CODE (new) == CLOBBER && XEXP (new, 0) == const0_rtx)
                return new;
 
-             SUBST (XEXP (x, i), new);
+             if (GET_CODE (new) == CONST_INT && GET_CODE (x) == SUBREG)
+               {
+                 x = simplify_subreg (GET_MODE (x), new,
+                                      GET_MODE (SUBREG_REG (x)),
+                                      SUBREG_BYTE (x));
+                 if (! x)
+                   abort ();
+               }
+             else if (GET_CODE (new) == CONST_INT
+                      && GET_CODE (x) == ZERO_EXTEND)
+               {
+                 x = simplify_unary_operation (ZERO_EXTEND, GET_MODE (x),
+                                               new, GET_MODE (XEXP (x, 0)));
+                 if (! x)
+                   abort ();
+               }
+             else
+               SUBST (XEXP (x, i), new);
            }
        }
     }
@@ -3914,12 +3980,14 @@ combine_simplify_rtx (x, op0_mode, last, in_dest)
       if (GET_CODE (XEXP (x, 0)) == NOT)
        return plus_constant (XEXP (XEXP (x, 0), 0), 1);
 
-      /* (neg (minus X Y)) can become (minus Y X).  */
+      /* (neg (minus X Y)) can become (minus Y X).  This transformation
+        isn't safe for modes with signed zeros, since if X and Y are
+        both +0, (minus Y X) is the same as (minus X Y).  If the rounding
+        mode is towards +infinity (or -infinity) then the two expressions
+        will be rounded differently.  */
       if (GET_CODE (XEXP (x, 0)) == MINUS
-         && (! FLOAT_MODE_P (mode)
-             /* x-y != -(y-x) with IEEE floating point.  */
-             || TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT
-             || flag_unsafe_math_optimizations))
+         && !HONOR_SIGNED_ZEROS (mode)
+         && !HONOR_SIGN_DEPENDENT_ROUNDING (mode))
        return gen_binary (MINUS, mode, XEXP (XEXP (x, 0), 1),
                           XEXP (XEXP (x, 0), 0));
 
@@ -4081,10 +4149,11 @@ combine_simplify_rtx (x, op0_mode, last, in_dest)
       if (XEXP (x, 1) == const0_rtx)
        return XEXP (x, 0);
 
-      /* In IEEE floating point, x-0 is not the same as x.  */
-      if ((TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT
-          || ! FLOAT_MODE_P (GET_MODE (XEXP (x, 0)))
-          || flag_unsafe_math_optimizations)
+      /* x - 0 is the same as x unless x's mode has signed zeros and
+        allows rounding towards -infinity.  Under those conditions,
+        0 - 0 is -0.  */
+      if (!(HONOR_SIGNED_ZEROS (GET_MODE (XEXP (x, 0)))
+           && HONOR_SIGN_DEPENDENT_ROUNDING (GET_MODE (XEXP (x, 0))))
          && XEXP (x, 1) == CONST0_RTX (GET_MODE (XEXP (x, 0))))
        return XEXP (x, 0);
       break;
@@ -4713,8 +4782,8 @@ simplify_if_then_else (x)
          simplify_gen_unary (NEG, mode,
                              simplify_gen_unary (ABS, mode, true_rtx, mode),
                              mode);
-    default:
-      break;
+      default:
+       break;
       }
 
   /* Look for MIN or MAX.  */
@@ -5685,11 +5754,9 @@ expand_field_assignment (x)
       if (GET_CODE (SET_DEST (x)) == STRICT_LOW_PART
          && GET_CODE (XEXP (SET_DEST (x), 0)) == SUBREG)
        {
-         int byte_offset = SUBREG_BYTE (XEXP (SET_DEST (x), 0));
-
          inner = SUBREG_REG (XEXP (SET_DEST (x), 0));
          len = GET_MODE_BITSIZE (GET_MODE (XEXP (SET_DEST (x), 0)));
-         pos = GEN_INT (BITS_PER_WORD * (byte_offset / UNITS_PER_WORD));
+         pos = GEN_INT (subreg_lsb (XEXP (SET_DEST (x), 0)));
        }
       else if (GET_CODE (SET_DEST (x)) == ZERO_EXTRACT
               && GET_CODE (XEXP (SET_DEST (x), 1)) == CONST_INT)
@@ -5965,6 +6032,9 @@ make_extraction (mode, inner, pos, pos_rtx, len,
       if (mode == tmode)
        return new;
 
+      if (GET_CODE (new) == CONST_INT)
+       return gen_int_mode (INTVAL (new), mode);
+
       /* If we know that no extraneous bits are set, and that the high
         bit is not set, convert the extraction to the cheaper of
         sign and zero extension, that are equivalent in these cases.  */
@@ -6703,7 +6773,8 @@ force_to_mode (x, mode, mask, reg, just_select)
             need it.  */
 
          if (GET_CODE (x) == AND && GET_CODE (XEXP (x, 1)) == CONST_INT
-             && (unsigned HOST_WIDE_INT) INTVAL (XEXP (x, 1)) == mask)
+             && ((INTVAL (XEXP (x, 1)) & GET_MODE_MASK (GET_MODE (x)))
+                 == (HOST_WIDE_INT) mask))
            x = XEXP (x, 0);
 
          /* If it remains an AND, try making another AND with the bits
@@ -6754,33 +6825,12 @@ force_to_mode (x, mode, mask, reg, just_select)
          smask |= (HOST_WIDE_INT) -1 << width;
 
        if (GET_CODE (XEXP (x, 1)) == CONST_INT
-           && exact_log2 (- smask) >= 0)
-         {
-#ifdef STACK_BIAS
-           if (STACK_BIAS
-               && (XEXP (x, 0) == stack_pointer_rtx
-                   || XEXP (x, 0) == frame_pointer_rtx))
-             {
-               int sp_alignment = STACK_BOUNDARY / BITS_PER_UNIT;
-               unsigned HOST_WIDE_INT sp_mask = GET_MODE_MASK (mode);
-
-               sp_mask &= ~(sp_alignment - 1);
-               if ((sp_mask & ~smask) == 0
-                   && ((INTVAL (XEXP (x, 1)) - STACK_BIAS) & ~smask) != 0)
-                 return force_to_mode (plus_constant (XEXP (x, 0),
-                                                      ((INTVAL (XEXP (x, 1)) -
-                                                        STACK_BIAS) & smask)
-                                                      + STACK_BIAS),
-                                       mode, smask, reg, next_select);
-             }
-#endif
-           if ((nonzero_bits (XEXP (x, 0), mode) & ~smask) == 0
-               && (INTVAL (XEXP (x, 1)) & ~smask) != 0)
-             return force_to_mode (plus_constant (XEXP (x, 0),
-                                                  (INTVAL (XEXP (x, 1))
-                                                   & smask)),
-                                   mode, smask, reg, next_select);
-         }
+           && exact_log2 (- smask) >= 0
+           && (nonzero_bits (XEXP (x, 0), mode) & ~smask) == 0
+           && (INTVAL (XEXP (x, 1)) & ~smask) != 0)
+         return force_to_mode (plus_constant (XEXP (x, 0),
+                                              (INTVAL (XEXP (x, 1)) & smask)),
+                               mode, smask, reg, next_select);
       }
 
       /* ... fall through ...  */
@@ -6976,7 +7026,7 @@ force_to_mode (x, mode, mask, reg, just_select)
        {
          int i = -1;
 
-         /* If the considered data is wider then HOST_WIDE_INT, we can't
+         /* If the considered data is wider than HOST_WIDE_INT, we can't
             represent a mask for all its bits in a single scalar.
             But we only care about the lower bits, so calculate these.  */
 
@@ -7059,7 +7109,7 @@ force_to_mode (x, mode, mask, reg, just_select)
 
     case NEG:
       /* If we just want the low-order bit, the NEG isn't needed since it
-        won't change the low-order bit.    */
+        won't change the low-order bit.  */
       if (mask == 1)
        return force_to_mode (XEXP (x, 0), mode, mask, reg, just_select);
 
@@ -7432,6 +7482,50 @@ known_cond (x, cond, reg, val)
            }
        }
     }
+  else if (code == SUBREG)
+    {
+      enum machine_mode inner_mode = GET_MODE (SUBREG_REG (x));
+      rtx new, r = known_cond (SUBREG_REG (x), cond, reg, val);
+
+      if (SUBREG_REG (x) != r)
+       {
+         /* We must simplify subreg here, before we lose track of the
+            original inner_mode.  */
+         new = simplify_subreg (GET_MODE (x), r,
+                                inner_mode, SUBREG_BYTE (x));
+         if (new)
+           return new;
+         else
+           SUBST (SUBREG_REG (x), r);
+       }
+
+      return x;
+    }
+  /* We don't have to handle SIGN_EXTEND here, because even in the
+     case of replacing something with a modeless CONST_INT, a
+     CONST_INT is already (supposed to be) a valid sign extension for
+     its narrower mode, which implies it's already properly
+     sign-extended for the wider mode.  Now, for ZERO_EXTEND, the
+     story is different.  */
+  else if (code == ZERO_EXTEND)
+    {
+      enum machine_mode inner_mode = GET_MODE (XEXP (x, 0));
+      rtx new, r = known_cond (XEXP (x, 0), cond, reg, val);
+
+      if (XEXP (x, 0) != r)
+       {
+         /* We must simplify the zero_extend here, before we lose
+             track of the original inner_mode.  */
+         new = simplify_unary_operation (ZERO_EXTEND, GET_MODE (x),
+                                         r, inner_mode);
+         if (new)
+           return new;
+         else
+           SUBST (XEXP (x, 0), r);
+       }
+
+      return x;
+    }
 
   fmt = GET_RTX_FORMAT (code);
   for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
@@ -7757,7 +7851,6 @@ simplify_and_const_int (x, mode, varop, constop)
      MODE.  */
 
   nonzero = nonzero_bits (varop, mode) & GET_MODE_MASK (mode);
-  nonzero = trunc_int_for_mode (nonzero, mode);
 
   /* Turn off all bits in the constant that are known to already be zero.
      Thus, if the AND isn't needed at all, we will have CONSTOP == NONZERO_BITS
@@ -7825,18 +7918,22 @@ simplify_and_const_int (x, mode, varop, constop)
   /* If we are only masking insignificant bits, return VAROP.  */
   if (constop == nonzero)
     x = varop;
-
-  /* Otherwise, return an AND.  See how much, if any, of X we can use.  */
-  else if (x == 0 || GET_CODE (x) != AND || GET_MODE (x) != mode)
-    x = gen_binary (AND, mode, varop, GEN_INT (constop));
-
   else
     {
-      if (GET_CODE (XEXP (x, 1)) != CONST_INT
-         || (unsigned HOST_WIDE_INT) INTVAL (XEXP (x, 1)) != constop)
-       SUBST (XEXP (x, 1), GEN_INT (constop));
+      /* Otherwise, return an AND.  */
+      constop = trunc_int_for_mode (constop, mode);
+      /* See how much, if any, of X we can use.  */
+      if (x == 0 || GET_CODE (x) != AND || GET_MODE (x) != mode)
+       x = gen_binary (AND, mode, varop, GEN_INT (constop));
+
+      else
+       {
+         if (GET_CODE (XEXP (x, 1)) != CONST_INT
+             || (unsigned HOST_WIDE_INT) INTVAL (XEXP (x, 1)) != constop)
+           SUBST (XEXP (x, 1), GEN_INT (constop));
 
-      SUBST (XEXP (x, 0), varop);
+         SUBST (XEXP (x, 0), varop);
+       }
     }
 
   return x;
@@ -7914,40 +8011,28 @@ nonzero_bits (x, mode)
        nonzero &= GET_MODE_MASK (ptr_mode);
 #endif
 
-#ifdef STACK_BOUNDARY
-      /* If this is the stack pointer, we may know something about its
-        alignment.  If PUSH_ROUNDING is defined, it is possible for the
-        stack to be momentarily aligned only to that amount, so we pick
-        the least alignment.  */
-
-      /* We can't check for arg_pointer_rtx here, because it is not
-        guaranteed to have as much alignment as the stack pointer.
-        In particular, in the Irix6 n64 ABI, the stack has 128 bit
-        alignment but the argument pointer has only 64 bit alignment.  */
-
-      if ((x == frame_pointer_rtx
-          || x == stack_pointer_rtx
-          || x == hard_frame_pointer_rtx
-          || (REGNO (x) >= FIRST_VIRTUAL_REGISTER
-              && REGNO (x) <= LAST_VIRTUAL_REGISTER))
-#ifdef STACK_BIAS
-         && !STACK_BIAS
-#endif
-             )
+      /* Include declared information about alignment of pointers.  */
+      /* ??? We don't properly preserve REG_POINTER changes across
+        pointer-to-integer casts, so we can't trust it except for
+        things that we know must be pointers.  See execute/960116-1.c.  */
+      if ((x == stack_pointer_rtx
+          || x == frame_pointer_rtx
+          || x == arg_pointer_rtx)
+         && REGNO_POINTER_ALIGN (REGNO (x)))
        {
-         int sp_alignment = STACK_BOUNDARY / BITS_PER_UNIT;
+         unsigned HOST_WIDE_INT alignment
+           = REGNO_POINTER_ALIGN (REGNO (x)) / BITS_PER_UNIT;
 
 #ifdef PUSH_ROUNDING
-         if (REGNO (x) == STACK_POINTER_REGNUM && PUSH_ARGS)
-           sp_alignment = MIN (PUSH_ROUNDING (1), sp_alignment);
+         /* If PUSH_ROUNDING is defined, it is possible for the
+            stack to be momentarily aligned only to that amount,
+            so we pick the least alignment.  */
+         if (x == stack_pointer_rtx && PUSH_ARGS)
+           alignment = MIN (PUSH_ROUNDING (1), alignment);
 #endif
 
-         /* We must return here, otherwise we may get a worse result from
-            one of the choices below.  There is nothing useful below as
-            far as the stack pointer is concerned.  */
-         return nonzero &= ~(sp_alignment - 1);
+         nonzero &= ~(alignment - 1);
        }
-#endif
 
       /* If X is a register whose nonzero bits value is current, use it.
         Otherwise, if X is a register whose value we can find, use that
@@ -7962,7 +8047,7 @@ nonzero_bits (x, mode)
                  && ! REGNO_REG_SET_P (BASIC_BLOCK (0)->global_live_at_start,
                                        REGNO (x))))
          && INSN_CUID (reg_last_set[REGNO (x)]) < subst_low_cuid)
-       return reg_last_set_nonzero_bits[REGNO (x)];
+       return reg_last_set_nonzero_bits[REGNO (x)] & nonzero;
 
       tem = get_last_value (x);
 
@@ -7988,7 +8073,7 @@ nonzero_bits (x, mode)
                           | ((HOST_WIDE_INT) (-1)
                              << GET_MODE_BITSIZE (GET_MODE (x))));
 #endif
-         return nonzero_bits (tem, mode);
+         return nonzero_bits (tem, mode) & nonzero;
        }
       else if (nonzero_sign_valid && reg_nonzero_bits[REGNO (x)])
        {
@@ -8126,22 +8211,6 @@ nonzero_bits (x, mode)
        switch (code)
          {
          case PLUS:
-#ifdef STACK_BIAS
-           if (STACK_BIAS
-               && (XEXP (x, 0) == stack_pointer_rtx
-                   || XEXP (x, 0) == frame_pointer_rtx)
-               && GET_CODE (XEXP (x, 1)) == CONST_INT)
-             {
-               int sp_alignment = STACK_BOUNDARY / BITS_PER_UNIT;
-
-               nz0 = (GET_MODE_MASK (mode) & ~(sp_alignment - 1));
-               nz1 = INTVAL (XEXP (x, 1)) - STACK_BIAS;
-               width0 = floor_log2 (nz0) + 1;
-               width1 = floor_log2 (nz1) + 1;
-               low0 = floor_log2 (nz0 & -nz0);
-               low1 = floor_log2 (nz1 & -nz1);
-             }
-#endif
            result_width = MAX (width0, width1) + 1;
            result_low = MIN (low0, low1);
            break;
@@ -8209,7 +8278,7 @@ nonzero_bits (x, mode)
         been zero-extended, we know that at least the high-order bits
         are zero, though others might be too.  */
 
-      if (SUBREG_PROMOTED_VAR_P (x) && SUBREG_PROMOTED_UNSIGNED_P (x))
+      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)));
 
@@ -9518,13 +9587,7 @@ simplify_shift_const (x, code, result_mode, varop, orig_count)
   if (new != 0)
     x = new;
   else
-    {
-      if (x == 0 || GET_CODE (x) != code || GET_MODE (x) != shift_mode)
-       x = gen_rtx_fmt_ee (code, shift_mode, varop, const_rtx);
-
-      SUBST (XEXP (x, 0), varop);
-      SUBST (XEXP (x, 1), const_rtx);
-    }
+    x = gen_rtx_fmt_ee (code, shift_mode, varop, const_rtx);
 
   /* If we have an outer operation and we just made a shift, it is
      possible that we could have simplified the shift were it not
@@ -9594,7 +9657,7 @@ recog_for_combine (pnewpat, insn, pnotes)
   int num_clobbers_to_add = 0;
   int i;
   rtx notes = 0;
-  rtx old_notes;
+  rtx dummy_insn;
 
   /* If PAT is a PARALLEL, check to see if it contains the CLOBBER
      we use to indicate that something didn't match.  If we find such a
@@ -9605,11 +9668,13 @@ recog_for_combine (pnewpat, insn, pnotes)
          && XEXP (XVECEXP (pat, 0, i), 0) == const0_rtx)
        return -1;
 
-  /* Remove the old notes prior to trying to recognize the new pattern.  */
-  old_notes = REG_NOTES (insn);
-  REG_NOTES (insn) = 0;
+  /* *pnewpat does not have to be actual PATTERN (insn), so make a dummy
+     instruction for pattern recognition.  */
+  dummy_insn = shallow_copy_rtx (insn);
+  PATTERN (dummy_insn) = pat;
+  REG_NOTES (dummy_insn) = 0;
 
-  insn_code_number = recog (pat, insn, &num_clobbers_to_add);
+  insn_code_number = recog (pat, dummy_insn, &num_clobbers_to_add);
 
   /* If it isn't, there is the possibility that we previously had an insn
      that clobbered some register as a side effect, but the combined
@@ -9634,15 +9699,14 @@ recog_for_combine (pnewpat, insn, pnotes)
       if (pos == 1)
        pat = XVECEXP (pat, 0, 0);
 
-      insn_code_number = recog (pat, insn, &num_clobbers_to_add);
+      PATTERN (dummy_insn) = pat;
+      insn_code_number = recog (pat, dummy_insn, &num_clobbers_to_add);
     }
 
   /* Recognize all noop sets, these will be killed by followup pass.  */
   if (insn_code_number < 0 && GET_CODE (pat) == SET && set_noop_p (pat))
     insn_code_number = NOOP_MOVE_INSN_CODE, num_clobbers_to_add = 0;
 
-  REG_NOTES (insn) = old_notes;
-
   /* If we had any clobbers to add, make a new pattern than contains
      them.  Then check to make sure that all of them are dead.  */
   if (num_clobbers_to_add)
@@ -10728,7 +10792,7 @@ simplify_comparison (code, pop0, pop1)
              unsigned HOST_WIDE_INT temp = const_op & GET_MODE_MASK (mode);
 
              temp >>= INTVAL (XEXP (op0, 1));
-             op1 = GEN_INT (trunc_int_for_mode (temp, mode));
+             op1 = gen_int_mode (temp, mode);
              op0 = XEXP (op0, 0);
              continue;
            }
@@ -10829,6 +10893,11 @@ simplify_comparison (code, pop0, pop1)
                  || (floor_log2 (const_op) + INTVAL (XEXP (op0, 1))
                      < mode_width)))
            {
+             /* If the shift was logical, then we must make the condition
+                unsigned.  */
+             if (GET_CODE (op0) == LSHIFTRT)
+               code = unsigned_condition (code);
+
              const_op <<= INTVAL (XEXP (op0, 1));
              op1 = GEN_INT (const_op);
              op0 = XEXP (op0, 0);
@@ -10967,19 +11036,19 @@ static enum rtx_code
 combine_reversed_comparison_code (exp)
      rtx exp;
 {
-   enum rtx_code code1 = reversed_comparison_code (exp, NULL);
-   rtx x;
-
-   if (code1 != UNKNOWN
-       || GET_MODE_CLASS (GET_MODE (XEXP (exp, 0))) != MODE_CC)
-     return code1;
-   /* Otherwise try and find where the condition codes were last set and
-      use that.  */
-   x = get_last_value (XEXP (exp, 0));
-   if (!x || GET_CODE (x) != COMPARE)
-     return UNKNOWN;
-   return reversed_comparison_code_parts (GET_CODE (exp),
-                                         XEXP (x, 0), XEXP (x, 1), NULL);
+  enum rtx_code code1 = reversed_comparison_code (exp, NULL);
+  rtx x;
+
+  if (code1 != UNKNOWN
+      || GET_MODE_CLASS (GET_MODE (XEXP (exp, 0))) != MODE_CC)
+    return code1;
+  /* Otherwise try and find where the condition codes were last set and
+     use that.  */
+  x = get_last_value (XEXP (exp, 0));
+  if (!x || GET_CODE (x) != COMPARE)
+    return UNKNOWN;
+  return reversed_comparison_code_parts (GET_CODE (exp),
+                                        XEXP (x, 0), XEXP (x, 1), NULL);
 }
 /* Return comparison with reversed code of EXP and operands OP0 and OP1.
    Return NULL_RTX in case we fail to do the reversal.  */
@@ -11269,7 +11338,7 @@ record_promoted_value (insn, subreg)
 
       if (reg_last_set[regno] == insn)
        {
-         if (SUBREG_PROMOTED_UNSIGNED_P (subreg))
+         if (SUBREG_PROMOTED_UNSIGNED_P (subreg) > 0)
            reg_last_set_nonzero_bits[regno] &= GET_MODE_MASK (mode);
        }
 
@@ -11616,6 +11685,7 @@ mark_used_regs_combine (x)
     case CONST_INT:
     case CONST:
     case CONST_DOUBLE:
+    case CONST_VECTOR:
     case PC:
     case ADDR_VEC:
     case ADDR_DIFF_VEC: