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 563f62a3ea076e3825de7bd814d4e889f79fbdb1
Author: Cedric BAIL <[email protected]>
AuthorDate: Mon Aug 3 13:27:46 2026 -0600
simd: add the codepoint plain-ASCII scan kernel
The same question as the byte scan, over already-decoded codepoints, for the
callers that hold cells rather than bytes. One unsigned compare instead of two:
g - 0x20 wraps for anything below 0x20, pushing it above the 0x5e span that
0x20..0x7e occupies.
No caller yet -- the cell-write path takes it up.
Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
---
src/bin/simd/simd.c | 85 ++++++++++++++++++++++++++++++++++++++++++++++
src/bin/simd/simd.h | 7 ++++
src/bin/simd/simd_neon.c | 30 ++++++++++++++++
src/bin/simd/simd_scalar.c | 14 ++++++++
4 files changed, 136 insertions(+)
diff --git a/src/bin/simd/simd.c b/src/bin/simd/simd.c
index 78de8b09..9e98572d 100644
--- a/src/bin/simd/simd.c
+++ b/src/bin/simd/simd.c
@@ -38,6 +38,16 @@ simd_scan_plain_ascii(const unsigned char *buf, size_t len)
return simd_scan_plain_ascii_scalar(buf, len);
}
+size_t
+simd_scan_plain_ascii_u32(const Eina_Unicode *buf, size_t len)
+{
+#if defined(TERMINOLOGY_HAVE_NEON)
+ if (EINA_LIKELY(_use_simd))
+ return simd_scan_plain_ascii_u32_neon(buf, len);
+#endif
+ return simd_scan_plain_ascii_u32_scalar(buf, len);
+}
+
void
simd_widen_ascii(const unsigned char *buf, size_t len, Eina_Unicode *out)
{
@@ -157,6 +167,53 @@ _test_scan(void)
}
}
+static void
+_test_scan_u32(void)
+{
+ size_t len, off, i;
+ int density;
+
+ for (len = 0; len <= 40; len++)
+ {
+ for (density = 0; density <= 100; density += 10)
+ {
+ for (off = 0; off < 8; off++)
+ {
+ /* Guarded in bytes, so an overread past the payload lands in
+ * guard bytes rather than in slack. */
+ unsigned char *base =
+ _alloc_guarded((off + len) * sizeof(Eina_Unicode));
+ Eina_Unicode *p = (Eina_Unicode *)(base + GUARD) + off;
+
+ for (i = 0; i < len; i++)
+ {
+ if ((int)(_rnd() % 100) < density)
+ {
+ switch (_rnd() % 7)
+ {
+ case 0: p[i] = 0x00; break;
+ case 1: p[i] = 0x1f; break;
+ case 2: p[i] = 0x7f; break;
+ case 3: p[i] = 0x80; break;
+ case 4: p[i] = 0x4e2d; break;
+ case 5: p[i] = 0x1f600; break;
+ default: p[i] = 0x80000000u | 0x1234; break;
+ }
+ }
+ else
+ p[i] = 0x20 + (_rnd() % 0x5f);
+ }
+
+ assert(simd_scan_plain_ascii_u32_scalar(p, len) ==
+ simd_scan_plain_ascii_u32_neon(p, len));
+ assert(_guards_intact(base,
+ (off + len) * sizeof(Eina_Unicode)));
+ free(base);
+ }
+ }
+ }
+}
+
static void
_test_widen(void)
{
@@ -219,6 +276,32 @@ _test_every_byte(void)
}
}
+static void
+_test_every_u32_boundary(void)
+{
+ static const Eina_Unicode vals[] = {
+ 0x00, 0x01, 0x1f, 0x20, 0x21, 0x7d, 0x7e, 0x7f, 0x80, 0xa0,
+ 0x200b, 0x300, 0x4e2d, 0xfe00, 0x1f600, 0x80000000u
+ };
+ size_t v, len, pos, i;
+
+ for (v = 0; v < sizeof(vals) / sizeof(vals[0]); v++)
+ {
+ for (len = 1; len <= 20; len++)
+ {
+ for (pos = 0; pos < len; pos++)
+ {
+ Eina_Unicode buf[24];
+
+ for (i = 0; i < len; i++) buf[i] = 'x';
+ buf[pos] = vals[v];
+ assert(simd_scan_plain_ascii_u32_scalar(buf, len) ==
+ simd_scan_plain_ascii_u32_neon(buf, len));
+ }
+ }
+ }
+}
+
#endif
int
@@ -226,8 +309,10 @@ tytest_simd_parity(void)
{
#if defined(TERMINOLOGY_HAVE_NEON)
_test_scan();
+ _test_scan_u32();
_test_widen();
_test_every_byte();
+ _test_every_u32_boundary();
#endif
/* Without a vector kernel the scalar path is the only path. */
return 0;
diff --git a/src/bin/simd/simd.h b/src/bin/simd/simd.h
index e64e93e4..7f47291e 100644
--- a/src/bin/simd/simd.h
+++ b/src/bin/simd/simd.h
@@ -21,6 +21,13 @@ 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
+/* Same, over decoded codepoints. */
+size_t simd_scan_plain_ascii_u32(const Eina_Unicode *buf, size_t len);
+size_t simd_scan_plain_ascii_u32_scalar(const Eina_Unicode *buf, size_t len);
+#if defined(TERMINOLOGY_HAVE_NEON)
+size_t simd_scan_plain_ascii_u32_neon(const Eina_Unicode *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,
diff --git a/src/bin/simd/simd_neon.c b/src/bin/simd/simd_neon.c
index 6ed4066f..cad10609 100644
--- a/src/bin/simd/simd_neon.c
+++ b/src/bin/simd/simd_neon.c
@@ -44,6 +44,36 @@ simd_scan_plain_ascii_neon(const unsigned char *buf, size_t len)
return len;
}
+size_t
+simd_scan_plain_ascii_u32_neon(const Eina_Unicode *buf, size_t len)
+{
+ /* One unsigned compare instead of two: g - 0x20 wraps for anything below
+ * 0x20, pushing it above the 0x5e span that 0x20..0x7e occupies. */
+ const uint32x4_t bias = vdupq_n_u32(0x20);
+ const uint32x4_t span = vdupq_n_u32(0x7e - 0x20);
+ size_t i = 0;
+
+ for (; i + 4 <= len; i += 4)
+ {
+ uint32x4_t v = vld1q_u32((const uint32_t *)(buf + i));
+ uint32x4_t bad = vcgtq_u32(vsubq_u32(v, bias), span);
+ uint64_t m;
+
+ /* Narrow the four 32-bit lanes to four 16-bit ones, so the first
+ * offending lane is a trailing-zero count divided by sixteen. */
+ m = vget_lane_u64(vreinterpret_u64_u16(vmovn_u32(bad)), 0);
+ if (m) return i + (size_t)(__builtin_ctzll(m) >> 4);
+ }
+
+ for (; i < len; i++)
+ {
+ Eina_Unicode g = buf[i];
+
+ if ((g < 0x20) || (g >= 0x7f)) return i;
+ }
+ return len;
+}
+
void
simd_widen_ascii_neon(const unsigned char *buf, size_t len, Eina_Unicode *out)
{
diff --git a/src/bin/simd/simd_scalar.c b/src/bin/simd/simd_scalar.c
index 0045088f..3702ac57 100644
--- a/src/bin/simd/simd_scalar.c
+++ b/src/bin/simd/simd_scalar.c
@@ -17,6 +17,20 @@ simd_scan_plain_ascii_scalar(const unsigned char *buf, size_t len)
return len;
}
+size_t
+simd_scan_plain_ascii_u32_scalar(const Eina_Unicode *buf, size_t len)
+{
+ size_t i;
+
+ for (i = 0; i < len; i++)
+ {
+ Eina_Unicode g = buf[i];
+
+ if ((g < 0x20) || (g >= 0x7f)) return i;
+ }
+ return len;
+}
+
void
simd_widen_ascii_scalar(const unsigned char *buf, size_t len, Eina_Unicode *out)
{
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.