Update master to aliroot
[u/mrichter/AliRoot.git] / Vc / cmake / VcMacros.cmake
CommitLineData
f22341db 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#=============================================================================
c017a39f 8# Copyright 2009-2013 Matthias Kretz <kretz@kde.org>
f22341db 9#
c017a39f 10# Redistribution and use in source and binary forms, with or without
11# modification, are permitted provided that the following conditions are
12# met:
f22341db 13#
c017a39f 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.
f22341db 36#=============================================================================
37
c017a39f 38cmake_minimum_required(VERSION 2.8.3)
39
f22341db 40get_filename_component(_currentDir "${CMAKE_CURRENT_LIST_FILE}" PATH)
41include ("${_currentDir}/UserWarning.cmake")
42include ("${_currentDir}/AddCompilerFlag.cmake")
43include ("${_currentDir}/OptimizeForArchitecture.cmake")
44
45macro(vc_determine_compiler)
46 if(NOT DEFINED Vc_COMPILER_IS_INTEL)
c017a39f 47 execute_process(COMMAND "${CMAKE_CXX_COMPILER}" "--version" OUTPUT_VARIABLE _cxx_compiler_version ERROR_VARIABLE _cxx_compiler_version)
f22341db 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)
1612d018 53 if(CMAKE_CXX_COMPILER MATCHES "(icpc|icc)$")
f22341db 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}")
23a11150 57 elseif(CMAKE_CXX_COMPILER MATCHES "(opencc|openCC)$")
f22341db 58 set(Vc_COMPILER_IS_OPEN64 true)
59 message(STATUS "Detected Compiler: Open64")
c017a39f 60 elseif(CMAKE_CXX_COMPILER MATCHES "clang\\+\\+$" OR "${_cxx_compiler_version}" MATCHES "clang")
f22341db 61 set(Vc_COMPILER_IS_CLANG true)
c017a39f 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}")
f22341db 65 elseif(MSVC)
66 set(Vc_COMPILER_IS_MSVC true)
c017a39f 67 message(STATUS "Detected Compiler: MSVC ${MSVC_VERSION}")
f22341db 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()
104endmacro()
105
106macro(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)
c017a39f 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)
f22341db 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)
c017a39f 115 set(CMAKE_C_FLAGS_RELWITHDEBUG "${CMAKE_CXX_FLAGS_RELWITHDEBUG}" CACHE STRING "Flags used by the compiler during release builds containing runtime checks." FORCE)
f22341db 116 set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO}" CACHE STRING "Flags used by the compiler during Release with Debug Info builds." FORCE)
c017a39f 117 if(CMAKE_BUILD_TYPE STREQUAL "Release" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebug")
f22341db 118 set(ENABLE_STRICT_ALIASING true CACHE BOOL "Enables strict aliasing rules for more aggressive optimizations")
119 if(NOT ENABLE_STRICT_ALIASING)
c017a39f 120 AddCompilerFlag(-fno-strict-aliasing)
f22341db 121 endif(NOT ENABLE_STRICT_ALIASING)
122 endif()
c017a39f 123 mark_as_advanced(CMAKE_CXX_FLAGS_RELWITHDEBUG CMAKE_C_FLAGS_RELWITHDEBUG)
f22341db 124endmacro()
125
126macro(vc_add_compiler_flag VAR _flag)
127 AddCompilerFlag("${_flag}" CXX_FLAGS ${VAR})
128endmacro()
129
130macro(vc_check_assembler)
131 if(APPLE)
132 if(NOT Vc_COMPILER_IS_CLANG)
3ea24db6 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)
f22341db 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")
6936ae04 151 UserWarning("Your binutils is too old (${_as_version}). Some optimizations of Vc will be disabled.")
f22341db 152 add_definitions(-DVC_NO_XGETBV) # old assembler doesn't know the xgetbv instruction
c017a39f 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)
f22341db 159 endif()
160 endif()
161 endif(APPLE)
162endmacro()
163
164macro(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)
c017a39f 170 if(_gcc_machine MATCHES "[x34567]86" OR _gcc_machine STREQUAL "mingw32")
f22341db 171 vc_add_compiler_flag(Vc_DEFINITIONS "-mfpmath=sse")
c017a39f 172 endif()
f22341db 173 endif()
174endmacro()
175
176macro(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)
6936ae04 191 set(Vc_XOP_INTRINSICS_BROKEN false)
c017a39f 192 set(Vc_FMA4_INTRINSICS_BROKEN false)
f22341db 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")
f22341db 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()
c017a39f 223
224 # Open64 4.5.1 still doesn't ship immintrin.h
225 set(Vc_AVX_INTRINSICS_BROKEN true)
f22341db 226 elseif(Vc_COMPILER_IS_GCC)
227 ##################################################################################################
228 # GCC #
229 ##################################################################################################
230 if(_add_warning_flags)
79c86c14 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")
c017a39f 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")
f22341db 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
6936ae04 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")
f22341db 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")
c017a39f 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)
f22341db 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")
c017a39f 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")
f22341db 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")
c017a39f 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)
f22341db 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")
6936ae04 352
c017a39f 353 # MSVC doesn't implement the XOP or FMA4 intrinsics
6936ae04 354 set(Vc_XOP_INTRINSICS_BROKEN true)
c017a39f 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()
f22341db 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...
c017a39f 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.")
79c86c14 364 elseif(Vc_CLANG_VERSION VERSION_EQUAL "3.2" AND NOT APPLE)
c017a39f 365 # the LLVM assembler gets FMAs wrong (bug 15040)
366 vc_add_compiler_flag(Vc_DEFINITIONS "-no-integrated-as")
367 endif()
f22341db 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")
c017a39f 372
79c86c14 373 if(NOT DEFINED Vc_INSIDE_ROOT) # ROOT has to set this up
374 AddCompilerFlag(-stdlib=libc++)
375 endif()
c017a39f 376 endif()
377
1612d018 378 if(NOT Vc_COMPILER_IS_MSVC AND NOT Vc_COMPILER_IS_INTEL)
79c86c14 379 vc_add_compiler_flag(Vc_DEFINITIONS "-ffp-contract=fast")
f22341db 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()
398endmacro()
c017a39f 399
400# helper macro for vc_compile_for_all_implementations
401macro(_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()
456endmacro()
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})
464macro(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)
79c86c14 535 _vc_compile_one_implementation(${_objs} SSE+XOP+FMA4 "-mxop -mfma4" "" "")
536 _vc_compile_one_implementation(${_objs} AVX+XOP+FMA4 "-mavx -mxop -mfma4" "" "")
c017a39f 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()
543endmacro()