• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2022 The Abseil Authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //      https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 // TODO(b/265984188): remove all uses and delete this header.
16 
17 #ifndef ABSL_BASE_INTERNAL_PREFETCH_H_
18 #define ABSL_BASE_INTERNAL_PREFETCH_H_
19 
20 #include "absl/base/attributes.h"
21 #include "absl/base/config.h"
22 #include "absl/base/prefetch.h"
23 
24 #ifdef __SSE__
25 #include <xmmintrin.h>
26 #endif
27 
28 #if defined(_MSC_VER) && defined(ABSL_INTERNAL_HAVE_SSE)
29 #include <intrin.h>
30 #pragma intrinsic(_mm_prefetch)
31 #endif
32 
33 // Compatibility wrappers around __builtin_prefetch, to prefetch data
34 // for read if supported by the toolchain.
35 
36 // Move data into the cache before it is read, or "prefetch" it.
37 //
38 // The value of `addr` is the address of the memory to prefetch. If
39 // the target and compiler support it, data prefetch instructions are
40 // generated. If the prefetch is done some time before the memory is
41 // read, it may be in the cache by the time the read occurs.
42 //
43 // The function names specify the temporal locality heuristic applied,
44 // using the names of Intel prefetch instructions:
45 //
46 //   T0 - high degree of temporal locality; data should be left in as
47 //        many levels of the cache possible
48 //   T1 - moderate degree of temporal locality
49 //   T2 - low degree of temporal locality
50 //   Nta - no temporal locality, data need not be left in the cache
51 //         after the read
52 //
53 // Incorrect or gratuitous use of these functions can degrade
54 // performance, so use them only when representative benchmarks show
55 // an improvement.
56 //
57 // Example usage:
58 //
59 //   absl::base_internal::PrefetchT0(addr);
60 //
61 // Currently, the different prefetch calls behave on some Intel
62 // architectures as follows:
63 //
64 //                 SNB..SKL   SKX
65 // PrefetchT0()   L1/L2/L3  L1/L2
66 // PrefetchT1()      L2/L3     L2
67 // PrefetchT2()      L2/L3     L2
68 // PrefetchNta()  L1/--/L3  L1*
69 //
70 // * On SKX PrefetchNta() will bring the line into L1 but will evict
71 //   from L3 cache. This might result in surprising behavior.
72 //
73 // SNB = Sandy Bridge, SKL = Skylake, SKX = Skylake Xeon.
74 //
75 namespace absl {
76 ABSL_NAMESPACE_BEGIN
77 namespace base_internal {
78 
79 ABSL_DEPRECATED("Use absl::PrefetchToLocalCache() instead")
PrefetchT0(const void * address)80 inline void PrefetchT0(const void* address) {
81   absl::PrefetchToLocalCache(address);
82 }
83 
84 ABSL_DEPRECATED("Use absl::PrefetchToLocalCache() instead")
PrefetchNta(const void * address)85 inline void PrefetchNta(const void* address) {
86   absl::PrefetchToLocalCacheNta(address);
87 }
88 
89 ABSL_DEPRECATED("Use __builtin_prefetch() for advanced prefetch logic instead")
90 void PrefetchT1(const void* addr);
91 
92 ABSL_DEPRECATED("Use __builtin_prefetch() for advanced prefetch logic instead")
93 void PrefetchT2(const void* addr);
94 
95 // Implementation details follow.
96 
97 #if ABSL_HAVE_BUILTIN(__builtin_prefetch) || defined(__GNUC__)
98 
99 #define ABSL_INTERNAL_HAVE_PREFETCH 1
100 
101 // See __builtin_prefetch:
102 // https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html.
103 //
104 // These functions speculatively load for read only. This is
105 // safe for all currently supported platforms. However, prefetch for
106 // store may have problems depending on the target platform.
107 //
PrefetchT1(const void * addr)108 inline void PrefetchT1(const void* addr) {
109   // Note: this uses prefetcht1 on Intel.
110   __builtin_prefetch(addr, 0, 2);
111 }
PrefetchT2(const void * addr)112 inline void PrefetchT2(const void* addr) {
113   // Note: this uses prefetcht2 on Intel.
114   __builtin_prefetch(addr, 0, 1);
115 }
116 
117 #elif defined(ABSL_INTERNAL_HAVE_SSE)
118 
119 #define ABSL_INTERNAL_HAVE_PREFETCH 1
120 
PrefetchT1(const void * addr)121 inline void PrefetchT1(const void* addr) {
122   _mm_prefetch(reinterpret_cast<const char*>(addr), _MM_HINT_T1);
123 }
PrefetchT2(const void * addr)124 inline void PrefetchT2(const void* addr) {
125   _mm_prefetch(reinterpret_cast<const char*>(addr), _MM_HINT_T2);
126 }
127 
128 #else
PrefetchT1(const void *)129 inline void PrefetchT1(const void*) {}
PrefetchT2(const void *)130 inline void PrefetchT2(const void*) {}
131 #endif
132 
133 }  // namespace base_internal
134 ABSL_NAMESPACE_END
135 }  // namespace absl
136 
137 #endif  // ABSL_BASE_INTERNAL_PREFETCH_H_
138