aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorBernd Schmidt <bernds@codesourcery.com>2011-07-06 14:21:03 +0000
committerBernd Schmidt <bernds@gcc.gnu.org>2011-07-06 14:21:03 +0000
commit2d0c270fd266218ff040965bb8231729df9144f1 (patch)
tree2a2d891d415bcfdd26b794dc666ecd03b7565eee /gcc
parent6d6c952527c53637280297b2e6a48d6b21606294 (diff)
downloadgcc-2d0c270fd266218ff040965bb8231729df9144f1.zip
gcc-2d0c270fd266218ff040965bb8231729df9144f1.tar.gz
gcc-2d0c270fd266218ff040965bb8231729df9144f1.tar.bz2
cse.c (find_comparison_args): Use val_mode_signbit_set_p.
* 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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog18
-rw-r--r--gcc/combine.c52
-rw-r--r--gcc/cse.c16
-rw-r--r--gcc/expmed.c25
-rw-r--r--gcc/expr.c7
-rw-r--r--gcc/rtl.h5
-rw-r--r--gcc/rtlanal.c40
-rw-r--r--gcc/simplify-rtx.c118
8 files changed, 147 insertions, 134 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 57c5390..e06f369 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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
diff --git a/gcc/combine.c b/gcc/combine.c
index 737f300..7ac4613 100644
--- a/gcc/combine.c
+++ b/gcc/combine.c
@@ -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;
diff --git a/gcc/cse.c b/gcc/cse.c
index 8a31cd1..9dc27c3 100644
--- 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)
diff --git a/gcc/expmed.c b/gcc/expmed.c
index 314fac7..e9b6016 100644
--- a/gcc/expmed.c
+++ b/gcc/expmed.c
@@ -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;
diff --git a/gcc/expr.c b/gcc/expr.c
index 176978a..e225d24 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -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);
}
diff --git a/gcc/rtl.h b/gcc/rtl.h
index da18788..2f2aaca 100644
--- 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,
diff --git a/gcc/rtlanal.c b/gcc/rtlanal.c
index 0be6504..9ac347e 100644
--- a/gcc/rtlanal.c
+++ b/gcc/rtlanal.c
@@ -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)
diff --git a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c
index f7669b1..6a5ec1a 100644
--- a/gcc/simplify-rtx.c
+++ b/gcc/simplify-rtx.c
@@ -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;
+}
/* 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);