1 # Macros for use with the Vc library. Vc can be found at http://code.compeng.uni-frankfurt.de/projects/vc
3 # The following macros are provided:
4 # vc_determine_compiler
5 # vc_set_preferred_compiler_flags
7 #=============================================================================
8 # Copyright 2009-2013 Matthias Kretz <kretz@kde.org>
10 # Redistribution and use in source and binary forms, with or without
11 # modification, are permitted provided that the following conditions are
14 # * Redistributions of source code must retain the above copyright notice,
15 # this list of conditions and the following disclaimer.
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.
21 # * The names of Kitware, Inc., the Insight Consortium, or the names of
22 # any consortium members, or of any contributors, may not be used to
23 # endorse or promote products derived from this software without
24 # specific prior written permission.
26 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS ``AS IS''
27 # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 # ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR
30 # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
32 # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
33 # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
34 # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 #=============================================================================
38 cmake_minimum_required(VERSION 2.8.3)
40 get_filename_component(_currentDir "${CMAKE_CURRENT_LIST_FILE}" PATH)
41 include ("${_currentDir}/UserWarning.cmake")
42 include ("${_currentDir}/AddCompilerFlag.cmake")
43 include ("${_currentDir}/OptimizeForArchitecture.cmake")
45 macro(vc_determine_compiler)
46 if(NOT DEFINED Vc_COMPILER_IS_INTEL)
47 execute_process(COMMAND "${CMAKE_CXX_COMPILER}" "--version" OUTPUT_VARIABLE _cxx_compiler_version ERROR_VARIABLE _cxx_compiler_version)
48 set(Vc_COMPILER_IS_INTEL false)
49 set(Vc_COMPILER_IS_OPEN64 false)
50 set(Vc_COMPILER_IS_CLANG false)
51 set(Vc_COMPILER_IS_MSVC false)
52 set(Vc_COMPILER_IS_GCC false)
53 if(CMAKE_CXX_COMPILER MATCHES "/(icpc|icc)$")
54 set(Vc_COMPILER_IS_INTEL true)
55 exec_program(${CMAKE_C_COMPILER} ARGS -dumpversion OUTPUT_VARIABLE Vc_ICC_VERSION)
56 message(STATUS "Detected Compiler: Intel ${Vc_ICC_VERSION}")
57 elseif(CMAKE_CXX_COMPILER MATCHES "(opencc|openCC)$")
58 set(Vc_COMPILER_IS_OPEN64 true)
59 message(STATUS "Detected Compiler: Open64")
60 elseif(CMAKE_CXX_COMPILER MATCHES "clang\\+\\+$" OR "${_cxx_compiler_version}" MATCHES "clang")
61 set(Vc_COMPILER_IS_CLANG true)
62 exec_program(${CMAKE_CXX_COMPILER} ARGS --version OUTPUT_VARIABLE Vc_CLANG_VERSION)
63 string(REGEX MATCH "[0-9]+\\.[0-9]+(\\.[0-9]+)?" Vc_CLANG_VERSION "${Vc_CLANG_VERSION}")
64 message(STATUS "Detected Compiler: Clang ${Vc_CLANG_VERSION}")
66 set(Vc_COMPILER_IS_MSVC true)
67 message(STATUS "Detected Compiler: MSVC ${MSVC_VERSION}")
68 elseif(CMAKE_COMPILER_IS_GNUCXX)
69 set(Vc_COMPILER_IS_GCC true)
70 exec_program(${CMAKE_C_COMPILER} ARGS -dumpversion OUTPUT_VARIABLE Vc_GCC_VERSION)
71 message(STATUS "Detected Compiler: GCC ${Vc_GCC_VERSION}")
73 # some distributions patch their GCC to return nothing or only major and minor version on -dumpversion.
74 # In that case we must extract the version number from --version.
75 if(NOT Vc_GCC_VERSION OR Vc_GCC_VERSION MATCHES "^[0-9]\\.[0-9]+$")
76 exec_program(${CMAKE_C_COMPILER} ARGS --version OUTPUT_VARIABLE Vc_GCC_VERSION)
77 string(REGEX MATCH "[0-9]+\\.[0-9]+\\.[0-9]+" Vc_GCC_VERSION "${Vc_GCC_VERSION}")
78 message(STATUS "GCC Version from --version: ${Vc_GCC_VERSION}")
81 # some distributions patch their GCC to be API incompatible to what the FSF released. In
82 # those cases we require a macro to identify the distribution version
83 find_program(_lsb_release lsb_release)
84 mark_as_advanced(_lsb_release)
86 execute_process(COMMAND ${_lsb_release} -is OUTPUT_VARIABLE _distributor_id OUTPUT_STRIP_TRAILING_WHITESPACE)
87 execute_process(COMMAND ${_lsb_release} -rs OUTPUT_VARIABLE _distributor_release OUTPUT_STRIP_TRAILING_WHITESPACE)
88 string(TOUPPER "${_distributor_id}" _distributor_id)
89 if(_distributor_id STREQUAL "UBUNTU")
90 execute_process(COMMAND ${CMAKE_C_COMPILER} --version OUTPUT_STRIP_TRAILING_WHITESPACE OUTPUT_VARIABLE _gcc_version)
91 string(REGEX MATCH "\\(.* ${Vc_GCC_VERSION}-([0-9]+).*\\)" _tmp "${_gcc_version}")
93 set(_patch ${CMAKE_MATCH_1})
94 string(REGEX MATCH "^([0-9]+)\\.([0-9]+)$" _tmp "${_distributor_release}")
95 execute_process(COMMAND printf 0x%x%02x%02x ${CMAKE_MATCH_1} ${CMAKE_MATCH_2} ${_patch} OUTPUT_STRIP_TRAILING_WHITESPACE OUTPUT_VARIABLE _tmp)
96 set(Vc_DEFINITIONS "${Vc_DEFINITIONS} -D__GNUC_UBUNTU_VERSION__=${_tmp}")
101 message(WARNING "Untested/-supported Compiler for use with Vc.\nPlease fill out the missing parts in the CMake scripts and submit a patch to http://code.compeng.uni-frankfurt.de/projects/vc")
106 macro(vc_set_gnu_buildtype_flags)
107 set(CMAKE_CXX_FLAGS_DEBUG "-g3" CACHE STRING "Flags used by the compiler during debug builds." FORCE)
108 set(CMAKE_CXX_FLAGS_MINSIZEREL "-Os -DNDEBUG" CACHE STRING "Flags used by the compiler during release minsize builds." FORCE)
109 set(CMAKE_CXX_FLAGS_RELEASE "-O3 -DNDEBUG" CACHE STRING "Flags used by the compiler during release builds (/MD /Ob1 /Oi /Ot /Oy /Gs will produce slightly less optimized but smaller files)." FORCE)
110 set(CMAKE_CXX_FLAGS_RELWITHDEBUG "-O3" CACHE STRING "Flags used by the compiler during release builds containing runtime checks." FORCE)
111 set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBUG} -g" CACHE STRING "Flags used by the compiler during Release with Debug Info builds." FORCE)
112 set(CMAKE_C_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}" CACHE STRING "Flags used by the compiler during debug builds." FORCE)
113 set(CMAKE_C_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL}" CACHE STRING "Flags used by the compiler during release minsize builds." FORCE)
114 set(CMAKE_C_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}" CACHE STRING "Flags used by the compiler during release builds (/MD /Ob1 /Oi /Ot /Oy /Gs will produce slightly less optimized but smaller files)." FORCE)
115 set(CMAKE_C_FLAGS_RELWITHDEBUG "${CMAKE_CXX_FLAGS_RELWITHDEBUG}" CACHE STRING "Flags used by the compiler during release builds containing runtime checks." FORCE)
116 set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO}" CACHE STRING "Flags used by the compiler during Release with Debug Info builds." FORCE)
117 if(CMAKE_BUILD_TYPE STREQUAL "Release" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebug")
118 set(ENABLE_STRICT_ALIASING true CACHE BOOL "Enables strict aliasing rules for more aggressive optimizations")
119 if(NOT ENABLE_STRICT_ALIASING)
120 AddCompilerFlag(-fno-strict-aliasing)
121 endif(NOT ENABLE_STRICT_ALIASING)
123 mark_as_advanced(CMAKE_CXX_FLAGS_RELWITHDEBUG CMAKE_C_FLAGS_RELWITHDEBUG)
126 macro(vc_add_compiler_flag VAR _flag)
127 AddCompilerFlag("${_flag}" CXX_FLAGS ${VAR})
130 macro(vc_check_assembler)
132 if(NOT Vc_COMPILER_IS_CLANG)
133 message(WARNING "Apple does not provide an assembler with AVX support. AVX will not be available. Please use Clang if you want to use AVX.")
134 set(Vc_DEFINITIONS "${Vc_DEFINITIONS} -DVC_NO_XGETBV")
135 set(Vc_AVX_INTRINSICS_BROKEN true)
141 exec_program(${CMAKE_CXX_COMPILER} ARGS -print-prog-name=as OUTPUT_VARIABLE _as)
142 mark_as_advanced(_as)
145 message(WARNING "Could not find 'as', the assembler used by GCC. Hoping everything will work out...")
147 exec_program(${_as} ARGS --version OUTPUT_VARIABLE _as_version)
148 string(REGEX REPLACE "\\([^\\)]*\\)" "" _as_version "${_as_version}")
149 string(REGEX MATCH "[1-9]\\.[0-9]+(\\.[0-9]+)?" _as_version "${_as_version}")
150 if(_as_version VERSION_LESS "2.18.93")
151 UserWarning("Your binutils is too old (${_as_version}). Some optimizations of Vc will be disabled.")
152 add_definitions(-DVC_NO_XGETBV) # old assembler doesn't know the xgetbv instruction
153 set(Vc_AVX_INTRINSICS_BROKEN true)
154 set(Vc_XOP_INTRINSICS_BROKEN true)
155 set(Vc_FMA4_INTRINSICS_BROKEN true)
156 elseif(_as_version VERSION_LESS "2.21.0")
157 UserWarning("Your binutils is too old (${_as_version}) for XOP instructions. They will therefore not be provided in libVc.")
158 set(Vc_XOP_INTRINSICS_BROKEN true)
164 macro(vc_check_fpmath)
165 # if compiling for 32 bit x86 we need to use the -mfpmath=sse since the x87 is broken by design
166 include (CheckCXXSourceRuns)
167 check_cxx_source_runs("int main() { return sizeof(void*) != 8; }" Vc_VOID_PTR_IS_64BIT)
168 if(NOT Vc_VOID_PTR_IS_64BIT)
169 exec_program(${CMAKE_C_COMPILER} ARGS -dumpmachine OUTPUT_VARIABLE _gcc_machine)
170 if(_gcc_machine MATCHES "[x34567]86" OR _gcc_machine STREQUAL "mingw32")
171 vc_add_compiler_flag(Vc_DEFINITIONS "-mfpmath=sse")
176 macro(vc_set_preferred_compiler_flags)
177 vc_determine_compiler()
179 set(_add_warning_flags false)
180 set(_add_buildtype_flags false)
181 foreach(_arg ${ARGN})
182 if(_arg STREQUAL "WARNING_FLAGS")
183 set(_add_warning_flags true)
184 elseif(_arg STREQUAL "BUILDTYPE_FLAGS")
185 set(_add_buildtype_flags true)
189 set(Vc_SSE_INTRINSICS_BROKEN false)
190 set(Vc_AVX_INTRINSICS_BROKEN false)
191 set(Vc_XOP_INTRINSICS_BROKEN false)
192 set(Vc_FMA4_INTRINSICS_BROKEN false)
194 if(Vc_COMPILER_IS_OPEN64)
195 ##################################################################################################
197 ##################################################################################################
198 if(_add_warning_flags)
199 AddCompilerFlag("-W")
200 AddCompilerFlag("-Wall")
201 AddCompilerFlag("-Wimplicit")
202 AddCompilerFlag("-Wswitch")
203 AddCompilerFlag("-Wformat")
204 AddCompilerFlag("-Wchar-subscripts")
205 AddCompilerFlag("-Wparentheses")
206 AddCompilerFlag("-Wmultichar")
207 AddCompilerFlag("-Wtrigraphs")
208 AddCompilerFlag("-Wpointer-arith")
209 AddCompilerFlag("-Wcast-align")
210 AddCompilerFlag("-Wreturn-type")
211 AddCompilerFlag("-Wno-unused-function")
212 AddCompilerFlag("-ansi")
213 AddCompilerFlag("-pedantic")
214 AddCompilerFlag("-Wno-long-long")
215 AddCompilerFlag("-Wshadow")
216 AddCompilerFlag("-Wold-style-cast")
217 AddCompilerFlag("-Wno-variadic-macros")
219 if(_add_buildtype_flags)
220 vc_set_gnu_buildtype_flags()
225 # Open64 4.5.1 still doesn't ship immintrin.h
226 set(Vc_AVX_INTRINSICS_BROKEN true)
227 elseif(Vc_COMPILER_IS_GCC)
228 ##################################################################################################
230 ##################################################################################################
231 if(_add_warning_flags)
232 set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -W -Wall -Wswitch -Wformat -Wchar-subscripts -Wparentheses -Wmultichar -Wtrigraphs -Wpointer-arith -Wcast-align -Wreturn-type -Wno-unused-function -pedantic -Wno-long-long -Wshadow")
233 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -W -Wall -Wswitch -Wformat -Wchar-subscripts -Wparentheses -Wmultichar -Wtrigraphs -Wpointer-arith -Wcast-align -Wreturn-type -Wno-unused-function -pedantic -Wno-long-long -Wshadow")
235 # the -ansi flag makes MinGW unusable, so maybe it's better to omit it
236 set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ansi")
237 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ansi")
239 AddCompilerFlag("-Wundef")
240 AddCompilerFlag("-Wold-style-cast")
241 AddCompilerFlag("-Wno-variadic-macros")
242 if(Vc_GCC_VERSION VERSION_GREATER "4.5.2" AND Vc_GCC_VERSION VERSION_LESS "4.6.4")
243 # GCC gives bogus "array subscript is above array bounds" warnings in math.cpp
244 AddCompilerFlag("-Wno-array-bounds")
246 if(Vc_GCC_VERSION VERSION_GREATER "4.7.99")
247 # GCC 4.8 warns about stuff we don't care about
248 # Some older GCC versions have problems to note that they don't support the flag
249 AddCompilerFlag("-Wno-unused-local-typedefs")
252 vc_add_compiler_flag(Vc_DEFINITIONS "-Wabi")
253 vc_add_compiler_flag(Vc_DEFINITIONS "-fabi-version=0") # ABI version 4 is required to make __m128 and __m256 appear as different types. 0 should give us the latest version.
255 if(_add_buildtype_flags)
256 vc_set_gnu_buildtype_flags()
259 # GCC 4.5.[01] fail at inlining some functions, creating functions with a single instructions,
260 # thus creating a large overhead.
261 if(Vc_GCC_VERSION VERSION_LESS "4.5.2" AND NOT Vc_GCC_VERSION VERSION_LESS "4.5.0")
262 UserWarning("GCC 4.5.0 and 4.5.1 have problems with inlining correctly. Setting early-inlining-insns=12 as workaround.")
263 AddCompilerFlag("--param early-inlining-insns=12")
266 if(Vc_GCC_VERSION VERSION_LESS "4.1.99")
267 UserWarning("Your GCC is ancient and crashes on some important optimizations. The full set of SSE2 intrinsics is not supported. Vc will fall back to the scalar implementation. Use of the may_alias and always_inline attributes will be disabled. In turn all code using Vc must be compiled with -fno-strict-aliasing")
268 vc_add_compiler_flag(Vc_DEFINITIONS "-fno-strict-aliasing")
269 set(Vc_AVX_INTRINSICS_BROKEN true)
270 set(Vc_SSE_INTRINSICS_BROKEN true)
271 elseif(Vc_GCC_VERSION VERSION_LESS "4.4.6")
272 UserWarning("Your GCC is older than 4.4.6. This is known to cause problems/bugs. Please update to the latest GCC if you can.")
273 set(Vc_AVX_INTRINSICS_BROKEN true)
274 if(Vc_GCC_VERSION VERSION_LESS "4.3.0")
275 UserWarning("Your GCC is older than 4.3.0. It is unable to handle the full set of SSE2 intrinsics. All SSE code will be disabled. Please update to the latest GCC if you can.")
276 set(Vc_SSE_INTRINSICS_BROKEN true)
280 if(Vc_GCC_VERSION VERSION_LESS 4.5.0)
281 UserWarning("GCC 4.4.x shows false positives for -Wparentheses, thus we rather disable the warning.")
282 string(REPLACE " -Wparentheses " " " CMAKE_C_FLAGS "${CMAKE_C_FLAGS}")
283 string(REPLACE " -Wparentheses " " " CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
284 set(Vc_DEFINITIONS "${Vc_DEFINITIONS} -Wno-parentheses")
286 UserWarning("GCC 4.4.x shows false positives for -Wstrict-aliasing, thus we rather disable the warning. Use a newer GCC for better warnings.")
287 AddCompilerFlag("-Wno-strict-aliasing")
289 UserWarning("GCC 4.4.x shows false positives for -Wuninitialized, thus we rather disable the warning. Use a newer GCC for better warnings.")
290 AddCompilerFlag("-Wno-uninitialized")
291 elseif(Vc_GCC_VERSION VERSION_EQUAL 4.6.0)
292 UserWarning("GCC 4.6.0 miscompiles AVX loads/stores, leading to spurious segfaults. Disabling AVX per default.")
293 set(Vc_AVX_INTRINSICS_BROKEN true)
294 elseif(Vc_GCC_VERSION VERSION_EQUAL 4.7.0)
295 UserWarning("GCC 4.7.0 miscompiles at -O3, adding -fno-predictive-commoning to the compiler flags as workaround")
296 set(Vc_DEFINITIONS "${Vc_DEFINITIONS} -fno-predictive-commoning")
297 elseif(Vc_GCC_VERSION VERSION_EQUAL 4.8.0)
298 UserWarning("GCC 4.8.0 miscompiles at -O3, adding -fno-tree-vectorize to the compiler flags as workaround")
299 set(Vc_DEFINITIONS "${Vc_DEFINITIONS} -fno-tree-vectorize")
304 elseif(Vc_COMPILER_IS_INTEL)
305 ##################################################################################################
307 ##################################################################################################
309 if(_add_buildtype_flags)
310 set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O3")
311 set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -DNDEBUG -O3")
312 set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -O3")
313 set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} -DNDEBUG -O3")
315 set(ALIAS_FLAGS "-no-ansi-alias")
316 if(CMAKE_BUILD_TYPE STREQUAL "Release" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo")
317 # default ICC to -no-ansi-alias because otherwise tests/utils_sse fails. So far I suspect a miscompilation...
318 set(ENABLE_STRICT_ALIASING false CACHE BOOL "Enables strict aliasing rules for more aggressive optimizations")
319 if(ENABLE_STRICT_ALIASING)
320 set(ALIAS_FLAGS "-ansi-alias")
321 endif(ENABLE_STRICT_ALIASING)
323 set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${ALIAS_FLAGS}")
324 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${ALIAS_FLAGS}")
326 vc_add_compiler_flag(Vc_DEFINITIONS "-diag-disable 913")
327 # Disable warning #13211 "Immediate parameter to intrinsic call too large". (sse/vector.tcc rotated(int))
328 vc_add_compiler_flag(Vc_DEFINITIONS "-diag-disable 13211")
330 if(NOT "$ENV{DASHBOARD_TEST_FROM_CTEST}" STREQUAL "")
331 # disable warning #2928: the __GXX_EXPERIMENTAL_CXX0X__ macro is disabled when using GNU version 4.6 with the c++0x option
332 # this warning just adds noise about problems in the compiler - but I'm only interested in seeing problems in Vc
333 vc_add_compiler_flag(Vc_DEFINITIONS "-diag-disable 2928")
336 # Intel doesn't implement the XOP or FMA4 intrinsics
337 set(Vc_XOP_INTRINSICS_BROKEN true)
338 set(Vc_FMA4_INTRINSICS_BROKEN true)
339 elseif(Vc_COMPILER_IS_MSVC)
340 if(_add_warning_flags)
341 AddCompilerFlag("/wd4800") # Disable warning "forcing value to bool"
342 AddCompilerFlag("/wd4996") # Disable warning about strdup vs. _strdup
343 AddCompilerFlag("/wd4244") # Disable warning "conversion from 'unsigned int' to 'float', possible loss of data"
344 AddCompilerFlag("/wd4146") # Disable warning "unary minus operator applied to unsigned type, result still unsigned"
345 AddCompilerFlag("/wd4227") # Disable warning "anachronism used : qualifiers on reference are ignored" (this is about 'restrict' usage on references, stupid MSVC)
346 AddCompilerFlag("/wd4722") # Disable warning "destructor never returns, potential memory leak" (warns about ~_UnitTest_Global_Object which we don't care about)
347 AddCompilerFlag("/wd4748") # Disable warning "/GS can not protect parameters and local variables from local buffer overrun because optimizations are disabled in function" (I don't get it)
348 add_definitions(-D_CRT_SECURE_NO_WARNINGS)
351 # MSVC does not support inline assembly on 64 bit! :(
352 # searching the help for xgetbv doesn't turn up anything. So just fall back to not supporting AVX on Windows :(
353 # TODO: apparently MSVC 2010 SP1 added _xgetbv
354 set(Vc_DEFINITIONS "${Vc_DEFINITIONS} -DVC_NO_XGETBV")
356 # get rid of the min/max macros
357 set(Vc_DEFINITIONS "${Vc_DEFINITIONS} -DNOMINMAX")
359 # MSVC doesn't implement the XOP or FMA4 intrinsics
360 set(Vc_XOP_INTRINSICS_BROKEN true)
361 set(Vc_FMA4_INTRINSICS_BROKEN true)
363 if(MSVC_VERSION LESS 1700)
364 UserWarning("MSVC before 2012 has a broken std::vector::resize implementation. STL + Vc code will probably not compile.")
366 elseif(Vc_COMPILER_IS_CLANG)
367 # for now I don't know of any arguments I want to pass. -march and stuff is tried by OptimizeForArchitecture...
368 if(Vc_CLANG_VERSION VERSION_EQUAL "3.0")
369 UserWarning("Clang 3.0 has serious issues to compile Vc code and will most likely crash when trying to do so.\nPlease update to a recent clang version.")
370 elseif(Vc_CLANG_VERSION VERSION_LESS "3.3")
371 # the LLVM assembler gets FMAs wrong (bug 15040)
372 vc_add_compiler_flag(Vc_DEFINITIONS "-no-integrated-as")
375 # disable these warnings because clang shows them for function overloads that were discarded via SFINAE
376 vc_add_compiler_flag(Vc_DEFINITIONS "-Wno-local-type-template-args")
377 vc_add_compiler_flag(Vc_DEFINITIONS "-Wno-unnamed-type-template-args")
379 AddCompilerFlag(-stdlib=libc++)
382 if(NOT Vc_COMPILER_IS_MSVC)
383 vc_add_compiler_flag(Vc_DEFINITIONS "-ffp-contract=fast")
386 OptimizeForArchitecture()
387 set(Vc_DEFINITIONS "${Vc_ARCHITECTURE_FLAGS} ${Vc_DEFINITIONS}")
389 set(VC_IMPL "auto" CACHE STRING "Force the Vc implementation globally to the selected instruction set. \"auto\" lets Vc use the best available instructions.")
390 if(NOT VC_IMPL STREQUAL "auto")
391 set(Vc_DEFINITIONS "${Vc_DEFINITIONS} -DVC_IMPL=${VC_IMPL}")
392 if(NOT VC_IMPL STREQUAL "Scalar")
393 set(_use_var "USE_${VC_IMPL}")
394 if(VC_IMPL STREQUAL "SSE")
395 set(_use_var "USE_SSE2")
398 message(WARNING "The selected value for VC_IMPL (${VC_IMPL}) will not work because the relevant instructions are not enabled via compiler flags.")
404 # helper macro for vc_compile_for_all_implementations
405 macro(_vc_compile_one_implementation _objs _impl)
406 list(FIND _disabled_targets "${_impl}" _disabled_index)
407 list(FIND _only_targets "${_impl}" _only_index)
408 if(${_disabled_index} EQUAL -1 AND (NOT _only_targets OR ${_only_index} GREATER -1))
411 foreach(_flag ${ARGN})
412 if(_flag STREQUAL "NO_FLAG")
416 string(REPLACE " " ";" _flag_list "${_flag}")
417 foreach(_flag ${_flag_list})
418 AddCompilerFlag(${_flag} CXX_RESULT _ok)
424 set(_extra_flags ${_flag_list})
429 set(_outfile_flag -c -o)
430 if(Vc_COMPILER_IS_MSVC)
431 # MSVC for 64bit does not recognize /arch:SSE2 anymore. Therefore we set override _ok if _impl
433 if("${_impl}" MATCHES "SSE")
436 set(_outfile_flag /c /Fo)
440 get_filename_component(_out "${_vc_compile_src}" NAME_WE)
441 get_filename_component(_ext "${_vc_compile_src}" EXT)
442 if(Vc_COMPILER_IS_MSVC)
443 set(_out "${_out}_${_impl}${_ext}.obj")
445 set(_out "${_out}_${_impl}${_ext}.o")
447 add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${_out}
448 COMMAND ${CMAKE_CXX_COMPILER} ${_flags} ${_extra_flags}
450 ${_outfile_flag}${_out} ${CMAKE_CURRENT_SOURCE_DIR}/${_vc_compile_src}
451 MAIN_DEPENDENCY ${CMAKE_CURRENT_SOURCE_DIR}/${_vc_compile_src}
452 IMPLICIT_DEPENDS CXX ${CMAKE_CURRENT_SOURCE_DIR}/${_vc_compile_src}
453 COMMENT "Building CXX object ${_out}"
454 WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
457 list(APPEND ${_objs} "${CMAKE_CURRENT_BINARY_DIR}/${_out}")
462 # Generate compile rules for the given C++ source file for all available implementations and return
463 # the resulting list of object files in _obj
464 # all remaining arguments are additional flags
466 # vc_compile_for_all_implementations(_objs src/trigonometric.cpp FLAGS -DCOMPILE_BLAH EXCLUDE Scalar)
467 # add_executable(executable main.cpp ${_objs})
468 macro(vc_compile_for_all_implementations _objs _src)
471 # remove all -march, -msse, etc. flags from the flags we want to pass
472 string(REPLACE "${Vc_ARCHITECTURE_FLAGS}" "" _flags "${Vc_DEFINITIONS}")
473 string(REPLACE "-DVC_IMPL=[^ ]*" "" _flags "${_flags}")
475 # capture the -march= switch as -mtune; if there is none skip it
476 if(Vc_ARCHITECTURE_FLAGS MATCHES "-march=")
477 string(REGEX REPLACE "^.*-march=([^ ]*).*$" "-mtune=\\1" _tmp "${Vc_ARCHITECTURE_FLAGS}")
478 set(_flags "${_flags} ${_tmp}")
481 unset(_disabled_targets)
484 foreach(_arg ${ARGN})
485 if(_arg STREQUAL "FLAGS")
487 elseif(_arg STREQUAL "EXCLUDE")
489 elseif(_arg STREQUAL "ONLY")
491 elseif(_state EQUAL 1)
492 set(_flags "${_flags} ${_arg}")
493 elseif(_state EQUAL 2)
494 list(APPEND _disabled_targets "${_arg}")
495 elseif(_state EQUAL 3)
496 list(APPEND _only_targets "${_arg}")
498 message(FATAL_ERROR "incorrect argument to vc_compile_for_all_implementations")
502 # make a semicolon separated list of all flags
503 string(TOUPPER "${CMAKE_BUILD_TYPE}" _tmp)
504 set(_tmp "CMAKE_CXX_FLAGS_${_tmp}")
505 string(REPLACE " " ";" _tmp "${CMAKE_CXX_FLAGS} ${${_tmp}} ${_flags}")
507 foreach(item ${_tmp})
508 if(item MATCHES "^[^']*'[^']*$")
510 list(APPEND _flags "${_str} ${item}")
516 list(APPEND _flags "${item}")
519 get_directory_property(_inc INCLUDE_DIRECTORIES)
521 list(APPEND _flags "-I${_i}")
524 set(_vc_compile_src "${_src}")
526 _vc_compile_one_implementation(${_objs} Scalar NO_FLAG)
527 if(NOT Vc_SSE_INTRINSICS_BROKEN)
528 _vc_compile_one_implementation(${_objs} SSE2 "-msse2" "-xSSE2" "/arch:SSE2")
529 _vc_compile_one_implementation(${_objs} SSE3 "-msse3" "-xSSE3" "/arch:SSE2")
530 _vc_compile_one_implementation(${_objs} SSSE3 "-mssse3" "-xSSSE3" "/arch:SSE2")
531 _vc_compile_one_implementation(${_objs} SSE4_1 "-msse4.1" "-xSSE4.1" "/arch:SSE2")
532 _vc_compile_one_implementation(${_objs} SSE4_2 "-msse4.2" "-xSSE4.2" "/arch:SSE2")
533 _vc_compile_one_implementation(${_objs} SSE3+SSE4a "-msse4a")
535 if(NOT Vc_AVX_INTRINSICS_BROKEN)
536 _vc_compile_one_implementation(${_objs} AVX "-mavx" "-xAVX" "/arch:AVX")
537 if(NOT Vc_XOP_INTRINSICS_BROKEN)
538 if(NOT Vc_FMA4_INTRINSICS_BROKEN)
539 _vc_compile_one_implementation(${_objs} SSE+XOP+FMA4 "-mxop -mfma4" "" "")
540 _vc_compile_one_implementation(${_objs} AVX+XOP+FMA4 "-mavx -mxop -mfma4" "" "")
542 _vc_compile_one_implementation(${_objs} SSE+XOP+FMA "-mxop -mfma" "" "")
543 _vc_compile_one_implementation(${_objs} AVX+XOP+FMA "-mavx -mxop -mfma" "" "")
545 _vc_compile_one_implementation(${_objs} AVX+FMA "-mavx -mfma" "" "")