From 0d2db459a52912b0d7c7419662dd24d8c7c2bda5 Mon Sep 17 00:00:00 2001 From: Raghuveer Devulapalli Date: Mon, 16 Feb 2026 04:25:51 +0000 Subject: [PATCH 1/2] =?UTF-8?q?SIMD:=20simplify=20AVX=E2=80=91512=20detect?= =?UTF-8?q?ion=20and=20check=20OS=20level=20support?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replaces manual CPUID bit parsing in jvector_simd_check.c with __builtin_cpu_supports and adds __builtin_cpu_init(). This corrects missing XSAVE runtime checks, preventing #UD exceptions on systems where 512‑bit register state saves are disabled. --- .../src/main/c/jvector_simd_check.c | 24 ++++++------------- 1 file changed, 7 insertions(+), 17 deletions(-) diff --git a/jvector-native/src/main/c/jvector_simd_check.c b/jvector-native/src/main/c/jvector_simd_check.c index bf134805e..c09f0897b 100644 --- a/jvector-native/src/main/c/jvector_simd_check.c +++ b/jvector-native/src/main/c/jvector_simd_check.c @@ -18,20 +18,10 @@ #include "jvector_simd.h" bool check_compatibility(void) { - unsigned int eax, ebx, ecx, edx; - bool avx512f_supported = false, avx512cd_supported = false, - avx512bw_supported = false, avx512dq_supported = false, - avx512vl_supported = false; - - // Check for AVX-512 Foundation (AVX-512F) and other AVX-512 features: - // These are indicated by various bits of EBX from leaf 7, sub-leaf 0. - if (__get_cpuid_count(7, 0, &eax, &ebx, &ecx, &edx)) { - avx512f_supported = ebx & (1 << 16); // AVX-512F - avx512cd_supported = ebx & (1 << 28); // AVX-512CD - avx512bw_supported = ebx & (1 << 30); // AVX-512BW - avx512dq_supported = ebx & (1 << 17); // AVX-512DQ - avx512vl_supported = ebx & (1 << 31); // AVX-512VL - } - - return avx512f_supported && avx512cd_supported && avx512bw_supported && avx512dq_supported && avx512vl_supported; -} \ No newline at end of file + __builtin_cpu_init(); + return (__builtin_cpu_supports("avx512f") && + __builtin_cpu_supports("avx512cd") && + __builtin_cpu_supports("avx512dq") && + __builtin_cpu_supports("avx512bw") && + __builtin_cpu_supports("avx512vl")); +} From 05c3ed95108424b74150117357114eb2f60b6636 Mon Sep 17 00:00:00 2001 From: Raghuveer Devulapalli Date: Mon, 16 Feb 2026 04:44:32 +0000 Subject: [PATCH 2/2] Rename check_compatibility to check_avx512_compatibility --- jvector-native/src/main/c/jvector_simd.c | 2 +- jvector-native/src/main/c/jvector_simd.h | 2 +- .../src/main/c/jvector_simd_check.c | 5 +++- .../vector/NativeVectorizationProvider.java | 2 +- .../jvector/vector/cnative/NativeSimdOps.java | 30 +++++++++---------- 5 files changed, 22 insertions(+), 19 deletions(-) diff --git a/jvector-native/src/main/c/jvector_simd.c b/jvector-native/src/main/c/jvector_simd.c index d9c909c0f..6bfde3f9a 100644 --- a/jvector-native/src/main/c/jvector_simd.c +++ b/jvector-native/src/main/c/jvector_simd.c @@ -26,7 +26,7 @@ __m512i maskEighthBit; __attribute__((constructor)) void initialize_constants() { - if (check_compatibility()) { + if (check_avx512_compatibility()) { initialIndexRegister = _mm512_setr_epi32(-16, -15, -14, -13, -12, -11, -10, -9, -8, -7, -6, -5, -4, -3, -2, -1); indexIncrement = _mm512_set1_epi32(16); diff --git a/jvector-native/src/main/c/jvector_simd.h b/jvector-native/src/main/c/jvector_simd.h index 55f1a46c1..39da01316 100644 --- a/jvector-native/src/main/c/jvector_simd.h +++ b/jvector-native/src/main/c/jvector_simd.h @@ -20,7 +20,7 @@ #define VECTOR_SIMD_DOT_H // check CPU support -bool check_compatibility(void); +bool check_avx512_compatibility(void); //F32 float dot_product_f32(int preferred_size, const float* a, int aoffset, const float* b, int boffset, int length); diff --git a/jvector-native/src/main/c/jvector_simd_check.c b/jvector-native/src/main/c/jvector_simd_check.c index c09f0897b..50736e85a 100644 --- a/jvector-native/src/main/c/jvector_simd_check.c +++ b/jvector-native/src/main/c/jvector_simd_check.c @@ -17,7 +17,10 @@ #include #include "jvector_simd.h" -bool check_compatibility(void) { +bool check_avx512_compatibility(void) { + /* __builtin_cpu_init required when this is used in ifunc + resolver/__attribute__((constructor)) context, otherwise the CPU + features may not be detected correctly. */ __builtin_cpu_init(); return (__builtin_cpu_supports("avx512f") && __builtin_cpu_supports("avx512cd") && diff --git a/jvector-native/src/main/java/io/github/jbellis/jvector/vector/NativeVectorizationProvider.java b/jvector-native/src/main/java/io/github/jbellis/jvector/vector/NativeVectorizationProvider.java index 7bb4fa514..5194e1108 100644 --- a/jvector-native/src/main/java/io/github/jbellis/jvector/vector/NativeVectorizationProvider.java +++ b/jvector-native/src/main/java/io/github/jbellis/jvector/vector/NativeVectorizationProvider.java @@ -35,7 +35,7 @@ public NativeVectorizationProvider() { if (!libraryLoaded) { throw new UnsupportedOperationException("Failed to load supporting native library."); } - if (!NativeSimdOps.check_compatibility()) { + if (!NativeSimdOps.check_avx512_compatibility()) { throw new UnsupportedOperationException("Native SIMD operations are not supported on this platform due to missing CPU support."); } this.vectorUtilSupport = new NativeVectorUtilSupport(); diff --git a/jvector-native/src/main/java/io/github/jbellis/jvector/vector/cnative/NativeSimdOps.java b/jvector-native/src/main/java/io/github/jbellis/jvector/vector/cnative/NativeSimdOps.java index 014bdf4b0..5bf5b2f01 100644 --- a/jvector-native/src/main/java/io/github/jbellis/jvector/vector/cnative/NativeSimdOps.java +++ b/jvector-native/src/main/java/io/github/jbellis/jvector/vector/cnative/NativeSimdOps.java @@ -96,11 +96,11 @@ public static int __bool_true_false_are_defined() { return __bool_true_false_are_defined; } - private static class check_compatibility { + private static class check_avx512_compatibility { public static final FunctionDescriptor DESC = FunctionDescriptor.of( NativeSimdOps.C_BOOL ); - public static final MemorySegment ADDR = NativeSimdOps.findOrThrow("check_compatibility"); + public static final MemorySegment ADDR = NativeSimdOps.findOrThrow("check_avx512_compatibility"); public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC, Linker.Option.critical(true)); } @@ -108,43 +108,43 @@ private static class check_compatibility { /** * Function descriptor for: * {@snippet lang=c : - * _Bool check_compatibility() + * _Bool check_avx512_compatibility() * } */ - public static FunctionDescriptor check_compatibility$descriptor() { - return check_compatibility.DESC; + public static FunctionDescriptor check_avx512_compatibility$descriptor() { + return check_avx512_compatibility.DESC; } /** * Downcall method handle for: * {@snippet lang=c : - * _Bool check_compatibility() + * _Bool check_avx512_compatibility() * } */ - public static MethodHandle check_compatibility$handle() { - return check_compatibility.HANDLE; + public static MethodHandle check_avx512_compatibility$handle() { + return check_avx512_compatibility.HANDLE; } /** * Address for: * {@snippet lang=c : - * _Bool check_compatibility() + * _Bool check_avx512_compatibility() * } */ - public static MemorySegment check_compatibility$address() { - return check_compatibility.ADDR; + public static MemorySegment check_avx512_compatibility$address() { + return check_avx512_compatibility.ADDR; } /** * {@snippet lang=c : - * _Bool check_compatibility() + * _Bool check_avx512_compatibility() * } */ - public static boolean check_compatibility() { - var mh$ = check_compatibility.HANDLE; + public static boolean check_avx512_compatibility() { + var mh$ = check_avx512_compatibility.HANDLE; try { if (TRACE_DOWNCALLS) { - traceDowncall("check_compatibility"); + traceDowncall("check_avx512_compatibility"); } return (boolean)mh$.invokeExact(); } catch (Throwable ex$) {