Wasm SIMD128 beyond bitsets + amalgamation wasm differential harness#818
Wasm SIMD128 beyond bitsets + amalgamation wasm differential harness#818stereobooster wants to merge 24 commits into
Conversation
Native vs scalar wasm vs -msimd128 share one amalgamation harness and must produce identical deterministic output; clearer diff on mismatch. Refs RoaringBitmap#801 Co-authored-by: Cursor <cursoragent@cursor.com>
Pins Emscripten 3.1.74 + WABT; only Docker needed locally. Refs RoaringBitmap#801 Co-authored-by: Cursor <cursoragent@cursor.com>
Require wasm uplift in linked binaries and roaring-only objects; scan LLVM IR for @llvm.wasm.* intrinsic names so generic vector IR alone cannot satisfy the SIMD leg. Skip the IR gate in CI until RoaringBitmapGH-801 SIMD builtins land. Refs RoaringBitmap#801 Co-authored-by: Cursor <cursoragent@cursor.com>
Bitset cardinality and bitwise container ops use wasm_simd128 when -msimd128; differential harness and CI enforce matching digests plus SIMD bytecode uplift and an LLVM amalgamation SIMD trace (@llvm.ctpop.v16i8 on newer Clang). Co-authored-by: Cursor <cursoragent@cursor.com>
Adds v128 paths in array_util and bitset_util, wires containers and Neon /simd pairing, strengthens the wasm differential harness and coverage doc, and applies repo clang-format to touched headers and sources. Co-authored-by: Cursor <cursoragent@cursor.com>
Move digest setup (PATH, wabt install, run_wasm_differential_test) into tools/ci_wasm_differential_digest.sh and drop the redundant wasm_simd_coverage documentation file. Co-authored-by: Cursor <cursoragent@cursor.com>
Free the roaring_bitmap_or temporary in wasm_diff_harness so leak checkers stay quiet, document WASM/x86 semantic traps and SIMD assumptions, tighten CI by rejecting guard-skipping env in GitHub Actions, and clarify the NEON pairing checker as structural-only. Co-authored-by: Cursor <cursoragent@cursor.com>
…nter. Reserve wasm_* for compiler intrinsics where possible, rename the exported array serializer and SIMD-only internals for consistent namespacing, and document SIMD latency expectations plus differential-test exit codes. The pairing script now requires each Wasm #elif chain to precede Neon coverage without forcing Dummy Wasm blocks for NEON-only work. Apply clang-format to touched headers and TU. Co-authored-by: Cursor <cursoragent@cursor.com>
…recipe. Keeps docker-only runs for tools/run_wasm_differential_test.sh without adding maintained Dockerfile paths under tools/docker. Co-authored-by: Cursor <cursoragent@cursor.com>
6a9e37c to
5b33f09
Compare
…te-c. Zig 0.13's translate-c emits block labels named blk/blk_1, which collided with the C local `blk` and produced invalid Zig; use quad_ptr instead. Co-authored-by: Cursor <cursoragent@cursor.com>
Adds a deterministic left-associated roaring_bitmap_or fold mirroring facetsearch-style unions, validates after each inplace OR, and digests export invariants so native vs wasm SIMD parity catches phantom ids. Co-authored-by: Cursor <cursoragent@cursor.com>
CMocka bitmap_metamorphic_unit covers membership oracles for bitwise ops, iterator/export parity, cardinality laws, inplace parity, deep OR folds, and portable round-trip. LibFuzzer exercises OR-chain and pairwise bitmap metamorphism. wasm_diff_harness emits matching meta_* digest lines on native vs wasm legs; Emscripten links get larger stack/initial memory. Co-authored-by: Cursor <cursoragent@cursor.com>
… harness. Co-authored-by: Cursor <cursoragent@cursor.com>
…cast helper. Delegates wasm intersect_vector16 back to intersect_uint16 for digest parity against native; SIMD bitset word ops rely on roaring_hamming after v128 bitwise combine. Leaves bitset uint32 SIMD table decode wired out until it matches TZCNT peeling. Co-authored-by: Cursor <cursoragent@cursor.com>
The decoder must apply one base adjustment to both v128 halves of each 256-bit table row before a single baseVec += 8; re-enable the >=8192 card fast path on wasm32 SIMD. Co-authored-by: Cursor <cursoragent@cursor.com>
…if pairing check. Portable kernels are replaced with wasm128 merges and PCMPESTRI-mask emulation so wasm32+msimd128 matches native digests end-to-end. array_container_andnot uses difference_vector16 on wasm when outputs do not alias. README and tooling clarify check_wasm_simd_neon_pairing.sh (runs in CI) vs run_wasm_differential_test.sh parity. Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
…arity. Exposes chunked i32x4 export mirroring AVX2; wasm amalgamation SIMD builds flip it via -DCROARING_WASM_SIMD_RUN_CONTAINER_EXPAND so digest checks stay the gate. Co-authored-by: Cursor <cursoragent@cursor.com>
When SIMD is enabled and capacity meets the SIMD headroom check, populate the array via bitset_extract_setbits_wasm_uint16; keeps wasm-diff parity with scalar extract. Co-authored-by: Cursor <cursoragent@cursor.com>
Uses the same Schlegel/Lemire mask path as intersect_vector16 on AVX2 and wasm SIMD, with tails delegated to intersect_uint16_nonempty. Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Drop CROARING_WASM_SIMD_RUN_CONTAINER_EXPAND—digest/CI parity is sufficient; fuzz gets rid of unreachable doc_cap guards; wasm bitset SIMD popcnt comments clarify load+scalar lowering; wasm-diff/README updated. Co-authored-by: Cursor <cursoragent@cursor.com>
Clarify Schlegel/Lemire mask parity with intersect_vector16 paths, digest scope, and wasm_simd_perf_smoke limitations; add callsite note in array_container_intersect. Co-authored-by: Cursor <cursoragent@cursor.com>
|
Okay this is huge one. I can try to split it. |
Reflow block comments so the clang-format workflow matches upstream style. Co-authored-by: Cursor <cursoragent@cursor.com>
yes this needs a break down. It is not reviewable in current shape. Do you have any high-level feedback, regarding test-strategy choice, for example. Do not look at small details just yet |
|
Closing this in favor of a set of small, single-purpose PRs Open now
Coming next, stacked on #837 (opened as each predecessor merges, to keep diffs clean and CI green):
Dropped from the original branch as unrelated/unmotivated: the The differential-digest CI gate is added together with the first SIMD path so every PR stays green. |

Summary
Extend Wasm SIMD128 beyond
src/containers/bitset.cto the rest of the hotpaths, wire it into array / bitset / run conversion code, and add a
differential-digest harness that proves native, scalar-wasm, and
-msimd128wasm produce bit-identical output.
Closes #801. Primarily a perf change.
SIMD coverage
array_util.c— Schlegel/Lemire-style intersect / union / xor / difference,optional
memequals, uint16→uint32 widen, and a newintersect_vector16_nonemptyfor balancedarray_container_intersectparitywith the pcmpestra/shuffle-mask paths. SIMD vs scalar speed for the Nonempty
variant is workload-dependent; correctness is tied to the differential
digests, not to
tools/wasm_simd_perf_smoke.sh(whole-harness wall clock).bitset_util.c,bitset.c— bitset merges and SIMD bit-extract.run.c—run_container_to_uint32_arrayuses chunkedi32x4widening(mirroring the AVX2 path) under
__wasm_simd128__/CROARING_WASM_SIMD,with no separate opt-in switch.
convert.c/array.c—array_container_from_bitsetcallsbitset_extract_setbits_wasm_uint16when SIMD is enabled and the arraycapacity clears the SIMD headroom guard; otherwise scalar.
Wasm-specific helpers use a
croaring_wasm_*prefix (includingcroaring_wasm_array_container_to_uint32_array) to avoid colliding with thewasm_*intrinsics inwasm_simd128.h.Verification
tests/wasm_diff_harness.c— amalgamation workload that comparesdeterministic digests across native, Emscripten scalar wasm, and
emcc -msimd128. Guarded by SIMD-uplift checks (wasm-objdumpheuristic onthe linked wasm + roaring-only objects) and an amalgamation LLVM IR trace
for
@llvm.wasm.*/@llvm.ctpop.v16i8. Temporaries are freed so leaksanitizers stay quiet.
tools/run_wasm_differential_test.shdrives the harness end-to-end.CI / tooling
.github/workflows/emscripten.ymlruns onubuntu-latestviasetup-emsdk(no Docker), and pipes through
tools/check_wasm_simd_neon_pairing.sh(structural heuristic on Wasm/NEON
elifhygiene) andtools/ci_wasm_differential_digest.sh.wasm_differential_test,wasm_neon_simd_parity_check.tools/run-wasm-diff-docker.sh— optional local runner that builds a pinnedEmscripten 3.1.74 +
wabtimage from an inline Dockerfile. CI does not usethis path.
tools/wasm_simd_perf_smoke.sh+tools/_wasm_perf_bench_helper.py—optional throughput smoke. Wall-clock noise-prone; complements but does not
replace the digest correctness story.
Misc
.gitignorebuild-debug/and.DS_Store.