https://gcc.gnu.org/g:c078309cda304ffa18d2bd322512530e6feffdfb

commit r16-4414-gc078309cda304ffa18d2bd322512530e6feffdfb
Author: Tamar Christina <[email protected]>
Date:   Tue Oct 14 10:24:13 2025 +0100

    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:
---
 gcc/testsuite/gcc.dg/vect/pr121949_1.c | 45 ++++++++++++++++++++++++++++++++++
 gcc/testsuite/gcc.dg/vect/pr121949_2.c | 45 ++++++++++++++++++++++++++++++++++
 gcc/testsuite/gcc.dg/vect/pr121949_3.c | 45 ++++++++++++++++++++++++++++++++++
 gcc/tree-vect-patterns.cc              |  7 ++++--
 4 files changed, 140 insertions(+), 2 deletions(-)

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 000000000000..9e8d41e3bb53
--- /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 000000000000..f448eb6a7792
--- /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 000000000000..b7e6a3d3fe19
--- /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 6a377e384a0e..becee62a9f53 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;

Reply via email to