/src/LPM/external.protobuf/include/absl/base/internal/prefetch.h
Line | Count | Source (jump to first uncovered line) |
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 | | #ifndef ABSL_BASE_INTERNAL_PREFETCH_H_ |
16 | | #define ABSL_BASE_INTERNAL_PREFETCH_H_ |
17 | | |
18 | | #include "absl/base/config.h" |
19 | | |
20 | | #ifdef __SSE__ |
21 | | #include <xmmintrin.h> |
22 | | #endif |
23 | | |
24 | | #if defined(_MSC_VER) && defined(ABSL_INTERNAL_HAVE_SSE) |
25 | | #include <intrin.h> |
26 | | #pragma intrinsic(_mm_prefetch) |
27 | | #endif |
28 | | |
29 | | // Compatibility wrappers around __builtin_prefetch, to prefetch data |
30 | | // for read if supported by the toolchain. |
31 | | |
32 | | // Move data into the cache before it is read, or "prefetch" it. |
33 | | // |
34 | | // The value of `addr` is the address of the memory to prefetch. If |
35 | | // the target and compiler support it, data prefetch instructions are |
36 | | // generated. If the prefetch is done some time before the memory is |
37 | | // read, it may be in the cache by the time the read occurs. |
38 | | // |
39 | | // The function names specify the temporal locality heuristic applied, |
40 | | // using the names of Intel prefetch instructions: |
41 | | // |
42 | | // T0 - high degree of temporal locality; data should be left in as |
43 | | // many levels of the cache possible |
44 | | // T1 - moderate degree of temporal locality |
45 | | // T2 - low degree of temporal locality |
46 | | // Nta - no temporal locality, data need not be left in the cache |
47 | | // after the read |
48 | | // |
49 | | // Incorrect or gratuitous use of these functions can degrade |
50 | | // performance, so use them only when representative benchmarks show |
51 | | // an improvement. |
52 | | // |
53 | | // Example usage: |
54 | | // |
55 | | // absl::base_internal::PrefetchT0(addr); |
56 | | // |
57 | | // Currently, the different prefetch calls behave on some Intel |
58 | | // architectures as follows: |
59 | | // |
60 | | // SNB..SKL SKX |
61 | | // PrefetchT0() L1/L2/L3 L1/L2 |
62 | | // PrefetchT1() L2/L3 L2 |
63 | | // PrefetchT2() L2/L3 L2 |
64 | | // PrefetchNta() L1/--/L3 L1* |
65 | | // |
66 | | // * On SKX PrefetchNta() will bring the line into L1 but will evict |
67 | | // from L3 cache. This might result in surprising behavior. |
68 | | // |
69 | | // SNB = Sandy Bridge, SKL = Skylake, SKX = Skylake Xeon. |
70 | | // |
71 | | namespace absl { |
72 | | ABSL_NAMESPACE_BEGIN |
73 | | namespace base_internal { |
74 | | |
75 | | void PrefetchT0(const void* addr); |
76 | | void PrefetchT1(const void* addr); |
77 | | void PrefetchT2(const void* addr); |
78 | | void PrefetchNta(const void* addr); |
79 | | |
80 | | // Implementation details follow. |
81 | | |
82 | | #if ABSL_HAVE_BUILTIN(__builtin_prefetch) || defined(__GNUC__) |
83 | | |
84 | | #define ABSL_INTERNAL_HAVE_PREFETCH 1 |
85 | | |
86 | | // See __builtin_prefetch: |
87 | | // https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html. |
88 | | // |
89 | | // These functions speculatively load for read only. This is |
90 | | // safe for all currently supported platforms. However, prefetch for |
91 | | // store may have problems depending on the target platform. |
92 | | // |
93 | 0 | inline void PrefetchT0(const void* addr) { |
94 | 0 | // Note: this uses prefetcht0 on Intel. |
95 | 0 | __builtin_prefetch(addr, 0, 3); |
96 | 0 | } |
97 | 0 | inline void PrefetchT1(const void* addr) { |
98 | 0 | // Note: this uses prefetcht1 on Intel. |
99 | 0 | __builtin_prefetch(addr, 0, 2); |
100 | 0 | } |
101 | 0 | inline void PrefetchT2(const void* addr) { |
102 | 0 | // Note: this uses prefetcht2 on Intel. |
103 | 0 | __builtin_prefetch(addr, 0, 1); |
104 | 0 | } |
105 | 0 | inline void PrefetchNta(const void* addr) { |
106 | 0 | // Note: this uses prefetchtnta on Intel. |
107 | 0 | __builtin_prefetch(addr, 0, 0); |
108 | 0 | } |
109 | | |
110 | | #elif defined(ABSL_INTERNAL_HAVE_SSE) |
111 | | |
112 | | #define ABSL_INTERNAL_HAVE_PREFETCH 1 |
113 | | |
114 | | inline void PrefetchT0(const void* addr) { |
115 | | _mm_prefetch(reinterpret_cast<const char*>(addr), _MM_HINT_T0); |
116 | | } |
117 | | inline void PrefetchT1(const void* addr) { |
118 | | _mm_prefetch(reinterpret_cast<const char*>(addr), _MM_HINT_T1); |
119 | | } |
120 | | inline void PrefetchT2(const void* addr) { |
121 | | _mm_prefetch(reinterpret_cast<const char*>(addr), _MM_HINT_T2); |
122 | | } |
123 | | inline void PrefetchNta(const void* addr) { |
124 | | _mm_prefetch(reinterpret_cast<const char*>(addr), _MM_HINT_NTA); |
125 | | } |
126 | | |
127 | | #else |
128 | | inline void PrefetchT0(const void*) {} |
129 | | inline void PrefetchT1(const void*) {} |
130 | | inline void PrefetchT2(const void*) {} |
131 | | inline void PrefetchNta(const void*) {} |
132 | | #endif |
133 | | |
134 | | } // namespace base_internal |
135 | | ABSL_NAMESPACE_END |
136 | | } // namespace absl |
137 | | |
138 | | #endif // ABSL_BASE_INTERNAL_PREFETCH_H_ |