File indexing completed on 2025-01-30 10:25:51
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028 #ifndef VC_COMMON_STORAGE_H_
0029 #define VC_COMMON_STORAGE_H_
0030
0031 #include "aliasingentryhelper.h"
0032 #include "types.h"
0033 #include "maskbool.h"
0034 #ifdef Vc_IMPL_AVX
0035 #include "../avx/intrinsics.h"
0036 #endif
0037 #include "macros.h"
0038
0039 namespace Vc_VERSIONED_NAMESPACE
0040 {
0041 namespace Detail
0042 {
0043 template <typename V> inline V zero();
0044 }
0045 namespace Common
0046 {
0047 namespace Detail
0048 {
0049 #ifdef Vc_IMPL_AVX
0050 template <typename ValueType, size_t Size> struct IntrinsicType {
0051 using type = typename std::conditional<
0052 std::is_integral<ValueType>::value,
0053 typename std::conditional<sizeof(ValueType) * Size == 16, __m128i, __m256i>::type,
0054 typename std::conditional<
0055 std::is_same<ValueType, double>::value,
0056 typename std::conditional<sizeof(ValueType) * Size == 16, __m128d,
0057 __m256d>::type,
0058 typename std::conditional<sizeof(ValueType) * Size == 16, __m128,
0059 __m256>::type>::type>::type;
0060 };
0061 #elif defined Vc_IMPL_SSE
0062 template <typename ValueType, size_t Size> struct IntrinsicType {
0063 using type = typename std::conditional<
0064 std::is_integral<ValueType>::value, __m128i,
0065 typename std::conditional<std::is_same<ValueType, double>::value, __m128d,
0066 __m128>::type>::type;
0067 };
0068 #else
0069 template <typename ValueType, size_t Size> struct IntrinsicType {
0070 static_assert(Size == 1,
0071 "IntrinsicType without SIMD target support may only have Size = 1");
0072 using type = ValueType;
0073 };
0074 #endif
0075 template <typename ValueType, size_t Size, size_t Bytes = sizeof(ValueType) * Size>
0076 struct BuiltinType;
0077 #ifdef Vc_USE_BUILTIN_VECTOR_TYPES
0078 #define Vc_VECBUILTIN __attribute__((__vector_size__(16)))
0079 template <size_t Size> struct BuiltinType< double , Size, 16> { typedef double type Vc_VECBUILTIN; };
0080 template <size_t Size> struct BuiltinType< float , Size, 16> { typedef float type Vc_VECBUILTIN; };
0081 template <size_t Size> struct BuiltinType< long long, Size, 16> { typedef long long type Vc_VECBUILTIN; };
0082 template <size_t Size> struct BuiltinType<unsigned long long, Size, 16> { typedef unsigned long long type Vc_VECBUILTIN; };
0083 template <size_t Size> struct BuiltinType< long , Size, 16> { typedef long type Vc_VECBUILTIN; };
0084 template <size_t Size> struct BuiltinType<unsigned long , Size, 16> { typedef unsigned long type Vc_VECBUILTIN; };
0085 template <size_t Size> struct BuiltinType< int , Size, 16> { typedef int type Vc_VECBUILTIN; };
0086 template <size_t Size> struct BuiltinType<unsigned int , Size, 16> { typedef unsigned int type Vc_VECBUILTIN; };
0087 template <size_t Size> struct BuiltinType< short , Size, 16> { typedef short type Vc_VECBUILTIN; };
0088 template <size_t Size> struct BuiltinType<unsigned short , Size, 16> { typedef unsigned short type Vc_VECBUILTIN; };
0089 template <size_t Size> struct BuiltinType< char , Size, 16> { typedef char type Vc_VECBUILTIN; };
0090 template <size_t Size> struct BuiltinType<unsigned char , Size, 16> { typedef unsigned char type Vc_VECBUILTIN; };
0091 template <size_t Size> struct BuiltinType< signed char , Size, 16> { typedef signed char type Vc_VECBUILTIN; };
0092 template <size_t Size> struct BuiltinType< bool , Size, 16> { typedef unsigned char type Vc_VECBUILTIN; };
0093 #undef Vc_VECBUILTIN
0094 #define Vc_VECBUILTIN __attribute__((__vector_size__(32)))
0095 template <size_t Size> struct BuiltinType< double , Size, 32> { typedef double type Vc_VECBUILTIN; };
0096 template <size_t Size> struct BuiltinType< float , Size, 32> { typedef float type Vc_VECBUILTIN; };
0097 template <size_t Size> struct BuiltinType< long long, Size, 32> { typedef long long type Vc_VECBUILTIN; };
0098 template <size_t Size> struct BuiltinType<unsigned long long, Size, 32> { typedef unsigned long long type Vc_VECBUILTIN; };
0099 template <size_t Size> struct BuiltinType< long , Size, 32> { typedef long type Vc_VECBUILTIN; };
0100 template <size_t Size> struct BuiltinType<unsigned long , Size, 32> { typedef unsigned long type Vc_VECBUILTIN; };
0101 template <size_t Size> struct BuiltinType< int , Size, 32> { typedef int type Vc_VECBUILTIN; };
0102 template <size_t Size> struct BuiltinType<unsigned int , Size, 32> { typedef unsigned int type Vc_VECBUILTIN; };
0103 template <size_t Size> struct BuiltinType< short , Size, 32> { typedef short type Vc_VECBUILTIN; };
0104 template <size_t Size> struct BuiltinType<unsigned short , Size, 32> { typedef unsigned short type Vc_VECBUILTIN; };
0105 template <size_t Size> struct BuiltinType< char , Size, 32> { typedef char type Vc_VECBUILTIN; };
0106 template <size_t Size> struct BuiltinType<unsigned char , Size, 32> { typedef unsigned char type Vc_VECBUILTIN; };
0107 template <size_t Size> struct BuiltinType< signed char , Size, 32> { typedef signed char type Vc_VECBUILTIN; };
0108 template <size_t Size> struct BuiltinType< bool , Size, 32> { typedef unsigned char type Vc_VECBUILTIN; };
0109 #undef Vc_VECBUILTIN
0110 #endif
0111 }
0112
0113 template <typename ValueType, size_t Size>
0114 using IntrinsicType = typename Detail::IntrinsicType<ValueType, Size>::type;
0115
0116 template <typename ValueType, size_t Size>
0117 using BuiltinType = typename Detail::BuiltinType<ValueType, Size>::type;
0118
0119 namespace AliasStrategy
0120 {
0121 struct Union {};
0122 struct MayAlias {};
0123 struct VectorBuiltin {};
0124 struct UnionMembers {};
0125 }
0126
0127 using DefaultStrategy =
0128 #if defined Vc_USE_BUILTIN_VECTOR_TYPES
0129 AliasStrategy::VectorBuiltin;
0130 #elif defined Vc_MSVC
0131 AliasStrategy::UnionMembers;
0132 #elif defined Vc_ICC
0133 AliasStrategy::Union;
0134 #elif defined __GNUC__
0135 AliasStrategy::MayAlias;
0136 #else
0137 AliasStrategy::Union;
0138 #endif
0139
0140 template <typename ValueType, size_t Size, typename Strategy = DefaultStrategy>
0141 class Storage;
0142
0143
0144 template <typename ValueType, size_t Size>
0145 class Storage<ValueType, Size, AliasStrategy::Union>
0146 {
0147 static_assert(std::is_fundamental<ValueType>::value &&
0148 std::is_arithmetic<ValueType>::value,
0149 "Only works for fundamental arithmetic types.");
0150
0151 public:
0152 using VectorType = IntrinsicType<ValueType, Size>;
0153 using EntryType = ValueType;
0154
0155 union Alias {
0156 Vc_INTRINSIC Alias(VectorType vv) : v(vv) {}
0157 VectorType v;
0158 EntryType m[Size];
0159 };
0160
0161 Vc_INTRINSIC Storage() : data(Vc::Detail::zero<VectorType>()) {}
0162 Vc_INTRINSIC Storage(const VectorType &x) : data(x) { assertCorrectAlignment(&data); }
0163 template <typename U>
0164 Vc_INTRINSIC explicit Storage(const U &x,
0165 enable_if<sizeof(U) == sizeof(VectorType)> = nullarg)
0166 : data(reinterpret_cast<VectorType>(x))
0167 {
0168 assertCorrectAlignment(&data);
0169 }
0170
0171 Vc_INTRINSIC Storage(const Storage &) = default;
0172 Vc_INTRINSIC Storage &operator=(const Storage &) = default;
0173
0174 Vc_INTRINSIC operator const VectorType &() const { return data; }
0175 Vc_INTRINSIC Vc_PURE VectorType &v() { return data; }
0176 Vc_INTRINSIC Vc_PURE const VectorType &v() const { return data; }
0177 Vc_INTRINSIC Vc_PURE EntryType m(size_t i) const { return Alias(data).m[i]; }
0178 Vc_INTRINSIC void set(size_t i, EntryType x)
0179 {
0180 Alias a(data);
0181 a.m[i] = x;
0182 data = a.v;
0183 }
0184
0185 private:
0186 VectorType data;
0187 };
0188
0189 template <typename ValueType, size_t Size>
0190 class Storage<ValueType, Size, AliasStrategy::MayAlias>
0191 {
0192 static_assert(std::is_fundamental<ValueType>::value &&
0193 std::is_arithmetic<ValueType>::value,
0194 "Only works for fundamental arithmetic types.");
0195
0196 public:
0197 using VectorType = IntrinsicType<ValueType, Size>;
0198 using EntryType = ValueType;
0199
0200 Vc_INTRINSIC Storage() : data() { assertCorrectAlignment(&data); }
0201 Vc_INTRINSIC Storage(const VectorType &x) : data(x)
0202 {
0203 assertCorrectAlignment(&data);
0204 }
0205 template <typename U>
0206 Vc_INTRINSIC explicit Storage(const U &x,
0207 enable_if<sizeof(U) == sizeof(VectorType)> = nullarg)
0208 : data(reinterpret_cast<const VectorType &>(x))
0209 {
0210 assertCorrectAlignment(&data);
0211 }
0212 Vc_INTRINSIC Storage &operator=(const VectorType &x)
0213 {
0214 data = x;
0215 return *this;
0216 }
0217
0218 Vc_INTRINSIC Storage(const Storage &) = default;
0219 Vc_INTRINSIC Storage &operator=(const Storage &) = default;
0220
0221 Vc_INTRINSIC operator const VectorType &() const { return v(); }
0222 Vc_INTRINSIC Vc_PURE VectorType &v() { return data; }
0223 Vc_INTRINSIC Vc_PURE const VectorType &v() const { return data; }
0224
0225 Vc_INTRINSIC Vc_PURE EntryType m(size_t i) const
0226 {
0227 return aliasing_cast<EntryType>(&data)[i];
0228 }
0229 Vc_INTRINSIC void set(size_t i, EntryType x)
0230 {
0231 aliasing_cast<EntryType>(&data)[i] = x;
0232 }
0233
0234 private:
0235 VectorType data;
0236 };
0237
0238 template <typename ValueType, size_t Size>
0239 class Storage<ValueType, Size, AliasStrategy::VectorBuiltin>
0240 {
0241 static_assert(std::is_fundamental<ValueType>::value &&
0242 std::is_arithmetic<ValueType>::value,
0243 "Only works for fundamental arithmetic types.");
0244
0245 using Builtin = BuiltinType<ValueType, Size>;
0246
0247 public:
0248 using VectorType =
0249 #ifdef Vc_TEMPLATES_DROP_ATTRIBUTES
0250 MayAlias<IntrinsicType<ValueType, Size>>;
0251 #else
0252 IntrinsicType<ValueType, Size>;
0253 #endif
0254 using EntryType = ValueType;
0255
0256 Vc_INTRINSIC Storage() : data() { assertCorrectAlignment(&data); }
0257 Vc_INTRINSIC Storage(const Storage &) = default;
0258 Vc_INTRINSIC Storage &operator=(const Storage &) = default;
0259
0260 Vc_INTRINSIC Storage(const VectorType &x)
0261 : data(aliasing_cast<Builtin>(x))
0262 {
0263 assertCorrectAlignment(&data);
0264 }
0265 template <typename U>
0266 Vc_INTRINSIC explicit Storage(const U &x,
0267 enable_if<sizeof(U) == sizeof(VectorType)> = nullarg)
0268 : data(aliasing_cast<Builtin>(x))
0269 {
0270 assertCorrectAlignment(&data);
0271 }
0272 Vc_INTRINSIC Storage &operator=(const VectorType &x)
0273 {
0274 data = aliasing_cast<Builtin>(x);
0275 return *this;
0276 }
0277
0278 Vc_INTRINSIC operator const VectorType &() const { return v(); }
0279 Vc_INTRINSIC Vc_PURE VectorType &v() { return reinterpret_cast<VectorType &>(data); }
0280 Vc_INTRINSIC Vc_PURE const VectorType &v() const { return reinterpret_cast<const VectorType &>(data); }
0281
0282 Vc_INTRINSIC Vc_PURE EntryType m(size_t i) const { return data[i]; }
0283 Vc_INTRINSIC void set(size_t i, EntryType x) { data[i] = x; }
0284
0285 Vc_INTRINSIC Builtin &builtin() { return data; }
0286 Vc_INTRINSIC const Builtin &builtin() const { return data; }
0287
0288 private:
0289 Builtin data;
0290 };
0291
0292 template <typename ValueType, size_t Size>
0293 class Storage<ValueType, Size, AliasStrategy::UnionMembers>
0294 {
0295 static_assert(std::is_fundamental<ValueType>::value &&
0296 std::is_arithmetic<ValueType>::value,
0297 "Only works for fundamental arithmetic types.");
0298
0299 public:
0300 using VectorType = IntrinsicType<ValueType, Size>;
0301 using EntryType = ValueType;
0302
0303 Vc_INTRINSIC Storage() : data() { assertCorrectAlignment(&data); }
0304 Vc_INTRINSIC Storage(const VectorType &x) : data(x)
0305 {
0306 assertCorrectAlignment(&data);
0307 }
0308 template <typename U>
0309 Vc_INTRINSIC explicit Storage(const U &x,
0310 enable_if<sizeof(U) == sizeof(VectorType)> = nullarg)
0311 : data(reinterpret_cast<const VectorType &>(x))
0312 {
0313 assertCorrectAlignment(&data);
0314 }
0315 Vc_INTRINSIC Storage &operator=(const VectorType &x)
0316 {
0317 data = x;
0318 return *this;
0319 }
0320
0321 Vc_INTRINSIC Storage(const Storage &) = default;
0322 Vc_INTRINSIC Storage &operator=(const Storage &) = default;
0323
0324 Vc_INTRINSIC Vc_PURE VectorType &v() { return data; }
0325 Vc_INTRINSIC Vc_PURE const VectorType &v() const { return data; }
0326
0327 Vc_INTRINSIC_L Vc_PURE_L EntryType m(size_t i) const Vc_INTRINSIC_R Vc_PURE_R;
0328 Vc_INTRINSIC void set(size_t i, EntryType x) { ref(i) = x; }
0329
0330 private:
0331 Vc_INTRINSIC_L Vc_PURE_L EntryType &ref(size_t i) Vc_INTRINSIC_R Vc_PURE_R;
0332 VectorType data;
0333 };
0334
0335 #ifdef Vc_MSVC
0336 template <> Vc_INTRINSIC Vc_PURE double Storage< double, 2, AliasStrategy::UnionMembers>::m(size_t i) const { return data.m128d_f64[i]; }
0337 template <> Vc_INTRINSIC Vc_PURE float Storage< float , 4, AliasStrategy::UnionMembers>::m(size_t i) const { return data.m128_f32[i]; }
0338 template <> Vc_INTRINSIC Vc_PURE signed int Storage< signed int , 4, AliasStrategy::UnionMembers>::m(size_t i) const { return data.m128i_i32[i]; }
0339 template <> Vc_INTRINSIC Vc_PURE signed short Storage< signed short , 8, AliasStrategy::UnionMembers>::m(size_t i) const { return data.m128i_i16[i]; }
0340 template <> Vc_INTRINSIC Vc_PURE signed char Storage< signed char ,16, AliasStrategy::UnionMembers>::m(size_t i) const { return data.m128i_i8[i]; }
0341 template <> Vc_INTRINSIC Vc_PURE unsigned int Storage<unsigned int , 4, AliasStrategy::UnionMembers>::m(size_t i) const { return data.m128i_u32[i]; }
0342 template <> Vc_INTRINSIC Vc_PURE unsigned short Storage<unsigned short , 8, AliasStrategy::UnionMembers>::m(size_t i) const { return data.m128i_u16[i]; }
0343 template <> Vc_INTRINSIC Vc_PURE unsigned char Storage<unsigned char ,16, AliasStrategy::UnionMembers>::m(size_t i) const { return data.m128i_u8[i]; }
0344
0345 template <> Vc_INTRINSIC Vc_PURE double &Storage< double, 2, AliasStrategy::UnionMembers>::ref(size_t i) { return data.m128d_f64[i]; }
0346 template <> Vc_INTRINSIC Vc_PURE float &Storage< float , 4, AliasStrategy::UnionMembers>::ref(size_t i) { return data.m128_f32[i]; }
0347 template <> Vc_INTRINSIC Vc_PURE signed int &Storage< signed int , 4, AliasStrategy::UnionMembers>::ref(size_t i) { return data.m128i_i32[i]; }
0348 template <> Vc_INTRINSIC Vc_PURE signed short &Storage< signed short , 8, AliasStrategy::UnionMembers>::ref(size_t i) { return data.m128i_i16[i]; }
0349 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]); }
0350 template <> Vc_INTRINSIC Vc_PURE unsigned int &Storage<unsigned int , 4, AliasStrategy::UnionMembers>::ref(size_t i) { return data.m128i_u32[i]; }
0351 template <> Vc_INTRINSIC Vc_PURE unsigned short &Storage<unsigned short , 8, AliasStrategy::UnionMembers>::ref(size_t i) { return data.m128i_u16[i]; }
0352 template <> Vc_INTRINSIC Vc_PURE unsigned char &Storage<unsigned char ,16, AliasStrategy::UnionMembers>::ref(size_t i) { return data.m128i_u8[i]; }
0353
0354 #ifdef Vc_IMPL_AVX
0355 template <> Vc_INTRINSIC Vc_PURE double Storage< double, 4, AliasStrategy::UnionMembers>::m(size_t i) const { return data.m256d_f64[i]; }
0356 template <> Vc_INTRINSIC Vc_PURE float Storage< float , 8, AliasStrategy::UnionMembers>::m(size_t i) const { return data.m256_f32[i]; }
0357 template <> Vc_INTRINSIC Vc_PURE signed int Storage< signed int , 8, AliasStrategy::UnionMembers>::m(size_t i) const { return data.m256i_i32[i]; }
0358 template <> Vc_INTRINSIC Vc_PURE signed short Storage< signed short ,16, AliasStrategy::UnionMembers>::m(size_t i) const { return data.m256i_i16[i]; }
0359 template <> Vc_INTRINSIC Vc_PURE signed char Storage< signed char ,32, AliasStrategy::UnionMembers>::m(size_t i) const { return data.m256i_i8[i]; }
0360 template <> Vc_INTRINSIC Vc_PURE unsigned int Storage<unsigned int , 8, AliasStrategy::UnionMembers>::m(size_t i) const { return data.m256i_u32[i]; }
0361 template <> Vc_INTRINSIC Vc_PURE unsigned short Storage<unsigned short ,16, AliasStrategy::UnionMembers>::m(size_t i) const { return data.m256i_u16[i]; }
0362 template <> Vc_INTRINSIC Vc_PURE unsigned char Storage<unsigned char ,32, AliasStrategy::UnionMembers>::m(size_t i) const { return data.m256i_u8[i]; }
0363
0364 template <> Vc_INTRINSIC Vc_PURE double &Storage< double, 4, AliasStrategy::UnionMembers>::ref(size_t i) { return data.m256d_f64[i]; }
0365 template <> Vc_INTRINSIC Vc_PURE float &Storage< float , 8, AliasStrategy::UnionMembers>::ref(size_t i) { return data.m256_f32[i]; }
0366 template <> Vc_INTRINSIC Vc_PURE signed int &Storage< signed int , 8, AliasStrategy::UnionMembers>::ref(size_t i) { return data.m256i_i32[i]; }
0367 template <> Vc_INTRINSIC Vc_PURE signed short &Storage< signed short ,16, AliasStrategy::UnionMembers>::ref(size_t i) { return data.m256i_i16[i]; }
0368 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]); }
0369 template <> Vc_INTRINSIC Vc_PURE unsigned int &Storage<unsigned int , 8, AliasStrategy::UnionMembers>::ref(size_t i) { return data.m256i_u32[i]; }
0370 template <> Vc_INTRINSIC Vc_PURE unsigned short &Storage<unsigned short ,16, AliasStrategy::UnionMembers>::ref(size_t i) { return data.m256i_u16[i]; }
0371 template <> Vc_INTRINSIC Vc_PURE unsigned char &Storage<unsigned char ,32, AliasStrategy::UnionMembers>::ref(size_t i) { return data.m256i_u8[i]; }
0372 #endif
0373 #endif
0374
0375 template <typename VectorType, typename EntryType>
0376 using VectorMemoryUnion = Storage<EntryType, sizeof(VectorType) / sizeof(EntryType)>;
0377
0378 }
0379 }
0380
0381 #endif