Vc  1.4.2
SIMD Vector Classes for C++
loadstoreflags.h
1 /* This file is part of the Vc library. {{{
2 Copyright © 2013-2015 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_COMMON_LOADSTOREFLAGS_H_
29 #define VC_COMMON_LOADSTOREFLAGS_H_
30 
31 #include "../traits/type_traits.h"
32 
33 namespace Vc_VERSIONED_NAMESPACE
34 {
35 
41 struct Exclusive {};
45 struct Shared {};
46 
47 namespace LoadStoreFlags
48 {
49 
50 struct StreamingFlag {};
51 struct UnalignedFlag {};
52 struct PrefetchFlagBase {};
53 // TODO: determine a good default for typical CPU use
54 template <size_t L1 = 16 * 64, size_t L2 = 128 * 64, typename ExclusiveOrShared_ = void>
55 struct PrefetchFlag : public PrefetchFlagBase {
56  typedef ExclusiveOrShared_ ExclusiveOrShared;
57  static constexpr size_t L1Stride = L1;
58  static constexpr size_t L2Stride = L2;
59  static constexpr bool IsExclusive = std::is_same<ExclusiveOrShared, Exclusive>::value;
60  static constexpr bool IsShared = std::is_same<ExclusiveOrShared, Shared>::value;
61 };
62 
63 template<typename Base, typename Default, typename... LoadStoreFlags> struct ExtractType
64 {
65  typedef Default type;
66 };
67 template<typename Base, typename Default, typename T, typename... LoadStoreFlags> struct ExtractType<Base, Default, T, LoadStoreFlags...>
68 {
69  typedef typename std::conditional<std::is_base_of<Base, T>::value, T, typename ExtractType<Base, Default, LoadStoreFlags...>::type>::type type;
70 };
71 
72 // ICC warns about the constexpr members in LoadStoreFlags: member "LoadStoreFlags<Flags...>::IsAligned" was declared but never referenced
73 // who needs that warning, especially if it was referenced...
74 // The warning cannot be reenabled because it gets emitted whenever the LoadStoreFlags is instantiated
75 // somewhere, so it could be anywhere.
76 #ifdef Vc_ICC
77 #pragma warning(disable: 177)
78 #endif
79 
83 template<typename... Flags> struct LoadStoreFlags
84 {
85 private:
86  // ICC doesn't grok this line:
87  //template<typename Test> using TestFlag = std::is_same<typename ExtractType<StreamingFlag, void, Flags...>::type, void>;
88  typedef typename ExtractType<PrefetchFlagBase, PrefetchFlag<0, 0>, Flags...>::type Prefetch;
89 
90 public:
91  constexpr LoadStoreFlags() {}
92 
93  static constexpr bool IsStreaming = !std::is_same<typename ExtractType<StreamingFlag, void, Flags...>::type, void>::value;
94  static constexpr bool IsUnaligned = !std::is_same<typename ExtractType<UnalignedFlag, void, Flags...>::type, void>::value;
95  static constexpr bool IsAligned = !IsUnaligned;
96  static constexpr bool IsPrefetch = !std::is_same<typename ExtractType<PrefetchFlagBase, void, Flags...>::type, void>::value;
97  static constexpr bool IsExclusivePrefetch = Prefetch::IsExclusive;
98  static constexpr bool IsSharedPrefetch = Prefetch::IsShared;
99  static constexpr size_t L1Stride = Prefetch::L1Stride;
100  static constexpr size_t L2Stride = Prefetch::L2Stride;
101 
102  typedef LoadStoreFlags<typename std::conditional<std::is_same<Flags, UnalignedFlag>::value, void, Flags>::type...> UnalignedRemoved;
103 
104  // The following EnableIf* convenience types cannot use enable_if because then no LoadStoreFlags type
105  // could ever be instantiated. Instead these types are defined either as void* or void. The
106  // function that does SFINAE then assigns "= nullptr" to this type. Thus, the ones with just
107  // void result in substitution failure.
108  typedef typename std::conditional<IsAligned && !IsStreaming, void *, void>::type EnableIfAligned;
109  typedef typename std::conditional<IsAligned && IsStreaming, void *, void>::type EnableIfStreaming;
110  typedef typename std::conditional<IsUnaligned && !IsStreaming, void *, void>::type EnableIfUnalignedNotStreaming;
111  typedef typename std::conditional<IsUnaligned && IsStreaming, void *, void>::type EnableIfUnalignedAndStreaming;
112  typedef typename std::conditional<IsUnaligned , void *, void>::type EnableIfUnaligned;
113  typedef typename std::conditional<!IsUnaligned , void *, void>::type EnableIfNotUnaligned;
114  typedef typename std::conditional<IsPrefetch , void *, void>::type EnableIfPrefetch;
115  typedef typename std::conditional<!IsPrefetch , void *, void>::type EnableIfNotPrefetch;
116 };
117 
121 template<> struct LoadStoreFlags<>
122 {
123  constexpr LoadStoreFlags() {}
124 
125  static constexpr bool IsStreaming = false;
126  static constexpr bool IsUnaligned = false;
127  static constexpr bool IsAligned = !IsUnaligned;
128  static constexpr bool IsPrefetch = false;
129  static constexpr bool IsExclusivePrefetch = false;
130  static constexpr bool IsSharedPrefetch = false;
131  static constexpr size_t L1Stride = 0;
132  static constexpr size_t L2Stride = 0;
133  typedef void* EnableIfAligned;
134  typedef void* EnableIfNotUnaligned;
135  typedef void* EnableIfNotPrefetch;
136 };
137 
146 template<typename... LFlags, typename... RFlags>
147 constexpr LoadStoreFlags<LFlags..., RFlags...> operator|(LoadStoreFlags<LFlags...>, LoadStoreFlags<RFlags...>)
148 {
149  return LoadStoreFlags<LFlags..., RFlags...>();
150 }
151 
152 } // LoadStoreFlags namespace
153 
154 using LoadStoreFlags::PrefetchFlag;
155 
156 typedef LoadStoreFlags::LoadStoreFlags<> AlignedTag;
157 typedef LoadStoreFlags::LoadStoreFlags<LoadStoreFlags::StreamingFlag> StreamingTag;
158 typedef LoadStoreFlags::LoadStoreFlags<LoadStoreFlags::UnalignedFlag> UnalignedTag;
159 
161 typedef UnalignedTag DefaultLoadTag;
163 typedef UnalignedTag DefaultStoreTag;
164 
178 constexpr AlignedTag Aligned;
179 
191 constexpr UnalignedTag Unaligned;
192 
206 constexpr StreamingTag Streaming;
207 
212 constexpr LoadStoreFlags::LoadStoreFlags<PrefetchFlag<>> PrefetchDefault;
214 
220 template <size_t L1 = PrefetchFlag<>::L1Stride,
221  size_t L2 = PrefetchFlag<>::L2Stride,
222  typename ExclusiveOrShared = PrefetchFlag<>::ExclusiveOrShared>
223 struct Prefetch : public LoadStoreFlags::LoadStoreFlags<PrefetchFlag<L1, L2, ExclusiveOrShared>>
224 {
225 };
226 
227 namespace Traits
228 {
230 template <typename... Ts>
231 struct is_loadstoreflag_internal<LoadStoreFlags::LoadStoreFlags<Ts...>> : public std::true_type
232 {
233 };
236 template <size_t L1, size_t L2, typename ExclusiveOrShared>
237 struct is_loadstoreflag_internal<Prefetch<L1, L2, ExclusiveOrShared>> : public std::true_type
238 {
239 };
240 } // namespace Traits
241 } // namespace Vc
242 
243 #endif // VC_COMMON_LOADSTOREFLAGS_H_
Vc::DefaultStoreTag
UnalignedTag DefaultStoreTag
The default store tag type uses unaligned (non-streaming) stores.
Definition: loadstoreflags.h:163
Vc::Unaligned
constexpr UnalignedTag Unaligned
Use this object for a flags parameter to request unaligned loads and stores.
Definition: loadstoreflags.h:191
Vc::Shared
Hint for Prefetch to select prefetches that mark the memory as shared.
Definition: loadstoreflags.h:45
Vc::Aligned
constexpr AlignedTag Aligned
Use this object for a flags parameter to request aligned loads and stores.
Definition: loadstoreflags.h:178
Vc::DefaultLoadTag
UnalignedTag DefaultLoadTag
The default load tag type uses unaligned (non-streaming) loads.
Definition: loadstoreflags.h:161
Vc::Streaming
constexpr StreamingTag Streaming
Use this object for a flags parameter to request streaming loads and stores.
Definition: loadstoreflags.h:206
Vc::operator|
result_vector_type< L, R > operator|(L &&lhs, R &&rhs)
Applies | component-wise and concurrently.
Definition: simdarray.h:1723
Vc::PrefetchDefault
constexpr LoadStoreFlags::LoadStoreFlags< PrefetchFlag<> > PrefetchDefault
Use this object for a flags parameter to request default software prefetches to be emitted.
Definition: loadstoreflags.h:212
Vc::Exclusive
Hint for Prefetch to select prefetches that mark the memory as exclusive.
Definition: loadstoreflags.h:41