From 309791cc6150f4aa5ffd4140fa39906cc8a76873 Mon Sep 17 00:00:00 2001 From: ismagom Date: Fri, 16 Oct 2015 11:48:59 +0200 Subject: [PATCH] Try_compile() based CMAKE SSE checking --- CMakeLists.txt | 10 +-- cmake/modules/CheckCSourceRuns.cmake | 107 +++++++++++++++++++++++ cmake/modules/FindSSE.cmake | 123 +++++++++++---------------- srslte/lib/fec/src/rm_turbo.c | 6 +- srslte/lib/utils/src/vector.c | 14 ++- 5 files changed, 168 insertions(+), 92 deletions(-) create mode 100644 cmake/modules/CheckCSourceRuns.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 85ea56d5c..9d39ab4c6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -87,13 +87,11 @@ FIND_PACKAGE(SSE) IF(CMAKE_COMPILER_IS_GNUCC) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wno-write-strings -Wno-format-extra-args -Winline -Wno-unused-result -Wno-format -std=c99 -D_GNU_SOURCE -g -march=native -O3") - IF(AVX_FOUND) + IF(HAVE_AVX) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mfpmath=sse -mavx -DLV_HAVE_AVX -DLV_HAVE_SSE") - ELSEIF(SSE4_2_FOUND) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mfpmath=sse -msse_4.2 -DLV_HAVE_SSE") - ELSEIF(SSE4_1_FOUND) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mfpmath=sse -msse_4.1 -DLV_HAVE_SSE") - ENDIF(AVX_FOUND) + ELSEIF(HAVE_SSE) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mfpmath=sse -msse4.1 -DLV_HAVE_SSE") + ENDIF(HAVE_AVX) # IF(${CMAKE_BUILD_TYPE} STREQUAL "Debug") # set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror -Wno-error=implicit-function-declaration -Wno-error=unused-but-set-variable") diff --git a/cmake/modules/CheckCSourceRuns.cmake b/cmake/modules/CheckCSourceRuns.cmake new file mode 100644 index 000000000..5afeab685 --- /dev/null +++ b/cmake/modules/CheckCSourceRuns.cmake @@ -0,0 +1,107 @@ +#.rst: +# CheckCSourceRuns +# ---------------- +# +# Check if the given C source code compiles and runs. +# +# CHECK_C_SOURCE_RUNS( ) +# +# :: +# +# - source code to try to compile +# - variable to store the result +# (1 for success, empty for failure) +# Will be created as an internal cache variable. +# +# The following variables may be set before calling this macro to modify +# the way the check is run: +# +# :: +# +# CMAKE_REQUIRED_FLAGS = string of compile command line flags +# CMAKE_REQUIRED_DEFINITIONS = list of macros to define (-DFOO=bar) +# CMAKE_REQUIRED_INCLUDES = list of include directories +# CMAKE_REQUIRED_LIBRARIES = list of libraries to link +# CMAKE_REQUIRED_QUIET = execute quietly without messages + +#============================================================================= +# Copyright 2006-2009 Kitware, Inc. +# +# Distributed under the OSI-approved BSD License (the "License"); +# see accompanying file Copyright.txt for details. +# +# This software is distributed WITHOUT ANY WARRANTY; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the License for more information. +#============================================================================= +# (To distribute this file outside of CMake, substitute the full +# License text for the above reference.) + + + +macro(CHECK_C_SOURCE_RUNS SOURCE VAR) + if(NOT DEFINED "${VAR}") + set(MACRO_CHECK_FUNCTION_DEFINITIONS + "-D${VAR} ${CMAKE_REQUIRED_FLAGS}") + if(CMAKE_REQUIRED_LIBRARIES) + set(CHECK_C_SOURCE_COMPILES_ADD_LIBRARIES + LINK_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES}) + else() + set(CHECK_C_SOURCE_COMPILES_ADD_LIBRARIES) + endif() + if(CMAKE_REQUIRED_INCLUDES) + set(CHECK_C_SOURCE_COMPILES_ADD_INCLUDES + "-DINCLUDE_DIRECTORIES:STRING=${CMAKE_REQUIRED_INCLUDES}") + else() + set(CHECK_C_SOURCE_COMPILES_ADD_INCLUDES) + endif() + file(WRITE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/src.c" + "${SOURCE}\n") + + if(NOT CMAKE_REQUIRED_QUIET) + message(STATUS "Performing Test ${VAR}") + endif() + try_run(${VAR}_EXITCODE ${VAR}_COMPILED + ${CMAKE_BINARY_DIR} + ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/src.c + COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS} + ${CHECK_C_SOURCE_COMPILES_ADD_LIBRARIES} + CMAKE_FLAGS -DCOMPILE_DEFINITIONS:STRING=${MACRO_CHECK_FUNCTION_DEFINITIONS} + -DCMAKE_SKIP_RPATH:BOOL=${CMAKE_SKIP_RPATH} + "${CHECK_C_SOURCE_COMPILES_ADD_INCLUDES}" + COMPILE_OUTPUT_VARIABLE OUTPUT) + # if it did not compile make the return value fail code of 1 + if(NOT ${VAR}_COMPILED) + set(${VAR}_EXITCODE 1) + endif() + # if the return value was 0 then it worked + if("${${VAR}_EXITCODE}" EQUAL 0) + set(${VAR} 1 CACHE INTERNAL "Test ${VAR}") + if(NOT CMAKE_REQUIRED_QUIET) + message(STATUS "Performing Test ${VAR} - Success") + endif() + file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log + "Performing C SOURCE FILE Test ${VAR} succeeded with the following output:\n" + "${OUTPUT}\n" + "Return value: ${${VAR}}\n" + "Source file was:\n${SOURCE}\n") + else() + if(CMAKE_CROSSCOMPILING AND "${${VAR}_EXITCODE}" MATCHES "FAILED_TO_RUN") + set(${VAR} "${${VAR}_EXITCODE}") + else() + set(${VAR} "" CACHE INTERNAL "Test ${VAR}") + endif() + + if(NOT CMAKE_REQUIRED_QUIET) + message(STATUS "Performing Test ${VAR} - Failed") + endif() + file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log + "Performing C SOURCE FILE Test ${VAR} failed with the following output:\n" + "${OUTPUT}\n" + "Return value: ${${VAR}_EXITCODE}\n" + "Source file was:\n${SOURCE}\n") + + endif() + endif() +endmacro() + diff --git a/cmake/modules/FindSSE.cmake b/cmake/modules/FindSSE.cmake index 1af23d0be..8647e9413 100644 --- a/cmake/modules/FindSSE.cmake +++ b/cmake/modules/FindSSE.cmake @@ -1,85 +1,58 @@ -# Check if SSE instructions are available on the machine where -# the project is compiled. +if (NOT CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64|^i[3,9]86$") + return() +endif() -# Minimum requirement to enable SSE turbo decoder is SSE4.1 -# Since SSE 4.1 includes all previous SSE, look only for this one. +include(CheckCSourceRuns) -# Check also AVX availability (for equalizer) +option(ENABLE_SSE "Enable compile-time SSE4.1 support." ON) +option(ENABLE_AVX "Enable compile-time AVX support." ON) -IF(CMAKE_SYSTEM_NAME MATCHES "Linux") - EXEC_PROGRAM(cat ARGS "/proc/cpuinfo" OUTPUT_VARIABLE CPUINFO) +if (ENABLE_SSE) + # + # Check compiler for SSE4_1 intrinsics + # + if (CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_CLANG ) + set(CMAKE_REQUIRED_FLAGS "-msse4.1") + check_c_source_runs(" + #include + #include - STRING(REGEX REPLACE "^.*(sse4_1).*$" "\\1" SSE_THERE ${CPUINFO}) - STRING(COMPARE EQUAL "sse4_1" "${SSE_THERE}" SSE41_TRUE) - IF (SSE41_TRUE) - set(SSE4_1_FOUND true CACHE BOOL "SSE4.1 available on host") - ELSE (SSE41_TRUE) - set(SSE4_1_FOUND false CACHE BOOL "SSE4.1 available on host") - ENDIF (SSE41_TRUE) + int main() + { + __m128i a = _mm_setzero_si128(); + __m128i b = _mm_minpos_epu16(a); + return 0; + }" + HAVE_SSE) + endif() - STRING(REGEX REPLACE "^.*(sse4_2).*$" "\\1" SSE_THERE ${CPUINFO}) - STRING(COMPARE EQUAL "sse4_2" "${SSE_THERE}" SSE42_TRUE) - IF (SSE42_TRUE) - set(SSE4_2_FOUND true CACHE BOOL "SSE4.2 available on host") - ELSE (SSE42_TRUE) - set(SSE4_2_FOUND false CACHE BOOL "SSE4.2 available on host") - ENDIF (SSE42_TRUE) + if (HAVE_SSE) + message(STATUS "SSE4.1 is enabled - target CPU must support it") + endif() + + if (ENABLE_AVX) - STRING(REGEX REPLACE "^.*(avx).*$" "\\1" SSE_THERE ${CPUINFO}) - STRING(COMPARE EQUAL "avx" "${SSE_THERE}" AVX_TRUE) - IF (AVX_TRUE) - set(AVX_FOUND true CACHE BOOL "AVX available on host") - ELSE (AVX_TRUE) - set(AVX_FOUND false CACHE BOOL "AVX available on host") - ENDIF (AVX_TRUE) -ELSEIF(CMAKE_SYSTEM_NAME MATCHES "Darwin") - EXEC_PROGRAM("/usr/sbin/sysctl -n machdep.cpu.features" OUTPUT_VARIABLE - CPUINFO) + # + # Check compiler for AVX intrinsics + # + if (CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_CLANG ) + set(CMAKE_REQUIRED_FLAGS "-mavx") + check_c_source_runs(" + #include - STRING(REGEX REPLACE "^.*(SSE4.1).*$" "\\1" SSE_THERE ${CPUINFO}) - STRING(COMPARE EQUAL "SSE4.1" "${SSE_THERE}" SSE41_TRUE) - IF (SSE41_TRUE) - set(SSE4_1_FOUND true CACHE BOOL "SSE4.1 available on host") - ELSE (SSE41_TRUE) - set(SSE4_1_FOUND false CACHE BOOL "SSE4.1 available on host") - ENDIF (SSE41_TRUE) + int main() + { + __m256i a = _mm256_setzero_si256(); + return 0; + }" + HAVE_AVX) + endif() - STRING(REGEX REPLACE "^.*(SSE4.2).*$" "\\1" SSE_THERE ${CPUINFO}) - STRING(COMPARE EQUAL "SSE4.2" "${SSE_THERE}" SSE42_TRUE) - IF (SSE42_TRUE) - set(SSE4_2_FOUND true CACHE BOOL "SSE4.2 available on host") - ELSE (SSE42_TRUE) - set(SSE4_2_FOUND false CACHE BOOL "SSE4.2 available on host") - ENDIF (SSE42_TRUE) + if (HAVE_AVX) + message(STATUS "AVX is enabled - target CPU must support it") + endif() + endif() - STRING(REGEX REPLACE "^.*(AVX).*$" "\\1" SSE_THERE ${CPUINFO}) - STRING(COMPARE EQUAL "AVX" "${SSE_THERE}" AVX_TRUE) - IF (AVX_TRUE) - set(AVX_FOUND true CACHE BOOL "AVX available on host") - ELSE (AVX_TRUE) - set(AVX_FOUND false CACHE BOOL "AVX available on host") - ENDIF (AVX_TRUE) - -ELSEIF(CMAKE_SYSTEM_NAME MATCHES "Windows") - # TODO - set(SSE4_2_FOUND false CACHE BOOL "SSE4.2 available on host") - set(SSE4_1_FOUND false CACHE BOOL "SSE4.1 available on host") - set(AVX_FOUND false CACHE BOOL "AVX available on host") -ELSE(CMAKE_SYSTEM_NAME MATCHES "Linux") - set(SSE4_1_FOUND false CACHE BOOL "SSE4.1 available on host") - set(AVX_FOUND false CACHE BOOL "AVX available on host") -ENDIF(CMAKE_SYSTEM_NAME MATCHES "Linux") +endif() -if(NOT SSE4_1_FOUND) - MESSAGE(STATUS "Could not find hardware support for SSE4.1 on this machine.") -endif(NOT SSE4_1_FOUND) - -if(NOT SSE4_2_FOUND) - MESSAGE(STATUS "Could not find hardware support for SSE4.2 on this machine.") -endif(NOT SSE4_2_FOUND) - -if(NOT AVX_FOUND) - MESSAGE(STATUS "Could not find hardware support for AVX on this machine.") -endif(NOT AVX_FOUND) - -mark_as_advanced(SSE4_1_FOUND AVX_FOUND) \ No newline at end of file +mark_as_advanced(HAVE_SSE, HAVE_AVX) \ No newline at end of file diff --git a/srslte/lib/fec/src/rm_turbo.c b/srslte/lib/fec/src/rm_turbo.c index a108d942c..4fae6c6d3 100644 --- a/srslte/lib/fec/src/rm_turbo.c +++ b/srslte/lib/fec/src/rm_turbo.c @@ -326,8 +326,8 @@ int srslte_rm_turbo_rx_lut_sse(int16_t *input, int16_t *output, uint32_t in_len, /* Simplify load if we do not need to wrap (ie high rates) */ if (in_len <= out_len) { for (int i=0;i