Re: [PATCH 16/20] alpha: add vectorized single-char fast path for strspn

Matt Turner <[email protected]>
Newsgroups gmane.comp.lib.glibc.alpha
Message-ID <CAEdQ38FEKPJ8UO+21BF+wVa=NML8rszXcx=1UD9HxYbwoQ+AGA@mail.gmail.com>
On Wed, Aug 12, 2026 at 4:05 PM Adhemerval Zanella Netto
<[email protected]> wrote:
>
>
>
> On 11/08/26 22:19, Matt Turner wrote:
> > The generic strspn's single-accept-char case was a byte-at-a-time scalar
> > loop. Alpha has no hand-tuned strspn at all, so add one: the single-char
> > case now scans a word at a time via cmpbge, finding the first byte that
> > differs from the broadcast accept character (a NUL byte always differs
> > from a non-NUL accept char, so this doubles as the string end check with
> > no separate test). The multi-char case keeps the existing bitmap-table
> > scan unchanged -- already efficient, nothing to gain there.
> >
> > Measured on an EV68CB against the old scalar loop: 4.3x faster at 64B,
> > 5.5-5.7x at 256B, ~6.8x at 4KB, ~7.7-7.8x at 64KB, converging toward the
> > 8x ceiling the word width sets. Correctness verified against a reference
> > scan at lengths 0 to 255 and all eight starting byte alignments,
> > including runs that cross a word boundary and strings with a leading
> > mismatch.
>
> Why can't we optimize the generic implementation, instead of adding an
> arch-specific code? Richard Henderson, Wilco, and myself have done a lot
> of optimization on generic code to avoid the need of such code.
>
> The 'cmpbge' is already modeled by find_zero_ne_all (sysdeps/alpha/string-fza.h),
> along with index_first (sysdeps/alpha/string-fzi.h) which will use cttz for
> __alpha_cix__.
>
> So we can expand the generic implementation as:
>
> --
> diff --git a/string/strspn.c b/string/strspn.c
> index 9b90ae61e70..f01f9bbb32c 100644
> --- a/string/strspn.c
> +++ b/string/strspn.c
> @@ -18,6 +18,9 @@
>  #include <string.h>
>  #include <stdint.h>
>  #include <libc-pointer-arith.h>
> +#include <string-fzc.h>
> +#include <string-fzi.h>
> +#include <string-shift.h>
>
>  #undef strspn
>  #ifndef STRSPN
> @@ -33,9 +36,24 @@ STRSPN (const char *str, const char *accept)
>      return 0;
>    if (__glibc_unlikely (accept[1] == '\0'))
>      {
> -      const char *a = str;
> -      for (; *str == *accept; str++);
> -      return str - a;
> +      /* Skip bytes equal to ACCEPT[0] one word at a time, stopping at the
> +        first byte that differs from it.  */
> +      uintptr_t s_int = (uintptr_t) str;
> +      const op_t *word_ptr
> +       = (const op_t *) PTR_ALIGN_DOWN (str, sizeof (op_t));
> +      op_t repeated_c = repeat_bytes (accept[0]);
> +
> +      op_t word = *word_ptr;
> +      find_t mask = shift_find (find_zero_ne_all (word, repeated_c), s_int);
> +      if (mask != 0)
> +       return index_first (mask);
> +
> +      do
> +       word = *++word_ptr;
> +      while (find_zero_ne_all (word, repeated_c) == 0);
> +
> +      return (const char *) word_ptr - str
> +            + index_first_zero_ne (word, repeated_c);
>      }
>
>    /* Use multiple small memsets to enable inlining on most targets.  */
> --
>
> And this have the extra advantage of optimization not only alpha, but potentially
> all other ABIs that uses the generic implementation.

Absolutely. I'll send a patch against the generic implementation and
remove this patch from the alpha-specific series.

Thanks!
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.