Re: [PATCH 2/2] string: Speed up strcasecmp test data initialization

Adhemerval Zanella Netto <[email protected]> Fri, 7 Aug 2026 10:35:55 -0300
Newsgroups gmane.comp.lib.glibc.alpha
Organization Linaro
Message-ID <[email protected]>

On 05/08/26 18:14, Magnus Lindholm wrote:
> The strcasecmp and strncasecmp tests repeatedly initialize large
> buffers for many combinations of lengths and alignments.  The existing
> loops perform a remainder operation and call toupper and tolower for
> every element.
> 
> Generate at most max_char elements using an additive recurrence and
> apply the case conversions while creating this initial pattern.  The
> recurrence produces the same sequence as the existing multiplication
> and remainder expression.  Expand the completed pattern using bulk
> copies.
> 
> This preserves the generated test data and locale-dependent case
> conversion while substantially reducing the initialization cost on
> slower systems.
> 
> Signed-off-by: Magnus Lindholm <[email protected]>

Nice catch, LTGM.

Reviewed-by: Adhemerval Zanella  <[email protected]>

> ---
>  string/test-strcasecmp.c  | 22 ++++++++++++++++++++--
>  string/test-strncasecmp.c | 23 +++++++++++++++++++++--
>  2 files changed, 41 insertions(+), 4 deletions(-)
> 
> diff --git a/string/test-strcasecmp.c b/string/test-strcasecmp.c
> index a5235fa1bb..d090dcbf36 100644
> --- a/string/test-strcasecmp.c
> +++ b/string/test-strcasecmp.c
> @@ -63,6 +63,9 @@ 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 step = 23U % (size_t) max_char;
> +  size_t pattern_len;
>    char *s1, *s2;
>  
>    if (len == 0)
> @@ -80,10 +83,25 @@ do_test (size_t align1, size_t align2, size_t len, int max_char,
>    s1 = (char *) (buf1 + align1);
>    s2 = (char *) (buf2 + align2);
>  
> -  for (i = 0; i < len; i++)
> +  pattern_len
> +    = len < (size_t) max_char ? len : (size_t) max_char;
> +
> +  for (i = 0; i < pattern_len; i++)
>      {
> -      s1[i] = toupper (1 + 23 * i % max_char);
> +      s1[i] = toupper (1 + value);
>        s2[i] = tolower (s1[i]);
> +      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);
> +      memcpy (s2 + i, s2, copy);
> +      i += copy;
>      }
>  
>    s1[len] = s2[len] = 0;
> diff --git a/string/test-strncasecmp.c b/string/test-strncasecmp.c
> index 035c680532..6b00113e66 100644
> --- a/string/test-strncasecmp.c
> +++ b/string/test-strncasecmp.c
> @@ -83,6 +83,9 @@ do_test (size_t align1, size_t align2, size_t n, size_t len, int max_char,
>  	 int exp_result)
>  {
>    size_t i;
> +  size_t value = 0;
> +  size_t step = 23U % (size_t) max_char;
> +  size_t pattern_len;
>    char *s1, *s2;
>  
>    if (len == 0)
> @@ -100,10 +103,26 @@ do_test (size_t align1, size_t align2, size_t n, size_t len, int max_char,
>    s1 = (char *) (buf1 + align1);
>    s2 = (char *) (buf2 + align2);
>  
> -  for (i = 0; i < len; i++)
> +  pattern_len
> +    = len < (size_t) max_char ? len : (size_t) max_char;
> +
> +  for (i = 0; i < pattern_len; i++)
>      {
> -      s1[i] = toupper (1 + 23 * i % max_char);
> +      s1[i] = toupper (1 + value);
>        s2[i] = tolower (s1[i]);
> +
> +      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);
> +      memcpy (s2 + i, s2, copy);
> +      i += copy;
>      }
>  
>    s1[len] = s2[len] = 0;