You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

156 lines
4.7 KiB

# This script checks for the highest level of AVX support on the host
# by compiling and running small C++ programs that use AVX intrinsics.
#
# You can invoke this module using the following command:
#
# FIND_PACKAGE(AVX [major[.minor]] [EXACT] [QUIET|REQUIRED])
#
# where the version string is one of:
#
# 1.0 for AVX support
# 2.0 for AVX2 support
#
# Note that any ".0" in the above version string is optional.
#
# If any AVX support is detected, the following variables are set:
#
# AVX_FOUND = 1
# AVX_VERSION = the requested version, if EXACT is true, or
# the highest AVX version found.
# AVX_FLAGS = compile flags for the version of AVX found
#
# If AVX is not supported on the host platform, these variables are
# not set. If QUIET is true, the module does not print a message if
# AVX if missing. If REQUIRED is true, the module produces a fatal
# error if AVX support is missing.
#
set(AVX_FLAGS)
set(AVX_FOUND)
set(DETECTED_AVX_10)
set(DETECTED_AVX_20)
if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX)
execute_process(COMMAND ${CMAKE_CXX_COMPILER} "-dumpversion" OUTPUT_VARIABLE GCC_VERSION_STRING)
if(GCC_VERSION_STRING VERSION_GREATER 4.2 AND NOT APPLE AND NOT CMAKE_CROSSCOMPILING)
SET(AVX_FLAGS "${AVX_FLAGS} -march=native")
message(STATUS "Using CPU native flags for AVX optimization: ${AVX_FLAGS}")
endif()
endif()
include(CheckCXXSourceRuns)
set(CMAKE_REQUIRED_FLAGS)
# Generate a list of AVX versions to test.
if(AVX_FIND_VERSION_EXACT)
if(AVX_FIND_VERSION VERSION_EQUAL "2.0")
set(_AVX_TEST_20 1)
elseif(AVX_FIND_VERSION VERSION_EQUAL "1.0")
set(_AVX_TEST_10 1)
endif()
else()
if(NOT AVX_FIND_VERSION VERSION_GREATER "2.0")
set(_AVX_TEST_20 1)
endif()
if(NOT AVX_FIND_VERSION VERSION_GREATER "1.0")
set(_AVX_TEST_10 1)
endif()
endif()
# Check for AVX2 support.
if(_AVX_TEST_20)
if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
set(CMAKE_REQUIRED_FLAGS "-mavx2")
elseif(CMAKE_CXX_COMPILER_ID MATCHES "Intel")
set(CMAKE_REQUIRED_FLAGS "-xHost")
elseif(MSVC AND NOT CMAKE_CL_64)
set(CMAKE_REQUIRED_FLAGS "/arch:AVX2")
endif()
check_cxx_source_runs("
#include <immintrin.h>
int main()
{
__m256i a = _mm256_set_epi32 (-1, 2, -3, 4, -1, 2, -3, 4);
__m256i result = _mm256_abs_epi32 (a);
return 0;
}" DETECTED_AVX_20)
endif()
# Check for AVX support.
if(_AVX_TEST_10)
if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
set(CMAKE_REQUIRED_FLAGS "-mavx")
elseif(CMAKE_CXX_COMPILER_ID MATCHES "Intel")
set(CMAKE_REQUIRED_FLAGS "-xHost")
elseif(MSVC AND NOT CMAKE_CL_64)
set(CMAKE_REQUIRED_FLAGS "/arch:AVX")
endif()
check_cxx_source_runs("
#include <immintrin.h>
int main()
{
__m256 a = _mm256_set_ps (-1.0f, 2.0f, -3.0f, 4.0f, -1.0f, 2.0f, -3.0f, 4.0f);
__m256 b = _mm256_set_ps (1.0f, 2.0f, 3.0f, 4.0f, 1.0f, 2.0f, 3.0f, 4.0f);
__m256 result = _mm256_add_ps (a, b);
return 0;
}" DETECTED_AVX_10)
endif()
set(CMAKE_REQUIRED_FLAGS)
if(DETECTED_AVX_20)
set(AVX_VERSION "2.0")
set(AVX_STR "2_0")
set(AVX_FOUND 1)
elseif(DETECTED_AVX_10)
set(AVX_VERSION "1.0")
set(AVX_STR "1_0")
set(AVX_FOUND 1)
endif()
if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
if(DETECTED_AVX_20)
SET(AVX_FLAGS "${AVX_FLAGS} -mavx2")
elseif(DETECTED_AVX_10)
SET(AVX_FLAGS "${AVX_FLAGS} -mavx")
endif()
# TODO: Check for AVX512 support
SET(AVX_FLAGS "${AVX_FLAGS} -mno-avx512f -mno-avx512pf -mno-avx512er -mno-avx512cd")
elseif(CMAKE_CXX_COMPILER_ID MATCHES "Intel")
set(AVX_FLAGS "-xHost")
elseif(MSVC)
if(DETECTED_AVX_20)
SET(AVX_FLAGS "${AVX_FLAGS} /arch:AVX2")
elseif(DETECTED_AVX_10)
SET(AVX_FLAGS "${AVX_FLAGS} /arch:AVX")
endif()
endif()
if(AVX_FOUND)
message(STATUS " Found AVX ${AVX_VERSION} extensions, using flags: ${AVX_FLAGS}")
else()
message(STATUS " No AVX support found")
set(AVX_FLAGS "")
endif()
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${AVX_FLAGS}")
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} ${AVX_FLAGS}")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} ${AVX_FLAGS}")
return()
#-------------------------------------
# If no AVX support is found, print an error message.
if(AVX_FIND_VERSION)
set(_AVX_ERROR_MESSAGE "AVX ${AVX_FIND_VERSION} support is not found on this architecture")
else()
set(_AVX_ERROR_MESSAGE "AVX support is not found on this architecture")
endif()
if(AVX_FIND_REQUIRED)
message(FATAL_ERROR "${_AVX_ERROR_MESSAGE}")
elseif(NOT AVX_FIND_QUIETLY)
message(STATUS "${_AVX_ERROR_MESSAGE}")
endif()