[clang] Avoid linking libdl unless needed
[llvm-project.git] / libc / cmake / modules / LLVMLibCCheckCpuFeatures.cmake
blob0bb4af869487b3bbb33783f4bb40823e51a234d6
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)
7 endif()
9 list(SORT ALL_CPU_FEATURES)
11 # Function to check whether the host supports the provided set of features.
12 # Usage:
13 # host_supports(
14 #   <output variable>
15 #   <list of cpu features>
16 # )
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)
21   else()
22     unset(${output_var} PARENT_SCOPE)
23   endif()
24 endfunction()
26 # Function to compute the flags to pass down to the compiler.
27 # Usage:
28 # compute_flags(
29 #   <output variable>
30 #   MARCH <arch name or "native">
31 #   REQUIRE <list of mandatory features to enable>
32 #   REJECT <list of features to disable>
33 # )
34 function(compute_flags output_var)
35   cmake_parse_arguments(
36     "COMPUTE_FLAGS"
37     "" # Optional arguments
38     "MARCH" # Single value arguments
39     "REQUIRE;REJECT" # Multi value arguments
40     ${ARGN})
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})
44     if(var)
45       message(FATAL_ERROR "Cpu Features REQUIRE and REJECT ${var}")
46     endif()
47   endif()
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}")
52     endif()
53     foreach(feature IN LISTS COMPUTE_FLAGS_REQUIRE)
54       string(TOLOWER ${feature} lowercase_feature)
55       list(APPEND current "-m${lowercase_feature}")
56     endforeach()
57     foreach(feature IN LISTS COMPUTE_FLAGS_REJECT)
58       string(TOLOWER ${feature} lowercase_feature)
59       list(APPEND current "-mno-${lowercase_feature}")
60     endforeach()
61   else()
62     # In future, we can extend for other compilers.
63     message(FATAL_ERROR "Unkown compiler ${CMAKE_CXX_COMPILER_ID}.")
64   endif()
65   # Export the list of flags.
66   set(${output_var} "${current}" PARENT_SCOPE)
67 endfunction()
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}")
78     endif()
79   endforeach()
80   set(${output_var} ${tmp} PARENT_SCOPE)
81 endfunction()
83 # Generates a cpp file to introspect the compiler defined flags.
84 function(_generate_check_code)
85   foreach(feature IN LISTS ALL_CPU_FEATURES)
86     set(DEFINITIONS
87         "${DEFINITIONS}
88 #ifdef __${feature}__
89     \"${feature}\",
90 #endif")
91   endforeach()
92   configure_file(
93     "${LIBC_SOURCE_DIR}/cmake/modules/cpu_features/check_cpu_features.cpp.in"
94     "cpu_features/check_cpu_features.cpp" @ONLY)
95 endfunction()
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(
103     "CHECK_DEFINED"
104     "" # Optional arguments
105     "MARCH" # Single value arguments
106     "REQUIRE;REJECT" # Multi value arguments
107     ${ARGN})
108   compute_flags(
109     flags
110     MARCH  ${CHECK_DEFINED_MARCH}
111     REQUIRE ${CHECK_DEFINED_REQUIRE}
112     REJECT  ${CHECK_DEFINED_REJECT})
113   try_run(
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))
120     set(${output_var}
121         "${run_output}"
122         PARENT_SCOPE)
123   else()
124     message(FATAL_ERROR "${compile_output}")
125   endif()
126 endfunction()
128 # Populates the HOST_CPU_FEATURES list.
129 _check_defined_cpu_feature(HOST_CPU_FEATURES MARCH native)