1 /* This file is part of the Vc library. {{{ 2 Copyright © 2018 Matthias Kretz <kretz@kde.org> 3 4 Redistribution and use in source and binary forms, with or without 5 modification, are permitted provided that the following conditions are met: 6 * Redistributions of source code must retain the above copyright 7 notice, this list of conditions and the following disclaimer. 8 * Redistributions in binary form must reproduce the above copyright 9 notice, this list of conditions and the following disclaimer in the 10 documentation and/or other materials provided with the distribution. 11 * Neither the names of contributing organizations nor the 12 names of its contributors may be used to endorse or promote products 13 derived from this software without specific prior written permission. 14 15 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 16 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY 19 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 26 }}}*/ 27 28 #ifndef VC_FWDDECL_H_ 29 #define VC_FWDDECL_H_ 30 31 #include <cstddef> // for std::size_t 32 33 #define Vc_VERSIONED_NAMESPACE Vc_1 34 35 namespace Vc_VERSIONED_NAMESPACE 36 { 37 namespace VectorAbi 38 { 39 struct Scalar {}; 40 struct Sse {}; 41 struct Avx {}; 42 struct Mic {}; 43 template <class T> struct DeduceCompatible; 44 template <class T> struct DeduceBest; 45 } // namespace VectorAbi 46 47 namespace Common 48 { 49 template <class T, std::size_t N> struct select_best_vector_type; 50 } // namespace Common 51 52 template <class T, class Abi> class Mask; 53 template <class T, class Abi> class Vector; 54 55 // === having SimdArray<T, N> in the Vc namespace leads to a ABI bug === 56 // 57 // SimdArray<double, 4> can be { double[4] }, { __m128d[2] }, or { __m256d } even though the type 58 // is the same. 59 // The question is, what should SimdArray focus on? 60 // a) A type that makes interfacing between different implementations possible? 61 // b) Or a type that makes fixed size SIMD easier and efficient? 62 // 63 // a) can be achieved by using a union with T[N] as one member. But this may have more serious 64 // performance implications than only less efficient parameter passing (because compilers have a 65 // much harder time wrt. aliasing issues). Also alignment would need to be set to the sizeof in 66 // order to be compatible with targets with larger alignment requirements. 67 // But, the in-memory representation of masks is not portable. Thus, at the latest with AVX-512, 68 // there would be a problem with requiring SimdMaskArray<T, N> to be an ABI compatible type. 69 // AVX-512 uses one bit per boolean, whereas SSE/AVX use sizeof(T) Bytes per boolean. Conversion 70 // between the two representations is not a trivial operation. Therefore choosing one or the other 71 // representation will have a considerable impact for the targets that do not use this 72 // representation. Since the future probably belongs to one bit per boolean representation, I would 73 // go with that choice. 74 // 75 // b) requires that SimdArray<T, N> != SimdArray<T, N> if 76 // SimdArray<T, N>::vector_type != SimdArray<T, N>::vector_type 77 // 78 // Therefore use SimdArray<T, N, V>, where V follows from the above. 79 template <class T, std::size_t N, 80 class V = typename Common::select_best_vector_type<T, N>::type, 81 std::size_t Wt = V::Size> 82 class SimdArray; 83 template <class T, std::size_t N, 84 class V = typename Common::select_best_vector_type<T, N>::type, 85 std::size_t Wt = V::Size> 86 class SimdMaskArray; 87 88 namespace simd_abi 89 { 90 using scalar = VectorAbi::Scalar; 91 template <int N> struct fixed_size; 92 template <class T> using compatible = typename VectorAbi::DeduceCompatible<T>::type; 93 template <class T> using native = typename VectorAbi::DeduceBest<T>::type; 94 using __sse = VectorAbi::Sse; 95 using __avx = VectorAbi::Avx; 96 struct __avx512; 97 struct __neon; 98 } // namespace simd_abi 99 100 template <class T, class Abi = simd_abi::compatible<T>> using simd = Vector<T, Abi>; 101 template <class T, class Abi = simd_abi::compatible<T>> using simd_mask = Mask<T, Abi>; 102 template <class T> using native_simd = simd<T, simd_abi::native<T>>; 103 template <class T> using native_simd_mask = simd_mask<T, simd_abi::native<T>>; 104 template <class T, int N> using fixed_size_simd = simd<T, simd_abi::fixed_size<N>>; 105 template <class T, int N> 106 using fixed_size_simd_mask = simd_mask<T, simd_abi::fixed_size<N>>; 107 108 } // namespace Vc_VERSIONED_NAMESPACE 109 110 #ifndef DOXYGEN 111 // doxygen has Vc_VERSIONED_NAMESPACE predefined to Vc 112 namespace Vc = Vc_VERSIONED_NAMESPACE; 113 #endif // DOXYGEN 114 115 #endif // VC_FWDDECL_H_ 116 117 // vim: foldmethod=marker 118