Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 0 additions & 6 deletions crates/core_arch/missing-x86.md
Comment thread
sayantn marked this conversation as resolved.
Original file line number Diff line number Diff line change
Expand Up @@ -70,12 +70,6 @@
</p></details>


<details><summary>["CLFLUSHOPT"]</summary><p>

* [ ] [`_mm_clflushopt`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_clflushopt)
</p></details>


<details><summary>["CLWB"]</summary><p>

* [ ] [`_mm_clwb`](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_clwb)
Expand Down
1 change: 1 addition & 0 deletions crates/core_arch/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
const_eval_select,
maybe_uninit_as_bytes,
movrs_target_feature,
clflushopt_target_feature,
min_adt_const_params
)]
#![cfg_attr(test, feature(test, abi_vectorcall, stdarch_internal))]
Expand Down
51 changes: 51 additions & 0 deletions crates/core_arch/src/x86/clflushopt.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
//! `CLFLUSHOPT` cache-line flush.

#[cfg(test)]
use stdarch_test::assert_instr;

#[allow(improper_ctypes)]
unsafe extern "unadjusted" {
#[link_name = "llvm.x86.clflushopt"]
fn clflushopt(p: *const u8);
}

/// Invalidates from every level of the cache hierarchy the cache line that
/// contains `p`.
///
/// Unlike [`_mm_clflush`], `CLFLUSHOPT` is only ordered with respect to older
/// writes to the flushed cache line and with respect to fence/locked
/// operations; it is *not* serialized against other `CLFLUSHOPT`/`CLFLUSH`
/// instructions or unrelated stores. This makes flushing a range of lines
/// substantially faster, but a fence (e.g. [`_mm_sfence`] or [`_mm_mfence`]) is
/// required afterward to order the flushes against subsequent operations.
///
/// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_clflushopt)
Copy link
Copy Markdown
Contributor

@folkertdev folkertdev May 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add a # Safety section here where you document that (unlike other prefetch functions) this function needs a valid pointer? Or at least that is what I think

subject to all permission checking and faults associated with a byte load

means?

cc @Amanieu @sayantn if I'm misinterpreting that.

View changes since the review

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For consistency you can add the same section to the _mm_clflush doc comment.

///
/// # Safety
///
/// Unlike the prefetch intrinsics, `CLFLUSHOPT` is subject to all the
/// permission checking and faults associated with a byte load, so `p` must
/// point to a byte that is valid for reads.
///
/// [`_mm_clflush`]: crate::arch::x86::_mm_clflush
/// [`_mm_sfence`]: crate::arch::x86::_mm_sfence
/// [`_mm_mfence`]: crate::arch::x86::_mm_mfence
#[inline]
#[target_feature(enable = "clflushopt")]
#[cfg_attr(test, assert_instr(clflushopt))]
#[unstable(feature = "simd_x86_clflushopt", issue = "157096")]
pub unsafe fn _mm_clflushopt(p: *const u8) {
clflushopt(p);
}

#[cfg(test)]
mod tests {
use crate::core_arch::x86::*;
use stdarch_test::simd_test;

#[simd_test(enable = "clflushopt")]
unsafe fn test_mm_clflushopt() {
let x = 0_u8;
_mm_clflushopt(core::ptr::addr_of!(x));
}
}
4 changes: 4 additions & 0 deletions crates/core_arch/src/x86/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -692,6 +692,10 @@ mod adx;
#[stable(feature = "simd_x86_adx", since = "1.33.0")]
pub use self::adx::*;

mod clflushopt;
#[unstable(feature = "simd_x86_clflushopt", issue = "157096")]
pub use self::clflushopt::*;

#[cfg(test)]
use stdarch_test::assert_instr;

Expand Down
6 changes: 6 additions & 0 deletions crates/core_arch/src/x86/sse2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,12 @@ pub fn _mm_pause() {
/// the cache hierarchy.
///
/// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_clflush)
///
/// # Safety
///
/// Unlike the prefetch intrinsics, `CLFLUSH` is subject to all the permission
/// checking and faults associated with a byte load, so `p` must point to a
/// byte that is valid for reads.
#[inline]
#[target_feature(enable = "sse2")]
#[cfg_attr(test, assert_instr(clflush))]
Expand Down
12 changes: 7 additions & 5 deletions crates/stdarch-verify/tests/x86-intel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -661,12 +661,14 @@ fn matches(rust: &Function, intel: &Intrinsic) -> Result<(), String> {
fn pointed_type(intrinsic: &Intrinsic) -> Result<Type, String> {
Ok(
if intrinsic.tech == "AMX"
|| intrinsic
.cpuid
.iter()
.any(|cpuid| matches!(&**cpuid, "KEYLOCKER" | "KEYLOCKER_WIDE" | "XSAVE" | "FXSR"))
|| intrinsic.cpuid.iter().any(|cpuid| {
matches!(
&**cpuid,
"KEYLOCKER" | "KEYLOCKER_WIDE" | "XSAVE" | "FXSR" | "CLFLUSHOPT"
)
})
{
// AMX, KEYLOCKER and XSAVE intrinsics should take `*u8`
// AMX, KEYLOCKER, XSAVE and CLFLUSHOPT intrinsics should take `*u8`
U8
} else if intrinsic.name == "_mm_clflush" {
// Just a false match in the following logic
Expand Down
Loading