This implements the same behavior as D141997 but makes sure that the same detection mechanism is used between CMake and source code.
Differential Revision: https://reviews.llvm.org/D142108
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()
--- /dev/null
+#include "src/__support/cpu_features.h"
+
+#ifndef LIBC_TARGET_HAS_AVX2
+#error unsupported
+#endif
--- /dev/null
+#include "src/__support/cpu_features.h"
+
+#ifndef LIBC_TARGET_HAS_AVX512BW
+#error unsupported
+#endif
--- /dev/null
+#include "src/__support/cpu_features.h"
+
+#ifndef LIBC_TARGET_HAS_AVX512F
+#error unsupported
+#endif
--- /dev/null
+#include "src/__support/cpu_features.h"
+
+#ifndef LIBC_TARGET_HAS_FMA
+#error unsupported
+#endif
--- /dev/null
+#include "src/__support/cpu_features.h"
+
+#ifndef LIBC_TARGET_HAS_SSE2
+#error unsupported
+#endif
--- /dev/null
+#include "src/__support/cpu_features.h"
+
+#ifndef LIBC_TARGET_HAS_SSE4_2
+#error unsupported
+#endif
+++ /dev/null
-#include <stdio.h>
-#include <stdlib.h>
-
-// 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.
- "<end_of_feature_list>"
- };
- 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;
-}
HDRS
architectures.h
common.h
+ cpu_features.h
endian.h
)
#include "src/__support/architectures.h"
#include "src/__support/common.h"
+#include "src/__support/cpu_features.h"
#if defined(LIBC_TARGET_HAS_FMA)
#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"
#include "src/__support/architectures.h"
#include "src/__support/common.h"
+#include "src/__support/cpu_features.h"
namespace __llvm_libc {
namespace fputil {
#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"
#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
--- /dev/null
+//===-- 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__) || defined(__FMA__)
+#define LIBC_TARGET_HAS_FMA
+#endif
+
+#endif // LLVM_LIBC_SRC_SUPPORT_CPU_FEATURES_H
#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 <errno.h>
#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 <errno.h>
#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 <errno.h>
#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 <errno.h>
#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"
#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 <errno.h>
#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 <errno.h>
#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 {
hdrs = [
"src/__support/architectures.h",
"src/__support/common.h",
+ "src/__support/cpu_features.h",
"src/__support/endian.h",
],
)