diff --git a/libc/cmake/modules/LLVMLibCCheckCpuFeatures.cmake b/libc/cmake/modules/LLVMLibCCheckCpuFeatures.cmake index b97b03f7b07a8..9a18ac018d77f 100644 --- a/libc/cmake/modules/LLVMLibCCheckCpuFeatures.cmake +++ b/libc/cmake/modules/LLVMLibCCheckCpuFeatures.cmake @@ -44,44 +44,32 @@ function(_intersection output_var list1 list2) set(${output_var} ${tmp} PARENT_SCOPE) endfunction() -# Generates a cpp file to introspect the compiler defined flags. -function(_generate_check_code) +set(AVAILABLE_CPU_FEATURES "") +if(LIBC_CROSSBUILD) + # If we are doing a cross build, we will just assume that all CPU features + # are available. + set(AVAILABLE_CPU_FEATURES ${ALL_CPU_FEATURES}) +else() + # Try compile a C file to check if flag is supported. + set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) foreach(feature IN LISTS ALL_CPU_FEATURES) - set(DEFINITIONS - "${DEFINITIONS} -#ifdef __${feature}__ - \"${feature}\", -#endif") + try_compile( + has_feature + ${CMAKE_CURRENT_BINARY_DIR}/cpu_features + SOURCES ${LIBC_SOURCE_DIR}/cmake/modules/cpu_features/check_${feature}.cpp + COMPILE_DEFINITIONS -I${LIBC_SOURCE_DIR} ${LIBC_COMPILE_OPTIONS_NATIVE} + ) + if(has_feature) + list(APPEND AVAILABLE_CPU_FEATURES ${feature}) + endif() endforeach() - configure_file( - "${LIBC_SOURCE_DIR}/cmake/modules/cpu_features/check_cpu_features.cpp.in" - "cpu_features/check_cpu_features.cpp" @ONLY) -endfunction() -_generate_check_code() +endif() -set(LIBC_CPU_FEATURES "" CACHE PATH "Host supported CPU features") +set(LIBC_CPU_FEATURES ${AVAILABLE_CPU_FEATURES} CACHE STRING "Host supported CPU features") -if(LIBC_CROSSBUILD) - _intersection(cpu_features "${ALL_CPU_FEATURES}" "${LIBC_CPU_FEATURES}") - if(NOT "${cpu_features}" STREQUAL "${LIBC_CPU_FEATURES}") - message(FATAL_ERROR "Unsupported CPU features: ${cpu_features}") - endif() - message(STATUS "Set CPU features: ${cpu_features}") - set(LIBC_CPU_FEATURES "${cpu_features}") +_intersection(cpu_features "${AVAILABLE_CPU_FEATURES}" "${LIBC_CPU_FEATURES}") +if(NOT "${cpu_features}" STREQUAL "${LIBC_CPU_FEATURES}") + message(FATAL_ERROR "Unsupported CPU features: ${cpu_features}") else() - # Populates the LIBC_CPU_FEATURES list from host. - try_run( - run_result compile_result "${CMAKE_CURRENT_BINARY_DIR}/check_${feature}" - "${CMAKE_CURRENT_BINARY_DIR}/cpu_features/check_cpu_features.cpp" - COMPILE_DEFINITIONS ${LIBC_COMPILE_OPTIONS_NATIVE} - COMPILE_OUTPUT_VARIABLE compile_output - RUN_OUTPUT_VARIABLE run_output) - if("${run_result}" EQUAL 0) - message(STATUS "Set CPU features: ${run_output}") - set(LIBC_CPU_FEATURES "${run_output}") - elseif(NOT ${compile_result}) - message(FATAL_ERROR "Failed to compile: ${compile_output}") - else() - message(FATAL_ERROR "Failed to run: ${run_output}") - endif() + message(STATUS "Set CPU features: ${cpu_features}") endif() diff --git a/libc/cmake/modules/cpu_features/check_AVX2.cpp b/libc/cmake/modules/cpu_features/check_AVX2.cpp new file mode 100644 index 0000000000000..4330308ab836e --- /dev/null +++ b/libc/cmake/modules/cpu_features/check_AVX2.cpp @@ -0,0 +1,5 @@ +#include "src/__support/cpu_features.h" + +#ifndef LIBC_TARGET_HAS_AVX2 +#error unsupported +#endif diff --git a/libc/cmake/modules/cpu_features/check_AVX512BW.cpp b/libc/cmake/modules/cpu_features/check_AVX512BW.cpp new file mode 100644 index 0000000000000..4e8cfc2f10fab --- /dev/null +++ b/libc/cmake/modules/cpu_features/check_AVX512BW.cpp @@ -0,0 +1,5 @@ +#include "src/__support/cpu_features.h" + +#ifndef LIBC_TARGET_HAS_AVX512BW +#error unsupported +#endif diff --git a/libc/cmake/modules/cpu_features/check_AVX512F.cpp b/libc/cmake/modules/cpu_features/check_AVX512F.cpp new file mode 100644 index 0000000000000..8491654b692e9 --- /dev/null +++ b/libc/cmake/modules/cpu_features/check_AVX512F.cpp @@ -0,0 +1,5 @@ +#include "src/__support/cpu_features.h" + +#ifndef LIBC_TARGET_HAS_AVX512F +#error unsupported +#endif diff --git a/libc/cmake/modules/cpu_features/check_FMA.cpp b/libc/cmake/modules/cpu_features/check_FMA.cpp new file mode 100644 index 0000000000000..909875684ecfe --- /dev/null +++ b/libc/cmake/modules/cpu_features/check_FMA.cpp @@ -0,0 +1,5 @@ +#include "src/__support/cpu_features.h" + +#ifndef LIBC_TARGET_HAS_FMA +#error unsupported +#endif diff --git a/libc/cmake/modules/cpu_features/check_SSE2.cpp b/libc/cmake/modules/cpu_features/check_SSE2.cpp new file mode 100644 index 0000000000000..eee2dea2d5381 --- /dev/null +++ b/libc/cmake/modules/cpu_features/check_SSE2.cpp @@ -0,0 +1,5 @@ +#include "src/__support/cpu_features.h" + +#ifndef LIBC_TARGET_HAS_SSE2 +#error unsupported +#endif diff --git a/libc/cmake/modules/cpu_features/check_SSE4_2.cpp b/libc/cmake/modules/cpu_features/check_SSE4_2.cpp new file mode 100644 index 0000000000000..43586b25ed7d8 --- /dev/null +++ b/libc/cmake/modules/cpu_features/check_SSE4_2.cpp @@ -0,0 +1,5 @@ +#include "src/__support/cpu_features.h" + +#ifndef LIBC_TARGET_HAS_SSE4_2 +#error unsupported +#endif diff --git a/libc/cmake/modules/cpu_features/check_cpu_features.cpp.in b/libc/cmake/modules/cpu_features/check_cpu_features.cpp.in deleted file mode 100644 index 7a3fc037c300a..0000000000000 --- a/libc/cmake/modules/cpu_features/check_cpu_features.cpp.in +++ /dev/null @@ -1,32 +0,0 @@ -#include -#include - -// This file is instantiated by CMake. -// DEFINITIONS below is replaced with a set of lines like so: -// #ifdef __SSE2__ -// "SSE2", -// #endif -// -// This allows for introspection of compiler definitions. -// The output of the program is a single line of semi colon separated feature -// names. - -// MSVC is using a different set of preprocessor definitions for -// SSE and SSE2, see _M_IX86_FP in -// https://docs.microsoft.com/en-us/cpp/preprocessor/predefined-macros - -int main(int, char **) { - const char *strings[] = { - @DEFINITIONS@ - // If DEFINITIONS turns out to be empty, we don't want to list - // an empty array. So, we add an end of list marker. - "" - }; - const size_t size = sizeof(strings) / sizeof(strings[0]); - for (size_t i = 0; i < size; ++i) { - if (i) - putchar(';'); - fputs(strings[i], stdout); - } - return EXIT_SUCCESS; -} diff --git a/libc/src/__support/CMakeLists.txt b/libc/src/__support/CMakeLists.txt index 2526d0cd56dba..9ea67c7da50be 100644 --- a/libc/src/__support/CMakeLists.txt +++ b/libc/src/__support/CMakeLists.txt @@ -33,6 +33,7 @@ add_header_library( HDRS architectures.h common.h + cpu_features.h endian.h ) diff --git a/libc/src/__support/FPUtil/FMA.h b/libc/src/__support/FPUtil/FMA.h index f14a978f53e06..7b0dbe4c1a928 100644 --- a/libc/src/__support/FPUtil/FMA.h +++ b/libc/src/__support/FPUtil/FMA.h @@ -11,6 +11,7 @@ #include "src/__support/architectures.h" #include "src/__support/common.h" +#include "src/__support/cpu_features.h" #if defined(LIBC_TARGET_HAS_FMA) diff --git a/libc/src/__support/FPUtil/aarch64/FMA.h b/libc/src/__support/FPUtil/aarch64/FMA.h index f742197e0477f..1591c9b9ee091 100644 --- a/libc/src/__support/FPUtil/aarch64/FMA.h +++ b/libc/src/__support/FPUtil/aarch64/FMA.h @@ -10,6 +10,7 @@ #define LLVM_LIBC_SRC_SUPPORT_FPUTIL_AARCH64_FMA_H #include "src/__support/architectures.h" +#include "src/__support/cpu_features.h" #if !defined(LLVM_LIBC_ARCH_AARCH64) #error "Invalid include" diff --git a/libc/src/__support/FPUtil/multiply_add.h b/libc/src/__support/FPUtil/multiply_add.h index 384035e76840c..27f0081e803e5 100644 --- a/libc/src/__support/FPUtil/multiply_add.h +++ b/libc/src/__support/FPUtil/multiply_add.h @@ -11,6 +11,7 @@ #include "src/__support/architectures.h" #include "src/__support/common.h" +#include "src/__support/cpu_features.h" namespace __llvm_libc { namespace fputil { diff --git a/libc/src/__support/FPUtil/x86_64/FMA.h b/libc/src/__support/FPUtil/x86_64/FMA.h index 40da101952c4a..43b144331ce5c 100644 --- a/libc/src/__support/FPUtil/x86_64/FMA.h +++ b/libc/src/__support/FPUtil/x86_64/FMA.h @@ -11,6 +11,7 @@ #include "src/__support/architectures.h" #include "src/__support/common.h" +#include "src/__support/cpu_features.h" #if !defined(LLVM_LIBC_ARCH_X86_64) #error "Invalid include" diff --git a/libc/src/__support/architectures.h b/libc/src/__support/architectures.h index d3106daf12caa..af97469f60b09 100644 --- a/libc/src/__support/architectures.h +++ b/libc/src/__support/architectures.h @@ -49,12 +49,4 @@ #define LLVM_LIBC_ARCH_ANY_ARM #endif -#if defined(LLVM_LIBC_ARCH_AARCH64) -#define LIBC_TARGET_HAS_FMA -#elif defined(LLVM_LIBC_ARCH_X86_64) -#if (defined(__AVX2__) || defined(__FMA__)) -#define LIBC_TARGET_HAS_FMA -#endif -#endif - #endif // LLVM_LIBC_SUPPORT_ARCHITECTURES_H diff --git a/libc/src/__support/cpu_features.h b/libc/src/__support/cpu_features.h new file mode 100644 index 0000000000000..c3ecd351b68f1 --- /dev/null +++ b/libc/src/__support/cpu_features.h @@ -0,0 +1,43 @@ +//===-- Compile time cpu feature detection ----------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// This file lists target cpu features by introspecting compiler enabled +// preprocessor definitions. +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIBC_SRC_SUPPORT_CPU_FEATURES_H +#define LLVM_LIBC_SRC_SUPPORT_CPU_FEATURES_H + +#if defined(__SSE2__) +#define LIBC_TARGET_HAS_SSE2 +#endif + +#if defined(__SSE4_2__) +#define LIBC_TARGET_HAS_SSE4_2 +#endif + +#if defined(__AVX__) +#define LIBC_TARGET_HAS_AVX +#endif + +#if defined(__AVX2__) +#define LIBC_TARGET_HAS_AVX2 +#endif + +#if defined(__AVX512F__) +#define LIBC_TARGET_HAS_AVX512F +#endif + +#if defined(__AVX512BW__) +#define LIBC_TARGET_HAS_AVX512BW +#endif + +#if defined(__ARM_FEATURE_FMA) || defined(__AVX2__) +#define LIBC_TARGET_HAS_FMA +#endif + +#endif // LLVM_LIBC_SRC_SUPPORT_CPU_FEATURES_H diff --git a/libc/src/math/generic/asinf.cpp b/libc/src/math/generic/asinf.cpp index 7314b3868090b..1b38e8dc3e859 100644 --- a/libc/src/math/generic/asinf.cpp +++ b/libc/src/math/generic/asinf.cpp @@ -13,6 +13,7 @@ #include "src/__support/FPUtil/except_value_utils.h" #include "src/__support/FPUtil/multiply_add.h" #include "src/__support/FPUtil/sqrt.h" +#include "src/__support/cpu_features.h" #include diff --git a/libc/src/math/generic/cosf.cpp b/libc/src/math/generic/cosf.cpp index ebccc99dab04c..fce60cdcb723d 100644 --- a/libc/src/math/generic/cosf.cpp +++ b/libc/src/math/generic/cosf.cpp @@ -14,6 +14,7 @@ #include "src/__support/FPUtil/except_value_utils.h" #include "src/__support/FPUtil/multiply_add.h" #include "src/__support/common.h" +#include "src/__support/cpu_features.h" #include diff --git a/libc/src/math/generic/expm1f.cpp b/libc/src/math/generic/expm1f.cpp index 6c187b838acdb..8b57522be0761 100644 --- a/libc/src/math/generic/expm1f.cpp +++ b/libc/src/math/generic/expm1f.cpp @@ -16,6 +16,7 @@ #include "src/__support/FPUtil/multiply_add.h" #include "src/__support/FPUtil/nearest_integer.h" #include "src/__support/common.h" +#include "src/__support/cpu_features.h" #include diff --git a/libc/src/math/generic/sincosf.cpp b/libc/src/math/generic/sincosf.cpp index 25a59bd915e95..991eb32b1468c 100644 --- a/libc/src/math/generic/sincosf.cpp +++ b/libc/src/math/generic/sincosf.cpp @@ -12,6 +12,7 @@ #include "src/__support/FPUtil/FPBits.h" #include "src/__support/FPUtil/multiply_add.h" #include "src/__support/common.h" +#include "src/__support/cpu_features.h" #include diff --git a/libc/src/math/generic/sincosf_utils.h b/libc/src/math/generic/sincosf_utils.h index 38ee2784de5a9..809ceff1d7c51 100644 --- a/libc/src/math/generic/sincosf_utils.h +++ b/libc/src/math/generic/sincosf_utils.h @@ -12,6 +12,7 @@ #include "src/__support/FPUtil/FPBits.h" #include "src/__support/FPUtil/PolyEval.h" #include "src/__support/common.h" +#include "src/__support/cpu_features.h" #if defined(LIBC_TARGET_HAS_FMA) #include "range_reduction_fma.h" diff --git a/libc/src/math/generic/sinf.cpp b/libc/src/math/generic/sinf.cpp index cae25a74381b5..836df2887825d 100644 --- a/libc/src/math/generic/sinf.cpp +++ b/libc/src/math/generic/sinf.cpp @@ -14,6 +14,7 @@ #include "src/__support/FPUtil/PolyEval.h" #include "src/__support/FPUtil/multiply_add.h" #include "src/__support/common.h" +#include "src/__support/cpu_features.h" #include diff --git a/libc/src/math/generic/tanf.cpp b/libc/src/math/generic/tanf.cpp index 0deb968047400..8b720c48e5dec 100644 --- a/libc/src/math/generic/tanf.cpp +++ b/libc/src/math/generic/tanf.cpp @@ -15,6 +15,7 @@ #include "src/__support/FPUtil/multiply_add.h" #include "src/__support/FPUtil/nearest_integer.h" #include "src/__support/common.h" +#include "src/__support/cpu_features.h" #include diff --git a/libc/src/math/generic/tanhf.cpp b/libc/src/math/generic/tanhf.cpp index 22b95870f4c69..8b6771b768821 100644 --- a/libc/src/math/generic/tanhf.cpp +++ b/libc/src/math/generic/tanhf.cpp @@ -8,6 +8,7 @@ #include "src/math/tanhf.h" #include "src/__support/FPUtil/FPBits.h" +#include "src/__support/cpu_features.h" #include "src/math/generic/explogxf.h" namespace __llvm_libc { diff --git a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel index 3d2a8d59eb542..2088391847891 100644 --- a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel +++ b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel @@ -79,6 +79,7 @@ libc_support_library( hdrs = [ "src/__support/architectures.h", "src/__support/common.h", + "src/__support/cpu_features.h", "src/__support/endian.h", ], )