Skip to content

Commit

Permalink
cmake: add detection of AVX, AVX2, SSE41
Browse files Browse the repository at this point in the history
  • Loading branch information
zdenop committed Apr 22, 2019
1 parent b7065e2 commit 21838b0
Show file tree
Hide file tree
Showing 5 changed files with 903 additions and 50 deletions.
96 changes: 46 additions & 50 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,38 @@ endif()
#
###############################################################################

# auto optimize
include(OptimizeForArchitecture)
AutodetectHostArchitecture()
OptimizeForArchitecture()
foreach(flag ${Vc_ARCHITECTURE_FLAGS})
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${flag}")
endforeach()

# add definition as expected in src/arch/simddetect.cpp
set(AVX_OPT 0)
set(AVX2_OPT 0)
set(SSE41_OPT 0)
set(MARCH_NATIVE_OPT 0)
foreach(flag ${_enable_vector_unit_list}) # from OptimizeForArchitecture()
string(TOUPPER "${flag}" flag)
string(REPLACE "\." "_" flag "${flag}")
set(sim_flags "${sim_flags} -D${flag}")
string(REPLACE "_" "" flag "${flag}")
if("${flag}" MATCHES "AVX|AVX2|SSE41")
set("${flag}_OPT" 1)
endif()
endforeach(flag)
FILE(GLOB arch_files "src/arch/*.cpp")
set_source_files_properties(${arch_files} PROPERTIES COMPILE_FLAGS "${CMAKE_CXX_FLAGS} ${sim_flags}")
include(CheckCXXCompilerFlag)
CHECK_CXX_COMPILER_FLAG("-march=native" COMPILER_SUPPORTS_MARCH_NATIVE)
if(COMPILER_SUPPORTS_MARCH_NATIVE)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native -mtune=native")
set_source_files_properties(src/arch/dotproduct.cpp PROPERTIES COMPILE_FLAGS "${CMAKE_CXX_FLAGS} -O3 -ffast-math")
set(MARCH_NATIVE_OPT 1)
endif()

set(AUTOCONFIG_SRC ${CMAKE_CURRENT_BINARY_DIR}/config_auto.h.in)
set(AUTOCONFIG ${CMAKE_CURRENT_BINARY_DIR}/config_auto.h)
add_definitions(-DHAVE_CONFIG_H)
Expand Down Expand Up @@ -243,7 +275,9 @@ endif()
########################################

file(GLOB tesseract_src
src/arch/*.cpp
src/arch/simddetect.cpp
src/arch/intsimdmatrix.cpp
src/arch/dotproduct.cpp
src/ccmain/*.cpp
src/ccstruct/*.cpp
src/ccutil/*.cpp
Expand All @@ -256,6 +290,17 @@ file(GLOB tesseract_src
src/viewer/*.cpp
src/wordrec/*.cpp
)

if(AVX_OPT)
list(APPEND tesseract_src src/arch/dotproductavx.cpp)
endif(AVX_OPT)
if(AVX2_OPT)
list(APPEND tesseract_src src/arch/intsimdmatrixavx2.cpp)
endif(AVX2_OPT)
if(SSE41_OPT)
list(APPEND tesseract_src src/arch/dotproductsse.cpp src/arch/intsimdmatrixsse.cpp)
endif(SSE41_OPT)

file(GLOB tesseract_hdr
src/api/*.h
src/arch/*.h
Expand Down Expand Up @@ -290,56 +335,7 @@ if (WIN32)
${tesseract_hdr}
${CMAKE_CURRENT_SOURCE_DIR}/src/vs2010/tesseract/resource.h)
set(tesseract_rsc ${CMAKE_CURRENT_BINARY_DIR}/vs2010/tesseract/libtesseract.rc)
if (NOT CLANG)
set_source_files_properties(
${CMAKE_CURRENT_SOURCE_DIR}/src/arch/dotproductsse.cpp
PROPERTIES COMPILE_DEFINITIONS __SSE4_1__)
set_source_files_properties(
${CMAKE_CURRENT_SOURCE_DIR}/src/arch/intsimdmatrixsse.cpp
PROPERTIES COMPILE_DEFINITIONS __SSE4_1__)
set_source_files_properties(
${CMAKE_CURRENT_SOURCE_DIR}/src/arch/dotproductavx.cpp
PROPERTIES COMPILE_FLAGS "/arch:AVX")
set_source_files_properties(
${CMAKE_CURRENT_SOURCE_DIR}/src/arch/intsimdmatrixavx2.cpp
PROPERTIES COMPILE_FLAGS "/arch:AVX2")
set_source_files_properties(
${CMAKE_CURRENT_SOURCE_DIR}/src/arch/simddetect.cpp
PROPERTIES COMPILE_FLAGS "/DAVX /DAVX2 /DSSE4_1")
else(CLANG)
set_source_files_properties(
${CMAKE_CURRENT_SOURCE_DIR}/src/arch/dotproductsse.cpp
PROPERTIES COMPILE_FLAGS "-msse4.1")
set_source_files_properties(
${CMAKE_CURRENT_SOURCE_DIR}/src/arch/intsimdmatrixsse.cpp
PROPERTIES COMPILE_FLAGS "-msse4.1")
set_source_files_properties(
${CMAKE_CURRENT_SOURCE_DIR}/src/arch/dotproductavx.cpp
PROPERTIES COMPILE_FLAGS "-mavx")
set_source_files_properties(
${CMAKE_CURRENT_SOURCE_DIR}/src/arch/intsimdmatrixavx2.cpp
PROPERTIES COMPILE_FLAGS "-mavx2")
set_source_files_properties(
${CMAKE_CURRENT_SOURCE_DIR}/src/arch/simddetect.cpp
PROPERTIES COMPILE_FLAGS "-DAVX -DAVX2 -DSSE4_1")
endif() # NOT CLANG
endif() # MSVC
else()
set_source_files_properties(
${CMAKE_CURRENT_SOURCE_DIR}/src/arch/dotproductsse.cpp
PROPERTIES COMPILE_FLAGS "-msse4.1")
set_source_files_properties(
${CMAKE_CURRENT_SOURCE_DIR}/src/arch/intsimdmatrixsse.cpp
PROPERTIES COMPILE_FLAGS "-msse4.1")
set_source_files_properties(
${CMAKE_CURRENT_SOURCE_DIR}/src/arch/dotproductavx.cpp
PROPERTIES COMPILE_FLAGS "-mavx")
set_source_files_properties(
${CMAKE_CURRENT_SOURCE_DIR}/src/arch/intsimdmatrixavx2.cpp
PROPERTIES COMPILE_FLAGS "-mavx2")
set_source_files_properties(
${CMAKE_CURRENT_SOURCE_DIR}/src/arch/simddetect.cpp
PROPERTIES COMPILE_FLAGS "-DAVX -DAVX2 -DSSE4_1")
endif()

add_library (libtesseract ${LIBRARY_TYPE} ${tesseract_src} ${tesseract_hdr}
Expand Down
130 changes: 130 additions & 0 deletions cmake/AddCompilerFlag.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
# - Add a given compiler flag to flags variables.
# AddCompilerFlag(<flag> [<var>])
# or
# AddCompilerFlag(<flag> [C_FLAGS <var>] [CXX_FLAGS <var>] [C_RESULT <var>]
# [CXX_RESULT <var>])

#=============================================================================
# Copyright 2010-2015 Matthias Kretz <[email protected]>
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
#
# * Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# * Neither the names of contributing organizations nor the
# names of its contributors may be used to endorse or promote products
# derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS ``AS IS''
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#=============================================================================

get_filename_component(_currentDir "${CMAKE_CURRENT_LIST_FILE}" PATH)
include("${_currentDir}/CheckCCompilerFlag.cmake")
include("${_currentDir}/CheckCXXCompilerFlag.cmake")

macro(AddCompilerFlag _flag)
string(REGEX REPLACE "[-.+/:= ]" "_" _flag_esc "${_flag}")

set(_c_flags "CMAKE_C_FLAGS")
set(_cxx_flags "CMAKE_CXX_FLAGS")
set(_c_result tmp)
set(_cxx_result tmp)
if(${ARGC} EQUAL 2)
message(WARNING "Deprecated use of the AddCompilerFlag macro.")
unset(_c_result)
set(_cxx_result ${ARGV1})
elseif(${ARGC} GREATER 2)
set(state 0)
unset(_c_flags)
unset(_cxx_flags)
unset(_c_result)
unset(_cxx_result)
foreach(_arg ${ARGN})
if("x${_arg}" STREQUAL "xC_FLAGS")
set(state 1)
if(NOT DEFINED _c_result)
set(_c_result tmp0)
endif()
elseif("x${_arg}" STREQUAL "xCXX_FLAGS")
set(state 2)
if(NOT DEFINED _cxx_result)
set(_cxx_result tmp1)
endif()
elseif("x${_arg}" STREQUAL "xC_RESULT")
set(state 3)
elseif("x${_arg}" STREQUAL "xCXX_RESULT")
set(state 4)
elseif(state EQUAL 1)
set(_c_flags "${_arg}")
elseif(state EQUAL 2)
set(_cxx_flags "${_arg}")
elseif(state EQUAL 3)
set(_c_result "${_arg}")
elseif(state EQUAL 4)
set(_cxx_result "${_arg}")
else()
message(FATAL_ERROR "Syntax error for AddCompilerFlag")
endif()
endforeach()
endif()

set(_c_code "int main() { return 0; }")
set(_cxx_code "int main() { return 0; }")
if("${_flag}" STREQUAL "-mfma")
# Compiling with FMA3 support may fail only at the assembler level.
# In that case we need to have such an instruction in the test code
set(_c_code "#include <immintrin.h>
__m128 foo(__m128 x) { return _mm_fmadd_ps(x, x, x); }
int main() { return 0; }")
set(_cxx_code "${_c_code}")
elseif("${_flag}" STREQUAL "-stdlib=libc++")
# Compiling with libc++ not only requires a compiler that understands it, but also
# the libc++ headers itself
set(_cxx_code "#include <iostream>
#include <cstdio>
int main() { return 0; }")
else()
set(_cxx_code "#include <cstdio>
int main() { return 0; }")
endif()

if(DEFINED _c_result)
check_c_compiler_flag("${_flag}" check_c_compiler_flag_${_flag_esc} "${_c_code}")
set(${_c_result} ${check_c_compiler_flag_${_flag_esc}})
endif()
if(DEFINED _cxx_result)
check_cxx_compiler_flag("${_flag}" check_cxx_compiler_flag_${_flag_esc} "${_cxx_code}")
set(${_cxx_result} ${check_cxx_compiler_flag_${_flag_esc}})
endif()

macro(my_append _list _flag _special)
if("x${_list}" STREQUAL "x${_special}")
set(${_list} "${${_list}} ${_flag}")
else()
list(APPEND ${_list} "${_flag}")
endif()
endmacro()

if(check_c_compiler_flag_${_flag_esc} AND DEFINED _c_flags)
my_append(${_c_flags} "${_flag}" CMAKE_C_FLAGS)
endif()
if(check_cxx_compiler_flag_${_flag_esc} AND DEFINED _cxx_flags)
my_append(${_cxx_flags} "${_flag}" CMAKE_CXX_FLAGS)
endif()
endmacro(AddCompilerFlag)
73 changes: 73 additions & 0 deletions cmake/CheckCCompilerFlag.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
# - Check whether the C compiler supports a given flag.
# CHECK_C_COMPILER_FLAG(<flag> <var>)
# <flag> - the compiler flag
# <var> - variable to store the result
# This internally calls the check_c_source_compiles macro.
# See help for CheckCSourceCompiles for a listing of variables
# that can modify the build.

#=============================================================================
# Copyright 2006-2009 Kitware, Inc.
# Copyright 2006 Alexander Neundorf <[email protected]>
# Copyright 2011-2013 Matthias Kretz <[email protected]>
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
#
# * Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# * The names of Kitware, Inc., the Insight Consortium, or the names of
# any consortium members, or of any contributors, may not be used to
# endorse or promote products derived from this software without
# specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS ``AS IS''
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#=============================================================================

INCLUDE(CheckCSourceCompiles)

MACRO (CHECK_C_COMPILER_FLAG _FLAG _RESULT)
SET(SAFE_CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS}")
SET(CMAKE_REQUIRED_DEFINITIONS "${_FLAG}")
if(${ARGC} GREATER 2)
SET(TEST_SOURCE "${ARGV2}")
else()
SET(TEST_SOURCE "int main() { return 0;}")
endif()
CHECK_C_SOURCE_COMPILES("${TEST_SOURCE}" ${_RESULT}
# Some compilers do not fail with a bad flag
FAIL_REGEX "error: bad value (.*) for .* switch" # GNU
FAIL_REGEX "argument unused during compilation" # clang
FAIL_REGEX "is valid for .* but not for C" # GNU
FAIL_REGEX "unrecognized .*option" # GNU
FAIL_REGEX "ignored for target" # GNU
FAIL_REGEX "ignoring unknown option" # MSVC
FAIL_REGEX "warning D9002" # MSVC
FAIL_REGEX "[Uu]nknown option" # HP
FAIL_REGEX "[Ww]arning: [Oo]ption" # SunPro
FAIL_REGEX "command option .* is not recognized" # XL
FAIL_REGEX "WARNING: unknown flag:" # Open64
FAIL_REGEX "command line error" # ICC
FAIL_REGEX "command line warning" # ICC
FAIL_REGEX "#10236:" # ICC: File not found
FAIL_REGEX " #10159: " # ICC
FAIL_REGEX " #10353: " # ICC: option '-mfma' ignored, suggest using '-march=core-avx2'
)
SET (CMAKE_REQUIRED_DEFINITIONS "${SAFE_CMAKE_REQUIRED_DEFINITIONS}")
ENDMACRO (CHECK_C_COMPILER_FLAG)

Loading

0 comments on commit 21838b0

Please sign in to comment.