summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Derek Mauro <dmauro@google.com>2022-05-18 16:13:48 -0700
committerGravatar Copybara-Service <copybara-worker@google.com>2022-05-18 16:14:29 -0700
commita168dd01438976657ddcfe09660c738dd73f8726 (patch)
tree47b2d97c943c3aeedbec49f843584e283ed0c436
parent3e04aade4e7a53aebbbed1a1268117f1f522bfb0 (diff)
Use SSE instructions for prefetch when __builtin_prefetch is unavailable
This notably gets prefetch working on MSVC Implementation note: https://docs.microsoft.com/en-us/windows/win32/api/winnt/nf-winnt-prefetchcacheline MSVC does have PreFetchCacheLine, but that would require including <windows.h> in a header PiperOrigin-RevId: 449602543 Change-Id: I5e6ca4b7c3d287779aa03c2fd348b41fb65c3680
-rw-r--r--absl/base/config.h15
-rw-r--r--absl/base/internal/prefetch.h27
2 files changed, 42 insertions, 0 deletions
diff --git a/absl/base/config.h b/absl/base/config.h
index 3f5ace3f..a0d599fe 100644
--- a/absl/base/config.h
+++ b/absl/base/config.h
@@ -837,6 +837,21 @@ static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != 'h' ||
#define ABSL_INTERNAL_HAS_RTTI 1
#endif // !defined(__GNUC__) || defined(__GXX_RTTI)
+// ABSL_INTERNAL_HAVE_SSE is used for compile-time detection of SSE support.
+// See https://gcc.gnu.org/onlinedocs/gcc/x86-Options.html for an overview of
+// which architectures support the various x86 instruction sets.
+#ifdef ABSL_INTERNAL_HAVE_SSE
+#error ABSL_INTERNAL_HAVE_SSE cannot be directly set
+#elif defined(__SSE__)
+#define ABSL_INTERNAL_HAVE_SSE 1
+#elif defined(_M_X64) || (defined(_M_IX86_FP) && _M_IX86_FP >= 1)
+// MSVC only defines _M_IX86_FP for x86 32-bit code, and _M_IX86_FP >= 1
+// indicates that at least SSE was targeted with the /arch:SSE option.
+// All x86-64 processors support SSE, so support can be assumed.
+// https://docs.microsoft.com/en-us/cpp/preprocessor/predefined-macros
+#define ABSL_INTERNAL_HAVE_SSE 1
+#endif
+
// ABSL_INTERNAL_HAVE_SSE2 is used for compile-time detection of SSE2 support.
// See https://gcc.gnu.org/onlinedocs/gcc/x86-Options.html for an overview of
// which architectures support the various x86 instruction sets.
diff --git a/absl/base/internal/prefetch.h b/absl/base/internal/prefetch.h
index d4971a68..06419283 100644
--- a/absl/base/internal/prefetch.h
+++ b/absl/base/internal/prefetch.h
@@ -17,6 +17,15 @@
#include "absl/base/config.h"
+#ifdef __SSE__
+#include <xmmintrin.h>
+#endif
+
+#if defined(_MSC_VER) && defined(ABSL_INTERNAL_HAVE_SSE)
+#include <intrin.h>
+#pragma intrinsic(_mm_prefetch)
+#endif
+
// Compatibility wrappers around __builtin_prefetch, to prefetch data
// for read if supported by the toolchain.
@@ -97,6 +106,24 @@ inline void PrefetchNta(const void* addr) {
// Note: this uses prefetchtnta on Intel.
__builtin_prefetch(addr, 0, 0);
}
+
+#elif defined(ABSL_INTERNAL_HAVE_SSE)
+
+#define ABSL_INTERNAL_HAVE_PREFETCH 1
+
+inline void PrefetchT0(const void* addr) {
+ _mm_prefetch(reinterpret_cast<const char*>(addr), _MM_HINT_T0);
+}
+inline void PrefetchT1(const void* addr) {
+ _mm_prefetch(reinterpret_cast<const char*>(addr), _MM_HINT_T1);
+}
+inline void PrefetchT2(const void* addr) {
+ _mm_prefetch(reinterpret_cast<const char*>(addr), _MM_HINT_T2);
+}
+inline void PrefetchNta(const void* addr) {
+ _mm_prefetch(reinterpret_cast<const char*>(addr), _MM_HINT_NTA);
+}
+
#else
inline void PrefetchT0(const void*) {}
inline void PrefetchT1(const void*) {}