From 2d0c270fd266218ff040965bb8231729df9144f1 Mon Sep 17 00:00:00 2001 From: Bernd Schmidt Date: Wed, 6 Jul 2011 14:21:03 +0000 Subject: [PATCH] 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 --- gcc/ChangeLog | 18 +++++++ gcc/combine.c | 52 ++++++-------------- gcc/cse.c | 16 ++---- gcc/expmed.c | 25 +++------- gcc/expr.c | 7 ++- gcc/rtl.h | 5 ++ gcc/rtlanal.c | 40 ++++++--------- gcc/simplify-rtx.c | 118 ++++++++++++++++++++++++++++++--------------- 8 files changed, 147 insertions(+), 134 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 57c5390edeb..e06f36996e9 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,21 @@ +2011-07-06 Bernd Schmidt + + * 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 PR tree-optimization/49645 diff --git a/gcc/combine.c b/gcc/combine.c index 737f300b063..7ac4613955c 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 8a31cd1a3da..9dc27c383e8 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 314fac79c28..e9b6016cf8b 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 176978a2257..e225d245a04 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 da18788a292..2f2aaca7b42 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 0be6504a943..9ac347ed0fa 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 f7669b1ebc9..6a5ec1a1bfa 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); -- 2.30.2