Re: [PATCH] [v2] libcpp: add an AArch64 SVE2 search_line_fast
Kyrylo Tkachov <[email protected]>
| Newsgroups | gmane.comp.gcc.patches |
|---|---|
| Message-ID | <[email protected]> |
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)); > +}