core/stdarch/crates/core_arch/src/x86/clflushopt.rs
1//! `CLFLUSHOPT` cache-line flush.
2
3#[cfg(test)]
4use stdarch_test::assert_instr;
5
6#[allow(improper_ctypes)]
7unsafe extern "unadjusted" {
8 #[link_name = "llvm.x86.clflushopt"]
9 fn clflushopt(p: *const u8);
10}
11
12/// Invalidates from every level of the cache hierarchy the cache line that
13/// contains `p`.
14///
15/// Unlike [`_mm_clflush`], `CLFLUSHOPT` is only ordered with respect to older
16/// writes to the flushed cache line and with respect to fence/locked
17/// operations; it is *not* serialized against other `CLFLUSHOPT`/`CLFLUSH`
18/// instructions or unrelated stores. This makes flushing a range of lines
19/// substantially faster, but a fence (e.g. [`_mm_sfence`] or [`_mm_mfence`]) is
20/// required afterward to order the flushes against subsequent operations.
21///
22/// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_clflushopt)
23///
24/// # Safety
25///
26/// Unlike the prefetch intrinsics, `CLFLUSHOPT` is subject to all the
27/// permission checking and faults associated with a byte load, so `p` must
28/// point to a byte that is valid for reads.
29///
30/// [`_mm_clflush`]: crate::arch::x86::_mm_clflush
31/// [`_mm_sfence`]: crate::arch::x86::_mm_sfence
32/// [`_mm_mfence`]: crate::arch::x86::_mm_mfence
33#[inline]
34#[target_feature(enable = "clflushopt")]
35#[cfg_attr(test, assert_instr(clflushopt))]
36#[unstable(feature = "simd_x86_clflushopt", issue = "157096")]
37pub unsafe fn _mm_clflushopt(p: *const u8) {
38 clflushopt(p);
39}
40
41#[cfg(test)]
42mod tests {
43 use crate::core_arch::x86::*;
44 use stdarch_test::simd_test;
45
46 #[simd_test(enable = "clflushopt")]
47 unsafe fn test_mm_clflushopt() {
48 let x = 0_u8;
49 _mm_clflushopt(core::ptr::addr_of!(x));
50 }
51}