Commit 7c61657f by Richard Sandiford Committed by Richard Sandiford

[25/77] Use is_a <scalar_int_mode> for bitmask optimisations

Explicitly check for scalar_int_mode in code that maps arithmetic
to full-mode bit operations.  These operations wouldn't work correctly
for vector modes, for example.  In many cases this is enforced also by
checking whether an operand is CONST_INT_P, but there were other cases
where the condition is more indirect.

2017-08-30  Richard Sandiford  <richard.sandiford@linaro.org>
	    Alan Hayward  <alan.hayward@arm.com>
	    David Sherwood  <david.sherwood@arm.com>

gcc/
	* combine.c (combine_simplify_rtx): Add checks for
	is_a <scalar_int_mode>.
	(simplify_if_then_else): Likewise.
	(make_field_assignment): Likewise.
	(simplify_comparison): Likewise.
	* ifcvt.c (noce_try_bitop): Likewise.
	* loop-invariant.c (canonicalize_address_mult): Likewise.
	* simplify-rtx.c (simplify_unary_operation_1): Likewise.

Co-Authored-By: Alan Hayward <alan.hayward@arm.com>
Co-Authored-By: David Sherwood <david.sherwood@arm.com>

From-SVN: r251477
parent 64ab8765
...@@ -2,6 +2,19 @@ ...@@ -2,6 +2,19 @@
Alan Hayward <alan.hayward@arm.com> Alan Hayward <alan.hayward@arm.com>
David Sherwood <david.sherwood@arm.com> David Sherwood <david.sherwood@arm.com>
* combine.c (combine_simplify_rtx): Add checks for
is_a <scalar_int_mode>.
(simplify_if_then_else): Likewise.
(make_field_assignment): Likewise.
(simplify_comparison): Likewise.
* ifcvt.c (noce_try_bitop): Likewise.
* loop-invariant.c (canonicalize_address_mult): Likewise.
* simplify-rtx.c (simplify_unary_operation_1): Likewise.
2017-08-30 Richard Sandiford <richard.sandiford@linaro.org>
Alan Hayward <alan.hayward@arm.com>
David Sherwood <david.sherwood@arm.com>
* simplify-rtx.c (simplify_binary_operation_1): Use * simplify-rtx.c (simplify_binary_operation_1): Use
is_a <scalar_int_mode> instead of !VECTOR_MODE_P. is_a <scalar_int_mode> instead of !VECTOR_MODE_P.
......
...@@ -5850,13 +5850,14 @@ combine_simplify_rtx (rtx x, machine_mode op0_mode, int in_dest, ...@@ -5850,13 +5850,14 @@ combine_simplify_rtx (rtx x, machine_mode op0_mode, int in_dest,
if (!REG_P (temp) if (!REG_P (temp)
&& ! (GET_CODE (temp) == SUBREG && ! (GET_CODE (temp) == SUBREG
&& REG_P (SUBREG_REG (temp))) && REG_P (SUBREG_REG (temp)))
&& (i = exact_log2 (nonzero_bits (temp, mode))) >= 0) && is_a <scalar_int_mode> (mode, &int_mode)
&& (i = exact_log2 (nonzero_bits (temp, int_mode))) >= 0)
{ {
rtx temp1 = simplify_shift_const rtx temp1 = simplify_shift_const
(NULL_RTX, ASHIFTRT, mode, (NULL_RTX, ASHIFTRT, int_mode,
simplify_shift_const (NULL_RTX, ASHIFT, mode, temp, simplify_shift_const (NULL_RTX, ASHIFT, int_mode, temp,
GET_MODE_PRECISION (mode) - 1 - i), GET_MODE_PRECISION (int_mode) - 1 - i),
GET_MODE_PRECISION (mode) - 1 - i); GET_MODE_PRECISION (int_mode) - 1 - i);
/* If all we did was surround TEMP with the two shifts, we /* If all we did was surround TEMP with the two shifts, we
haven't improved anything, so don't use it. Otherwise, haven't improved anything, so don't use it. Otherwise,
...@@ -5947,12 +5948,15 @@ combine_simplify_rtx (rtx x, machine_mode op0_mode, int in_dest, ...@@ -5947,12 +5948,15 @@ combine_simplify_rtx (rtx x, machine_mode op0_mode, int in_dest,
&& !REG_P (XEXP (x, 0)) && !REG_P (XEXP (x, 0))
&& ! (GET_CODE (XEXP (x, 0)) == SUBREG && ! (GET_CODE (XEXP (x, 0)) == SUBREG
&& REG_P (SUBREG_REG (XEXP (x, 0)))) && REG_P (SUBREG_REG (XEXP (x, 0))))
&& nonzero_bits (XEXP (x, 0), mode) == 1) && is_a <scalar_int_mode> (mode, &int_mode)
return simplify_shift_const (NULL_RTX, ASHIFTRT, mode, && nonzero_bits (XEXP (x, 0), int_mode) == 1)
simplify_shift_const (NULL_RTX, ASHIFT, mode, return simplify_shift_const
gen_rtx_XOR (mode, XEXP (x, 0), const1_rtx), (NULL_RTX, ASHIFTRT, int_mode,
GET_MODE_PRECISION (mode) - 1), simplify_shift_const (NULL_RTX, ASHIFT, int_mode,
GET_MODE_PRECISION (mode) - 1); gen_rtx_XOR (int_mode, XEXP (x, 0),
const1_rtx),
GET_MODE_PRECISION (int_mode) - 1),
GET_MODE_PRECISION (int_mode) - 1);
/* If we are adding two things that have no bits in common, convert /* If we are adding two things that have no bits in common, convert
the addition into an IOR. This will often be further simplified, the addition into an IOR. This will often be further simplified,
...@@ -5990,11 +5994,12 @@ combine_simplify_rtx (rtx x, machine_mode op0_mode, int in_dest, ...@@ -5990,11 +5994,12 @@ combine_simplify_rtx (rtx x, machine_mode op0_mode, int in_dest,
case MINUS: case MINUS:
/* (minus <foo> (and <foo> (const_int -pow2))) becomes /* (minus <foo> (and <foo> (const_int -pow2))) becomes
(and <foo> (const_int pow2-1)) */ (and <foo> (const_int pow2-1)) */
if (GET_CODE (XEXP (x, 1)) == AND if (is_a <scalar_int_mode> (mode, &int_mode)
&& GET_CODE (XEXP (x, 1)) == AND
&& CONST_INT_P (XEXP (XEXP (x, 1), 1)) && CONST_INT_P (XEXP (XEXP (x, 1), 1))
&& pow2p_hwi (-UINTVAL (XEXP (XEXP (x, 1), 1))) && pow2p_hwi (-UINTVAL (XEXP (XEXP (x, 1), 1)))
&& rtx_equal_p (XEXP (XEXP (x, 1), 0), XEXP (x, 0))) && rtx_equal_p (XEXP (XEXP (x, 1), 0), XEXP (x, 0)))
return simplify_and_const_int (NULL_RTX, mode, XEXP (x, 0), return simplify_and_const_int (NULL_RTX, int_mode, XEXP (x, 0),
-INTVAL (XEXP (XEXP (x, 1), 1)) - 1); -INTVAL (XEXP (XEXP (x, 1), 1)) - 1);
break; break;
...@@ -6025,14 +6030,16 @@ combine_simplify_rtx (rtx x, machine_mode op0_mode, int in_dest, ...@@ -6025,14 +6030,16 @@ combine_simplify_rtx (rtx x, machine_mode op0_mode, int in_dest,
case UDIV: case UDIV:
/* If this is a divide by a power of two, treat it as a shift if /* If this is a divide by a power of two, treat it as a shift if
its first operand is a shift. */ its first operand is a shift. */
if (CONST_INT_P (XEXP (x, 1)) if (is_a <scalar_int_mode> (mode, &int_mode)
&& CONST_INT_P (XEXP (x, 1))
&& (i = exact_log2 (UINTVAL (XEXP (x, 1)))) >= 0 && (i = exact_log2 (UINTVAL (XEXP (x, 1)))) >= 0
&& (GET_CODE (XEXP (x, 0)) == ASHIFT && (GET_CODE (XEXP (x, 0)) == ASHIFT
|| GET_CODE (XEXP (x, 0)) == LSHIFTRT || GET_CODE (XEXP (x, 0)) == LSHIFTRT
|| GET_CODE (XEXP (x, 0)) == ASHIFTRT || GET_CODE (XEXP (x, 0)) == ASHIFTRT
|| GET_CODE (XEXP (x, 0)) == ROTATE || GET_CODE (XEXP (x, 0)) == ROTATE
|| GET_CODE (XEXP (x, 0)) == ROTATERT)) || GET_CODE (XEXP (x, 0)) == ROTATERT))
return simplify_shift_const (NULL_RTX, LSHIFTRT, mode, XEXP (x, 0), i); return simplify_shift_const (NULL_RTX, LSHIFTRT, int_mode,
XEXP (x, 0), i);
break; break;
case EQ: case NE: case EQ: case NE:
...@@ -6316,23 +6323,29 @@ simplify_if_then_else (rtx x) ...@@ -6316,23 +6323,29 @@ simplify_if_then_else (rtx x)
std::swap (true_rtx, false_rtx); std::swap (true_rtx, false_rtx);
} }
/* If we are comparing against zero and the expression being tested has scalar_int_mode from_mode;
only a single bit that might be nonzero, that is its value when it is if (is_a <scalar_int_mode> (GET_MODE (from), &from_mode))
not equal to zero. Similarly if it is known to be -1 or 0. */ {
/* If we are comparing against zero and the expression being
if (true_code == EQ && true_val == const0_rtx tested has only a single bit that might be nonzero, that is
&& pow2p_hwi (nzb = nonzero_bits (from, GET_MODE (from)))) its value when it is not equal to zero. Similarly if it is
known to be -1 or 0. */
if (true_code == EQ
&& true_val == const0_rtx
&& pow2p_hwi (nzb = nonzero_bits (from, from_mode)))
{ {
false_code = EQ; false_code = EQ;
false_val = gen_int_mode (nzb, GET_MODE (from)); false_val = gen_int_mode (nzb, from_mode);
} }
else if (true_code == EQ && true_val == const0_rtx else if (true_code == EQ
&& (num_sign_bit_copies (from, GET_MODE (from)) && true_val == const0_rtx
== GET_MODE_PRECISION (GET_MODE (from)))) && (num_sign_bit_copies (from, from_mode)
== GET_MODE_PRECISION (from_mode)))
{ {
false_code = EQ; false_code = EQ;
false_val = constm1_rtx; false_val = constm1_rtx;
} }
}
/* Now simplify an arm if we know the value of the register in the /* Now simplify an arm if we know the value of the register in the
branch and it is used in the arm. Be careful due to the potential branch and it is used in the arm. Be careful due to the potential
...@@ -6581,16 +6594,19 @@ simplify_if_then_else (rtx x) ...@@ -6581,16 +6594,19 @@ simplify_if_then_else (rtx x)
negation of a single bit, we can convert this operation to a shift. We negation of a single bit, we can convert this operation to a shift. We
can actually do this more generally, but it doesn't seem worth it. */ can actually do this more generally, but it doesn't seem worth it. */
if (true_code == NE && XEXP (cond, 1) == const0_rtx if (true_code == NE
&& false_rtx == const0_rtx && CONST_INT_P (true_rtx) && is_a <scalar_int_mode> (mode, &int_mode)
&& ((1 == nonzero_bits (XEXP (cond, 0), mode) && XEXP (cond, 1) == const0_rtx
&& false_rtx == const0_rtx
&& CONST_INT_P (true_rtx)
&& ((1 == nonzero_bits (XEXP (cond, 0), int_mode)
&& (i = exact_log2 (UINTVAL (true_rtx))) >= 0) && (i = exact_log2 (UINTVAL (true_rtx))) >= 0)
|| ((num_sign_bit_copies (XEXP (cond, 0), mode) || ((num_sign_bit_copies (XEXP (cond, 0), int_mode)
== GET_MODE_PRECISION (mode)) == GET_MODE_PRECISION (int_mode))
&& (i = exact_log2 (-UINTVAL (true_rtx))) >= 0))) && (i = exact_log2 (-UINTVAL (true_rtx))) >= 0)))
return return
simplify_shift_const (NULL_RTX, ASHIFT, mode, simplify_shift_const (NULL_RTX, ASHIFT, int_mode,
gen_lowpart (mode, XEXP (cond, 0)), i); gen_lowpart (int_mode, XEXP (cond, 0)), i);
/* (IF_THEN_ELSE (NE A 0) C1 0) is A or a zero-extend of A if the only /* (IF_THEN_ELSE (NE A 0) C1 0) is A or a zero-extend of A if the only
non-zero bit in A is C1. */ non-zero bit in A is C1. */
...@@ -9461,7 +9477,11 @@ make_field_assignment (rtx x) ...@@ -9461,7 +9477,11 @@ make_field_assignment (rtx x)
HOST_WIDE_INT pos; HOST_WIDE_INT pos;
unsigned HOST_WIDE_INT len; unsigned HOST_WIDE_INT len;
rtx other; rtx other;
machine_mode mode;
/* All the rules in this function are specific to scalar integers. */
scalar_int_mode mode;
if (!is_a <scalar_int_mode> (GET_MODE (dest), &mode))
return x;
/* If SRC was (and (not (ashift (const_int 1) POS)) DEST), this is /* If SRC was (and (not (ashift (const_int 1) POS)) DEST), this is
a clear of a one-bit field. We will have changed it to a clear of a one-bit field. We will have changed it to
...@@ -9534,7 +9554,6 @@ make_field_assignment (rtx x) ...@@ -9534,7 +9554,6 @@ make_field_assignment (rtx x)
/* Partial overlap. We can reduce the source AND. */ /* Partial overlap. We can reduce the source AND. */
if ((and_mask & ze_mask) != and_mask) if ((and_mask & ze_mask) != and_mask)
{ {
mode = GET_MODE (src);
src = gen_rtx_AND (mode, XEXP (src, 0), src = gen_rtx_AND (mode, XEXP (src, 0),
gen_int_mode (and_mask & ze_mask, mode)); gen_int_mode (and_mask & ze_mask, mode));
return gen_rtx_SET (dest, src); return gen_rtx_SET (dest, src);
...@@ -9553,7 +9572,10 @@ make_field_assignment (rtx x) ...@@ -9553,7 +9572,10 @@ make_field_assignment (rtx x)
assignment. The first one we are likely to encounter is an outer assignment. The first one we are likely to encounter is an outer
narrowing SUBREG, which we can just strip for the purposes of narrowing SUBREG, which we can just strip for the purposes of
identifying the constant-field assignment. */ identifying the constant-field assignment. */
if (GET_CODE (src) == SUBREG && subreg_lowpart_p (src)) scalar_int_mode src_mode = mode;
if (GET_CODE (src) == SUBREG
&& subreg_lowpart_p (src)
&& is_a <scalar_int_mode> (GET_MODE (SUBREG_REG (src)), &src_mode))
src = SUBREG_REG (src); src = SUBREG_REG (src);
if (GET_CODE (src) != IOR && GET_CODE (src) != XOR) if (GET_CODE (src) != IOR && GET_CODE (src) != XOR)
...@@ -9599,10 +9621,11 @@ make_field_assignment (rtx x) ...@@ -9599,10 +9621,11 @@ make_field_assignment (rtx x)
else else
return x; return x;
pos = get_pos_from_mask ((~c1) & GET_MODE_MASK (GET_MODE (dest)), &len); pos = get_pos_from_mask ((~c1) & GET_MODE_MASK (mode), &len);
if (pos < 0 || pos + len > GET_MODE_PRECISION (GET_MODE (dest)) if (pos < 0
|| GET_MODE_PRECISION (GET_MODE (dest)) > HOST_BITS_PER_WIDE_INT || pos + len > GET_MODE_PRECISION (mode)
|| (c1 & nonzero_bits (other, GET_MODE (dest))) != 0) || GET_MODE_PRECISION (mode) > HOST_BITS_PER_WIDE_INT
|| (c1 & nonzero_bits (other, mode)) != 0)
return x; return x;
assign = make_extraction (VOIDmode, dest, pos, NULL_RTX, len, 1, 1, 0); assign = make_extraction (VOIDmode, dest, pos, NULL_RTX, len, 1, 1, 0);
...@@ -9611,17 +9634,16 @@ make_field_assignment (rtx x) ...@@ -9611,17 +9634,16 @@ make_field_assignment (rtx x)
/* The mode to use for the source is the mode of the assignment, or of /* The mode to use for the source is the mode of the assignment, or of
what is inside a possible STRICT_LOW_PART. */ what is inside a possible STRICT_LOW_PART. */
mode = (GET_CODE (assign) == STRICT_LOW_PART machine_mode new_mode = (GET_CODE (assign) == STRICT_LOW_PART
? GET_MODE (XEXP (assign, 0)) : GET_MODE (assign)); ? GET_MODE (XEXP (assign, 0)) : GET_MODE (assign));
/* Shift OTHER right POS places and make it the source, restricting it /* Shift OTHER right POS places and make it the source, restricting it
to the proper length and mode. */ to the proper length and mode. */
src = canon_reg_for_combine (simplify_shift_const (NULL_RTX, LSHIFTRT, src = canon_reg_for_combine (simplify_shift_const (NULL_RTX, LSHIFTRT,
GET_MODE (src), src_mode, other, pos),
other, pos),
dest); dest);
src = force_to_mode (src, mode, src = force_to_mode (src, new_mode,
len >= HOST_BITS_PER_WIDE_INT len >= HOST_BITS_PER_WIDE_INT
? HOST_WIDE_INT_M1U ? HOST_WIDE_INT_M1U
: (HOST_WIDE_INT_1U << len) - 1, : (HOST_WIDE_INT_1U << len) - 1,
...@@ -11745,16 +11767,17 @@ simplify_comparison (enum rtx_code code, rtx *pop0, rtx *pop1) ...@@ -11745,16 +11767,17 @@ simplify_comparison (enum rtx_code code, rtx *pop0, rtx *pop1)
&& GET_CODE (XEXP (op1, 0)) == ASHIFT && GET_CODE (XEXP (op1, 0)) == ASHIFT
&& GET_CODE (XEXP (XEXP (op0, 0), 0)) == SUBREG && GET_CODE (XEXP (XEXP (op0, 0), 0)) == SUBREG
&& GET_CODE (XEXP (XEXP (op1, 0), 0)) == SUBREG && GET_CODE (XEXP (XEXP (op1, 0), 0)) == SUBREG
&& (GET_MODE (SUBREG_REG (XEXP (XEXP (op0, 0), 0))) && is_a <scalar_int_mode> (GET_MODE (op0), &mode)
== GET_MODE (SUBREG_REG (XEXP (XEXP (op1, 0), 0)))) && (is_a <scalar_int_mode>
(GET_MODE (SUBREG_REG (XEXP (XEXP (op0, 0), 0))), &inner_mode))
&& inner_mode == GET_MODE (SUBREG_REG (XEXP (XEXP (op1, 0), 0)))
&& CONST_INT_P (XEXP (op0, 1)) && CONST_INT_P (XEXP (op0, 1))
&& XEXP (op0, 1) == XEXP (op1, 1) && XEXP (op0, 1) == XEXP (op1, 1)
&& XEXP (op0, 1) == XEXP (XEXP (op0, 0), 1) && XEXP (op0, 1) == XEXP (XEXP (op0, 0), 1)
&& XEXP (op0, 1) == XEXP (XEXP (op1, 0), 1) && XEXP (op0, 1) == XEXP (XEXP (op1, 0), 1)
&& (INTVAL (XEXP (op0, 1)) && (INTVAL (XEXP (op0, 1))
== (GET_MODE_PRECISION (GET_MODE (op0)) == (GET_MODE_PRECISION (mode)
- (GET_MODE_PRECISION - GET_MODE_PRECISION (inner_mode))))
(GET_MODE (SUBREG_REG (XEXP (XEXP (op0, 0), 0))))))))
{ {
op0 = SUBREG_REG (XEXP (XEXP (op0, 0), 0)); op0 = SUBREG_REG (XEXP (XEXP (op0, 0), 0));
op1 = SUBREG_REG (XEXP (XEXP (op1, 0), 0)); op1 = SUBREG_REG (XEXP (XEXP (op1, 0), 0));
......
...@@ -2808,7 +2808,7 @@ noce_try_bitop (struct noce_if_info *if_info) ...@@ -2808,7 +2808,7 @@ noce_try_bitop (struct noce_if_info *if_info)
{ {
rtx cond, x, a, result; rtx cond, x, a, result;
rtx_insn *seq; rtx_insn *seq;
machine_mode mode; scalar_int_mode mode;
enum rtx_code code; enum rtx_code code;
int bitnum; int bitnum;
...@@ -2816,6 +2816,10 @@ noce_try_bitop (struct noce_if_info *if_info) ...@@ -2816,6 +2816,10 @@ noce_try_bitop (struct noce_if_info *if_info)
cond = if_info->cond; cond = if_info->cond;
code = GET_CODE (cond); code = GET_CODE (cond);
/* Check for an integer operation. */
if (!is_a <scalar_int_mode> (GET_MODE (x), &mode))
return FALSE;
if (!noce_simple_bbs (if_info)) if (!noce_simple_bbs (if_info))
return FALSE; return FALSE;
...@@ -2838,7 +2842,6 @@ noce_try_bitop (struct noce_if_info *if_info) ...@@ -2838,7 +2842,6 @@ noce_try_bitop (struct noce_if_info *if_info)
|| ! rtx_equal_p (x, XEXP (cond, 0))) || ! rtx_equal_p (x, XEXP (cond, 0)))
return FALSE; return FALSE;
bitnum = INTVAL (XEXP (cond, 2)); bitnum = INTVAL (XEXP (cond, 2));
mode = GET_MODE (x);
if (BITS_BIG_ENDIAN) if (BITS_BIG_ENDIAN)
bitnum = GET_MODE_BITSIZE (mode) - 1 - bitnum; bitnum = GET_MODE_BITSIZE (mode) - 1 - bitnum;
if (bitnum < 0 || bitnum >= HOST_BITS_PER_WIDE_INT) if (bitnum < 0 || bitnum >= HOST_BITS_PER_WIDE_INT)
......
...@@ -774,16 +774,16 @@ canonicalize_address_mult (rtx x) ...@@ -774,16 +774,16 @@ canonicalize_address_mult (rtx x)
FOR_EACH_SUBRTX_VAR (iter, array, x, NONCONST) FOR_EACH_SUBRTX_VAR (iter, array, x, NONCONST)
{ {
rtx sub = *iter; rtx sub = *iter;
scalar_int_mode sub_mode;
if (GET_CODE (sub) == ASHIFT if (is_a <scalar_int_mode> (GET_MODE (sub), &sub_mode)
&& GET_CODE (sub) == ASHIFT
&& CONST_INT_P (XEXP (sub, 1)) && CONST_INT_P (XEXP (sub, 1))
&& INTVAL (XEXP (sub, 1)) < GET_MODE_BITSIZE (GET_MODE (sub)) && INTVAL (XEXP (sub, 1)) < GET_MODE_BITSIZE (sub_mode)
&& INTVAL (XEXP (sub, 1)) >= 0) && INTVAL (XEXP (sub, 1)) >= 0)
{ {
HOST_WIDE_INT shift = INTVAL (XEXP (sub, 1)); HOST_WIDE_INT shift = INTVAL (XEXP (sub, 1));
PUT_CODE (sub, MULT); PUT_CODE (sub, MULT);
XEXP (sub, 1) = gen_int_mode (HOST_WIDE_INT_1 << shift, XEXP (sub, 1) = gen_int_mode (HOST_WIDE_INT_1 << shift, sub_mode);
GET_MODE (sub));
iter.skip_subrtxes (); iter.skip_subrtxes ();
} }
} }
......
...@@ -925,7 +925,7 @@ simplify_unary_operation_1 (enum rtx_code code, machine_mode mode, rtx op) ...@@ -925,7 +925,7 @@ simplify_unary_operation_1 (enum rtx_code code, machine_mode mode, rtx op)
{ {
enum rtx_code reversed; enum rtx_code reversed;
rtx temp; rtx temp;
scalar_int_mode inner; scalar_int_mode inner, int_mode;
switch (code) switch (code)
{ {
...@@ -986,10 +986,11 @@ simplify_unary_operation_1 (enum rtx_code code, machine_mode mode, rtx op) ...@@ -986,10 +986,11 @@ simplify_unary_operation_1 (enum rtx_code code, machine_mode mode, rtx op)
minus 1 is (ge foo (const_int 0)) if STORE_FLAG_VALUE is -1, minus 1 is (ge foo (const_int 0)) if STORE_FLAG_VALUE is -1,
so we can perform the above simplification. */ so we can perform the above simplification. */
if (STORE_FLAG_VALUE == -1 if (STORE_FLAG_VALUE == -1
&& is_a <scalar_int_mode> (mode, &int_mode)
&& GET_CODE (op) == ASHIFTRT && GET_CODE (op) == ASHIFTRT
&& CONST_INT_P (XEXP (op, 1)) && CONST_INT_P (XEXP (op, 1))
&& INTVAL (XEXP (op, 1)) == GET_MODE_PRECISION (mode) - 1) && INTVAL (XEXP (op, 1)) == GET_MODE_PRECISION (int_mode) - 1)
return simplify_gen_relational (GE, mode, VOIDmode, return simplify_gen_relational (GE, int_mode, VOIDmode,
XEXP (op, 0), const0_rtx); XEXP (op, 0), const0_rtx);
...@@ -1339,8 +1340,10 @@ simplify_unary_operation_1 (enum rtx_code code, machine_mode mode, rtx op) ...@@ -1339,8 +1340,10 @@ simplify_unary_operation_1 (enum rtx_code code, machine_mode mode, rtx op)
return op; return op;
/* If operand is known to be only -1 or 0, convert ABS to NEG. */ /* If operand is known to be only -1 or 0, convert ABS to NEG. */
if (num_sign_bit_copies (op, mode) == GET_MODE_PRECISION (mode)) if (is_a <scalar_int_mode> (mode, &int_mode)
return gen_rtx_NEG (mode, op); && (num_sign_bit_copies (op, int_mode)
== GET_MODE_PRECISION (int_mode)))
return gen_rtx_NEG (int_mode, op);
break; break;
...@@ -1494,12 +1497,13 @@ simplify_unary_operation_1 (enum rtx_code code, machine_mode mode, rtx op) ...@@ -1494,12 +1497,13 @@ simplify_unary_operation_1 (enum rtx_code code, machine_mode mode, rtx op)
is similarly (zero_extend:M (subreg:O <X>)). */ is similarly (zero_extend:M (subreg:O <X>)). */
if ((GET_CODE (op) == ASHIFTRT || GET_CODE (op) == LSHIFTRT) if ((GET_CODE (op) == ASHIFTRT || GET_CODE (op) == LSHIFTRT)
&& GET_CODE (XEXP (op, 0)) == ASHIFT && GET_CODE (XEXP (op, 0)) == ASHIFT
&& is_a <scalar_int_mode> (mode, &int_mode)
&& CONST_INT_P (XEXP (op, 1)) && CONST_INT_P (XEXP (op, 1))
&& XEXP (XEXP (op, 0), 1) == XEXP (op, 1) && XEXP (XEXP (op, 0), 1) == XEXP (op, 1)
&& GET_MODE_BITSIZE (GET_MODE (op)) > INTVAL (XEXP (op, 1))) && GET_MODE_BITSIZE (GET_MODE (op)) > INTVAL (XEXP (op, 1)))
{ {
scalar_int_mode tmode; scalar_int_mode tmode;
gcc_assert (GET_MODE_BITSIZE (mode) gcc_assert (GET_MODE_BITSIZE (int_mode)
> GET_MODE_BITSIZE (GET_MODE (op))); > GET_MODE_BITSIZE (GET_MODE (op)));
if (int_mode_for_size (GET_MODE_BITSIZE (GET_MODE (op)) if (int_mode_for_size (GET_MODE_BITSIZE (GET_MODE (op))
- INTVAL (XEXP (op, 1)), 1).exists (&tmode)) - INTVAL (XEXP (op, 1)), 1).exists (&tmode))
...@@ -1509,7 +1513,7 @@ simplify_unary_operation_1 (enum rtx_code code, machine_mode mode, rtx op) ...@@ -1509,7 +1513,7 @@ simplify_unary_operation_1 (enum rtx_code code, machine_mode mode, rtx op)
if (inner) if (inner)
return simplify_gen_unary (GET_CODE (op) == ASHIFTRT return simplify_gen_unary (GET_CODE (op) == ASHIFTRT
? SIGN_EXTEND : ZERO_EXTEND, ? SIGN_EXTEND : ZERO_EXTEND,
mode, inner, tmode); int_mode, inner, tmode);
} }
} }
...@@ -1610,6 +1614,7 @@ simplify_unary_operation_1 (enum rtx_code code, machine_mode mode, rtx op) ...@@ -1610,6 +1614,7 @@ simplify_unary_operation_1 (enum rtx_code code, machine_mode mode, rtx op)
GET_MODE_PRECISION (N) - I bits. */ GET_MODE_PRECISION (N) - I bits. */
if (GET_CODE (op) == LSHIFTRT if (GET_CODE (op) == LSHIFTRT
&& GET_CODE (XEXP (op, 0)) == ASHIFT && GET_CODE (XEXP (op, 0)) == ASHIFT
&& is_a <scalar_int_mode> (mode, &int_mode)
&& CONST_INT_P (XEXP (op, 1)) && CONST_INT_P (XEXP (op, 1))
&& XEXP (XEXP (op, 0), 1) == XEXP (op, 1) && XEXP (XEXP (op, 0), 1) == XEXP (op, 1)
&& GET_MODE_PRECISION (GET_MODE (op)) > INTVAL (XEXP (op, 1))) && GET_MODE_PRECISION (GET_MODE (op)) > INTVAL (XEXP (op, 1)))
...@@ -1621,7 +1626,8 @@ simplify_unary_operation_1 (enum rtx_code code, machine_mode mode, rtx op) ...@@ -1621,7 +1626,8 @@ simplify_unary_operation_1 (enum rtx_code code, machine_mode mode, rtx op)
rtx inner = rtx inner =
rtl_hooks.gen_lowpart_no_emit (tmode, XEXP (XEXP (op, 0), 0)); rtl_hooks.gen_lowpart_no_emit (tmode, XEXP (XEXP (op, 0), 0));
if (inner) if (inner)
return simplify_gen_unary (ZERO_EXTEND, mode, inner, tmode); return simplify_gen_unary (ZERO_EXTEND, int_mode,
inner, tmode);
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment