]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
vect: Add uncounted loop unit tests
authorVictor Do Nascimento <victor.donascimento@arm.com>
Mon, 1 Dec 2025 17:23:53 +0000 (17:23 +0000)
committerVictor Do Nascimento <victor.donascimento@arm.com>
Mon, 15 Dec 2025 15:27:40 +0000 (15:27 +0000)
gcc/testsuite/ChangeLog:

* gcc.dg/vect/vect-early-break_40.c: Fix.
* gcc.dg/gomp/static-chunk-size-one.c: Likewise.
* gcc.dg/vect/vect-uncounted_1.c: New.
* gcc.dg/vect/vect-uncounted_2.c: Likewise.
* gcc.dg/vect/vect-uncounted_3.c: Likewise.
* gcc.dg/vect/vect-uncounted_4.c: Likewise.
* gcc.dg/vect/vect-uncounted_5.c: Likewise.
* gcc.dg/vect/vect-uncounted_6.c: Likewise.
* gcc.dg/vect/vect-uncounted_7.c: Likewise.
* gcc.dg/vect/vect-uncounted-run_1.c: Likewise.
* gcc.dg/vect/vect-uncounted-run_2.c: Likewise.
* gcc.dg/vect/vect-uncounted-run_3.c: Likewise.
* gcc.dg/vect/vect-uncounted-prolog-peel_1.c: Likewise.

13 files changed:
gcc/testsuite/gcc.dg/gomp/static-chunk-size-one.c
gcc/testsuite/gcc.dg/vect/vect-early-break_40.c
gcc/testsuite/gcc.dg/vect/vect-uncounted-prolog-peel_1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/vect/vect-uncounted-run_1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/vect/vect-uncounted-run_2.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/vect/vect-uncounted-run_3.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/vect/vect-uncounted_1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/vect/vect-uncounted_2.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/vect/vect-uncounted_3.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/vect/vect-uncounted_4.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/vect/vect-uncounted_5.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/vect/vect-uncounted_6.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/vect/vect-uncounted_7.c [new file with mode: 0644]

index e82de772deb2693d4e09fd87fae91ea88bd87f5e..12b508657fafa62c5047b7809a3c026e2466ab03 100644 (file)
@@ -1,5 +1,5 @@
 /* { dg-do compile } */
-/* { dg-options "-fopenmp -O2 -fdump-tree-optimized -fno-tree-pre" } */
+/* { dg-options "-fopenmp -O2 -fdump-tree-optimized -fno-tree-pre -fno-tree-vectorize" } */
 
 int
 bar ()
index 428f6249fa68f00bd70fa660dd9c1bb508181f4a..9c0e1fb1264f21bfa764675ec40fa2b57e63b4d2 100644 (file)
@@ -23,5 +23,4 @@ unsigned test4(unsigned x)
  return ret;
 }
 
-/* SCEV can't currently analyze this loop bounds.  */
-/* { dg-final { scan-tree-dump "vectorized 1 loops in function" "vect" { xfail *-*-* } } } */
\ No newline at end of file
+/* { dg-final { scan-tree-dump "vectorized 1 loops in function" "vect" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/vect-uncounted-prolog-peel_1.c b/gcc/testsuite/gcc.dg/vect/vect-uncounted-prolog-peel_1.c
new file mode 100644 (file)
index 0000000..fab4ed0
--- /dev/null
@@ -0,0 +1,23 @@
+/* { dg-add-options vect_early_break } */
+/* { dg-do compile } */
+/* { dg-require-effective-target vect_early_break } */
+/* { dg-require-effective-target vect_int } */
+
+int
+foo (int *haystack, int needle)
+{
+  int i = 0;
+  while (1)
+    {
+      if (haystack[i] == needle)
+       return i;
+      i++;
+     }
+}
+
+/* { dg-final { scan-tree-dump {note:\s*Alignment of access forced using peeling.} "vect" } } */
+/* { dg-final { scan-tree-dump {if \(prolog_loop_niters.[0-9_]+ == 0\)\n\s*goto} "vect" } } */
+/* { dg-final { scan-tree-dump {ivtmp_[0-9_]+ = PHI <ivtmp_[0-9_]+\([0-9_]+\), 0\([0-9_]+\)>} "vect" } } */
+/* { dg-final { scan-tree-dump {ivtmp_[0-9_]+ = ivtmp_[0-9_]+ \+ 1;} "vect" } } */
+/* { dg-final { scan-tree-dump {if \(ivtmp_[0-9_]+ >= prolog_loop_niters.[0-9_]+\)\n\s*goto} "vect" } } */
+/* { dg-final { scan-tree-dump {vectorized 1 loops in function} "vect" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/vect-uncounted-run_1.c b/gcc/testsuite/gcc.dg/vect/vect-uncounted-run_1.c
new file mode 100644 (file)
index 0000000..75a8ed1
--- /dev/null
@@ -0,0 +1,56 @@
+/* Check we can derive scalar IV return value from vectorized IV value,
+   resetting it on entry into the scalar epilogue loop via BIT_FIELD_REF.  */
+/* { dg-add-options vect_early_break } */
+/* { dg-require-effective-target vect_early_break_hw } */
+/* { dg-require-effective-target vect_int } */
+
+#include <assert.h>
+#include "tree-vect.h"
+
+#define N 128
+#define VAL 13
+
+__attribute__((noipa, noinline))
+int
+foo (int *haystack, int needle)
+{
+  int i = 0;
+  while (1)
+    {
+      if (haystack[i] == needle)
+       return i;
+      i++;
+     }
+}
+
+#define CHECK_MATCH(POS)               \
+  void                                 \
+  check_match_ ## POS (void)           \
+  {                                    \
+    int input[N] = {[0 ... N-1] = 0};  \
+    input[POS] = VAL;                  \
+    int res = foo (input, VAL);                \
+    assert (res == POS);               \
+  }
+
+CHECK_MATCH (0)
+CHECK_MATCH (3)
+CHECK_MATCH (127)
+
+#undef CHECK_MATCH
+#define CHECK_MATCH(POS) check_match_ ## POS ()
+
+int
+main ()
+{
+  CHECK_MATCH (0);
+  CHECK_MATCH (3);
+  CHECK_MATCH (127);
+  return 0;
+}
+
+/* { dg-final { scan-tree-dump "Loop being analyzed as uncounted." "vect" } } */
+/* { dg-final { scan-tree-dump "vectorized 1 loops in function" "vect" } } */
+/* Ensure we reset our scalar IV so as to repeat the last vector iteration.  */
+/* { dg-final { scan-tree-dump {_[0-9_]+ = BIT_FIELD_REF <vect_i_[0-9_.]+, [0-9]+, 0>} "vect" } } */
+
diff --git a/gcc/testsuite/gcc.dg/vect/vect-uncounted-run_2.c b/gcc/testsuite/gcc.dg/vect/vect-uncounted-run_2.c
new file mode 100644 (file)
index 0000000..c5019de
--- /dev/null
@@ -0,0 +1,41 @@
+/* execution test for the correct resetting of live out values on epilog loop
+   entry.  */
+/* { dg-add-options vect_early_break } */
+/* { dg-do run } */
+/* { dg-require-effective-target vect_early_break_hw } */
+/* { dg-require-effective-target vect_int } */
+
+#include <assert.h>
+#include "tree-vect.h"
+#define N 9
+
+__attribute__((noipa, noinline))
+void
+test01 ()
+{
+    {
+      int x[N] = {2, 4, 6, 8, 10, 12, 14, 16, 18};
+      const int y[N] = {3, 5, 7, 9, 11, 13, 15, 17, 19};
+      int z[N] = {5, 9, 13, 17, 21, 25, 29, 33, 37};
+
+      int *x0 = x;
+      int *xN = x+N;
+      const int *y0 = y;
+      const int *yN = y+N;
+
+      int *res = x;
+
+      for (; x0 != xN && y0 != yN; ++x0, (void)++y0, ++res)
+       *res = *x0 + *y0;
+      assert (x0 == x+N && y0 == y+N && res == x+N);
+      assert (x[0] == z[0] && x[1] == z[1]);
+    }
+}
+
+int
+main ()
+{
+  test01 ();
+}
+
+/* { dg-final { scan-tree-dump "vectorized 1 loops in function" "vect" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/vect-uncounted-run_3.c b/gcc/testsuite/gcc.dg/vect/vect-uncounted-run_3.c
new file mode 100644 (file)
index 0000000..26fcb06
--- /dev/null
@@ -0,0 +1,42 @@
+/* Check vectorization of uncounted reductions.  */
+/* { dg-add-options vect_early_break } */
+/* { dg-do run } */
+/* { dg-require-effective-target vect_early_break_hw } */
+/* { dg-require-effective-target vect_int } */
+#include <assert.h>
+#include "tree-vect.h"
+
+__attribute__((noipa, noinline))
+int
+foo (int *a0, int *aN, int accum)
+{
+  int i = 0;
+  while (1)
+    {
+      if (a0[i++] == *aN)
+       return accum;
+      accum += a0[i];
+     }
+}
+
+void
+accum_check (int *a0, int len, int accum, int result)
+{
+  int retval = foo (a0, a0+len, accum);
+  assert (retval == result);
+}
+
+int
+main (void)
+{
+  int a[] = {0,1,2,3,4,5,6,10,11,12};
+  accum_check (a, 5, 0, 15);
+  accum_check (a, 9, 0, 54);
+  accum_check (a, 6, 0, 21);
+  accum_check (a, 6, 5, 26);
+  return 0;
+}
+
+/* { dg-final { scan-tree-dump "Loop being analyzed as uncounted." "vect" } } */
+/* { dg-final { scan-tree-dump "Detected reduction." "vect" } } */
+/* { dg-final { scan-tree-dump "vectorized 1 loops in function" "vect" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/vect-uncounted_1.c b/gcc/testsuite/gcc.dg/vect/vect-uncounted_1.c
new file mode 100644 (file)
index 0000000..e5bfbc6
--- /dev/null
@@ -0,0 +1,24 @@
+/* Check we can derive scalar IV return value from vectorized IV value,
+   resetting it on entry into the scalar epilogue loop via BIT_FIELD_REF.  */
+/* { dg-add-options vect_early_break } */
+/* { dg-do compile } */
+/* { dg-require-effective-target vect_early_break } */
+/* { dg-require-effective-target vect_int } */
+
+int
+foo (int *haystack, int needle)
+{
+  int i = 0;
+  while (1)
+    {
+      if (haystack[i] == needle)
+       return i;
+      i++;
+     }
+}
+
+/* { dg-final { scan-tree-dump "Loop being analyzed as uncounted." "vect" } } */
+/* { dg-final { scan-tree-dump "vectorized 1 loops in function" "vect" } } */
+/* Ensure we reset our scalar IV so as to repeat the last vector iteration.  */
+/* { dg-final { scan-tree-dump {_[0-9_]+ = BIT_FIELD_REF <vect_i_[0-9_.]+, [0-9]+, 0>} "vect" } } */
+
diff --git a/gcc/testsuite/gcc.dg/vect/vect-uncounted_2.c b/gcc/testsuite/gcc.dg/vect/vect-uncounted_2.c
new file mode 100644 (file)
index 0000000..33fb0ce
--- /dev/null
@@ -0,0 +1,21 @@
+/* { dg-add-options vect_early_break } */
+/* { dg-do compile } */
+/* { dg-require-effective-target vect_early_break } */
+/* { dg-require-effective-target vect_int } */
+
+int
+foo (int *a0, int *aN, int *b0, int *bN)
+{
+  int *a = a0;
+  int *b = b0;
+
+  for (;a != aN && b != bN; a++, b++)
+    *a += *b;
+}
+
+/* { dg-final { scan-tree-dump "Loop being analyzed as uncounted." "vect" } } */
+/* { dg-final { scan-tree-dump "vectorized 1 loops in function" "vect" } } */
+/* Make sure the values used in peeled epilog loop effectively reset the last vectorized iteration.  */
+/* { dg-final { scan-tree-dump {<bb ([0-9]+)>[^\n\r]*:.+# (a_[0-9]+) = PHI <a_[0-9]+\([0-9]+\).+<bb [0-9]+>[^\n\r]*:.+# a_[0-9]+ = PHI <\2\(\1\)>} "vect" } } */
+/* { dg-final { scan-tree-dump {<bb ([0-9]+)>[^\n\r]*:.+# (b_[0-9]+) = PHI <b_[0-9]+\([0-9]+\).+<bb [0-9]+>[^\n\r]*:.+# b_[0-9]+ = PHI <\2\(\1\)>} "vect" } } */
+
diff --git a/gcc/testsuite/gcc.dg/vect/vect-uncounted_3.c b/gcc/testsuite/gcc.dg/vect/vect-uncounted_3.c
new file mode 100644 (file)
index 0000000..ace2024
--- /dev/null
@@ -0,0 +1,27 @@
+/* Test the correct resetting of live out values on epilog loop entry for IV
+   when it's incremented prior to exit taken.  */
+/* { dg-add-options vect_early_break } */
+/* { dg-do compile } */
+/* { dg-require-effective-target vect_early_break } */
+/* { dg-require-effective-target vect_int } */
+
+extern int N;
+
+int
+foo (int c[N], int d[N], int a)
+{
+  int i = 0;
+  while(c[i] != 0)
+    {
+      i += 1;
+      if (d[i] == a)
+       break;
+      if (d[i] == 7)
+       break;
+    }
+  return i;
+}
+
+/* { dg-final { scan-tree-dump "Loop being analyzed as uncounted." "vect" } } */
+/* { dg-final { scan-tree-dump "BIT_FIELD_REF <vect_vec_iv_.\[0-9_\]+, \[0-9\]+, 0>" "vect" } } */
+/* { dg-final { scan-tree-dump "vectorized 1 loops in function" "vect" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/vect-uncounted_4.c b/gcc/testsuite/gcc.dg/vect/vect-uncounted_4.c
new file mode 100644 (file)
index 0000000..328dbb6
--- /dev/null
@@ -0,0 +1,22 @@
+/* Check vectorization of uncounted reductions.  */
+/* { dg-add-options vect_early_break } */
+/* { dg-do compile } */
+/* { dg-require-effective-target vect_early_break } */
+/* { dg-require-effective-target vect_int } */
+
+int
+foo (int *a0, int *aN, int accum)
+{
+  int i = 0;
+  while (1)
+    {
+      if (a0[i++] == *aN)
+       return accum;
+      accum += a0[i];
+     }
+}
+
+/* { dg-final { scan-tree-dump "Loop being analyzed as uncounted." "vect" } } */
+/* { dg-final { scan-tree-dump "Detected reduction." "vect" } } */
+/* { dg-final { scan-tree-dump "vectorized 1 loops in function" "vect" } } */
+/* { dg-final { scan-tree-dump {vect_accum_([0-9_.]+) = PHI <vect_accum_[0-9_.]+\([0-9]+\), { (0, )+0 }\([0-9]+\)>.*# vect_accum_[0-9_.]+ = PHI <vect_accum_\1\([0-9]+\)>} "vect" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/vect-uncounted_5.c b/gcc/testsuite/gcc.dg/vect/vect-uncounted_5.c
new file mode 100644 (file)
index 0000000..6b572b8
--- /dev/null
@@ -0,0 +1,20 @@
+/* Loop with undetermined increment at compile-time is treated as uncounted.  */
+/* Adapted from pr102572.cc  */
+/* { dg-add-options vect_early_break } */
+/* { dg-do compile } */
+/* { dg-require-effective-target vect_early_break } */
+/* { dg-require-effective-target vect_int } */
+
+int a, b, c, f;
+void g(bool h, int d[][5])
+{
+  int k = 0;
+  for (short i = f; i; i += 1)
+    {
+      a = h && d[0][i];
+      for (int j = 0; j < 4; j += c)
+       b++;
+    }
+}
+/* { dg-final { scan-tree-dump "Loop being analyzed as uncounted." "vect" } } */
+/* { dg-final { scan-tree-dump "vectorized 1 loops in function" "vect" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/vect-uncounted_6.c b/gcc/testsuite/gcc.dg/vect/vect-uncounted_6.c
new file mode 100644 (file)
index 0000000..a7776da
--- /dev/null
@@ -0,0 +1,24 @@
+/* Check the vectorization of existing testsuite examples  */
+/* Taken from pr109331.c  */
+/* { dg-add-options vect_early_break } */
+/* { dg-do compile } */
+/* { dg-require-effective-target vect_early_break } */
+/* { dg-require-effective-target vect_int } */
+
+char *ustol_dpp;
+void ustol(int flags)
+{
+  char *s;
+  if (s)
+    flags |= 3;
+  switch (flags & 3)
+  case 3:
+    while (*s)
+    case '+':
+      ++s;
+  if (flags)
+    ustol_dpp = s;
+}
+
+/* { dg-final { scan-tree-dump "Loop being analyzed as uncounted." "vect" } } */
+/* { dg-final { scan-tree-dump "vectorized 1 loops in function" "vect" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/vect-uncounted_7.c b/gcc/testsuite/gcc.dg/vect/vect-uncounted_7.c
new file mode 100644 (file)
index 0000000..83aa308
--- /dev/null
@@ -0,0 +1,24 @@
+/* Check the vectorization of existing testsuite examples  */
+/* Taken from pr54824.c  */
+/* { dg-additional-options "-w" } */
+/* { dg-add-options vect_early_break } */
+/* { dg-do compile } */
+/* { dg-require-effective-target vect_early_break } */
+/* { dg-require-effective-target vect_int } */
+
+void __attribute__((noreturn)) bar(void)
+{
+}
+
+void foo(int i, char *p, char *q)
+{
+  while (*p++) {
+      if (i)
+       p++;
+      if (!*q++)
+       bar();
+  }
+}
+
+/* { dg-final { scan-tree-dump "Loop being analyzed as uncounted." "vect" } } */
+/* { dg-final { scan-tree-dump "vectorized 1 loops in function" "vect" } } */