blob: 86c3822c864c03f9dca0bd3aa23067f9636c3b35 [file] [log] [blame]
Guillaume Chatelet04a309d2020-02-11 13:37:02 +01001# ------------------------------------------------------------------------------
Guillaume Chatelet1aab0552020-02-20 15:00:45 +01002# Cpu features definition and flags
Guillaume Chatelet04a309d2020-02-11 13:37:02 +01003# ------------------------------------------------------------------------------
Guillaume Chatelet1aab0552020-02-20 15:00:45 +01004
5if(${LIBC_TARGET_MACHINE} MATCHES "x86|x86_64")
Guillaume Chatelet04a309d2020-02-11 13:37:02 +01006 set(ALL_CPU_FEATURES SSE SSE2 AVX AVX2 AVX512F)
Siva Chandrac76a1d0f2020-06-10 10:55:00 -07007 list(SORT ALL_CPU_FEATURES)
Guillaume Chatelet1aab0552020-02-20 15:00:45 +01008endif()
9
Guillaume Chatelet04a309d2020-02-11 13:37:02 +010010# Function to check whether the host supports the provided set of features.
11# Usage:
12# host_supports(
13# <output variable>
14# <list of cpu features>
15# )
16function(host_supports output_var features)
17 _intersection(a "${HOST_CPU_FEATURES}" "${features}")
18 if("${a}" STREQUAL "${features}")
19 set(${output_var} TRUE PARENT_SCOPE)
20 else()
21 unset(${output_var} PARENT_SCOPE)
22 endif()
23endfunction()
24
25# Function to compute the flags to pass down to the compiler.
26# Usage:
27# compute_flags(
28# <output variable>
29# MARCH <arch name or "native">
30# REQUIRE <list of mandatory features to enable>
31# REJECT <list of features to disable>
32# )
33function(compute_flags output_var)
34 cmake_parse_arguments(
35 "COMPUTE_FLAGS"
36 "" # Optional arguments
37 "MARCH" # Single value arguments
38 "REQUIRE;REJECT" # Multi value arguments
39 ${ARGN})
40 # Check that features are not required and rejected at the same time.
41 if(COMPUTE_FLAGS_REQUIRE AND COMPUTE_FLAGS_REJECT)
42 _intersection(var ${COMPUTE_FLAGS_REQUIRE} ${COMPUTE_FLAGS_REJECT})
43 if(var)
44 message(FATAL_ERROR "Cpu Features REQUIRE and REJECT ${var}")
45 endif()
46 endif()
47 # Generate the compiler flags in `current`.
48 if(${CMAKE_CXX_COMPILER_ID} MATCHES "Clang|GNU")
49 if(COMPUTE_FLAGS_MARCH)
50 list(APPEND current "-march=${COMPUTE_FLAGS_MARCH}")
51 endif()
52 foreach(feature IN LISTS COMPUTE_FLAGS_REQUIRE)
53 string(TOLOWER ${feature} lowercase_feature)
54 list(APPEND current "-m${lowercase_feature}")
55 endforeach()
56 foreach(feature IN LISTS COMPUTE_FLAGS_REJECT)
57 string(TOLOWER ${feature} lowercase_feature)
58 list(APPEND current "-mno-${lowercase_feature}")
59 endforeach()
Guillaume Chatelet1aab0552020-02-20 15:00:45 +010060 else()
61 # In future, we can extend for other compilers.
62 message(FATAL_ERROR "Unkown compiler ${CMAKE_CXX_COMPILER_ID}.")
63 endif()
Guillaume Chatelet04a309d2020-02-11 13:37:02 +010064 # Export the list of flags.
65 set(${output_var} "${current}" PARENT_SCOPE)
Guillaume Chatelet1aab0552020-02-20 15:00:45 +010066endfunction()
67
Guillaume Chatelet04a309d2020-02-11 13:37:02 +010068# ------------------------------------------------------------------------------
69# Internal helpers and utilities.
70# ------------------------------------------------------------------------------
Guillaume Chatelet1aab0552020-02-20 15:00:45 +010071
Guillaume Chatelet04a309d2020-02-11 13:37:02 +010072# Computes the intersection between two lists.
73function(_intersection output_var list1 list2)
74 foreach(element IN LISTS list1)
75 if("${list2}" MATCHES "(^|;)${element}(;|$)")
76 list(APPEND tmp "${element}")
Guillaume Chatelet1aab0552020-02-20 15:00:45 +010077 endif()
78 endforeach()
Guillaume Chatelet04a309d2020-02-11 13:37:02 +010079 set(${output_var} ${tmp} PARENT_SCOPE)
Guillaume Chatelet1aab0552020-02-20 15:00:45 +010080endfunction()
81
Guillaume Chatelet04a309d2020-02-11 13:37:02 +010082# Generates a cpp file to introspect the compiler defined flags.
83function(_generate_check_code)
84 foreach(feature IN LISTS ALL_CPU_FEATURES)
85 set(DEFINITIONS
86 "${DEFINITIONS}
87#ifdef __${feature}__
88 \"${feature}\",
89#endif")
Guillaume Chatelet1aab0552020-02-20 15:00:45 +010090 endforeach()
Guillaume Chatelet04a309d2020-02-11 13:37:02 +010091 configure_file(
92 "${LIBC_SOURCE_DIR}/cmake/modules/cpu_features/check_cpu_features.cpp.in"
93 "cpu_features/check_cpu_features.cpp" @ONLY)
Guillaume Chatelet1aab0552020-02-20 15:00:45 +010094endfunction()
Guillaume Chatelet04a309d2020-02-11 13:37:02 +010095_generate_check_code()
Guillaume Chatelet1aab0552020-02-20 15:00:45 +010096
Guillaume Chatelet04a309d2020-02-11 13:37:02 +010097# Compiles and runs the code generated above with the specified requirements.
98# This is helpful to infer which features a particular target supports or if
99# a specific features implies other features (e.g. BMI2 implies SSE2 and SSE).
100function(_check_defined_cpu_feature output_var)
101 cmake_parse_arguments(
102 "CHECK_DEFINED"
103 "" # Optional arguments
104 "MARCH" # Single value arguments
105 "REQUIRE;REJECT" # Multi value arguments
106 ${ARGN})
107 compute_flags(
108 flags
109 MARCH ${CHECK_DEFINED_MARCH}
110 REQUIRE ${CHECK_DEFINED_REQUIRE}
111 REJECT ${CHECK_DEFINED_REJECT})
Guillaume Chatelet1aab0552020-02-20 15:00:45 +0100112 try_run(
Guillaume Chatelet04a309d2020-02-11 13:37:02 +0100113 run_result compile_result "${CMAKE_CURRENT_BINARY_DIR}/check_${feature}"
114 "${CMAKE_CURRENT_BINARY_DIR}/cpu_features/check_cpu_features.cpp"
115 COMPILE_DEFINITIONS ${flags}
116 COMPILE_OUTPUT_VARIABLE compile_output
117 RUN_OUTPUT_VARIABLE run_output)
Guillaume Chatelet1aab0552020-02-20 15:00:45 +0100118 if(${compile_result} AND ("${run_result}" EQUAL 0))
Guillaume Chatelet04a309d2020-02-11 13:37:02 +0100119 set(${output_var}
120 "${run_output}"
121 PARENT_SCOPE)
122 else()
123 message(FATAL_ERROR "${compile_output}")
Guillaume Chatelet1aab0552020-02-20 15:00:45 +0100124 endif()
125endfunction()
126
Guillaume Chatelet04a309d2020-02-11 13:37:02 +0100127# Populates the HOST_CPU_FEATURES list.
Siva Chandrac76a1d0f2020-06-10 10:55:00 -0700128# Use -march=native only when the compiler supports it.
129include(CheckCXXCompilerFlag)
130CHECK_CXX_COMPILER_FLAG("-march=native" COMPILER_SUPPORTS_MARCH_NATIVE)
131if(COMPILER_SUPPORTS_MARCH_NATIVE)
132 _check_defined_cpu_feature(HOST_CPU_FEATURES MARCH native)
133else()
134 _check_defined_cpu_feature(HOST_CPU_FEATURES)
135endif()