Vc  1.3.2-dev
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 #ifdef Vc_IMPL_MIC
54 template<size_t L1 = 8 * 64, size_t L2 = 64 * 64,
55 #else
56 // TODO: determine a good default for typical CPU use
57 template<size_t L1 = 16 * 64, size_t L2 = 128 * 64,
58 #endif
59  typename ExclusiveOrShared_ = void> struct PrefetchFlag : public PrefetchFlagBase
60 {
61  typedef ExclusiveOrShared_ ExclusiveOrShared;
62  static constexpr size_t L1Stride = L1;
63  static constexpr size_t L2Stride = L2;
64  static constexpr bool IsExclusive = std::is_same<ExclusiveOrShared, Exclusive>::value;
65  static constexpr bool IsShared = std::is_same<ExclusiveOrShared, Shared>::value;
66 };
67 
68 template<typename Base, typename Default, typename... LoadStoreFlags> struct ExtractType
69 {
70  typedef Default type;
71 };
72 template<typename Base, typename Default, typename T, typename... LoadStoreFlags> struct ExtractType<Base, Default, T, LoadStoreFlags...>
73 {
74  typedef typename std::conditional<std::is_base_of<Base, T>::value, T, typename ExtractType<Base, Default, LoadStoreFlags...>::type>::type type;
75 };
76 
77 // ICC warns about the constexpr members in LoadStoreFlags: member "LoadStoreFlags<Flags...>::IsAligned" was declared but never referenced
78 // who needs that warning, especially if it was referenced...
79 // The warning cannot be reenabled because it gets emitted whenever the LoadStoreFlags is instantiated
80 // somewhere, so it could be anywhere.
81 #ifdef Vc_ICC
82 #pragma warning(disable: 177)
83 #endif
84 
88 template<typename... Flags> struct LoadStoreFlags
89 {
90 private:
91  // ICC doesn't grok this line:
92  //template<typename Test> using TestFlag = std::is_same<typename ExtractType<StreamingFlag, void, Flags...>::type, void>;
93  typedef typename ExtractType<PrefetchFlagBase, PrefetchFlag<0, 0>, Flags...>::type Prefetch;
94 
95 public:
96  constexpr LoadStoreFlags() {}
97 
98  static constexpr bool IsStreaming = !std::is_same<typename ExtractType<StreamingFlag, void, Flags...>::type, void>::value;
99  static constexpr bool IsUnaligned = !std::is_same<typename ExtractType<UnalignedFlag, void, Flags...>::type, void>::value;
100  static constexpr bool IsAligned = !IsUnaligned;
101  static constexpr bool IsPrefetch = !std::is_same<typename ExtractType<PrefetchFlagBase, void, Flags...>::type, void>::value;
102  static constexpr bool IsExclusivePrefetch = Prefetch::IsExclusive;
103  static constexpr bool IsSharedPrefetch = Prefetch::IsShared;
104  static constexpr size_t L1Stride = Prefetch::L1Stride;
105  static constexpr size_t L2Stride = Prefetch::L2Stride;
106 
107  typedef LoadStoreFlags<typename std::conditional<std::is_same<Flags, UnalignedFlag>::value, void, Flags>::type...> UnalignedRemoved;
108 
109  // The following EnableIf* convenience types cannot use enable_if because then no LoadStoreFlags type
110  // could ever be instantiated. Instead these types are defined either as void* or void. The
111  // function that does SFINAE then assigns "= nullptr" to this type. Thus, the ones with just
112  // void result in substitution failure.
113  typedef typename std::conditional<IsAligned && !IsStreaming, void *, void>::type EnableIfAligned;
114  typedef typename std::conditional<IsAligned && IsStreaming, void *, void>::type EnableIfStreaming;
115  typedef typename std::conditional<IsUnaligned && !IsStreaming, void *, void>::type EnableIfUnalignedNotStreaming;
116  typedef typename std::conditional<IsUnaligned && IsStreaming, void *, void>::type EnableIfUnalignedAndStreaming;
117  typedef typename std::conditional<IsUnaligned , void *, void>::type EnableIfUnaligned;
118  typedef typename std::conditional<!IsUnaligned , void *, void>::type EnableIfNotUnaligned;
119  typedef typename std::conditional<IsPrefetch , void *, void>::type EnableIfPrefetch;
120  typedef typename std::conditional<!IsPrefetch , void *, void>::type EnableIfNotPrefetch;
121 };
122 
126 template<> struct LoadStoreFlags<>
127 {
128  constexpr LoadStoreFlags() {}
129 
130  static constexpr bool IsStreaming = false;
131  static constexpr bool IsUnaligned = false;
132  static constexpr bool IsAligned = !IsUnaligned;
133  static constexpr bool IsPrefetch = false;
134  static constexpr bool IsExclusivePrefetch = false;
135  static constexpr bool IsSharedPrefetch = false;
136  static constexpr size_t L1Stride = 0;
137  static constexpr size_t L2Stride = 0;
138  typedef void* EnableIfAligned;
139  typedef void* EnableIfNotUnaligned;
140  typedef void* EnableIfNotPrefetch;
141 };
142 
151 template<typename... LFlags, typename... RFlags>
152 constexpr LoadStoreFlags<LFlags..., RFlags...> operator|(LoadStoreFlags<LFlags...>, LoadStoreFlags<RFlags...>)
153 {
154  return LoadStoreFlags<LFlags..., RFlags...>();
155 }
156 
157 } // LoadStoreFlags namespace
158 
159 using LoadStoreFlags::PrefetchFlag;
160 
161 typedef LoadStoreFlags::LoadStoreFlags<> AlignedTag;
162 typedef LoadStoreFlags::LoadStoreFlags<LoadStoreFlags::StreamingFlag> StreamingTag;
163 typedef LoadStoreFlags::LoadStoreFlags<LoadStoreFlags::UnalignedFlag> UnalignedTag;
164 
166 typedef UnalignedTag DefaultLoadTag;
168 typedef UnalignedTag DefaultStoreTag;
169 
183 constexpr AlignedTag Aligned;
184 
196 constexpr UnalignedTag Unaligned;
197 
211 constexpr StreamingTag Streaming;
212 
217 constexpr LoadStoreFlags::LoadStoreFlags<PrefetchFlag<>> PrefetchDefault;
219 
225 template <size_t L1 = PrefetchFlag<>::L1Stride,
226  size_t L2 = PrefetchFlag<>::L2Stride,
227  typename ExclusiveOrShared = PrefetchFlag<>::ExclusiveOrShared>
228 struct Prefetch : public LoadStoreFlags::LoadStoreFlags<PrefetchFlag<L1, L2, ExclusiveOrShared>>
229 {
230 };
231 
232 namespace Traits
233 {
235 template <typename... Ts>
236 struct is_loadstoreflag_internal<LoadStoreFlags::LoadStoreFlags<Ts...>> : public std::true_type
237 {
238 };
241 template <size_t L1, size_t L2, typename ExclusiveOrShared>
242 struct is_loadstoreflag_internal<Prefetch<L1, L2, ExclusiveOrShared>> : public std::true_type
243 {
244 };
245 } // namespace Traits
246 } // namespace Vc
247 
248 #endif // VC_COMMON_LOADSTOREFLAGS_H_
Hint for Prefetch to select prefetches that mark the memory as shared.
result_vector_type< L, R > operator|(L &&lhs, R &&rhs)
Applies | component-wise and concurrently.
Definition: simdarray.h:1612
UnalignedTag DefaultLoadTag
The default load tag type uses unaligned (non-streaming) loads.
constexpr LoadStoreFlags::LoadStoreFlags< PrefetchFlag<> > PrefetchDefault
Use this object for a flags parameter to request default software prefetches to be emitted...
Hint for Prefetch to select prefetches that mark the memory as exclusive.
UnalignedTag DefaultStoreTag
The default store tag type uses unaligned (non-streaming) stores.
constexpr AlignedTag Aligned
Use this object for a flags parameter to request aligned loads and stores.
constexpr StreamingTag Streaming
Use this object for a flags parameter to request streaming loads and stores.
constexpr UnalignedTag Unaligned
Use this object for a flags parameter to request unaligned loads and stores.