diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc index 162947b047b..3816df92b18 100644 --- a/gcc/config/aarch64/aarch64.cc +++ b/gcc/config/aarch64/aarch64.cc @@ -27344,8 +27344,9 @@ aarch64_expand_sve_vec_perm (rtx target, rtx op0, rtx op1, rtx sel) rtx sel_reg = force_reg (sel_mode, sel); /* Check if the sel only references the first values vector. */ - if (CONST_VECTOR_P (sel) - && aarch64_const_vec_all_in_range_p (sel, 0, nunits - 1)) + if (GET_MODE_MASK (GET_MODE_INNER (sel_mode)) <= nunits - 1U + || (CONST_VECTOR_P (sel) + && aarch64_const_vec_all_in_range_p (sel, 0, nunits - 1))) { emit_unspec2 (target, UNSPEC_TBL, op0, sel_reg); return; diff --git a/gcc/testsuite/gcc.target/aarch64/sve/vec_perm_2.c b/gcc/testsuite/gcc.target/aarch64/sve/vec_perm_2.c new file mode 100644 index 00000000000..42fa5f1f97f --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/sve/vec_perm_2.c @@ -0,0 +1,26 @@ +/* { dg-options "-O2 -msve-vector-bits=2048" } */ +/* { dg-final { check-function-bodies "**" "" } } */ + +#include + +/* +** test8: +** tbl z0\.b, {z0\.b}, z2\.b +** ret +*/ +svint8_t +test8 (svint8_t x, svint8_t y, svint8_t z) +{ + return __builtin_shuffle (x, y, z); +} + +svint16_t +test16 (svint16_t x, svint16_t y, svint16_t z) +{ + return __builtin_shuffle (x, y, z); +} + +/* { dg-final { scan-assembler-times {\tand\t} 1 } } */ +/* { dg-final { scan-assembler-times {\tsub\t} 1 } } */ +/* { dg-final { scan-assembler-times {\ttbl\t} 3 } } */ +/* { dg-final { scan-assembler-times {\torr\t} 1 } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/sve/vec_perm_3.c b/gcc/testsuite/gcc.target/aarch64/sve/vec_perm_3.c new file mode 100644 index 00000000000..2fead0890c4 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/sve/vec_perm_3.c @@ -0,0 +1,22 @@ +/* { dg-options "-O2 -msve-vector-bits=1024" } */ + +#include + +svint8_t +test8 (svint8_t x, svint8_t y, svint8_t z) +{ + return __builtin_shuffle (x, y, z); +} + +svint16_t +test16 (svint16_t x, svint16_t y, svint16_t z) +{ + return __builtin_shuffle (x, y, z); +} + +/* test8 does not need an AND. In principle, its subtraction of 128 + from the selector can be rendered as a SUB, an ADD, or an EOR. */ +/* { dg-final { scan-assembler-times {\tand\t} 1 } } */ +/* { dg-final { scan-assembler-times {\t(?:sub|add|eor)\t} 2 } } */ +/* { dg-final { scan-assembler-times {\ttbl\t} 4 } } */ +/* { dg-final { scan-assembler-times {\torr\t} 2 } } */