]> git.uio.no Git - u/mrichter/AliRoot.git/blob - Vc/cmake/VcMacros.cmake
update to Vc 0.7.3-dev
[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       vc_add_compiler_flag(Vc_DEFINITIONS "-ffp-contract=fast")
384    endif()
385
386    OptimizeForArchitecture()
387    set(Vc_DEFINITIONS "${Vc_ARCHITECTURE_FLAGS} ${Vc_DEFINITIONS}")
388
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")
396          endif()
397          if(NOT ${_use_var})
398             message(WARNING "The selected value for VC_IMPL (${VC_IMPL}) will not work because the relevant instructions are not enabled via compiler flags.")
399          endif()
400       endif()
401    endif()
402 endmacro()
403
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))
409       set(_extra_flags)
410       set(_ok FALSE)
411       foreach(_flag ${ARGN})
412          if(_flag STREQUAL "NO_FLAG")
413             set(_ok TRUE)
414             break()
415          endif()
416          string(REPLACE " " ";" _flag_list "${_flag}")
417          foreach(_flag ${_flag_list})
418             AddCompilerFlag(${_flag} CXX_RESULT _ok)
419             if(NOT _ok)
420                break()
421             endif()
422          endforeach()
423          if(_ok)
424             set(_extra_flags ${_flag_list})
425             break()
426          endif()
427       endforeach()
428
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
432          # says SSE
433          if("${_impl}" MATCHES "SSE")
434             set(_ok TRUE)
435          endif()
436          set(_outfile_flag /c /Fo)
437       endif()
438
439       if(_ok)
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")
444          else()
445             set(_out "${_out}_${_impl}${_ext}.o")
446          endif()
447          add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${_out}
448             COMMAND ${CMAKE_CXX_COMPILER} ${_flags} ${_extra_flags}
449             -DVC_IMPL=${_impl}
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}"
455             VERBATIM
456             )
457          list(APPEND ${_objs} "${CMAKE_CURRENT_BINARY_DIR}/${_out}")
458       endif()
459    endif()
460 endmacro()
461
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
465 # Example:
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)
469    set(${_objs})
470
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}")
474
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}")
479    endif()
480
481    unset(_disabled_targets)
482    unset(_only_targets)
483    set(_state 0)
484    foreach(_arg ${ARGN})
485       if(_arg STREQUAL "FLAGS")
486          set(_state 1)
487       elseif(_arg STREQUAL "EXCLUDE")
488          set(_state 2)
489       elseif(_arg STREQUAL "ONLY")
490          set(_state 3)
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}")
497       else()
498          message(FATAL_ERROR "incorrect argument to vc_compile_for_all_implementations")
499       endif()
500    endforeach()
501
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}")
506    set(_flags)
507    foreach(item ${_tmp})
508       if(item MATCHES "^[^']*'[^']*$")
509          if(_str)
510             list(APPEND _flags "${_str} ${item}")
511             unset(_str)
512          else()
513             set(_str "${item}")
514          endif()
515       else()
516          list(APPEND _flags "${item}")
517       endif()
518    endforeach()
519    get_directory_property(_inc INCLUDE_DIRECTORIES)
520    foreach(_i ${_inc})
521       list(APPEND _flags "-I${_i}")
522    endforeach()
523
524    set(_vc_compile_src "${_src}")
525
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")
534    endif()
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"  ""    "")
541          endif()
542          _vc_compile_one_implementation(${_objs} SSE+XOP+FMA "-mxop -mfma"        ""    "")
543          _vc_compile_one_implementation(${_objs} AVX+XOP+FMA "-mavx -mxop -mfma"  ""    "")
544       endif()
545       _vc_compile_one_implementation(${_objs} AVX+FMA "-mavx -mfma"  ""    "")
546    endif()
547 endmacro()