[reland][libc][NFC] Detect host CPU features using try_compile instead of try_run.
authorGuillaume Chatelet <gchatelet@google.com>
Tue, 24 Jan 2023 16:04:10 +0000 (16:04 +0000)
committerGuillaume Chatelet <gchatelet@google.com>
Tue, 24 Jan 2023 16:04:10 +0000 (16:04 +0000)
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

24 files changed:
libc/cmake/modules/LLVMLibCCheckCpuFeatures.cmake
libc/cmake/modules/cpu_features/check_AVX2.cpp [new file with mode: 0644]
libc/cmake/modules/cpu_features/check_AVX512BW.cpp [new file with mode: 0644]
libc/cmake/modules/cpu_features/check_AVX512F.cpp [new file with mode: 0644]
libc/cmake/modules/cpu_features/check_FMA.cpp [new file with mode: 0644]
libc/cmake/modules/cpu_features/check_SSE2.cpp [new file with mode: 0644]
libc/cmake/modules/cpu_features/check_SSE4_2.cpp [new file with mode: 0644]
libc/cmake/modules/cpu_features/check_cpu_features.cpp.in [deleted file]
libc/src/__support/CMakeLists.txt
libc/src/__support/FPUtil/FMA.h
libc/src/__support/FPUtil/aarch64/FMA.h
libc/src/__support/FPUtil/multiply_add.h
libc/src/__support/FPUtil/x86_64/FMA.h
libc/src/__support/architectures.h
libc/src/__support/cpu_features.h [new file with mode: 0644]
libc/src/math/generic/asinf.cpp
libc/src/math/generic/cosf.cpp
libc/src/math/generic/expm1f.cpp
libc/src/math/generic/sincosf.cpp
libc/src/math/generic/sincosf_utils.h
libc/src/math/generic/sinf.cpp
libc/src/math/generic/tanf.cpp
libc/src/math/generic/tanhf.cpp
utils/bazel/llvm-project-overlay/libc/BUILD.bazel

index b97b03f..9a18ac0 100644 (file)
@@ -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 (file)
index 0000000..4330308
--- /dev/null
@@ -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 (file)
index 0000000..4e8cfc2
--- /dev/null
@@ -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 (file)
index 0000000..8491654
--- /dev/null
@@ -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 (file)
index 0000000..9098756
--- /dev/null
@@ -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 (file)
index 0000000..eee2dea
--- /dev/null
@@ -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 (file)
index 0000000..43586b2
--- /dev/null
@@ -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 (file)
index 7a3fc03..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-#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;
-}
index 2526d0c..9ea67c7 100644 (file)
@@ -33,6 +33,7 @@ add_header_library(
   HDRS
     architectures.h
     common.h
+    cpu_features.h
     endian.h
 )
 
index f14a978..7b0dbe4 100644 (file)
@@ -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)
 
index f742197..1591c9b 100644 (file)
@@ -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"
index 384035e..27f0081 100644 (file)
@@ -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 {
index 40da101..43b1443 100644 (file)
@@ -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"
index d3106da..af97469 100644 (file)
 #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 (file)
index 0000000..68bf6fa
--- /dev/null
@@ -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__) || defined(__FMA__)
+#define LIBC_TARGET_HAS_FMA
+#endif
+
+#endif // LLVM_LIBC_SRC_SUPPORT_CPU_FEATURES_H
index 7314b38..1b38e8d 100644 (file)
@@ -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 <errno.h>
 
index ebccc99..fce60cd 100644 (file)
@@ -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 <errno.h>
 
index 6c187b8..8b57522 100644 (file)
@@ -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 <errno.h>
 
index 25a59bd..991eb32 100644 (file)
@@ -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 <errno.h>
 
index a193216..358c1cf 100644 (file)
@@ -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"
index cae25a7..836df28 100644 (file)
@@ -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 <errno.h>
 
index 0deb968..8b720c4 100644 (file)
@@ -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 <errno.h>
 
index 22b9587..8b6771b 100644 (file)
@@ -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 {
index be4dafd..e9d3a55 100644 (file)
@@ -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",
     ],
 )