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-07-13 Richard Sandiford
Alan Hayward
David Sherwood
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.
Index: gcc/combine.c
===
--- gcc/combine.c 2017-07-13 09:18:42.622481204 +0100
+++ gcc/combine.c 2017-07-13 09:18:43.037447143 +0100
@@ -10343,8 +10343,6 @@ try_widen_shift_mode (enum rtx_code code
machine_mode orig_mode, machine_mode mode,
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));
/* In general we can't perform in wider mode for right shift and rotate. */
@@ -10405,7 +10403,7 @@ simplify_shift_const_1 (enum rtx_code co
int count;
machine_mode mode = result_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
= (GET_MODE_SIZE (mode) + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD;
/* We form (outer_op (code varop count) (outer_const)). */
@@ -10445,9 +10443,19 @@ simplify_shift_const_1 (enum rtx_code co
count = bitsize - count;
}
- shift_mode = try_widen_shift_mode (code, varop, count, result_mode,
-mode, outer_op, outer_const);
- machine_mode shift_unit_mode = GET_MODE_INNER (shift_mode);
+ shift_mode = result_mode;
+ if (shift_mode != mode)
+ {
+ /* We only change the modes of scalar shifts. */
+ int_mode = as_a (mode);
+ int_result_mode = as_a (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 (GET_MODE_INNER (shift_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
@@ -10542,6 +10550,7 @@ simplify_shift_const_1 (enum rtx_code co
/* The following rules apply only to scalars. */
if (shift_mode != shift_unit_mode)
break;
+ int_mode = as_a (mode);
/* If we have (xshiftrt (mem ...) C) and C is MODE_WIDTH
minus the width of a smaller mode, we can do this with a
@@ -10550,15 +10559,15 @@ simplify_shift_const_1 (enum rtx_code co
&& ! mode_dependent_address_p (XEXP (varop, 0),
MEM_ADDR_SPACE (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 ()))
{
new_rtx = adjust_address_nv (varop, tmode,
- BYTES_BIG_ENDIAN ? 0
- : count / BITS_PER_UNIT);
+ BYTES_BIG_ENDIAN ? 0
+ : count / BITS_PER_UNIT);
varop = gen_rtx_fmt_e (code == ASHIFTRT ? SIGN_EXTEND
-: ZERO_EXTEND, mode, new_rtx);
+: ZERO_EXTEND, int_mode, new_rtx);
count = 0;
continue;
}
@@ -10568,20 +10577,22 @@ simplify_shift_const_1 (enum rtx_code co
/* The following rules apply only to scalars. */
if (shift_mode != shift_unit_mode)
break;
+ int_mode = as_a (mode);
+ int_varop_mode = as_a (GET_MODE (varop));
/* 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 widest mode in MODE. */
if (subreg_lowpart_p (varop)
&& is_int_mode (GET_MODE (SUBREG_REG (varop)), _mode)
- && GET_MODE_SIZE (inner_mode) > GET_MODE_SIZE (GET_MODE (varop))
+ && GET_MODE_SIZE (inner_mode) > GET_MODE_SIZE (int_varop_mode)
&&