include(gmxTestInlineASM)
function(gmx_suggest_simd _suggested_simd)
+ if(${_suggested_simd})
+ # There's already been a suggestion made, which can't change
+ return()
+ endif()
# for x86 we need inline asm to use cpuid
gmx_test_inline_asm_gcc_x86(GMX_X86_GCC_INLINE_ASM)
# Get CPU SIMD properties information
set(_compile_definitions "${GCC_INLINE_ASM_DEFINE} -I${CMAKE_SOURCE_DIR}/src -DGMX_CPUINFO_STANDALONE ${GMX_STDLIB_CXX_FLAGS}")
+ if(GMX_TARGET_X86)
+ set(_compile_definitions "${_compile_definitions} -DGMX_TARGET_X86")
+ endif()
+
+ # Prepare a default suggestion
+ set(OUTPUT_SIMD "None")
# We need to execute the binary, so this only works if not cross-compiling.
# However, note that we are NOT limited to x86.
if(NOT CMAKE_CROSSCOMPILING)
- # We can use try_run(... LINK_LIBRARIES ${GMX_STDLIB_LIBRARIES})
- # once we require CMake at least 2.8.11. The code below works
- # even when GMX_STDLIB_LIBRARIES is empty.
+ # TODO Extract this try_compile to a helper function, because
+ # it duplicates code in gmxDetectSimd.cmake
+ set(GMX_DETECTSIMD_BINARY "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/GmxDetectSimd${CMAKE_EXECUTABLE_SUFFIX}")
set(LINK_LIBRARIES "${GMX_STDLIB_LIBRARIES}")
- try_run(GMX_CPUINFO_RUN_SIMD GMX_CPUINFO_COMPILED
- ${CMAKE_BINARY_DIR}
- ${CMAKE_SOURCE_DIR}/src/gromacs/hardware/cpuinfo.cpp
- COMPILE_DEFINITIONS ${_compile_definitions}
- CMAKE_FLAGS "-DLINK_LIBRARIES=${LINK_LIBRARIES}"
- RUN_OUTPUT_VARIABLE OUTPUT_TMP
- COMPILE_OUTPUT_VARIABLE GMX_CPUINFO_COMPILE_OUTPUT
- ARGS "-features")
-
- if(NOT GMX_CPUINFO_COMPILED)
- message(WARNING "Cannot compile cpuinfo code, which means no SIMD instructions.")
- message(STATUS "Compile output: ${GMX_CPUINFO_COMPILE_OUTPUT}")
- set(OUTPUT_TMP "None")
- elseif(NOT GMX_CPUINFO_RUN_SIMD EQUAL 0)
- message(WARNING "Cannot run cpuinfo code, which means no SIMD instructions.")
- message(STATUS "Run output: ${OUTPUT_TMP}")
- set(OUTPUT_TMP "None")
- endif(NOT GMX_CPUINFO_COMPILED)
+ try_compile(GMX_DETECTSIMD_COMPILED
+ "${CMAKE_CURRENT_BINARY_DIR}"
+ "${CMAKE_CURRENT_SOURCE_DIR}/src/gromacs/hardware/cpuinfo.cpp"
+ COMPILE_DEFINITIONS "${_compile_definitions}"
+ CMAKE_FLAGS "-DLINK_LIBRARIES=${LINK_LIBRARIES}"
+ OUTPUT_VARIABLE GMX_DETECTSIMD_COMPILED_OUTPUT
+ COPY_FILE ${GMX_DETECTSIMD_BINARY})
+ unset(_compile_definitions)
- set(OUTPUT_SIMD "None")
- if(GMX_TARGET_X86)
- if(OUTPUT_TMP MATCHES " avx512er ")
- set(OUTPUT_SIMD "AVX_512_KNL")
- elseif(OUTPUT_TMP MATCHES " avx512f ")
- set(OUTPUT_SIMD "AVX_512")
- elseif(OUTPUT_TMP MATCHES " avx2 ")
- set(OUTPUT_SIMD "AVX2_256")
- elseif(OUTPUT_TMP MATCHES " avx ")
- if(OUTPUT_TMP MATCHES " fma4 ")
- # AMD that works better with avx-128-fma
- set(OUTPUT_SIMD "AVX_128_FMA")
+ if(GMX_DETECTSIMD_COMPILED)
+ # TODO Extract this duplication of
+ # gmxSetBuildInformation.cmake to a helper function
+ if(NOT DEFINED GMX_DETECTSIMD_RUN)
+ execute_process(COMMAND ${GMX_DETECTSIMD_BINARY} "-simd"
+ RESULT_VARIABLE GMX_DETECTSIMD_RUN
+ OUTPUT_VARIABLE OUTPUT_TMP
+ ERROR_QUIET)
+ set(GMX_DETECTSIMD_RUN "${GMX_DETECTSIMD_RUN}" CACHE INTERNAL "Result of running CPUID code with arg -simd")
+ if(GMX_DETECTSIMD_RUN EQUAL 0)
+ # Make a concrete suggestion of SIMD level
+ string(STRIP "${OUTPUT_TMP}" OUTPUT_SIMD)
+ message(STATUS "Detected best SIMD instructions for this CPU - ${OUTPUT_SIMD}")
else()
- # Intel
- set(OUTPUT_SIMD "AVX_256")
+ message(WARNING "Cannot run CPUID code, which means no SIMD suggestion can be made.")
+ message(STATUS "Run output: ${OUTPUT_TMP}")
endif()
- elseif(OUTPUT_TMP MATCHES " sse4.1 ")
- set(OUTPUT_SIMD "SSE4.1")
- elseif(OUTPUT_TMP MATCHES " sse2 ")
- set(OUTPUT_SIMD "SSE2")
endif()
else()
- if(OUTPUT_TMP MATCHES " vsx ")
- set(OUTPUT_SIMD "IBM_VSX")
- elseif(OUTPUT_TMP MATCHES " vmx ")
- set(OUTPUT_SIMD "IBM_VMX")
- elseif(OUTPUT_TMP MATCHES " qpx ")
- set(OUTPUT_SIMD "IBM_QPX")
- elseif(OUTPUT_TMP MATCHES " neon_asimd ")
- set(OUTPUT_SIMD "ARM_NEON_ASIMD")
- elseif(OUTPUT_TMP MATCHES " neon ")
- set(OUTPUT_SIMD "ARM_NEON")
- endif()
+ message(WARNING "Cannot compile CPUID code, which means no SIMD instructions.")
+ message(STATUS "Compile output: ${GMX_CPUID_COMPILE_OUTPUT}")
endif()
-
- set(${_suggested_simd} "${OUTPUT_SIMD}" PARENT_SCOPE)
- message(STATUS "Detected best SIMD instructions for this CPU - ${OUTPUT_SIMD}")
else()
- set(${_suggested_simd} "None" PARENT_SCOPE)
message(WARNING "Cannot detect SIMD architecture for this cross-compile; you should check it manually.")
endif()
+
+ set(${_suggested_simd} "${OUTPUT_SIMD}" CACHE INTERNAL "Suggested SIMD")
endfunction()
function(gmx_detect_simd _suggested_simd)