From 4be3c4948d7e50a672fe17dbd0448ee741380bbe Mon Sep 17 00:00:00 2001 From: Tony Davis Date: Thu, 29 Jan 2026 13:16:53 -0600 Subject: [PATCH 1/2] Add Windows support for GNU-style Clang and OpenMP 2.0 compatibility This patch enables BLIS to build on Windows using Clang compilers with GNU-style command-line interface (e.g., LLVM/Clang, not Clang-CL) and adds compatibility for systems with OpenMP 2.0 implementations. Changes: 1. CMakeLists.txt: Detect Clang with GNU frontend on Windows - Check CMAKE_C_COMPILER_FRONTEND_VARIANT to distinguish GNU-style Clang from MSVC-style Clang-CL - Use -fopenmp-simd for GNU-style Clang on Windows - Maintains backward compatibility with MSVC toolchain 2. frame/thread/bli_thread.c: Add OpenMP 2.0 compatibility shims - Provide fallback implementations for omp_get_active_level() and omp_get_max_active_levels() (OpenMP 3.0 functions) - Windows SDK and some legacy OpenMP implementations only support OpenMP 2.0 - Shims safely disable nested parallelism (rare in BLAS workloads) - Zero performance overhead on systems with OpenMP 3.0+ Testing: - Validated on Windows with TheRock's LLVM/Clang toolchain - Builds successfully with OpenMP threading enabled - ILP64 support functional - Zen4-optimized kernels compile and link correctly Rationale: This enables BLIS to be built with consistent toolchains across Linux and Windows platforms, supporting projects that use custom LLVM builds rather than platform-default compilers. Signed-off-by: Tony Davis Co-authored-by: Cursor --- CMakeLists.txt | 8 +++++++- frame/thread/bli_thread.c | 12 ++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c3160475b4..c808b64032 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1135,7 +1135,13 @@ endif() # --- #pragma omp simd flags (used for reference kernels only) --- if(PRAGMA_OMP_SIMD) if(WIN32) - set(COMPSIMDFLAGS /openmp:experimental) + # Check if using Clang with GNU-like command-line (not MSVC/Clang-CL) + if(CMAKE_C_COMPILER_ID STREQUAL "Clang" AND + CMAKE_C_COMPILER_FRONTEND_VARIANT STREQUAL "GNU") + set(COMPSIMDFLAGS -fopenmp-simd) + else() + set(COMPSIMDFLAGS /openmp:experimental) + endif() else() set(COMPSIMDFLAGS -fopenmp-simd) endif() diff --git a/frame/thread/bli_thread.c b/frame/thread/bli_thread.c index 03bc1b0a08..2d2f223c32 100644 --- a/frame/thread/bli_thread.c +++ b/frame/thread/bli_thread.c @@ -35,6 +35,18 @@ #include "blis.h" +// OpenMP 2.0 compatibility: Provide fallbacks for OpenMP 3.0 functions +// Microsoft Visual Studio's OpenMP only supports OpenMP 2.0 +// Note: omp.h is already included by blis.h when BLIS_ENABLE_OPENMP is defined +#if defined(BLIS_ENABLE_OPENMP) && defined(_MSC_VER) +static inline int omp_get_active_level(void) { + return 0; // Always assume top-level (no nested parallelism support) +} +static inline int omp_get_max_active_levels(void) { + return 1; // OpenMP 2.0 doesn't support nested parallelism +} +#endif + thrinfo_t BLIS_PACKM_SINGLE_THREADED = {}; thrinfo_t BLIS_GEMM_SINGLE_THREADED = {}; thrcomm_t BLIS_SINGLE_COMM = {}; From 8f7876b63ced58b38dc8e45aca491cac777b40e5 Mon Sep 17 00:00:00 2001 From: Tony Davis Date: Thu, 29 Jan 2026 14:21:42 -0600 Subject: [PATCH 2/2] Simplify to only OpenMP 2.0 compatibility fix - Remove Clang-specific CMake changes (not needed for MSVC use case) - Use _OPENMP version check instead of _MSC_VER for better portability - _OPENMP < 200811 detects any OpenMP 2.x implementation (200203 = 2.0, 200811 = 3.0) - More future-proof: won't break when MSVC adds OpenMP 3.0 support - Thanks to GitHub Copilot for suggesting this improvement Co-authored-by: Copilot Co-authored-by: Cursor --- CMakeLists.txt | 8 +------- frame/thread/bli_thread.c | 8 ++++++-- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c808b64032..c3160475b4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1135,13 +1135,7 @@ endif() # --- #pragma omp simd flags (used for reference kernels only) --- if(PRAGMA_OMP_SIMD) if(WIN32) - # Check if using Clang with GNU-like command-line (not MSVC/Clang-CL) - if(CMAKE_C_COMPILER_ID STREQUAL "Clang" AND - CMAKE_C_COMPILER_FRONTEND_VARIANT STREQUAL "GNU") - set(COMPSIMDFLAGS -fopenmp-simd) - else() - set(COMPSIMDFLAGS /openmp:experimental) - endif() + set(COMPSIMDFLAGS /openmp:experimental) else() set(COMPSIMDFLAGS -fopenmp-simd) endif() diff --git a/frame/thread/bli_thread.c b/frame/thread/bli_thread.c index 2d2f223c32..d7d3276785 100644 --- a/frame/thread/bli_thread.c +++ b/frame/thread/bli_thread.c @@ -36,9 +36,13 @@ #include "blis.h" // OpenMP 2.0 compatibility: Provide fallbacks for OpenMP 3.0 functions -// Microsoft Visual Studio's OpenMP only supports OpenMP 2.0 +// Some compilers (e.g., MSVC, older GCC) only support OpenMP 2.0 which lacks: +// - omp_get_active_level() (OpenMP 3.0) +// - omp_get_max_active_levels() (OpenMP 3.0) +// The _OPENMP macro is set to version-specific values by OpenMP-compliant compilers: +// 200203 = OpenMP 2.0, 200811 = OpenMP 3.0, 201107 = OpenMP 3.1, etc. // Note: omp.h is already included by blis.h when BLIS_ENABLE_OPENMP is defined -#if defined(BLIS_ENABLE_OPENMP) && defined(_MSC_VER) +#if defined(BLIS_ENABLE_OPENMP) && defined(_OPENMP) && _OPENMP < 200811 static inline int omp_get_active_level(void) { return 0; // Always assume top-level (no nested parallelism support) }