Re: [PATCH] [v2] libcpp: add an AArch64 SVE2 search_line_fast
Wilco Dijkstra <[email protected]>
| Newsgroups | gmane.comp.gcc.patches |
|---|---|
| Message-ID | <PAWPR08MB8982581ED40D9FD9D54A352683DC2@PAWPR08MB8982.eurprd08.prod.outlook.com> |
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 :-)
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);
+ data = svld1_u8 (pg, s);
+ match = svmatch_u8 (pg, data, needles);
+ return s + svcntp_b8 (pg, svbrkb_b_z (pg, match));
+}