7#ifndef PXR_BASE_ARCH_PREFETCH_H
8#define PXR_BASE_ARCH_PREFETCH_H
21#include "pxr/base/arch/defines.h"
26#if defined(ARCH_COMPILER_MSVC)
30PXR_NAMESPACE_OPEN_SCOPE
55template <ArchPrefetchAccess Access, ArchPrefetchLocality Locality>
56void Arch_PrefetchOneLine(
void const *addr)
noexcept
58#if defined(ARCH_COMPILER_GCC) || \
59 defined(ARCH_COMPILER_CLANG) || \
60 defined(ARCH_COMPILER_ICC)
65 __builtin_prefetch(addr,
static_cast<int>(Access),
66 static_cast<int>(Locality));
68#elif defined(ARCH_COMPILER_MSVC) && defined(ARCH_CPU_ARM)
72#elif defined(ARCH_COMPILER_MSVC) && defined(ARCH_CPU_INTEL)
75 Locality == ArchPrefetchLocality::None ? _MM_HINT_NTA :
76 Locality == ArchPrefetchLocality::L3 ? _MM_HINT_T2 :
77 Locality == ArchPrefetchLocality::L2 ? _MM_HINT_T1 : _MM_HINT_T0;
79 _mm_prefetch(
reinterpret_cast<char const *
>(addr), hint);
92template <
size_t Size,
size_t Align,
class Fn>
94Arch_ForEachPrefetchLine(
void const *addr, Fn &&fn)
noexcept
98 static_assert(Align != 0 && (Align & (Align - 1)) == 0,
99 "Align must be a power of two");
100 static_assert((LineSize & (LineSize - 1)) == 0,
101 "ARCH_CACHE_LINE_SIZE must be a power of two");
103 constexpr size_t MinLines = (Size + LineSize - 1) / LineSize;
104 constexpr uintptr_t LineMask = ~static_cast<uintptr_t>(LineSize - 1);
111 constexpr bool MightStraddle =
112 Size != 0 && (Align < LineSize) &&
113 ((LineSize - Align) + Size > MinLines * LineSize);
115 char const *ptr =
reinterpret_cast<char const *
>(
116 reinterpret_cast<uintptr_t
>(addr) & LineMask);
119 for (
size_t i = 0; i != MinLines; ++i) {
125 if constexpr (MightStraddle) {
126 if (
reinterpret_cast<char const *
>(addr) + Size > ptr) {
140Arch_ForEachPrefetchLine(
void const *addr,
size_t numBytes, Fn &&fn)
noexcept
143 constexpr uintptr_t LineMask = ~static_cast<uintptr_t>(LineSize - 1);
149 uintptr_t
const a =
reinterpret_cast<uintptr_t
>(addr);
150 uintptr_t
const begin = a & LineMask;
151 uintptr_t
const last = (a + numBytes - 1) & LineMask;
161 uintptr_t
const end = last + LineSize;
165 fn(
reinterpret_cast<char const *
>(p));
173template <
class T,
class Fn>
175Arch_ForEachPrefetchLine(T
const *addr,
size_t count, Fn &&fn)
noexcept
177 Arch_ForEachPrefetchLine(
static_cast<void const *
>(addr),
178 count *
sizeof(T), fn);
188template <
size_t Size = 1,
195 Arch_ForEachPrefetchLine<Size, Align>(addr, [](
void const *line) {
196 Arch_PrefetchOneLine<Access, Locality>(line);
212 Arch_ForEachPrefetchLine(addr, numBytes, [](
void const *line) {
213 Arch_PrefetchOneLine<Access, Locality>(line);
233 Arch_ForEachPrefetchLine(addr, count, [](
void const *line) {
234 Arch_PrefetchOneLine<Access, Locality>(line);
241template <ArchPrefetchLocality Locality = ArchPrefetchLocality::L2,
class T>
246 ArchPrefetchAccess::Read, Locality>(addr);
252template <ArchPrefetchLocality Locality = ArchPrefetchLocality::L2,
class T>
257 ArchPrefetchAccess::Write, Locality>(addr);
262PXR_NAMESPACE_CLOSE_SCOPE
Provide architecture-specific memory-alignment information.
#define ARCH_CACHE_LINE_SIZE
The size of a CPU cache line on the current processor architecture in bytes.
void ArchPrefetchRead(T const *addr) noexcept
Prefetch for reading the object at addr with given locality.
ArchPrefetchLocality
How much temporal locality you expect on the address after the fetch.
ArchPrefetchAccess
The kind of access a prefetch is preparing for.
void ArchPrefetchRange(void const *addr, size_t numBytes) noexcept
Prefetch the cache lines that [addr, addr+numBytes) occupy, where numBytes is a runtime value.
void ArchPrefetchWrite(T const *addr) noexcept
Prefetch for writing the object at addr with given locality.
void ArchPrefetch(void const *addr) noexcept
Prefetch the cache lines that [addr, addr+Size) occupy.