https://gcc.gnu.org/g:2671f988c928d3d6cd81ebec86a5c3dee938e8cd
commit r17-4737-g2671f988c928d3d6cd81ebec86a5c3dee938e8cd Author: Juergen Christ <[email protected]> Date: Mon Sep 21 18:40:56 2026 +0200 s390x: Optimize vec_perm instrinsic 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]> Diff: --- gcc/config/s390/s390.cc | 26 +++++++ gcc/testsuite/gcc.target/s390/zvector/vec_perm-1.c | 87 ++++++++++++++++++++++ 2 files changed, 113 insertions(+) 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 } } */
