On Thu, 2 Oct 2025, Tamar Christina wrote:
> 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.
>
> Bootstrapped Regtested on aarch64-none-linux-gnu,
> arm-none-linux-gnueabihf, x86_64-pc-linux-gnu
> -m32, -m64 and no issues
>
> Ok for master?
So I think the idea of the code was that the shift vectorization
code can handle constant and external defs by themselves. With
BB vectorization you now catch external defs here, can you
add a check excluding those?
OK with that change.
Thanks,
Richard.
> Thanks,
> Tamar
>
> 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
> 0000000000000000000000000000000000000000..9e8d41e3bb532a619df2b1beb9dc0ddbe9cb87ee
> --- /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
> 0000000000000000000000000000000000000000..f448eb6a77921ec838eb041a5f746ddab8f23c62
> --- /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
> 0000000000000000000000000000000000000000..b7e6a3d3fe19d665c0bf018119f40e7301dc5799
> --- /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
> 782327235db16384c2d71186911802daf7a15ebc..89383eb180349e3f42b150d231b47a8508d30191
> 100644
> --- a/gcc/tree-vect-patterns.cc
> +++ b/gcc/tree-vect-patterns.cc
> @@ -4087,10 +4087,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);
> + stmt_vec_info def_vinfo = vinfo->lookup_def (oprnd1);
> if (!def_vinfo)
> 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;
>
>
>
--
Richard Biener <[email protected]>
SUSE Software Solutions Germany GmbH,
Frankenstrasse 146, 90461 Nuernberg, Germany;
GF: Ivo Totev, Andrew McDonald, Werner Knoblich; (HRB 36809, AG Nuernberg)