Skip to content

Commit 2dcd532

Browse files
committed
Add a separate function for a non-temporal read prefetch
1 parent 206dca8 commit 2dcd532

File tree

1 file changed

+47
-21
lines changed

1 file changed

+47
-21
lines changed

library/core/src/hint.rs

Lines changed: 47 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -826,18 +826,14 @@ pub fn select_unpredictable<T>(condition: bool, true_val: T, false_val: T) -> T
826826
///
827827
/// The locality is just a hint, and may be ignored on some targets or by the hardware.
828828
///
829-
/// Used with functions like [`prefetch_read_data`] and [`prefetch_write_data`].
829+
/// Used with functions like [`prefetch_read`] and [`prefetch_write`].
830830
///
831-
/// [`prefetch_read_data`]: crate::hint::prefetch_read_data
832-
/// [`prefetch_write_data`]: crate::hint::prefetch_write_data
831+
/// [`prefetch_read`]: crate::hint::prefetch_read
832+
/// [`prefetch_write`]: crate::hint::prefetch_write
833833
#[unstable(feature = "hint_prefetch", issue = "146941")]
834834
#[non_exhaustive]
835835
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
836836
pub enum Locality {
837-
/// Data is unlikely to be reused soon.
838-
///
839-
/// Typically bypasses the caches so they are not polluted.
840-
NonTemporal = 0,
841837
/// Data is expected to be reused eventually.
842838
///
843839
/// Typically prefetches into L3 cache (if the CPU supports it).
@@ -865,30 +861,46 @@ pub enum Locality {
865861
/// # Examples
866862
///
867863
/// ```
868-
/// use std::hint::{Locality, prefetch_read_data};
864+
/// #![feature(hint_prefetch)]
865+
/// use std::hint::{Locality, prefetch_read};
869866
/// use std::mem::size_of_val;
870867
///
871868
/// // Prefetch all of `slice` into the L1 cache.
872869
/// fn prefetch_slice<T>(slice: &[T]) {
873870
/// // On most systems the cache line size is 64 bytes.
874871
/// for offset in (0..size_of_val(slice)).step_by(64) {
875-
/// prefetch_read_data(slice.as_ptr().wrapping_add(offset), Locality::L1);
872+
/// prefetch_read(slice.as_ptr().wrapping_add(offset), Locality::L1);
876873
/// }
877874
/// }
878875
/// ```
879876
#[inline(always)]
880877
#[unstable(feature = "hint_prefetch", issue = "146941")]
881-
pub const fn prefetch_read_data<T>(ptr: *const T, locality: Locality) {
878+
pub const fn prefetch_read<T>(ptr: *const T, locality: Locality) {
882879
match locality {
883-
Locality::NonTemporal => {
884-
intrinsics::prefetch_read_data::<T, { Locality::NonTemporal as i32 }>(ptr)
885-
}
886880
Locality::L3 => intrinsics::prefetch_read_data::<T, { Locality::L3 as i32 }>(ptr),
887881
Locality::L2 => intrinsics::prefetch_read_data::<T, { Locality::L2 as i32 }>(ptr),
888882
Locality::L1 => intrinsics::prefetch_read_data::<T, { Locality::L1 as i32 }>(ptr),
889883
}
890884
}
891885

886+
/// Prefetch the cache line containing `ptr` for a single future read, but attempt to avoid
887+
/// polluting the cache.
888+
///
889+
/// A strategically placed prefetch can reduce cache miss latency if the data is accessed
890+
/// soon after, but may also increase bandwidth usage or evict other cache lines.
891+
///
892+
/// A prefetch is a *hint*, and may be ignored on certain targets or by the hardware.
893+
///
894+
/// Passing a dangling or invalid pointer is permitted: the memory will not
895+
/// actually be dereferenced, and no faults are raised.
896+
#[inline(always)]
897+
#[unstable(feature = "hint_prefetch", issue = "146941")]
898+
pub const fn prefetch_read_non_temporal<T>(ptr: *const T, locality: Locality) {
899+
// The LLVM intrinsic does not currently support specifying the locality.
900+
let _ = locality;
901+
intrinsics::prefetch_read_data::<T, 0>(ptr)
902+
}
903+
892904
/// Prefetch the cache line containing `ptr` for a future write.
893905
///
894906
/// A strategically placed prefetch can reduce cache miss latency if the data is accessed
@@ -898,19 +910,35 @@ pub const fn prefetch_read_data<T>(ptr: *const T, locality: Locality) {
898910
///
899911
/// Passing a dangling or invalid pointer is permitted: the memory will not
900912
/// actually be dereferenced, and no faults are raised.
913+
#[inline(always)]
901914
#[unstable(feature = "hint_prefetch", issue = "146941")]
902-
pub const fn prefetch_write_data<T>(ptr: *mut T, locality: Locality) {
915+
pub const fn prefetch_write<T>(ptr: *mut T, locality: Locality) {
903916
match locality {
904-
Locality::NonTemporal => {
905-
intrinsics::prefetch_write_data::<T, { Locality::NonTemporal as i32 }>(ptr)
906-
}
907917
Locality::L3 => intrinsics::prefetch_write_data::<T, { Locality::L3 as i32 }>(ptr),
908918
Locality::L2 => intrinsics::prefetch_write_data::<T, { Locality::L2 as i32 }>(ptr),
909919
Locality::L1 => intrinsics::prefetch_write_data::<T, { Locality::L1 as i32 }>(ptr),
910920
}
911921
}
912922

913-
/// Prefetch the cache line containing `ptr` for a future read.
923+
/// Prefetch the cache line containing `ptr` for a single future write, but attempt to avoid
924+
/// polluting the cache.
925+
///
926+
/// A strategically placed prefetch can reduce cache miss latency if the data is accessed
927+
/// soon after, but may also increase bandwidth usage or evict other cache lines.
928+
///
929+
/// A prefetch is a *hint*, and may be ignored on certain targets or by the hardware.
930+
///
931+
/// Passing a dangling or invalid pointer is permitted: the memory will not
932+
/// actually be dereferenced, and no faults are raised.
933+
#[inline(always)]
934+
#[unstable(feature = "hint_prefetch", issue = "146941")]
935+
pub const fn prefetch_write_non_temporal<T>(ptr: *const T, locality: Locality) {
936+
// The LLVM intrinsic does not currently support specifying the locality.
937+
let _ = locality;
938+
intrinsics::prefetch_write_data::<T, 0>(ptr)
939+
}
940+
941+
/// Prefetch the cache line containing `ptr` into the instruction cache for a future read.
914942
///
915943
/// A strategically placed prefetch can reduce cache miss latency if the instructions are
916944
/// accessed soon after, but may also increase bandwidth usage or evict other cache lines.
@@ -919,12 +947,10 @@ pub const fn prefetch_write_data<T>(ptr: *mut T, locality: Locality) {
919947
///
920948
/// Passing a dangling or invalid pointer is permitted: the memory will not
921949
/// actually be dereferenced, and no faults are raised.
950+
#[inline(always)]
922951
#[unstable(feature = "hint_prefetch", issue = "146941")]
923952
pub const fn prefetch_read_instruction<T>(ptr: *const T, locality: Locality) {
924953
match locality {
925-
Locality::NonTemporal => {
926-
intrinsics::prefetch_read_instruction::<T, { Locality::NonTemporal as i32 }>(ptr)
927-
}
928954
Locality::L3 => intrinsics::prefetch_read_instruction::<T, { Locality::L3 as i32 }>(ptr),
929955
Locality::L2 => intrinsics::prefetch_read_instruction::<T, { Locality::L2 as i32 }>(ptr),
930956
Locality::L1 => intrinsics::prefetch_read_instruction::<T, { Locality::L1 as i32 }>(ptr),

0 commit comments

Comments
 (0)