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.