Skip to content

Commit 206dca8

Browse files
committed
add core::hint::prefetch_{read, write}_{data, instruction}
well, we don't expose `prefetch_write_instruction`, that one doesn't really make sense in practice.
1 parent 42d009c commit 206dca8

File tree

1 file changed

+112
-0
lines changed

1 file changed

+112
-0
lines changed

library/core/src/hint.rs

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -818,3 +818,115 @@ pub fn select_unpredictable<T>(condition: bool, true_val: T, false_val: T) -> T
818818
crate::intrinsics::select_unpredictable(condition, true_val, false_val).assume_init()
819819
}
820820
}
821+
822+
/// The expected temporal locality of a memory prefetch operation.
823+
///
824+
/// Locality expresses how likely the prefetched data is to be reused soon,
825+
/// and therefore which level of cache it should be brought into.
826+
///
827+
/// The locality is just a hint, and may be ignored on some targets or by the hardware.
828+
///
829+
/// Used with functions like [`prefetch_read_data`] and [`prefetch_write_data`].
830+
///
831+
/// [`prefetch_read_data`]: crate::hint::prefetch_read_data
832+
/// [`prefetch_write_data`]: crate::hint::prefetch_write_data
833+
#[unstable(feature = "hint_prefetch", issue = "146941")]
834+
#[non_exhaustive]
835+
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
836+
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,
841+
/// Data is expected to be reused eventually.
842+
///
843+
/// Typically prefetches into L3 cache (if the CPU supports it).
844+
L3 = 1,
845+
/// Data is expected to be reused in the near future.
846+
///
847+
/// Typically prefetches into L2 cache.
848+
L2 = 2,
849+
/// Data is expected to be reused very soon.
850+
///
851+
/// Typically prefetches into L1 cache.
852+
L1 = 3,
853+
}
854+
855+
/// Prefetch the cache line containing `ptr` for a future read.
856+
///
857+
/// A strategically placed prefetch can reduce cache miss latency if the data is accessed
858+
/// soon after, but may also increase bandwidth usage or evict other cache lines.
859+
///
860+
/// A prefetch is a *hint*, and may be ignored on certain targets or by the hardware.
861+
///
862+
/// Passing a dangling or invalid pointer is permitted: the memory will not
863+
/// actually be dereferenced, and no faults are raised.
864+
///
865+
/// # Examples
866+
///
867+
/// ```
868+
/// use std::hint::{Locality, prefetch_read_data};
869+
/// use std::mem::size_of_val;
870+
///
871+
/// // Prefetch all of `slice` into the L1 cache.
872+
/// fn prefetch_slice<T>(slice: &[T]) {
873+
/// // On most systems the cache line size is 64 bytes.
874+
/// for offset in (0..size_of_val(slice)).step_by(64) {
875+
/// prefetch_read_data(slice.as_ptr().wrapping_add(offset), Locality::L1);
876+
/// }
877+
/// }
878+
/// ```
879+
#[inline(always)]
880+
#[unstable(feature = "hint_prefetch", issue = "146941")]
881+
pub const fn prefetch_read_data<T>(ptr: *const T, locality: Locality) {
882+
match locality {
883+
Locality::NonTemporal => {
884+
intrinsics::prefetch_read_data::<T, { Locality::NonTemporal as i32 }>(ptr)
885+
}
886+
Locality::L3 => intrinsics::prefetch_read_data::<T, { Locality::L3 as i32 }>(ptr),
887+
Locality::L2 => intrinsics::prefetch_read_data::<T, { Locality::L2 as i32 }>(ptr),
888+
Locality::L1 => intrinsics::prefetch_read_data::<T, { Locality::L1 as i32 }>(ptr),
889+
}
890+
}
891+
892+
/// Prefetch the cache line containing `ptr` for a future write.
893+
///
894+
/// A strategically placed prefetch can reduce cache miss latency if the data is accessed
895+
/// soon after, but may also increase bandwidth usage or evict other cache lines.
896+
///
897+
/// A prefetch is a *hint*, and may be ignored on certain targets or by the hardware.
898+
///
899+
/// Passing a dangling or invalid pointer is permitted: the memory will not
900+
/// actually be dereferenced, and no faults are raised.
901+
#[unstable(feature = "hint_prefetch", issue = "146941")]
902+
pub const fn prefetch_write_data<T>(ptr: *mut T, locality: Locality) {
903+
match locality {
904+
Locality::NonTemporal => {
905+
intrinsics::prefetch_write_data::<T, { Locality::NonTemporal as i32 }>(ptr)
906+
}
907+
Locality::L3 => intrinsics::prefetch_write_data::<T, { Locality::L3 as i32 }>(ptr),
908+
Locality::L2 => intrinsics::prefetch_write_data::<T, { Locality::L2 as i32 }>(ptr),
909+
Locality::L1 => intrinsics::prefetch_write_data::<T, { Locality::L1 as i32 }>(ptr),
910+
}
911+
}
912+
913+
/// Prefetch the cache line containing `ptr` for a future read.
914+
///
915+
/// A strategically placed prefetch can reduce cache miss latency if the instructions are
916+
/// accessed soon after, but may also increase bandwidth usage or evict other cache lines.
917+
///
918+
/// A prefetch is a *hint*, and may be ignored on certain targets or by the hardware.
919+
///
920+
/// Passing a dangling or invalid pointer is permitted: the memory will not
921+
/// actually be dereferenced, and no faults are raised.
922+
#[unstable(feature = "hint_prefetch", issue = "146941")]
923+
pub const fn prefetch_read_instruction<T>(ptr: *const T, locality: Locality) {
924+
match locality {
925+
Locality::NonTemporal => {
926+
intrinsics::prefetch_read_instruction::<T, { Locality::NonTemporal as i32 }>(ptr)
927+
}
928+
Locality::L3 => intrinsics::prefetch_read_instruction::<T, { Locality::L3 as i32 }>(ptr),
929+
Locality::L2 => intrinsics::prefetch_read_instruction::<T, { Locality::L2 as i32 }>(ptr),
930+
Locality::L1 => intrinsics::prefetch_read_instruction::<T, { Locality::L1 as i32 }>(ptr),
931+
}
932+
}

0 commit comments

Comments
 (0)