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 a4dad43122dd26a43913a298993f7f11c8cf73ee
Author: Cedric BAIL <[email protected]>
AuthorDate: Mon Aug 3 13:27:46 2026 -0600
simd: add the record byte-OR kernel
OR one bit into the same byte of every record of an array. The vector form only
pays off when the stride lines up with the vector -- a 12-byte record repeats
against a 16-byte vector every 48 bytes -- so every other stride falls through
to the scalar form rather than pretending to be vectorised.
No caller yet -- the autowrapped marking of saved rows takes it up.
Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
---
src/bin/simd/simd.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++
src/bin/simd/simd.h | 11 ++++++++++
src/bin/simd/simd_neon.c | 35 +++++++++++++++++++++++++++++++
src/bin/simd/simd_scalar.c | 11 ++++++++++
4 files changed, 108 insertions(+)
diff --git a/src/bin/simd/simd.c b/src/bin/simd/simd.c
index b7e11ef8..4a5592b0 100644
--- a/src/bin/simd/simd.c
+++ b/src/bin/simd/simd.c
@@ -58,6 +58,20 @@ simd_rscan_nonzero(const unsigned char *buf, size_t len)
return simd_rscan_nonzero_scalar(buf, len);
}
+void
+simd_records_or_byte(void *buf, size_t n, size_t rec, size_t off,
+ unsigned char bit)
+{
+#if defined(TERMINOLOGY_HAVE_NEON)
+ if (EINA_LIKELY(_use_simd))
+ {
+ simd_records_or_byte_neon(buf, n, rec, off, bit);
+ return;
+ }
+#endif
+ simd_records_or_byte_scalar(buf, n, rec, off, bit);
+}
+
void
simd_widen_ascii(const unsigned char *buf, size_t len, Eina_Unicode *out)
{
@@ -270,6 +284,42 @@ _test_rscan(void)
}
}
+static void
+_test_records_or(void)
+{
+ size_t n, off, rec, i;
+
+ /* Both the vectorised 12-byte stride and one that must fall back. */
+ for (rec = 11; rec <= 12; rec++)
+ {
+ for (n = 0; n <= 40; n++)
+ {
+ for (off = 0; off < rec; off++)
+ {
+ unsigned char *a = _alloc_guarded(n * rec);
+ unsigned char *b = _alloc_guarded(n * rec);
+
+ for (i = 0; i < n * rec; i++)
+ {
+ unsigned char v = (unsigned char)(_rnd() & 0xff);
+
+ a[GUARD + i] = v;
+ b[GUARD + i] = v;
+ }
+
+ simd_records_or_byte_scalar(a + GUARD, n, rec, off, 0x40);
+ simd_records_or_byte_neon(b + GUARD, n, rec, off, 0x40);
+
+ assert(memcmp(a + GUARD, b + GUARD, n * rec) == 0);
+ assert(_guards_intact(a, n * rec));
+ assert(_guards_intact(b, n * rec));
+ free(a);
+ free(b);
+ }
+ }
+ }
+}
+
static void
_test_widen(void)
{
@@ -367,6 +417,7 @@ tytest_simd_parity(void)
_test_scan();
_test_scan_u32();
_test_rscan();
+ _test_records_or();
_test_widen();
_test_every_byte();
_test_every_u32_boundary();
diff --git a/src/bin/simd/simd.h b/src/bin/simd/simd.h
index 343fe7fa..7583d822 100644
--- a/src/bin/simd/simd.h
+++ b/src/bin/simd/simd.h
@@ -35,6 +35,17 @@ size_t simd_rscan_nonzero_scalar(const unsigned char *buf, size_t len);
size_t simd_rscan_nonzero_neon(const unsigned char *buf, size_t len);
#endif
+/* OR 'bit' into byte 'off' of each of 'n' records of 'rec' bytes. 'off' must
+ * be less than 'rec'. */
+void simd_records_or_byte(void *buf, size_t n, size_t rec, size_t off,
+ unsigned char bit);
+void simd_records_or_byte_scalar(void *buf, size_t n, size_t rec, size_t off,
+ unsigned char bit);
+#if defined(TERMINOLOGY_HAVE_NEON)
+void simd_records_or_byte_neon(void *buf, size_t n, size_t rec, size_t off,
+ unsigned char bit);
+#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 c132260b..3806798a 100644
--- a/src/bin/simd/simd_neon.c
+++ b/src/bin/simd/simd_neon.c
@@ -106,6 +106,41 @@ simd_rscan_nonzero_neon(const unsigned char *buf, size_t len)
return 0;
}
+void
+simd_records_or_byte_neon(void *buf, size_t n, size_t rec, size_t off,
+ unsigned char bit)
+{
+ unsigned char *p = (unsigned char *)buf;
+ size_t i = 0;
+
+ /* A 12-byte stride lines up with the vector every four records, so the mask
+ * repeats every 48 bytes. Other strides use the scalar form. */
+ if ((rec == 12) && (off < rec))
+ {
+ unsigned char pat[48];
+ uint8x16_t m0, m1, m2;
+
+ memset(pat, 0, sizeof(pat));
+ pat[off] = bit;
+ pat[rec + off] = bit;
+ pat[2 * rec + off] = bit;
+ pat[3 * rec + off] = bit;
+ m0 = vld1q_u8(pat);
+ m1 = vld1q_u8(pat + 16);
+ m2 = vld1q_u8(pat + 32);
+
+ for (; i + 4 <= n; i += 4, p += 48)
+ {
+ vst1q_u8(p, vorrq_u8(vld1q_u8(p), m0));
+ vst1q_u8(p + 16, vorrq_u8(vld1q_u8(p + 16), m1));
+ vst1q_u8(p + 32, vorrq_u8(vld1q_u8(p + 32), m2));
+ }
+ }
+
+ for (; i < n; i++, p += rec)
+ p[off] |= bit;
+}
+
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 3676b94c..61c36e96 100644
--- a/src/bin/simd/simd_scalar.c
+++ b/src/bin/simd/simd_scalar.c
@@ -42,6 +42,17 @@ simd_rscan_nonzero_scalar(const unsigned char *buf, size_t len)
return 0;
}
+void
+simd_records_or_byte_scalar(void *buf, size_t n, size_t rec, size_t off,
+ unsigned char bit)
+{
+ unsigned char *p = (unsigned char *)buf + off;
+ size_t i;
+
+ for (i = 0; i < n; i++, p += rec)
+ *p |= bit;
+}
+
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.