Commit e3731c52 by Richard Sandiford Committed by Richard Sandiford

[42/77] Use scalar_int_mode in simplify_shift_const_1

This patch makes simplify_shift_const_1 use scalar_int_modes
for all code that is specific to scalars rather than vectors.
This includes situations in which the new shift mode is different
from the original one, since the function never changes the mode
of vector shifts.  That in turn makes it more natural to test for
equal modes in simplify_shift_const_1 rather than try_widen_shift_mode
(which only applies to scalars).

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

gcc/
	* combine.c (try_widen_shift_mode): Move check for equal modes to...
	(simplify_shift_const_1): ...here.  Use scalar_int_mode for
	shift_unit_mode and for modes involved in scalar shifts.

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

From-SVN: r251494
parent 0b73246f
...@@ -2,6 +2,14 @@ ...@@ -2,6 +2,14 @@
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 (try_widen_shift_mode): Move check for equal modes to...
(simplify_shift_const_1): ...here. Use scalar_int_mode for
shift_unit_mode and for modes involved in scalar shifts.
2017-08-30 Richard Sandiford <richard.sandiford@linaro.org>
Alan Hayward <alan.hayward@arm.com>
David Sherwood <david.sherwood@arm.com>
* combine.c (force_int_to_mode): New function, split out from... * combine.c (force_int_to_mode): New function, split out from...
(force_to_mode): ...here. Keep xmode up-to-date and use it (force_to_mode): ...here. Keep xmode up-to-date and use it
instead of GET_MODE (x). instead of GET_MODE (x).
......
...@@ -10321,8 +10321,6 @@ try_widen_shift_mode (enum rtx_code code, rtx op, int count, ...@@ -10321,8 +10321,6 @@ try_widen_shift_mode (enum rtx_code code, rtx op, int count,
machine_mode orig_mode, machine_mode mode, machine_mode orig_mode, machine_mode mode,
enum rtx_code outer_code, HOST_WIDE_INT outer_const) enum rtx_code outer_code, HOST_WIDE_INT outer_const)
{ {
if (orig_mode == mode)
return mode;
gcc_assert (GET_MODE_PRECISION (mode) > GET_MODE_PRECISION (orig_mode)); gcc_assert (GET_MODE_PRECISION (mode) > GET_MODE_PRECISION (orig_mode));
/* In general we can't perform in wider mode for right shift and rotate. */ /* In general we can't perform in wider mode for right shift and rotate. */
...@@ -10383,7 +10381,7 @@ simplify_shift_const_1 (enum rtx_code code, machine_mode result_mode, ...@@ -10383,7 +10381,7 @@ simplify_shift_const_1 (enum rtx_code code, machine_mode result_mode,
int count; int count;
machine_mode mode = result_mode; machine_mode mode = result_mode;
machine_mode shift_mode; machine_mode shift_mode;
scalar_int_mode tmode, inner_mode; scalar_int_mode tmode, inner_mode, int_mode, int_varop_mode, int_result_mode;
unsigned int mode_words unsigned int mode_words
= (GET_MODE_SIZE (mode) + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD; = (GET_MODE_SIZE (mode) + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD;
/* We form (outer_op (code varop count) (outer_const)). */ /* We form (outer_op (code varop count) (outer_const)). */
...@@ -10423,9 +10421,19 @@ simplify_shift_const_1 (enum rtx_code code, machine_mode result_mode, ...@@ -10423,9 +10421,19 @@ simplify_shift_const_1 (enum rtx_code code, machine_mode result_mode,
count = bitsize - count; count = bitsize - count;
} }
shift_mode = try_widen_shift_mode (code, varop, count, result_mode, shift_mode = result_mode;
mode, outer_op, outer_const); if (shift_mode != mode)
machine_mode shift_unit_mode = GET_MODE_INNER (shift_mode); {
/* We only change the modes of scalar shifts. */
int_mode = as_a <scalar_int_mode> (mode);
int_result_mode = as_a <scalar_int_mode> (result_mode);
shift_mode = try_widen_shift_mode (code, varop, count,
int_result_mode, int_mode,
outer_op, outer_const);
}
scalar_int_mode shift_unit_mode
= as_a <scalar_int_mode> (GET_MODE_INNER (shift_mode));
/* Handle cases where the count is greater than the size of the mode /* Handle cases where the count is greater than the size of the mode
minus 1. For ASHIFT, use the size minus one as the count (this can minus 1. For ASHIFT, use the size minus one as the count (this can
...@@ -10520,6 +10528,7 @@ simplify_shift_const_1 (enum rtx_code code, machine_mode result_mode, ...@@ -10520,6 +10528,7 @@ simplify_shift_const_1 (enum rtx_code code, machine_mode result_mode,
/* The following rules apply only to scalars. */ /* The following rules apply only to scalars. */
if (shift_mode != shift_unit_mode) if (shift_mode != shift_unit_mode)
break; break;
int_mode = as_a <scalar_int_mode> (mode);
/* If we have (xshiftrt (mem ...) C) and C is MODE_WIDTH /* If we have (xshiftrt (mem ...) C) and C is MODE_WIDTH
minus the width of a smaller mode, we can do this with a minus the width of a smaller mode, we can do this with a
...@@ -10528,7 +10537,7 @@ simplify_shift_const_1 (enum rtx_code code, machine_mode result_mode, ...@@ -10528,7 +10537,7 @@ simplify_shift_const_1 (enum rtx_code code, machine_mode result_mode,
&& ! mode_dependent_address_p (XEXP (varop, 0), && ! mode_dependent_address_p (XEXP (varop, 0),
MEM_ADDR_SPACE (varop)) MEM_ADDR_SPACE (varop))
&& ! MEM_VOLATILE_P (varop) && ! MEM_VOLATILE_P (varop)
&& (int_mode_for_size (GET_MODE_BITSIZE (mode) - count, 1) && (int_mode_for_size (GET_MODE_BITSIZE (int_mode) - count, 1)
.exists (&tmode))) .exists (&tmode)))
{ {
new_rtx = adjust_address_nv (varop, tmode, new_rtx = adjust_address_nv (varop, tmode,
...@@ -10536,7 +10545,7 @@ simplify_shift_const_1 (enum rtx_code code, machine_mode result_mode, ...@@ -10536,7 +10545,7 @@ simplify_shift_const_1 (enum rtx_code code, machine_mode result_mode,
: count / BITS_PER_UNIT); : count / BITS_PER_UNIT);
varop = gen_rtx_fmt_e (code == ASHIFTRT ? SIGN_EXTEND varop = gen_rtx_fmt_e (code == ASHIFTRT ? SIGN_EXTEND
: ZERO_EXTEND, mode, new_rtx); : ZERO_EXTEND, int_mode, new_rtx);
count = 0; count = 0;
continue; continue;
} }
...@@ -10546,20 +10555,22 @@ simplify_shift_const_1 (enum rtx_code code, machine_mode result_mode, ...@@ -10546,20 +10555,22 @@ simplify_shift_const_1 (enum rtx_code code, machine_mode result_mode,
/* The following rules apply only to scalars. */ /* The following rules apply only to scalars. */
if (shift_mode != shift_unit_mode) if (shift_mode != shift_unit_mode)
break; break;
int_mode = as_a <scalar_int_mode> (mode);
int_varop_mode = as_a <scalar_int_mode> (GET_MODE (varop));
/* If VAROP is a SUBREG, strip it as long as the inner operand has /* If VAROP is a SUBREG, strip it as long as the inner operand has
the same number of words as what we've seen so far. Then store the same number of words as what we've seen so far. Then store
the widest mode in MODE. */ the widest mode in MODE. */
if (subreg_lowpart_p (varop) if (subreg_lowpart_p (varop)
&& is_int_mode (GET_MODE (SUBREG_REG (varop)), &inner_mode) && is_int_mode (GET_MODE (SUBREG_REG (varop)), &inner_mode)
&& GET_MODE_SIZE (inner_mode) > GET_MODE_SIZE (GET_MODE (varop)) && GET_MODE_SIZE (inner_mode) > GET_MODE_SIZE (int_varop_mode)
&& (unsigned int) ((GET_MODE_SIZE (inner_mode) && (unsigned int) ((GET_MODE_SIZE (inner_mode)
+ (UNITS_PER_WORD - 1)) / UNITS_PER_WORD) + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD)
== mode_words == mode_words
&& GET_MODE_CLASS (GET_MODE (varop)) == MODE_INT) && GET_MODE_CLASS (int_varop_mode) == MODE_INT)
{ {
varop = SUBREG_REG (varop); varop = SUBREG_REG (varop);
if (GET_MODE_SIZE (inner_mode) > GET_MODE_SIZE (mode)) if (GET_MODE_SIZE (inner_mode) > GET_MODE_SIZE (int_mode))
mode = inner_mode; mode = inner_mode;
continue; continue;
} }
...@@ -10618,14 +10629,17 @@ simplify_shift_const_1 (enum rtx_code code, machine_mode result_mode, ...@@ -10618,14 +10629,17 @@ simplify_shift_const_1 (enum rtx_code code, machine_mode result_mode,
/* The following rules apply only to scalars. */ /* The following rules apply only to scalars. */
if (shift_mode != shift_unit_mode) if (shift_mode != shift_unit_mode)
break; break;
int_mode = as_a <scalar_int_mode> (mode);
int_varop_mode = as_a <scalar_int_mode> (GET_MODE (varop));
int_result_mode = as_a <scalar_int_mode> (result_mode);
/* Here we have two nested shifts. The result is usually the /* Here we have two nested shifts. The result is usually the
AND of a new shift with a mask. We compute the result below. */ AND of a new shift with a mask. We compute the result below. */
if (CONST_INT_P (XEXP (varop, 1)) if (CONST_INT_P (XEXP (varop, 1))
&& INTVAL (XEXP (varop, 1)) >= 0 && INTVAL (XEXP (varop, 1)) >= 0
&& INTVAL (XEXP (varop, 1)) < GET_MODE_PRECISION (GET_MODE (varop)) && INTVAL (XEXP (varop, 1)) < GET_MODE_PRECISION (int_varop_mode)
&& HWI_COMPUTABLE_MODE_P (result_mode) && HWI_COMPUTABLE_MODE_P (int_result_mode)
&& HWI_COMPUTABLE_MODE_P (mode)) && HWI_COMPUTABLE_MODE_P (int_mode))
{ {
enum rtx_code first_code = GET_CODE (varop); enum rtx_code first_code = GET_CODE (varop);
unsigned int first_count = INTVAL (XEXP (varop, 1)); unsigned int first_count = INTVAL (XEXP (varop, 1));
...@@ -10640,18 +10654,18 @@ simplify_shift_const_1 (enum rtx_code code, machine_mode result_mode, ...@@ -10640,18 +10654,18 @@ simplify_shift_const_1 (enum rtx_code code, machine_mode result_mode,
(ashiftrt:M1 (ashift:M1 (and:M1 (subreg:M1 FOO 0) C3) C2) C1). (ashiftrt:M1 (ashift:M1 (and:M1 (subreg:M1 FOO 0) C3) C2) C1).
This simplifies certain SIGN_EXTEND operations. */ This simplifies certain SIGN_EXTEND operations. */
if (code == ASHIFT && first_code == ASHIFTRT if (code == ASHIFT && first_code == ASHIFTRT
&& count == (GET_MODE_PRECISION (result_mode) && count == (GET_MODE_PRECISION (int_result_mode)
- GET_MODE_PRECISION (GET_MODE (varop)))) - GET_MODE_PRECISION (int_varop_mode)))
{ {
/* C3 has the low-order C1 bits zero. */ /* C3 has the low-order C1 bits zero. */
mask = GET_MODE_MASK (mode) mask = GET_MODE_MASK (int_mode)
& ~((HOST_WIDE_INT_1U << first_count) - 1); & ~((HOST_WIDE_INT_1U << first_count) - 1);
varop = simplify_and_const_int (NULL_RTX, result_mode, varop = simplify_and_const_int (NULL_RTX, int_result_mode,
XEXP (varop, 0), mask); XEXP (varop, 0), mask);
varop = simplify_shift_const (NULL_RTX, ASHIFT, result_mode, varop = simplify_shift_const (NULL_RTX, ASHIFT,
varop, count); int_result_mode, varop, count);
count = first_count; count = first_count;
code = ASHIFTRT; code = ASHIFTRT;
continue; continue;
...@@ -10662,11 +10676,11 @@ simplify_shift_const_1 (enum rtx_code code, machine_mode result_mode, ...@@ -10662,11 +10676,11 @@ simplify_shift_const_1 (enum rtx_code code, machine_mode result_mode,
this to either an ASHIFT or an ASHIFTRT depending on the this to either an ASHIFT or an ASHIFTRT depending on the
two counts. two counts.
We cannot do this if VAROP's mode is not SHIFT_MODE. */ We cannot do this if VAROP's mode is not SHIFT_UNIT_MODE. */
if (code == ASHIFTRT && first_code == ASHIFT if (code == ASHIFTRT && first_code == ASHIFT
&& GET_MODE (varop) == shift_mode && int_varop_mode == shift_unit_mode
&& (num_sign_bit_copies (XEXP (varop, 0), shift_mode) && (num_sign_bit_copies (XEXP (varop, 0), shift_unit_mode)
> first_count)) > first_count))
{ {
varop = XEXP (varop, 0); varop = XEXP (varop, 0);
...@@ -10697,7 +10711,7 @@ simplify_shift_const_1 (enum rtx_code code, machine_mode result_mode, ...@@ -10697,7 +10711,7 @@ simplify_shift_const_1 (enum rtx_code code, machine_mode result_mode,
if (code == first_code) if (code == first_code)
{ {
if (GET_MODE (varop) != result_mode if (int_varop_mode != int_result_mode
&& (code == ASHIFTRT || code == LSHIFTRT && (code == ASHIFTRT || code == LSHIFTRT
|| code == ROTATE)) || code == ROTATE))
break; break;
...@@ -10709,8 +10723,8 @@ simplify_shift_const_1 (enum rtx_code code, machine_mode result_mode, ...@@ -10709,8 +10723,8 @@ simplify_shift_const_1 (enum rtx_code code, machine_mode result_mode,
if (code == ASHIFTRT if (code == ASHIFTRT
|| (code == ROTATE && first_code == ASHIFTRT) || (code == ROTATE && first_code == ASHIFTRT)
|| GET_MODE_PRECISION (mode) > HOST_BITS_PER_WIDE_INT || GET_MODE_PRECISION (int_mode) > HOST_BITS_PER_WIDE_INT
|| (GET_MODE (varop) != result_mode || (int_varop_mode != int_result_mode
&& (first_code == ASHIFTRT || first_code == LSHIFTRT && (first_code == ASHIFTRT || first_code == LSHIFTRT
|| first_code == ROTATE || first_code == ROTATE
|| code == ROTATE))) || code == ROTATE)))
...@@ -10720,19 +10734,19 @@ simplify_shift_const_1 (enum rtx_code code, machine_mode result_mode, ...@@ -10720,19 +10734,19 @@ simplify_shift_const_1 (enum rtx_code code, machine_mode result_mode,
nonzero bits of the inner shift the same way the nonzero bits of the inner shift the same way the
outer shift will. */ outer shift will. */
mask_rtx = gen_int_mode (nonzero_bits (varop, GET_MODE (varop)), mask_rtx = gen_int_mode (nonzero_bits (varop, int_varop_mode),
result_mode); int_result_mode);
mask_rtx mask_rtx
= simplify_const_binary_operation (code, result_mode, mask_rtx, = simplify_const_binary_operation (code, int_result_mode,
GEN_INT (count)); mask_rtx, GEN_INT (count));
/* Give up if we can't compute an outer operation to use. */ /* Give up if we can't compute an outer operation to use. */
if (mask_rtx == 0 if (mask_rtx == 0
|| !CONST_INT_P (mask_rtx) || !CONST_INT_P (mask_rtx)
|| ! merge_outer_ops (&outer_op, &outer_const, AND, || ! merge_outer_ops (&outer_op, &outer_const, AND,
INTVAL (mask_rtx), INTVAL (mask_rtx),
result_mode, &complement_p)) int_result_mode, &complement_p))
break; break;
/* If the shifts are in the same direction, we add the /* If the shifts are in the same direction, we add the
...@@ -10769,22 +10783,22 @@ simplify_shift_const_1 (enum rtx_code code, machine_mode result_mode, ...@@ -10769,22 +10783,22 @@ simplify_shift_const_1 (enum rtx_code code, machine_mode result_mode,
/* For ((unsigned) (cstULL >> count)) >> cst2 we have to make /* For ((unsigned) (cstULL >> count)) >> cst2 we have to make
sure the result will be masked. See PR70222. */ sure the result will be masked. See PR70222. */
if (code == LSHIFTRT if (code == LSHIFTRT
&& mode != result_mode && int_mode != int_result_mode
&& !merge_outer_ops (&outer_op, &outer_const, AND, && !merge_outer_ops (&outer_op, &outer_const, AND,
GET_MODE_MASK (result_mode) GET_MODE_MASK (int_result_mode)
>> orig_count, result_mode, >> orig_count, int_result_mode,
&complement_p)) &complement_p))
break; break;
/* For ((int) (cstLL >> count)) >> cst2 just give up. Queuing /* For ((int) (cstLL >> count)) >> cst2 just give up. Queuing
up outer sign extension (often left and right shift) is up outer sign extension (often left and right shift) is
hardly more efficient than the original. See PR70429. */ hardly more efficient than the original. See PR70429. */
if (code == ASHIFTRT && mode != result_mode) if (code == ASHIFTRT && int_mode != int_result_mode)
break; break;
rtx new_rtx = simplify_const_binary_operation (code, mode, rtx new_rtx = simplify_const_binary_operation (code, int_mode,
XEXP (varop, 0), XEXP (varop, 0),
GEN_INT (count)); GEN_INT (count));
varop = gen_rtx_fmt_ee (code, mode, new_rtx, XEXP (varop, 1)); varop = gen_rtx_fmt_ee (code, int_mode, new_rtx, XEXP (varop, 1));
count = 0; count = 0;
continue; continue;
} }
...@@ -10805,6 +10819,8 @@ simplify_shift_const_1 (enum rtx_code code, machine_mode result_mode, ...@@ -10805,6 +10819,8 @@ simplify_shift_const_1 (enum rtx_code code, machine_mode result_mode,
/* The following rules apply only to scalars. */ /* The following rules apply only to scalars. */
if (shift_mode != shift_unit_mode) if (shift_mode != shift_unit_mode)
break; break;
int_varop_mode = as_a <scalar_int_mode> (GET_MODE (varop));
int_result_mode = as_a <scalar_int_mode> (result_mode);
/* If we have (xshiftrt (ior (plus X (const_int -1)) X) C) /* If we have (xshiftrt (ior (plus X (const_int -1)) X) C)
with C the size of VAROP - 1 and the shift is logical if with C the size of VAROP - 1 and the shift is logical if
...@@ -10817,15 +10833,15 @@ simplify_shift_const_1 (enum rtx_code code, machine_mode result_mode, ...@@ -10817,15 +10833,15 @@ simplify_shift_const_1 (enum rtx_code code, machine_mode result_mode,
&& XEXP (XEXP (varop, 0), 1) == constm1_rtx && XEXP (XEXP (varop, 0), 1) == constm1_rtx
&& (STORE_FLAG_VALUE == 1 || STORE_FLAG_VALUE == -1) && (STORE_FLAG_VALUE == 1 || STORE_FLAG_VALUE == -1)
&& (code == LSHIFTRT || code == ASHIFTRT) && (code == LSHIFTRT || code == ASHIFTRT)
&& count == (GET_MODE_PRECISION (GET_MODE (varop)) - 1) && count == (GET_MODE_PRECISION (int_varop_mode) - 1)
&& rtx_equal_p (XEXP (XEXP (varop, 0), 0), XEXP (varop, 1))) && rtx_equal_p (XEXP (XEXP (varop, 0), 0), XEXP (varop, 1)))
{ {
count = 0; count = 0;
varop = gen_rtx_LE (GET_MODE (varop), XEXP (varop, 1), varop = gen_rtx_LE (int_varop_mode, XEXP (varop, 1),
const0_rtx); const0_rtx);
if (STORE_FLAG_VALUE == 1 ? code == ASHIFTRT : code == LSHIFTRT) if (STORE_FLAG_VALUE == 1 ? code == ASHIFTRT : code == LSHIFTRT)
varop = gen_rtx_NEG (GET_MODE (varop), varop); varop = gen_rtx_NEG (int_varop_mode, varop);
continue; continue;
} }
...@@ -10838,19 +10854,20 @@ simplify_shift_const_1 (enum rtx_code code, machine_mode result_mode, ...@@ -10838,19 +10854,20 @@ simplify_shift_const_1 (enum rtx_code code, machine_mode result_mode,
if (CONST_INT_P (XEXP (varop, 1)) if (CONST_INT_P (XEXP (varop, 1))
/* We can't do this if we have (ashiftrt (xor)) and the /* We can't do this if we have (ashiftrt (xor)) and the
constant has its sign bit set in shift_mode with shift_mode constant has its sign bit set in shift_unit_mode with
wider than result_mode. */ shift_unit_mode wider than result_mode. */
&& !(code == ASHIFTRT && GET_CODE (varop) == XOR && !(code == ASHIFTRT && GET_CODE (varop) == XOR
&& result_mode != shift_mode && int_result_mode != shift_unit_mode
&& 0 > trunc_int_for_mode (INTVAL (XEXP (varop, 1)), && 0 > trunc_int_for_mode (INTVAL (XEXP (varop, 1)),
shift_mode)) shift_unit_mode))
&& (new_rtx = simplify_const_binary_operation && (new_rtx = simplify_const_binary_operation
(code, result_mode, (code, int_result_mode,
gen_int_mode (INTVAL (XEXP (varop, 1)), result_mode), gen_int_mode (INTVAL (XEXP (varop, 1)), int_result_mode),
GEN_INT (count))) != 0 GEN_INT (count))) != 0
&& CONST_INT_P (new_rtx) && CONST_INT_P (new_rtx)
&& merge_outer_ops (&outer_op, &outer_const, GET_CODE (varop), && merge_outer_ops (&outer_op, &outer_const, GET_CODE (varop),
INTVAL (new_rtx), result_mode, &complement_p)) INTVAL (new_rtx), int_result_mode,
&complement_p))
{ {
varop = XEXP (varop, 0); varop = XEXP (varop, 0);
continue; continue;
...@@ -10863,16 +10880,16 @@ simplify_shift_const_1 (enum rtx_code code, machine_mode result_mode, ...@@ -10863,16 +10880,16 @@ simplify_shift_const_1 (enum rtx_code code, machine_mode result_mode,
changes the sign bit. */ changes the sign bit. */
if (CONST_INT_P (XEXP (varop, 1)) if (CONST_INT_P (XEXP (varop, 1))
&& !(code == ASHIFTRT && GET_CODE (varop) == XOR && !(code == ASHIFTRT && GET_CODE (varop) == XOR
&& result_mode != shift_mode && int_result_mode != shift_unit_mode
&& 0 > trunc_int_for_mode (INTVAL (XEXP (varop, 1)), && 0 > trunc_int_for_mode (INTVAL (XEXP (varop, 1)),
shift_mode))) shift_unit_mode)))
{ {
rtx lhs = simplify_shift_const (NULL_RTX, code, shift_mode, rtx lhs = simplify_shift_const (NULL_RTX, code, shift_unit_mode,
XEXP (varop, 0), count); XEXP (varop, 0), count);
rtx rhs = simplify_shift_const (NULL_RTX, code, shift_mode, rtx rhs = simplify_shift_const (NULL_RTX, code, shift_unit_mode,
XEXP (varop, 1), count); XEXP (varop, 1), count);
varop = simplify_gen_binary (GET_CODE (varop), shift_mode, varop = simplify_gen_binary (GET_CODE (varop), shift_unit_mode,
lhs, rhs); lhs, rhs);
varop = apply_distributive_law (varop); varop = apply_distributive_law (varop);
...@@ -10885,6 +10902,7 @@ simplify_shift_const_1 (enum rtx_code code, machine_mode result_mode, ...@@ -10885,6 +10902,7 @@ simplify_shift_const_1 (enum rtx_code code, machine_mode result_mode,
/* The following rules apply only to scalars. */ /* The following rules apply only to scalars. */
if (shift_mode != shift_unit_mode) if (shift_mode != shift_unit_mode)
break; break;
int_result_mode = as_a <scalar_int_mode> (result_mode);
/* Convert (lshiftrt (eq FOO 0) C) to (xor FOO 1) if STORE_FLAG_VALUE /* Convert (lshiftrt (eq FOO 0) C) to (xor FOO 1) if STORE_FLAG_VALUE
says that the sign bit can be tested, FOO has mode MODE, C is says that the sign bit can be tested, FOO has mode MODE, C is
...@@ -10892,13 +10910,13 @@ simplify_shift_const_1 (enum rtx_code code, machine_mode result_mode, ...@@ -10892,13 +10910,13 @@ simplify_shift_const_1 (enum rtx_code code, machine_mode result_mode,
that may be nonzero. */ that may be nonzero. */
if (code == LSHIFTRT if (code == LSHIFTRT
&& XEXP (varop, 1) == const0_rtx && XEXP (varop, 1) == const0_rtx
&& GET_MODE (XEXP (varop, 0)) == result_mode && GET_MODE (XEXP (varop, 0)) == int_result_mode
&& count == (GET_MODE_PRECISION (result_mode) - 1) && count == (GET_MODE_PRECISION (int_result_mode) - 1)
&& HWI_COMPUTABLE_MODE_P (result_mode) && HWI_COMPUTABLE_MODE_P (int_result_mode)
&& STORE_FLAG_VALUE == -1 && STORE_FLAG_VALUE == -1
&& nonzero_bits (XEXP (varop, 0), result_mode) == 1 && nonzero_bits (XEXP (varop, 0), int_result_mode) == 1
&& merge_outer_ops (&outer_op, &outer_const, XOR, 1, result_mode, && merge_outer_ops (&outer_op, &outer_const, XOR, 1,
&complement_p)) int_result_mode, &complement_p))
{ {
varop = XEXP (varop, 0); varop = XEXP (varop, 0);
count = 0; count = 0;
...@@ -10910,12 +10928,13 @@ simplify_shift_const_1 (enum rtx_code code, machine_mode result_mode, ...@@ -10910,12 +10928,13 @@ simplify_shift_const_1 (enum rtx_code code, machine_mode result_mode,
/* The following rules apply only to scalars. */ /* The following rules apply only to scalars. */
if (shift_mode != shift_unit_mode) if (shift_mode != shift_unit_mode)
break; break;
int_result_mode = as_a <scalar_int_mode> (result_mode);
/* (lshiftrt (neg A) C) where A is either 0 or 1 and C is one less /* (lshiftrt (neg A) C) where A is either 0 or 1 and C is one less
than the number of bits in the mode is equivalent to A. */ than the number of bits in the mode is equivalent to A. */
if (code == LSHIFTRT if (code == LSHIFTRT
&& count == (GET_MODE_PRECISION (result_mode) - 1) && count == (GET_MODE_PRECISION (int_result_mode) - 1)
&& nonzero_bits (XEXP (varop, 0), result_mode) == 1) && nonzero_bits (XEXP (varop, 0), int_result_mode) == 1)
{ {
varop = XEXP (varop, 0); varop = XEXP (varop, 0);
count = 0; count = 0;
...@@ -10925,8 +10944,8 @@ simplify_shift_const_1 (enum rtx_code code, machine_mode result_mode, ...@@ -10925,8 +10944,8 @@ simplify_shift_const_1 (enum rtx_code code, machine_mode result_mode,
/* NEG commutes with ASHIFT since it is multiplication. Move the /* NEG commutes with ASHIFT since it is multiplication. Move the
NEG outside to allow shifts to combine. */ NEG outside to allow shifts to combine. */
if (code == ASHIFT if (code == ASHIFT
&& merge_outer_ops (&outer_op, &outer_const, NEG, 0, result_mode, && merge_outer_ops (&outer_op, &outer_const, NEG, 0,
&complement_p)) int_result_mode, &complement_p))
{ {
varop = XEXP (varop, 0); varop = XEXP (varop, 0);
continue; continue;
...@@ -10937,16 +10956,17 @@ simplify_shift_const_1 (enum rtx_code code, machine_mode result_mode, ...@@ -10937,16 +10956,17 @@ simplify_shift_const_1 (enum rtx_code code, machine_mode result_mode,
/* The following rules apply only to scalars. */ /* The following rules apply only to scalars. */
if (shift_mode != shift_unit_mode) if (shift_mode != shift_unit_mode)
break; break;
int_result_mode = as_a <scalar_int_mode> (result_mode);
/* (lshiftrt (plus A -1) C) where A is either 0 or 1 and C /* (lshiftrt (plus A -1) C) where A is either 0 or 1 and C
is one less than the number of bits in the mode is is one less than the number of bits in the mode is
equivalent to (xor A 1). */ equivalent to (xor A 1). */
if (code == LSHIFTRT if (code == LSHIFTRT
&& count == (GET_MODE_PRECISION (result_mode) - 1) && count == (GET_MODE_PRECISION (int_result_mode) - 1)
&& XEXP (varop, 1) == constm1_rtx && XEXP (varop, 1) == constm1_rtx
&& nonzero_bits (XEXP (varop, 0), result_mode) == 1 && nonzero_bits (XEXP (varop, 0), int_result_mode) == 1
&& merge_outer_ops (&outer_op, &outer_const, XOR, 1, result_mode, && merge_outer_ops (&outer_op, &outer_const, XOR, 1,
&complement_p)) int_result_mode, &complement_p))
{ {
count = 0; count = 0;
varop = XEXP (varop, 0); varop = XEXP (varop, 0);
...@@ -10961,21 +10981,20 @@ simplify_shift_const_1 (enum rtx_code code, machine_mode result_mode, ...@@ -10961,21 +10981,20 @@ simplify_shift_const_1 (enum rtx_code code, machine_mode result_mode,
if ((code == ASHIFTRT || code == LSHIFTRT) if ((code == ASHIFTRT || code == LSHIFTRT)
&& count < HOST_BITS_PER_WIDE_INT && count < HOST_BITS_PER_WIDE_INT
&& nonzero_bits (XEXP (varop, 1), result_mode) >> count == 0 && nonzero_bits (XEXP (varop, 1), int_result_mode) >> count == 0
&& (nonzero_bits (XEXP (varop, 1), result_mode) && (nonzero_bits (XEXP (varop, 1), int_result_mode)
& nonzero_bits (XEXP (varop, 0), result_mode)) == 0) & nonzero_bits (XEXP (varop, 0), int_result_mode)) == 0)
{ {
varop = XEXP (varop, 0); varop = XEXP (varop, 0);
continue; continue;
} }
else if ((code == ASHIFTRT || code == LSHIFTRT) else if ((code == ASHIFTRT || code == LSHIFTRT)
&& count < HOST_BITS_PER_WIDE_INT && count < HOST_BITS_PER_WIDE_INT
&& HWI_COMPUTABLE_MODE_P (result_mode) && HWI_COMPUTABLE_MODE_P (int_result_mode)
&& 0 == (nonzero_bits (XEXP (varop, 0), result_mode) && 0 == (nonzero_bits (XEXP (varop, 0), int_result_mode)
>> count) >> count)
&& 0 == (nonzero_bits (XEXP (varop, 0), result_mode) && 0 == (nonzero_bits (XEXP (varop, 0), int_result_mode)
& nonzero_bits (XEXP (varop, 1), & nonzero_bits (XEXP (varop, 1), int_result_mode)))
result_mode)))
{ {
varop = XEXP (varop, 1); varop = XEXP (varop, 1);
continue; continue;
...@@ -10985,12 +11004,13 @@ simplify_shift_const_1 (enum rtx_code code, machine_mode result_mode, ...@@ -10985,12 +11004,13 @@ simplify_shift_const_1 (enum rtx_code code, machine_mode result_mode,
if (code == ASHIFT if (code == ASHIFT
&& CONST_INT_P (XEXP (varop, 1)) && CONST_INT_P (XEXP (varop, 1))
&& (new_rtx = simplify_const_binary_operation && (new_rtx = simplify_const_binary_operation
(ASHIFT, result_mode, (ASHIFT, int_result_mode,
gen_int_mode (INTVAL (XEXP (varop, 1)), result_mode), gen_int_mode (INTVAL (XEXP (varop, 1)), int_result_mode),
GEN_INT (count))) != 0 GEN_INT (count))) != 0
&& CONST_INT_P (new_rtx) && CONST_INT_P (new_rtx)
&& merge_outer_ops (&outer_op, &outer_const, PLUS, && merge_outer_ops (&outer_op, &outer_const, PLUS,
INTVAL (new_rtx), result_mode, &complement_p)) INTVAL (new_rtx), int_result_mode,
&complement_p))
{ {
varop = XEXP (varop, 0); varop = XEXP (varop, 0);
continue; continue;
...@@ -11003,14 +11023,15 @@ simplify_shift_const_1 (enum rtx_code code, machine_mode result_mode, ...@@ -11003,14 +11023,15 @@ simplify_shift_const_1 (enum rtx_code code, machine_mode result_mode,
for reasoning in doing so. */ for reasoning in doing so. */
if (code == LSHIFTRT if (code == LSHIFTRT
&& CONST_INT_P (XEXP (varop, 1)) && CONST_INT_P (XEXP (varop, 1))
&& mode_signbit_p (result_mode, XEXP (varop, 1)) && mode_signbit_p (int_result_mode, XEXP (varop, 1))
&& (new_rtx = simplify_const_binary_operation && (new_rtx = simplify_const_binary_operation
(code, result_mode, (code, int_result_mode,
gen_int_mode (INTVAL (XEXP (varop, 1)), result_mode), gen_int_mode (INTVAL (XEXP (varop, 1)), int_result_mode),
GEN_INT (count))) != 0 GEN_INT (count))) != 0
&& CONST_INT_P (new_rtx) && CONST_INT_P (new_rtx)
&& merge_outer_ops (&outer_op, &outer_const, XOR, && merge_outer_ops (&outer_op, &outer_const, XOR,
INTVAL (new_rtx), result_mode, &complement_p)) INTVAL (new_rtx), int_result_mode,
&complement_p))
{ {
varop = XEXP (varop, 0); varop = XEXP (varop, 0);
continue; continue;
...@@ -11022,6 +11043,7 @@ simplify_shift_const_1 (enum rtx_code code, machine_mode result_mode, ...@@ -11022,6 +11043,7 @@ simplify_shift_const_1 (enum rtx_code code, machine_mode result_mode,
/* The following rules apply only to scalars. */ /* The following rules apply only to scalars. */
if (shift_mode != shift_unit_mode) if (shift_mode != shift_unit_mode)
break; break;
int_varop_mode = as_a <scalar_int_mode> (GET_MODE (varop));
/* If we have (xshiftrt (minus (ashiftrt X C)) X) C) /* If we have (xshiftrt (minus (ashiftrt X C)) X) C)
with C the size of VAROP - 1 and the shift is logical if with C the size of VAROP - 1 and the shift is logical if
...@@ -11032,18 +11054,18 @@ simplify_shift_const_1 (enum rtx_code code, machine_mode result_mode, ...@@ -11032,18 +11054,18 @@ simplify_shift_const_1 (enum rtx_code code, machine_mode result_mode,
if ((STORE_FLAG_VALUE == 1 || STORE_FLAG_VALUE == -1) if ((STORE_FLAG_VALUE == 1 || STORE_FLAG_VALUE == -1)
&& GET_CODE (XEXP (varop, 0)) == ASHIFTRT && GET_CODE (XEXP (varop, 0)) == ASHIFTRT
&& count == (GET_MODE_PRECISION (GET_MODE (varop)) - 1) && count == (GET_MODE_PRECISION (int_varop_mode) - 1)
&& (code == LSHIFTRT || code == ASHIFTRT) && (code == LSHIFTRT || code == ASHIFTRT)
&& CONST_INT_P (XEXP (XEXP (varop, 0), 1)) && CONST_INT_P (XEXP (XEXP (varop, 0), 1))
&& INTVAL (XEXP (XEXP (varop, 0), 1)) == count && INTVAL (XEXP (XEXP (varop, 0), 1)) == count
&& rtx_equal_p (XEXP (XEXP (varop, 0), 0), XEXP (varop, 1))) && rtx_equal_p (XEXP (XEXP (varop, 0), 0), XEXP (varop, 1)))
{ {
count = 0; count = 0;
varop = gen_rtx_GT (GET_MODE (varop), XEXP (varop, 1), varop = gen_rtx_GT (int_varop_mode, XEXP (varop, 1),
const0_rtx); const0_rtx);
if (STORE_FLAG_VALUE == 1 ? code == ASHIFTRT : code == LSHIFTRT) if (STORE_FLAG_VALUE == 1 ? code == ASHIFTRT : code == LSHIFTRT)
varop = gen_rtx_NEG (GET_MODE (varop), varop); varop = gen_rtx_NEG (int_varop_mode, varop);
continue; continue;
} }
...@@ -11079,8 +11101,15 @@ simplify_shift_const_1 (enum rtx_code code, machine_mode result_mode, ...@@ -11079,8 +11101,15 @@ simplify_shift_const_1 (enum rtx_code code, machine_mode result_mode,
break; break;
} }
shift_mode = try_widen_shift_mode (code, varop, count, result_mode, mode, shift_mode = result_mode;
outer_op, outer_const); if (shift_mode != mode)
{
/* We only change the modes of scalar shifts. */
int_mode = as_a <scalar_int_mode> (mode);
int_result_mode = as_a <scalar_int_mode> (result_mode);
shift_mode = try_widen_shift_mode (code, varop, count, int_result_mode,
int_mode, outer_op, outer_const);
}
/* We have now finished analyzing the shift. The result should be /* We have now finished analyzing the shift. The result should be
a shift of type CODE with SHIFT_MODE shifting VAROP COUNT places. If a shift of type CODE with SHIFT_MODE shifting VAROP COUNT places. If
...@@ -11115,8 +11144,9 @@ simplify_shift_const_1 (enum rtx_code code, machine_mode result_mode, ...@@ -11115,8 +11144,9 @@ simplify_shift_const_1 (enum rtx_code code, machine_mode result_mode,
/* If we were doing an LSHIFTRT in a wider mode than it was originally, /* If we were doing an LSHIFTRT in a wider mode than it was originally,
turn off all the bits that the shift would have turned off. */ turn off all the bits that the shift would have turned off. */
if (orig_code == LSHIFTRT && result_mode != shift_mode) if (orig_code == LSHIFTRT && result_mode != shift_mode)
x = simplify_and_const_int (NULL_RTX, shift_mode, x, /* We only change the modes of scalar shifts. */
GET_MODE_MASK (result_mode) >> orig_count); x = simplify_and_const_int (NULL_RTX, as_a <scalar_int_mode> (shift_mode),
x, GET_MODE_MASK (result_mode) >> orig_count);
/* Do the remainder of the processing in RESULT_MODE. */ /* Do the remainder of the processing in RESULT_MODE. */
x = gen_lowpart_or_truncate (result_mode, x); x = gen_lowpart_or_truncate (result_mode, x);
...@@ -11128,12 +11158,14 @@ simplify_shift_const_1 (enum rtx_code code, machine_mode result_mode, ...@@ -11128,12 +11158,14 @@ simplify_shift_const_1 (enum rtx_code code, machine_mode result_mode,
if (outer_op != UNKNOWN) if (outer_op != UNKNOWN)
{ {
int_result_mode = as_a <scalar_int_mode> (result_mode);
if (GET_RTX_CLASS (outer_op) != RTX_UNARY if (GET_RTX_CLASS (outer_op) != RTX_UNARY
&& GET_MODE_PRECISION (result_mode) < HOST_BITS_PER_WIDE_INT) && GET_MODE_PRECISION (int_result_mode) < HOST_BITS_PER_WIDE_INT)
outer_const = trunc_int_for_mode (outer_const, result_mode); outer_const = trunc_int_for_mode (outer_const, int_result_mode);
if (outer_op == AND) if (outer_op == AND)
x = simplify_and_const_int (NULL_RTX, result_mode, x, outer_const); x = simplify_and_const_int (NULL_RTX, int_result_mode, x, outer_const);
else if (outer_op == SET) else if (outer_op == SET)
{ {
/* This means that we have determined that the result is /* This means that we have determined that the result is
...@@ -11142,9 +11174,9 @@ simplify_shift_const_1 (enum rtx_code code, machine_mode result_mode, ...@@ -11142,9 +11174,9 @@ simplify_shift_const_1 (enum rtx_code code, machine_mode result_mode,
x = GEN_INT (outer_const); x = GEN_INT (outer_const);
} }
else if (GET_RTX_CLASS (outer_op) == RTX_UNARY) else if (GET_RTX_CLASS (outer_op) == RTX_UNARY)
x = simplify_gen_unary (outer_op, result_mode, x, result_mode); x = simplify_gen_unary (outer_op, int_result_mode, x, int_result_mode);
else else
x = simplify_gen_binary (outer_op, result_mode, x, x = simplify_gen_binary (outer_op, int_result_mode, x,
GEN_INT (outer_const)); GEN_INT (outer_const));
} }
......
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