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!