Re: libcpp: Improve search_line_sve2
Kyrylo Tkachov <[email protected]>
| Newsgroups | gmane.comp.gcc.patches |
|---|---|
| Message-ID | <[email protected]> |
> On 19 Aug 2026, at 23:09, Wilco Dijkstra <[email protected]> wrote: > > > Improve search_line_sve2() - like the AdvSIMD version, loop until a match is > found even if the input pointer is unaligned or close to the end. This relies > on CPP_BUFFER_PADDING >= 256 (maximum SVE vector length) and *end containing a > match. The resulting code is both simpler and faster. > > Performance is ~1-2% better on a huge trace that replays the calls from libcpp. > > Passes bootstrap, OK for commit? Ok. Thanks for improving it. Kyrill > > libcpp/ChangeLog: > > * lex.cc (search_line_sve): Improve. > > --- > > diff --git a/libcpp/lex.cc b/libcpp/lex.cc > index bd35e28ce8f40a33e94f560b510107d49477d44d..047765fe733f028a663fe95c6bc206c9c4ee228f 100644 > --- a/libcpp/lex.cc > +++ b/libcpp/lex.cc > @@ -758,18 +758,19 @@ done: > into a byte index, in place of the bitmask the Neon version has to > build and move to a general register. > > - Unlike the Neon version this one needs neither alignment nor a > - page-crossing test. Full-vector loads run while S is at or below > - END rounded down to a vector boundary, so they may extend a little > - past *END into the tail padding; a single predicated vector then > - covers any remainder. The newline that _cpp_convert_input forces > - at *END still terminates the scan. > + Loop until a match is found even if the input pointer is unaligned > + or close to the end. Since this may overread, it relies on *end > + containing a match and CPP_BUFFER_PADDING >= 256 (maximum SVE vector > + length). > > The loop consumes svcntb () bytes per iteration, so it scales with the > implemented vector length. */ > > +/* Unaligned loads, potentially using padding after the final newline. */ > +static_assert (CPP_BUFFER_PADDING >= 256, ""); > + > static const uchar * __attribute__ ((target ("+sve2"))) > -search_line_sve2 (const uchar *s, const uchar *end) > +search_line_sve2 (const uchar *s, const uchar *end ATTRIBUTE_UNUSED) > { > /* Order within a segment is irrelevant to MATCH, which tests set > membership, so this needs no adjustment for big-endian. */ > @@ -777,34 +778,20 @@ search_line_sve2 (const uchar *s, const uchar *end) > | ((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; > - > - /* Unaligned loads, potentially using padding after the final newline. */ > - static_assert (CPP_BUFFER_PADDING >= 256, ""); > > - /* Align END down to a vector boundary so the loop can consume on > - average half a vector more near the end. */ > - limit = (uintptr_t) end & -vl; > + svuint8_t data = svld1_u8 (all, s); > + svbool_t match = svmatch_u8 (all, data, needles); > + if (__builtin_expect (svptest_any (all, match), 1)) > + return s + svcntp_b8 (all, svbrkb_b_z (all, match)); > > - while ((uintptr_t) s <= limit) > + while (1) > { > + s += svcntb (); > data = svld1_u8 (all, s); > match = svmatch_u8 (all, data, needles); > - if (svptest_any (all, match)) > + if (__builtin_expect (svptest_any (all, match), 1)) > 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 ((uintptr_t) s, (uintptr_t) end); > - data = svld1_u8 (pg, s); > - match = svmatch_u8 (pg, data, needles); > - return s + svcntp_b8 (pg, svbrkb_b_z (pg, match)); > } > > static bool lexer_has_sve2; >