Skip to content

ci: cover i386 and ClangCL for the AVX2-dispatch guard; drop dead _M_X64 - #144

Open
filipecosta90 wants to merge 8 commits into
mainfrom
ci/cover-i386-and-clangcl
Open

filipecosta90 wants to merge 8 commits into
mainfrom
ci/cover-i386-and-clangcl

Conversation

@filipecosta90

Copy link
Copy Markdown
Contributor

Follow-up to #142 (ClangCL) and #143 (i386), which both edited the AVX2 runtime-dispatch guard in src/hdr_histogram.c but were validated manually rather than in CI.

Why

The CI matrix excludes 32-bit Linux and never selects the ClangCL toolset, so neither configuration the guard specifically handles was exercised. A future refactor of the guard could silently reintroduce either break.

What

Two regression jobs, in both of which HDR_HAS_AVX2_DISPATCH must be compiled out:

  • build-linux-i386 — 32-bit GCC (-m32, gcc-multilib), HDR_LOG_REQUIRED=DISABLED so no 32-bit zlib is needed. The core suites still run hdr_value_at_percentile (the dispatched path). Guards against the Don't attempt AVX2 on i386 #143 break (_mm_extract_epi64 is unavailable in 32-bit codegen).
  • build-windows-clangcl — the ClangCL VS toolset (-T ClangCL) on x64. Guards against the Fix ClangCL build on Windows #142 break (clang-cl defines __clang__+_MSC_VER and previously failed to link __cpu_model).

Also simplifies the guard: _M_X64 is a dead term once _MSC_VER is excluded (only the MSVC family defines _M_X64, and clang-cl uses _M_X64 rather than __x86_64__), so it now gates on __x86_64__ alone, with a comment documenting why 32-bit / MSVC-ABI / ICC are excluded.

No functional change on the platforms that ship the AVX2 path (64-bit GCC/Clang on Linux/macOS): the fast path stays enabled there.

🤖 Generated with Claude Code

The AVX2 runtime-dispatch guard in src/hdr_histogram.c is the subject of two
recently merged fixes (#142 clang-cl, #143 i386), yet CI exercised neither
configuration: the matrix excludes 32-bit Linux and never selects the ClangCL
toolset. Add two regression jobs that build exactly those configurations, in
both of which HDR_HAS_AVX2_DISPATCH must be compiled out:

  - build-linux-i386: 32-bit GCC (-m32, gcc-multilib), HDR_LOG_REQUIRED=DISABLED
    so no 32-bit zlib is needed; the core suites still run hdr_value_at_percentile.
  - build-windows-clangcl: the ClangCL VS toolset (-T ClangCL) on x64.

Also simplify the guard: _M_X64 is dead once _MSC_VER is excluded (only the
MSVC family defines _M_X64, and clang-cl uses _M_X64 rather than __x86_64__),
so gate on __x86_64__ alone and document why 32-bit / MSVC-ABI / ICC are out.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@filipecosta90
filipecosta90 requested a review from mikeb01 July 23, 2026 14:41
fcostaoliveira and others added 2 commits July 23, 2026 15:41
…index type)

The ClangCL CI job added in this PR surfaced a pre-existing clang-cl build
break that PR #142 did not cover: _BitScanReverse{,64} take an
'unsigned long *' out-parameter, but the index was declared uint32_t. MSVC
cl.exe tolerates this (same width), but clang-cl treats the pointer-type
mismatch as a hard error (-Wincompatible-pointer-types is a default error in
Clang 16+). Declare the index as 'unsigned long' to match the intrinsic; on
Windows it is 32-bit, so behavior is unchanged. Fixes both the _WIN64 and
32-bit branches.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Second clang-cl-only break surfaced by the new ClangCL CI job: on the MSVC
atomic path, hdr_atomic_{load,store}_pointer are typed 'void**' functions, so
passing 'struct hdr_histogram**' is a hard error under clang-cl
(-Wincompatible-pointer-types, default error in Clang 16+). GCC/Clang use a
type-generic __atomic_* macro, so this never showed on Linux/macOS. Cast the
call-site arguments to (void**), matching the existing idiom in
test/hdr_atomic_test.c. void* and object pointers share representation
(C11 6.2.5p28), so behavior is unchanged on all platforms.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…-bit

Adversarial review of the guard comment found a factual error: clang-cl
defines __x86_64__ AND __clang__ (alongside _MSC_VER), so it is the
!defined(_MSC_VER) clause -- not the arch/compiler check -- that keeps clang-cl
out of the AVX2 dispatch. Correct the comment so a future editor does not drop
_MSC_VER and reintroduce the #142 break. Verified with
clang --target=x86_64-pc-windows-msvc -dM -E.

Also harden the i386 job: assert the built test binary is 'ELF 32-bit' so the
job fails loudly if -m32 is ever silently ignored (would otherwise be a
false-positive regression test).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@fcostaoliveira
fcostaoliveira force-pushed the ci/cover-i386-and-clangcl branch from 149bddd to e2d1506 Compare August 28, 2026 10:31
@github-actions

github-actions Bot commented Sep 2, 2026

Copy link
Copy Markdown

🤖 Automated first-pass review — a human maintainer's review is still required before merge.

The guard simplification checks out: _M_X64 really is dead once !defined(_MSC_VER) is in the condition, since every compiler that defines _M_X64 (cl, clang-cl, ICC on Windows) also defines _MSC_VER, and MinGW-w64 x86_64 still comes in via __x86_64__ as before — no platform changes branch. Nothing here touches struct hdr_histogram's layout or an existing public signature (count_leading_zeros_64 is static, hdr_atomic.h is a private header, and the recorder change is call-site casts only), so no SOVERSION move is implied. The unsigned long out-param is right on every branch that guard selects — Windows is LLP64, so it's 32-bit there and the 63 - leading_zero result is unchanged. The (void**) casts match the idiom already in test/hdr_atomic_test.c:37, all three call sites in the tree are covered, and they also clear the incompatible-pointer warnings the existing MSVC matrix jobs have presumably been emitting quietly (no -Werror here, so nobody would have noticed).

Two things I'd tighten in the CI half:

  • The ClangCL job's comment says it "fails if the exclusion regresses", but unlike the i386 job it has no explicit HDR_HAS_AVX2_DISPATCH assert — its only regression signal is the link failing on __cpu_model. That is what broke in Fix ClangCL build on Windows #142, but it's indirect: if clang's builtins are linkable in some future image, the job goes green with the dispatch wrongly enabled. Worth the same negative macro assert you gave i386, for symmetry.
  • The positive assert is if: matrix.os == 'linux' only, yet macOS x64 also ships the AVX2 path. Cheap to extend, and it's the other half of the guard this PR is pinning down.

One thing I can't verify from the diff: whether the i386 build actually links, specifically whether 64-bit __atomic_* under -m32 needs -latomic for hdr_histogram_atomic_test / hdr_histogram_atomic_concurrency_test (the latter is if(UNIX), so it does get built here). The job's own run answers that, and that's the right place for it.

fcostaoliveira and others added 3 commits September 2, 2026 12:29
The negative assert used 'cc -m32 ... | grep -q ... && { exit 1; } || true'.
The trailing '|| true' greens the step even if 'cc -m32' itself breaks (e.g.
missing multilib): grep sees empty input, doesn't match, and the step passes
— the same false-positive class the 'ELF 32-bit' check was added to close.

Write the preprocessor macros to a file first so a broken 'cc -m32' fails the
step under 'set -e', then assert with an explicit if-guard. (A '! grep'
one-liner would not work: a pipeline preceded by '!' is exempted from 'set -e',
so a match would not fail the step.) Now fails on both a broken command and a
regressed guard.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
# Conflicts:
#	.github/workflows/ci.yml
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