If vec_perm intrinsic is called with a constant permutation vector, try to
optimize this such that the permutation vector can be removed altogether.

gcc/ChangeLog:

        * config/s390/s390.cc (s390_expand_builtin): Optimize vec_perm
          builtin.

gcc/testsuite/ChangeLog:

        * gcc.target/s390/zvector/vec_perm-1.c: New test.

Bootstrapped and regtested on s390x.  Ok for trunk?

Signed-off-by: Juergen Christ <[email protected]>
---
 gcc/config/s390/s390.cc                       |  8 ++
 .../gcc.target/s390/zvector/vec_perm-1.c      | 79 +++++++++++++++++++
 2 files changed, 87 insertions(+)
 create mode 100644 gcc/testsuite/gcc.target/s390/zvector/vec_perm-1.c

diff --git a/gcc/config/s390/s390.cc b/gcc/config/s390/s390.cc
index 2e7997979918..94ffdaba53b8 100644
--- a/gcc/config/s390/s390.cc
+++ b/gcc/config/s390/s390.cc
@@ -972,6 +972,14 @@ s390_expand_builtin (tree exp, rtx target, rtx subtarget 
ATTRIBUTE_UNUSED,
       if (arity >= MAX_ARGS)
        return NULL_RTX;
 
+      vec_perm_builder sel;
+      if (arity == 2 && icode == CODE_FOR_vec_permv16qi
+         && TREE_CODE(arg) == VECTOR_CST
+         && tree_to_vec_perm_builder (&sel, arg))
+       return expand_vec_perm_const (mode, op[0], op[1], sel,
+                                     TYPE_MODE (TREE_TYPE (arg)),
+                                     target);
+
       if (O_IMM_P (op_flags)
          && TREE_CODE (arg) != INTEGER_CST)
        {
diff --git a/gcc/testsuite/gcc.target/s390/zvector/vec_perm-1.c 
b/gcc/testsuite/gcc.target/s390/zvector/vec_perm-1.c
new file mode 100644
index 000000000000..9c6d17381f53
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/vec_perm-1.c
@@ -0,0 +1,79 @@
+/* Test whether vec_perm with constant permutation mask gets optimized.  */
+
+/* { dg-do compile { target { s390*-*-* } } } */
+/* { dg-options "-march=z14 -mzarch -mzvector" } */
+
+#include <vecintrin.h>
+
+typedef signed char v16qi __attribute__((vector_size(16)));
+typedef unsigned char uv16qi __attribute__((vector_size(16)));
+typedef char bv16qi __attribute__((vector_size(16),s390_vector_bool));
+
+typedef signed short int v8hi __attribute__((vector_size(16)));
+typedef unsigned short int uv8hi __attribute__((vector_size(16)));
+typedef short int bv8hi __attribute__((vector_size(16),s390_vector_bool));
+
+typedef signed int v4si __attribute__((vector_size(16)));
+typedef unsigned int uv4si __attribute__((vector_size(16)));
+typedef int bv4si __attribute__((vector_size(16),s390_vector_bool));
+
+typedef signed long long v2di __attribute__((vector_size(16)));
+typedef unsigned long long uv2di __attribute__((vector_size(16)));
+typedef long long bv2di __attribute__((vector_size(16),s390_vector_bool));
+
+typedef float v4sf __attribute__((vector_size(16)));
+typedef double v2df __attribute__((vector_size(16)));
+
+#define T(t)                                                           \
+  t                                                                    \
+  mergehi_##t (t in)                                                   \
+  {                                                                    \
+    return vec_perm (in, in,                                           \
+                    (__vector unsigned char)                           \
+                    {0,1,2,3,4,5,6,7,16,17,18,19,20,21,22,23});        \
+  }                                                                    \
+  t                                                                    \
+  mergelow_##t (t in)                                                  \
+  {                                                                    \
+  return vec_perm (in, in,                                             \
+                  (__vector unsigned char)                             \
+                  {8,9,10,11,12,13,14,15,24,25,26,27,28,29,30,31});    \
+  }                                                                    \
+  t                                                                    \
+  pack_hi_##t (t in)                                                   \
+  {                                                                    \
+  return vec_perm (in, in,                                             \
+                  (__vector unsigned char)                             \
+                  {1,3,5,7,9,11,13,15,17,19,21,23,25,27,29,31});       \
+  }                                                                    \
+   t                                                                   \
+   pack_si_##t (t in)                                                  \
+   {                                                                   \
+     return vec_perm (in, in,                                          \
+                     (__vector unsigned char)                          \
+                     {2,3,6,7,10,11,14,15,18,19,22,23,26,27,30,31});   \
+   }                                                                   \
+   t                                                                   \
+   pack_di_##t (t in)                                                  \
+   {                                                                   \
+     return vec_perm (in, in,                                          \
+                     (__vector unsigned char)                          \
+                     {4,5,6,7,12,13,14,15,20,21,22,23,28,29,30,31});   \
+   }
+
+T(v16qi)
+T(uv16qi)
+T(bv16qi)
+T(v8hi)
+T(uv8hi)
+T(bv8hi)
+T(v4si)
+T(uv4si)
+T(bv4si)
+T(v2di)
+T(uv2di)
+T(bv2di)
+T(v4sf)
+T(v2df)
+
+/* { dg-final { scan-assembler-not {vperm} } } */
-- 
2.43.7

Reply via email to