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 36e0f8db673f8499ef453d51f6f259b23c03829b
Author: Cedric BAIL <[email protected]>
AuthorDate: Mon Aug 3 13:27:46 2026 -0600
simd: add the reverse non-zero byte scan kernel
Index one past the last non-zero byte, which is what a trailing-length scan over
a row of cells asks for. Walks backwards a vector at a time and takes the
highest set lane of the first block that has one.
No caller yet -- the line-length scan takes it up.
Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
---
src/bin/simd/simd.c | 57 ++++++++++++++++++++++++++++++++++++++++++++++
src/bin/simd/simd.h | 7 ++++++
src/bin/simd/simd_neon.c | 32 ++++++++++++++++++++++++++
src/bin/simd/simd_scalar.c | 11 +++++++++
4 files changed, 107 insertions(+)
diff --git a/src/bin/simd/simd.c b/src/bin/simd/simd.c
index 9e98572d..b7e11ef8 100644
--- a/src/bin/simd/simd.c
+++ b/src/bin/simd/simd.c
@@ -48,6 +48,16 @@ simd_scan_plain_ascii_u32(const Eina_Unicode *buf, size_t len)
return simd_scan_plain_ascii_u32_scalar(buf, len);
}
+size_t
+simd_rscan_nonzero(const unsigned char *buf, size_t len)
+{
+#if defined(TERMINOLOGY_HAVE_NEON)
+ if (EINA_LIKELY(_use_simd))
+ return simd_rscan_nonzero_neon(buf, len);
+#endif
+ return simd_rscan_nonzero_scalar(buf, len);
+}
+
void
simd_widen_ascii(const unsigned char *buf, size_t len, Eina_Unicode *out)
{
@@ -214,6 +224,52 @@ _test_scan_u32(void)
}
}
+static void
+_test_rscan(void)
+{
+ size_t len, off, pos;
+ int density;
+
+ for (len = 0; len <= 70; len++)
+ {
+ for (density = 0; density <= 100; density += 25)
+ {
+ for (off = 0; off < 16; off++)
+ {
+ unsigned char *base = _alloc_guarded(off + len);
+ unsigned char *p = base + GUARD + off;
+
+ memset(p, 0, len);
+ for (pos = 0; pos < len; pos++)
+ {
+ if ((int)(_rnd() % 100) < density)
+ p[pos] = (unsigned char)(1 + (_rnd() % 255));
+ }
+
+ assert(simd_rscan_nonzero_scalar(p, len) ==
+ simd_rscan_nonzero_neon(p, len));
+ assert(_guards_intact(base, off + len));
+ free(base);
+ }
+ }
+ }
+
+ /* One non-zero byte walked across every position: pins down the lane
+ * arithmetic rather than trusting the random fill to have covered it. */
+ for (len = 1; len <= 40; len++)
+ {
+ for (pos = 0; pos < len; pos++)
+ {
+ unsigned char buf[48];
+
+ memset(buf, 0, sizeof(buf));
+ buf[pos] = 0x01;
+ assert(simd_rscan_nonzero_scalar(buf, len) == pos + 1);
+ assert(simd_rscan_nonzero_neon(buf, len) == pos + 1);
+ }
+ }
+}
+
static void
_test_widen(void)
{
@@ -310,6 +366,7 @@ tytest_simd_parity(void)
#if defined(TERMINOLOGY_HAVE_NEON)
_test_scan();
_test_scan_u32();
+ _test_rscan();
_test_widen();
_test_every_byte();
_test_every_u32_boundary();
diff --git a/src/bin/simd/simd.h b/src/bin/simd/simd.h
index 7f47291e..343fe7fa 100644
--- a/src/bin/simd/simd.h
+++ b/src/bin/simd/simd.h
@@ -28,6 +28,13 @@ size_t simd_scan_plain_ascii_u32_scalar(const Eina_Unicode *buf, size_t len);
size_t simd_scan_plain_ascii_u32_neon(const Eina_Unicode *buf, size_t len);
#endif
+/* Index one past the last non-zero byte, or 0 if every byte is zero. */
+size_t simd_rscan_nonzero(const unsigned char *buf, size_t len);
+size_t simd_rscan_nonzero_scalar(const unsigned char *buf, size_t len);
+#if defined(TERMINOLOGY_HAVE_NEON)
+size_t simd_rscan_nonzero_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,
diff --git a/src/bin/simd/simd_neon.c b/src/bin/simd/simd_neon.c
index cad10609..c132260b 100644
--- a/src/bin/simd/simd_neon.c
+++ b/src/bin/simd/simd_neon.c
@@ -74,6 +74,38 @@ simd_scan_plain_ascii_u32_neon(const Eina_Unicode *buf, size_t len)
return len;
}
+size_t
+simd_rscan_nonzero_neon(const unsigned char *buf, size_t len)
+{
+ size_t i = len;
+
+ while (i >= 16)
+ {
+ uint8x16_t v = vld1q_u8(buf + i - 16);
+ uint64_t m;
+
+ /* vtstq_u8(v, v) is 0xff in every lane whose byte is non-zero. */
+ m = vget_lane_u64(vreinterpret_u64_u8(
+ vshrn_n_u16(vreinterpretq_u16_u8(vtstq_u8(v, v)),
+ 4)), 0);
+ if (m)
+ {
+ /* Highest set nibble is the last non-zero byte of this block. */
+ size_t lane = (size_t)(63 - __builtin_clzll(m)) >> 2;
+
+ return i - 16 + lane + 1;
+ }
+ i -= 16;
+ }
+
+ while (i > 0)
+ {
+ if (buf[i - 1]) return i;
+ i--;
+ }
+ return 0;
+}
+
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 3702ac57..3676b94c 100644
--- a/src/bin/simd/simd_scalar.c
+++ b/src/bin/simd/simd_scalar.c
@@ -31,6 +31,17 @@ simd_scan_plain_ascii_u32_scalar(const Eina_Unicode *buf, size_t len)
return len;
}
+size_t
+simd_rscan_nonzero_scalar(const unsigned char *buf, size_t len)
+{
+ while (len > 0)
+ {
+ if (buf[len - 1]) return len;
+ len--;
+ }
+ return 0;
+}
+
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.