#[inline(always)]
pub fn prefetch_read(p: *const u8) {
#[cfg(miri)]
let _ = p;
#[cfg(all(not(miri), target_arch = "x86_64"))]
unsafe {
core::arch::x86_64::_mm_prefetch(p.cast::<i8>(), core::arch::x86_64::_MM_HINT_T0);
}
#[cfg(all(not(miri), target_arch = "aarch64"))]
unsafe {
core::arch::asm!(
"prfm pldl1keep, [{p}]",
p = in(reg) p,
options(nostack, readonly, preserves_flags),
);
}
#[cfg(all(not(miri), not(any(target_arch = "x86_64", target_arch = "aarch64"))))]
let _ = p;
}
#[inline(always)]
pub fn prefetch<T>(r: &T) {
prefetch_read(core::ptr::from_ref(r).cast::<u8>());
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn a_hint_changes_nothing_it_can_be_asked_about() {
let v: Vec<u64> = (0..1024).collect();
for i in (0..v.len()).step_by(8) {
prefetch(&v[i]);
}
assert_eq!(v[1023], 1023);
prefetch_read(v.as_ptr().cast());
assert_eq!(v.iter().sum::<u64>(), (0..1024u64).sum());
}
#[test]
fn a_line_nobody_owns_is_still_only_a_hint() {
let v = [1u8, 2, 3, 4];
let past = unsafe { v.as_ptr().add(v.len()) };
prefetch_read(past);
assert_eq!(v[0], 1);
}
}