[AArch64] Handle SVE subregs that are effectively REVs
Subreg reads should be equivalent to storing the inner register to
memory and loading the appropriate memory bytes back, with subreg
writes doing the reverse. For the reasons explained in the comments,
this isn't what happens for big-endian SVE if we simply reinterpret
one vector register as having a different element size, so the
conceptual store and load is needed in the general case.
However, that obviously produces poor code if we do it too often.
The patch therefore adds a pattern for handling the operation in
registers. This copes with the important case of a VIEW_CONVERT
created by tree-vect-slp.c:duplicate_and_interleave.
It might make sense to tighten the predicates in aarch64-sve.md so
that such subregs are not allowed as operands to most instructions,
but that's future work.
This fixes the sve/slp_*.c tests on aarch64_be.
2018-02-01 Richard Sandiford <richard.sandiford@linaro.org>
gcc/
* config/aarch64/aarch64-protos.h (aarch64_split_sve_subreg_move)
(aarch64_maybe_expand_sve_subreg_move): Declare.
* config/aarch64/aarch64.md (UNSPEC_REV_SUBREG): New unspec.
* config/aarch64/predicates.md (aarch64_any_register_operand): New
predicate.
* config/aarch64/aarch64-sve.md (mov<mode>): Optimize subreg moves
that are semantically a reverse operation.
(*aarch64_sve_mov<mode>_subreg_be): New pattern.
* config/aarch64/aarch64.c (aarch64_maybe_expand_sve_subreg_move):
(aarch64_replace_reg_mode, aarch64_split_sve_subreg_move): New
functions.
(aarch64_can_change_mode_class): For big-endian, forbid changes
between two SVE modes if they have different element sizes.
Reviewed-by: James Greenhalgh <james.greenhalgh@arm.com>
From-SVN: r257289