Fix compilation on clang-cl.exe (#1355)

Fixes https://github.com/ikawrakow/ik_llama.cpp/issues/1169

See bitwise ariphmetics here: https://clang.llvm.org/doxygen/avx512fintrin_8h_source.html

Clang (and GCC) supports a language feature called Vector Extensions.

To Clang, `__m512i` is not just a "struct" or a "bag of bits"; it is recognized by the compiler as a native vector type.
Because it is a native vector type, Clang automatically maps standard C operators to the corresponding hardware instructions.
When you write `a | b`, Clang sees that a and b are 512-bit integer vectors.
It implicitly understands that the bitwise OR operator (|) applies to these vectors.
It automatically generates the VPORQ (or VPORD) instruction without needing any helper function.

MSVC follows a stricter, more traditional C++ model regarding intrinsics.

In MSVC, __m512i is defined in the header files (<immintrin.h>) as a struct or union (e.g., typedef struct __m512i { ... } __m512i). To the MSVC compiler, it is essentially a user-defined data type, not a fundamental language primitive like int or float.
Standard C++ does not define what `|` means for a user-defined struct.
MSVC does not have the same "Vector Extensions" that automatically apply operators to these structs.
When you write `a | b` in MSVC, the compiler looks for a definition of `operator|` for the __m512i struct. Since the standard headers don't provide one, the compiler throws an error.
You must use the explicit intrinsic function provided by Intel/MSVC: _mm512_or_si512(a, b).

To get the nice syntax `(a | b)` in MSVC, you have to manually "teach" the compiler what `|` means by defining the `operator|` overload yourself.
This commit is contained in:
mullecofo
2026-03-04 07:00:28 +00:00
committed by GitHub
parent fd16a418de
commit 2f93bf7563

View File

@@ -83,10 +83,12 @@ static inline float32x4_t v_gelu(float32x4_t x, float32x4_t c1, float32x4_t c2)
#if defined(__AVX512F__) && defined(_MSC_VER)
#include <immintrin.h>
#ifndef __clang__
static inline __m512i operator|(__m512i a, __m512i b) { return _mm512_or_si512(a, b); }
static inline __m512i operator&(__m512i a, __m512i b) { return _mm512_and_si512(a, b); }
static inline __m512i operator^(__m512i a, __m512i b) { return _mm512_xor_si512(a, b); }
#endif
#endif
#if defined(__AVX512F__) && defined(__AVX512DQ__)