1/* Copyright (C) 2011-2012 Povilas Kanapickas <povilas@radix.lt>
2
3 Distributed under the Boost Software License, Version 1.0.
4 (See accompanying file LICENSE_1_0.txt or copy at
5 http://www.boost.org/LICENSE_1_0.txt)
6*/
7
8#ifndef LIBSIMDPP_SIMDPP_DETAIL_WORKAROUNDS_H
9#define LIBSIMDPP_SIMDPP_DETAIL_WORKAROUNDS_H
10
11// this file contains workarounds for common compiler problems
12
13// the implementation of XOP's com instruction is buggy in clang 3.5 and 3.4.
14#if defined(__clang__) && (__clang_major__ == 3) && (__clang_minor__ < 6)
15#define SIMDPP_WORKAROUND_XOP_COM 1
16#endif
17
18#if SIMDPP_USE_NEON64
19#if (__GNUC__ == 4) && (__GNUC_MINOR__ <= 8) && !defined(__INTEL_COMPILER) && !defined(__clang__)
20/* GCC 4.8 and older misses various functions:
21 - vdupq_laneq_* family of functions
22 - vreinterpretq_f64_* family of functions
23 - vreinterpretq_*_f64 family of functions
24*/
25#error "The first supported GCC version for aarch64 NEON is 4.9"
26#endif
27
28#if (__GNUC__ == 4) && (__GNUC_MINOR__ <= 9) && !defined(__INTEL_COMPILER) && !defined(__clang__)
29#define vmul_f64(x, y) ((float64x1_t)( ((float64x1_t)(x)) * ((float64x1_t)(y)) ))
30#endif
31#endif
32
33#if SIMDPP_USE_AVX512F
34#if defined(__GNUC__) && (__GNUC__ < 6) && !defined(__INTEL_COMPILER) && !defined(__clang__)
35/* GCC 5.x and older have the following bugs:
36 - https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70059.
37 _mm512_inserti64x4(x, y, 0) and related intrinsics result in wrong code.
38 _mm512_castsi256_si512 is not available in GCC 4.9, thus there's no way
39 to convert between 256-bit and 512-bit vectors.
40 - Error: invalid register operand for `vpsrlw' when compiling shift code
41 on old binutils
42*/
43#error "The first supported GCC version for AVX512F is 6.0"
44#endif
45
46#if (!defined(__APPLE__) && ((__clang_major__ == 4) || (__clang_major__ == 5))) || \
47 (defined(__APPLE__) && (__clang_major__ == 9))
48// Internal compiler errors when trying to select wrong instruction for specific
49// combination of shuffles. Not possible to work around as shuffle detection is
50// quite clever.
51#error Clang 4.x-5.x is not supported on AVX512F due to compiler bugs.
52#endif
53#endif
54
55#if SIMDPP_USE_AVX512VL
56#if !defined(__APPLE__) && (__clang_major__ == 3)
57// clang 3.9 and older incorrectly compile reduce_{min,max} for int32 and uint32
58#error Clang 3.9 and older is not supported on AVX512VL due to compiler bugs.
59#endif
60#endif
61
62#if SIMDPP_USE_AVX || SIMDPP_USE_AVX2
63#if (__clang_major__ == 3) && (__clang_minor__ == 6)
64/* See https://llvm.org/bugs/show_bug.cgi?id=23441. Clang does not generate
65 correct floating-point code for basic 256-bit floating-point operations,
66 such as those resulting from _mm256_set_ps, _mm256_load_ps. Due to the
67 nature of affected operations, the bug is almost impossible to work around
68 reliably.
69*/
70#error AVX and AVX2 are not supported on clang 3.6 due to compiler bugs
71#endif
72#endif
73
74#if SIMDPP_USE_AVX
75#if (__GNUC__ == 4) && (__GNUC_MINOR__ == 4) && !defined(__INTEL_COMPILER) && !defined(__clang__)
76/* GCC emits "Error: operand size mismatch for `vmovq'" when compiling
77 256-bit shuffling intrinsics. No workaround has been found yet
78*/
79#error AVX is not supported in GCC 4.4 due to compiler bugs
80#endif
81#endif
82
83#if (__clang_major__ == 3) && (__clang_minor__ <= 4)
84#define SIMDPP_WORKAROUND_AVX2_SHIFT_INTRINSICS 1
85/* Clang 3.4 and older may crash when the following intrinsics are used with
86 arguments that are known at compile time: _mm256_sll_epi{16,32,64},
87 _mm256_srl_epi{16,32,64}, _mm256_sra_epi{16,32}
88*/
89#endif
90
91#if SIMDPP_USE_ALTIVEC
92#if defined(__GNUC__) && (__GNUC__ < 6) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ && \
93 !defined(__INTEL_COMPILER) && !defined(__clang__)
94// Internal compiler errors or wrong behaviour on various SIMD memory operations
95#error GCC 5.x and older not supported on PPC little-endian due to compiler bugs.
96#endif
97#endif
98
99#if SIMDPP_USE_VSX_206
100#if defined(__GNUC__) && (__GNUC__ < 6) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ && \
101 !defined(__INTEL_COMPILER) && !defined(__clang__)
102// Internal compiler errors or wrong behaviour on various SIMD memory operations
103#error GCC 5.x and older not supported on VSX big-endian due to compiler bugs.
104#endif
105#endif
106
107#if SIMDPP_USE_AVX512F && (__clang_major__ == 3)
108// Clang does not have _MM_CMPINT_* definitions up to Clang 4.0.
109#ifndef _MM_CMPINT_EQ
110#define _MM_CMPINT_EQ 0
111#endif
112#ifndef _MM_CMPINT_LT
113#define _MM_CMPINT_LT 1
114#endif
115#ifndef _MM_CMPINT_LE
116#define _MM_CMPINT_LE 2
117#endif
118#ifndef _MM_CMPINT_FALSE
119#define _MM_CMPINT_FALSE 3
120#endif
121#ifndef _MM_CMPINT_NEQ
122#define _MM_CMPINT_NEQ 4
123#endif
124#ifndef _MM_CMPINT_NLT
125#define _MM_CMPINT_NLT 5
126#endif
127#ifndef _MM_CMPINT_NLE
128#define _MM_CMPINT_NLE 6
129#endif
130#ifndef _MM_CMPINT_TRUE
131#define _MM_CMPINT_TRUE 7
132#endif
133#endif
134
135namespace simdpp {
136namespace SIMDPP_ARCH_NAMESPACE {
137namespace detail {
138
139template<unsigned V> struct make_constexpr { static const unsigned value = V; };
140
141} // namespace detail
142} // namespace SIMDPP_ARCH_NAMESPACE
143} // namespace simdpp
144
145#if __GNUC__
146#define SIMDPP_WORKAROUND_MAKE_CONSTEXPR(X) detail::make_constexpr<(X)>::value
147#else
148#define SIMDPP_WORKAROUND_MAKE_CONSTEXPR(X) (X)
149#endif
150
151#endif
152