From edcc9bc8e3bf9914c3c7bfda183894d3de67732f Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 8 Aug 2023 16:38:06 +0200 Subject: [PATCH 1/4] Rust does not let you observe or mutate the floating-point register in well-defined ways --- crates/core_arch/src/x86/sse.rs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/crates/core_arch/src/x86/sse.rs b/crates/core_arch/src/x86/sse.rs index 3d4471ba36..980a9cbb74 100644 --- a/crates/core_arch/src/x86/sse.rs +++ b/crates/core_arch/src/x86/sse.rs @@ -1365,6 +1365,15 @@ pub unsafe fn _mm_sfence() { /// Gets the unsigned 32-bit value of the MXCSR control and status register. /// +/// Note that Rust makes no guarantees whatsoever about the contents of this regiser: Rust +/// floating-point operations may or may not result in this register getting updated with exception +/// state, and the register can change between two invocations of this function even when no +/// floating-point operations appear in the source code (since floating-point operations appearing +/// earlier or later can be reordered). +/// +/// If you need to perform some floating-point operations and check whether they raised an +/// exception, use an inline assembly block for the entire sequence of operations. +/// /// For more info see [`_mm_setcsr`](fn._mm_setcsr.html) /// /// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_getcsr) @@ -1401,6 +1410,16 @@ pub unsafe fn _mm_getcsr() -> u32 { /// * The *denormals-are-zero mode flag* turns all numbers which would be /// denormalized (exponent bits are all zeros) into zeros. /// +/// Note that modfying the masking flags, rounding mode, or denormals-are-zero mode flags leads to +/// **immediate Undefined Behavior**: Rust assumes that these are always in their default state and +/// will optimize accordingly. This even applies when the register is altered and later reset to its +/// original value without any floating-point operations appearing in the source code between those +/// operations (since floating-point operations appearing earlier or later can be reordered). +/// +/// If you need to perform some floating-point operations under a different masking flags, rounding +/// mode, or denormals-are-zero mode, use an inline assembly block and make sure to restore the +/// original MXCSR register state before the end of the block. +/// /// ## Exception Flags /// /// * `_MM_EXCEPT_INVALID`: An invalid operation was performed (e.g., dividing From 81b599a3a383da12cbd685619bb7c402d6f8ccae Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 8 Aug 2023 19:57:23 +0200 Subject: [PATCH 2/4] fix typo Co-authored-by: Jacob Lifshay --- crates/core_arch/src/x86/sse.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/core_arch/src/x86/sse.rs b/crates/core_arch/src/x86/sse.rs index 980a9cbb74..19652509fb 100644 --- a/crates/core_arch/src/x86/sse.rs +++ b/crates/core_arch/src/x86/sse.rs @@ -1410,7 +1410,7 @@ pub unsafe fn _mm_getcsr() -> u32 { /// * The *denormals-are-zero mode flag* turns all numbers which would be /// denormalized (exponent bits are all zeros) into zeros. /// -/// Note that modfying the masking flags, rounding mode, or denormals-are-zero mode flags leads to +/// Note that modifying the masking flags, rounding mode, or denormals-are-zero mode flags leads to /// **immediate Undefined Behavior**: Rust assumes that these are always in their default state and /// will optimize accordingly. This even applies when the register is altered and later reset to its /// original value without any floating-point operations appearing in the source code between those From 5bc98d8de2037dcf7e84139df9ff562b123a7855 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 8 Aug 2023 22:01:38 +0200 Subject: [PATCH 3/4] another typo --- crates/core_arch/src/x86/sse.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/core_arch/src/x86/sse.rs b/crates/core_arch/src/x86/sse.rs index 19652509fb..ff6ba788f1 100644 --- a/crates/core_arch/src/x86/sse.rs +++ b/crates/core_arch/src/x86/sse.rs @@ -1365,7 +1365,7 @@ pub unsafe fn _mm_sfence() { /// Gets the unsigned 32-bit value of the MXCSR control and status register. /// -/// Note that Rust makes no guarantees whatsoever about the contents of this regiser: Rust +/// Note that Rust makes no guarantees whatsoever about the contents of this register: Rust /// floating-point operations may or may not result in this register getting updated with exception /// state, and the register can change between two invocations of this function even when no /// floating-point operations appear in the source code (since floating-point operations appearing From 695df4200c92c1834228ac702292236cf2f56d1e Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 14 Aug 2023 16:23:37 +0200 Subject: [PATCH 4/4] deprecate _mm_getcsr and _mm_setcsr --- crates/core_arch/src/x86/sse.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/crates/core_arch/src/x86/sse.rs b/crates/core_arch/src/x86/sse.rs index ff6ba788f1..1b6839f2a5 100644 --- a/crates/core_arch/src/x86/sse.rs +++ b/crates/core_arch/src/x86/sse.rs @@ -1381,6 +1381,10 @@ pub unsafe fn _mm_sfence() { #[target_feature(enable = "sse")] #[cfg_attr(test, assert_instr(stmxcsr))] #[stable(feature = "simd_x86", since = "1.27.0")] +#[deprecated( + since = "1.73.0", + note = "see `_mm_getcsr` documentation - use inline assembly instead" +)] pub unsafe fn _mm_getcsr() -> u32 { let mut result = 0_i32; stmxcsr(&mut result as *mut _ as *mut i8); @@ -1528,6 +1532,10 @@ pub unsafe fn _mm_getcsr() -> u32 { #[target_feature(enable = "sse")] #[cfg_attr(test, assert_instr(ldmxcsr))] #[stable(feature = "simd_x86", since = "1.27.0")] +#[deprecated( + since = "1.73.0", + note = "see `_mm_setcsr` documentation - use inline assembly instead" +)] pub unsafe fn _mm_setcsr(val: u32) { ldmxcsr(&val as *const _ as *const i8); }