Skip to content

simd: saturating narrows down the 512-bit ladder (16x32 -> 32x16 -> 64x8) - #373

Merged
AdaWorldAPI merged 1 commit into
masterfrom
feat/simd-narrow-ladder-20261024
Oct 24, 2026
Merged

AdaWorldAPI merged 1 commit into
masterfrom
feat/simd-narrow-ladder-20261024

Conversation

@AdaWorldAPI

Copy link
Copy Markdown
Owner

Summary

#372 merged at its first commit (e07be5b). That commit's narrow is off the 512-bit ladder: I32x16 -> I8x16/U8x16, a 128-bit result. The ladder rework reached the #372 branch after the merge (dc26129), so it never landed. This PR applies that same diff to master: it removes the I8x16/U8x16 narrow and adds the ladder steps on every backend.

  • I32x16::narrow_saturating_i16(hi) -> I16x32
  • I16x32::narrow_saturating_i8(hi) -> I8x64
  • I16x32::narrow_saturating_u8(hi) -> U8x64

Lanes 0..N come from self and N..2N from hi. Each lane is clamped to the narrow range.

backend how
AVX-512 vpmovsdw / vpmovswb / vpmovuswb, then vinserti64x4 (u8 first raises negative lanes to 0)
AVX2 / AVX SSE2 packssdw / packsswb / packuswb over 16-byte quarters
NEON sqxtn / sqxtun + vcombine
wasm simd128 i16x8_narrow_i32x4, i8x16_narrow_i16x8, u8x16_narrow_i16x8
scalar clamp
nightly simd_clamp + cast

Two backend notes:

  • wasm: I16x32 / I8x64 / U8x64 come from the scalar backend on wasm. Their narrows are therefore implemented in simd_wasm.rs, and the scalar versions are cfg-gated off for that arm.
  • aarch64: the facade now re-exports the NEON I16x32 / I8x64 (+ i16x32 / i8x64). simd_neon.rs already had both types, but no arm re-exported them.

Nightly keeps F32x16::cast_i32 and I32x16::cast_f32.

Verification

git diff origin/master on this branch equals git diff e07be5b dc26129 (checked with diff), so the measurements taken on dc26129 apply unchanged:

  • Parity group 0x10xx in simd-masking-parity:
    • inputs: an edge set plus 63 random rounds;
    • the chained i32→i16→i8/u8 result is compared with a single clamp;
    • the in-range f32↔i32 casts are compared with as;
    • anti-vacuity: some lanes must saturate and some must pass through unchanged.
  • All 8 arms pass, 17 groups bit-identical: native v4, native v3, avx-qemu, v2-qemu, neon-qemu, wasm, wasm-scalar, nightly.
  • Disable run: with the AVX-512 u8 "raise negatives to 0" step removed, the parity check fails with 0x1080, the u8 lane holding i32::MIN.
  • Lowered assembly (#[inline(never)] wrappers, release):
    • v4: two vshufi64x2 + one vpackssdw / vpacksswb / vpackuswb per narrow;
    • v3: four 128-bit packs per narrow;
    • no scalar code on either.
  • cargo clippy --lib -D warnings is clean on v4 and v3. The new doctests pass (v4, release).

Generated by Claude Code

…4x8)

#372 merged at its first commit (e07be5b), whose narrow was off the ladder:
I32x16 -> I8x16/U8x16, a 128-bit result. This replaces it with the ladder
steps:

- I32x16::narrow_saturating_i16(hi) -> I16x32
- I16x32::narrow_saturating_i8(hi)  -> I8x64
- I16x32::narrow_saturating_u8(hi)  -> U8x64

Lanes 0..N come from self, N..2N from hi, each clamped to the narrow range.
Realized per backend: AVX-512 vpmovsdw/vpmovswb/vpmovuswb (u8 raises
negatives to 0 first), AVX2/AVX SSE2 packs, NEON sqxtn/sqxtun, wasm
narrow_i32x4/i16x8 (I16x32 comes from scalar there, so its narrows live in
simd_wasm.rs and the scalar ones are gated off), scalar clamp, nightly
simd_clamp + cast.

aarch64 now re-exports the NEON I16x32/I8x64 the backend already carried.
Nightly keeps F32x16::cast_i32 and I32x16::cast_f32.

Parity group 0x10xx: edge sets plus 63 random rounds, chained i32->i16->i8/u8
against one clamp, in-range casts, anti-vacuity on saturated and kept lanes.
17 groups bit-identical on native v4, native v3, avx-qemu, v2-qemu,
neon-qemu, wasm, wasm-scalar, nightly.

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

coderabbitai Bot commented Oct 24, 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: fa038c28-94b9-40bc-a9ec-6e6b6b06e671
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Warning

Billing warning: we have not been able to collect payment for this subscription for more than 72 hours. Please update the payment method or pay any pending invoices in Billing to avoid service interruption.

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.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 24, 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-24T17:41:56.445767Z 9dc5862 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 6bd296e into master Oct 24, 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