Skip to content

Commit b422b01

Browse files
dgbomaomao194313
andauthored
Implement prefetch hints for aarch64 (#918)
Co-authored-by: Wang Maozhang <[email protected]>
1 parent 6408c20 commit b422b01

File tree

4 files changed

+95
-1
lines changed

4 files changed

+95
-1
lines changed

crates/core_arch/src/aarch64/mod.rs

+3
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ pub use self::tme::*;
2121
mod crc;
2222
pub use self::crc::*;
2323

24+
mod prefetch;
25+
pub use self::prefetch::*;
26+
2427
pub use super::acle::*;
2528

2629
#[cfg(test)]
+89
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
#[cfg(test)]
2+
use stdarch_test::assert_instr;
3+
4+
extern "C" {
5+
#[link_name = "llvm.prefetch"]
6+
fn prefetch(p: *const i8, rw: i32, loc: i32, ty: i32);
7+
}
8+
9+
/// See [`prefetch`](fn._prefetch.html).
10+
pub const _PREFETCH_READ: i32 = 0;
11+
12+
/// See [`prefetch`](fn._prefetch.html).
13+
pub const _PREFETCH_WRITE: i32 = 1;
14+
15+
/// See [`prefetch`](fn._prefetch.html).
16+
pub const _PREFETCH_LOCALITY0: i32 = 0;
17+
18+
/// See [`prefetch`](fn._prefetch.html).
19+
pub const _PREFETCH_LOCALITY1: i32 = 1;
20+
21+
/// See [`prefetch`](fn._prefetch.html).
22+
pub const _PREFETCH_LOCALITY2: i32 = 2;
23+
24+
/// See [`prefetch`](fn._prefetch.html).
25+
pub const _PREFETCH_LOCALITY3: i32 = 3;
26+
27+
/// Fetch the cache line that contains address `p` using the given `rw` and `locality`.
28+
///
29+
/// The `rw` must be one of:
30+
///
31+
/// * [`_PREFETCH_READ`](constant._PREFETCH_READ.html): the prefetch is preparing
32+
/// for a read.
33+
///
34+
/// * [`_PREFETCH_WRITE`](constant._PREFETCH_WRITE.html): the prefetch is preparing
35+
/// for a write.
36+
///
37+
/// The `locality` must be one of:
38+
///
39+
/// * [`_PREFETCH_LOCALITY0`](constant._PREFETCH_LOCALITY0.html): Streaming or
40+
/// non-temporal prefetch, for data that is used only once.
41+
///
42+
/// * [`_PREFETCH_LOCALITY1`](constant._PREFETCH_LOCALITY1.html): Fetch into level 3 cache.
43+
///
44+
/// * [`_PREFETCH_LOCALITY2`](constant._PREFETCH_LOCALITY2.html): Fetch into level 2 cache.
45+
///
46+
/// * [`_PREFETCH_LOCALITY3`](constant._PREFETCH_LOCALITY3.html): Fetch into level 1 cache.
47+
///
48+
/// The prefetch memory instructions signal to the memory system that memory accesses
49+
/// from a specified address are likely to occur in the near future. The memory system
50+
/// can respond by taking actions that are expected to speed up the memory access when
51+
/// they do occur, such as preloading the specified address into one or more caches.
52+
/// Because these signals are only hints, it is valid for a particular CPU to treat
53+
/// any or all prefetch instructions as a NOP.
54+
///
55+
///
56+
/// [Arm's documentation](https://developer.arm.com/documentation/den0024/a/the-a64-instruction-set/memory-access-instructions/prefetching-memory?lang=en)
57+
#[inline(always)]
58+
#[cfg_attr(test, assert_instr("prfm pldl1strm", rw = _PREFETCH_READ, locality = _PREFETCH_LOCALITY0))]
59+
#[cfg_attr(test, assert_instr("prfm pldl3keep", rw = _PREFETCH_READ, locality = _PREFETCH_LOCALITY1))]
60+
#[cfg_attr(test, assert_instr("prfm pldl2keep", rw = _PREFETCH_READ, locality = _PREFETCH_LOCALITY2))]
61+
#[cfg_attr(test, assert_instr("prfm pldl1keep", rw = _PREFETCH_READ, locality = _PREFETCH_LOCALITY3))]
62+
#[cfg_attr(test, assert_instr("prfm pstl1strm", rw = _PREFETCH_WRITE, locality = _PREFETCH_LOCALITY0))]
63+
#[cfg_attr(test, assert_instr("prfm pstl3keep", rw = _PREFETCH_WRITE, locality = _PREFETCH_LOCALITY1))]
64+
#[cfg_attr(test, assert_instr("prfm pstl2keep", rw = _PREFETCH_WRITE, locality = _PREFETCH_LOCALITY2))]
65+
#[cfg_attr(test, assert_instr("prfm pstl1keep", rw = _PREFETCH_WRITE, locality = _PREFETCH_LOCALITY3))]
66+
#[rustc_args_required_const(1, 2)]
67+
pub unsafe fn _prefetch(p: *const i8, rw: i32, locality: i32) {
68+
// We use the `llvm.prefetch` instrinsic with `cache type` = 1 (data cache).
69+
// `rw` and `strategy` are based on the function parameters.
70+
macro_rules! pref {
71+
($rdwr:expr, $local:expr) => {
72+
match ($rdwr, $local) {
73+
(0, 0) => prefetch(p, 0, 0, 1),
74+
(0, 1) => prefetch(p, 0, 1, 1),
75+
(0, 2) => prefetch(p, 0, 2, 1),
76+
(0, 3) => prefetch(p, 0, 3, 1),
77+
(1, 0) => prefetch(p, 1, 0, 1),
78+
(1, 1) => prefetch(p, 1, 1, 1),
79+
(1, 2) => prefetch(p, 1, 2, 1),
80+
(1, 3) => prefetch(p, 1, 3, 1),
81+
(_, _) => panic!(
82+
"Illegal (rw, locality) pair in prefetch, value ({}, {}).",
83+
$rdwr, $local
84+
),
85+
}
86+
};
87+
}
88+
pref!(rw, locality);
89+
}

crates/core_arch/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#![feature(
77
const_fn,
88
const_fn_union,
9+
const_fn_transmute,
910
const_generics,
1011
custom_inner_attributes,
1112
link_llvm_intrinsics,

crates/stdarch-verify/tests/arm.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,7 @@ fn verify_all_signatures() {
330330
"_rbit_u64",
331331
"_cls_u32",
332332
"_cls_u64",
333+
"_prefetch",
333334
];
334335
if !skip.contains(&rust.name) {
335336
println!(
@@ -350,7 +351,7 @@ fn verify_all_signatures() {
350351
// Skip some intrinsics that aren't NEON and are located in different
351352
// places than the whitelists below.
352353
match rust.name {
353-
"brk" | "__breakpoint" | "udf" => continue,
354+
"brk" | "__breakpoint" | "udf" | "_prefetch" => continue,
354355
_ => {}
355356
}
356357
let arm = match map.get(rust.name) {

0 commit comments

Comments
 (0)