option(WITH_SIMD "Enable best platform specific vector instruction support" ON) cmake_dependent_option(WITH_AVX2 "Compile AVX2 optimizations." ON "WITH_SIMD" OFF) if(WITH_SSE2) message(WARNING "WITH_SSE2 is deprecated, use WITH_SIMD instead") set(WITH_SIMD ON CACHE BOOL "WITH_SSE2") endif() if(WITH_NEON) message(WARNING "WITH_NEON is deprecated, use WITH_SIMD instead") set(WITH_SIMD ON CACHE BOOL "WITH_NEON") endif() macro(set_simd_source_file_properties INTRINSIC_TYPE) if(ARGC LESS_EQUAL 1) message(FATAL_ERROR "set_simd_source_file_properties called with invalid arguments: [${ARGC}] {${ARGN}") endif() # see https://cmake.org/cmake/help/latest/variable/CMAKE_LANG_COMPILER_ID.html set(GCC_CLANG_NAMES "AppleClang;Clang;CrayClang;FujitsuClang;GNU;IntelLLVM;TIClang;XLClang;IBMClang") set(SSE_X86_LIST "i686;x86") set(SSE_LIST "x86_64;ia64;x64;amd64;ia64;em64t;${SSE_X86_LIST}") set(NEON_LIST "arm;armv7;armv8b;armv8l") set(SUPPORTED_INTRINSICS_LIST "neon;sse2;sse3;ssse3;sse4.1;sse4.2;avx2") string(TOLOWER "${CMAKE_SYSTEM_PROCESSOR}" SYSTEM_PROCESSOR) if(NOT "${INTRINSIC_TYPE}" IN_LIST SUPPORTED_INTRINSICS_LIST) message(WARNING "Intrinsic type ${INTRINSIC_TYPE} not supported, only ${SUPPORTED_INTRINSICS_LIST} are available") else() set(SIMD_LINK_ARG "") if(MSVC) # https://learn.microsoft.com/en-us/cpp/build/reference/arch-x64?view=msvc-140 if("${SYSTEM_PROCESSOR}" IN_LIST SSE_LIST) if("${SYSTEM_PROCESSOR}" IN_LIST SSE_X86_LIST) # /arch:SSE2 is the default, so do nothing set(SIMD_LINK_ARG "ignore") if("${INTRINSIC_TYPE}" STREQUAL "avx2") set(SIMD_LINK_ARG "/arch:AVX2") endif() else() # /arch:SSE2 is the default, so do nothing set(SIMD_LINK_ARG "ignore") if("${INTRINSIC_TYPE}" STREQUAL "sse4.2") set(SIMD_LINK_ARG "/arch:SSE4.2") elseif("${INTRINSIC_TYPE}" STREQUAL "avx2") set(SIMD_LINK_ARG "/arch:AVX2") endif() endif() endif() elseif("${CMAKE_C_COMPILER_ID}" IN_LIST GCC_CLANG_NAMES) set(HAVE_SSE_AVX OFF) foreach(ARCH ${CMAKE_OSX_ARCHITECTURES}) if("${ARCH}" IN_LIST SSE_LIST) set(HAVE_SSE_AVX ON) endif() endforeach() if("${SYSTEM_PROCESSOR}" IN_LIST SSE_LIST OR HAVE_SSE_AVX) if("${INTRINSIC_TYPE}" STREQUAL "sse2") set(SIMD_LINK_ARG "-msse2") elseif("${INTRINSIC_TYPE}" STREQUAL "sse3") set(SIMD_LINK_ARG "-msse3") elseif("${INTRINSIC_TYPE}" STREQUAL "ssse3") set(SIMD_LINK_ARG "-mssse3") elseif("${INTRINSIC_TYPE}" STREQUAL "sse4.1") set(SIMD_LINK_ARG "-msse4.1") elseif("${INTRINSIC_TYPE}" STREQUAL "sse4.2") set(SIMD_LINK_ARG "-msse4.2") elseif("${INTRINSIC_TYPE}" STREQUAL "avx2") set(SIMD_LINK_ARG "-mavx2") endif() endif() else() message(WARNING "[SIMD] Unsupported compiler ${CMAKE_C_COMPILER_ID}, ignoring") endif() if("${INTRINSIC_TYPE}" STREQUAL "neon") set(HAVE_NEON OFF) foreach(ARCH ${CMAKE_OSX_ARCHITECTURES}) if("${ARCH}" IN_LIST NEON_LIST) set(HAVE_NEON ON) endif() endforeach() if("${SYSTEM_PROCESSOR}" IN_LIST NEON_LIST OR HAVE_NEON) if(MSVC) set(SIMD_LINK_ARG "/arch:VFPv4") elseif("${CMAKE_C_COMPILER_ID}" IN_LIST GCC_CLANG_NAMES) set(SIMD_LINK_ARG "-mfpu=neon") else() message(WARNING "[SIMD] Unsupported compiler ${CMAKE_C_COMPILER_ID}, ignoring") endif() endif() endif() if(SIMD_LINK_ARG STREQUAL "") message(NOTICE "INTRINSIC_TYPE=${INTRINSIC_TYPE}: not supported on target platform, ignoring") elseif(SIMD_LINK_ARG STREQUAL "ignore") message(NOTICE "INTRINSIC_TYPE=${INTRINSIC_TYPE}: does not require linker flags, enabled by default") else() message("[SIMD] linking ${INTRINSIC_TYPE} [${SIMD_LINK_ARG}]: ${ARGN}") foreach(src ${ARGN}) set_source_files_properties(${src} PROPERTIES COMPILE_FLAGS "${SIMD_LINK_ARG}") endforeach() endif() endif() endmacro()