1# ------------------------------------------------------------------------------
2# Cpu features definition and flags
3# ------------------------------------------------------------------------------
4
5# Initialize ALL_CPU_FEATURES as empty list.
6set(ALL_CPU_FEATURES "")
7
8if(${LIBC_TARGET_ARCHITECTURE_IS_X86})
9  set(ALL_CPU_FEATURES SSE2 SSE4_2 AVX2 AVX512F)
10  set(LIBC_COMPILE_OPTIONS_NATIVE -march=native)
11elseif(${LIBC_TARGET_ARCHITECTURE_IS_AARCH64})
12  set(LIBC_COMPILE_OPTIONS_NATIVE -mcpu=native)
13endif()
14
15# Making sure ALL_CPU_FEATURES is sorted.
16list(SORT ALL_CPU_FEATURES)
17
18# Function to check whether the target CPU supports the provided set of features.
19# Usage:
20# cpu_supports(
21#   <output variable>
22#   <list of cpu features>
23# )
24function(cpu_supports output_var features)
25  _intersection(var "${LIBC_CPU_FEATURES}" "${features}")
26  if("${var}" STREQUAL "${features}")
27    set(${output_var} TRUE PARENT_SCOPE)
28  else()
29    unset(${output_var} PARENT_SCOPE)
30  endif()
31endfunction()
32
33# ------------------------------------------------------------------------------
34# Internal helpers and utilities.
35# ------------------------------------------------------------------------------
36
37# Computes the intersection between two lists.
38function(_intersection output_var list1 list2)
39  foreach(element IN LISTS list1)
40    if("${list2}" MATCHES "(^|;)${element}(;|$)")
41      list(APPEND tmp "${element}")
42    endif()
43  endforeach()
44  set(${output_var} ${tmp} PARENT_SCOPE)
45endfunction()
46
47# Generates a cpp file to introspect the compiler defined flags.
48function(_generate_check_code)
49  foreach(feature IN LISTS ALL_CPU_FEATURES)
50    set(DEFINITIONS
51        "${DEFINITIONS}
52#ifdef __${feature}__
53    \"${feature}\",
54#endif")
55  endforeach()
56  configure_file(
57    "${LIBC_SOURCE_DIR}/cmake/modules/cpu_features/check_cpu_features.cpp.in"
58    "cpu_features/check_cpu_features.cpp" @ONLY)
59endfunction()
60_generate_check_code()
61
62set(LIBC_CPU_FEATURES "" CACHE PATH "Host supported CPU features")
63
64if(CMAKE_CROSSCOMPILING)
65  _intersection(cpu_features "${ALL_CPU_FEATURES}" "${LIBC_CPU_FEATURES}")
66  if(NOT "${cpu_features}" STREQUAL "${LIBC_CPU_FEATURES}")
67    message(FATAL_ERROR "Unsupported CPU features: ${cpu_features}")
68  endif()
69  set(LIBC_CPU_FEATURES "${cpu_features}")
70else()
71  # Populates the LIBC_CPU_FEATURES list from host.
72  try_run(
73    run_result compile_result "${CMAKE_CURRENT_BINARY_DIR}/check_${feature}"
74    "${CMAKE_CURRENT_BINARY_DIR}/cpu_features/check_cpu_features.cpp"
75    COMPILE_DEFINITIONS ${LIBC_COMPILE_OPTIONS_NATIVE}
76    COMPILE_OUTPUT_VARIABLE compile_output
77    RUN_OUTPUT_VARIABLE run_output)
78  if("${run_result}" EQUAL 0)
79    set(LIBC_CPU_FEATURES "${run_output}")
80  elseif(NOT ${compile_result})
81    message(FATAL_ERROR "Failed to compile: ${compile_output}")
82  else()
83    message(FATAL_ERROR "Failed to run: ${run_output}")
84  endif()
85endif()
86