Re: [PATCH] libcpp: Optimize AArch64 search_line_fast

Alexander Monakov <[email protected]>
Newsgroups gmane.comp.gcc.patches
Message-ID <[email protected]>
On Wed, 12 Aug 2026, Wilco Dijkstra wrote:

> Performance is significantly better as a result: 48% faster on Neoverse N1,
> 67% on Neoverse V1 and 69% on Neoverse V2.

It is a bit strange to see exact numbers without a mention of the workload.
It is not very surprising that the new loop runs 2x-3x faster on modern CPUs,
but if you're showing exact percentages, can you say how you measured them,
please?

> Passes bootstrap, OK for commit?
> 
> libcpp/ChangeLog:
> 
>         (search_line_fast): New optimized AdvSIMD implementation.

'* lex.cc' looks missing at the start of entry.

> +   Typical statistics for number of characters till a match:
> +    1-15: 30.9%
> +   16-31: 22.2%
> +   32-47: 18.3%
> +   48-63: 14.1%
> +   64-79: 13.0%
> +   80-95:  1.1%
> +     >96:  0.3%

Yeah. When working on x86 SSSE3 implementation I noticed that at 16 characters
per iteration, the branch that exits the loop tends to be pretty unpredictable
on "typical" C++ sources, so moving to 32 characters per iteration helped with
that a bit, even with 16-byte vectors (so two vector loads per iteration, etc)

I wonder if you looked at something like that? Doing two 16-character matches
per one iteration, then combining results into one GPR for the final CBZ?
Not sure if there's a way to make the epilogue cheap enough, though.

> +   To get good performance, what matters is to quickly get the match result
> +   for the first few vectors with minimal initialization overhead.  Hence we
> +   simply loop using the unaligned input till we get close to the end.  */

I don't see why you want to switch to an aligned load at the end. x86 relies
on sufficient padding to make unaligned loads all the way. One more issue with
that:

> +  const uchar *limit = (const uchar*) ((uintptr_t)end & ~15);

This is not safe in absence of padding: when 's' itself is not aligned,
and 'end' is close to it, this may move 'limit' to before 's', and then
the load from *limit will pick up bytes prior to 's'.

Now, libcpp provides sufficient tail padding (at least 16 bytes, with '\n'
at the beginning of padding area) so in context this is safe, but then
the final aligned load should never be reached, and computing 'limit' is
pointless.

Alexander
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.