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 011570e65fc2d66fab1c31965723aad72684066d
Author: Cedric BAIL <[email protected]>
AuthorDate: Mon Aug 3 13:27:46 2026 -0600

    simd: add the ASCII widening kernel
    
    The other half of what the decoder needs: bytes already known to be plain
    printable ASCII, zero-extended into codepoints. NEON gets there in two widening
    steps per half, 8 -> 16 -> 32 bits, four stores per sixteen bytes.
    
    Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
---
 src/bin/simd/simd.c        | 52 ++++++++++++++++++++++++++++++++++++++++++++++
 src/bin/simd/simd.h        |  9 ++++++++
 src/bin/simd/simd_neon.c   | 21 +++++++++++++++++++
 src/bin/simd/simd_scalar.c |  9 ++++++++
 4 files changed, 91 insertions(+)

diff --git a/src/bin/simd/simd.c b/src/bin/simd/simd.c
index 81de04f3..78de8b09 100644
--- a/src/bin/simd/simd.c
+++ b/src/bin/simd/simd.c
@@ -37,6 +37,19 @@ simd_scan_plain_ascii(const unsigned char *buf, size_t len)
 #endif
    return simd_scan_plain_ascii_scalar(buf, len);
 }
+
+void
+simd_widen_ascii(const unsigned char *buf, size_t len, Eina_Unicode *out)
+{
+#if defined(TERMINOLOGY_HAVE_NEON)
+   if (EINA_LIKELY(_use_simd))
+     {
+        simd_widen_ascii_neon(buf, len, out);
+        return;
+     }
+#endif
+   simd_widen_ascii_scalar(buf, len, out);
+}
 /* Parity tests: each vector kernel must agree with its scalar reference.
  *
  * Buffers are guard-padded so a kernel writing outside its range fails even
@@ -144,6 +157,44 @@ _test_scan(void)
      }
 }
 
+static void
+_test_widen(void)
+{
+   size_t len, off, i;
+
+   for (len = 0; len <= 70; len++)
+     {
+        for (off = 0; off < 16; off++)
+          {
+             unsigned char *base = _alloc_guarded(off + len);
+             unsigned char *p = base + GUARD + off;
+             Eina_Unicode *o1 = calloc(len + 8, sizeof(Eina_Unicode));
+             Eina_Unicode *o2 = calloc(len + 8, sizeof(Eina_Unicode));
+
+             assert(o1 != NULL);
+             assert(o2 != NULL);
+             _fill(p, len, 0);
+             for (i = 0; i < 8; i++)
+               {
+                  o1[len + i] = 0xdeadbeef;
+                  o2[len + i] = 0xdeadbeef;
+               }
+
+             simd_widen_ascii_scalar(p, len, o1);
+             simd_widen_ascii_neon(p, len, o2);
+
+             assert(memcmp(o1, o2, (len + 8) * sizeof(Eina_Unicode)) == 0);
+             for (i = 0; i < 8; i++)
+               assert(o2[len + i] == 0xdeadbeef);
+             assert(_guards_intact(base, off + len));
+
+             free(base);
+             free(o1);
+             free(o2);
+          }
+     }
+}
+
 /* Every byte value, at every position, exhaustively. */
 static void
 _test_every_byte(void)
@@ -175,6 +226,7 @@ tytest_simd_parity(void)
 {
 #if defined(TERMINOLOGY_HAVE_NEON)
    _test_scan();
+   _test_widen();
    _test_every_byte();
 #endif
    /* Without a vector kernel the scalar path is the only path. */
diff --git a/src/bin/simd/simd.h b/src/bin/simd/simd.h
index ded8372e..e64e93e4 100644
--- a/src/bin/simd/simd.h
+++ b/src/bin/simd/simd.h
@@ -21,6 +21,15 @@ size_t simd_scan_plain_ascii_scalar(const unsigned char *buf, size_t len);
 size_t simd_scan_plain_ascii_neon(const unsigned char *buf, size_t len);
 #endif
 
+/* Widen bytes already known to be plain printable ASCII into codepoints. */
+void simd_widen_ascii(const unsigned char *buf, size_t len, Eina_Unicode *out);
+void simd_widen_ascii_scalar(const unsigned char *buf, size_t len,
+                             Eina_Unicode *out);
+#if defined(TERMINOLOGY_HAVE_NEON)
+void simd_widen_ascii_neon(const unsigned char *buf, size_t len,
+                           Eina_Unicode *out);
+#endif
+
 /* Read TERMINOLOGY_SIMD_DISABLE, which switches the vector kernels off without
  * a rebuild. Modelled on EFL's EVAS_NEON_DISABLE. */
 void simd_init(void);
diff --git a/src/bin/simd/simd_neon.c b/src/bin/simd/simd_neon.c
index ab6f88b7..6ed4066f 100644
--- a/src/bin/simd/simd_neon.c
+++ b/src/bin/simd/simd_neon.c
@@ -44,5 +44,26 @@ simd_scan_plain_ascii_neon(const unsigned char *buf, size_t len)
    return len;
 }
 
+void
+simd_widen_ascii_neon(const unsigned char *buf, size_t len, Eina_Unicode *out)
+{
+   size_t i = 0;
+
+   for (; i + 16 <= len; i += 16)
+     {
+        uint8x16_t v = vld1q_u8(buf + i);
+        /* Zero-extend 8 -> 16 -> 32 bits in two steps per half. */
+        uint16x8_t w0 = vmovl_u8(vget_low_u8(v));
+        uint16x8_t w1 = vmovl_u8(vget_high_u8(v));
+
+        vst1q_u32((uint32_t *)(out + i +  0), vmovl_u16(vget_low_u16(w0)));
+        vst1q_u32((uint32_t *)(out + i +  4), vmovl_u16(vget_high_u16(w0)));
+        vst1q_u32((uint32_t *)(out + i +  8), vmovl_u16(vget_low_u16(w1)));
+        vst1q_u32((uint32_t *)(out + i + 12), vmovl_u16(vget_high_u16(w1)));
+     }
+
+   for (; i < len; i++)
+     out[i] = buf[i];
+}
 
 #endif
diff --git a/src/bin/simd/simd_scalar.c b/src/bin/simd/simd_scalar.c
index f36098ce..0045088f 100644
--- a/src/bin/simd/simd_scalar.c
+++ b/src/bin/simd/simd_scalar.c
@@ -16,3 +16,12 @@ simd_scan_plain_ascii_scalar(const unsigned char *buf, size_t len)
      }
    return len;
 }
+
+void
+simd_widen_ascii_scalar(const unsigned char *buf, size_t len, Eina_Unicode *out)
+{
+   size_t i;
+
+   for (i = 0; i < len; i++)
+     out[i] = buf[i];
+}

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

Reply via email to