The backend currently defines a whole vector shift left for 64bit vectors, adding the shift right can also improve code for some PERMs too. So this adds that pattern.
I added a testcase for the shift left also. I also fixed the instruction template there which was using a space instead of a tab after the instruction. Built and tested on aarch64-linux-gnu. PR target/113872 gcc/ChangeLog: * config/aarch64/aarch64-simd.md (vec_shr_<mode><vczle><vczbe>): Use tab instead of space after the instruction in the template. (vec_shl_<mode><vczle><vczbe>): New pattern * config/aarch64/iterators.md (unspec): Add UNSPEC_VEC_SHL gcc/testsuite/ChangeLog: * gcc.target/aarch64/perm_zero-1.c: New test. * gcc.target/aarch64/perm_zero-2.c: New test. Signed-off-by: Andrew Pinski <quic_apin...@quicinc.com> --- gcc/config/aarch64/aarch64-simd.md | 18 ++++++++++++++++-- gcc/config/aarch64/iterators.md | 1 + gcc/testsuite/gcc.target/aarch64/perm_zero-1.c | 15 +++++++++++++++ gcc/testsuite/gcc.target/aarch64/perm_zero-2.c | 15 +++++++++++++++ 4 files changed, 47 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/gcc.target/aarch64/perm_zero-1.c create mode 100644 gcc/testsuite/gcc.target/aarch64/perm_zero-2.c diff --git a/gcc/config/aarch64/aarch64-simd.md b/gcc/config/aarch64/aarch64-simd.md index f8bb973a278..0d2f1ea3902 100644 --- a/gcc/config/aarch64/aarch64-simd.md +++ b/gcc/config/aarch64/aarch64-simd.md @@ -1592,9 +1592,23 @@ (define_insn "vec_shr_<mode><vczle><vczbe>" "TARGET_SIMD" { if (BYTES_BIG_ENDIAN) - return "shl %d0, %d1, %2"; + return "shl\t%d0, %d1, %2"; else - return "ushr %d0, %d1, %2"; + return "ushr\t%d0, %d1, %2"; + } + [(set_attr "type" "neon_shift_imm")] +) +(define_insn "vec_shl_<mode><vczle><vczbe>" + [(set (match_operand:VD 0 "register_operand" "=w") + (unspec:VD [(match_operand:VD 1 "register_operand" "w") + (match_operand:SI 2 "immediate_operand" "i")] + UNSPEC_VEC_SHL))] + "TARGET_SIMD" + { + if (BYTES_BIG_ENDIAN) + return "ushr\t%d0, %d1, %2"; + else + return "shl\t%d0, %d1, %2"; } [(set_attr "type" "neon_shift_imm")] ) diff --git a/gcc/config/aarch64/iterators.md b/gcc/config/aarch64/iterators.md index 99cde46f1ba..3aebe9cf18a 100644 --- a/gcc/config/aarch64/iterators.md +++ b/gcc/config/aarch64/iterators.md @@ -758,6 +758,7 @@ (define_c_enum "unspec" UNSPEC_PMULL ; Used in aarch64-simd.md. UNSPEC_PMULL2 ; Used in aarch64-simd.md. UNSPEC_REV_REGLIST ; Used in aarch64-simd.md. + UNSPEC_VEC_SHL ; Used in aarch64-simd.md. UNSPEC_VEC_SHR ; Used in aarch64-simd.md. UNSPEC_SQRDMLAH ; Used in aarch64-simd.md. UNSPEC_SQRDMLSH ; Used in aarch64-simd.md. diff --git a/gcc/testsuite/gcc.target/aarch64/perm_zero-1.c b/gcc/testsuite/gcc.target/aarch64/perm_zero-1.c new file mode 100644 index 00000000000..3c8f0591a2f --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/perm_zero-1.c @@ -0,0 +1,15 @@ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ +/* PR target/113872 */ +/* For 64bit vectors, PERM with a constant 0 should produce a shift instead of the ext instruction. */ + +#define vect64 __attribute__((vector_size(8))) + +void f(vect64 unsigned short *a) +{ + *a = __builtin_shufflevector((vect64 unsigned short){0},*a, 3,4,5,6); +} + +/* { dg-final { scan-assembler-times "ushr\t" 1 { target aarch64_big_endian } } } */ +/* { dg-final { scan-assembler-times "shl\t" 1 { target aarch64_little_endian } } } */ +/* { dg-final { scan-assembler-not "ext\t" } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/perm_zero-2.c b/gcc/testsuite/gcc.target/aarch64/perm_zero-2.c new file mode 100644 index 00000000000..970e428f832 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/perm_zero-2.c @@ -0,0 +1,15 @@ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ +/* PR target/113872 */ +/* For 64bit vectors, PERM with a constant 0 should produce a shift instead of the ext instruction. */ + +#define vect64 __attribute__((vector_size(8))) + +void f(vect64 unsigned short *a) +{ + *a = __builtin_shufflevector(*a, (vect64 unsigned short){0},3,4,5,6); +} + +/* { dg-final { scan-assembler-times "shl\t" 1 { target aarch64_big_endian } } } */ +/* { dg-final { scan-assembler-times "ushr\t" 1 { target aarch64_little_endian } } } */ +/* { dg-final { scan-assembler-not "ext\t" } } */ -- 2.43.0