Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-30 10:25:46

0001 /*  This file is part of the Vc library. {{{
0002 Copyright © 2013-2015 Matthias Kretz <kretz@kde.org>
0003 
0004 Redistribution and use in source and binary forms, with or without
0005 modification, are permitted provided that the following conditions are met:
0006     * Redistributions of source code must retain the above copyright
0007       notice, this list of conditions and the following disclaimer.
0008     * Redistributions in binary form must reproduce the above copyright
0009       notice, this list of conditions and the following disclaimer in the
0010       documentation and/or other materials provided with the distribution.
0011     * Neither the names of contributing organizations nor the
0012       names of its contributors may be used to endorse or promote products
0013       derived from this software without specific prior written permission.
0014 
0015 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
0016 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
0017 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
0018 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
0019 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
0020 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
0021 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
0022 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
0023 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
0024 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
0025 
0026 }}}*/
0027 
0028 #ifndef VC_COMMON_LOADSTOREFLAGS_H_
0029 #define VC_COMMON_LOADSTOREFLAGS_H_
0030 
0031 #include "../traits/type_traits.h"
0032 
0033 namespace Vc_VERSIONED_NAMESPACE
0034 {
0035 
0036 /**
0037  * Hint for \ref Prefetch to select prefetches that mark the memory as exclusive.
0038  *
0039  * This hint may optimize the prefetch if the memory will subsequently be written to.
0040  */
0041 struct Exclusive {};
0042 /**
0043  * Hint for \ref Prefetch to select prefetches that mark the memory as shared.
0044  */
0045 struct Shared {};
0046 
0047 namespace LoadStoreFlags
0048 {
0049 
0050 struct StreamingFlag {};
0051 struct UnalignedFlag {};
0052 struct PrefetchFlagBase {};
0053 // TODO: determine a good default for typical CPU use
0054 template <size_t L1 = 16 * 64, size_t L2 = 128 * 64, typename ExclusiveOrShared_ = void>
0055 struct PrefetchFlag : public PrefetchFlagBase {
0056     typedef ExclusiveOrShared_ ExclusiveOrShared;
0057     static constexpr size_t L1Stride = L1;
0058     static constexpr size_t L2Stride = L2;
0059     static constexpr bool IsExclusive = std::is_same<ExclusiveOrShared, Exclusive>::value;
0060     static constexpr bool IsShared = std::is_same<ExclusiveOrShared, Shared>::value;
0061 };
0062 
0063 template<typename Base, typename Default, typename... LoadStoreFlags> struct ExtractType
0064 {
0065     typedef Default type;
0066 };
0067 template<typename Base, typename Default, typename T, typename... LoadStoreFlags> struct ExtractType<Base, Default, T, LoadStoreFlags...>
0068 {
0069     typedef typename std::conditional<std::is_base_of<Base, T>::value, T, typename ExtractType<Base, Default, LoadStoreFlags...>::type>::type type;
0070 };
0071 
0072 // ICC warns about the constexpr members in LoadStoreFlags: member "LoadStoreFlags<Flags...>::IsAligned" was declared but never referenced
0073 // who needs that warning, especially if it was referenced...
0074 // The warning cannot be reenabled because it gets emitted whenever the LoadStoreFlags is instantiated
0075 // somewhere, so it could be anywhere.
0076 #ifdef Vc_ICC
0077 #pragma warning(disable: 177)
0078 #endif
0079 /**\internal
0080  * Implementation of the load/store flags mechanism. This is internal API. Only some
0081  * concrete aliases are API-relevant types.
0082  */
0083 template<typename... Flags> struct LoadStoreFlags
0084 {
0085 private:
0086     // ICC doesn't grok this line:
0087     //template<typename Test> using TestFlag = std::is_same<typename ExtractType<StreamingFlag, void, Flags...>::type, void>;
0088     typedef typename ExtractType<PrefetchFlagBase, PrefetchFlag<0, 0>, Flags...>::type Prefetch;
0089 
0090 public:
0091     constexpr LoadStoreFlags() {}
0092 
0093     static constexpr bool IsStreaming = !std::is_same<typename ExtractType<StreamingFlag, void, Flags...>::type, void>::value;
0094     static constexpr bool IsUnaligned = !std::is_same<typename ExtractType<UnalignedFlag, void, Flags...>::type, void>::value;
0095     static constexpr bool IsAligned = !IsUnaligned;
0096     static constexpr bool IsPrefetch = !std::is_same<typename ExtractType<PrefetchFlagBase, void, Flags...>::type, void>::value;
0097     static constexpr bool IsExclusivePrefetch = Prefetch::IsExclusive;
0098     static constexpr bool IsSharedPrefetch = Prefetch::IsShared;
0099     static constexpr size_t L1Stride = Prefetch::L1Stride;
0100     static constexpr size_t L2Stride = Prefetch::L2Stride;
0101 
0102     typedef LoadStoreFlags<typename std::conditional<std::is_same<Flags, UnalignedFlag>::value, void, Flags>::type...> UnalignedRemoved;
0103 
0104     // The following EnableIf* convenience types cannot use enable_if because then no LoadStoreFlags type
0105     // could ever be instantiated. Instead these types are defined either as void* or void. The
0106     // function that does SFINAE then assigns "= nullptr" to this type. Thus, the ones with just
0107     // void result in substitution failure.
0108     typedef typename std::conditional<IsAligned   && !IsStreaming, void *, void>::type EnableIfAligned;
0109     typedef typename std::conditional<IsAligned   &&  IsStreaming, void *, void>::type EnableIfStreaming;
0110     typedef typename std::conditional<IsUnaligned && !IsStreaming, void *, void>::type EnableIfUnalignedNotStreaming;
0111     typedef typename std::conditional<IsUnaligned &&  IsStreaming, void *, void>::type EnableIfUnalignedAndStreaming;
0112     typedef typename std::conditional<IsUnaligned                , void *, void>::type EnableIfUnaligned;
0113     typedef typename std::conditional<!IsUnaligned               , void *, void>::type EnableIfNotUnaligned;
0114     typedef typename std::conditional<IsPrefetch                 , void *, void>::type EnableIfPrefetch;
0115     typedef typename std::conditional<!IsPrefetch                , void *, void>::type EnableIfNotPrefetch;
0116 };
0117 
0118 /**\internal
0119  * Specialization for no flags (i.e aligned, non-streaming, no prefetching)
0120  */
0121 template<> struct LoadStoreFlags<>
0122 {
0123     constexpr LoadStoreFlags() {}
0124 
0125     static constexpr bool IsStreaming = false;
0126     static constexpr bool IsUnaligned = false;
0127     static constexpr bool IsAligned = !IsUnaligned;
0128     static constexpr bool IsPrefetch = false;
0129     static constexpr bool IsExclusivePrefetch = false;
0130     static constexpr bool IsSharedPrefetch = false;
0131     static constexpr size_t L1Stride = 0;
0132     static constexpr size_t L2Stride = 0;
0133     typedef void* EnableIfAligned;
0134     typedef void* EnableIfNotUnaligned;
0135     typedef void* EnableIfNotPrefetch;
0136 };
0137 
0138 /**
0139  * Operator for concatenation of LoadStoreFlags.
0140  *
0141  * Example:
0142  * \code
0143  * float_v x(mem, Vc::Aligned | Vc::Streaming);
0144  * \endcode
0145  */
0146 template<typename... LFlags, typename... RFlags>
0147 constexpr LoadStoreFlags<LFlags..., RFlags...> operator|(LoadStoreFlags<LFlags...>, LoadStoreFlags<RFlags...>)
0148 {
0149     return LoadStoreFlags<LFlags..., RFlags...>();
0150 }
0151 
0152 } // LoadStoreFlags namespace
0153 
0154 using LoadStoreFlags::PrefetchFlag;
0155 
0156 typedef LoadStoreFlags::LoadStoreFlags<> AlignedTag;
0157 typedef LoadStoreFlags::LoadStoreFlags<LoadStoreFlags::StreamingFlag> StreamingTag;
0158 typedef LoadStoreFlags::LoadStoreFlags<LoadStoreFlags::UnalignedFlag> UnalignedTag;
0159 
0160 /// The default load tag type uses unaligned (non-streaming) loads.
0161 typedef UnalignedTag DefaultLoadTag;
0162 /// The default store tag type uses unaligned (non-streaming) stores.
0163 typedef UnalignedTag DefaultStoreTag;
0164 
0165 /**\addtogroup Utilities
0166  * @{
0167  */
0168 /**
0169  * Use this object for a \p flags parameter to request aligned loads and stores.
0170  *
0171  * It specifies that a load/store can expect a memory address that is aligned on
0172  * the correct boundary. (i.e. \p MemoryAlignment)
0173  *
0174  * \warning
0175  * If you specify Aligned, but the memory address is not aligned the program
0176  * will most likely crash.
0177  */
0178 constexpr AlignedTag Aligned;
0179 
0180 /**
0181  * Use this object for a \p flags parameter to request unaligned loads and stores.
0182  *
0183  * It specifies that a load/store can \em not expect a memory address that is
0184  * aligned on the correct boundary. (i.e. alignment is less than
0185  * \p MemoryAlignment)
0186  *
0187  * \note
0188  * If you specify Unaligned, but the memory address is aligned the load/store
0189  * will execute slightly slower than necessary.
0190  */
0191 constexpr UnalignedTag Unaligned;
0192 
0193 /**
0194  * Use this object for a \p flags parameter to request streaming loads and stores.
0195  *
0196  * It specifies that the cache should be bypassed for the given load/store.
0197  * Whether this will actually be done depends on the target system's capabilities.
0198  *
0199  * Streaming stores can be interesting when the code calculates values that, after being
0200  * written to memory, will not be used for a long time or used by a different thread.
0201  *
0202  * \note
0203  * Expect that most target systems do not support unaligned streaming loads or stores.
0204  * Therefore, make sure that you also specify Aligned.
0205  */
0206 constexpr StreamingTag Streaming;
0207 
0208 /**
0209  * Use this object for a \p flags parameter to request default software prefetches to be
0210  * emitted.
0211  */
0212 constexpr LoadStoreFlags::LoadStoreFlags<PrefetchFlag<>> PrefetchDefault;
0213 ///@}
0214 
0215 /**
0216  * \tparam L1
0217  * \tparam L2
0218  * \tparam ExclusiveOrShared
0219  */
0220 template <size_t L1 = PrefetchFlag<>::L1Stride,
0221           size_t L2 = PrefetchFlag<>::L2Stride,
0222           typename ExclusiveOrShared = PrefetchFlag<>::ExclusiveOrShared>
0223 struct Prefetch : public LoadStoreFlags::LoadStoreFlags<PrefetchFlag<L1, L2, ExclusiveOrShared>>
0224 {
0225 };
0226 
0227 namespace Traits
0228 {
0229 ///\internal partial specialization for detecting LoadStoreFlags types
0230 template <typename... Ts>
0231 struct is_loadstoreflag_internal<LoadStoreFlags::LoadStoreFlags<Ts...>> : public std::true_type
0232 {
0233 };
0234 ///\internal partial specialization for detecting the derived Prefetch type as a
0235 /// load/store flag.
0236 template <size_t L1, size_t L2, typename ExclusiveOrShared>
0237 struct is_loadstoreflag_internal<Prefetch<L1, L2, ExclusiveOrShared>> : public std::true_type
0238 {
0239 };
0240 }  // namespace Traits
0241 }  // namespace Vc
0242 
0243 #endif // VC_COMMON_LOADSTOREFLAGS_H_