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));
+}
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.