Fixes the aarch64 ARM NEON fast paths that truncated 64-bit versions to 32 bits when USE_64_BIT=1, producing spurious conflicts/commits once the version counter exceeded 2^32 - 1.
Root cause
scan16 (both the indexed Node48 variant and the Node256 variant) and checkMaxBetweenExclusiveImpl(Node16) copied only the low 32 bits of each InternalVersionT into uint32x4_t lanes and compared against a 32-bit readVersion. With USE_64_BIT=1, InternalVersionT stores an int64_t, so this is wrong for any version above 2^32.
Fix
The per-version vs[i] > readVersion computation is extracted into a shared conflictMask16 helper that returns a uint8x16_t (byte i = 0xff on conflict). For 64-bit versions it compares the full int64 values with vcgtq_s64 and narrows the result into the same nibble-packed (4 bits per version) layout the callers already consume; the 32-bit path is unchanged.
Verification
Built on aarch64 with -DUSE_64_BIT=1 (the previously failing configuration). script_test_internal_version_zero now passes, the corpus blackbox case eace36b9... (which previously reported Expected commit, got conflict ... at version 6993204482) now succeeds, and the full non-valgrind ctest suite (8554 tests) passes for both USE_64_BIT=1 and the default 32-bit build. (Valgrind tests are skipped here because the host valgrind does not support this aarch64 CPU.)
## Summary
Fixes the aarch64 ARM NEON fast paths that truncated 64-bit versions to 32 bits when `USE_64_BIT=1`, producing spurious conflicts/commits once the version counter exceeded `2^32 - 1`.
## Root cause
`scan16` (both the indexed `Node48` variant and the `Node256` variant) and `checkMaxBetweenExclusiveImpl(Node16)` copied only the low 32 bits of each `InternalVersionT` into `uint32x4_t` lanes and compared against a 32-bit `readVersion`. With `USE_64_BIT=1`, `InternalVersionT` stores an `int64_t`, so this is wrong for any version above `2^32`.
## Fix
The per-version `vs[i] > readVersion` computation is extracted into a shared `conflictMask16` helper that returns a `uint8x16_t` (byte `i` = `0xff` on conflict). For 64-bit versions it compares the full `int64` values with `vcgtq_s64` and narrows the result into the same nibble-packed (4 bits per version) layout the callers already consume; the 32-bit path is unchanged.
## Verification
Built on aarch64 with `-DUSE_64_BIT=1` (the previously failing configuration). `script_test_internal_version_zero` now passes, the corpus blackbox case `eace36b9...` (which previously reported `Expected commit, got conflict ... at version 6993204482`) now succeeds, and the full non-valgrind ctest suite (8554 tests) passes for both `USE_64_BIT=1` and the default 32-bit build. (Valgrind tests are skipped here because the host valgrind does not support this aarch64 CPU.)
Closes #69
When USE_64_BIT=1, InternalVersionT stores an int64_t, but the aarch64
NEON fast paths in scan16 (both the indexed Node48 variant and the
Node256 variant) and checkMaxBetweenExclusiveImpl(Node16) only copied the
low 32 bits of each version into uint32x4_t lanes and compared against a
truncated 32-bit readVersion. This produced wrong conflict/commit
decisions once any version exceeded 2^32 - 1.
Extract the per-version "greater than readVersion" computation into a
shared conflictMask16 helper. For 64-bit versions it uses vcgtq_s64 on
the full int64 values and narrows the resulting 16-byte mask into the
same nibble-packed layout the callers already consume. The 32-bit path is
preserved unchanged.
Closes#69
andrew
merged commit 1179c1f56e into main2026-08-03 12:26:09 +00:00
andrew
deleted branch weaselbot/issue-692026-08-03 12:26:10 +00:00
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Summary
Fixes the aarch64 ARM NEON fast paths that truncated 64-bit versions to 32 bits when
USE_64_BIT=1, producing spurious conflicts/commits once the version counter exceeded2^32 - 1.Root cause
scan16(both the indexedNode48variant and theNode256variant) andcheckMaxBetweenExclusiveImpl(Node16)copied only the low 32 bits of eachInternalVersionTintouint32x4_tlanes and compared against a 32-bitreadVersion. WithUSE_64_BIT=1,InternalVersionTstores anint64_t, so this is wrong for any version above2^32.Fix
The per-version
vs[i] > readVersioncomputation is extracted into a sharedconflictMask16helper that returns auint8x16_t(bytei=0xffon conflict). For 64-bit versions it compares the fullint64values withvcgtq_s64and narrows the result into the same nibble-packed (4 bits per version) layout the callers already consume; the 32-bit path is unchanged.Verification
Built on aarch64 with
-DUSE_64_BIT=1(the previously failing configuration).script_test_internal_version_zeronow passes, the corpus blackbox caseeace36b9...(which previously reportedExpected commit, got conflict ... at version 6993204482) now succeeds, and the full non-valgrind ctest suite (8554 tests) passes for bothUSE_64_BIT=1and the default 32-bit build. (Valgrind tests are skipped here because the host valgrind does not support this aarch64 CPU.)Closes #69