VNx16QI (the SVE register byte mode) is the only SVE mode for which LD1 and LDR result in the same register layout for big-endian. It is therefore the only mode for which we allow LDR and STR to be used for big-endian SVE moves.
The SME support sometimes needs to use LDR and STR to save and restore Z register contents around an SMSTART/SMSTOP SM. It therefore needs to use VNx16QI regardless of the type of value that is stored in the Z registers. Tested on aarch64-linux-gnu and aarch64_be-elf, pushed to trunk. Richard gcc/ PR target/112930 * config/aarch64/aarch64.cc (aarch64_sme_mode_switch_regs::add_reg): Force specific SVE modes for single registers as well as structures. --- gcc/config/aarch64/aarch64.cc | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc index 5cffdabc62e..2a64053f675 100644 --- a/gcc/config/aarch64/aarch64.cc +++ b/gcc/config/aarch64/aarch64.cc @@ -4956,14 +4956,17 @@ aarch64_sme_mode_switch_regs::add_reg (machine_mode mode, unsigned int regno) gcc_assert ((vec_flags & VEC_STRUCT) || end_regno == regno + 1); for (; regno < end_regno; regno++) { + /* Force the mode of SVE saves and restores even for single registers. + This is necessary because big-endian targets only allow LDR Z and + STR Z to be used with byte modes. */ machine_mode submode = mode; - if (vec_flags & VEC_STRUCT) + if (vec_flags & VEC_SVE_PRED) + submode = VNx16BImode; + else if (vec_flags & VEC_SVE_DATA) + submode = SVE_BYTE_MODE; + else if (vec_flags & VEC_STRUCT) { - if (vec_flags & VEC_SVE_PRED) - submode = VNx16BImode; - else if (vec_flags & VEC_SVE_DATA) - submode = SVE_BYTE_MODE; - else if (vec_flags & VEC_PARTIAL) + if (vec_flags & VEC_PARTIAL) submode = V8QImode; else submode = V16QImode; -- 2.25.1