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 
135 namespace simdpp {
136 namespace SIMDPP_ARCH_NAMESPACE {
137 namespace detail {
138 
139 template<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