Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,10 @@ jobs:
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
# macos-15-intel compiles the AVX2 kernels with AppleClang, the only
# toolchain that rejects '#pragma GCC target' - it guards the exact
# wheel-build configuration used by the macOS Intel release job.
os: [ubuntu-latest, windows-latest, macos-latest, macos-15-intel]
steps:
- uses: actions/checkout@v7
- name: Configure MSVC
Expand Down
2 changes: 1 addition & 1 deletion src/v2_simd.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
// Instruction-set-specific kernels are isolated in dedicated translation
// units so vector code can never leak into baseline compilation:
//
// v2_simd_avx2.cpp x86-64 AVX2 kernels (in-source '#pragma GCC target',
// v2_simd_avx2.cpp x86-64 AVX2 kernels (per-function target attribute,
// or MSVC '/arch:AVX2' scoped to that file)
// v2_simd_neon.cpp AArch64 NEON kernels (baseline ISA, no flags needed)
// v2_simd_crc.cpp AArch64 CRC-32 extension (optional, runtime-probed)
Expand Down
28 changes: 14 additions & 14 deletions src/v2_simd_avx2.cpp
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
// WIMF v2 AVX2 kernels.
//
// GCC/Clang enable AVX2 in-source via '#pragma GCC target' so no global
// compiler flag is needed and other translation units stay baseline-portable.
// MSVC has no per-function ISA selection, so the build system must compile
// this file with '/arch:AVX2' (CMake scopes that flag to this file only).
// The whole unit is skipped unless WIMF_SIMD_ENABLE_AVX2 is defined.
// GCC, Clang, and AppleClang enable AVX2 per function via
// '__attribute__((target("avx2")))' so no global compiler flag is needed and
// other translation units stay baseline-portable. AppleClang rejects the
// GCC-style '#pragma GCC target' form, which is why the attribute is applied
// to each kernel directly. MSVC has no per-function ISA selection, so the
// build system must compile this file with '/arch:AVX2' (CMake scopes that
// flag to this file only). The whole unit is skipped unless
// WIMF_SIMD_ENABLE_AVX2 is defined.

#include "v2_simd.hpp"

Expand All @@ -14,16 +17,17 @@
#error "WIMF_SIMD_ENABLE_AVX2 requires /arch:AVX2 when compiling with MSVC"
#endif

#if defined(__GNUC__) || defined(__clang__)
#pragma GCC push_options
#pragma GCC target("avx2")
#if defined(_MSC_VER)
#define WIMF_AVX2_TARGET
#else
#define WIMF_AVX2_TARGET __attribute__((target("avx2")))
#endif

#include <immintrin.h>

namespace wimf::v2::simd::avx2 {

uint64_t left_filter_cost(const uint8_t* row, size_t width) noexcept {
WIMF_AVX2_TARGET uint64_t left_filter_cost(const uint8_t* row, size_t width) noexcept {
if (width == 0) return 0;
uint64_t cost = row[0] <= 128 ? row[0] : 256u - row[0];
const __m256i zero = _mm256_setzero_si256();
Expand All @@ -50,7 +54,7 @@ uint64_t left_filter_cost(const uint8_t* row, size_t width) noexcept {
return cost;
}

void left_filter_emit(const uint8_t* row, uint8_t* out, size_t width) noexcept {
WIMF_AVX2_TARGET void left_filter_emit(const uint8_t* row, uint8_t* out, size_t width) noexcept {
if (width == 0) return;
out[0] = row[0];
size_t x = 1;
Expand All @@ -64,8 +68,4 @@ void left_filter_emit(const uint8_t* row, uint8_t* out, size_t width) noexcept {

} // namespace wimf::v2::simd::avx2

#if defined(__GNUC__) || defined(__clang__)
#pragma GCC pop_options
#endif

#endif // WIMF_AVX2_KERNELS
Loading