diff --git a/libc/cmake/modules/LLVMLibCCheckCpuFeatures.cmake b/libc/cmake/modules/LLVMLibCCheckCpuFeatures.cmake new file mode 100644 --- /dev/null +++ b/libc/cmake/modules/LLVMLibCCheckCpuFeatures.cmake @@ -0,0 +1,53 @@ +set(ALL_CPU_FEATURES) + +# Defines a cpu feature +# - Adds the feature to ALL_CPU_FEATURES +# - Defines enabling and disabling flags for the feature +# CPU_FEATURES__ENABLE_FLAG +# CPU_FEATURES__DISABLE_FLAG +function(define_cpu_feature_optimization name) + cmake_parse_arguments( + "DCFO" + "" # No optional arguments + "CLANG_FLAG" # Single value arguments + "" # Multi value arguments + ${ARGN} + ) + list(APPEND ALL_CPU_FEATURES ${name}) + set(ALL_CPU_FEATURES ${ALL_CPU_FEATURES} PARENT_SCOPE) + set(CPU_FEATURES_${name}_ENABLE_FLAG "-m${DCFO_CLANG_FLAG}" PARENT_SCOPE) + set(CPU_FEATURES_${name}_DISABLE_FLAG "-mno-${DCFO_CLANG_FLAG}" PARENT_SCOPE) +endfunction() + +if(${LIBC_TARGET_MACHINE} MATCHES "x86|x86_64") + define_cpu_feature_optimization(SSE CLANG_FLAG sse) + define_cpu_feature_optimization(SSE2 CLANG_FLAG sse2) + define_cpu_feature_optimization(AVX CLANG_FLAG avx) + define_cpu_feature_optimization(AVX512F CLANG_FLAG avx512f) +endif() + +set(HOST_CPU_FEATURES) +function(check_cpu_features feature) + if(NOT ${feature} IN_LIST ALL_CPU_FEATURES) + message(FATAL_ERROR "${feature} is not part of available ${ALL_CPU_FEATURES}") + endif() + string(TOLOWER ${feature} lowercase_feature) + try_run( + run_result + compile_result + "${CMAKE_CURRENT_BINARY_DIR}/check_${lowercase_feature}" + "${CMAKE_MODULE_PATH}/cpu_features/check_${lowercase_feature}.cpp" + COMPILE_DEFINITIONS ${CPU_FEATURES_${feature}_ENABLE_FLAG} + OUTPUT_VARIABLE compile_output + ) + if(${compile_result} AND ("${run_result}" EQUAL 0)) + list(APPEND HOST_CPU_FEATURES ${feature}) + set(HOST_CPU_FEATURES ${HOST_CPU_FEATURES} PARENT_SCOPE) + endif() +endfunction() + +# Tests the host system against all cpu features and populates +# HOST_CPU_FEATURES with a subset of ALL_CPU_FEATURES. +foreach(feature IN LISTS ALL_CPU_FEATURES) + check_cpu_features(${feature}) +endforeach(feature) diff --git a/libc/cmake/modules/cpu_features/check_avx.cpp b/libc/cmake/modules/cpu_features/check_avx.cpp new file mode 100644 --- /dev/null +++ b/libc/cmake/modules/cpu_features/check_avx.cpp @@ -0,0 +1,8 @@ +#if !defined __AVX__ +#error "missing __AVX__" +#endif +#include +int main() { + (void)_mm256_set1_epi8('0'); + return 0; +} diff --git a/libc/cmake/modules/cpu_features/check_avx512f.cpp b/libc/cmake/modules/cpu_features/check_avx512f.cpp new file mode 100644 --- /dev/null +++ b/libc/cmake/modules/cpu_features/check_avx512f.cpp @@ -0,0 +1,8 @@ +#if !defined __AVX512F__ +#error "missing __AVX512F__" +#endif +#include +int main() { + (void)_mm512_undefined(); + return 0; +} diff --git a/libc/cmake/modules/cpu_features/check_sse.cpp b/libc/cmake/modules/cpu_features/check_sse.cpp new file mode 100644 --- /dev/null +++ b/libc/cmake/modules/cpu_features/check_sse.cpp @@ -0,0 +1,8 @@ +#if !defined __SSE__ +#error "missing __SSE__" +#endif +#include +int main() { + (void)_mm_set_ss(1.0f); + return 0; +} diff --git a/libc/cmake/modules/cpu_features/check_sse2.cpp b/libc/cmake/modules/cpu_features/check_sse2.cpp new file mode 100644 --- /dev/null +++ b/libc/cmake/modules/cpu_features/check_sse2.cpp @@ -0,0 +1,8 @@ +#if !defined __SSE2__ +#error "missing __SSE2__" +#endif +#include +int main() { + (void)_mm_set1_epi8('0'); + return 0; +}