Skip to content

Commit 21838b0

Browse files
committed
cmake: add detection of AVX, AVX2, SSE41
1 parent b7065e2 commit 21838b0

5 files changed

+903
-50
lines changed

CMakeLists.txt

+46-50
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,38 @@ endif()
175175
#
176176
###############################################################################
177177

178+
# auto optimize
179+
include(OptimizeForArchitecture)
180+
AutodetectHostArchitecture()
181+
OptimizeForArchitecture()
182+
foreach(flag ${Vc_ARCHITECTURE_FLAGS})
183+
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${flag}")
184+
endforeach()
185+
186+
# add definition as expected in src/arch/simddetect.cpp
187+
set(AVX_OPT 0)
188+
set(AVX2_OPT 0)
189+
set(SSE41_OPT 0)
190+
set(MARCH_NATIVE_OPT 0)
191+
foreach(flag ${_enable_vector_unit_list}) # from OptimizeForArchitecture()
192+
string(TOUPPER "${flag}" flag)
193+
string(REPLACE "\." "_" flag "${flag}")
194+
set(sim_flags "${sim_flags} -D${flag}")
195+
string(REPLACE "_" "" flag "${flag}")
196+
if("${flag}" MATCHES "AVX|AVX2|SSE41")
197+
set("${flag}_OPT" 1)
198+
endif()
199+
endforeach(flag)
200+
FILE(GLOB arch_files "src/arch/*.cpp")
201+
set_source_files_properties(${arch_files} PROPERTIES COMPILE_FLAGS "${CMAKE_CXX_FLAGS} ${sim_flags}")
202+
include(CheckCXXCompilerFlag)
203+
CHECK_CXX_COMPILER_FLAG("-march=native" COMPILER_SUPPORTS_MARCH_NATIVE)
204+
if(COMPILER_SUPPORTS_MARCH_NATIVE)
205+
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native -mtune=native")
206+
set_source_files_properties(src/arch/dotproduct.cpp PROPERTIES COMPILE_FLAGS "${CMAKE_CXX_FLAGS} -O3 -ffast-math")
207+
set(MARCH_NATIVE_OPT 1)
208+
endif()
209+
178210
set(AUTOCONFIG_SRC ${CMAKE_CURRENT_BINARY_DIR}/config_auto.h.in)
179211
set(AUTOCONFIG ${CMAKE_CURRENT_BINARY_DIR}/config_auto.h)
180212
add_definitions(-DHAVE_CONFIG_H)
@@ -243,7 +275,9 @@ endif()
243275
########################################
244276

245277
file(GLOB tesseract_src
246-
src/arch/*.cpp
278+
src/arch/simddetect.cpp
279+
src/arch/intsimdmatrix.cpp
280+
src/arch/dotproduct.cpp
247281
src/ccmain/*.cpp
248282
src/ccstruct/*.cpp
249283
src/ccutil/*.cpp
@@ -256,6 +290,17 @@ file(GLOB tesseract_src
256290
src/viewer/*.cpp
257291
src/wordrec/*.cpp
258292
)
293+
294+
if(AVX_OPT)
295+
list(APPEND tesseract_src src/arch/dotproductavx.cpp)
296+
endif(AVX_OPT)
297+
if(AVX2_OPT)
298+
list(APPEND tesseract_src src/arch/intsimdmatrixavx2.cpp)
299+
endif(AVX2_OPT)
300+
if(SSE41_OPT)
301+
list(APPEND tesseract_src src/arch/dotproductsse.cpp src/arch/intsimdmatrixsse.cpp)
302+
endif(SSE41_OPT)
303+
259304
file(GLOB tesseract_hdr
260305
src/api/*.h
261306
src/arch/*.h
@@ -290,56 +335,7 @@ if (WIN32)
290335
${tesseract_hdr}
291336
${CMAKE_CURRENT_SOURCE_DIR}/src/vs2010/tesseract/resource.h)
292337
set(tesseract_rsc ${CMAKE_CURRENT_BINARY_DIR}/vs2010/tesseract/libtesseract.rc)
293-
if (NOT CLANG)
294-
set_source_files_properties(
295-
${CMAKE_CURRENT_SOURCE_DIR}/src/arch/dotproductsse.cpp
296-
PROPERTIES COMPILE_DEFINITIONS __SSE4_1__)
297-
set_source_files_properties(
298-
${CMAKE_CURRENT_SOURCE_DIR}/src/arch/intsimdmatrixsse.cpp
299-
PROPERTIES COMPILE_DEFINITIONS __SSE4_1__)
300-
set_source_files_properties(
301-
${CMAKE_CURRENT_SOURCE_DIR}/src/arch/dotproductavx.cpp
302-
PROPERTIES COMPILE_FLAGS "/arch:AVX")
303-
set_source_files_properties(
304-
${CMAKE_CURRENT_SOURCE_DIR}/src/arch/intsimdmatrixavx2.cpp
305-
PROPERTIES COMPILE_FLAGS "/arch:AVX2")
306-
set_source_files_properties(
307-
${CMAKE_CURRENT_SOURCE_DIR}/src/arch/simddetect.cpp
308-
PROPERTIES COMPILE_FLAGS "/DAVX /DAVX2 /DSSE4_1")
309-
else(CLANG)
310-
set_source_files_properties(
311-
${CMAKE_CURRENT_SOURCE_DIR}/src/arch/dotproductsse.cpp
312-
PROPERTIES COMPILE_FLAGS "-msse4.1")
313-
set_source_files_properties(
314-
${CMAKE_CURRENT_SOURCE_DIR}/src/arch/intsimdmatrixsse.cpp
315-
PROPERTIES COMPILE_FLAGS "-msse4.1")
316-
set_source_files_properties(
317-
${CMAKE_CURRENT_SOURCE_DIR}/src/arch/dotproductavx.cpp
318-
PROPERTIES COMPILE_FLAGS "-mavx")
319-
set_source_files_properties(
320-
${CMAKE_CURRENT_SOURCE_DIR}/src/arch/intsimdmatrixavx2.cpp
321-
PROPERTIES COMPILE_FLAGS "-mavx2")
322-
set_source_files_properties(
323-
${CMAKE_CURRENT_SOURCE_DIR}/src/arch/simddetect.cpp
324-
PROPERTIES COMPILE_FLAGS "-DAVX -DAVX2 -DSSE4_1")
325-
endif() # NOT CLANG
326338
endif() # MSVC
327-
else()
328-
set_source_files_properties(
329-
${CMAKE_CURRENT_SOURCE_DIR}/src/arch/dotproductsse.cpp
330-
PROPERTIES COMPILE_FLAGS "-msse4.1")
331-
set_source_files_properties(
332-
${CMAKE_CURRENT_SOURCE_DIR}/src/arch/intsimdmatrixsse.cpp
333-
PROPERTIES COMPILE_FLAGS "-msse4.1")
334-
set_source_files_properties(
335-
${CMAKE_CURRENT_SOURCE_DIR}/src/arch/dotproductavx.cpp
336-
PROPERTIES COMPILE_FLAGS "-mavx")
337-
set_source_files_properties(
338-
${CMAKE_CURRENT_SOURCE_DIR}/src/arch/intsimdmatrixavx2.cpp
339-
PROPERTIES COMPILE_FLAGS "-mavx2")
340-
set_source_files_properties(
341-
${CMAKE_CURRENT_SOURCE_DIR}/src/arch/simddetect.cpp
342-
PROPERTIES COMPILE_FLAGS "-DAVX -DAVX2 -DSSE4_1")
343339
endif()
344340

345341
add_library (libtesseract ${LIBRARY_TYPE} ${tesseract_src} ${tesseract_hdr}

cmake/AddCompilerFlag.cmake

+130
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
# - Add a given compiler flag to flags variables.
2+
# AddCompilerFlag(<flag> [<var>])
3+
# or
4+
# AddCompilerFlag(<flag> [C_FLAGS <var>] [CXX_FLAGS <var>] [C_RESULT <var>]
5+
# [CXX_RESULT <var>])
6+
7+
#=============================================================================
8+
# Copyright 2010-2015 Matthias Kretz <kretz@kde.org>
9+
#
10+
# Redistribution and use in source and binary forms, with or without
11+
# modification, are permitted provided that the following conditions are
12+
# met:
13+
#
14+
# * Redistributions of source code must retain the above copyright notice,
15+
# this list of conditions and the following disclaimer.
16+
#
17+
# * Redistributions in binary form must reproduce the above copyright notice,
18+
# this list of conditions and the following disclaimer in the documentation
19+
# and/or other materials provided with the distribution.
20+
#
21+
# * Neither the names of contributing organizations nor the
22+
# names of its contributors may be used to endorse or promote products
23+
# derived from this software without specific prior written permission.
24+
#
25+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS ``AS IS''
26+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28+
# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR
29+
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30+
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
31+
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
32+
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
33+
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
34+
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35+
#=============================================================================
36+
37+
get_filename_component(_currentDir "${CMAKE_CURRENT_LIST_FILE}" PATH)
38+
include("${_currentDir}/CheckCCompilerFlag.cmake")
39+
include("${_currentDir}/CheckCXXCompilerFlag.cmake")
40+
41+
macro(AddCompilerFlag _flag)
42+
string(REGEX REPLACE "[-.+/:= ]" "_" _flag_esc "${_flag}")
43+
44+
set(_c_flags "CMAKE_C_FLAGS")
45+
set(_cxx_flags "CMAKE_CXX_FLAGS")
46+
set(_c_result tmp)
47+
set(_cxx_result tmp)
48+
if(${ARGC} EQUAL 2)
49+
message(WARNING "Deprecated use of the AddCompilerFlag macro.")
50+
unset(_c_result)
51+
set(_cxx_result ${ARGV1})
52+
elseif(${ARGC} GREATER 2)
53+
set(state 0)
54+
unset(_c_flags)
55+
unset(_cxx_flags)
56+
unset(_c_result)
57+
unset(_cxx_result)
58+
foreach(_arg ${ARGN})
59+
if("x${_arg}" STREQUAL "xC_FLAGS")
60+
set(state 1)
61+
if(NOT DEFINED _c_result)
62+
set(_c_result tmp0)
63+
endif()
64+
elseif("x${_arg}" STREQUAL "xCXX_FLAGS")
65+
set(state 2)
66+
if(NOT DEFINED _cxx_result)
67+
set(_cxx_result tmp1)
68+
endif()
69+
elseif("x${_arg}" STREQUAL "xC_RESULT")
70+
set(state 3)
71+
elseif("x${_arg}" STREQUAL "xCXX_RESULT")
72+
set(state 4)
73+
elseif(state EQUAL 1)
74+
set(_c_flags "${_arg}")
75+
elseif(state EQUAL 2)
76+
set(_cxx_flags "${_arg}")
77+
elseif(state EQUAL 3)
78+
set(_c_result "${_arg}")
79+
elseif(state EQUAL 4)
80+
set(_cxx_result "${_arg}")
81+
else()
82+
message(FATAL_ERROR "Syntax error for AddCompilerFlag")
83+
endif()
84+
endforeach()
85+
endif()
86+
87+
set(_c_code "int main() { return 0; }")
88+
set(_cxx_code "int main() { return 0; }")
89+
if("${_flag}" STREQUAL "-mfma")
90+
# Compiling with FMA3 support may fail only at the assembler level.
91+
# In that case we need to have such an instruction in the test code
92+
set(_c_code "#include <immintrin.h>
93+
__m128 foo(__m128 x) { return _mm_fmadd_ps(x, x, x); }
94+
int main() { return 0; }")
95+
set(_cxx_code "${_c_code}")
96+
elseif("${_flag}" STREQUAL "-stdlib=libc++")
97+
# Compiling with libc++ not only requires a compiler that understands it, but also
98+
# the libc++ headers itself
99+
set(_cxx_code "#include <iostream>
100+
#include <cstdio>
101+
int main() { return 0; }")
102+
else()
103+
set(_cxx_code "#include <cstdio>
104+
int main() { return 0; }")
105+
endif()
106+
107+
if(DEFINED _c_result)
108+
check_c_compiler_flag("${_flag}" check_c_compiler_flag_${_flag_esc} "${_c_code}")
109+
set(${_c_result} ${check_c_compiler_flag_${_flag_esc}})
110+
endif()
111+
if(DEFINED _cxx_result)
112+
check_cxx_compiler_flag("${_flag}" check_cxx_compiler_flag_${_flag_esc} "${_cxx_code}")
113+
set(${_cxx_result} ${check_cxx_compiler_flag_${_flag_esc}})
114+
endif()
115+
116+
macro(my_append _list _flag _special)
117+
if("x${_list}" STREQUAL "x${_special}")
118+
set(${_list} "${${_list}} ${_flag}")
119+
else()
120+
list(APPEND ${_list} "${_flag}")
121+
endif()
122+
endmacro()
123+
124+
if(check_c_compiler_flag_${_flag_esc} AND DEFINED _c_flags)
125+
my_append(${_c_flags} "${_flag}" CMAKE_C_FLAGS)
126+
endif()
127+
if(check_cxx_compiler_flag_${_flag_esc} AND DEFINED _cxx_flags)
128+
my_append(${_cxx_flags} "${_flag}" CMAKE_CXX_FLAGS)
129+
endif()
130+
endmacro(AddCompilerFlag)

cmake/CheckCCompilerFlag.cmake

+73
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
# - Check whether the C compiler supports a given flag.
2+
# CHECK_C_COMPILER_FLAG(<flag> <var>)
3+
# <flag> - the compiler flag
4+
# <var> - variable to store the result
5+
# This internally calls the check_c_source_compiles macro.
6+
# See help for CheckCSourceCompiles for a listing of variables
7+
# that can modify the build.
8+
9+
#=============================================================================
10+
# Copyright 2006-2009 Kitware, Inc.
11+
# Copyright 2006 Alexander Neundorf <neundorf@kde.org>
12+
# Copyright 2011-2013 Matthias Kretz <kretz@kde.org>
13+
#
14+
# Redistribution and use in source and binary forms, with or without
15+
# modification, are permitted provided that the following conditions are
16+
# met:
17+
#
18+
# * Redistributions of source code must retain the above copyright notice,
19+
# this list of conditions and the following disclaimer.
20+
#
21+
# * Redistributions in binary form must reproduce the above copyright notice,
22+
# this list of conditions and the following disclaimer in the documentation
23+
# and/or other materials provided with the distribution.
24+
#
25+
# * The names of Kitware, Inc., the Insight Consortium, or the names of
26+
# any consortium members, or of any contributors, may not be used to
27+
# endorse or promote products derived from this software without
28+
# specific prior written permission.
29+
#
30+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS ``AS IS''
31+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
32+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
33+
# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR
34+
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
35+
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
36+
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
37+
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
38+
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
39+
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40+
#=============================================================================
41+
42+
INCLUDE(CheckCSourceCompiles)
43+
44+
MACRO (CHECK_C_COMPILER_FLAG _FLAG _RESULT)
45+
SET(SAFE_CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS}")
46+
SET(CMAKE_REQUIRED_DEFINITIONS "${_FLAG}")
47+
if(${ARGC} GREATER 2)
48+
SET(TEST_SOURCE "${ARGV2}")
49+
else()
50+
SET(TEST_SOURCE "int main() { return 0;}")
51+
endif()
52+
CHECK_C_SOURCE_COMPILES("${TEST_SOURCE}" ${_RESULT}
53+
# Some compilers do not fail with a bad flag
54+
FAIL_REGEX "error: bad value (.*) for .* switch" # GNU
55+
FAIL_REGEX "argument unused during compilation" # clang
56+
FAIL_REGEX "is valid for .* but not for C" # GNU
57+
FAIL_REGEX "unrecognized .*option" # GNU
58+
FAIL_REGEX "ignored for target" # GNU
59+
FAIL_REGEX "ignoring unknown option" # MSVC
60+
FAIL_REGEX "warning D9002" # MSVC
61+
FAIL_REGEX "[Uu]nknown option" # HP
62+
FAIL_REGEX "[Ww]arning: [Oo]ption" # SunPro
63+
FAIL_REGEX "command option .* is not recognized" # XL
64+
FAIL_REGEX "WARNING: unknown flag:" # Open64
65+
FAIL_REGEX "command line error" # ICC
66+
FAIL_REGEX "command line warning" # ICC
67+
FAIL_REGEX "#10236:" # ICC: File not found
68+
FAIL_REGEX " #10159: " # ICC
69+
FAIL_REGEX " #10353: " # ICC: option '-mfma' ignored, suggest using '-march=core-avx2'
70+
)
71+
SET (CMAKE_REQUIRED_DEFINITIONS "${SAFE_CMAKE_REQUIRED_DEFINITIONS}")
72+
ENDMACRO (CHECK_C_COMPILER_FLAG)
73+

0 commit comments

Comments
 (0)