diff options
author | Derek Mauro <dmauro@google.com> | 2022-05-18 16:13:48 -0700 |
---|---|---|
committer | Copybara-Service <copybara-worker@google.com> | 2022-05-18 16:14:29 -0700 |
commit | a168dd01438976657ddcfe09660c738dd73f8726 (patch) | |
tree | 47b2d97c943c3aeedbec49f843584e283ed0c436 /absl | |
parent | 3e04aade4e7a53aebbbed1a1268117f1f522bfb0 (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
Diffstat (limited to 'absl')
-rw-r--r-- | absl/base/config.h | 15 | ||||
-rw-r--r-- | absl/base/internal/prefetch.h | 27 |
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*) {} |