You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Count the bits set in each element of an integer batch. The common kernel is
the SWAR fold; x86 uses the PSHUFB nibble lookup from SSSE3 up, NEON uses CNT
with pairwise widening adds, SVE uses svcnt_x, and WASM uses i8x16.popcnt with
pairwise widening extends, folding 32-bit counts with a shift-and-add pair for
64-bit elements. VSX and VXE use vec_popcnt, which the compiler maps to a
single VPOPCNTB/H/W/D or VPOPCT.
For 64-bit elements the two x86 nibble tables carry a +4 and a -4 bias, after
libpopcnt, so PSADBW yields the byte count and the 8-byte sum in one
instruction. This drops the VPADDB, and measures 1.09x on SSE and AVX2 and
1.05x on AVX-512.
sse2 gets its own kernel, since the SWAR fold is what a default x86-64 build
runs and it leaves PSADBW and PMADDWD unused. PSADBW sums the eight byte counts
of a 64-bit element in one instruction, PMADDWD adds the two halves of a 32-bit
one, and the byte shifts drop the mask that the fold already applies. This cuts
64-bit elements from 25 instructions to 16, 32-bit ones from 22 to 19 and 8-bit
ones from 15 to 14, and measures 1.5x, 1.09x and 1.08x. 16-bit elements keep
the fold's instruction count, since SSE2 has no PMADDUBSW to combine the two
byte counts of an element.
The NEON kernel takes UDOT when __ARM_FEATURE_DOTPROD is defined: one
instruction replaces the two pairwise widening adds that fold byte counts into
32-bit elements. The Arm cross-compilation matrix gains an armv8.2-a+dotprod
row, so qemu covers both paths.
avx512vnni gains a 32-bit kernel: VPDPBUSD does in one uop what the VPMADDUBSW
and VPMADDWD pair does in two, and the zero accumulator is free because the
register copy is eliminated at rename. This measures 1.14x. The same
substitution on 256-bit vectors is neutral, since three ports serve them, so
avxvnni gets no kernel.
The CI job labelled avx512vnni built for knm, which enables avx5124vnniw rather
than avx512vnni and selected the avx512pf arch, so it covered neither kernel.
It now builds for cascadelake.
Assisted-by: Claude Opus 5 <noreply@anthropic.com>
0 commit comments