cse.c (find_comparison_args): Use val_mode_signbit_set_p.
authorBernd Schmidt <bernds@codesourcery.com>
Wed, 6 Jul 2011 14:21:03 +0000 (14:21 +0000)
committerBernd Schmidt <bernds@gcc.gnu.org>
Wed, 6 Jul 2011 14:21:03 +0000 (14:21 +0000)
* cse.c (find_comparison_args): Use val_mode_signbit_set_p.
* simplify-rtx.c (mode_signbit_p): Use GET_MODE_PRECISION.
(val_mode_signbit_p, val_mode_signbit_set_p): New functions.
(simplify_const_unary_operation, simplify_binary_operation_1,
simplify_const_binary_operation,
simplify_const_relational_operation): Use them.  Use
GET_MODE_MASK for masking and sign-extensions.
* combine.c (set_nonzero_bits_and_sign_copies, simplify_set,
combine_simplify_rtx, force_to_mode, reg_nonzero_bits_for_combine,
simplify_shift_const_1, simplify_comparison): Likewise.
* expr.c (convert_modes): Likewise.
* rtlanal.c (nonzero_bits1, canonicalize_condition): Likewise.
* expmed.c (emit_cstore, emit_store_flag_1, emit_store_flag):
Likewise.
* rtl.h (val_mode_signbit_p, val_mode_signbit_set_p): Declare.

From-SVN: r175917

gcc/ChangeLog
gcc/combine.c
gcc/cse.c
gcc/expmed.c
gcc/expr.c
gcc/rtl.h
gcc/rtlanal.c
gcc/simplify-rtx.c

index 57c5390edeb2d4f113b72ebcc2aecda6395a1f43..e06f36996e9fc398f6239be7852cf31a95a38a80 100644 (file)
@@ -1,3 +1,21 @@
+2011-07-06  Bernd Schmidt  <bernds@codesourcery.com>
+
+       * cse.c (find_comparison_args): Use val_mode_signbit_set_p.
+       * simplify-rtx.c (mode_signbit_p): Use GET_MODE_PRECISION.
+       (val_mode_signbit_p, val_mode_signbit_set_p): New functions.
+       (simplify_const_unary_operation, simplify_binary_operation_1,
+       simplify_const_binary_operation,
+       simplify_const_relational_operation): Use them.  Use
+       GET_MODE_MASK for masking and sign-extensions.
+       * combine.c (set_nonzero_bits_and_sign_copies, simplify_set,
+       combine_simplify_rtx, force_to_mode, reg_nonzero_bits_for_combine,
+       simplify_shift_const_1, simplify_comparison): Likewise.
+       * expr.c (convert_modes): Likewise.
+       * rtlanal.c (nonzero_bits1, canonicalize_condition): Likewise.
+       * expmed.c (emit_cstore, emit_store_flag_1, emit_store_flag):
+       Likewise.
+       * rtl.h (val_mode_signbit_p, val_mode_signbit_set_p): Declare.
+
 2011-07-06  Richard Guenther  <rguenther@suse.de>
 
        PR tree-optimization/49645
index 737f300b0633d50e0367d97dd6a5355647137a13..7ac4613955c1f14dfc9899cf869fbb2cbd895fcd 100644 (file)
@@ -1627,15 +1627,11 @@ set_nonzero_bits_and_sign_copies (rtx x, const_rtx set, void *data)
             ??? For 2.5, try to tighten up the MD files in this regard
             instead of this kludge.  */
 
-         if (GET_MODE_BITSIZE (GET_MODE (x)) < BITS_PER_WORD
+         if (GET_MODE_PRECISION (GET_MODE (x)) < BITS_PER_WORD
              && CONST_INT_P (src)
              && INTVAL (src) > 0
-             && 0 != (UINTVAL (src)
-                      & ((unsigned HOST_WIDE_INT) 1
-                         << (GET_MODE_BITSIZE (GET_MODE (x)) - 1))))
-           src = GEN_INT (UINTVAL (src)
-                          | ((unsigned HOST_WIDE_INT) (-1)
-                             << GET_MODE_BITSIZE (GET_MODE (x))));
+             && val_signbit_known_set_p (GET_MODE (x), INTVAL (src)))
+           src = GEN_INT (INTVAL (src) | ~GET_MODE_MASK (GET_MODE (x)));
 #endif
 
          /* Don't call nonzero_bits if it cannot change anything.  */
@@ -5887,8 +5883,7 @@ combine_simplify_rtx (rtx x, enum machine_mode op0_mode, int in_dest,
             going to test the sign bit.  */
          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))
+             && val_signbit_p (mode, STORE_FLAG_VALUE)
              && op1 == const0_rtx
              && mode == GET_MODE (op0)
              && (i = exact_log2 (nonzero_bits (op0, mode))) >= 0)
@@ -6551,10 +6546,8 @@ simplify_set (rtx x)
       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))))
+      if (val_signbit_known_clear_p (GET_MODE (src),
+                                    nonzero_bits (inner, inner_mode)))
        {
          SUBST (SET_SRC (x), inner);
          src = SET_SRC (x);
@@ -8445,9 +8438,7 @@ force_to_mode (rtx x, enum machine_mode mode, unsigned HOST_WIDE_INT mask,
     case ASHIFTRT:
       /* If we are just looking for the sign bit, we don't need this shift at
         all, even if it has a variable count.  */
-      if (GET_MODE_BITSIZE (GET_MODE (x)) <= HOST_BITS_PER_WIDE_INT
-         && (mask == ((unsigned HOST_WIDE_INT) 1
-                      << (GET_MODE_BITSIZE (GET_MODE (x)) - 1))))
+      if (val_signbit_p (GET_MODE (x), mask))
        return force_to_mode (XEXP (x, 0), mode, mask, next_select);
 
       /* If this is a shift by a constant, get a mask that contains those bits
@@ -9589,15 +9580,11 @@ reg_nonzero_bits_for_combine (const_rtx x, enum machine_mode mode,
         ??? For 2.5, try to tighten up the MD files in this regard
         instead of this kludge.  */
 
-      if (GET_MODE_BITSIZE (GET_MODE (x)) < GET_MODE_BITSIZE (mode)
+      if (GET_MODE_PRECISION (GET_MODE (x)) < GET_MODE_PRECISION (mode)
          && CONST_INT_P (tem)
          && INTVAL (tem) > 0
-         && 0 != (UINTVAL (tem)
-                  & ((unsigned HOST_WIDE_INT) 1
-                     << (GET_MODE_BITSIZE (GET_MODE (x)) - 1))))
-       tem = GEN_INT (UINTVAL (tem)
-                      | ((unsigned HOST_WIDE_INT) (-1)
-                         << GET_MODE_BITSIZE (GET_MODE (x))));
+         && val_signbit_known_set_p (GET_MODE (x), INTVAL (tem)))
+       tem = GEN_INT (INTVAL (tem) | ~GET_MODE_MASK (GET_MODE (x)));
 #endif
       return tem;
     }
@@ -9987,11 +9974,9 @@ simplify_shift_const_1 (enum rtx_code code, enum machine_mode result_mode,
         ASHIFTRT to LSHIFTRT if we know the sign bit is clear.
         `make_compound_operation' will convert it to an ASHIFTRT for
         those machines (such as VAX) that don't have an LSHIFTRT.  */
-      if (GET_MODE_BITSIZE (shift_mode) <= HOST_BITS_PER_WIDE_INT
-         && code == ASHIFTRT
-         && ((nonzero_bits (varop, shift_mode)
-              & ((unsigned HOST_WIDE_INT) 1
-                 << (GET_MODE_BITSIZE (shift_mode) - 1))) == 0))
+      if (code == ASHIFTRT
+         && val_signbit_known_clear_p (shift_mode,
+                                       nonzero_bits (varop, shift_mode)))
        code = LSHIFTRT;
 
       if (((code == LSHIFTRT
@@ -11424,10 +11409,7 @@ simplify_comparison (enum rtx_code code, rtx *pop0, rtx *pop1)
          mode = GET_MODE (XEXP (op0, 0));
          if (mode != VOIDmode && GET_MODE_CLASS (mode) == MODE_INT
              && ! unsigned_comparison_p
-             && (GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT)
-             && ((unsigned HOST_WIDE_INT) const_op
-                 < (((unsigned HOST_WIDE_INT) 1
-                     << (GET_MODE_BITSIZE (mode) - 1))))
+             && val_signbit_known_clear_p (mode, const_op)
              && have_insn_for (COMPARE, mode))
            {
              op0 = XEXP (op0, 0);
@@ -11614,11 +11596,7 @@ simplify_comparison (enum rtx_code code, rtx *pop0, rtx *pop1)
          /* Check for the cases where we simply want the result of the
             earlier test or the opposite of that result.  */
          if (code == NE || code == EQ
-             || (GET_MODE_BITSIZE (GET_MODE (op0)) <= HOST_BITS_PER_WIDE_INT
-                 && GET_MODE_CLASS (GET_MODE (op0)) == MODE_INT
-                 && (STORE_FLAG_VALUE
-                     & (((unsigned HOST_WIDE_INT) 1
-                         << (GET_MODE_BITSIZE (GET_MODE (op0)) - 1))))
+             || (val_signbit_known_set_p (GET_MODE (op0), STORE_FLAG_VALUE)
                  && (code == LT || code == GE)))
            {
              enum rtx_code new_code;
index 8a31cd1a3da4b22fa4bf2eba8ab1f533684f29fd..9dc27c383e88e8251aa1367e614241d901f7fa70 100644 (file)
--- a/gcc/cse.c
+++ b/gcc/cse.c
@@ -3063,12 +3063,8 @@ find_comparison_args (enum rtx_code code, rtx *parg1, rtx *parg2,
                 for STORE_FLAG_VALUE, also look at LT and GE operations.  */
              || ((code == NE
                   || (code == LT
-                      && GET_MODE_CLASS (inner_mode) == MODE_INT
-                      && (GET_MODE_BITSIZE (inner_mode)
-                          <= HOST_BITS_PER_WIDE_INT)
-                      && (STORE_FLAG_VALUE
-                          & ((HOST_WIDE_INT) 1
-                             << (GET_MODE_BITSIZE (inner_mode) - 1))))
+                      && val_signbit_known_set_p (inner_mode,
+                                                  STORE_FLAG_VALUE))
 #ifdef FLOAT_STORE_FLAG_VALUE
                   || (code == LT
                       && SCALAR_FLOAT_MODE_P (inner_mode)
@@ -3083,12 +3079,8 @@ find_comparison_args (enum rtx_code code, rtx *parg1, rtx *parg2,
            }
          else if ((code == EQ
                    || (code == GE
-                       && GET_MODE_CLASS (inner_mode) == MODE_INT
-                       && (GET_MODE_BITSIZE (inner_mode)
-                           <= HOST_BITS_PER_WIDE_INT)
-                       && (STORE_FLAG_VALUE
-                           & ((HOST_WIDE_INT) 1
-                              << (GET_MODE_BITSIZE (inner_mode) - 1))))
+                       && val_signbit_known_set_p (inner_mode,
+                                                   STORE_FLAG_VALUE))
 #ifdef FLOAT_STORE_FLAG_VALUE
                    || (code == GE
                        && SCALAR_FLOAT_MODE_P (inner_mode)
index 314fac79c284c679c43765ee1f00f33654a5381a..e9b6016cf8be53480cdb55e9399beb1ef5572c3e 100644 (file)
@@ -5039,10 +5039,8 @@ emit_cstore (rtx target, enum insn_code icode, enum rtx_code code,
   if (GET_MODE_SIZE (target_mode) > GET_MODE_SIZE (result_mode))
     {
       convert_move (target, subtarget,
-                   (GET_MODE_BITSIZE (result_mode) <= HOST_BITS_PER_WIDE_INT)
-                   && 0 == (STORE_FLAG_VALUE
-                            & ((HOST_WIDE_INT) 1
-                               << (GET_MODE_BITSIZE (result_mode) -1))));
+                   val_signbit_known_clear_p (result_mode,
+                                              STORE_FLAG_VALUE));
       op0 = target;
       result_mode = target_mode;
     }
@@ -5066,9 +5064,7 @@ emit_cstore (rtx target, enum insn_code icode, enum rtx_code code,
   /* We don't want to use STORE_FLAG_VALUE < 0 below since this makes
      it hard to use a value of just the sign bit due to ANSI integer
      constant typing rules.  */
-  else if (GET_MODE_BITSIZE (result_mode) <= HOST_BITS_PER_WIDE_INT
-          && (STORE_FLAG_VALUE
-              & ((HOST_WIDE_INT) 1 << (GET_MODE_BITSIZE (result_mode) - 1))))
+  else if (val_signbit_known_set_p (result_mode, STORE_FLAG_VALUE))
     op0 = expand_shift (RSHIFT_EXPR, result_mode, op0,
                        GET_MODE_BITSIZE (result_mode) - 1, subtarget,
                        normalizep == 1);
@@ -5206,9 +5202,9 @@ emit_store_flag_1 (rtx target, enum rtx_code code, rtx op0, rtx op1,
            target = gen_reg_rtx (target_mode);
 
          convert_move (target, tem,
-                       0 == ((normalizep ? normalizep : STORE_FLAG_VALUE)
-                             & ((HOST_WIDE_INT) 1
-                                << (GET_MODE_BITSIZE (word_mode) -1))));
+                       !val_signbit_known_set_p (word_mode,
+                                                 (normalizep ? normalizep
+                                                  : STORE_FLAG_VALUE)));
          return target;
        }
     }
@@ -5218,10 +5214,7 @@ emit_store_flag_1 (rtx target, enum rtx_code code, rtx op0, rtx op1,
   if (op1 == const0_rtx && (code == LT || code == GE)
       && GET_MODE_CLASS (mode) == MODE_INT
       && (normalizep || STORE_FLAG_VALUE == 1
-         || (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))))))
+         || val_signbit_p (mode, STORE_FLAG_VALUE)))
     {
       subtarget = target;
 
@@ -5330,9 +5323,7 @@ emit_store_flag (rtx target, enum rtx_code code, rtx op0, rtx op1,
       if (STORE_FLAG_VALUE == 1 || STORE_FLAG_VALUE == -1)
        normalizep = STORE_FLAG_VALUE;
 
-      else if (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)))
+      else if (val_signbit_p (mode, STORE_FLAG_VALUE))
        ;
       else
        return 0;
index 176978a2257db958a11b0ca3204fe71a00db0eda..e225d245a044f21574731fd98f8cc4a80caa6dff 100644 (file)
@@ -764,14 +764,13 @@ convert_modes (enum machine_mode mode, enum machine_mode oldmode, rtx x, int uns
          && GET_MODE_SIZE (mode) > GET_MODE_SIZE (oldmode))
        {
          HOST_WIDE_INT val = INTVAL (x);
-         int width = GET_MODE_BITSIZE (oldmode);
 
          /* We must sign or zero-extend in this case.  Start by
             zero-extending, then sign extend if we need to.  */
-         val &= ((HOST_WIDE_INT) 1 << width) - 1;
+         val &= GET_MODE_MASK (oldmode);
          if (! unsignedp
-             && (val & ((HOST_WIDE_INT) 1 << (width - 1))))
-           val |= (HOST_WIDE_INT) (-1) << width;
+             && val_signbit_known_set_p (oldmode, val))
+           val |= ~GET_MODE_MASK (oldmode);
 
          return gen_int_mode (val, mode);
        }
index da18788a292fb3bca6c9964cdd557d66d983a72f..2f2aaca7b426d21ac8687d0518eccb20faaaa1f6 100644 (file)
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -1816,6 +1816,11 @@ extern rtx simplify_rtx (const_rtx);
 extern rtx avoid_constant_pool_reference (rtx);
 extern rtx delegitimize_mem_from_attrs (rtx);
 extern bool mode_signbit_p (enum machine_mode, const_rtx);
+extern bool val_signbit_p (enum machine_mode, unsigned HOST_WIDE_INT);
+extern bool val_signbit_known_set_p (enum machine_mode,
+                                    unsigned HOST_WIDE_INT);
+extern bool val_signbit_known_clear_p (enum machine_mode,
+                                      unsigned HOST_WIDE_INT);
 
 /* In reginfo.c  */
 extern enum machine_mode choose_hard_reg_mode (unsigned int, unsigned int,
index 0be6504a9432b0cccf7e1faf3f6ec3d6a84647aa..9ac347ed0fa5b6768e84a592c5bc7fb2917bbf5c 100644 (file)
@@ -3849,6 +3849,7 @@ nonzero_bits1 (const_rtx x, enum machine_mode mode, const_rtx known_x,
   unsigned HOST_WIDE_INT nonzero = GET_MODE_MASK (mode);
   unsigned HOST_WIDE_INT inner_nz;
   enum rtx_code code;
+  enum machine_mode inner_mode;
   unsigned int mode_width = GET_MODE_BITSIZE (mode);
 
   /* For floating-point and vector values, assume all bits are needed.  */
@@ -4028,9 +4029,7 @@ nonzero_bits1 (const_rtx x, enum machine_mode mode, const_rtx known_x,
       if (GET_MODE (XEXP (x, 0)) != VOIDmode)
        {
          inner_nz &= GET_MODE_MASK (GET_MODE (XEXP (x, 0)));
-         if (inner_nz
-             & (((unsigned HOST_WIDE_INT) 1
-                 << (GET_MODE_BITSIZE (GET_MODE (XEXP (x, 0))) - 1))))
+         if (val_signbit_known_set_p (GET_MODE (XEXP (x, 0)), inner_nz))
            inner_nz |= (GET_MODE_MASK (mode)
                         & ~GET_MODE_MASK (GET_MODE (XEXP (x, 0))));
        }
@@ -4153,12 +4152,12 @@ nonzero_bits1 (const_rtx x, enum machine_mode mode, const_rtx known_x,
                  & cached_nonzero_bits (SUBREG_REG (x), GET_MODE (x),
                                         known_x, known_mode, known_ret);
 
+      inner_mode = GET_MODE (SUBREG_REG (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
         object might be nonzero.  */
-      if (GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (x))) <= BITS_PER_WORD
-         && (GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (x)))
-             <= HOST_BITS_PER_WIDE_INT))
+      if (GET_MODE_BITSIZE (inner_mode) <= BITS_PER_WORD
+         && (GET_MODE_BITSIZE (inner_mode) <= HOST_BITS_PER_WIDE_INT))
        {
          nonzero &= cached_nonzero_bits (SUBREG_REG (x), mode,
                                          known_x, known_mode, known_ret);
@@ -4166,12 +4165,9 @@ nonzero_bits1 (const_rtx x, enum machine_mode mode, const_rtx known_x,
 #if defined (WORD_REGISTER_OPERATIONS) && defined (LOAD_EXTEND_OP)
          /* If this is a typical RISC machine, we only have to worry
             about the way loads are extended.  */
-         if ((LOAD_EXTEND_OP (GET_MODE (SUBREG_REG (x))) == SIGN_EXTEND
-              ? (((nonzero
-                   & (((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 (inner_mode) == SIGN_EXTEND
+              ? val_signbit_known_set_p (inner_mode, nonzero)
+              : LOAD_EXTEND_OP (inner_mode) != ZERO_EXTEND)
              || !MEM_P (SUBREG_REG (x)))
 #endif
            {
@@ -4179,9 +4175,9 @@ nonzero_bits1 (const_rtx x, enum machine_mode mode, const_rtx known_x,
                 causes the high-order bits to become undefined.  So they are
                 not known to be zero.  */
              if (GET_MODE_SIZE (GET_MODE (x))
-                 > GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))))
+                 > GET_MODE_SIZE (inner_mode))
                nonzero |= (GET_MODE_MASK (GET_MODE (x))
-                           & ~GET_MODE_MASK (GET_MODE (SUBREG_REG (x))));
+                           & ~GET_MODE_MASK (inner_mode));
            }
        }
       break;
@@ -4921,12 +4917,8 @@ canonicalize_condition (rtx insn, rtx cond, int reverse, rtx *earliest,
          if ((GET_CODE (SET_SRC (set)) == COMPARE
               || (((code == NE
                     || (code == LT
-                        && GET_MODE_CLASS (inner_mode) == MODE_INT
-                        && (GET_MODE_BITSIZE (inner_mode)
-                            <= HOST_BITS_PER_WIDE_INT)
-                        && (STORE_FLAG_VALUE
-                            & ((unsigned HOST_WIDE_INT) 1
-                               << (GET_MODE_BITSIZE (inner_mode) - 1))))
+                        && val_signbit_known_set_p (inner_mode,
+                                                    STORE_FLAG_VALUE))
 #ifdef FLOAT_STORE_FLAG_VALUE
                     || (code == LT
                         && SCALAR_FLOAT_MODE_P (inner_mode)
@@ -4941,12 +4933,8 @@ canonicalize_condition (rtx insn, rtx cond, int reverse, rtx *earliest,
            x = SET_SRC (set);
          else if (((code == EQ
                     || (code == GE
-                        && (GET_MODE_BITSIZE (inner_mode)
-                            <= HOST_BITS_PER_WIDE_INT)
-                        && GET_MODE_CLASS (inner_mode) == MODE_INT
-                        && (STORE_FLAG_VALUE
-                            & ((unsigned HOST_WIDE_INT) 1
-                               << (GET_MODE_BITSIZE (inner_mode) - 1))))
+                        && val_signbit_known_set_p (inner_mode,
+                                                    STORE_FLAG_VALUE))
 #ifdef FLOAT_STORE_FLAG_VALUE
                     || (code == GE
                         && SCALAR_FLOAT_MODE_P (inner_mode)
index f7669b1ebc912f429eb07b3342582fc0beee72cc..6a5ec1a1bfa8d4ca9f608423d8c93e1fb10535b5 100644 (file)
@@ -82,7 +82,7 @@ mode_signbit_p (enum machine_mode mode, const_rtx x)
   if (GET_MODE_CLASS (mode) != MODE_INT)
     return false;
 
-  width = GET_MODE_BITSIZE (mode);
+  width = GET_MODE_PRECISION (mode);
   if (width == 0)
     return false;
 
@@ -103,6 +103,62 @@ mode_signbit_p (enum machine_mode mode, const_rtx x)
     val &= ((unsigned HOST_WIDE_INT) 1 << width) - 1;
   return val == ((unsigned HOST_WIDE_INT) 1 << (width - 1));
 }
+
+/* Test whether VAL is equal to the most significant bit of mode MODE
+   (after masking with the mode mask of MODE).  Returns false if the
+   precision of MODE is too large to handle.  */
+
+bool
+val_signbit_p (enum machine_mode mode, unsigned HOST_WIDE_INT val)
+{
+  unsigned int width;
+
+  if (GET_MODE_CLASS (mode) != MODE_INT)
+    return false;
+
+  width = GET_MODE_PRECISION (mode);
+  if (width == 0 || width > HOST_BITS_PER_WIDE_INT)
+    return false;
+
+  val &= GET_MODE_MASK (mode);
+  return val == ((unsigned HOST_WIDE_INT) 1 << (width - 1));
+}
+
+/* Test whether the most significant bit of mode MODE is set in VAL.
+   Returns false if the precision of MODE is too large to handle.  */
+bool
+val_signbit_known_set_p (enum machine_mode mode, unsigned HOST_WIDE_INT val)
+{
+  unsigned int width;
+
+  if (GET_MODE_CLASS (mode) != MODE_INT)
+    return false;
+
+  width = GET_MODE_PRECISION (mode);
+  if (width == 0 || width > HOST_BITS_PER_WIDE_INT)
+    return false;
+
+  val &= (unsigned HOST_WIDE_INT) 1 << (width - 1);
+  return val != 0;
+}
+
+/* Test whether the most significant bit of mode MODE is clear in VAL.
+   Returns false if the precision of MODE is too large to handle.  */
+bool
+val_signbit_known_clear_p (enum machine_mode mode, unsigned HOST_WIDE_INT val)
+{
+  unsigned int width;
+
+  if (GET_MODE_CLASS (mode) != MODE_INT)
+    return false;
+
+  width = GET_MODE_PRECISION (mode);
+  if (width == 0 || width > HOST_BITS_PER_WIDE_INT)
+    return false;
+
+  val &= (unsigned HOST_WIDE_INT) 1 << (width - 1);
+  return val == 0;
+}
 \f
 /* Make a binary operation by properly ordering the operands and
    seeing if the expression folds.  */
@@ -908,12 +964,8 @@ simplify_unary_operation_1 (enum rtx_code code, enum machine_mode mode, rtx op)
 
       /* If operand is something known to be positive, ignore the ABS.  */
       if (GET_CODE (op) == FFS || GET_CODE (op) == ABS
-         || ((GET_MODE_BITSIZE (GET_MODE (op))
-              <= HOST_BITS_PER_WIDE_INT)
-             && ((nonzero_bits (op, GET_MODE (op))
-                  & ((unsigned HOST_WIDE_INT) 1
-                     << (GET_MODE_BITSIZE (GET_MODE (op)) - 1)))
-                 == 0)))
+         || val_signbit_known_clear_p (GET_MODE (op),
+                                       nonzero_bits (op, GET_MODE (op))))
        return op;
 
       /* If operand is known to be only -1 or 0, convert ABS to NEG.  */
@@ -1425,8 +1477,7 @@ simplify_const_unary_operation (enum rtx_code code, enum machine_mode mode,
              val = arg0;
            }
          else if (GET_MODE_BITSIZE (op_mode) < HOST_BITS_PER_WIDE_INT)
-           val = arg0 & ~((unsigned HOST_WIDE_INT) (-1)
-                          << GET_MODE_BITSIZE (op_mode));
+           val = arg0 & GET_MODE_MASK (op_mode);
          else
            return 0;
          break;
@@ -1444,13 +1495,9 @@ simplify_const_unary_operation (enum rtx_code code, enum machine_mode mode,
            }
          else if (GET_MODE_BITSIZE (op_mode) < HOST_BITS_PER_WIDE_INT)
            {
-             val
-               = arg0 & ~((unsigned HOST_WIDE_INT) (-1)
-                          << GET_MODE_BITSIZE (op_mode));
-             if (val & ((unsigned HOST_WIDE_INT) 1
-                        << (GET_MODE_BITSIZE (op_mode) - 1)))
-               val
-                 -= (unsigned HOST_WIDE_INT) 1 << GET_MODE_BITSIZE (op_mode);
+             val = arg0 & GET_MODE_MASK (op_mode);
+             if (val_signbit_known_set_p (op_mode, val))
+               val |= ~GET_MODE_MASK (op_mode);
            }
          else
            return 0;
@@ -1602,10 +1649,8 @@ simplify_const_unary_operation (enum rtx_code code, enum machine_mode mode,
          else
            {
              lv = l1 & GET_MODE_MASK (op_mode);
-             if (GET_MODE_BITSIZE (op_mode) < HOST_BITS_PER_WIDE_INT
-                 && (lv & ((unsigned HOST_WIDE_INT) 1
-                           << (GET_MODE_BITSIZE (op_mode) - 1))) != 0)
-               lv -= (unsigned HOST_WIDE_INT) 1 << GET_MODE_BITSIZE (op_mode);
+             if (val_signbit_known_set_p (op_mode, lv))
+               lv |= ~GET_MODE_MASK (op_mode);
 
              hv = HWI_SIGN_EXTEND (lv);
            }
@@ -2663,9 +2708,7 @@ simplify_binary_operation_1 (enum rtx_code code, enum machine_mode mode,
 
       /* (xor (comparison foo bar) (const_int sign-bit))
         when STORE_FLAG_VALUE is the sign bit.  */
-      if (GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT
-         && ((STORE_FLAG_VALUE & GET_MODE_MASK (mode))
-             == (unsigned HOST_WIDE_INT) 1 << (GET_MODE_BITSIZE (mode) - 1))
+      if (val_signbit_p (mode, STORE_FLAG_VALUE)
          && trueop1 == const_true_rtx
          && COMPARISON_P (op0)
          && (reversed = reversed_comparison (op0, mode)))
@@ -3028,8 +3071,7 @@ simplify_binary_operation_1 (enum rtx_code code, enum machine_mode mode,
 
     case SMIN:
       if (width <= HOST_BITS_PER_WIDE_INT
-         && CONST_INT_P (trueop1)
-         && UINTVAL (trueop1) == (unsigned HOST_WIDE_INT) 1 << (width -1)
+         && mode_signbit_p (mode, trueop1)
          && ! side_effects_p (op0))
        return op1;
       if (rtx_equal_p (trueop0, trueop1) && ! side_effects_p (op0))
@@ -3634,16 +3676,16 @@ simplify_const_binary_operation (enum rtx_code code, enum machine_mode mode,
 
       if (width < HOST_BITS_PER_WIDE_INT)
         {
-          arg0 &= ((unsigned HOST_WIDE_INT) 1 << width) - 1;
-          arg1 &= ((unsigned HOST_WIDE_INT) 1 << width) - 1;
+          arg0 &= GET_MODE_MASK (mode);
+          arg1 &= GET_MODE_MASK (mode);
 
           arg0s = arg0;
-          if (arg0s & ((unsigned HOST_WIDE_INT) 1 << (width - 1)))
-           arg0s |= ((unsigned HOST_WIDE_INT) (-1) << width);
+         if (val_signbit_known_set_p (mode, arg0s))
+           arg0s |= ~GET_MODE_MASK (mode);
 
-         arg1s = arg1;
-         if (arg1s & ((unsigned HOST_WIDE_INT) 1 << (width - 1)))
-           arg1s |= ((unsigned HOST_WIDE_INT) (-1) << width);
+          arg1s = arg1;
+         if (val_signbit_known_set_p (mode, arg1s))
+           arg1s |= ~GET_MODE_MASK (mode);
        }
       else
        {
@@ -4616,14 +4658,14 @@ simplify_const_relational_operation (enum rtx_code code,
         we have to sign or zero-extend the values.  */
       if (width != 0 && width < HOST_BITS_PER_WIDE_INT)
        {
-         l0u &= ((unsigned HOST_WIDE_INT) 1 << width) - 1;
-         l1u &= ((unsigned HOST_WIDE_INT) 1 << width) - 1;
+         l0u &= GET_MODE_MASK (mode);
+         l1u &= GET_MODE_MASK (mode);
 
-         if (l0s & ((unsigned HOST_WIDE_INT) 1 << (width - 1)))
-           l0s |= ((unsigned HOST_WIDE_INT) (-1) << width);
+         if (val_signbit_known_set_p (mode, l0s))
+           l0s |= ~GET_MODE_MASK (mode);
 
-         if (l1s & ((unsigned HOST_WIDE_INT) 1 << (width - 1)))
-           l1s |= ((unsigned HOST_WIDE_INT) (-1) << width);
+         if (val_signbit_known_set_p (mode, l1s))
+           l1s |= ~GET_MODE_MASK (mode);
        }
       if (width != 0 && width <= HOST_BITS_PER_WIDE_INT)
        h0u = h1u = 0, h0s = HWI_SIGN_EXTEND (l0s), h1s = HWI_SIGN_EXTEND (l1s);