1 # ------------------------------------------------------------------------------
2 # Cpu features definition and flags
3 # ------------------------------------------------------------------------------
5 if(${LIBC_TARGET_MACHINE} MATCHES "x86|x86_64")
6 set(ALL_CPU_FEATURES SSE SSE2 AVX AVX2 AVX512F)
9 list(SORT ALL_CPU_FEATURES)
11 # Function to check whether the host supports the provided set of features.
15 # <list of cpu features>
17 function(host_supports output_var features)
18 _intersection(a "${HOST_CPU_FEATURES}" "${features}")
19 if("${a}" STREQUAL "${features}")
20 set(${output_var} TRUE PARENT_SCOPE)
22 unset(${output_var} PARENT_SCOPE)
26 # Function to compute the flags to pass down to the compiler.
30 # MARCH <arch name or "native">
31 # REQUIRE <list of mandatory features to enable>
32 # REJECT <list of features to disable>
34 function(compute_flags output_var)
35 cmake_parse_arguments(
37 "" # Optional arguments
38 "MARCH" # Single value arguments
39 "REQUIRE;REJECT" # Multi value arguments
41 # Check that features are not required and rejected at the same time.
42 if(COMPUTE_FLAGS_REQUIRE AND COMPUTE_FLAGS_REJECT)
43 _intersection(var ${COMPUTE_FLAGS_REQUIRE} ${COMPUTE_FLAGS_REJECT})
45 message(FATAL_ERROR "Cpu Features REQUIRE and REJECT ${var}")
48 # Generate the compiler flags in `current`.
49 if(${CMAKE_CXX_COMPILER_ID} MATCHES "Clang|GNU")
50 if(COMPUTE_FLAGS_MARCH)
51 list(APPEND current "-march=${COMPUTE_FLAGS_MARCH}")
53 foreach(feature IN LISTS COMPUTE_FLAGS_REQUIRE)
54 string(TOLOWER ${feature} lowercase_feature)
55 list(APPEND current "-m${lowercase_feature}")
57 foreach(feature IN LISTS COMPUTE_FLAGS_REJECT)
58 string(TOLOWER ${feature} lowercase_feature)
59 list(APPEND current "-mno-${lowercase_feature}")
62 # In future, we can extend for other compilers.
63 message(FATAL_ERROR "Unkown compiler ${CMAKE_CXX_COMPILER_ID}.")
65 # Export the list of flags.
66 set(${output_var} "${current}" PARENT_SCOPE)
69 # ------------------------------------------------------------------------------
70 # Internal helpers and utilities.
71 # ------------------------------------------------------------------------------
73 # Computes the intersection between two lists.
74 function(_intersection output_var list1 list2)
75 foreach(element IN LISTS list1)
76 if("${list2}" MATCHES "(^|;)${element}(;|$)")
77 list(APPEND tmp "${element}")
80 set(${output_var} ${tmp} PARENT_SCOPE)
83 # Generates a cpp file to introspect the compiler defined flags.
84 function(_generate_check_code)
85 foreach(feature IN LISTS ALL_CPU_FEATURES)
93 "${LIBC_SOURCE_DIR}/cmake/modules/cpu_features/check_cpu_features.cpp.in"
94 "cpu_features/check_cpu_features.cpp" @ONLY)
96 _generate_check_code()
98 # Compiles and runs the code generated above with the specified requirements.
99 # This is helpful to infer which features a particular target supports or if
100 # a specific features implies other features (e.g. BMI2 implies SSE2 and SSE).
101 function(_check_defined_cpu_feature output_var)
102 cmake_parse_arguments(
104 "" # Optional arguments
105 "MARCH" # Single value arguments
106 "REQUIRE;REJECT" # Multi value arguments
110 MARCH ${CHECK_DEFINED_MARCH}
111 REQUIRE ${CHECK_DEFINED_REQUIRE}
112 REJECT ${CHECK_DEFINED_REJECT})
114 run_result compile_result "${CMAKE_CURRENT_BINARY_DIR}/check_${feature}"
115 "${CMAKE_CURRENT_BINARY_DIR}/cpu_features/check_cpu_features.cpp"
116 COMPILE_DEFINITIONS ${flags}
117 COMPILE_OUTPUT_VARIABLE compile_output
118 RUN_OUTPUT_VARIABLE run_output)
119 if(${compile_result} AND ("${run_result}" EQUAL 0))
124 message(FATAL_ERROR "${compile_output}")
128 # Populates the HOST_CPU_FEATURES list.
129 _check_defined_cpu_feature(HOST_CPU_FEATURES MARCH native)