On 12/4/25 10:24, Tamar Christina wrote:
Hi Victor,

-----Original Message-----
From: Victor Do Nascimento <[email protected]>
Sent: 03 December 2025 17:22
To: [email protected]
Cc: Tamar Christina <[email protected]>; [email protected]; Victor
Do Nascimento <[email protected]>
Subject: [PATCH v3] vect: Add uncounted loop unit tests

New in this revision:

   - Cleanup previously proposed tests
   - Add new tests

------------
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.
---
  .../gcc.dg/gomp/static-chunk-size-one.c       |  2 +-
  .../gcc.dg/vect/vect-early-break_40.c         |  3 +-
  gcc/testsuite/gcc.dg/vect/vect-uncounted-1.c  | 24 ++++++++
  gcc/testsuite/gcc.dg/vect/vect-uncounted-2.c  | 21 +++++++
  gcc/testsuite/gcc.dg/vect/vect-uncounted-3.c  | 27 +++++++++
  gcc/testsuite/gcc.dg/vect/vect-uncounted-4.c  | 22 ++++++++
  gcc/testsuite/gcc.dg/vect/vect-uncounted-5.c  | 20 +++++++
  gcc/testsuite/gcc.dg/vect/vect-uncounted-6.c  | 24 ++++++++
  gcc/testsuite/gcc.dg/vect/vect-uncounted-7.c  | 24 ++++++++
  .../vect/vect-uncounted-prolog-peel-1.c       | 23 ++++++++
  .../gcc.dg/vect/vect-uncounted-run-1.c        | 55 +++++++++++++++++++
  .../gcc.dg/vect/vect-uncounted-run-2.c        | 38 +++++++++++++
  .../gcc.dg/vect/vect-uncounted-run-3.c        | 40 ++++++++++++++
  13 files changed, 320 insertions(+), 3 deletions(-)
  create mode 100644 gcc/testsuite/gcc.dg/vect/vect-uncounted-1.c
  create mode 100644 gcc/testsuite/gcc.dg/vect/vect-uncounted-2.c
  create mode 100644 gcc/testsuite/gcc.dg/vect/vect-uncounted-3.c
  create mode 100644 gcc/testsuite/gcc.dg/vect/vect-uncounted-4.c
  create mode 100644 gcc/testsuite/gcc.dg/vect/vect-uncounted-5.c
  create mode 100644 gcc/testsuite/gcc.dg/vect/vect-uncounted-6.c
  create mode 100644 gcc/testsuite/gcc.dg/vect/vect-uncounted-7.c
  create mode 100644 gcc/testsuite/gcc.dg/vect/vect-uncounted-prolog-peel-
1.c
  create mode 100644 gcc/testsuite/gcc.dg/vect/vect-uncounted-run-1.c
  create mode 100644 gcc/testsuite/gcc.dg/vect/vect-uncounted-run-2.c
  create mode 100644 gcc/testsuite/gcc.dg/vect/vect-uncounted-run-3.c

diff --git a/gcc/testsuite/gcc.dg/gomp/static-chunk-size-one.c
b/gcc/testsuite/gcc.dg/gomp/static-chunk-size-one.c
index e82de772deb..12b508657fa 100644
--- a/gcc/testsuite/gcc.dg/gomp/static-chunk-size-one.c
+++ b/gcc/testsuite/gcc.dg/gomp/static-chunk-size-one.c
@@ -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" } */

This one seems weird, how come you're turning off the vectorizer in OMP test?

Dejagnu test for the unit test:

/* { dg-final { scan-tree-dump-times "PHI" 3 "optimized" } } */

The test is about parallelizing work over threads.  It checks for the
number of PHI nodes under the assumption that the work is done with a
scalar loop in each thread.  If you don't turn off the vectorizer,
you start to get autovectorization in x86 (which changes the no. of PHI
nodes, causing the test to fail there), but no autovec in AArch64, where
the test still passes.

Therefore, to get consistency across targets, ensuring the test executes
as before, it is appropriate to turn off autovec.

Cheers,
Victor


  int
  bar ()
diff --git a/gcc/testsuite/gcc.dg/vect/vect-early-break_40.c
b/gcc/testsuite/gcc.dg/vect/vect-early-break_40.c
index 428f6249fa6..9c0e1fb1264 100644
--- a/gcc/testsuite/gcc.dg/vect/vect-early-break_40.c
+++ b/gcc/testsuite/gcc.dg/vect/vect-early-break_40.c
@@ -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-1.c
b/gcc/testsuite/gcc.dg/vect/vect-uncounted-1.c
new file mode 100644
index 00000000000..e5bfbc64527
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/vect-uncounted-1.c
@@ -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 } */

Tests in the vect/ directory don't specify the action, they're detected 
automatically
so drop this and the run from the tests

+/* { 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
index 00000000000..33fb0ce1f0d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/vect-uncounted-2.c
@@ -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
index 00000000000..ace20240663
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/vect-uncounted-3.c
@@ -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
index 00000000000..0544e321233
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/vect-uncounted-4.c
@@ -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, 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
index 00000000000..6b572b812e0
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/vect-uncounted-5.c
@@ -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
index 00000000000..a7776da24c5
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/vect-uncounted-6.c
@@ -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
index 00000000000..83aa3085ce7
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/vect-uncounted-7.c
@@ -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" } } */
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
index 00000000000..fab4ed0f569
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/vect-uncounted-prolog-peel-1.c
@@ -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
index 00000000000..ff09d955d34
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/vect-uncounted-run-1.c
@@ -0,0 +1,55 @@
+/* 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 run } */
+/* { dg-require-effective-target vect_early_break } */

Run tests need to check vect_early_break_hw instead.
Also include `tree-vect.h`

+/* { dg-require-effective-target vect_int } */
+
+#include <assert.h>
+
+#define N 128
+#define VAL 13
+
+int

It's also useful to add __attribute__((nopia)) to these
So that there's no possibility of them being inlined and
optimized away.

+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 ()
+{

And call check_vect () in main to initialize things.

Thanks,
Tamar

+  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
index 00000000000..7e38b7c6701
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/vect-uncounted-run-2.c
@@ -0,0 +1,38 @@
+/* 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 } */
+/* { dg-require-effective-target vect_int } */
+
+#include <assert.h>
+#define N 9
+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
index 00000000000..45fcda39854
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/vect-uncounted-run-3.c
@@ -0,0 +1,40 @@
+/* Check vectorization of uncounted reductions.  */
+/* { dg-add-options vect_early_break } */
+/* { dg-do run } */
+/* { dg-require-effective-target vect_early_break } */
+/* { dg-require-effective-target vect_int } */
+#include <assert.h>
+
+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" } } */
--
2.43.0


Reply via email to