From: Tamar Christina Date: Tue, 14 Oct 2025 09:24:13 +0000 (+0100) Subject: middle-end: Relax vect_recog_vector_vector_shift_pattern STMT def type [PR121949] X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=c078309cda304ffa18d2bd322512530e6feffdfb;p=thirdparty%2Fgcc.git middle-end: Relax vect_recog_vector_vector_shift_pattern STMT def type [PR121949] The example void f(long long* acc) { for (int row = 0; row < 64; ++row) acc[row] = acc[row] << row; } fails to vectorize because the size of row is different than the size of the being shifted value. The vectorizer has a pattern that should deal with such shifts in vect_recog_vector_vector_shift_pattern however this pattern is using vect_get_internal_def to get the definition of the shift operand. This needlessly restricts the pattern to only internal_defs. The vectorizer can deal with casts on any operand type so this restriction isn't needed and this is dropped. gcc/ChangeLog: PR tree-optimization/121949 * tree-vect-patterns.cc (vect_recog_vector_vector_shift_pattern): Remove restriction on internal_def. gcc/testsuite/ChangeLog: PR tree-optimization/121949 * gcc.dg/vect/pr121949_1.c: New test. * gcc.dg/vect/pr121949_2.c: New test. * gcc.dg/vect/pr121949_3.c: New test. --- diff --git a/gcc/testsuite/gcc.dg/vect/pr121949_1.c b/gcc/testsuite/gcc.dg/vect/pr121949_1.c new file mode 100644 index 00000000000..9e8d41e3bb5 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/pr121949_1.c @@ -0,0 +1,45 @@ +#ifndef TYPE +#define TYPE short +#define MAX 16 +#define IV_TYPE char +#endif + +#include "tree-vect.h" + +__attribute__((noipa)) +void f(TYPE* acc) +{ + for (IV_TYPE row = 0; row < MAX; ++row) + acc[row] = acc[row] << row; +} + +__attribute__((noipa)) +void g(TYPE* acc) +{ +#pragma GCC novector + for (IV_TYPE row = 0; row < MAX; ++row) + acc[row] = acc[row] << row; +} + +int main () +{ + + check_vect (); + + TYPE acc1[MAX] = {}; + TYPE acc2[MAX] = {}; +#pragma GCC novector + for (int i = 0; i < MAX; i++) + acc1[i] = acc2[i] = i; + + f (acc1); + f (acc2); + +#pragma GCC novector + for (int i = 0; i < MAX; i++) + if (acc1[i] != acc2[i]) + __builtin_abort (); +} + +/* { dg-final { scan-tree-dump "LOOP VECTORIZED" "vect" { target { vect_var_shift && vect_int } } } } */ +/* { dg-final { scan-tree-dump "vect_recog_over_widening_pattern: detected" "vect" { target { vect_var_shift && vect_int } } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/pr121949_2.c b/gcc/testsuite/gcc.dg/vect/pr121949_2.c new file mode 100644 index 00000000000..f448eb6a779 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/pr121949_2.c @@ -0,0 +1,45 @@ +#ifndef TYPE +#define TYPE int +#define MAX 32 +#define IV_TYPE short +#endif + +#include "tree-vect.h" + +__attribute__((noipa)) +void f(TYPE* acc) +{ + for (IV_TYPE row = 0; row < MAX; ++row) + acc[row] = acc[row] << row; +} + +__attribute__((noipa)) +void g(TYPE* acc) +{ +#pragma GCC novector + for (IV_TYPE row = 0; row < MAX; ++row) + acc[row] = acc[row] << row; +} + +int main () +{ + + check_vect (); + + TYPE acc1[MAX] = {}; + TYPE acc2[MAX] = {}; +#pragma GCC novector + for (int i = 0; i < MAX; i++) + acc1[i] = acc2[i] = i; + + f (acc1); + f (acc2); + +#pragma GCC novector + for (int i = 0; i < MAX; i++) + if (acc1[i] != acc2[i]) + __builtin_abort (); +} + +/* { dg-final { scan-tree-dump "LOOP VECTORIZED" "vect" { target { vect_var_shift && vect_int } } } } */ +/* { dg-final { scan-tree-dump-not "vect_recog_over_widening_pattern: detected" "vect" { target { vect_var_shift && vect_int } } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/pr121949_3.c b/gcc/testsuite/gcc.dg/vect/pr121949_3.c new file mode 100644 index 00000000000..b7e6a3d3fe1 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/pr121949_3.c @@ -0,0 +1,45 @@ +#ifndef TYPE +#define TYPE long long +#define MAX 64 +#define IV_TYPE int +#endif + +#include "tree-vect.h" + +__attribute__((noipa)) +void f(TYPE* acc) +{ + for (IV_TYPE row = 0; row < MAX; ++row) + acc[row] = acc[row] << row; +} + +__attribute__((noipa)) +void g(TYPE* acc) +{ +#pragma GCC novector + for (IV_TYPE row = 0; row < MAX; ++row) + acc[row] = acc[row] << row; +} + +int main () +{ + + check_vect (); + + TYPE acc1[MAX] = {}; + TYPE acc2[MAX] = {}; +#pragma GCC novector + for (int i = 0; i < MAX; i++) + acc1[i] = acc2[i] = i; + + f (acc1); + f (acc2); + +#pragma GCC novector + for (int i = 0; i < MAX; i++) + if (acc1[i] != acc2[i]) + __builtin_abort (); +} + +/* { dg-final { scan-tree-dump "LOOP VECTORIZED" "vect" { target { vect_var_shift && vect_int } } } } */ +/* { dg-final { scan-tree-dump "vect_recog_vector_vector_shift_pattern: detected" "vect" { target { vect_var_shift && vect_int } } } } */ diff --git a/gcc/tree-vect-patterns.cc b/gcc/tree-vect-patterns.cc index 6a377e384a0..becee62a9f5 100644 --- a/gcc/tree-vect-patterns.cc +++ b/gcc/tree-vect-patterns.cc @@ -4085,10 +4085,13 @@ vect_recog_vector_vector_shift_pattern (vec_info *vinfo, != TYPE_PRECISION (TREE_TYPE (oprnd0))) return NULL; - stmt_vec_info def_vinfo = vect_get_internal_def (vinfo, oprnd1); - if (!def_vinfo) + stmt_vec_info def_vinfo = vinfo->lookup_def (oprnd1); + if (!def_vinfo || STMT_VINFO_DEF_TYPE (def_vinfo) == vect_external_def) return NULL; + def_vinfo = vect_stmt_to_vectorize (def_vinfo); + gcc_assert (def_vinfo); + *type_out = get_vectype_for_scalar_type (vinfo, TREE_TYPE (oprnd0)); if (*type_out == NULL_TREE) return NULL;