VcMacros.cmake 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512
  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-2015 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. # * Redistributions in binary form must reproduce the above copyright notice,
  17. # this list of conditions and the following disclaimer in the documentation
  18. # and/or other materials provided with the distribution.
  19. # * Neither the names of contributing organizations nor the
  20. # names of its contributors may be used to endorse or promote products
  21. # derived from this software without specific prior written permission.
  22. #
  23. # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS ``AS IS''
  24. # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  25. # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  26. # ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR
  27. # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  28. # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  29. # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  30. # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  31. # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  32. # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  33. #=============================================================================
  34. cmake_minimum_required(VERSION 2.8.3)
  35. get_filename_component(_currentDir "${CMAKE_CURRENT_LIST_FILE}" PATH)
  36. include ("${_currentDir}/UserWarning.cmake")
  37. include ("${_currentDir}/AddCompilerFlag.cmake")
  38. include ("${_currentDir}/OptimizeForArchitecture.cmake")
  39. macro(vc_determine_compiler)
  40. if(NOT DEFINED Vc_COMPILER_IS_INTEL)
  41. execute_process(COMMAND "${CMAKE_CXX_COMPILER}" "--version" OUTPUT_VARIABLE _cxx_compiler_version ERROR_VARIABLE _cxx_compiler_version)
  42. set(Vc_COMPILER_IS_INTEL false)
  43. set(Vc_COMPILER_IS_OPEN64 false)
  44. set(Vc_COMPILER_IS_CLANG false)
  45. set(Vc_COMPILER_IS_MSVC false)
  46. set(Vc_COMPILER_IS_GCC false)
  47. if(CMAKE_CXX_COMPILER MATCHES "/(icpc|icc)$")
  48. set(Vc_COMPILER_IS_INTEL true)
  49. exec_program(${CMAKE_CXX_COMPILER} ARGS -dumpversion OUTPUT_VARIABLE Vc_ICC_VERSION)
  50. message(STATUS "Detected Compiler: Intel ${Vc_ICC_VERSION}")
  51. # break build with too old clang as early as possible.
  52. if(Vc_ICC_VERSION VERSION_LESS 18.0.0)
  53. message(FATAL_ERROR "Vc 1.4 requires least ICC 18")
  54. endif()
  55. elseif(CMAKE_CXX_COMPILER MATCHES "(opencc|openCC)$")
  56. set(Vc_COMPILER_IS_OPEN64 true)
  57. message(STATUS "Detected Compiler: Open64")
  58. elseif(CMAKE_CXX_COMPILER MATCHES "clang\\+\\+$" OR "${_cxx_compiler_version}" MATCHES "clang")
  59. set(Vc_COMPILER_IS_CLANG true)
  60. exec_program(${CMAKE_CXX_COMPILER} ARGS --version OUTPUT_VARIABLE Vc_CLANG_VERSION)
  61. string(REGEX MATCH "[0-9]+\\.[0-9]+(\\.[0-9]+)?" Vc_CLANG_VERSION "${Vc_CLANG_VERSION}")
  62. message(STATUS "Detected Compiler: Clang ${Vc_CLANG_VERSION}")
  63. # break build with too old clang as early as possible.
  64. if(Vc_CLANG_VERSION VERSION_LESS 3.4)
  65. message(FATAL_ERROR "Vc 1.x requires C++11 support. This requires at least clang 3.4")
  66. endif()
  67. elseif(MSVC)
  68. set(Vc_COMPILER_IS_MSVC true)
  69. execute_process(COMMAND ${CMAKE_CXX_COMPILER} /nologo -EP "${_currentDir}/msvc_version.c" OUTPUT_STRIP_TRAILING_WHITESPACE OUTPUT_VARIABLE Vc_MSVC_VERSION)
  70. string(STRIP "${Vc_MSVC_VERSION}" Vc_MSVC_VERSION)
  71. string(REPLACE "MSVC " "" Vc_MSVC_VERSION "${Vc_MSVC_VERSION}")
  72. message(STATUS "Detected Compiler: MSVC ${Vc_MSVC_VERSION}")
  73. elseif(CMAKE_COMPILER_IS_GNUCXX)
  74. set(Vc_COMPILER_IS_GCC true)
  75. exec_program(${CMAKE_CXX_COMPILER} ARGS -dumpversion OUTPUT_VARIABLE Vc_GCC_VERSION)
  76. message(STATUS "Detected Compiler: GCC ${Vc_GCC_VERSION}")
  77. # some distributions patch their GCC to return nothing or only major and minor version on -dumpversion.
  78. # In that case we must extract the version number from --version.
  79. if(NOT Vc_GCC_VERSION OR Vc_GCC_VERSION MATCHES "^[0-9]\\.[0-9]+$")
  80. exec_program(${CMAKE_CXX_COMPILER} ARGS --version OUTPUT_VARIABLE Vc_GCC_VERSION)
  81. string(REGEX MATCH "[0-9]+\\.[0-9]+\\.[0-9]+" Vc_GCC_VERSION "${Vc_GCC_VERSION}")
  82. message(STATUS "GCC Version from --version: ${Vc_GCC_VERSION}")
  83. endif()
  84. # some distributions patch their GCC to be API incompatible to what the FSF released. In
  85. # those cases we require a macro to identify the distribution version
  86. find_program(Vc_lsb_release lsb_release)
  87. mark_as_advanced(Vc_lsb_release)
  88. if(Vc_lsb_release)
  89. if(NOT Vc_distributor_id)
  90. execute_process(COMMAND ${Vc_lsb_release} -is OUTPUT_VARIABLE Vc_distributor_id OUTPUT_STRIP_TRAILING_WHITESPACE)
  91. string(TOUPPER "${Vc_distributor_id}" Vc_distributor_id)
  92. set(Vc_distributor_id "${Vc_distributor_id}" CACHE STRING "lsb distribution id")
  93. execute_process(COMMAND ${Vc_lsb_release} -rs OUTPUT_VARIABLE Vc_distributor_release OUTPUT_STRIP_TRAILING_WHITESPACE)
  94. set(Vc_distributor_release "${Vc_distributor_release}" CACHE STRING "lsb release id")
  95. endif()
  96. if(Vc_distributor_id STREQUAL "UBUNTU")
  97. execute_process(COMMAND ${CMAKE_CXX_COMPILER} --version OUTPUT_STRIP_TRAILING_WHITESPACE OUTPUT_VARIABLE _gcc_version)
  98. string(REGEX MATCH "\\(.* ${Vc_GCC_VERSION}-([0-9]+).*\\)" _tmp "${_gcc_version}")
  99. if(_tmp)
  100. set(_patch ${CMAKE_MATCH_1})
  101. string(REGEX MATCH "^([0-9]+)\\.([0-9]+)$" _tmp "${Vc_distributor_release}")
  102. execute_process(COMMAND printf 0x%x%02x%02x ${CMAKE_MATCH_1} ${CMAKE_MATCH_2} ${_patch} OUTPUT_STRIP_TRAILING_WHITESPACE OUTPUT_VARIABLE _tmp)
  103. set(Vc_DEFINITIONS "${Vc_DEFINITIONS} -D__GNUC_UBUNTU_VERSION__=${_tmp}")
  104. endif()
  105. endif()
  106. endif()
  107. # break build with too old GCC as early as possible.
  108. if(Vc_GCC_VERSION VERSION_LESS 4.8.1)
  109. message(FATAL_ERROR "Vc 1.x requires C++11 support. This requires at least GCC 4.8.1")
  110. endif()
  111. else()
  112. message(WARNING "Untested/-supported Compiler (${CMAKE_CXX_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")
  113. endif()
  114. endif()
  115. endmacro()
  116. macro(vc_set_gnu_buildtype_flags)
  117. set(CMAKE_CXX_FLAGS_DEBUG "-g3" CACHE STRING "Flags used by the compiler during debug builds." FORCE)
  118. set(CMAKE_CXX_FLAGS_MINSIZEREL "-Os -DNDEBUG" CACHE STRING "Flags used by the compiler during release minsize builds." FORCE)
  119. 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)
  120. set(CMAKE_CXX_FLAGS_RELWITHDEBUG "-O3" CACHE STRING "Flags used by the compiler during release builds containing runtime checks." FORCE)
  121. set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBUG} -g" CACHE STRING "Flags used by the compiler during Release with Debug Info builds." FORCE)
  122. set(CMAKE_C_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}" CACHE STRING "Flags used by the compiler during debug builds." FORCE)
  123. set(CMAKE_C_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL}" CACHE STRING "Flags used by the compiler during release minsize builds." FORCE)
  124. 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)
  125. set(CMAKE_C_FLAGS_RELWITHDEBUG "${CMAKE_CXX_FLAGS_RELWITHDEBUG}" CACHE STRING "Flags used by the compiler during release builds containing runtime checks." FORCE)
  126. set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO}" CACHE STRING "Flags used by the compiler during Release with Debug Info builds." FORCE)
  127. if(CMAKE_BUILD_TYPE STREQUAL "Release" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebug")
  128. set(ENABLE_STRICT_ALIASING true CACHE BOOL "Enables strict aliasing rules for more aggressive optimizations")
  129. if(NOT ENABLE_STRICT_ALIASING)
  130. AddCompilerFlag(-fno-strict-aliasing)
  131. endif(NOT ENABLE_STRICT_ALIASING)
  132. endif()
  133. mark_as_advanced(CMAKE_CXX_FLAGS_RELWITHDEBUG CMAKE_C_FLAGS_RELWITHDEBUG)
  134. endmacro()
  135. macro(vc_add_compiler_flag VAR _flag)
  136. AddCompilerFlag("${_flag}" CXX_FLAGS ${VAR})
  137. endmacro()
  138. macro(vc_check_assembler)
  139. exec_program(${CMAKE_CXX_COMPILER} ARGS -print-prog-name=as OUTPUT_VARIABLE _as)
  140. mark_as_advanced(_as)
  141. if(NOT _as)
  142. message(WARNING "Could not find 'as', the assembler used by GCC. Hoping everything will work out...")
  143. else()
  144. exec_program(${_as} ARGS --version OUTPUT_VARIABLE _as_version)
  145. string(REGEX REPLACE "\\([^\\)]*\\)" "" _as_version "${_as_version}")
  146. string(REGEX MATCH "[1-9]\\.[0-9]+(\\.[0-9]+)?" _as_version "${_as_version}")
  147. if(_as_version VERSION_LESS "2.18.93")
  148. UserWarning("Your binutils is too old (${_as_version}). Some optimizations of Vc will be disabled.")
  149. set(Vc_DEFINITIONS "${Vc_DEFINITIONS} -DVc_NO_XGETBV") # old assembler doesn't know the xgetbv instruction
  150. set(Vc_AVX_INTRINSICS_BROKEN true)
  151. set(Vc_XOP_INTRINSICS_BROKEN true)
  152. set(Vc_FMA4_INTRINSICS_BROKEN true)
  153. elseif(_as_version VERSION_LESS "2.21.0")
  154. UserWarning("Your binutils is too old (${_as_version}) for XOP and AVX2 instructions. They will therefore not be provided in libVc.")
  155. set(Vc_XOP_INTRINSICS_BROKEN true)
  156. set(Vc_AVX2_INTRINSICS_BROKEN true)
  157. endif()
  158. endif()
  159. endmacro()
  160. macro(vc_set_preferred_compiler_flags)
  161. vc_determine_compiler()
  162. # Look for libmvec, which provides vectorized implementations of libm
  163. find_library(Vc_LIB_MVEC mvec)
  164. if(Vc_LIB_MVEC)
  165. set(SAFE_CMAKE_REQUIRED_LIBRARIES "${CMAKE_REQUIRED_LIBRARIES}")
  166. set(CMAKE_REQUIRED_LIBRARIES ${Vc_LIB_MVEC})
  167. CHECK_CXX_SOURCE_COMPILES("
  168. #include <x86intrin.h>
  169. extern \"C\" {
  170. __m128 _ZGVbN4v_sinf(__m128);
  171. __m128d _ZGVbN2v_sin(__m128d);
  172. __m128 _ZGVbN4v_cosf(__m128);
  173. __m128d _ZGVbN2v_cos(__m128d);
  174. }
  175. __m128 f0(__m128 x) { return _ZGVbN4v_cosf(_ZGVbN4v_sinf(x)); }
  176. __m128d f1(__m128d x) { return _ZGVbN2v_cos(_ZGVbN2v_sin(x)); }
  177. int main() { return 0; }
  178. " Vc_HAVE_SSE_SINCOS)
  179. CHECK_CXX_SOURCE_COMPILES("
  180. #include <x86intrin.h>
  181. extern \"C\" {
  182. __m256 _ZGVdN8v_sinf(__m256);
  183. __m256d _ZGVdN4v_sin(__m256d);
  184. __m256 _ZGVdN8v_cosf(__m256);
  185. __m256d _ZGVdN4v_cos(__m256d);
  186. }
  187. __m256 f0(__m256 x) { return _ZGVdN8v_cosf(_ZGVdN8v_sinf(x)); }
  188. __m256d f1(__m256d x) { return _ZGVdN4v_cos(_ZGVdN4v_sin(x)); }
  189. int main() { return 0; }
  190. " Vc_HAVE_AVX_SINCOS)
  191. set(CMAKE_REQUIRED_LIBRARIES "${SAFE_CMAKE_REQUIRED_LIBRARIES}")
  192. if(Vc_HAVE_SSE_SINCOS AND Vc_HAVE_AVX_SINCOS)
  193. option(USE_LIBMVEC "Use GNU's libmvec for vectorized sine and cosine" OFF)
  194. if(USE_LIBMVEC)
  195. set(Vc_DEFINITIONS "${Vc_DEFINITIONS} -DVc_HAVE_LIBMVEC=1")
  196. endif()
  197. endif()
  198. endif(Vc_LIB_MVEC)
  199. set(_add_warning_flags false)
  200. set(_add_buildtype_flags false)
  201. foreach(_arg ${ARGN})
  202. if(_arg STREQUAL "WARNING_FLAGS")
  203. set(_add_warning_flags true)
  204. elseif(_arg STREQUAL "BUILDTYPE_FLAGS")
  205. set(_add_buildtype_flags true)
  206. endif()
  207. endforeach()
  208. set(Vc_SSE_INTRINSICS_BROKEN false)
  209. set(Vc_AVX_INTRINSICS_BROKEN false)
  210. set(Vc_AVX2_INTRINSICS_BROKEN false)
  211. set(Vc_XOP_INTRINSICS_BROKEN false)
  212. set(Vc_FMA4_INTRINSICS_BROKEN false)
  213. if(Vc_COMPILER_IS_OPEN64)
  214. ##################################################################################################
  215. # Open64 #
  216. ##################################################################################################
  217. if(_add_warning_flags)
  218. AddCompilerFlag("-W")
  219. AddCompilerFlag("-Wall")
  220. AddCompilerFlag("-Wimplicit")
  221. AddCompilerFlag("-Wswitch")
  222. AddCompilerFlag("-Wformat")
  223. AddCompilerFlag("-Wchar-subscripts")
  224. AddCompilerFlag("-Wparentheses")
  225. AddCompilerFlag("-Wmultichar")
  226. AddCompilerFlag("-Wtrigraphs")
  227. AddCompilerFlag("-Wpointer-arith")
  228. AddCompilerFlag("-Wcast-align")
  229. AddCompilerFlag("-Wreturn-type")
  230. AddCompilerFlag("-pedantic")
  231. AddCompilerFlag("-Wno-long-long")
  232. AddCompilerFlag("-Wshadow")
  233. AddCompilerFlag("-Wold-style-cast")
  234. AddCompilerFlag("-Wno-variadic-macros")
  235. endif()
  236. if(_add_buildtype_flags)
  237. vc_set_gnu_buildtype_flags()
  238. endif()
  239. vc_check_assembler()
  240. # Open64 4.5.1 still doesn't ship immintrin.h
  241. set(Vc_AVX_INTRINSICS_BROKEN true)
  242. set(Vc_AVX2_INTRINSICS_BROKEN true)
  243. elseif(Vc_COMPILER_IS_GCC)
  244. ##################################################################################################
  245. # GCC #
  246. ##################################################################################################
  247. if(_add_warning_flags)
  248. foreach(_f -W -Wall -Wswitch -Wformat -Wchar-subscripts -Wparentheses -Wmultichar -Wtrigraphs -Wpointer-arith -Wcast-align -Wreturn-type -pedantic -Wshadow -Wundef)
  249. AddCompilerFlag("${_f}")
  250. endforeach()
  251. foreach(_f -Wold-style-cast)
  252. AddCompilerFlag("${_f}" CXX_FLAGS CMAKE_CXX_FLAGS)
  253. endforeach()
  254. endif()
  255. vc_add_compiler_flag(Vc_COMPILE_FLAGS "-Wabi")
  256. vc_add_compiler_flag(Vc_COMPILE_FLAGS "-fabi-version=0") # ABI version 4 is required to make __m128 and __m256 appear as different types. 0 should give us the latest version.
  257. vc_add_compiler_flag(Vc_COMPILE_FLAGS "-fabi-compat-version=0") # GCC 5 introduced this switch
  258. # and defaults it to 2 if -fabi-version is 0. But in that case the bug -fabi-version=0 is
  259. # supposed to fix resurfaces. For now just make sure that it compiles and links.
  260. # Bug report pending.
  261. if(_add_buildtype_flags)
  262. vc_set_gnu_buildtype_flags()
  263. endif()
  264. if(APPLE)
  265. # The GNU assembler (as) on Mac OS X is hopelessly outdated. The -q flag
  266. # to as tells it to use the clang assembler, though, which is fine.
  267. # -Wa,-q tells GCC to pass -q to as.
  268. vc_add_compiler_flag(Vc_COMPILE_FLAGS "-Wa,-q")
  269. # Apparently the MacOS clang assember doesn't understand XOP instructions.
  270. set(Vc_XOP_INTRINSICS_BROKEN true)
  271. else()
  272. vc_check_assembler()
  273. endif()
  274. elseif(Vc_COMPILER_IS_INTEL)
  275. ##################################################################################################
  276. # Intel Compiler #
  277. ##################################################################################################
  278. if(_add_buildtype_flags)
  279. set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O3")
  280. set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -DNDEBUG -O3")
  281. set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -O3")
  282. set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} -DNDEBUG -O3")
  283. endif()
  284. if(CMAKE_BUILD_TYPE STREQUAL "Release" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo")
  285. set(ENABLE_STRICT_ALIASING true CACHE BOOL "Enables strict aliasing rules for more aggressive optimizations")
  286. if(ENABLE_STRICT_ALIASING)
  287. AddCompilerFlag(-ansi-alias CXX_FLAGS Vc_COMPILE_FLAGS)
  288. else()
  289. AddCompilerFlag(-no-ansi-alias CXX_FLAGS Vc_COMPILE_FLAGS)
  290. endif()
  291. endif()
  292. if(NOT "$ENV{DASHBOARD_TEST_FROM_CTEST}" STREQUAL "")
  293. # disable warning #2928: the __GXX_EXPERIMENTAL_CXX0X__ macro is disabled when using GNU version 4.6 with the c++0x option
  294. # this warning just adds noise about problems in the compiler - but I'm only interested in seeing problems in Vc
  295. vc_add_compiler_flag(Vc_COMPILE_FLAGS "-diag-disable 2928")
  296. endif()
  297. # Intel doesn't implement the XOP or FMA4 intrinsics
  298. set(Vc_XOP_INTRINSICS_BROKEN true)
  299. set(Vc_FMA4_INTRINSICS_BROKEN true)
  300. elseif(Vc_COMPILER_IS_MSVC)
  301. ##################################################################################################
  302. # Microsoft Visual Studio #
  303. ##################################################################################################
  304. if(_add_warning_flags)
  305. AddCompilerFlag("/wd4800") # Disable warning "forcing value to bool"
  306. AddCompilerFlag("/wd4996") # Disable warning about strdup vs. _strdup
  307. AddCompilerFlag("/wd4244") # Disable warning "conversion from 'unsigned int' to 'float', possible loss of data"
  308. AddCompilerFlag("/wd4146") # Disable warning "unary minus operator applied to unsigned type, result still unsigned"
  309. AddCompilerFlag("/wd4227") # Disable warning "anachronism used : qualifiers on reference are ignored" (this is about 'restrict' usage on references, stupid MSVC)
  310. AddCompilerFlag("/wd4722") # Disable warning "destructor never returns, potential memory leak" (warns about ~_UnitTest_Global_Object which we don't care about)
  311. 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)
  312. add_definitions(-D_CRT_SECURE_NO_WARNINGS)
  313. endif()
  314. vc_add_compiler_flag(Vc_COMPILE_FLAGS "/Gv") # default to __vectorcall
  315. if(MSVC_VERSION LESS 1900)
  316. UserWarning("MSVC before 2015 does not support enough of C++11")
  317. endif()
  318. elseif(Vc_COMPILER_IS_CLANG)
  319. ##################################################################################################
  320. # Clang #
  321. ##################################################################################################
  322. if(Vc_CLANG_VERSION VERSION_GREATER "3.5.99" AND Vc_CLANG_VERSION VERSION_LESS 3.7.0)
  323. UserWarning("Clang 3.6 has serious issues with AVX code generation, frequently losing 50% of the data. AVX is therefore disabled.\nPlease update to a more recent clang version.\n")
  324. set(Vc_AVX_INTRINSICS_BROKEN true)
  325. set(Vc_AVX2_INTRINSICS_BROKEN true)
  326. endif()
  327. # disable these warnings because clang shows them for function overloads that were discarded via SFINAE
  328. vc_add_compiler_flag(Vc_COMPILE_FLAGS "-Wno-local-type-template-args")
  329. vc_add_compiler_flag(Vc_COMPILE_FLAGS "-Wno-unnamed-type-template-args")
  330. endif()
  331. if(NOT Vc_COMPILER_IS_MSVC)
  332. vc_add_compiler_flag(Vc_COMPILE_FLAGS "-ffp-contract=fast")
  333. endif()
  334. OptimizeForArchitecture()
  335. set(Vc_IMPL "auto" CACHE STRING "Force the Vc implementation globally to the selected instruction set. \"auto\" lets Vc use the best available instructions.")
  336. if(NOT Vc_IMPL STREQUAL "auto")
  337. set(Vc_DEFINITIONS "${Vc_DEFINITIONS} -DVc_IMPL=${Vc_IMPL}")
  338. if(NOT Vc_IMPL STREQUAL "Scalar")
  339. set(_use_var "USE_${Vc_IMPL}")
  340. if(Vc_IMPL STREQUAL "SSE")
  341. set(_use_var "USE_SSE2")
  342. endif()
  343. if(NOT ${_use_var})
  344. message(WARNING "The selected value for Vc_IMPL (${Vc_IMPL}) will not work because the relevant instructions are not enabled via compiler flags.")
  345. endif()
  346. endif()
  347. endif()
  348. endmacro()
  349. # helper macro for vc_compile_for_all_implementations
  350. macro(_vc_compile_one_implementation _srcs _impl)
  351. list(FIND _disabled_targets "${_impl}" _disabled_index)
  352. list(FIND _only_targets "${_impl}" _only_index)
  353. if(${_disabled_index} GREATER -1)
  354. if(${_only_index} GREATER -1)
  355. # disabled and enabled -> error
  356. message(FATAL_ERROR "vc_compile_for_all_implementations lists ${_impl} in both the ONLY and EXCLUDE lists. Please remove one.")
  357. endif()
  358. list(REMOVE_AT _disabled_targets ${_disabled_index})
  359. # skip the rest and return
  360. elseif(NOT _only_targets OR ${_only_index} GREATER -1)
  361. if(${_only_index} GREATER -1)
  362. list(REMOVE_AT _only_targets ${_only_index})
  363. endif()
  364. set(_extra_flags)
  365. set(_ok FALSE)
  366. foreach(_flags_it ${ARGN})
  367. if(_flags_it STREQUAL "NO_FLAG")
  368. set(_ok TRUE)
  369. break()
  370. endif()
  371. string(REPLACE " " ";" _flag_list "${_flags_it}")
  372. foreach(_f ${_flag_list})
  373. AddCompilerFlag(${_f} CXX_RESULT _ok)
  374. if(NOT _ok)
  375. break()
  376. endif()
  377. endforeach()
  378. if(_ok)
  379. set(_extra_flags ${_flags_it})
  380. break()
  381. endif()
  382. endforeach()
  383. if(Vc_COMPILER_IS_MSVC)
  384. # MSVC for 64bit does not recognize /arch:SSE2 anymore. Therefore we set override _ok if _impl
  385. # says SSE
  386. if("${_impl}" MATCHES "SSE")
  387. set(_ok TRUE)
  388. endif()
  389. endif()
  390. if(_ok)
  391. get_filename_component(_out "${_vc_compile_src}" NAME_WE)
  392. get_filename_component(_ext "${_vc_compile_src}" EXT)
  393. set(_out "${CMAKE_CURRENT_BINARY_DIR}/${_out}_${_impl}${_ext}")
  394. add_custom_command(OUTPUT "${_out}"
  395. COMMAND ${CMAKE_COMMAND} -E copy "${_vc_compile_src}" "${_out}"
  396. DEPENDS "${_vc_compile_src}"
  397. COMMENT "Copy to ${_out}"
  398. WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
  399. VERBATIM)
  400. set_source_files_properties( "${_out}" PROPERTIES
  401. COMPILE_DEFINITIONS "Vc_IMPL=${_impl}"
  402. COMPILE_FLAGS "${_flags} ${_extra_flags}"
  403. )
  404. list(APPEND ${_srcs} "${_out}")
  405. endif()
  406. endif()
  407. endmacro()
  408. # Generate compile rules for the given C++ source file for all available implementations and return
  409. # the resulting list of object files in _obj
  410. # all remaining arguments are additional flags
  411. # Example:
  412. # vc_compile_for_all_implementations(_objs src/trigonometric.cpp FLAGS -DCOMPILE_BLAH EXCLUDE Scalar)
  413. # add_executable(executable main.cpp ${_objs})
  414. macro(vc_compile_for_all_implementations _srcs _src)
  415. set(_flags)
  416. unset(_disabled_targets)
  417. unset(_only_targets)
  418. set(_state 0)
  419. foreach(_arg ${ARGN})
  420. if(_arg STREQUAL "FLAGS")
  421. set(_state 1)
  422. elseif(_arg STREQUAL "EXCLUDE")
  423. set(_state 2)
  424. elseif(_arg STREQUAL "ONLY")
  425. set(_state 3)
  426. elseif(_state EQUAL 1)
  427. set(_flags "${_flags} ${_arg}")
  428. elseif(_state EQUAL 2)
  429. list(APPEND _disabled_targets "${_arg}")
  430. elseif(_state EQUAL 3)
  431. list(APPEND _only_targets "${_arg}")
  432. else()
  433. message(FATAL_ERROR "incorrect argument to vc_compile_for_all_implementations")
  434. endif()
  435. endforeach()
  436. set(_vc_compile_src "${_src}")
  437. _vc_compile_one_implementation(${_srcs} Scalar NO_FLAG)
  438. if(NOT Vc_SSE_INTRINSICS_BROKEN)
  439. _vc_compile_one_implementation(${_srcs} SSE2 "-xSSE2" "-msse2" "/arch:SSE2")
  440. _vc_compile_one_implementation(${_srcs} SSE3 "-xSSE3" "-msse3" "/arch:SSE2")
  441. _vc_compile_one_implementation(${_srcs} SSSE3 "-xSSSE3" "-mssse3" "/arch:SSE2")
  442. _vc_compile_one_implementation(${_srcs} SSE4_1 "-xSSE4.1" "-msse4.1" "/arch:SSE2")
  443. _vc_compile_one_implementation(${_srcs} SSE4_2 "-xSSE4.2" "-msse4.2" "/arch:SSE2")
  444. _vc_compile_one_implementation(${_srcs} SSE3+SSE4a "-msse4a")
  445. endif()
  446. if(NOT Vc_AVX_INTRINSICS_BROKEN)
  447. _vc_compile_one_implementation(${_srcs} AVX "-xAVX" "-mavx" "/arch:AVX")
  448. if(NOT Vc_XOP_INTRINSICS_BROKEN)
  449. if(NOT Vc_FMA4_INTRINSICS_BROKEN)
  450. _vc_compile_one_implementation(${_srcs} SSE+XOP+FMA4 "-mxop -mfma4" "" "")
  451. _vc_compile_one_implementation(${_srcs} AVX+XOP+FMA4 "-mavx -mxop -mfma4" "" "")
  452. endif()
  453. _vc_compile_one_implementation(${_srcs} SSE+XOP+FMA "-mxop -mfma" "" "")
  454. _vc_compile_one_implementation(${_srcs} AVX+XOP+FMA "-mavx -mxop -mfma" "" "")
  455. endif()
  456. _vc_compile_one_implementation(${_srcs} AVX+FMA "-mavx -mfma" "" "")
  457. endif()
  458. if(NOT Vc_AVX2_INTRINSICS_BROKEN)
  459. # The necessary list is not clear to me yet. At this point I'll only consider Intel CPUs, in
  460. # which case AVX2 implies the availability of FMA and BMI2
  461. #_vc_compile_one_implementation(${_srcs} AVX2 "-mavx2")
  462. #_vc_compile_one_implementation(${_srcs} AVX2+BMI2 "-mavx2 -mbmi2")
  463. _vc_compile_one_implementation(${_srcs} AVX2+FMA+BMI2 "-xCORE-AVX2" "-mavx2 -mfma -mbmi2" "/arch:AVX2")
  464. #_vc_compile_one_implementation(${_srcs} AVX2+FMA "-mavx2 -mfma")
  465. endif()
  466. list(LENGTH _only_targets _len)
  467. if(_len GREATER 0)
  468. message(WARNING "The following unknown targets where listed in the ONLY list of vc_compile_for_all_implementations: '${_only_targets}'")
  469. endif()
  470. list(LENGTH _disabled_targets _len)
  471. if(_len GREATER 0)
  472. message(WARNING "The following unknown targets where listed in the EXCLUDE list of vc_compile_for_all_implementations: '${_disabled_targets}'")
  473. endif()
  474. endmacro()