Back to home page

EIC code displayed by LXR

 
 

    


Warning, file /include/absl/base/prefetch.h was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 // Copyright 2023 The Abseil Authors
0002 //
0003 // Licensed under the Apache License, Version 2.0 (the "License");
0004 // you may not use this file except in compliance with the License.
0005 // You may obtain a copy of the License at
0006 //
0007 //     https://www.apache.org/licenses/LICENSE-2.0
0008 //
0009 // Unless required by applicable law or agreed to in writing, software
0010 // distributed under the License is distributed on an "AS IS" BASIS,
0011 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0012 // See the License for the specific language governing permissions and
0013 // limitations under the License.
0014 //
0015 // -----------------------------------------------------------------------------
0016 // File: prefetch.h
0017 // -----------------------------------------------------------------------------
0018 //
0019 // This header file defines prefetch functions to prefetch memory contents
0020 // into the first level cache (L1) for the current CPU. The prefetch logic
0021 // offered in this header is limited to prefetching first level cachelines
0022 // only, and is aimed at relatively 'simple' prefetching logic.
0023 //
0024 #ifndef ABSL_BASE_PREFETCH_H_
0025 #define ABSL_BASE_PREFETCH_H_
0026 
0027 #include "absl/base/attributes.h"
0028 #include "absl/base/config.h"
0029 
0030 #if defined(ABSL_INTERNAL_HAVE_SSE)
0031 #include <xmmintrin.h>
0032 #endif
0033 
0034 #if defined(_MSC_VER)
0035 #include <intrin.h>
0036 #if defined(ABSL_INTERNAL_HAVE_SSE)
0037 #pragma intrinsic(_mm_prefetch)
0038 #endif
0039 #endif
0040 
0041 namespace absl {
0042 ABSL_NAMESPACE_BEGIN
0043 
0044 // Moves data into the L1 cache before it is read, or "prefetches" it.
0045 //
0046 // The value of `addr` is the address of the memory to prefetch. If
0047 // the target and compiler support it, data prefetch instructions are
0048 // generated. If the prefetch is done some time before the memory is
0049 // read, it may be in the cache by the time the read occurs.
0050 //
0051 // This method prefetches data with the highest degree of temporal locality;
0052 // data is prefetched where possible into all levels of the cache.
0053 //
0054 // Incorrect or gratuitous use of this function can degrade performance.
0055 // Use this function only when representative benchmarks show an improvement.
0056 //
0057 // Example:
0058 //
0059 //  // Computes incremental checksum for `data`.
0060 //  int ComputeChecksum(int sum, absl::string_view data);
0061 //
0062 //  // Computes cumulative checksum for all values in `data`
0063 //  int ComputeChecksum(absl::Span<const std::string> data) {
0064 //    int sum = 0;
0065 //    auto it = data.begin();
0066 //    auto pit = data.begin();
0067 //    auto end = data.end();
0068 //    for (int dist = 8; dist > 0 && pit != data.end(); --dist, ++pit) {
0069 //      absl::PrefetchToLocalCache(pit->data());
0070 //    }
0071 //    for (; pit != end; ++pit, ++it) {
0072 //      sum = ComputeChecksum(sum, *it);
0073 //      absl::PrefetchToLocalCache(pit->data());
0074 //    }
0075 //    for (; it != end; ++it) {
0076 //      sum = ComputeChecksum(sum, *it);
0077 //    }
0078 //    return sum;
0079 //  }
0080 //
0081 void PrefetchToLocalCache(const void* addr);
0082 
0083 // Moves data into the L1 cache before it is read, or "prefetches" it.
0084 //
0085 // This function is identical to `PrefetchToLocalCache()` except that it has
0086 // non-temporal locality: the fetched data should not be left in any of the
0087 // cache tiers. This is useful for cases where the data is used only once /
0088 // short term, for example, invoking a destructor on an object.
0089 //
0090 // Incorrect or gratuitous use of this function can degrade performance.
0091 // Use this function only when representative benchmarks show an improvement.
0092 //
0093 // Example:
0094 //
0095 //  template <typename Iterator>
0096 //  void DestroyPointers(Iterator begin, Iterator end) {
0097 //    size_t distance = std::min(8U, bars.size());
0098 //
0099 //    int dist = 8;
0100 //    auto prefetch_it = begin;
0101 //    while (prefetch_it != end && --dist;) {
0102 //      absl::PrefetchToLocalCacheNta(*prefetch_it++);
0103 //    }
0104 //    while (prefetch_it != end) {
0105 //      delete *begin++;
0106 //      absl::PrefetchToLocalCacheNta(*prefetch_it++);
0107 //    }
0108 //    while (begin != end) {
0109 //      delete *begin++;
0110 //    }
0111 //  }
0112 //
0113 void PrefetchToLocalCacheNta(const void* addr);
0114 
0115 // Moves data into the L1 cache with the intent to modify it.
0116 //
0117 // This function is similar to `PrefetchToLocalCache()` except that it
0118 // prefetches cachelines with an 'intent to modify' This typically includes
0119 // invalidating cache entries for this address in all other cache tiers, and an
0120 // exclusive access intent.
0121 //
0122 // Incorrect or gratuitous use of this function can degrade performance. As this
0123 // function can invalidate cached cachelines on other caches and computer cores,
0124 // incorrect usage of this function can have an even greater negative impact
0125 // than incorrect regular prefetches.
0126 // Use this function only when representative benchmarks show an improvement.
0127 //
0128 // Example:
0129 //
0130 //  void* Arena::Allocate(size_t size) {
0131 //    void* ptr = AllocateBlock(size);
0132 //    absl::PrefetchToLocalCacheForWrite(ptr);
0133 //    return ptr;
0134 //  }
0135 //
0136 void PrefetchToLocalCacheForWrite(const void* addr);
0137 
0138 #if ABSL_HAVE_BUILTIN(__builtin_prefetch) || defined(__GNUC__)
0139 
0140 #define ABSL_HAVE_PREFETCH 1
0141 
0142 // See __builtin_prefetch:
0143 // https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html.
0144 //
0145 ABSL_ATTRIBUTE_ALWAYS_INLINE inline void PrefetchToLocalCache(
0146     const void* addr) {
0147   __builtin_prefetch(addr, 0, 3);
0148 }
0149 
0150 ABSL_ATTRIBUTE_ALWAYS_INLINE inline void PrefetchToLocalCacheNta(
0151     const void* addr) {
0152   __builtin_prefetch(addr, 0, 0);
0153 }
0154 
0155 ABSL_ATTRIBUTE_ALWAYS_INLINE inline void PrefetchToLocalCacheForWrite(
0156     const void* addr) {
0157   // [x86] gcc/clang don't generate PREFETCHW for __builtin_prefetch(.., 1)
0158   // unless -march=broadwell or newer; this is not generally the default, so we
0159   // manually emit prefetchw. PREFETCHW is recognized as a no-op on older Intel
0160   // processors and has been present on AMD processors since the K6-2.
0161 #if defined(__x86_64__) && !defined(__PRFCHW__)
0162   asm("prefetchw %0" : : "m"(*reinterpret_cast<const char*>(addr)));
0163 #else
0164   __builtin_prefetch(addr, 1, 3);
0165 #endif
0166 }
0167 
0168 #elif defined(ABSL_INTERNAL_HAVE_SSE)
0169 
0170 #define ABSL_HAVE_PREFETCH 1
0171 
0172 ABSL_ATTRIBUTE_ALWAYS_INLINE inline void PrefetchToLocalCache(
0173     const void* addr) {
0174   _mm_prefetch(reinterpret_cast<const char*>(addr), _MM_HINT_T0);
0175 }
0176 
0177 ABSL_ATTRIBUTE_ALWAYS_INLINE inline void PrefetchToLocalCacheNta(
0178     const void* addr) {
0179   _mm_prefetch(reinterpret_cast<const char*>(addr), _MM_HINT_NTA);
0180 }
0181 
0182 ABSL_ATTRIBUTE_ALWAYS_INLINE inline void PrefetchToLocalCacheForWrite(
0183     const void* addr) {
0184 #if defined(_MM_HINT_ET0)
0185   _mm_prefetch(reinterpret_cast<const char*>(addr), _MM_HINT_ET0);
0186 #elif !defined(_MSC_VER) && defined(__x86_64__)
0187   // _MM_HINT_ET0 is not universally supported. As we commented further
0188   // up, PREFETCHW is recognized as a no-op on older Intel processors
0189   // and has been present on AMD processors since the K6-2. We have this
0190   // disabled for MSVC compilers as this miscompiles on older MSVC compilers.
0191   asm("prefetchw %0" : : "m"(*reinterpret_cast<const char*>(addr)));
0192 #endif
0193 }
0194 
0195 #else
0196 
0197 ABSL_ATTRIBUTE_ALWAYS_INLINE inline void PrefetchToLocalCache(
0198     const void* addr) {}
0199 ABSL_ATTRIBUTE_ALWAYS_INLINE inline void PrefetchToLocalCacheNta(
0200     const void* addr) {}
0201 ABSL_ATTRIBUTE_ALWAYS_INLINE inline void PrefetchToLocalCacheForWrite(
0202     const void* addr) {}
0203 
0204 #endif
0205 
0206 ABSL_NAMESPACE_END
0207 }  // namespace absl
0208 
0209 #endif  // ABSL_BASE_PREFETCH_H_