Hi Wilco,
> On 12 Aug 2026, at 18:59, Wilco Dijkstra <[email protected]> wrote:
>
> Hi Kyrill,
>
>> SVE2 does the whole thing in far fewer instructions and, being
>> vector-length agnostic, keeps scaling on implementations wider than
>> 128 bits. Every 128-bit segment of the needle vector holds the four
>> characters, so a single MATCH reports set membership for the whole
>> vector, and MATCH sets the condition flags directly, so the loop branch
>> needs no reduction. BRKB and INCP then convert the result predicate
>> straight into a pointer increment.
>
> Looks great now - just 2 minor things below (but it's fine for commit either
> way).
>
> You might also want to try out my optimized AdvSIMD version at
> https://gcc.gnu.org/pipermail/gcc-patches/2026-August/727347.html :-)
Great! I’ll have a look.
>
> Cheers,
> Wilco
>
> +static const uchar * __attribute__ ((target ("+sve2")))
> +search_line_sve2 (const uchar *s, const uchar *end)
> +{
> + /* Order within a segment is irrelevant to MATCH, which tests set
> + membership, so this needs no adjustment for big-endian. */
> + const uint32_t chars = ((uint32_t) '\n' | ((uint32_t) '\r' << 8)
> + | ((uint32_t) '\\' << 16) | ((uint32_t) '?' << 24));
> + const svuint8_t needles = svreinterpret_u8_u32 (svdup_n_u32 (chars));
> + const svbool_t all = svptrue_b8 ();
> + const uint64_t vl = svcntb ();
> + svuint8_t data;
> + svbool_t match;
> + uintptr_t limit;
> +
> + /* The last address from which a whole vector still lies below END.
> + Computed on integers so that a buffer shorter than a vector simply
> + skips the loop. */
> + limit = (uintptr_t) end;
> + limit = limit >= vl ? limit - vl : 0;
>
> Why not: limit = (uintptr_t) end & -vl; ?
>
> That's simpler and allows the loop to process 0.5VL more data near the end.
>
> + while ((uintptr_t) s <= limit)
> + {
> + data = svld1_u8 (all, s);
> + match = svmatch_u8 (all, data, needles);
> + if (svptest_any (all, match))
> + return s + svcntp_b8 (all, svbrkb_b_z (all, match));
> + s += vl;
> + }
> +
> + /* What is left, up to and including *END, which _cpp_convert_input
> + forces to a newline. That guarantees a match, so no further test is
> + needed. */
> + svbool_t pg = svwhilele_b8_u64 ((uint64_t) (uintptr_t) s,
> + (uint64_t) (uintptr_t) end);
>
> Why the double casting? It could just be svwhilele_b8_u64 ((uintptr_t) s,
> (uintptr_t) end);
Thanks, I’ve adjusted both and pushed as
ad3f5b0855ef5f3efd6b0a13c29f98cdbf598eb7
Kyrill
>
> + data = svld1_u8 (pg, s);
> + match = svmatch_u8 (pg, data, needles);
> + return s + svcntp_b8 (pg, svbrkb_b_z (pg, match));
> +}