Rework constant subreg folds and handle more variable-length cases

This patch rewrites the way simplify_subreg handles constants.
It uses similar native_encode/native_decode routines to the
tree-level handling of VIEW_CONVERT_EXPR, meaning that we can
move between rtx constants and the target memory image of them.

The main point of this patch is to support subregs of constant-length
vectors for VLA vectors, beyond the very simple cases that were already
handled.  Many of the new tests failed before the patch for variable-
length vectors.

The boolean side is tested more by the upcoming SVE ACLE work.

2019-09-19  Richard Sandiford  <richard.sandiford@arm.com>

gcc/
	* defaults.h (TARGET_UNIT): New macro.
	(target_unit): New type.
	* rtl.h (native_encode_rtx, native_decode_rtx)
	(native_decode_vector_rtx, subreg_size_lsb): Declare.
	(subreg_lsb_1): Turn into an inline wrapper around subreg_size_lsb.
	* rtlanal.c (subreg_lsb_1): Delete.
	(subreg_size_lsb): New function.
	* simplify-rtx.c: Include rtx-vector-builder.h
	(simplify_immed_subreg): Delete.
	(native_encode_rtx, native_decode_vector_rtx, native_decode_rtx)
	(simplify_const_vector_byte_offset, simplify_const_vector_subreg): New
	functions.
	(simplify_subreg): Use them.
	(test_vector_subregs_modes, test_vector_subregs_repeating)
	(test_vector_subregs_fore_back, test_vector_subregs_stepped)
	(test_vector_subregs): New functions.
	(test_vector_ops): Call test_vector_subregs for integer vector
	modes with at least 2 elements.

From-SVN: r275959
This commit is contained in:
Richard Sandiford 2019-09-19 09:04:28 +00:00 committed by Richard Sandiford
parent 4736041b5a
commit f24f4c1588
5 changed files with 698 additions and 357 deletions

View file

@ -1,3 +1,24 @@
2019-09-19 Richard Sandiford <richard.sandiford@arm.com>
* defaults.h (TARGET_UNIT): New macro.
(target_unit): New type.
* rtl.h (native_encode_rtx, native_decode_rtx)
(native_decode_vector_rtx, subreg_size_lsb): Declare.
(subreg_lsb_1): Turn into an inline wrapper around subreg_size_lsb.
* rtlanal.c (subreg_lsb_1): Delete.
(subreg_size_lsb): New function.
* simplify-rtx.c: Include rtx-vector-builder.h
(simplify_immed_subreg): Delete.
(native_encode_rtx, native_decode_vector_rtx, native_decode_rtx)
(simplify_const_vector_byte_offset, simplify_const_vector_subreg): New
functions.
(simplify_subreg): Use them.
(test_vector_subregs_modes, test_vector_subregs_repeating)
(test_vector_subregs_fore_back, test_vector_subregs_stepped)
(test_vector_subregs): New functions.
(test_vector_ops): Call test_vector_subregs for integer vector
modes with at least 2 elements.
2019-09-19 Richard Biener <rguenther@suse.de>
* tree-parloops.c (parloops_is_slp_reduction): Do not set

View file

@ -1459,4 +1459,18 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#define DWARF_GNAT_ENCODINGS_DEFAULT DWARF_GNAT_ENCODINGS_GDB
#endif
#ifndef USED_FOR_TARGET
/* Done this way to keep gengtype happy. */
#if BITS_PER_UNIT == 8
#define TARGET_UNIT uint8_t
#elif BITS_PER_UNIT == 16
#define TARGET_UNIT uint16_t
#elif BITS_PER_UNIT == 32
#define TARGET_UNIT uint32_t
#else
#error Unknown BITS_PER_UNIT
#endif
typedef TARGET_UNIT target_unit;
#endif
#endif /* ! GCC_DEFAULTS_H */

View file

@ -2406,12 +2406,30 @@ extern int rtx_cost (rtx, machine_mode, enum rtx_code, int, bool);
extern int address_cost (rtx, machine_mode, addr_space_t, bool);
extern void get_full_rtx_cost (rtx, machine_mode, enum rtx_code, int,
struct full_rtx_costs *);
extern bool native_encode_rtx (machine_mode, rtx, vec<target_unit> &,
unsigned int, unsigned int);
extern rtx native_decode_rtx (machine_mode, vec<target_unit>,
unsigned int);
extern rtx native_decode_vector_rtx (machine_mode, vec<target_unit>,
unsigned int, unsigned int, unsigned int);
extern poly_uint64 subreg_lsb (const_rtx);
extern poly_uint64 subreg_lsb_1 (machine_mode, machine_mode, poly_uint64);
extern poly_uint64 subreg_size_lsb (poly_uint64, poly_uint64, poly_uint64);
extern poly_uint64 subreg_size_offset_from_lsb (poly_uint64, poly_uint64,
poly_uint64);
extern bool read_modify_subreg_p (const_rtx);
/* Given a subreg's OUTER_MODE, INNER_MODE, and SUBREG_BYTE, return the
bit offset at which the subreg begins (counting from the least significant
bit of the operand). */
inline poly_uint64
subreg_lsb_1 (machine_mode outer_mode, machine_mode inner_mode,
poly_uint64 subreg_byte)
{
return subreg_size_lsb (GET_MODE_SIZE (outer_mode),
GET_MODE_SIZE (inner_mode), subreg_byte);
}
/* Return the subreg byte offset for a subreg whose outer mode is
OUTER_MODE, whose inner mode is INNER_MODE, and where there are
LSB_SHIFT *bits* between the lsb of the outer value and the lsb of

View file

@ -3637,23 +3637,31 @@ loc_mentioned_in_p (rtx *loc, const_rtx in)
return 0;
}
/* Helper function for subreg_lsb. Given a subreg's OUTER_MODE, INNER_MODE,
and SUBREG_BYTE, return the bit offset where the subreg begins
(counting from the least significant bit of the operand). */
/* Reinterpret a subreg as a bit extraction from an integer and return
the position of the least significant bit of the extracted value.
In other words, if the extraction were performed as a shift right
and mask, return the number of bits to shift right.
The outer value of the subreg has OUTER_BYTES bytes and starts at
byte offset SUBREG_BYTE within an inner value of INNER_BYTES bytes. */
poly_uint64
subreg_lsb_1 (machine_mode outer_mode,
machine_mode inner_mode,
poly_uint64 subreg_byte)
subreg_size_lsb (poly_uint64 outer_bytes,
poly_uint64 inner_bytes,
poly_uint64 subreg_byte)
{
poly_uint64 subreg_end, trailing_bytes, byte_pos;
/* A paradoxical subreg begins at bit position 0. */
if (paradoxical_subreg_p (outer_mode, inner_mode))
return 0;
gcc_checking_assert (ordered_p (outer_bytes, inner_bytes));
if (maybe_gt (outer_bytes, inner_bytes))
{
gcc_checking_assert (known_eq (subreg_byte, 0U));
return 0;
}
subreg_end = subreg_byte + GET_MODE_SIZE (outer_mode);
trailing_bytes = GET_MODE_SIZE (inner_mode) - subreg_end;
subreg_end = subreg_byte + outer_bytes;
trailing_bytes = inner_bytes - subreg_end;
if (WORDS_BIG_ENDIAN && BYTES_BIG_ENDIAN)
byte_pos = trailing_bytes;
else if (!WORDS_BIG_ENDIAN && !BYTES_BIG_ENDIAN)

File diff suppressed because it is too large Load diff