Merge pull request #9756 from pranitbauva1997:doc-typo-faster
[platform/upstream/opencv.git] / cmake / OpenCVCompilerOptimizations.cmake
1 # x86/x86-64 arch:
2 # SSE / SSE2 (always available on 64-bit CPUs)
3 # SSE3 / SSSE3
4 # SSE4_1 / SSE4_2 / POPCNT
5 # AVX / AVX2 / AVX512
6 # FMA3
7
8 # CPU_{opt}_SUPPORTED=ON/OFF - compiler support (possibly with additional flag)
9 # CPU_{opt}_IMPLIES=<list>
10 # CPU_{opt}_FORCE=<list> - subset of "implies" list
11 # CPU_{opt}_FLAGS_ON=""
12 # CPU_{opt}_FEATURE_ALIAS - mapping to CV_CPU_* HWFeature enum
13
14 # Input variables:
15 # CPU_BASELINE=<list> - preferred list of baseline optimizations
16 # CPU_DISPATCH=<list> - preferred list of dispatched optimizations
17
18 # Advanced input variables:
19 # CPU_BASELINE_REQUIRE=<list> - list of required baseline optimizations
20 # CPU_DISPATCH_REQUIRE=<list> - list of required dispatched optimizations
21 # CPU_BASELINE_DISABLE=<list> - list of disabled baseline optimizations
22
23 # Output variables:
24 # CPU_BASELINE_FINAL=<list> - final list of enabled compiler optimizations
25 # CPU_DISPATCH_FINAL=<list> - final list of dispatched optimizations
26 #
27 # CPU_DISPATCH_FLAGS_${opt} - flags for source files compiled separately (_opt_avx2.cpp)
28
29 set(CPU_ALL_OPTIMIZATIONS "SSE;SSE2;SSE3;SSSE3;SSE4_1;SSE4_2;POPCNT;AVX;FP16;AVX2;FMA3") # without AVX512
30 list(APPEND CPU_ALL_OPTIMIZATIONS NEON VFPV3 FP16)
31 list(REMOVE_DUPLICATES CPU_ALL_OPTIMIZATIONS)
32
33 ocv_update(CPU_VFPV3_FEATURE_ALIAS "")
34
35
36 set(HELP_CPU_BASELINE "Specify list of enabled baseline CPU optimizations")
37 set(HELP_CPU_BASELINE_REQUIRE "Specify list of required baseline CPU optimizations")
38 set(HELP_CPU_BASELINE_DISABLE "Specify list of forbidden baseline CPU optimizations")
39 set(HELP_CPU_DISPATCH "Specify list of dispatched CPU optimizations")
40 set(HELP_CPU_DISPATCH_REQUIRE "Specify list of required dispatched CPU optimizations")
41
42 foreach(var CPU_BASELINE CPU_BASELINE_REQUIRE CPU_BASELINE_DISABLE CPU_DISPATCH CPU_DISPATCH_REQUIRE)
43   if(DEFINED ${var})
44     string(REPLACE "," ";" _list "${${var}}")
45     set(${var} "${_list}" CACHE STRING "${HELP_${var}}" FORCE)
46   endif()
47 endforeach()
48
49 # process legacy flags
50 macro(ocv_optimization_process_obsolete_option legacy_flag OPT legacy_warn)
51   if(DEFINED ${legacy_flag})
52     if(${legacy_warn})
53       message(STATUS "WARNING: Option ${legacy_flag}='${${legacy_flag}}' is deprecated and should not be used anymore")
54       message(STATUS "         Behaviour of this option is not backward compatible")
55       message(STATUS "         Refer to 'CPU_BASELINE'/'CPU_DISPATCH' CMake options documentation")
56     endif()
57     if(${legacy_flag})
58       if(NOT ";${CPU_BASELINE_REQUIRE};" MATCHES ";${OPT};")
59         set(CPU_BASELINE_REQUIRE "${CPU_BASELINE_REQUIRE};${OPT}" CACHE STRING "${HELP_CPU_BASELINE_REQUIRE}" FORCE)
60       endif()
61     else()
62       if(NOT ";${CPU_BASELINE_DISABLE};" MATCHES ";${OPT};")
63         set(CPU_BASELINE_DISABLE "${CPU_BASELINE_DISABLE};${OPT}" CACHE STRING "${HELP_CPU_BASELINE_DISABLE}" FORCE)
64       endif()
65     endif()
66   endif()
67 endmacro()
68 ocv_optimization_process_obsolete_option(ENABLE_SSE SSE ON)
69 ocv_optimization_process_obsolete_option(ENABLE_SSE2 SSE2 ON)
70 ocv_optimization_process_obsolete_option(ENABLE_SSE3 SSE3 ON)
71 ocv_optimization_process_obsolete_option(ENABLE_SSSE3 SSSE3 ON)
72 ocv_optimization_process_obsolete_option(ENABLE_SSE41 SSE4_1 ON)
73 ocv_optimization_process_obsolete_option(ENABLE_SSE42 SSE4_2 ON)
74 ocv_optimization_process_obsolete_option(ENABLE_POPCNT POPCNT ON)
75 ocv_optimization_process_obsolete_option(ENABLE_AVX AVX ON)
76 ocv_optimization_process_obsolete_option(ENABLE_AVX2 AVX2 ON)
77 ocv_optimization_process_obsolete_option(ENABLE_FMA3 FMA3 ON)
78
79 ocv_optimization_process_obsolete_option(ENABLE_VFPV3 VFPV3 OFF)
80 ocv_optimization_process_obsolete_option(ENABLE_NEON NEON OFF)
81
82
83 macro(ocv_is_optimization_in_list resultvar check_opt)
84   set(__checked "")
85   set(__queue ${ARGN})
86   set(${resultvar} 0)
87   while(__queue AND NOT ${resultvar})
88     list(REMOVE_DUPLICATES __queue)
89     set(__queue_current ${__queue})
90     set(__queue "")
91     foreach(OPT ${__queue_current})
92       if("x${OPT}" STREQUAL "x${check_opt}")
93         set(${resultvar} 1)
94         break()
95       elseif(NOT ";${__checked};" MATCHES ";${OPT};")
96         list(APPEND __queue ${CPU_${OPT}_IMPLIES})
97       endif()
98       list(APPEND __checked ${OPT})
99     endforeach()
100   endwhile()
101 endmacro()
102
103 macro(ocv_is_optimization_in_force_list resultvar check_opt)
104   set(__checked "")
105   set(__queue ${ARGN})
106   set(${resultvar} 0)
107   while(__queue AND NOT ${resultvar})
108     list(REMOVE_DUPLICATES __queue)
109     set(__queue_current ${__queue})
110     set(__queue "")
111     foreach(OPT ${__queue_current})
112       if(OPT STREQUAL "${check_opt}")
113         set(${resultvar} 1)
114         break()
115       elseif(NOT ";${__checked};" MATCHES ";${OPT};")
116         list(APPEND __queue ${CPU_${OPT}_FORCE})
117       endif()
118       list(APPEND __checked ${OPT})
119     endforeach()
120   endwhile()
121 endmacro()
122
123 macro(ocv_append_optimization_flag var OPT)
124   if(CPU_${OPT}_FLAGS_CONFLICT)
125     string(REGEX REPLACE " ${CPU_${OPT}_FLAGS_CONFLICT}" "" ${var} " ${${var}} ")
126     string(REGEX REPLACE "^ +" "" ${var} "${${var}}")
127   endif()
128   set(${var} "${${var}} ${CPU_${OPT}_FLAGS_ON}")
129 endmacro()
130
131 # Support GCC -march=native or Intel Compiler -xHost flags
132 if(";${CPU_BASELINE};" MATCHES ";NATIVE;" OR ";${CPU_BASELINE};" MATCHES ";HOST;")
133   set(CPU_BASELINE_DETECT ON)
134   set(_add_native_flag ON)
135 elseif(";${CPU_BASELINE};" MATCHES ";DETECT;")
136   set(CPU_BASELINE_DETECT ON)
137 elseif(" ${CMAKE_CXX_FLAGS} " MATCHES " -march=native | -xHost | /QxHost ")
138   if(DEFINED CPU_BASELINE)
139     message(STATUS "CPU: Detected '-march=native' or '-xHost' compiler flag. Force CPU_BASELINE=DETECT.")
140   endif()
141   set(CPU_BASELINE "DETECT" CACHE STRING "${HELP_CPU_BASELINE}")
142   set(CPU_BASELINE_DETECT ON)
143 endif()
144
145 if(X86 OR X86_64)
146   ocv_update(CPU_KNOWN_OPTIMIZATIONS "SSE;SSE2;SSE3;SSSE3;SSE4_1;POPCNT;SSE4_2;FP16;FMA3;AVX;AVX2") # without AVX512
147
148   ocv_update(CPU_SSE_TEST_FILE "${OpenCV_SOURCE_DIR}/cmake/checks/cpu_sse.cpp")
149   ocv_update(CPU_SSE2_TEST_FILE "${OpenCV_SOURCE_DIR}/cmake/checks/cpu_sse2.cpp")
150   ocv_update(CPU_SSE3_TEST_FILE "${OpenCV_SOURCE_DIR}/cmake/checks/cpu_sse3.cpp")
151   ocv_update(CPU_SSSE3_TEST_FILE "${OpenCV_SOURCE_DIR}/cmake/checks/cpu_ssse3.cpp")
152   ocv_update(CPU_SSE4_1_TEST_FILE "${OpenCV_SOURCE_DIR}/cmake/checks/cpu_sse41.cpp")
153   ocv_update(CPU_SSE4_2_TEST_FILE "${OpenCV_SOURCE_DIR}/cmake/checks/cpu_sse42.cpp")
154   ocv_update(CPU_POPCNT_TEST_FILE "${OpenCV_SOURCE_DIR}/cmake/checks/cpu_popcnt.cpp")
155   ocv_update(CPU_AVX_TEST_FILE "${OpenCV_SOURCE_DIR}/cmake/checks/cpu_avx.cpp")
156   ocv_update(CPU_AVX2_TEST_FILE "${OpenCV_SOURCE_DIR}/cmake/checks/cpu_avx2.cpp")
157   ocv_update(CPU_FP16_TEST_FILE "${OpenCV_SOURCE_DIR}/cmake/checks/cpu_fp16.cpp")
158   ocv_update(CPU_AVX512_TEST_FILE "${OpenCV_SOURCE_DIR}/cmake/checks/cpu_avx512.cpp")
159
160   if(NOT OPENCV_CPU_OPT_IMPLIES_IGNORE)
161     ocv_update(CPU_AVX512_IMPLIES "AVX2")
162     ocv_update(CPU_AVX512_FORCE "") # Don't force other optimizations
163     ocv_update(CPU_AVX2_IMPLIES "AVX;FMA3;FP16")
164     ocv_update(CPU_FMA3_IMPLIES "AVX2")
165     ocv_update(CPU_FMA3_FORCE "") # Don't force other optimizations
166     ocv_update(CPU_FP16_IMPLIES "AVX")
167     ocv_update(CPU_FP16_FORCE "") # Don't force other optimizations
168     ocv_update(CPU_AVX_IMPLIES "SSE4_2")
169     ocv_update(CPU_SSE4_2_IMPLIES "SSE4_1;POPCNT")
170     ocv_update(CPU_POPCNT_IMPLIES "SSE4_1")
171     ocv_update(CPU_POPCNT_FORCE "") # Don't force other optimizations
172     ocv_update(CPU_SSE4_1_IMPLIES "SSE3;SSSE3")
173     ocv_update(CPU_SSSE3_IMPLIES "SSE3")
174     ocv_update(CPU_SSE3_IMPLIES "SSE2")
175     ocv_update(CPU_SSE2_IMPLIES "SSE")
176   endif()
177
178   if(CV_ICC)
179     macro(ocv_intel_compiler_optimization_option name unix_flags msvc_flags)
180       ocv_update(CPU_${name}_FLAGS_NAME "${name}")
181       if(MSVC)
182         set(enable_flags "${msvc_flags}")
183         set(flags_conflict "/arch:[^ ]+")
184       else()
185         set(enable_flags "${unix_flags}")
186         set(flags_conflict "-msse[^ ]*|-mssse3|-mavx[^ ]*|-march[^ ]+")
187       endif()
188       ocv_update(CPU_${name}_FLAGS_ON "${enable_flags}")
189       if(flags_conflict)
190         ocv_update(CPU_${name}_FLAGS_CONFLICT "${flags_conflict}")
191       endif()
192     endmacro()
193     ocv_intel_compiler_optimization_option(AVX2 "-march=core-avx2" "/arch:CORE-AVX2")
194     ocv_intel_compiler_optimization_option(FP16 "-mavx" "/arch:AVX")
195     ocv_intel_compiler_optimization_option(AVX "-mavx" "/arch:AVX")
196     ocv_intel_compiler_optimization_option(FMA3 "" "")
197     ocv_intel_compiler_optimization_option(POPCNT "" "")
198     ocv_intel_compiler_optimization_option(SSE4_2 "-msse4.2" "/arch:SSE4.2")
199     ocv_intel_compiler_optimization_option(SSE4_1 "-msse4.1" "/arch:SSE4.1")
200     ocv_intel_compiler_optimization_option(SSE3 "-msse3" "/arch:SSE3")
201     ocv_intel_compiler_optimization_option(SSSE3 "-mssse3" "/arch:SSSE3")
202     ocv_intel_compiler_optimization_option(SSE2 "-msse2" "/arch:SSE2")
203     if(NOT X86_64) # x64 compiler doesn't support /arch:sse
204       ocv_intel_compiler_optimization_option(SSE "-msse" "/arch:SSE")
205     endif()
206     #ocv_intel_compiler_optimization_option(AVX512   "-march=core-avx512")
207   elseif(CMAKE_COMPILER_IS_GNUCXX)
208     ocv_update(CPU_AVX2_FLAGS_ON "-mavx2")
209     ocv_update(CPU_FP16_FLAGS_ON "-mf16c")
210     ocv_update(CPU_AVX_FLAGS_ON "-mavx")
211     ocv_update(CPU_FMA3_FLAGS_ON "-mfma")
212     ocv_update(CPU_POPCNT_FLAGS_ON "-mpopcnt")
213     ocv_update(CPU_SSE4_2_FLAGS_ON "-msse4.2")
214     ocv_update(CPU_SSE4_1_FLAGS_ON "-msse4.1")
215     ocv_update(CPU_SSE3_FLAGS_ON "-msse3")
216     ocv_update(CPU_SSSE3_FLAGS_ON "-mssse3")
217     ocv_update(CPU_SSE2_FLAGS_ON "-msse2")
218     ocv_update(CPU_SSE_FLAGS_ON "-msse")
219     if(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS "5.0")
220       ocv_update(CPU_AVX512_FLAGS_ON "-mavx512f -mavx512pf -mavx512er -mavx512cd -mavx512vl -mavx512bw -mavx512dq -mavx512ifma -mavx512vbmi")
221     endif()
222   elseif(MSVC)
223     ocv_update(CPU_AVX2_FLAGS_ON "/arch:AVX2")
224     ocv_update(CPU_AVX_FLAGS_ON "/arch:AVX")
225     if(NOT MSVC64)
226       # 64-bit MSVC compiler uses SSE/SSE2 by default
227       ocv_update(CPU_SSE_FLAGS_ON "/arch:SSE")
228       ocv_update(CPU_SSE_SUPPORTED ON)
229       ocv_update(CPU_SSE2_FLAGS_ON "/arch:SSE2")
230       ocv_update(CPU_SSE2_SUPPORTED ON)
231     else()
232       ocv_update(CPU_SSE_SUPPORTED ON)
233       ocv_update(CPU_SSE2_SUPPORTED ON)
234     endif()
235     # Other instruction sets are supported by default since MSVC 2008 at least
236   else()
237     message(WARNING "TODO: Unsupported compiler")
238   endif()
239
240   if(NOT DEFINED CPU_DISPATCH)
241     set(CPU_DISPATCH "SSE4_1;SSE4_2;AVX;FP16;AVX2" CACHE STRING "${HELP_CPU_DISPATCH}")
242   endif()
243
244   if(NOT DEFINED CPU_BASELINE)
245     if(X86_64)
246       set(CPU_BASELINE "SSE3" CACHE STRING "${HELP_CPU_BASELINE}")
247     else()
248       set(CPU_BASELINE "SSE2" CACHE STRING "${HELP_CPU_BASELINE}")
249     endif()
250   endif()
251
252 elseif(ARM OR AARCH64)
253   ocv_update(CPU_NEON_TEST_FILE "${OpenCV_SOURCE_DIR}/cmake/checks/cpu_neon.cpp")
254   ocv_update(CPU_FP16_TEST_FILE "${OpenCV_SOURCE_DIR}/cmake/checks/cpu_fp16.cpp")
255   if(NOT AARCH64)
256     ocv_update(CPU_KNOWN_OPTIMIZATIONS "VFPV3;NEON;FP16")
257     ocv_update(CPU_VFPV3_FLAGS_ON "-mfpu=vfpv3")
258     ocv_update(CPU_NEON_FLAGS_ON "-mfpu=neon")
259     ocv_update(CPU_NEON_FLAGS_CONFLICT "-mfpu=[^ ]*")
260     ocv_update(CPU_FP16_FLAGS_ON "-mfpu=neon-fp16")
261     ocv_update(CPU_FP16_IMPLIES "NEON")
262     ocv_update(CPU_FP16_FLAGS_CONFLICT "-mfpu=[^ ]*")
263   else()
264     ocv_update(CPU_KNOWN_OPTIMIZATIONS "NEON;FP16")
265     ocv_update(CPU_NEON_FLAGS_ON "")
266     ocv_update(CPU_FP16_IMPLIES "NEON")
267     set(CPU_BASELINE "NEON;FP16" CACHE STRING "${HELP_CPU_BASELINE}")
268   endif()
269 endif()
270
271 # Helper values for cmake-gui
272 set(CPU_BASELINE "DETECT" CACHE STRING "${HELP_CPU_BASELINE}")
273 set(CPU_DISPATCH "" CACHE STRING "${HELP_CPU_DISPATCH}")
274 set_property(CACHE CPU_BASELINE PROPERTY STRINGS "" ${CPU_KNOWN_OPTIMIZATIONS})
275 set_property(CACHE CPU_DISPATCH PROPERTY STRINGS "" ${CPU_KNOWN_OPTIMIZATIONS})
276
277 # Update CPU_BASELINE_DETECT flag
278 if(";${CPU_BASELINE};" MATCHES ";DETECT;")
279   set(CPU_BASELINE_DETECT ON)
280 endif()
281
282 set(CPU_BASELINE_FLAGS "")
283
284 set(CPU_BASELINE_FINAL "")
285 set(CPU_DISPATCH_FINAL "")
286
287 if(CV_DISABLE_OPTIMIZATION)
288   set(CPU_DISPATCH "")
289   set(CPU_DISPATCH_REQUIRE "")
290 endif()
291
292 macro(ocv_check_compiler_optimization OPT)
293   if(NOT DEFINED CPU_${OPT}_SUPPORTED)
294     if((DEFINED CPU_${OPT}_FLAGS_ON AND NOT "x${CPU_${OPT}_FLAGS_ON}" STREQUAL "x") OR CPU_${OPT}_TEST_FILE)
295       set(_varname "")
296       if(CPU_${OPT}_TEST_FILE)
297         set(__available 0)
298         if(CPU_BASELINE_DETECT)
299           set(_varname "HAVE_CPU_${OPT}_SUPPORT")
300           ocv_check_compiler_flag(CXX "${CPU_BASELINE_FLAGS}" "${_varname}" "${CPU_${OPT}_TEST_FILE}")
301           if(${_varname})
302             list(APPEND CPU_BASELINE_FINAL ${OPT})
303             set(__available 1)
304           endif()
305         endif()
306         if(NOT __available)
307           if(NOT "x${CPU_${OPT}_FLAGS_NAME}" STREQUAL "x")
308             set(_varname "HAVE_CPU_${CPU_${OPT}_FLAGS_NAME}")
309             set(_compile_flags "${CPU_BASELINE_FLAGS}")
310             ocv_append_optimization_flag(_compile_flags ${OPT})
311             ocv_check_compiler_flag(CXX "${_compile_flags}" "${_varname}" "${CPU_${OPT}_TEST_FILE}")
312           elseif(NOT "x${CPU_${OPT}_FLAGS_ON}" STREQUAL "x")
313             ocv_check_flag_support(CXX "${CPU_${OPT}_FLAGS_ON}" _varname "" "${CPU_${OPT}_TEST_FILE}")
314           else()
315             set(_varname "HAVE_CPU_${OPT}_SUPPORT")
316             set(_compile_flags "${CPU_BASELINE_FLAGS}")
317             ocv_append_optimization_flag(_compile_flags ${OPT})
318             ocv_check_compiler_flag(CXX "${_compile_flags}" "${_varname}" "${CPU_${OPT}_TEST_FILE}")
319           endif()
320         endif()
321       else()
322         ocv_check_flag_support(CXX "${CPU_${OPT}_FLAGS_ON}" _varname "")
323       endif()
324       if(_varname AND ${_varname})
325         set(CPU_${OPT}_SUPPORTED ON)
326       elseif(NOT CPU_${OPT}_SUPPORTED)
327         message(STATUS "${OPT} is not supported by C++ compiler")
328       endif()
329     else()
330       set(CPU_${OPT}_SUPPORTED ON)
331     endif()
332   endif()
333 endmacro()
334
335 foreach(OPT ${CPU_KNOWN_OPTIMIZATIONS})
336   set(CPU_${OPT}_USAGE_COUNT 0 CACHE INTERNAL "")
337   if(NOT DEFINED CPU_${OPT}_FORCE)
338     set(CPU_${OPT}_FORCE "${CPU_${OPT}_IMPLIES}")
339   endif()
340 endforeach()
341
342 if(_add_native_flag)
343   set(_varname "HAVE_CPU_NATIVE_SUPPORT")
344   ocv_check_compiler_flag(CXX "-march=native" "${_varname}" "")
345   if(_varname)
346     set(CPU_BASELINE_FLAGS "${CPU_BASELINE_FLAGS} -march=native")
347   else()
348     set(_varname "HAVE_CPU_HOST_SUPPORT")
349     if(MSVC)
350       set(_flag "/QxHost")
351     else()
352       set(_flag "-xHost")
353     endif()
354     ocv_check_compiler_flag(CXX "${_flag}" "${_varname}" "")
355     if(_varname)
356       set(CPU_BASELINE_FLAGS "${CPU_BASELINE_FLAGS} ${flag}")
357     endif()
358   endif()
359 endif()
360
361 foreach(OPT ${CPU_KNOWN_OPTIMIZATIONS})
362   set(__is_disabled 0)
363   foreach(OPT2 ${CPU_BASELINE_DISABLE})
364     ocv_is_optimization_in_list(__is_disabled ${OPT2} ${OPT})
365     if(__is_disabled)
366       break()
367     endif()
368   endforeach()
369   if(__is_disabled)
370     set(__is_from_baseline 0)
371   else()
372     ocv_is_optimization_in_list(__is_from_baseline ${OPT} ${CPU_BASELINE_REQUIRE})
373     if(NOT __is_from_baseline)
374       ocv_is_optimization_in_list(__is_from_baseline ${OPT} ${CPU_BASELINE})
375     endif()
376   endif()
377   ocv_is_optimization_in_list(__is_from_dispatch ${OPT} ${CPU_DISPATCH_REQUIRE})
378   if(NOT __is_from_dispatch)
379     ocv_is_optimization_in_list(__is_from_dispatch ${OPT} ${CPU_DISPATCH})
380   endif()
381   if(__is_from_dispatch OR __is_from_baseline OR CPU_BASELINE_DETECT)
382     ocv_check_compiler_optimization(${OPT})
383   endif()
384   if(CPU_BASELINE_DETECT AND NOT __is_from_baseline AND NOT __is_disabled)
385     ocv_is_optimization_in_list(__is_from_baseline ${OPT} ${CPU_BASELINE_FINAL})
386   endif()
387   if(CPU_${OPT}_SUPPORTED)
388     if(";${CPU_DISPATCH};" MATCHES ";${OPT};" AND NOT __is_from_baseline)
389       list(APPEND CPU_DISPATCH_FINAL ${OPT})
390     elseif(__is_from_baseline)
391       list(APPEND CPU_BASELINE_FINAL ${OPT})
392       ocv_append_optimization_flag(CPU_BASELINE_FLAGS ${OPT})
393     endif()
394   endif()
395 endforeach()
396
397 foreach(OPT ${CPU_BASELINE_REQUIRE})
398   if(NOT ";${CPU_BASELINE_FINAL};" MATCHES ";${OPT};")
399     message(SEND_ERROR "Required baseline optimization is not supported: ${OPT} (CPU_BASELINE_REQUIRE=${CPU_BASELINE_REQUIRE})")
400   endif()
401 endforeach()
402
403 foreach(OPT ${CPU_BASELINE})
404   if(OPT STREQUAL "DETECT" OR OPT STREQUAL "HOST" OR OPT STREQUAL "NATIVE")
405     # nothing
406   elseif(NOT ";${CPU_BASELINE_FINAL};" MATCHES ";${OPT};")
407     message(STATUS "Optimization ${OPT} is not available, skipped")
408   endif()
409 endforeach()
410
411 foreach(OPT ${CPU_DISPATCH_REQUIRE})
412   if(";${CPU_DISPATCH_FINAL};" MATCHES ";${OPT};")
413     # OK
414   elseif(";${CPU_BASELINE_FINAL};" MATCHES ";${OPT};")
415     message(SEND_ERROR "Dispatched optimization ${OPT} is in baseline list (CPU_DISPATCH_REQUIRE=${CPU_DISPATCH_REQUIRE})")
416   else()
417     message(SEND_ERROR "Required dispatch optimization is not supported: ${OPT} (CPU_DISPATCH_REQUIRE=${CPU_DISPATCH_REQUIRE})")
418   endif()
419 endforeach()
420
421 foreach(OPT ${CPU_DISPATCH})
422   if(";${CPU_DISPATCH_FINAL};" MATCHES ";${OPT};")
423     # OK
424   elseif(";${CPU_BASELINE_FINAL};" MATCHES ";${OPT};")
425     # OK
426   else()
427     message(STATUS "Dispatch optimization ${OPT} is not available, skipped")
428   endif()
429 endforeach()
430
431 #message(STATUS "CPU_BASELINE_FINAL=${CPU_BASELINE_FINAL}")
432 #message(STATUS "CPU_DISPATCH_FINAL=${CPU_DISPATCH_FINAL}")
433
434 #if(CPU_DISPATCH_FINAL AND NOT PYTHON_DEFAULT_EXECUTABLE)
435 #  message(FATAL_ERROR "Python is required for CPU dispatched optimization support")
436 #endif()
437
438 macro(ocv_compiler_optimization_options)
439   set(__flags "${OPENCV_EXTRA_CXX_FLAGS} ${CPU_BASELINE_FLAGS}")
440   if(NOT __flags STREQUAL CACHED_CPU_BASELINE_FLAGS)
441     set(CACHED_CPU_BASELINE_FLAGS "${__flags}" CACHE INTERNAL "" FORCE)
442     ocv_clear_vars(HAVE_CPU_BASELINE_FLAGS)
443   endif()
444   ocv_check_compiler_flag(CXX "${__flags}" HAVE_CPU_BASELINE_FLAGS)
445   if(NOT HAVE_CPU_BASELINE_FLAGS)
446     message(FATAL_ERROR "Compiler doesn't support baseline optimization flags: ${CPU_BASELINE_FLAGS}")
447   endif()
448   add_extra_compiler_option_force("${CPU_BASELINE_FLAGS}")
449
450   foreach(OPT ${CPU_DISPATCH_FINAL})
451     set(__dispatch_flags "")
452     set(__dispatch_definitions "")
453     set(__dispatch_opts "")
454     set(__dispatch_opts_force "")
455     foreach(OPT2 ${CPU_KNOWN_OPTIMIZATIONS})
456       if(NOT CPU_${OPT2}_SUPPORTED)
457         #continue()
458       else()
459       ocv_is_optimization_in_list(__is_from_baseline ${OPT2} ${CPU_BASELINE_FINAL})
460       if(NOT __is_from_baseline)
461         ocv_is_optimization_in_list(__is_active ${OPT2} ${OPT})
462         if(__is_active)
463           ocv_append_optimization_flag(__dispatch_flags ${OPT2})
464           list(APPEND __dispatch_definitions "CV_CPU_COMPILE_${OPT2}=1")
465           list(APPEND __dispatch_opts "${OPT2}")
466         endif()
467         ocv_is_optimization_in_force_list(__is_force ${OPT2} ${OPT})
468         if(__is_force)
469           list(APPEND __dispatch_opts_force "${OPT2}")
470         endif()
471       endif()
472       endif()
473     endforeach()
474     set(__flags "${OPENCV_EXTRA_CXX_FLAGS} ${__dispatch_flags}")
475     if(NOT __flags STREQUAL CACHED_CPU_DISPATCH_${OPT}_FLAGS)
476       set(CACHED_CPU_DISPATCH_${OPT}_FLAGS "${__flags}" CACHE INTERNAL "" FORCE)
477       ocv_clear_vars(HAVE_CPU_DISPATCH_FLAGS_${OPT})
478     endif()
479     ocv_check_compiler_flag(CXX "${__flags}" HAVE_CPU_DISPATCH_FLAGS_${OPT})
480     if(NOT HAVE_CPU_DISPATCH_FLAGS_${OPT})
481       message(FATAL_ERROR "Compiler doesn't support optimization flags for ${OPT} dispatch mode: ${__dispatch_flags}")
482     endif()
483     set(CPU_DISPATCH_FLAGS_${OPT} "${__dispatch_flags}")
484     set(CPU_DISPATCH_DEFINITIONS_${OPT} "${__dispatch_definitions}")
485     set(CPU_DISPATCH_${OPT}_INCLUDED "${__dispatch_opts}")
486     set(CPU_DISPATCH_${OPT}_FORCED "${__dispatch_opts_force}")
487   endforeach()
488
489   if(ENABLE_POWERPC)
490     add_extra_compiler_option("-mcpu=G3 -mtune=G5")
491   endif()
492   if(ARM)
493     add_extra_compiler_option("-mfp16-format=ieee")
494   endif(ARM)
495 endmacro()
496
497 macro(ocv_compiler_optimization_options_finalize)
498   if(CMAKE_COMPILER_IS_GNUCXX AND (X86 OR X86_64))
499     if(NOT APPLE AND CMAKE_SIZEOF_VOID_P EQUAL 4)
500       if(OPENCV_EXTRA_CXX_FLAGS MATCHES "-m(sse2|avx)")
501         add_extra_compiler_option(-mfpmath=sse) # !! important - be on the same wave with x64 compilers
502       else()
503         add_extra_compiler_option(-mfpmath=387)
504       endif()
505     endif()
506   endif()
507
508   if(MSVC)
509     # Generate Intrinsic Functions
510     set(OPENCV_EXTRA_FLAGS "${OPENCV_EXTRA_FLAGS} /Oi")
511
512     if((X86 OR X86_64) AND CMAKE_SIZEOF_VOID_P EQUAL 4 AND ";${CPU_BASELINE_FINAL};" MATCHES ";SSE;")
513       set(OPENCV_EXTRA_FLAGS "${OPENCV_EXTRA_FLAGS} /fp:fast") # !! important - be on the same wave with x64 compilers
514     endif()
515   endif(MSVC)
516 endmacro()
517
518 macro(ocv_compiler_optimization_process_sources SOURCES_VAR_NAME LIBS_VAR_NAME TARGET_BASE_NAME)
519   set(__result "")
520   set(__result_libs "")
521   foreach(OPT ${CPU_DISPATCH_FINAL})
522     set(__result_${OPT} "")
523   endforeach()
524   foreach(fname ${${SOURCES_VAR_NAME}})
525     string(TOLOWER "${fname}" fname_LOWER)
526     get_filename_component(fname_LOWER "${fname_LOWER}" NAME)
527     if(fname_LOWER MATCHES "\\.(.*)\\.cpp$")
528       string(TOUPPER "${CMAKE_MATCH_1}" OPT_)
529       if(OPT_ MATCHES "(CUDA.*|DISPATCH.*|OCL)") # don't touch files like filename.cuda.cpp
530         list(APPEND __result "${fname}")
531         #continue()
532       elseif(CV_DISABLE_OPTIMIZATION OR NOT CV_ENABLE_INTRINSICS)
533         message(STATUS "Excluding from source files list (optimization is disabled): ${fname}")
534         #continue()
535       else()
536         get_source_file_property(__definitions "${fname}" COMPILE_DEFINITIONS)
537         if(__definitions)
538           list(APPEND __definitions "CV_CPU_DISPATCH_MODE=${OPT_}")
539         else()
540           set(__definitions "CV_CPU_DISPATCH_MODE=${OPT_}")
541         endif()
542         set_source_files_properties("${fname}" PROPERTIES COMPILE_DEFINITIONS "${__definitions}")
543
544         set(__opt_found 0)
545         foreach(OPT ${CPU_BASELINE_FINAL})
546           string(TOLOWER "${OPT}" OPT_LOWER)
547           if(fname_LOWER MATCHES "\\.${OPT_LOWER}\\.cpp$")
548 #message("${fname} BASELINE-${OPT}")
549             set(__opt_found 1)
550             list(APPEND __result "${fname}")
551             break()
552           endif()
553         endforeach()
554         foreach(OPT ${CPU_DISPATCH_FINAL})
555           foreach(OPT2 ${CPU_DISPATCH_${OPT}_FORCED})
556             string(TOLOWER "${OPT2}" OPT2_LOWER)
557             if(fname_LOWER MATCHES "\\.${OPT2_LOWER}\\.cpp$")
558               list(APPEND __result_${OPT} "${fname}")
559               math(EXPR CPU_${OPT}_USAGE_COUNT "${CPU_${OPT}_USAGE_COUNT}+1")
560               set(CPU_${OPT}_USAGE_COUNT "${CPU_${OPT}_USAGE_COUNT}" CACHE INTERNAL "" FORCE)
561 #message("(${CPU_${OPT}_USAGE_COUNT})${fname} ${OPT}")
562 #message("    ${CPU_DISPATCH_${OPT}_INCLUDED}")
563 #message("    ${CPU_DISPATCH_DEFINITIONS_${OPT}}")
564 #message("    ${CPU_DISPATCH_FLAGS_${OPT}}")
565               set(__opt_found 1)
566               break()
567             endif()
568           endforeach()
569           if(__opt_found)
570             set(__opt_found 1)
571             break()
572           endif()
573         endforeach()
574         if(NOT __opt_found)
575           message(STATUS "Excluding from source files list: ${fname}")
576         endif()
577       endif()
578     else()
579       list(APPEND __result "${fname}")
580     endif()
581   endforeach()
582
583   foreach(OPT ${CPU_DISPATCH_FINAL})
584     if(__result_${OPT})
585 #message("${OPT}: ${__result_${OPT}}")
586       if(CMAKE_GENERATOR MATCHES "^Visual")
587         # extra flags are added before common flags, so switching between optimizations doesn't work correctly
588         # Also CMAKE_CXX_FLAGS doesn't work (it is directory-based, so add_subdirectory is required)
589         add_library(${TARGET_BASE_NAME}_${OPT} OBJECT ${__result_${OPT}})
590         ocv_append_dependant_targets(${TARGET_BASE_NAME} ${TARGET_BASE_NAME}_${OPT})
591         set_target_properties(${TARGET_BASE_NAME}_${OPT} PROPERTIES COMPILE_DEFINITIONS "${CPU_DISPATCH_DEFINITIONS_${OPT}}")
592         set_target_properties(${TARGET_BASE_NAME}_${OPT} PROPERTIES COMPILE_FLAGS "${CPU_DISPATCH_FLAGS_${OPT}}")
593         target_include_directories(${TARGET_BASE_NAME}_${OPT} PRIVATE $<TARGET_PROPERTY:${TARGET_BASE_NAME},INCLUDE_DIRECTORIES>)
594         #list(APPEND __result_libs ${TARGET_BASE_NAME}_${OPT})
595         list(APPEND __result "$<TARGET_OBJECTS:${TARGET_BASE_NAME}_${OPT}>")
596       else()
597         foreach(fname ${__result_${OPT}})
598           get_source_file_property(__definitions "${fname}" COMPILE_DEFINITIONS)
599           if(__definitions)
600             list(APPEND __definitions "${CPU_DISPATCH_DEFINITIONS_${OPT}}")
601           else()
602             set(__definitions "${CPU_DISPATCH_DEFINITIONS_${OPT}}")
603           endif()
604           set_source_files_properties("${fname}" PROPERTIES COMPILE_DEFINITIONS "${__definitions}")
605           set_source_files_properties("${fname}" PROPERTIES COMPILE_FLAGS "${CPU_DISPATCH_FLAGS_${OPT}}")
606         endforeach()
607         list(APPEND __result ${__result_${OPT}})
608       endif()
609     endif()
610   endforeach()
611   set(${SOURCES_VAR_NAME} "${__result}")
612   list(APPEND ${LIBS_VAR_NAME} ${__result_libs})
613 endmacro()
614
615 macro(ocv_compiler_optimization_fill_cpu_config)
616   set(OPENCV_CPU_BASELINE_DEFINITIONS_CONFIGMAKE "")
617   foreach(OPT ${CPU_BASELINE_FINAL})
618     set(OPENCV_CPU_BASELINE_DEFINITIONS_CONFIGMAKE "${OPENCV_CPU_BASELINE_DEFINITIONS_CONFIGMAKE}
619 #define CV_CPU_COMPILE_${OPT} 1
620 #define CV_CPU_BASELINE_COMPILE_${OPT} 1
621 ")
622   endforeach()
623
624   set(OPENCV_CPU_BASELINE_DEFINITIONS_CONFIGMAKE "${OPENCV_CPU_BASELINE_DEFINITIONS_CONFIGMAKE}
625 #define CV_CPU_BASELINE_FEATURES 0 \\")
626   foreach(OPT ${CPU_BASELINE_FINAL})
627     if(NOT DEFINED CPU_${OPT}_FEATURE_ALIAS OR NOT "x${CPU_${OPT}_FEATURE_ALIAS}" STREQUAL "x")
628       set(OPENCV_CPU_BASELINE_DEFINITIONS_CONFIGMAKE "${OPENCV_CPU_BASELINE_DEFINITIONS_CONFIGMAKE}
629     , CV_CPU_${OPT} \\")
630     endif()
631   endforeach()
632   set(OPENCV_CPU_BASELINE_DEFINITIONS_CONFIGMAKE "${OPENCV_CPU_BASELINE_DEFINITIONS_CONFIGMAKE}\n")
633
634   set(__dispatch_modes "")
635   foreach(OPT ${CPU_DISPATCH_FINAL})
636     list(APPEND __dispatch_modes ${CPU_DISPATCH_${OPT}_FORCE} ${OPT})
637   endforeach()
638   list(REMOVE_DUPLICATES __dispatch_modes)
639   set(OPENCV_CPU_DISPATCH_DEFINITIONS_CONFIGMAKE "")
640   foreach(OPT ${__dispatch_modes})
641     set(OPENCV_CPU_DISPATCH_DEFINITIONS_CONFIGMAKE "${OPENCV_CPU_DISPATCH_DEFINITIONS_CONFIGMAKE}
642 #define CV_CPU_DISPATCH_COMPILE_${OPT} 1")
643   endforeach()
644
645   set(OPENCV_CPU_CONTROL_DEFINITIONS_CONFIGMAKE "// AUTOGENERATED, DO NOT EDIT\n")
646   foreach(OPT ${CPU_ALL_OPTIMIZATIONS})
647     if(NOT DEFINED CPU_${OPT}_FEATURE_ALIAS OR NOT "x${CPU_${OPT}_FEATURE_ALIAS}" STREQUAL "x")
648       set(OPENCV_CPU_CONTROL_DEFINITIONS_CONFIGMAKE "${OPENCV_CPU_CONTROL_DEFINITIONS_CONFIGMAKE}
649 #if !defined CV_DISABLE_OPTIMIZATION && defined CV_ENABLE_INTRINSICS && defined CV_CPU_COMPILE_${OPT}
650 #  define CV_TRY_${OPT} 1
651 #  define CV_CPU_HAS_SUPPORT_${OPT} 1
652 #  define CV_CPU_CALL_${OPT}(fn, args) return (opt_${OPT}::fn args)
653 #elif !defined CV_DISABLE_OPTIMIZATION && defined CV_ENABLE_INTRINSICS && defined CV_CPU_DISPATCH_COMPILE_${OPT}
654 #  define CV_TRY_${OPT} 1
655 #  define CV_CPU_HAS_SUPPORT_${OPT} (cv::checkHardwareSupport(CV_CPU_${OPT}))
656 #  define CV_CPU_CALL_${OPT}(fn, args) if (CV_CPU_HAS_SUPPORT_${OPT}) return (opt_${OPT}::fn args)
657 #else
658 #  define CV_TRY_${OPT} 0
659 #  define CV_CPU_HAS_SUPPORT_${OPT} 0
660 #  define CV_CPU_CALL_${OPT}(fn, args)
661 #endif
662 #define __CV_CPU_DISPATCH_CHAIN_${OPT}(fn, args, mode, ...)  CV_CPU_CALL_${OPT}(fn, args); __CV_EXPAND(__CV_CPU_DISPATCH_CHAIN_ ## mode(fn, args, __VA_ARGS__))
663 ")
664     endif()
665   endforeach()
666
667   set(OPENCV_CPU_CONTROL_DEFINITIONS_CONFIGMAKE "${OPENCV_CPU_CONTROL_DEFINITIONS_CONFIGMAKE}
668 #define CV_CPU_CALL_BASELINE(fn, args) return (cpu_baseline::fn args)
669 #define __CV_CPU_DISPATCH_CHAIN_BASELINE(fn, args, mode, ...)  CV_CPU_CALL_BASELINE(fn, args) /* last in sequence */
670 ")
671
672
673   set(__file "${CMAKE_SOURCE_DIR}/modules/core/include/opencv2/core/cv_cpu_helper.h")
674   if(EXISTS "${__file}")
675     file(READ "${__file}" __content)
676   endif()
677   if(__content STREQUAL OPENCV_CPU_CONTROL_DEFINITIONS_CONFIGMAKE)
678     #message(STATUS "${__file} contains same content")
679   else()
680     file(WRITE "${__file}" "${OPENCV_CPU_CONTROL_DEFINITIONS_CONFIGMAKE}")
681     message(WARNING "${__file} is updated")
682   endif()
683 endmacro()
684
685 macro(ocv_add_dispatched_file filename)
686   if(NOT OPENCV_INITIAL_PASS)
687     set(__codestr "
688 #include \"precomp.hpp\"
689 #include \"${filename}.simd.hpp\"
690 ")
691
692     set(__declarations_str "#define CV_CPU_SIMD_FILENAME \"${filename}.simd.hpp\"")
693     set(__dispatch_modes "BASELINE")
694
695     set(__optimizations "${ARGN}")
696     if(CV_DISABLE_OPTIMIZATION OR NOT CV_ENABLE_INTRINSICS)
697       set(__optimizations "")
698     endif()
699
700     foreach(OPT ${__optimizations})
701       string(TOLOWER "${OPT}" OPT_LOWER)
702       set(__file "${CMAKE_CURRENT_BINARY_DIR}/${filename}.${OPT_LOWER}.cpp")
703       if(EXISTS "${__file}")
704         file(READ "${__file}" __content)
705       endif()
706       if(__content STREQUAL __codestr)
707         #message(STATUS "${__file} contains up-to-date content")
708       else()
709         file(WRITE "${__file}" "${__codestr}")
710       endif()
711       list(APPEND OPENCV_MODULE_${the_module}_SOURCES_DISPATCHED "${__file}")
712
713       set(__declarations_str "${__declarations_str}
714 #define CV_CPU_DISPATCH_MODE ${OPT}
715 #include \"opencv2/core/private/cv_cpu_include_simd_declarations.hpp\"
716 ")
717       set(__dispatch_modes "${OPT}, ${__dispatch_modes}")
718     endforeach()
719
720     set(__declarations_str "${__declarations_str}
721 #define CV_CPU_DISPATCH_MODES_ALL ${__dispatch_modes}
722 ")
723
724     set(__file "${CMAKE_CURRENT_BINARY_DIR}/${filename}.simd_declarations.hpp")
725     if(EXISTS "${__file}")
726       file(READ "${__file}" __content)
727     endif()
728     if(__content STREQUAL __declarations_str)
729       #message(STATUS "${__file} contains up-to-date content")
730     else()
731       file(WRITE "${__file}" "${__declarations_str}")
732     endif()
733   endif()
734 endmacro()
735
736 if(CV_DISABLE_OPTIMIZATION OR CV_ICC)
737   ocv_update(CV_ENABLE_UNROLLED 0)
738 else()
739   ocv_update(CV_ENABLE_UNROLLED 1)
740 endif()