Skip to content

Fix AVX2 codegen SIGILL on non-AVX-512 CPUs - #70

Merged
ajroetker merged 1 commit into
mainfrom
fix/avx2-codegen-sigill-non-avx512
May 28, 2026
Merged

Fix AVX2 codegen SIGILL on non-AVX-512 CPUs#70
ajroetker merged 1 commit into
mainfrom
fix/avx2-codegen-sigill-non-avx512

Conversation

@ajroetker

@ajroetker ajroetker commented May 28, 2026

Copy link
Copy Markdown
Owner

Summary

Fixes three SIGILL crashes caused by the hwygen AVX2 code path. All fixes are at the code-generator level so they survive regeneration; the affected *_avx2.gen.go / *_avx512.gen.go files are regenerated in this PR.

Changes

  • cmd/hwygen/transformer.go, cmd/hwygen/transformer_ops.go: AVX2-only float64 exponent extraction + int64→float64 conversion.
  • cmd/hwygen/emitter.go: extend lazy-init of hoisted constants to AVX2.
  • Regenerated 11 packages' *_avx2.gen.go / *_avx512.gen.go.
  • hwy/contrib/algo/transform_test.go: added TestLogTransformFloat64 (the existing test only covered float32, which never hit the AVX-512-only instructions).

Verification

  • llvm-objdump of the regenerated BaseLogVec_avx2_Float64 (and a scan of all _avx2_ functions) confirms no AVX-512 (EVEX) instructions remain.
  • The int64→float64 magic constant was verified exact over the full exponent range [-1023, 1024].
  • Builds pass for linux/amd64, windows/amd64, and arm64 with GOEXPERIMENT=simd.
  • Full test suite passes, including hwygen golden tests and the new float64 Log test.

Note: the AVX2 path could not be executed locally (arm64 host; Rosetta lacks AVX2), so runtime confirmation relies on the disassembly check plus the verified arithmetic — CI on the AVX2-only runner exercises it.

Test plan

Closes #67
Closes #68
Closes #69

The hwygen AVX2 code path emitted instructions that crash with SIGILL on
CPUs that support AVX2 but not AVX-512, and broadcast constants that ran
before CPU-feature dispatch on CPUs without AVX2 at all.

Float64 Log (issues #67, #68): GetExponent generated Int64x4.ShiftAllRight
(VPSRAQ) and ConvertExponentToFloat generated Int64x4.ConvertToFloat64
(VCVTQQ2PD), both AVX-512-only. For the AVX2 target only, extract the
exponent with an unsigned logical shift (VPSRLQ) and convert int64->float64
via the magic-number trick (VPADDQ + reinterpret + VSUBPD), which is exact
over the exponent range. NEON keeps its native signed shift; AVX-512 keeps
the native ops since it only runs where they exist.

Hoisted constants (issue #69): the sync.Once lazy-init pattern was applied
only to AVX-512, so AVX2 broadcast constants still ran at package-init time
(before init() CPU detection) and SIGILL'd on non-AVX2 CPUs. Apply lazy init
to AVX2 as well, with target-specific helper names since the AVX2 and AVX512
files share a package and build tag.

Regenerated the affected *_avx2.gen.go/*_avx512.gen.go files and added a
float64 LogTransform regression test (the existing test only covered float32,
which never exercised the AVX-512-only instructions).
@ajroetker
ajroetker merged commit 796851d into main May 28, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant