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;
--- /dev/null
+/* { dg-options "-O2 -msve-vector-bits=2048" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include <arm_sve.h>
+
+/*
+** 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 } } */
--- /dev/null
+/* { dg-options "-O2 -msve-vector-bits=1024" } */
+
+#include <arm_sve.h>
+
+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 } } */