libcpp: Improve search_line_sve2

Wilco Dijkstra <[email protected]>
Newsgroups gmane.comp.gcc.patches
Message-ID <PAWPR08MB8982EC14365CA17D03D181C083A52@PAWPR08MB8982.eurprd08.prod.outlook.com>
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?

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;
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.