Fold the vec_perm intrinsic into a VEC_PERM_EXPR such that gcc can
optimize this.
gcc/ChangeLog:
* config/s390/s390.cc (s390_gimple_fold_builtin): New
function.
gcc/testsuite/ChangeLog:
* gcc.target/s390/zvector/vec_perm-1.c: New test.
Signed-off-by: Juergen Christ <[email protected]>
---
gcc/config/s390/s390.cc | 26 ++++++
.../gcc.target/s390/zvector/vec_perm-1.c | 87 +++++++++++++++++++
2 files changed, 113 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..03d2a694d09b 100644
--- a/gcc/config/s390/s390.cc
+++ b/gcc/config/s390/s390.cc
@@ -845,6 +845,30 @@ s390_const_operand_ok (tree arg, int argnum, int op_flags,
tree decl)
return true;
}
+static bool
+s390_gimple_fold_builtin (gimple_stmt_iterator *gsi)
+{
+ gcall *stmt = as_a <gcall *> (gsi_stmt (*gsi));
+ tree fndecl = gimple_call_fndecl (stmt);
+ unsigned int fcode = DECL_MD_FUNCTION_CODE (fndecl);
+ gimple *new_stmt;
+ tree arg0, arg1, arg2;
+
+ if (fcode == S390_BUILTIN_s390_vperm)
+ {
+ arg0 = gimple_call_arg (stmt, 0);
+ arg1 = gimple_call_arg (stmt, 1);
+ arg2 = gimple_call_arg (stmt, 2);
+ new_stmt = gimple_build_assign (gimple_call_lhs (stmt),
+ VEC_PERM_EXPR,
+ arg0, arg1, arg2);
+ gimple_set_location (new_stmt, gimple_location (stmt));
+ gsi_replace (gsi, new_stmt, false);
+ return true;
+ }
+ return false;
+}
+
/* Expand an expression EXP that calls a built-in function,
with result going to TARGET if that's convenient
(and in mode MODE if that's convenient).
@@ -18439,6 +18463,8 @@ s390_bitint_type_info (int n, struct bitint_info *info)
#undef TARGET_INIT_BUILTINS
#define TARGET_INIT_BUILTINS s390_init_builtins
+#undef TARGET_GIMPLE_FOLD_BUILTIN
+#define TARGET_GIMPLE_FOLD_BUILTIN s390_gimple_fold_builtin
#undef TARGET_EXPAND_BUILTIN
#define TARGET_EXPAND_BUILTIN s390_expand_builtin
#undef TARGET_BUILTIN_DECL
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..9afa400b0c7d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/zvector/vec_perm-1.c
@@ -0,0 +1,87 @@
+/* Test whether vec_perm with constant permutation mask gets optimized. */
+
+/* { dg-do compile { target { s390x-*-* } } } */
+/* { dg-options "-march=z14 -O2" } */
+
+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 __builtin_s390_vec_perm (in, in, \
+ (uv16qi) \
+ {0,1,2,3,4,5,6,7,16, \
+ 17,18,19,20,21,22,23}); \
+ } \
+ t \
+ mergelow_##t (t in) \
+ { \
+ return __builtin_s390_vec_perm (in, in, \
+ (uv16qi) \
+ {8,9,10,11,12,13,14,15, \
+ 24,25,26,27,28,29,30,31}); \
+ } \
+ t \
+ pack_hi_##t (t in) \
+ { \
+ return __builtin_s390_vec_perm (in, in, \
+ (uv16qi) \
+ {1,3,5,7,9,11,13,15, \
+ 17,19,21,23,25,27,29,31}); \
+ } \
+ t \
+ pack_si_##t (t in) \
+ { \
+ return __builtin_s390_vec_perm (in, in, \
+ (uv16qi) \
+ {2,3,6,7,10,11,14,15, \
+ 18,19,22,23,26,27,30,31}); \
+ } \
+ t \
+ pack_di_##t (t in) \
+ { \
+ return __builtin_s390_vec_perm (in, in, \
+ (uv16qi) \
+ {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} } } */
+/* { dg-final { scan-assembler-times {vmrh} 14 } } */
+/* { dg-final { scan-assembler-times {vmrl} 14 } } */
+/* { dg-final { scan-assembler-times {vpkh} 14 } } */
+/* { dg-final { scan-assembler-times {vpkf} 14 } } */
+/* { dg-final { scan-assembler-times {vpkg} 14 } } */
--
2.43.7