28 #ifndef VC_COMMON_STORAGE_H_
29 #define VC_COMMON_STORAGE_H_
31 #include "aliasingentryhelper.h"
35 #include "../avx/intrinsics.h"
39 namespace Vc_VERSIONED_NAMESPACE
43 template <
typename V>
inline V zero();
50 template <
typename ValueType,
size_t Size>
struct IntrinsicType {
51 using type =
typename std::conditional<
52 std::is_integral<ValueType>::value,
53 typename std::conditional<
sizeof(ValueType) * Size == 16, __m128i, __m256i>::type,
54 typename std::conditional<
55 std::is_same<ValueType, double>::value,
56 typename std::conditional<
sizeof(ValueType) * Size == 16, __m128d,
58 typename std::conditional<
sizeof(ValueType) * Size == 16, __m128,
59 __m256>::type>::type>::type;
61 #elif defined Vc_IMPL_SSE
62 template <
typename ValueType,
size_t Size>
struct IntrinsicType {
63 using type =
typename std::conditional<
64 std::is_integral<ValueType>::value, __m128i,
65 typename std::conditional<std::is_same<ValueType, double>::value, __m128d,
69 template <
typename ValueType,
size_t Size>
struct IntrinsicType {
70 static_assert(Size == 1,
71 "IntrinsicType without SIMD target support may only have Size = 1");
72 using type = ValueType;
75 template <
typename ValueType,
size_t Size,
size_t Bytes = sizeof(ValueType) * Size>
77 #ifdef Vc_USE_BUILTIN_VECTOR_TYPES
78 #define Vc_VECBUILTIN __attribute__((__vector_size__(16)))
79 template <
size_t Size>
struct BuiltinType< double , Size, 16> {
typedef double type Vc_VECBUILTIN; };
80 template <
size_t Size>
struct BuiltinType< float , Size, 16> {
typedef float type Vc_VECBUILTIN; };
81 template <
size_t Size>
struct BuiltinType< long long, Size, 16> {
typedef long long type Vc_VECBUILTIN; };
82 template <
size_t Size>
struct BuiltinType<unsigned long long, Size, 16> {
typedef unsigned long long type Vc_VECBUILTIN; };
83 template <
size_t Size>
struct BuiltinType< long , Size, 16> {
typedef long type Vc_VECBUILTIN; };
84 template <
size_t Size>
struct BuiltinType<unsigned long , Size, 16> {
typedef unsigned long type Vc_VECBUILTIN; };
85 template <
size_t Size>
struct BuiltinType< int , Size, 16> {
typedef int type Vc_VECBUILTIN; };
86 template <
size_t Size>
struct BuiltinType<unsigned int , Size, 16> {
typedef unsigned int type Vc_VECBUILTIN; };
87 template <
size_t Size>
struct BuiltinType< short , Size, 16> {
typedef short type Vc_VECBUILTIN; };
88 template <
size_t Size>
struct BuiltinType<unsigned short , Size, 16> {
typedef unsigned short type Vc_VECBUILTIN; };
89 template <
size_t Size>
struct BuiltinType< char , Size, 16> {
typedef char type Vc_VECBUILTIN; };
90 template <
size_t Size>
struct BuiltinType<unsigned char , Size, 16> {
typedef unsigned char type Vc_VECBUILTIN; };
91 template <
size_t Size>
struct BuiltinType< signed char , Size, 16> {
typedef signed char type Vc_VECBUILTIN; };
92 template <
size_t Size>
struct BuiltinType< bool , Size, 16> {
typedef unsigned char type Vc_VECBUILTIN; };
94 #define Vc_VECBUILTIN __attribute__((__vector_size__(32)))
95 template <
size_t Size>
struct BuiltinType< double , Size, 32> {
typedef double type Vc_VECBUILTIN; };
96 template <
size_t Size>
struct BuiltinType< float , Size, 32> {
typedef float type Vc_VECBUILTIN; };
97 template <
size_t Size>
struct BuiltinType< long long, Size, 32> {
typedef long long type Vc_VECBUILTIN; };
98 template <
size_t Size>
struct BuiltinType<unsigned long long, Size, 32> {
typedef unsigned long long type Vc_VECBUILTIN; };
99 template <
size_t Size>
struct BuiltinType< long , Size, 32> {
typedef long type Vc_VECBUILTIN; };
100 template <
size_t Size>
struct BuiltinType<unsigned long , Size, 32> {
typedef unsigned long type Vc_VECBUILTIN; };
101 template <
size_t Size>
struct BuiltinType< int , Size, 32> {
typedef int type Vc_VECBUILTIN; };
102 template <
size_t Size>
struct BuiltinType<unsigned int , Size, 32> {
typedef unsigned int type Vc_VECBUILTIN; };
103 template <
size_t Size>
struct BuiltinType< short , Size, 32> {
typedef short type Vc_VECBUILTIN; };
104 template <
size_t Size>
struct BuiltinType<unsigned short , Size, 32> {
typedef unsigned short type Vc_VECBUILTIN; };
105 template <
size_t Size>
struct BuiltinType< char , Size, 32> {
typedef char type Vc_VECBUILTIN; };
106 template <
size_t Size>
struct BuiltinType<unsigned char , Size, 32> {
typedef unsigned char type Vc_VECBUILTIN; };
107 template <
size_t Size>
struct BuiltinType< signed char , Size, 32> {
typedef signed char type Vc_VECBUILTIN; };
108 template <
size_t Size>
struct BuiltinType< bool , Size, 32> {
typedef unsigned char type Vc_VECBUILTIN; };
113 template <
typename ValueType,
size_t Size>
114 using IntrinsicType =
typename Detail::IntrinsicType<ValueType, Size>::type;
116 template <
typename ValueType,
size_t Size>
117 using BuiltinType =
typename Detail::BuiltinType<ValueType, Size>::type;
119 namespace AliasStrategy
123 struct VectorBuiltin {};
124 struct UnionMembers {};
127 using DefaultStrategy =
128 #if defined Vc_USE_BUILTIN_VECTOR_TYPES
129 AliasStrategy::VectorBuiltin;
130 #elif defined Vc_MSVC
131 AliasStrategy::UnionMembers;
133 AliasStrategy::Union;
134 #elif defined __GNUC__
135 AliasStrategy::MayAlias;
137 AliasStrategy::Union;
140 template <
typename ValueType,
size_t Size,
typename Strategy = DefaultStrategy>
144 template <
typename ValueType,
size_t Size>
145 class Storage<ValueType, Size, AliasStrategy::Union>
147 static_assert(std::is_fundamental<ValueType>::value &&
148 std::is_arithmetic<ValueType>::value,
149 "Only works for fundamental arithmetic types.");
152 using VectorType = IntrinsicType<ValueType, Size>;
153 using EntryType = ValueType;
156 Vc_INTRINSIC Alias(VectorType vv) : v(vv) {}
161 Vc_INTRINSIC Storage() : data(
Vc::Detail::zero<VectorType>()) {}
162 Vc_INTRINSIC Storage(
const VectorType &x) : data(x) { assertCorrectAlignment(&data); }
163 template <
typename U>
164 Vc_INTRINSIC
explicit Storage(
const U &x,
165 enable_if<
sizeof(U) ==
sizeof(VectorType)> = nullarg)
166 : data(reinterpret_cast<VectorType>(x))
168 assertCorrectAlignment(&data);
171 Vc_INTRINSIC Storage(
const Storage &) =
default;
172 Vc_INTRINSIC Storage &operator=(
const Storage &) =
default;
174 Vc_INTRINSIC
operator const VectorType &()
const {
return data; }
175 Vc_INTRINSIC Vc_PURE VectorType &v() {
return data; }
176 Vc_INTRINSIC Vc_PURE
const VectorType &v()
const {
return data; }
177 Vc_INTRINSIC Vc_PURE EntryType m(
size_t i)
const {
return Alias(data).m[i]; }
178 Vc_INTRINSIC
void set(
size_t i, EntryType x)
189 template <
typename ValueType,
size_t Size>
190 class Storage<ValueType, Size, AliasStrategy::MayAlias>
192 static_assert(std::is_fundamental<ValueType>::value &&
193 std::is_arithmetic<ValueType>::value,
194 "Only works for fundamental arithmetic types.");
197 using VectorType = IntrinsicType<ValueType, Size>;
198 using EntryType = ValueType;
200 Vc_INTRINSIC Storage() : data() { assertCorrectAlignment(&data); }
201 Vc_INTRINSIC Storage(
const VectorType &x) : data(x)
203 assertCorrectAlignment(&data);
205 template <
typename U>
206 Vc_INTRINSIC
explicit Storage(
const U &x,
207 enable_if<
sizeof(U) ==
sizeof(VectorType)> = nullarg)
208 : data(reinterpret_cast<const VectorType &>(x))
210 assertCorrectAlignment(&data);
212 Vc_INTRINSIC Storage &operator=(
const VectorType &x)
218 Vc_INTRINSIC Storage(
const Storage &) =
default;
219 Vc_INTRINSIC Storage &operator=(
const Storage &) =
default;
221 Vc_INTRINSIC
operator const VectorType &()
const {
return v(); }
222 Vc_INTRINSIC Vc_PURE VectorType &v() {
return data; }
223 Vc_INTRINSIC Vc_PURE
const VectorType &v()
const {
return data; }
225 Vc_INTRINSIC Vc_PURE EntryType m(
size_t i)
const
227 return aliasing_cast<EntryType>(&data)[i];
229 Vc_INTRINSIC
void set(
size_t i, EntryType x)
231 aliasing_cast<EntryType>(&data)[i] = x;
238 template <
typename ValueType,
size_t Size>
239 class Storage<ValueType, Size, AliasStrategy::VectorBuiltin>
241 static_assert(std::is_fundamental<ValueType>::value &&
242 std::is_arithmetic<ValueType>::value,
243 "Only works for fundamental arithmetic types.");
245 using Builtin = BuiltinType<ValueType, Size>;
249 #ifdef Vc_TEMPLATES_DROP_ATTRIBUTES
250 MayAlias<IntrinsicType<ValueType, Size>>;
252 IntrinsicType<ValueType, Size>;
254 using EntryType = ValueType;
256 Vc_INTRINSIC Storage() : data() { assertCorrectAlignment(&data); }
257 Vc_INTRINSIC Storage(
const Storage &) =
default;
258 Vc_INTRINSIC Storage &operator=(
const Storage &) =
default;
260 Vc_INTRINSIC Storage(
const VectorType &x)
261 : data(aliasing_cast<Builtin>(x))
263 assertCorrectAlignment(&data);
265 template <
typename U>
266 Vc_INTRINSIC
explicit Storage(
const U &x,
267 enable_if<
sizeof(U) ==
sizeof(VectorType)> = nullarg)
268 : data(aliasing_cast<Builtin>(x))
270 assertCorrectAlignment(&data);
272 Vc_INTRINSIC Storage &operator=(
const VectorType &x)
274 data = aliasing_cast<Builtin>(x);
278 Vc_INTRINSIC
operator const VectorType &()
const {
return v(); }
279 Vc_INTRINSIC Vc_PURE VectorType &v() {
return reinterpret_cast<VectorType &
>(data); }
280 Vc_INTRINSIC Vc_PURE
const VectorType &v()
const {
return reinterpret_cast<const VectorType &
>(data); }
282 Vc_INTRINSIC Vc_PURE EntryType m(
size_t i)
const {
return data[i]; }
283 Vc_INTRINSIC
void set(
size_t i, EntryType x) { data[i] = x; }
285 Vc_INTRINSIC Builtin &builtin() {
return data; }
286 Vc_INTRINSIC
const Builtin &builtin()
const {
return data; }
292 template <
typename ValueType,
size_t Size>
293 class Storage<ValueType, Size, AliasStrategy::UnionMembers>
295 static_assert(std::is_fundamental<ValueType>::value &&
296 std::is_arithmetic<ValueType>::value,
297 "Only works for fundamental arithmetic types.");
300 using VectorType = IntrinsicType<ValueType, Size>;
301 using EntryType = ValueType;
303 Vc_INTRINSIC Storage() : data() { assertCorrectAlignment(&data); }
304 Vc_INTRINSIC Storage(
const VectorType &x) : data(x)
306 assertCorrectAlignment(&data);
308 template <
typename U>
309 Vc_INTRINSIC
explicit Storage(
const U &x,
310 enable_if<
sizeof(U) ==
sizeof(VectorType)> = nullarg)
311 : data(reinterpret_cast<const VectorType &>(x))
313 assertCorrectAlignment(&data);
315 Vc_INTRINSIC Storage &operator=(
const VectorType &x)
321 Vc_INTRINSIC Storage(
const Storage &) =
default;
322 Vc_INTRINSIC Storage &operator=(
const Storage &) =
default;
324 Vc_INTRINSIC Vc_PURE VectorType &v() {
return data; }
325 Vc_INTRINSIC Vc_PURE
const VectorType &v()
const {
return data; }
327 Vc_INTRINSIC_L Vc_PURE_L EntryType m(
size_t i)
const Vc_INTRINSIC_R Vc_PURE_R;
328 Vc_INTRINSIC
void set(
size_t i, EntryType x) { ref(i) = x; }
331 Vc_INTRINSIC_L Vc_PURE_L EntryType &ref(
size_t i) Vc_INTRINSIC_R Vc_PURE_R;
336 template <> Vc_INTRINSIC Vc_PURE
double Storage< double, 2, AliasStrategy::UnionMembers>::m(
size_t i)
const {
return data.m128d_f64[i]; }
337 template <> Vc_INTRINSIC Vc_PURE
float Storage< float , 4, AliasStrategy::UnionMembers>::m(
size_t i)
const {
return data.m128_f32[i]; }
338 template <> Vc_INTRINSIC Vc_PURE
signed int Storage< signed int , 4, AliasStrategy::UnionMembers>::m(
size_t i)
const {
return data.m128i_i32[i]; }
339 template <> Vc_INTRINSIC Vc_PURE
signed short Storage< signed short , 8, AliasStrategy::UnionMembers>::m(
size_t i)
const {
return data.m128i_i16[i]; }
340 template <> Vc_INTRINSIC Vc_PURE
signed char Storage< signed char ,16, AliasStrategy::UnionMembers>::m(
size_t i)
const {
return data.m128i_i8[i]; }
341 template <> Vc_INTRINSIC Vc_PURE
unsigned int Storage<unsigned int , 4, AliasStrategy::UnionMembers>::m(
size_t i)
const {
return data.m128i_u32[i]; }
342 template <> Vc_INTRINSIC Vc_PURE
unsigned short Storage<unsigned short , 8, AliasStrategy::UnionMembers>::m(
size_t i)
const {
return data.m128i_u16[i]; }
343 template <> Vc_INTRINSIC Vc_PURE
unsigned char Storage<unsigned char ,16, AliasStrategy::UnionMembers>::m(
size_t i)
const {
return data.m128i_u8[i]; }
345 template <> Vc_INTRINSIC Vc_PURE
double &Storage< double, 2, AliasStrategy::UnionMembers>::ref(
size_t i) {
return data.m128d_f64[i]; }
346 template <> Vc_INTRINSIC Vc_PURE
float &Storage< float , 4, AliasStrategy::UnionMembers>::ref(
size_t i) {
return data.m128_f32[i]; }
347 template <> Vc_INTRINSIC Vc_PURE
signed int &Storage< signed int , 4, AliasStrategy::UnionMembers>::ref(
size_t i) {
return data.m128i_i32[i]; }
348 template <> Vc_INTRINSIC Vc_PURE
signed short &Storage< signed short , 8, AliasStrategy::UnionMembers>::ref(
size_t i) {
return data.m128i_i16[i]; }
349 template <> Vc_INTRINSIC Vc_PURE
signed char &Storage< signed char ,16, AliasStrategy::UnionMembers>::ref(
size_t i) {
return reinterpret_cast<signed char &
>(data.m128i_i8[i]); }
350 template <> Vc_INTRINSIC Vc_PURE
unsigned int &Storage<unsigned int , 4, AliasStrategy::UnionMembers>::ref(
size_t i) {
return data.m128i_u32[i]; }
351 template <> Vc_INTRINSIC Vc_PURE
unsigned short &Storage<unsigned short , 8, AliasStrategy::UnionMembers>::ref(
size_t i) {
return data.m128i_u16[i]; }
352 template <> Vc_INTRINSIC Vc_PURE
unsigned char &Storage<unsigned char ,16, AliasStrategy::UnionMembers>::ref(
size_t i) {
return data.m128i_u8[i]; }
355 template <> Vc_INTRINSIC Vc_PURE
double Storage< double, 4, AliasStrategy::UnionMembers>::m(
size_t i)
const {
return data.m256d_f64[i]; }
356 template <> Vc_INTRINSIC Vc_PURE
float Storage< float , 8, AliasStrategy::UnionMembers>::m(
size_t i)
const {
return data.m256_f32[i]; }
357 template <> Vc_INTRINSIC Vc_PURE
signed int Storage< signed int , 8, AliasStrategy::UnionMembers>::m(
size_t i)
const {
return data.m256i_i32[i]; }
358 template <> Vc_INTRINSIC Vc_PURE
signed short Storage< signed short ,16, AliasStrategy::UnionMembers>::m(
size_t i)
const {
return data.m256i_i16[i]; }
359 template <> Vc_INTRINSIC Vc_PURE
signed char Storage< signed char ,32, AliasStrategy::UnionMembers>::m(
size_t i)
const {
return data.m256i_i8[i]; }
360 template <> Vc_INTRINSIC Vc_PURE
unsigned int Storage<unsigned int , 8, AliasStrategy::UnionMembers>::m(
size_t i)
const {
return data.m256i_u32[i]; }
361 template <> Vc_INTRINSIC Vc_PURE
unsigned short Storage<unsigned short ,16, AliasStrategy::UnionMembers>::m(
size_t i)
const {
return data.m256i_u16[i]; }
362 template <> Vc_INTRINSIC Vc_PURE
unsigned char Storage<unsigned char ,32, AliasStrategy::UnionMembers>::m(
size_t i)
const {
return data.m256i_u8[i]; }
364 template <> Vc_INTRINSIC Vc_PURE
double &Storage< double, 4, AliasStrategy::UnionMembers>::ref(
size_t i) {
return data.m256d_f64[i]; }
365 template <> Vc_INTRINSIC Vc_PURE
float &Storage< float , 8, AliasStrategy::UnionMembers>::ref(
size_t i) {
return data.m256_f32[i]; }
366 template <> Vc_INTRINSIC Vc_PURE
signed int &Storage< signed int , 8, AliasStrategy::UnionMembers>::ref(
size_t i) {
return data.m256i_i32[i]; }
367 template <> Vc_INTRINSIC Vc_PURE
signed short &Storage< signed short ,16, AliasStrategy::UnionMembers>::ref(
size_t i) {
return data.m256i_i16[i]; }
368 template <> Vc_INTRINSIC Vc_PURE
signed char &Storage< signed char ,32, AliasStrategy::UnionMembers>::ref(
size_t i) {
return reinterpret_cast<signed char &
>(data.m256i_i8[i]); }
369 template <> Vc_INTRINSIC Vc_PURE
unsigned int &Storage<unsigned int , 8, AliasStrategy::UnionMembers>::ref(
size_t i) {
return data.m256i_u32[i]; }
370 template <> Vc_INTRINSIC Vc_PURE
unsigned short &Storage<unsigned short ,16, AliasStrategy::UnionMembers>::ref(
size_t i) {
return data.m256i_u16[i]; }
371 template <> Vc_INTRINSIC Vc_PURE
unsigned char &Storage<unsigned char ,32, AliasStrategy::UnionMembers>::ref(
size_t i) {
return data.m256i_u8[i]; }
375 template <
typename VectorType,
typename EntryType>
376 using VectorMemoryUnion = Storage<EntryType,
sizeof(VectorType) /
sizeof(EntryType)>;
381 #endif // VC_COMMON_STORAGE_H_