[PATCH 1/2] string: Speed up strcmp test data initialization

Magnus Lindholm <[email protected]> Wed, 5 Aug 2026 23:14:58 +0200
Newsgroups gmane.comp.lib.glibc.alpha
Message-ID <[email protected]>
The strcmp and strncmp tests repeatedly initialize large buffers for
many combinations of lengths and alignments.  The existing loops
perform a remainder operation and two individual stores for every
element.

Generate at most max_char elements using an additive recurrence.  The
recurrence produces the same sequence as the existing multiplication
and remainder expression.  Expand this initial pattern using bulk
copies, and then copy the completed first buffer to the second buffer.

This preserves the generated test data while substantially reducing
the initialization cost on slower systems.

The change also applies to the wcscmp and wcsncmp tests, which include
the same test sources.

Signed-off-by: Magnus Lindholm <[email protected]>
---
 string/test-strcmp.c  | 28 ++++++++++++++++++++++++++--
 string/test-strncmp.c | 28 ++++++++++++++++++++++++++--
 2 files changed, 52 insertions(+), 4 deletions(-)

diff --git a/string/test-strcmp.c b/string/test-strcmp.c
index 76ccff46e2..ca52827b11 100644
--- a/string/test-strcmp.c
+++ b/string/test-strcmp.c
@@ -156,6 +156,10 @@ do_test (size_t align1, size_t align2, size_t len, int max_char,
          int exp_result)
 {
   size_t i;
+  size_t value = 0;
+  size_t pattern_len;
+  size_t step
+    = (23U << ((CHARBYTES - 1) * 8)) % (size_t) max_char;
 
   CHAR *s1, *s2;
 
@@ -179,8 +183,28 @@ do_test (size_t align1, size_t align2, size_t len, int max_char,
   i = align2 + CHARBYTES * (len + 2);
   s2 = (CHAR *)(buf2 + ((page_size - i) / 16 * 16) + align2);
 
-  for (i = 0; i < len; i++)
-    s1[i] = s2[i] = 1 + (23 << ((CHARBYTES - 1) * 8)) * i % max_char;
+  /* The generated sequence repeats after at most max_char elements.  */
+  pattern_len
+    = len < (size_t) max_char ? len : (size_t) max_char;
+
+  for (i = 0; i < pattern_len; i++)
+    {
+      s1[i] = 1 + value;
+
+      value += step;
+      if (value >= (size_t) max_char)
+        value -= max_char;
+    }
+
+  while (i < len)
+    {
+      size_t copy = i < len - i ? i : len - i;
+
+      MEMCPY (s1 + i, s1, copy);
+      i += copy;
+    }
+
+  MEMCPY (s2, s1, len);
 
   s1[len] = s2[len] = 0;
   s1[len + 1] = 23;
diff --git a/string/test-strncmp.c b/string/test-strncmp.c
index 54ada39eb2..9da0f21f60 100644
--- a/string/test-strncmp.c
+++ b/string/test-strncmp.c
@@ -190,6 +190,9 @@ do_test_n (size_t align1, size_t align2, size_t len, size_t n, int n_in_bounds,
 {
   size_t i, buf_bound;
   CHAR *s1, *s2, *s1_end, *s2_end;
+  size_t value = 0;
+  size_t pattern_len;
+  size_t step = (23U << ((CHARBYTES - 1) * 8)) % (size_t) max_char;
 
   align1 &= ~(CHARBYTES - 1);
   align2 &= ~(CHARBYTES - 1);
@@ -216,8 +219,29 @@ do_test_n (size_t align1, size_t align2, size_t len, size_t n, int n_in_bounds,
       s2[n] = 23;
     }
 
-  for (i = 0; i < buf_bound; i++)
-    s1[i] = s2[i] = 1 + (23 << ((CHARBYTES - 1) * 8)) * i % max_char;
+  /* The generated sequence repeats after at most max_char elements.  */
+  pattern_len
+    = buf_bound < (size_t) max_char
+      ? buf_bound : (size_t) max_char;
+
+  for (i = 0; i < pattern_len; i++)
+    {
+      s1[i] = 1 + value;
+
+      value += step;
+      if (value >= (size_t) max_char)
+        value -= max_char;
+    }
+
+  while (i < buf_bound)
+    {
+      size_t copy = i < buf_bound - i ? i : buf_bound - i;
+
+      MEMCPY (s1 + i, s1, copy);
+      i += copy;
+    }
+
+  MEMCPY (s2, s1, buf_bound);
 
   s1[len] = 0;
   s2[len] = 0;
-- 
2.53.0