Skip to content

Add U64x8::sum8_u8_add_masked, a vertical masked byte sum - #390

Merged
AdaWorldAPI merged 3 commits into
masterfrom
claude/sum8-u8-masked
Oct 29, 2026
Merged

AdaWorldAPI merged 3 commits into
masterfrom
claude/sum8-u8-masked

Conversation

@AdaWorldAPI

Copy link
Copy Markdown
Owner

Summary

Adds one facade word, U64x8::sum8_u8_add_masked, a vertical masked byte sum with one realization per backend. It was missing from the facade and was recorded as a gap in #389 (draft, probe).

The word

U64x8::sum8_u8_add_masked(self, a: U8x64, keep: u64) -> U64x8

Lane j gains the sum of the bytes a[i], i in 8j..8j+8, whose bit i in keep is set.

  • Exact. Each call adds at most 8 * 255 = 2,040 to a lane.
  • The u64 lanes wrap only after more than 9 * 10^15 calls.
  • No horizontal reduction. Accumulate across calls and reduce once at the end.

Why: candidate E in #389 needs a masked byte sum for the power-of-two anchor term. With |b| = low7 + 128*bit7, a*|b| = a*low7 + 128*(sum of a where bit 7 of b is set). The facade only had U8x64::sum_bytes_u64, which reduces horizontally on every call.

Realizations

One per backend, no shared body.

Backend Instructions
AVX-512 (simd_avx512.rs) _mm512_maskz_mov_epi8, _mm512_sad_epu8 against zero, _mm512_add_epi64. Disassembly: kmovq, vmovdqu8 (zero-masked), vpxor, vpsadbw, vpaddq.
AVX2 (simd_avx2.rs, not on the AVX-only arm) Keep mask built in registers as in I32x16::dot4_u8_i8_add_masked (variable shift, multiply by 0x0101_0101, shift by 32, compare against BIT_IN_BYTE), AND, _mm256_sad_epu8, _mm256_add_epi64, two halves. LLVM emits 2 vpshufb while spreading the mask bytes; the source contains no shuffle, and the existing masked byte-dot lowers the same way.
AVX without AVX2 (simd_avx.rs) mask_byte_spread, _mm_cmpeq_epi8, AND, _mm_sad_epu8 per 16-byte quarter, _mm_add_epi64.
NEON (simd_neon.rs) vtstq_u8 mask from mask_byte_spread, AND, vpaddlq_u8, vpaddlq_u16, vpaddlq_u32, vaddq_u64. Cross-compiled assembly: uaddlp, uaddlp, uadalp (LLVM fused the final add into the accumulate). No scalar loop.
wasm simd128 (simd_wasm.rs) Mask from mask_byte_spread via i8x16_eq, AND, u16x8_extadd_pairwise_u8x16, u32x4_extadd_pairwise_u16x8; each u64 lane is (x & 0xFFFF_FFFF) + (x >> 32), added with i64x2_add. No shuffle.
scalar (simd_scalar.rs) Per-lane loop; the correctness anchor.
nightly-simd (simd_nightly/u_word_types.rs) Mask::from_bitmask(keep).select(...), bytes reinterpreted as u64x8 via from_ne_bytes, SWAR fold (8 to 16 to 32 to 64 bits).

Tests

In src/simd.rs, module dot4_nibble_facade_parity:

  • sum8_masked_matches_reference: 57 byte vectors x 8 random masks x 5 mask patterns (0, all, alternating, 0x8000_0000_0000_0001, random) x 3 accumulators (0, u64::MAX, random). Over 5,000 checks; wrap is exercised.
  • sum8_masked_gates_each_byte_by_its_own_bit: each of the 64 bits alone, and all-but-one.
  • sum8_masked_all_kept_agrees_with_sum_bytes: equals U8x64::sum_bytes_u64 when all bytes are kept; 1,000 accumulating calls.

Also:

  • A doc example on every backend's method; the doctest ran on the native (AVX-512) and config-v3 (AVX2) builds.
  • Cross-ISA harnesses crates/wasm-simd-parity and crates/neon-simd-parity: code 0x506 (per-bit gating) and 0x507 (random corpus, including u64::MAX accumulators).

Passed on: native AVX-512 VNNI, config-v4, config-v3 (AVX2), config-avx (qemu SandyBridge), config-v2 (scalar, qemu Nehalem), aarch64 (qemu), nightly-simd. scripts/wasm-parity.sh and scripts/neon-parity.sh pass; NEON assembly rung 3 passes.

Disable runs, each red:

Disabled Result
AVX-512 mask ignored red
AVX2 mask ignored red
AVX mask ignored red
scalar lane slice of 7 bytes instead of 8 red
NEON mask ignored red (parity code 0x506)
wasm high 32 bits of each lane dropped red (0x506)
nightly last SWAR fold dropped red

Lint: clippy -D warnings clean on native, v3, avx and aarch64; rustfmt clean. The facet-stride guard (no shuffle, no scalar loop in non-scalar backends, no u8/i8 mixing in added lines) reports nothing.

Benchmark

Out-of-tree bench crate: 4,096 random byte vectors with random masks, medians of 1,001 runs, on an AVX-512 VNNI Xeon.

Config sum8_u8_add_masked, per 64 bytes Reference loop (bit test per byte) Speedup
target-cpu=native (AVX-512) 0.687 ns 192.8 - 196.0 ns 281 - 285x
target-cpu=x86-64-v3 (AVX2) 1.987 - 1.991 ns 194.1 - 195.4 ns 98x

NEON and wasm were not timed; qemu and node timings are not meaningful.

Consumer

examples/u9_abacus/anchor.rs in #389 (candidate E's anchor term). Not wired in this PR.

Not in this PR

  • No dispatch.
  • No other facade word.
  • No storage format.

Generated by Claude Code

Lane j gains the sum of the bytes 8j..8j+8 of a U8x64 whose keep bit is
set, accumulated per lane with no horizontal reduction (vpsadbw on the
kept bytes on x86, pairwise widening adds on NEON and wasm). Realized in
every backend: AVX-512, AVX2, AVX, NEON, wasm, scalar and nightly.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XAqKMMjKnig6MXTd41Lf2v
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XAqKMMjKnig6MXTd41Lf2v
@coderabbitai

coderabbitai Bot commented Oct 29, 2026 •

Copy link
Copy Markdown
Contributor

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 9de51cdd-0afc-4bff-ad92-236e2b7424ef
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@AdaWorldAPI
AdaWorldAPI marked this pull request as ready for review October 29, 2026 21:12
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 29, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-29T21:13:13.813588Z 3dfa3b0 Draft marked ready
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@AdaWorldAPI
AdaWorldAPI merged commit 886c343 into master Oct 29, 2026
30 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants