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:
parent
4736041b5a
commit
f24f4c1588
5 changed files with 698 additions and 357 deletions
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
|
|
20
gcc/rtl.h
20
gcc/rtl.h
|
@ -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
|
||||
|
|
|
@ -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
Loading…
Add table
Reference in a new issue