]> git.uio.no Git - u/mrichter/AliRoot.git/blob - Vc/cmake/VcMacros.cmake
Merge branch 'master' of https://git.cern.ch/reps/AliRoot
[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("-ansi")
212          AddCompilerFlag("-pedantic")
213          AddCompilerFlag("-Wno-long-long")
214          AddCompilerFlag("-Wshadow")
215          AddCompilerFlag("-Wold-style-cast")
216          AddCompilerFlag("-Wno-variadic-macros")
217       endif()
218       if(_add_buildtype_flags)
219          vc_set_gnu_buildtype_flags()
220       endif()
221
222       vc_check_assembler()
223
224       # Open64 4.5.1 still doesn't ship immintrin.h
225       set(Vc_AVX_INTRINSICS_BROKEN true)
226    elseif(Vc_COMPILER_IS_GCC)
227       ##################################################################################################
228       #                                              GCC                                               #
229       ##################################################################################################
230       if(_add_warning_flags)
231          set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -W -Wall -Wswitch -Wformat -Wchar-subscripts -Wparentheses -Wmultichar -Wtrigraphs -Wpointer-arith -Wcast-align -Wreturn-type -pedantic -Wno-long-long -Wshadow")
232          set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -W -Wall -Wswitch -Wformat -Wchar-subscripts -Wparentheses -Wmultichar -Wtrigraphs -Wpointer-arith -Wcast-align -Wreturn-type -pedantic -Wno-long-long -Wshadow")
233          if(NOT WIN32)
234             # the -ansi flag makes MinGW unusable, so maybe it's better to omit it
235             set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ansi")
236             set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ansi")
237          endif()
238          AddCompilerFlag("-Wundef")
239          AddCompilerFlag("-Wold-style-cast")
240          AddCompilerFlag("-Wno-variadic-macros")
241          if(Vc_GCC_VERSION VERSION_GREATER "4.5.2" AND Vc_GCC_VERSION VERSION_LESS "4.6.4")
242             # GCC gives bogus "array subscript is above array bounds" warnings in math.cpp
243             AddCompilerFlag("-Wno-array-bounds")
244          endif()
245       endif()
246       vc_add_compiler_flag(Vc_DEFINITIONS "-Wabi")
247       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.
248
249       if(_add_buildtype_flags)
250          vc_set_gnu_buildtype_flags()
251       endif()
252
253       # GCC 4.5.[01] fail at inlining some functions, creating functions with a single instructions,
254       # thus creating a large overhead.
255       if(Vc_GCC_VERSION VERSION_LESS "4.5.2" AND NOT Vc_GCC_VERSION VERSION_LESS "4.5.0")
256          UserWarning("GCC 4.5.0 and 4.5.1 have problems with inlining correctly. Setting early-inlining-insns=12 as workaround.")
257          AddCompilerFlag("--param early-inlining-insns=12")
258       endif()
259
260       if(Vc_GCC_VERSION VERSION_LESS "4.1.99")
261          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")
262          vc_add_compiler_flag(Vc_DEFINITIONS "-fno-strict-aliasing")
263          set(Vc_AVX_INTRINSICS_BROKEN true)
264          set(Vc_SSE_INTRINSICS_BROKEN true)
265       elseif(Vc_GCC_VERSION VERSION_LESS "4.4.6")
266          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.")
267          set(Vc_AVX_INTRINSICS_BROKEN true)
268          if(Vc_GCC_VERSION VERSION_LESS "4.3.0")
269             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.")
270             set(Vc_SSE_INTRINSICS_BROKEN true)
271          endif()
272       endif()
273
274       if(Vc_GCC_VERSION VERSION_LESS 4.5.0)
275          UserWarning("GCC 4.4.x shows false positives for -Wparentheses, thus we rather disable the warning.")
276          string(REPLACE " -Wparentheses " " " CMAKE_C_FLAGS "${CMAKE_C_FLAGS}")
277          string(REPLACE " -Wparentheses " " " CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
278          set(Vc_DEFINITIONS "${Vc_DEFINITIONS} -Wno-parentheses")
279
280          UserWarning("GCC 4.4.x shows false positives for -Wstrict-aliasing, thus we rather disable the warning. Use a newer GCC for better warnings.")
281          AddCompilerFlag("-Wno-strict-aliasing")
282
283          UserWarning("GCC 4.4.x shows false positives for -Wuninitialized, thus we rather disable the warning. Use a newer GCC for better warnings.")
284          AddCompilerFlag("-Wno-uninitialized")
285       elseif(Vc_GCC_VERSION VERSION_EQUAL 4.6.0)
286          UserWarning("GCC 4.6.0 miscompiles AVX loads/stores, leading to spurious segfaults. Disabling AVX per default.")
287          set(Vc_AVX_INTRINSICS_BROKEN true)
288       elseif(Vc_GCC_VERSION VERSION_EQUAL 4.7.0)
289          UserWarning("GCC 4.7.0 miscompiles at -O3, adding -fno-predictive-commoning to the compiler flags as workaround")
290          set(Vc_DEFINITIONS "${Vc_DEFINITIONS} -fno-predictive-commoning")
291       elseif(Vc_GCC_VERSION VERSION_EQUAL 4.8.0)
292          UserWarning("GCC 4.8.0 miscompiles at -O3, adding -fno-tree-vectorize to the compiler flags as workaround")
293          set(Vc_DEFINITIONS "${Vc_DEFINITIONS} -fno-tree-vectorize")
294       endif()
295
296       vc_check_fpmath()
297       vc_check_assembler()
298    elseif(Vc_COMPILER_IS_INTEL)
299       ##################################################################################################
300       #                                          Intel Compiler                                        #
301       ##################################################################################################
302
303       if(_add_buildtype_flags)
304          set(CMAKE_CXX_FLAGS_RELEASE        "${CMAKE_CXX_FLAGS_RELEASE} -O3")
305          set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -DNDEBUG -O3")
306          set(CMAKE_C_FLAGS_RELEASE          "${CMAKE_C_FLAGS_RELEASE} -O3")
307          set(CMAKE_C_FLAGS_RELWITHDEBINFO   "${CMAKE_C_FLAGS_RELWITHDEBINFO} -DNDEBUG -O3")
308
309          set(ALIAS_FLAGS "-no-ansi-alias")
310          if(CMAKE_BUILD_TYPE STREQUAL "Release" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo")
311             # default ICC to -no-ansi-alias because otherwise tests/utils_sse fails. So far I suspect a miscompilation...
312             set(ENABLE_STRICT_ALIASING false CACHE BOOL "Enables strict aliasing rules for more aggressive optimizations")
313             if(ENABLE_STRICT_ALIASING)
314                set(ALIAS_FLAGS "-ansi-alias")
315             endif(ENABLE_STRICT_ALIASING)
316          endif()
317          set(CMAKE_C_FLAGS   "${CMAKE_C_FLAGS}   ${ALIAS_FLAGS}")
318          set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${ALIAS_FLAGS}")
319       endif()
320       vc_add_compiler_flag(Vc_DEFINITIONS "-diag-disable 913")
321       # Disable warning #13211 "Immediate parameter to intrinsic call too large". (sse/vector.tcc rotated(int))
322       vc_add_compiler_flag(Vc_DEFINITIONS "-diag-disable 13211")
323
324       if(NOT "$ENV{DASHBOARD_TEST_FROM_CTEST}" STREQUAL "")
325          # disable warning #2928: the __GXX_EXPERIMENTAL_CXX0X__ macro is disabled when using GNU version 4.6 with the c++0x option
326          # this warning just adds noise about problems in the compiler - but I'm only interested in seeing problems in Vc
327          vc_add_compiler_flag(Vc_DEFINITIONS "-diag-disable 2928")
328       endif()
329
330       # Intel doesn't implement the XOP or FMA4 intrinsics
331       set(Vc_XOP_INTRINSICS_BROKEN true)
332       set(Vc_FMA4_INTRINSICS_BROKEN true)
333    elseif(Vc_COMPILER_IS_MSVC)
334       if(_add_warning_flags)
335          AddCompilerFlag("/wd4800") # Disable warning "forcing value to bool"
336          AddCompilerFlag("/wd4996") # Disable warning about strdup vs. _strdup
337          AddCompilerFlag("/wd4244") # Disable warning "conversion from 'unsigned int' to 'float', possible loss of data"
338          AddCompilerFlag("/wd4146") # Disable warning "unary minus operator applied to unsigned type, result still unsigned"
339          AddCompilerFlag("/wd4227") # Disable warning "anachronism used : qualifiers on reference are ignored" (this is about 'restrict' usage on references, stupid MSVC)
340          AddCompilerFlag("/wd4722") # Disable warning "destructor never returns, potential memory leak" (warns about ~_UnitTest_Global_Object which we don't care about)
341          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)
342          add_definitions(-D_CRT_SECURE_NO_WARNINGS)
343       endif()
344
345       # MSVC does not support inline assembly on 64 bit! :(
346       # searching the help for xgetbv doesn't turn up anything. So just fall back to not supporting AVX on Windows :(
347       # TODO: apparently MSVC 2010 SP1 added _xgetbv
348       set(Vc_DEFINITIONS "${Vc_DEFINITIONS} -DVC_NO_XGETBV")
349
350       # get rid of the min/max macros
351       set(Vc_DEFINITIONS "${Vc_DEFINITIONS} -DNOMINMAX")
352
353       # MSVC doesn't implement the XOP or FMA4 intrinsics
354       set(Vc_XOP_INTRINSICS_BROKEN true)
355       set(Vc_FMA4_INTRINSICS_BROKEN true)
356
357       if(MSVC_VERSION LESS 1700)
358          UserWarning("MSVC before 2012 has a broken std::vector::resize implementation. STL + Vc code will probably not compile.")
359       endif()
360    elseif(Vc_COMPILER_IS_CLANG)
361       # for now I don't know of any arguments I want to pass. -march and stuff is tried by OptimizeForArchitecture...
362       if(Vc_CLANG_VERSION VERSION_EQUAL "3.0")
363          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.")
364       elseif(Vc_CLANG_VERSION VERSION_EQUAL "3.2" AND NOT APPLE)
365          # the LLVM assembler gets FMAs wrong (bug 15040)
366          vc_add_compiler_flag(Vc_DEFINITIONS "-no-integrated-as")
367       endif()
368
369       # disable these warnings because clang shows them for function overloads that were discarded via SFINAE
370       vc_add_compiler_flag(Vc_DEFINITIONS "-Wno-local-type-template-args")
371       vc_add_compiler_flag(Vc_DEFINITIONS "-Wno-unnamed-type-template-args")
372
373       if(NOT DEFINED Vc_INSIDE_ROOT)  # ROOT has to set this up
374          AddCompilerFlag(-stdlib=libc++)
375       endif()
376    endif()
377
378    if(NOT Vc_COMPILER_IS_MSVC AND NOT Vc_COMPILER_IS_INTEL)
379       vc_add_compiler_flag(Vc_DEFINITIONS "-ffp-contract=fast")
380    endif()
381
382    OptimizeForArchitecture()
383    set(Vc_DEFINITIONS "${Vc_ARCHITECTURE_FLAGS} ${Vc_DEFINITIONS}")
384
385    set(VC_IMPL "auto" CACHE STRING "Force the Vc implementation globally to the selected instruction set. \"auto\" lets Vc use the best available instructions.")
386    if(NOT VC_IMPL STREQUAL "auto")
387       set(Vc_DEFINITIONS "${Vc_DEFINITIONS} -DVC_IMPL=${VC_IMPL}")
388       if(NOT VC_IMPL STREQUAL "Scalar")
389          set(_use_var "USE_${VC_IMPL}")
390          if(VC_IMPL STREQUAL "SSE")
391             set(_use_var "USE_SSE2")
392          endif()
393          if(NOT ${_use_var})
394             message(WARNING "The selected value for VC_IMPL (${VC_IMPL}) will not work because the relevant instructions are not enabled via compiler flags.")
395          endif()
396       endif()
397    endif()
398 endmacro()
399
400 # helper macro for vc_compile_for_all_implementations
401 macro(_vc_compile_one_implementation _objs _impl)
402    list(FIND _disabled_targets "${_impl}" _disabled_index)
403    list(FIND _only_targets "${_impl}" _only_index)
404    if(${_disabled_index} EQUAL -1 AND (NOT _only_targets OR ${_only_index} GREATER -1))
405       set(_extra_flags)
406       set(_ok FALSE)
407       foreach(_flag ${ARGN})
408          if(_flag STREQUAL "NO_FLAG")
409             set(_ok TRUE)
410             break()
411          endif()
412          string(REPLACE " " ";" _flag_list "${_flag}")
413          foreach(_flag ${_flag_list})
414             AddCompilerFlag(${_flag} CXX_RESULT _ok)
415             if(NOT _ok)
416                break()
417             endif()
418          endforeach()
419          if(_ok)
420             set(_extra_flags ${_flag_list})
421             break()
422          endif()
423       endforeach()
424
425       set(_outfile_flag -c -o)
426       if(Vc_COMPILER_IS_MSVC)
427          # MSVC for 64bit does not recognize /arch:SSE2 anymore. Therefore we set override _ok if _impl
428          # says SSE
429          if("${_impl}" MATCHES "SSE")
430             set(_ok TRUE)
431          endif()
432          set(_outfile_flag /c /Fo)
433       endif()
434
435       if(_ok)
436          get_filename_component(_out "${_vc_compile_src}" NAME_WE)
437          get_filename_component(_ext "${_vc_compile_src}" EXT)
438          if(Vc_COMPILER_IS_MSVC)
439             set(_out "${_out}_${_impl}${_ext}.obj")
440          else()
441             set(_out "${_out}_${_impl}${_ext}.o")
442          endif()
443          add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${_out}
444             COMMAND ${CMAKE_CXX_COMPILER} ${_flags} ${_extra_flags}
445             -DVC_IMPL=${_impl}
446             ${_outfile_flag}${_out} ${CMAKE_CURRENT_SOURCE_DIR}/${_vc_compile_src}
447             MAIN_DEPENDENCY ${CMAKE_CURRENT_SOURCE_DIR}/${_vc_compile_src}
448             IMPLICIT_DEPENDS CXX ${CMAKE_CURRENT_SOURCE_DIR}/${_vc_compile_src}
449             COMMENT "Building CXX object ${_out}"
450             WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
451             VERBATIM
452             )
453          list(APPEND ${_objs} "${CMAKE_CURRENT_BINARY_DIR}/${_out}")
454       endif()
455    endif()
456 endmacro()
457
458 # Generate compile rules for the given C++ source file for all available implementations and return
459 # the resulting list of object files in _obj
460 # all remaining arguments are additional flags
461 # Example:
462 #   vc_compile_for_all_implementations(_objs src/trigonometric.cpp FLAGS -DCOMPILE_BLAH EXCLUDE Scalar)
463 #   add_executable(executable main.cpp ${_objs})
464 macro(vc_compile_for_all_implementations _objs _src)
465    set(${_objs})
466
467    # remove all -march, -msse, etc. flags from the flags we want to pass
468    string(REPLACE "${Vc_ARCHITECTURE_FLAGS}" "" _flags "${Vc_DEFINITIONS}")
469    string(REPLACE "-DVC_IMPL=[^ ]*" "" _flags "${_flags}")
470
471    # capture the -march= switch as -mtune; if there is none skip it
472    if(Vc_ARCHITECTURE_FLAGS MATCHES "-march=")
473       string(REGEX REPLACE "^.*-march=([^ ]*).*$" "-mtune=\\1" _tmp "${Vc_ARCHITECTURE_FLAGS}")
474       set(_flags "${_flags} ${_tmp}")
475    endif()
476
477    unset(_disabled_targets)
478    unset(_only_targets)
479    set(_state 0)
480    foreach(_arg ${ARGN})
481       if(_arg STREQUAL "FLAGS")
482          set(_state 1)
483       elseif(_arg STREQUAL "EXCLUDE")
484          set(_state 2)
485       elseif(_arg STREQUAL "ONLY")
486          set(_state 3)
487       elseif(_state EQUAL 1)
488          set(_flags "${_flags} ${_arg}")
489       elseif(_state EQUAL 2)
490          list(APPEND _disabled_targets "${_arg}")
491       elseif(_state EQUAL 3)
492          list(APPEND _only_targets "${_arg}")
493       else()
494          message(FATAL_ERROR "incorrect argument to vc_compile_for_all_implementations")
495       endif()
496    endforeach()
497
498    # make a semicolon separated list of all flags
499    string(TOUPPER "${CMAKE_BUILD_TYPE}" _tmp)
500    set(_tmp "CMAKE_CXX_FLAGS_${_tmp}")
501    string(REPLACE " " ";" _tmp "${CMAKE_CXX_FLAGS} ${${_tmp}} ${_flags}")
502    set(_flags)
503    foreach(item ${_tmp})
504       if(item MATCHES "^[^']*'[^']*$")
505          if(_str)
506             list(APPEND _flags "${_str} ${item}")
507             unset(_str)
508          else()
509             set(_str "${item}")
510          endif()
511       else()
512          list(APPEND _flags "${item}")
513       endif()
514    endforeach()
515    get_directory_property(_inc INCLUDE_DIRECTORIES)
516    foreach(_i ${_inc})
517       list(APPEND _flags "-I${_i}")
518    endforeach()
519
520    set(_vc_compile_src "${_src}")
521
522    _vc_compile_one_implementation(${_objs} Scalar NO_FLAG)
523    if(NOT Vc_SSE_INTRINSICS_BROKEN)
524       _vc_compile_one_implementation(${_objs} SSE2   "-msse2"   "-xSSE2"   "/arch:SSE2")
525       _vc_compile_one_implementation(${_objs} SSE3   "-msse3"   "-xSSE3"   "/arch:SSE2")
526       _vc_compile_one_implementation(${_objs} SSSE3  "-mssse3"  "-xSSSE3"  "/arch:SSE2")
527       _vc_compile_one_implementation(${_objs} SSE4_1 "-msse4.1" "-xSSE4.1" "/arch:SSE2")
528       _vc_compile_one_implementation(${_objs} SSE4_2 "-msse4.2" "-xSSE4.2" "/arch:SSE2")
529       _vc_compile_one_implementation(${_objs} SSE3+SSE4a  "-msse4a")
530    endif()
531    if(NOT Vc_AVX_INTRINSICS_BROKEN)
532       _vc_compile_one_implementation(${_objs} AVX      "-mavx"    "-xAVX"    "/arch:AVX")
533       if(NOT Vc_XOP_INTRINSICS_BROKEN)
534          if(NOT Vc_FMA4_INTRINSICS_BROKEN)
535             _vc_compile_one_implementation(${_objs} SSE+XOP+FMA4 "-mxop -mfma4"        ""    "")
536             _vc_compile_one_implementation(${_objs} AVX+XOP+FMA4 "-mavx -mxop -mfma4"  ""    "")
537          endif()
538          _vc_compile_one_implementation(${_objs} SSE+XOP+FMA "-mxop -mfma"        ""    "")
539          _vc_compile_one_implementation(${_objs} AVX+XOP+FMA "-mavx -mxop -mfma"  ""    "")
540       endif()
541       _vc_compile_one_implementation(${_objs} AVX+FMA "-mavx -mfma"  ""    "")
542    endif()
543 endmacro()