Merge branch release-5-1 into release-2016
[alexxy/gromacs.git] / cmake / gmxDetectSimd.cmake
index 4abf65e290faa90d884b89d2d79f2a9869156018..28fbdc21f63514e0b02692e0d08a4f482e0fc84d 100644 (file)
 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)
@@ -69,74 +73,56 @@ function(gmx_suggest_simd _suggested_simd)
 
     # 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)