]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
middle-end: Relax vect_recog_vector_vector_shift_pattern STMT def type [PR121949]
authorTamar Christina <tamar.christina@arm.com>
Tue, 14 Oct 2025 09:24:13 +0000 (10:24 +0100)
committerTamar Christina <tamar.christina@arm.com>
Tue, 14 Oct 2025 09:24:20 +0000 (10:24 +0100)
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.

gcc/testsuite/gcc.dg/vect/pr121949_1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/vect/pr121949_2.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/vect/pr121949_3.c [new file with mode: 0644]
gcc/tree-vect-patterns.cc

diff --git a/gcc/testsuite/gcc.dg/vect/pr121949_1.c b/gcc/testsuite/gcc.dg/vect/pr121949_1.c
new file mode 100644 (file)
index 0000000..9e8d41e
--- /dev/null
@@ -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 (file)
index 0000000..f448eb6
--- /dev/null
@@ -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 (file)
index 0000000..b7e6a3d
--- /dev/null
@@ -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 } } } }  */
index 6a377e384a0ec9e54a629a7de6ccdb3ce0bc1fef..becee62a9f536e228b130529de80e6ba101f6778 100644 (file)
@@ -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;