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

Reply via email to