29 #ifndef VC_COMMON_STORAGE_H_
30 #define VC_COMMON_STORAGE_H_
32 #include "aliasingentryhelper.h"
34 #include "maskentry.h"
36 #include "../avx/intrinsics.h"
40 namespace Vc_VERSIONED_NAMESPACE
47 template <
typename ValueType,
size_t Size>
struct IntrinsicType {
48 using type =
typename std::conditional<
49 std::is_integral<ValueType>::value,
50 typename std::conditional<sizeof(ValueType) * Size == 16, __m128i, __m256i>::type,
51 typename std::conditional<
52 std::is_same<ValueType, double>::value,
53 typename std::conditional<
sizeof(ValueType) * Size == 16, __m128d,
55 typename std::conditional<
sizeof(ValueType) * Size == 16, __m128,
56 __m256>::type>::type>::type;
58 #elif defined Vc_IMPL_SSE
59 template <
typename ValueType,
size_t Size>
struct IntrinsicType {
60 using type =
typename std::conditional<
61 std::is_integral<ValueType>::value, __m128i,
62 typename std::conditional<std::is_same<ValueType, double>::value, __m128d,
65 #elif defined Vc_IMPL_MIC
66 template <
typename ValueType,
size_t Size>
struct IntrinsicType {
67 using type =
typename std::conditional<
68 std::is_integral<ValueType>::value, __m512i,
69 typename std::conditional<std::is_same<ValueType, double>::value, __m512d,
73 template <
typename ValueType,
size_t Size>
struct IntrinsicType {
74 static_assert(Size == 1,
75 "IntrinsicType without SIMD target support may only have Size = 1");
76 using type = ValueType;
79 template <
typename ValueType,
size_t Size,
size_t Bytes = sizeof(ValueType) * Size>
83 typedef ValueType type;
85 #ifdef Vc_USE_BUILTIN_VECTOR_TYPES
86 #define Vc_VECBUILTIN __attribute__((__vector_size__(16)))
87 template <
size_t Size>
struct BuiltinType< double , Size, 16> {
typedef double type Vc_VECBUILTIN; };
88 template <
size_t Size>
struct BuiltinType< float , Size, 16> {
typedef float type Vc_VECBUILTIN; };
89 template <
size_t Size>
struct BuiltinType< long long, Size, 16> {
typedef long long type Vc_VECBUILTIN; };
90 template <
size_t Size>
struct BuiltinType<unsigned long long, Size, 16> {
typedef unsigned long long type Vc_VECBUILTIN; };
91 template <
size_t Size>
struct BuiltinType< long , Size, 16> {
typedef long type Vc_VECBUILTIN; };
92 template <
size_t Size>
struct BuiltinType<unsigned long , Size, 16> {
typedef unsigned long type Vc_VECBUILTIN; };
93 template <
size_t Size>
struct BuiltinType< int , Size, 16> {
typedef int type Vc_VECBUILTIN; };
94 template <
size_t Size>
struct BuiltinType<unsigned int , Size, 16> {
typedef unsigned int type Vc_VECBUILTIN; };
95 template <
size_t Size>
struct BuiltinType< short , Size, 16> {
typedef short type Vc_VECBUILTIN; };
96 template <
size_t Size>
struct BuiltinType<unsigned short , Size, 16> {
typedef unsigned short type Vc_VECBUILTIN; };
97 template <
size_t Size>
struct BuiltinType< char , Size, 16> {
typedef char type Vc_VECBUILTIN; };
98 template <
size_t Size>
struct BuiltinType<unsigned char , Size, 16> {
typedef unsigned char type Vc_VECBUILTIN; };
99 template <
size_t Size>
struct BuiltinType< signed char , Size, 16> {
typedef signed char type Vc_VECBUILTIN; };
101 #define Vc_VECBUILTIN __attribute__((__vector_size__(32)))
102 template <
size_t Size>
struct BuiltinType< double , Size, 32> {
typedef double type Vc_VECBUILTIN; };
103 template <
size_t Size>
struct BuiltinType< float , Size, 32> {
typedef float type Vc_VECBUILTIN; };
104 template <
size_t Size>
struct BuiltinType< long long, Size, 32> {
typedef long long type Vc_VECBUILTIN; };
105 template <
size_t Size>
struct BuiltinType<unsigned long long, Size, 32> {
typedef unsigned long long type Vc_VECBUILTIN; };
106 template <
size_t Size>
struct BuiltinType< long , Size, 32> {
typedef long type Vc_VECBUILTIN; };
107 template <
size_t Size>
struct BuiltinType<unsigned long , Size, 32> {
typedef unsigned long type Vc_VECBUILTIN; };
108 template <
size_t Size>
struct BuiltinType< int , Size, 32> {
typedef int type Vc_VECBUILTIN; };
109 template <
size_t Size>
struct BuiltinType<unsigned int , Size, 32> {
typedef unsigned int type Vc_VECBUILTIN; };
110 template <
size_t Size>
struct BuiltinType< short , Size, 32> {
typedef short type Vc_VECBUILTIN; };
111 template <
size_t Size>
struct BuiltinType<unsigned short , Size, 32> {
typedef unsigned short type Vc_VECBUILTIN; };
112 template <
size_t Size>
struct BuiltinType< char , Size, 32> {
typedef char type Vc_VECBUILTIN; };
113 template <
size_t Size>
struct BuiltinType<unsigned char , Size, 32> {
typedef unsigned char type Vc_VECBUILTIN; };
114 template <
size_t Size>
struct BuiltinType< signed char , Size, 32> {
typedef signed char type Vc_VECBUILTIN; };
119 template <
typename ValueType,
size_t Size>
120 using IntrinsicType =
typename Detail::IntrinsicType<ValueType, Size>::type;
122 template <
typename ValueType,
size_t Size>
123 using BuiltinType =
typename Detail::BuiltinType<ValueType, Size>::type;
125 namespace AliasStrategy
129 struct VectorBuiltin {};
130 struct UnionMembers {};
133 using DefaultStrategy =
134 #if defined Vc_USE_BUILTIN_VECTOR_TYPES
135 AliasStrategy::VectorBuiltin;
136 #elif defined Vc_MSVC
137 AliasStrategy::UnionMembers;
139 AliasStrategy::Union;
140 #elif defined __GNUC__
141 AliasStrategy::MayAlias;
143 AliasStrategy::Union;
146 template <
typename ValueType,
size_t Size,
typename Strategy = DefaultStrategy>
149 template <
typename ValueType,
size_t Size>
150 class Storage<ValueType, Size, AliasStrategy::Union>
152 static_assert(std::is_fundamental<ValueType>::value &&
153 std::is_arithmetic<ValueType>::value,
154 "Only works for fundamental arithmetic types.");
157 using VectorType = IntrinsicType<ValueType, Size>;
158 using EntryType = ValueType;
160 Vc_INTRINSIC Storage() : data() { assertCorrectAlignment(&data.v); }
161 Vc_INTRINSIC Storage(
const VectorType &x) : data(x)
163 assertCorrectAlignment(&data.v);
165 Vc_INTRINSIC Storage &operator=(
const VectorType &x)
171 Vc_INTRINSIC Storage(
const Storage &) =
default;
172 Vc_INTRINSIC Storage &operator=(
const Storage &) =
default;
174 Vc_INTRINSIC Vc_PURE VectorType &v() {
return data.v; }
175 Vc_INTRINSIC Vc_PURE
const VectorType &v()
const {
return data.v; }
177 Vc_INTRINSIC Vc_PURE EntryType m(
size_t i)
const {
return data.m[i]; }
178 Vc_INTRINSIC
void set(
size_t i, EntryType x) { data.m[i] = x; }
179 Vc_INTRINSIC Vc_PURE EntryType &ref(
size_t i) {
return data.m[i]; }
182 union VectorScalarUnion {
183 Vc_INTRINSIC VectorScalarUnion() : v() {}
184 Vc_INTRINSIC VectorScalarUnion(VectorType vv) : v(vv) {}
187 #pragma GCC diagnostic push
188 #pragma GCC diagnostic ignored "-Wpedantic"
192 #pragma GCC diagnostic pop
197 template <
typename ValueType,
size_t Size>
198 class Storage<ValueType, Size, AliasStrategy::MayAlias>
200 static_assert(std::is_fundamental<ValueType>::value &&
201 std::is_arithmetic<ValueType>::value,
202 "Only works for fundamental arithmetic types.");
205 using VectorType = IntrinsicType<ValueType, Size>;
206 using EntryType = ValueType;
208 Vc_INTRINSIC Storage() : data() { assertCorrectAlignment(&data); }
209 Vc_INTRINSIC Storage(
const VectorType &x) : data(x)
211 assertCorrectAlignment(&data);
213 Vc_INTRINSIC Storage &operator=(
const VectorType &x)
219 Vc_INTRINSIC Storage(
const Storage &) =
default;
220 Vc_INTRINSIC Storage &operator=(
const Storage &) =
default;
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 reinterpret_cast<const MayAlias<EntryType> *
>(&data)[i];
229 Vc_INTRINSIC
void set(
size_t i, EntryType x)
231 reinterpret_cast<MayAlias<EntryType> *
>(&data)[i] = x;
233 Vc_INTRINSIC Vc_PURE MayAlias<EntryType> &ref(
size_t i)
235 return reinterpret_cast<MayAlias<EntryType> *
>(&data)[i];
242 template <
typename ValueType,
size_t Size>
243 class Storage<ValueType, Size, AliasStrategy::VectorBuiltin>
245 static_assert(std::is_fundamental<ValueType>::value &&
246 std::is_arithmetic<ValueType>::value,
247 "Only works for fundamental arithmetic types.");
249 using Builtin = BuiltinType<ValueType, Size>;
252 using VectorType = IntrinsicType<ValueType, Size>;
253 using EntryType = ValueType;
255 Vc_INTRINSIC Storage() : data() { assertCorrectAlignment(&data); }
256 Vc_INTRINSIC Storage(
const VectorType &x)
257 : data(reinterpret_cast<const MayAlias<Builtin> &>(x))
259 assertCorrectAlignment(&data);
261 Vc_INTRINSIC Storage &operator=(
const VectorType &x)
263 data =
reinterpret_cast<const MayAlias<Builtin> &
>(x);
267 Vc_INTRINSIC Storage(
const Storage &) =
default;
268 Vc_INTRINSIC Storage &operator=(
const Storage &) =
default;
270 Vc_INTRINSIC Vc_PURE VectorType &v() {
return reinterpret_cast<VectorType &
>(data); }
271 Vc_INTRINSIC Vc_PURE
const VectorType &v()
const {
return reinterpret_cast<const VectorType &
>(data); }
273 Vc_INTRINSIC Vc_PURE EntryType m(
size_t i)
const {
return data[i]; }
274 Vc_INTRINSIC
void set(
size_t i, EntryType x) { data[i] = x; }
275 Vc_INTRINSIC Vc_PURE MayAlias<EntryType> &ref(
size_t i)
277 return reinterpret_cast<MayAlias<EntryType> *
>(&data)[i];
280 Vc_INTRINSIC Builtin &builtin() {
return data; }
281 Vc_INTRINSIC
const Builtin &builtin()
const {
return data; }
287 template <
typename ValueType,
size_t Size>
288 class Storage<ValueType, Size, AliasStrategy::UnionMembers>
290 static_assert(std::is_fundamental<ValueType>::value &&
291 std::is_arithmetic<ValueType>::value,
292 "Only works for fundamental arithmetic types.");
295 using VectorType = IntrinsicType<ValueType, Size>;
296 using EntryType = ValueType;
298 Vc_INTRINSIC Storage() : data() { assertCorrectAlignment(&data.v); }
299 Vc_INTRINSIC Storage(
const VectorType &x) : data(x)
301 assertCorrectAlignment(&data.v);
303 Vc_INTRINSIC Storage &operator=(
const VectorType &x)
309 Vc_INTRINSIC Storage(
const Storage &) =
default;
310 Vc_INTRINSIC Storage &operator=(
const Storage &) =
default;
312 Vc_INTRINSIC Vc_PURE VectorType &v() {
return data.v; }
313 Vc_INTRINSIC Vc_PURE
const VectorType &v()
const {
return data.v; }
315 Vc_INTRINSIC_L Vc_PURE_L EntryType m(
size_t i)
const Vc_INTRINSIC_R Vc_PURE_R;
316 Vc_INTRINSIC_L Vc_PURE_L EntryType &ref(
size_t i) Vc_INTRINSIC_R Vc_PURE_R;
317 Vc_INTRINSIC
void set(
size_t i, EntryType x) { ref(i) = x; }
324 template <> Vc_INTRINSIC Vc_PURE
double Storage< double, 2, AliasStrategy::UnionMembers>::m(
size_t i)
const {
return data.m128d_f64[i]; }
325 template <> Vc_INTRINSIC Vc_PURE
float Storage< float , 4, AliasStrategy::UnionMembers>::m(
size_t i)
const {
return data.m128_f32[i]; }
326 template <> Vc_INTRINSIC Vc_PURE
signed int Storage< signed int , 4, AliasStrategy::UnionMembers>::m(
size_t i)
const {
return data.m128i_i32[i]; }
327 template <> Vc_INTRINSIC Vc_PURE
signed short Storage< signed short , 8, AliasStrategy::UnionMembers>::m(
size_t i)
const {
return data.m128i_i16[i]; }
328 template <> Vc_INTRINSIC Vc_PURE
signed char Storage< signed char ,16, AliasStrategy::UnionMembers>::m(
size_t i)
const {
return data.m128i_i8[i]; }
329 template <> Vc_INTRINSIC Vc_PURE
unsigned int Storage<unsigned int , 4, AliasStrategy::UnionMembers>::m(
size_t i)
const {
return data.m128i_u32[i]; }
330 template <> Vc_INTRINSIC Vc_PURE
unsigned short Storage<unsigned short , 8, AliasStrategy::UnionMembers>::m(
size_t i)
const {
return data.m128i_u16[i]; }
331 template <> Vc_INTRINSIC Vc_PURE
unsigned char Storage<unsigned char ,16, AliasStrategy::UnionMembers>::m(
size_t i)
const {
return data.m128i_u8[i]; }
333 template <> Vc_INTRINSIC Vc_PURE
double &Storage< double, 2, AliasStrategy::UnionMembers>::ref(
size_t i) {
return data.m128d_f64[i]; }
334 template <> Vc_INTRINSIC Vc_PURE
float &Storage< float , 4, AliasStrategy::UnionMembers>::ref(
size_t i) {
return data.m128_f32[i]; }
335 template <> Vc_INTRINSIC Vc_PURE
signed int &Storage< signed int , 4, AliasStrategy::UnionMembers>::ref(
size_t i) {
return data.m128i_i32[i]; }
336 template <> Vc_INTRINSIC Vc_PURE
signed short &Storage< signed short , 8, AliasStrategy::UnionMembers>::ref(
size_t i) {
return data.m128i_i16[i]; }
337 template <> Vc_INTRINSIC Vc_PURE
signed char &Storage< signed char ,16, AliasStrategy::UnionMembers>::ref(
size_t i) {
return data.m128i_i8[i]; }
338 template <> Vc_INTRINSIC Vc_PURE
unsigned int &Storage<unsigned int , 4, AliasStrategy::UnionMembers>::ref(
size_t i) {
return data.m128i_u32[i]; }
339 template <> Vc_INTRINSIC Vc_PURE
unsigned short &Storage<unsigned short , 8, AliasStrategy::UnionMembers>::ref(
size_t i) {
return data.m128i_u16[i]; }
340 template <> Vc_INTRINSIC Vc_PURE
unsigned char &Storage<unsigned char ,16, AliasStrategy::UnionMembers>::ref(
size_t i) {
return data.m128i_u8[i]; }
343 template <> Vc_INTRINSIC Vc_PURE
double Storage< double, 4, AliasStrategy::UnionMembers>::m(
size_t i)
const {
return data.m256d_f64[i]; }
344 template <> Vc_INTRINSIC Vc_PURE
float Storage< float , 8, AliasStrategy::UnionMembers>::m(
size_t i)
const {
return data.m256_f32[i]; }
345 template <> Vc_INTRINSIC Vc_PURE
signed int Storage< signed int , 8, AliasStrategy::UnionMembers>::m(
size_t i)
const {
return data.m256i_i32[i]; }
346 template <> Vc_INTRINSIC Vc_PURE
signed short Storage< signed short ,16, AliasStrategy::UnionMembers>::m(
size_t i)
const {
return data.m256i_i16[i]; }
347 template <> Vc_INTRINSIC Vc_PURE
signed char Storage< signed char ,32, AliasStrategy::UnionMembers>::m(
size_t i)
const {
return data.m256i_i8[i]; }
348 template <> Vc_INTRINSIC Vc_PURE
unsigned int Storage<unsigned int , 8, AliasStrategy::UnionMembers>::m(
size_t i)
const {
return data.m256i_u32[i]; }
349 template <> Vc_INTRINSIC Vc_PURE
unsigned short Storage<unsigned short ,16, AliasStrategy::UnionMembers>::m(
size_t i)
const {
return data.m256i_u16[i]; }
350 template <> Vc_INTRINSIC Vc_PURE
unsigned char Storage<unsigned char ,32, AliasStrategy::UnionMembers>::m(
size_t i)
const {
return data.m256i_u8[i]; }
352 template <> Vc_INTRINSIC Vc_PURE
double &Storage< double, 4, AliasStrategy::UnionMembers>::ref(
size_t i) {
return data.m256d_f64[i]; }
353 template <> Vc_INTRINSIC Vc_PURE
float &Storage< float , 8, AliasStrategy::UnionMembers>::ref(
size_t i) {
return data.m256_f32[i]; }
354 template <> Vc_INTRINSIC Vc_PURE
signed int &Storage< signed int , 8, AliasStrategy::UnionMembers>::ref(
size_t i) {
return data.m256i_i32[i]; }
355 template <> Vc_INTRINSIC Vc_PURE
signed short &Storage< signed short ,16, AliasStrategy::UnionMembers>::ref(
size_t i) {
return data.m256i_i16[i]; }
356 template <> Vc_INTRINSIC Vc_PURE
signed char &Storage< signed char ,32, AliasStrategy::UnionMembers>::ref(
size_t i) {
return data.m256i_i8[i]; }
357 template <> Vc_INTRINSIC Vc_PURE
unsigned int &Storage<unsigned int , 8, AliasStrategy::UnionMembers>::ref(
size_t i) {
return data.m256i_u32[i]; }
358 template <> Vc_INTRINSIC Vc_PURE
unsigned short &Storage<unsigned short ,16, AliasStrategy::UnionMembers>::ref(
size_t i) {
return data.m256i_u16[i]; }
359 template <> Vc_INTRINSIC Vc_PURE
unsigned char &Storage<unsigned char ,32, AliasStrategy::UnionMembers>::ref(
size_t i) {
return data.m256i_u8[i]; }
363 template <
typename VectorType,
typename EntryType>
364 using VectorMemoryUnion = Storage<EntryType,
sizeof(VectorType) /
sizeof(EntryType)>;
369 #endif // VC_COMMON_STORAGE_H_