This is an automated email from the git hooks/post-receive script.

git pushed a commit to branch master
in repository terminology.

View the commit online.

commit 29752822f6056ca4a8b405768ea47ea806100b30
Author: Cedric BAIL <[email protected]>
AuthorDate: Mon Aug 3 13:27:46 2026 -0600

    utf8: widen runs of plain ASCII a run at a time
    
    utf8_to_codepoints() walked byte by byte through text that is overwhelmingly
    plain printable ASCII, paying the lead-byte dispatch for every character of it.
    Scan for the end of the run instead, then widen the whole run in one call.
    
    Compiled in only where there is a vector kernel to call. The scalar kernel walks
    the run exactly as the byte loop below it does, so it can only pay for the same
    bytes twice: on x86_64 that measured 4-6% slower than not doing it at all on the
    SGR and unicode corpora. Gating it at runtime on simd_enabled() is worse still,
    since the run path then stays in the loop to be branched over -- that alone cost
    ~8% on plain ASCII -- so the test is #if, with simd_enabled() kept inside it for
    hardware that has the kernels.
    
    The remaining kernel calls are guarded by an inline test on the first byte and a
    minimum run length. Without the guard, input that is mostly non-ASCII pays a
    call per character to be told the run is empty, which measured as a net loss.
    
    The escape-code suite and the unit tests are registered a second time with
    TERMINOLOGY_SIMD_DISABLE set. Where there is a vector kernel that gives the
    scalar path -- what every other target runs -- the same end-to-end coverage;
    where there is no kernel to disable, the second run is a duplicate.
    
    Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
---
 src/bin/utf8.c    | 33 +++++++++++++++++++++++++++++++++
 tests/meson.build | 15 +++++++++++++++
 2 files changed, 48 insertions(+)

diff --git a/src/bin/utf8.c b/src/bin/utf8.c
index 0a1a1610..b6eec7a5 100644
--- a/src/bin/utf8.c
+++ b/src/bin/utf8.c
@@ -1,5 +1,6 @@
 #include "private.h"
 #include "utf8.h"
+#include "simd/simd.h"
 
 /* How many bytes the sequence introduced by this lead byte occupies, or 0 if it
  * cannot start one (a continuation byte, or a length this decoder will not
@@ -54,10 +55,42 @@ utf8_to_codepoints(const char *buf, int len, Eina_Unicode *codepoints,
                    int *consumed)
 {
    int i = 0, j = 0;
+#if defined(TERMINOLOGY_HAVE_NEON)
+   /* Hoisted out of the loop: simd_enabled() is a call, and what it reports
+    * cannot change mid-buffer. */
+   Eina_Bool fast = simd_enabled();
+#endif
 
    while (i < len)
      {
         Eina_Unicode g;
+#if defined(TERMINOLOGY_HAVE_NEON)
+        size_t run;
+
+        /* Plain printable ASCII needs none of the per-character work below, so
+         * widen it a run at a time. The inline test on the first byte keeps
+         * mostly-non-ASCII input from calling the scanner per character.
+         *
+         * Compiled in only where there is a vector kernel to call. The scalar
+         * kernel walks the run exactly as the loop below does, so it can only
+         * pay for the same bytes twice -- and merely leaving this in the loop
+         * to be branched over costs the decoder ~8% on a non-NEON target. */
+        if (fast &&
+            ((unsigned char)buf[i] >= 0x20) && ((unsigned char)buf[i] < 0x7f))
+          run = simd_scan_plain_ascii((const unsigned char *)buf + i,
+                                      (size_t)(len - i));
+        else
+          run = 0;
+        /* Below this the scan-then-widen pair costs more than it saves. */
+        if (run >= 4)
+          {
+             simd_widen_ascii((const unsigned char *)buf + i, run,
+                              codepoints + j);
+             i += (int)run;
+             j += (int)run;
+             continue;
+          }
+#endif
 
         if (buf[i])
           {
diff --git a/tests/meson.build b/tests/meson.build
index 25ec8267..257e1ba4 100644
--- a/tests/meson.build
+++ b/tests/meson.build
@@ -28,8 +28,23 @@ if tests
          timeout: 600)
   endforeach
 
+  # Again with the vector kernels off, so the scalar path -- what non-NEON
+  # targets run -- has end-to-end coverage too.
+  test('escape-codes-scalar',
+       run_tests,
+       args: ['-v',
+              '-t', tytest.full_path(),
+              '-r', meson.current_source_dir() / 'tests.results',
+              '-d', meson.current_source_dir()],
+       env: {'TERMINOLOGY_SIMD_DISABLE': '1'},
+       depends: tytest,
+       workdir: meson.current_source_dir(),
+       timeout: 300)
+
   # The in-process C unit tests compiled into tytest itself.
   test('unit', tytest, args: ['all'], timeout: 120)
+  test('unit-scalar', tytest, args: ['all'],
+       env: {'TERMINOLOGY_SIMD_DISABLE': '1'}, timeout: 120)
 endif
 
 if benchmarks

-- 
To stop receiving notification emails like this one, please contact
the administrator of this repository.

Reply via email to