# Distributed under the OSI-approved BSD 3-Clause License. See accompanying # file Copyright.txt or https://cmake.org/licensing for details. #[=======================================================================[.rst: CheckCompilerMachineOption ------------------------------- Check compiler flag for machine optimization. Returns compiler flag for specified feature such as SSE AVX2 if available. if not available, return "". .. command:: check_compiler_machine_option compiler_machine_option( ) #]=======================================================================] include(CheckCCompilerFlag) include(CheckCXXCompilerFlag) include(CheckIncludeFileCXX) include(CheckIncludeFile) function(check_compiler_machine_option outvar feature) macro(__check_compiler_flag _flag _result) if(CMAKE_CXX_COMPILER_LOADED) check_cxx_compiler_flag("${_flag}" ${_result}) elseif(CMAKE_C_COMPILER_LOADED) check_c_compiler_flag("${_flag}" ${_result}) endif() endmacro() set(_FLAGS) if("${CMAKE_SYSTEM_PROCESSOR}" MATCHES "(x86|AMD64)") if(MSVC AND (${feature} MATCHES "SSE")) # SSE2 and SSE are default on set(_FLAGS " ") elseif(MSVC) # Only Visual Studio 2017 version 15.3 / Visual C++ 19.11 & up have support for AVX-512. # https://blogs.msdn.microsoft.com/vcblog/2017/07/11/microsoft-visual-studio-2017-supports-intel-avx-512/ set(MSVC_FLAG_MAP AVX512 "-arch:AVX512" AVX2 "-arch:AVX2" AVX "-arch:AVX") list(FIND MSVC_FLAG_MAP ${feature} _found) if(_found GREATER -1) math(EXPR index "${_found}+1") list(GET MSVC_FLAG_MAP ${index} _flag) __check_compiler_flag("${_flag}" test_${feature}) if(test_${feature}) set(_FLAGS "${_flag}") endif() endif() elseif(CMAKE_CXX_COMPILER MATCHES "/(icpc|icc)$") # ICC (on Linux) set(map_flag AVX2 "-xCORE_AVX2" AVX "-xAVX" SSE4_2 "-xSSE4.2" SSE4_1 "-xSSE4.1" SSSE3 "-xSSSE3" AVX512 "-xCORE-AVX512;-xMIC-AVX512" ) list(FIND map_flag "${feature}" _found) if(_found GREATER -1) math(EXPR index "${_found}+1") list(GET map_flag ${index} _flag) foreach(flag IN ITEMS ${_flag}) __check_compiler_flag(${_flag} _ok) if(_ok) set(_FLAGS ${_flag}) break() endif() endforeach() endif() else() # not MSVC and not ICC => GCC, Clang, Open64 string(TOLOWER ${feature} _flag) string(REPLACE "_" "." _flag "${_flag}") __check_compiler_flag("-m${_flag}" test_${_flag}) if(test_${_flag}) set(header_table "sse" "xmmintrin.h" "sse2" "emmintrin.h" "sse3" "pmmintrin.h" "ssse3" "tmmintrin.h" "sse4.1" "smmintrin.h" "sse4.2" "smmintrin.h" "sse4a" "ammintrin.h" "avx" "immintrin.h" "avx2" "immintrin.h" "fma4" "x86intrin.h" "xop" "x86intrin.h") set(_header FALSE) list(FIND header_table ${_flag} _found) if(_found GREATER -1) math(EXPR index "${_found} + 1") list(GET header_table ${index} _header) endif() set(_resultVar "HAVE_${_header}") string(REPLACE "." "_" _resultVar "${_resultVar}") if(_header) if(CMAKE_CXX_COMPILER_LOADED) check_include_file_cxx("${_header}" ${_resultVar} "-m${_flag}") elseif(CMAKE_C_COMPILER_LOADED) check_include_file("${_header}" ${_resultVar} "-m${_flag}") endif() if(NOT _header OR ${_resultVar}) set(_FLAGS "-m${_flag}") endif() endif() endif() endif() elseif("${CMAKE_SYSTEM_PROCESSOR}" MATCHES "(ARM|aarch64)") if(MSVC) # TODO implement me elseif(CMAKE_CXX_COMPILER MATCHES "/(icpc|icc)$") # ICC (on Linux) # TODO implement me else() # not MSVC and not ICC => GCC, Clang, Open64 string(TOLOWER ${feature} _flag) __check_compiler_flag("-m${_flag}" test_${_flag}) if(test_${_flag}) set(_FLAGS "-m${_flag}") endif() endif() endif() set(${outvar} "${_FLAGS}" PARENT_SCOPE) endfunction()