]> git.uio.no Git - u/mrichter/AliRoot.git/blob - Vc/cmake/VcMacros.cmake
added slewing correction by data
[u/mrichter/AliRoot.git] / Vc / cmake / VcMacros.cmake
1 # Macros for use with the Vc library. Vc can be found at http://code.compeng.uni-frankfurt.de/projects/vc
2 #
3 # The following macros are provided:
4 # vc_determine_compiler
5 # vc_set_preferred_compiler_flags
6 #
7 #=============================================================================
8 # Copyright 2009-2013   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 #  * 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.
25 #
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 #=============================================================================
37
38 cmake_minimum_required(VERSION 2.8.3)
39
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")
44
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}")
65       elseif(MSVC)
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}")
72
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}")
79          endif()
80
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)
85          if(_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}")
92                if(_tmp)
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}")
97                endif()
98             endif()
99          endif()
100       else()
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")
102       endif()
103    endif()
104 endmacro()
105
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)
122    endif()
123    mark_as_advanced(CMAKE_CXX_FLAGS_RELWITHDEBUG CMAKE_C_FLAGS_RELWITHDEBUG)
124 endmacro()
125
126 macro(vc_add_compiler_flag VAR _flag)
127    AddCompilerFlag("${_flag}" CXX_FLAGS ${VAR})
128 endmacro()
129
130 macro(vc_check_assembler)
131    if(APPLE)
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)
136       endif()
137    else(APPLE)
138       if(${ARGC} EQUAL 1)
139          set(_as "${ARGV1}")
140       else()
141          exec_program(${CMAKE_CXX_COMPILER} ARGS -print-prog-name=as OUTPUT_VARIABLE _as)
142          mark_as_advanced(_as)
143       endif()
144       if(NOT _as)
145          message(WARNING "Could not find 'as', the assembler used by GCC. Hoping everything will work out...")
146       else()
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)
159          endif()
160       endif()
161    endif(APPLE)
162 endmacro()
163
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")
172       endif()
173    endif()
174 endmacro()
175
176 macro(vc_set_preferred_compiler_flags)
177    vc_determine_compiler()
178
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)
186       endif()
187    endforeach()
188
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)
193
194    if(Vc_COMPILER_IS_OPEN64)
195       ##################################################################################################
196       #                                             Open64                                             #
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")
218       endif()
219       if(_add_buildtype_flags)
220          vc_set_gnu_buildtype_flags()
221       endif()
222
223       vc_check_assembler()
224
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       ##################################################################################################
229       #                                              GCC                                               #
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")
234          if(NOT WIN32)
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")
238          endif()
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")
245          endif()
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")
250          endif()
251       endif()
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.
254
255       if(_add_buildtype_flags)
256          vc_set_gnu_buildtype_flags()
257       endif()
258
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")
264       endif()
265
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)
277          endif()
278       endif()
279
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")
285
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")
288
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")
300       endif()
301
302       vc_check_fpmath()
303       vc_check_assembler()
304    elseif(Vc_COMPILER_IS_INTEL)
305       ##################################################################################################
306       #                                          Intel Compiler                                        #
307       ##################################################################################################
308
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")
314
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)
322          endif()
323          set(CMAKE_C_FLAGS   "${CMAKE_C_FLAGS}   ${ALIAS_FLAGS}")
324          set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${ALIAS_FLAGS}")
325       endif()
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")
329
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")
334       endif()
335
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)
349       endif()
350
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")
355
356       # get rid of the min/max macros
357       set(Vc_DEFINITIONS "${Vc_DEFINITIONS} -DNOMINMAX")
358
359       # MSVC doesn't implement the XOP or FMA4 intrinsics
360       set(Vc_XOP_INTRINSICS_BROKEN true)
361       set(Vc_FMA4_INTRINSICS_BROKEN true)
362
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.")
365       endif()
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")
373       endif()
374
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")
378
379       AddCompilerFlag(-stdlib=libc++)
380    endif()
381
382    if(NOT Vc_COMPILER_IS_MSVC)
383      if(NOT Vc_COMPILER_IS_INTEL)
384        vc_add_compiler_flag(Vc_DEFINITIONS "-ffp-contract=fast")
385      endif()
386    endif()
387
388    OptimizeForArchitecture()
389    set(Vc_DEFINITIONS "${Vc_ARCHITECTURE_FLAGS} ${Vc_DEFINITIONS}")
390
391    set(VC_IMPL "auto" CACHE STRING "Force the Vc implementation globally to the selected instruction set. \"auto\" lets Vc use the best available instructions.")
392    if(NOT VC_IMPL STREQUAL "auto")
393       set(Vc_DEFINITIONS "${Vc_DEFINITIONS} -DVC_IMPL=${VC_IMPL}")
394       if(NOT VC_IMPL STREQUAL "Scalar")
395          set(_use_var "USE_${VC_IMPL}")
396          if(VC_IMPL STREQUAL "SSE")
397             set(_use_var "USE_SSE2")
398          endif()
399          if(NOT ${_use_var})
400             message(WARNING "The selected value for VC_IMPL (${VC_IMPL}) will not work because the relevant instructions are not enabled via compiler flags.")
401          endif()
402       endif()
403    endif()
404 endmacro()
405
406 # helper macro for vc_compile_for_all_implementations
407 macro(_vc_compile_one_implementation _objs _impl)
408    list(FIND _disabled_targets "${_impl}" _disabled_index)
409    list(FIND _only_targets "${_impl}" _only_index)
410    if(${_disabled_index} EQUAL -1 AND (NOT _only_targets OR ${_only_index} GREATER -1))
411       set(_extra_flags)
412       set(_ok FALSE)
413       foreach(_flag ${ARGN})
414          if(_flag STREQUAL "NO_FLAG")
415             set(_ok TRUE)
416             break()
417          endif()
418          string(REPLACE " " ";" _flag_list "${_flag}")
419          foreach(_flag ${_flag_list})
420             AddCompilerFlag(${_flag} CXX_RESULT _ok)
421             if(NOT _ok)
422                break()
423             endif()
424          endforeach()
425          if(_ok)
426             set(_extra_flags ${_flag_list})
427             break()
428          endif()
429       endforeach()
430
431       set(_outfile_flag -c -o)
432       if(Vc_COMPILER_IS_MSVC)
433          # MSVC for 64bit does not recognize /arch:SSE2 anymore. Therefore we set override _ok if _impl
434          # says SSE
435          if("${_impl}" MATCHES "SSE")
436             set(_ok TRUE)
437          endif()
438          set(_outfile_flag /c /Fo)
439       endif()
440
441       if(_ok)
442          get_filename_component(_out "${_vc_compile_src}" NAME_WE)
443          get_filename_component(_ext "${_vc_compile_src}" EXT)
444          if(Vc_COMPILER_IS_MSVC)
445             set(_out "${_out}_${_impl}${_ext}.obj")
446          else()
447             set(_out "${_out}_${_impl}${_ext}.o")
448          endif()
449          add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${_out}
450             COMMAND ${CMAKE_CXX_COMPILER} ${_flags} ${_extra_flags}
451             -DVC_IMPL=${_impl}
452             ${_outfile_flag}${_out} ${CMAKE_CURRENT_SOURCE_DIR}/${_vc_compile_src}
453             MAIN_DEPENDENCY ${CMAKE_CURRENT_SOURCE_DIR}/${_vc_compile_src}
454             IMPLICIT_DEPENDS CXX ${CMAKE_CURRENT_SOURCE_DIR}/${_vc_compile_src}
455             COMMENT "Building CXX object ${_out}"
456             WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
457             VERBATIM
458             )
459          list(APPEND ${_objs} "${CMAKE_CURRENT_BINARY_DIR}/${_out}")
460       endif()
461    endif()
462 endmacro()
463
464 # Generate compile rules for the given C++ source file for all available implementations and return
465 # the resulting list of object files in _obj
466 # all remaining arguments are additional flags
467 # Example:
468 #   vc_compile_for_all_implementations(_objs src/trigonometric.cpp FLAGS -DCOMPILE_BLAH EXCLUDE Scalar)
469 #   add_executable(executable main.cpp ${_objs})
470 macro(vc_compile_for_all_implementations _objs _src)
471    set(${_objs})
472
473    # remove all -march, -msse, etc. flags from the flags we want to pass
474    string(REPLACE "${Vc_ARCHITECTURE_FLAGS}" "" _flags "${Vc_DEFINITIONS}")
475    string(REPLACE "-DVC_IMPL=[^ ]*" "" _flags "${_flags}")
476
477    # capture the -march= switch as -mtune; if there is none skip it
478    if(Vc_ARCHITECTURE_FLAGS MATCHES "-march=")
479       string(REGEX REPLACE "^.*-march=([^ ]*).*$" "-mtune=\\1" _tmp "${Vc_ARCHITECTURE_FLAGS}")
480       set(_flags "${_flags} ${_tmp}")
481    endif()
482
483    unset(_disabled_targets)
484    unset(_only_targets)
485    set(_state 0)
486    foreach(_arg ${ARGN})
487       if(_arg STREQUAL "FLAGS")
488          set(_state 1)
489       elseif(_arg STREQUAL "EXCLUDE")
490          set(_state 2)
491       elseif(_arg STREQUAL "ONLY")
492          set(_state 3)
493       elseif(_state EQUAL 1)
494          set(_flags "${_flags} ${_arg}")
495       elseif(_state EQUAL 2)
496          list(APPEND _disabled_targets "${_arg}")
497       elseif(_state EQUAL 3)
498          list(APPEND _only_targets "${_arg}")
499       else()
500          message(FATAL_ERROR "incorrect argument to vc_compile_for_all_implementations")
501       endif()
502    endforeach()
503
504    # make a semicolon separated list of all flags
505    string(TOUPPER "${CMAKE_BUILD_TYPE}" _tmp)
506    set(_tmp "CMAKE_CXX_FLAGS_${_tmp}")
507    string(REPLACE " " ";" _tmp "${CMAKE_CXX_FLAGS} ${${_tmp}} ${_flags}")
508    set(_flags)
509    foreach(item ${_tmp})
510       if(item MATCHES "^[^']*'[^']*$")
511          if(_str)
512             list(APPEND _flags "${_str} ${item}")
513             unset(_str)
514          else()
515             set(_str "${item}")
516          endif()
517       else()
518          list(APPEND _flags "${item}")
519       endif()
520    endforeach()
521    get_directory_property(_inc INCLUDE_DIRECTORIES)
522    foreach(_i ${_inc})
523       list(APPEND _flags "-I${_i}")
524    endforeach()
525
526    set(_vc_compile_src "${_src}")
527
528    _vc_compile_one_implementation(${_objs} Scalar NO_FLAG)
529    if(NOT Vc_SSE_INTRINSICS_BROKEN)
530       _vc_compile_one_implementation(${_objs} SSE2   "-msse2"   "-xSSE2"   "/arch:SSE2")
531       _vc_compile_one_implementation(${_objs} SSE3   "-msse3"   "-xSSE3"   "/arch:SSE2")
532       _vc_compile_one_implementation(${_objs} SSSE3  "-mssse3"  "-xSSSE3"  "/arch:SSE2")
533       _vc_compile_one_implementation(${_objs} SSE4_1 "-msse4.1" "-xSSE4.1" "/arch:SSE2")
534       _vc_compile_one_implementation(${_objs} SSE4_2 "-msse4.2" "-xSSE4.2" "/arch:SSE2")
535       _vc_compile_one_implementation(${_objs} SSE3+SSE4a  "-msse4a")
536    endif()
537    if(NOT Vc_AVX_INTRINSICS_BROKEN)
538       _vc_compile_one_implementation(${_objs} AVX      "-mavx"    "-xAVX"    "/arch:AVX")
539       if(NOT Vc_XOP_INTRINSICS_BROKEN)
540          if(NOT Vc_FMA4_INTRINSICS_BROKEN)
541            if (NOT Vc_COMPILER_IS_INTEL)
542              _vc_compile_one_implementation(${_objs} SSE+XOP+FMA4 "-mxop -mfma4"        ""    "")
543              _vc_compile_one_implementation(${_objs} AVX+XOP+FMA4 "-mavx -mxop -mfma4"  ""    "")
544           endif()
545          endif()
546          _vc_compile_one_implementation(${_objs} SSE+XOP+FMA "-mxop -mfma"        ""    "")
547          _vc_compile_one_implementation(${_objs} AVX+XOP+FMA "-mavx -mxop -mfma"  ""    "")
548       endif()
549       _vc_compile_one_implementation(${_objs} AVX+FMA "-mavx -mfma"  ""    "")
550    endif()
551 endmacro()