diff options
author | Richard Sandiford <richard.sandiford@arm.com> | 2019-09-19 09:04:28 +0000 |
---|---|---|
committer | Richard Sandiford <rsandifo@gcc.gnu.org> | 2019-09-19 09:04:28 +0000 |
commit | f24f4c15884bf1ee65a10e2f959842eec4198876 (patch) | |
tree | 36f90ba89bf92546561ae999a4a48cd9c5a4704f /gcc/rtlanal.c | |
parent | 4736041b5aa5681c44cbb9c183b11bbb781492fc (diff) | |
download | gcc-f24f4c15884bf1ee65a10e2f959842eec4198876.zip gcc-f24f4c15884bf1ee65a10e2f959842eec4198876.tar.gz gcc-f24f4c15884bf1ee65a10e2f959842eec4198876.tar.bz2 |
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
Diffstat (limited to 'gcc/rtlanal.c')
-rw-r--r-- | gcc/rtlanal.c | 28 |
1 files changed, 18 insertions, 10 deletions
diff --git a/gcc/rtlanal.c b/gcc/rtlanal.c index 3a72db7..28b399c 100644 --- a/gcc/rtlanal.c +++ b/gcc/rtlanal.c @@ -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) |