Follow-up idea spun off from PR #1977 (AVX2-VNNI adler32).
adler32_avx512_vnni uses only 2 VPDPBUSD accumulators (vs2, vs2_1). VPDPBUSD
has ~5-cycle latency, so two in-flight dot products can't cover it and the 128-byte loop is
latency-bound at ~5c/128B — the same ceiling as the AVX2-VNNI path.
But AVX-512 has 32 zmm registers, not AVX2's 16. The AVX2 kernel is physically capped at 4 accumulators; the AVX-512 kernel has the budget to unroll wider and simply isn't using it.
Unroll the main loop ×4 (256 B/iter) with four VPDPBUSD accumulators (vs2, vs2_1,
vs2_2, vs2_3), and peel the 64-byte remainder down to a 256-byte multiple. Four in-flight
dot products cover the latency, roughly halving the latency-bound time to ~5c/256B.
- Correctness: the restructured integer accounting was modeled scalar-side and is bit-identical to the reference adler32 across 331 sizes, including every block/NMAX boundary (63/64/65, 127/128, 191/192, 255/256/257, 5551/5552/5553, ...) with random initial adler.
- Codegen (clang 22,
-mavx512vnni): builds spill-free, 14 of 32 zmm registers used, 4vpdpbusdin the inner loop. The two-accumulator original uses 12 zmm.
- Up to ~2x on the compute-bound (L1/L2-resident) range where it's
VPDPBUSD-latency-bound. Negligible once memory-bandwidth-bound on large buffers. - Not benchmarked on hardware — I'm on arm64, so this is asm + scalar-model verification only. Needs an avx512vnni part (Ice Lake / Sapphire Rapids / Zen 4+). A/B before merging.
- The same 4-accumulator copy variant should follow if this holds up.
Apply with git apply from the repo root.