From 5a48d74743341833806cef949ba3d5097cbc98a5 Mon Sep 17 00:00:00 2001 From: Gabriel Majeri Date: Mon, 30 Sep 2019 15:02:07 +0300 Subject: [PATCH 1/4] Deprecate MXCSR-related intrinsics --- 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 2c4295ef61..a5533aa05e 100644 --- a/crates/core_arch/src/x86/sse.rs +++ b/crates/core_arch/src/x86/sse.rs @@ -1371,6 +1371,10 @@ pub unsafe fn _mm_sfence() { /// For more info see [`_mm_setcsr`](fn._mm_setcsr.html) /// /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_getcsr) +#[rustc_deprecated( + since = "1.40.0", + reason = "modifying MXCSR causes undefined behavior in LLVM, see https://github.com/rust-lang/stdarch/issues/781" +)] #[inline] #[target_feature(enable = "sse")] #[cfg_attr(test, assert_instr(stmxcsr))] @@ -1508,6 +1512,10 @@ pub unsafe fn _mm_getcsr() -> u32 { /// /// /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_setcsr) +#[rustc_deprecated( + since = "1.40.0", + reason = "modifying MXCSR causes undefined behavior in LLVM, see https://github.com/rust-lang/stdarch/issues/781" +)] #[inline] #[target_feature(enable = "sse")] #[cfg_attr(test, assert_instr(ldmxcsr))] From 3d9b318a25391fb2001cb59f9f3215d9e1021572 Mon Sep 17 00:00:00 2001 From: Gabriel Majeri Date: Thu, 10 Oct 2019 18:17:47 +0300 Subject: [PATCH 2/4] Update deprecation message and documentation --- crates/core_arch/src/x86/sse.rs | 128 +------------------------------- 1 file changed, 3 insertions(+), 125 deletions(-) diff --git a/crates/core_arch/src/x86/sse.rs b/crates/core_arch/src/x86/sse.rs index a5533aa05e..69f9ad96bf 100644 --- a/crates/core_arch/src/x86/sse.rs +++ b/crates/core_arch/src/x86/sse.rs @@ -1373,7 +1373,7 @@ pub unsafe fn _mm_sfence() { /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_getcsr) #[rustc_deprecated( since = "1.40.0", - reason = "modifying MXCSR causes undefined behavior in LLVM, see https://github.com/rust-lang/stdarch/issues/781" + reason = "accessing floating point exception state causes undefined behavior in LLVM, see https://github.com/rust-lang/stdarch/issues/781" )] #[inline] #[target_feature(enable = "sse")] @@ -1387,134 +1387,12 @@ pub unsafe fn _mm_getcsr() -> u32 { /// Sets the MXCSR register with the 32-bit unsigned integer value. /// -/// This register constrols how SIMD instructions handle floating point -/// operations. Modifying this register only affects the current thread. -/// -/// It contains several groups of flags: -/// -/// * *Exception flags* report which exceptions occurred since last they were -/// reset. -/// -/// * *Masking flags* can be used to mask (ignore) certain exceptions. By -/// default -/// these flags are all set to 1, so all exceptions are masked. When an -/// an exception is masked, the processor simply sets the exception flag and -/// continues the operation. If the exception is unmasked, the flag is also set -/// but additionally an exception handler is invoked. -/// -/// * *Rounding mode flags* control the rounding mode of floating point -/// instructions. -/// -/// * The *denormals-are-zero mode flag* turns all numbers which would be -/// denormalized (exponent bits are all zeros) into zeros. -/// -/// ## Exception Flags -/// -/// * `_MM_EXCEPT_INVALID`: An invalid operation was performed (e.g., dividing -/// Infinity by Infinity). -/// -/// * `_MM_EXCEPT_DENORM`: An operation attempted to operate on a denormalized -/// number. Mainly this can cause loss of precision. -/// -/// * `_MM_EXCEPT_DIV_ZERO`: Division by zero occurred. -/// -/// * `_MM_EXCEPT_OVERFLOW`: A numeric overflow exception occurred, i.e., a -/// result was too large to be represented (e.g., an `f32` with absolute -/// value -/// greater than `2^128`). -/// -/// * `_MM_EXCEPT_UNDERFLOW`: A numeric underflow exception occurred, i.e., a -/// result was too small to be represented in a normalized way (e.g., an -/// `f32` -/// with absulte value smaller than `2^-126`.) -/// -/// * `_MM_EXCEPT_INEXACT`: An inexact-result exception occurred (a.k.a. -/// precision exception). This means some precision was lost due to rounding. -/// For example, the fraction `1/3` cannot be represented accurately in a -/// 32 or 64 bit float and computing it would cause this exception to be -/// raised. Precision exceptions are very common, so they are usually masked. -/// -/// Exception flags can be read and set using the convenience functions -/// `_MM_GET_EXCEPTION_STATE` and `_MM_SET_EXCEPTION_STATE`. For example, to -/// check if an operation caused some overflow: -/// -/// ```rust,ignore -/// _MM_SET_EXCEPTION_STATE(0); // clear all exception flags -/// // perform calculations -/// if _MM_GET_EXCEPTION_STATE() & _MM_EXCEPT_OVERFLOW != 0 { -/// // handle overflow -/// } -/// ``` -/// -/// ## Masking Flags -/// -/// There is one masking flag for each exception flag: `_MM_MASK_INVALID`, -/// `_MM_MASK_DENORM`, `_MM_MASK_DIV_ZERO`, `_MM_MASK_OVERFLOW`, -/// `_MM_MASK_UNDERFLOW`, `_MM_MASK_INEXACT`. -/// -/// A single masking bit can be set via -/// -/// ```rust,ignore -/// _MM_SET_EXCEPTION_MASK(_MM_MASK_UNDERFLOW); -/// ``` -/// -/// However, since mask bits are by default all set to 1, it is more common to -/// want to *disable* certain bits. For example, to unmask the underflow -/// exception, use: -/// -/// ```rust,ignore -/// _mm_setcsr(_mm_getcsr() & !_MM_MASK_UNDERFLOW); // unmask underflow -/// exception -/// ``` -/// -/// Warning: an unmasked exception will cause an exception handler to be -/// called. -/// The standard handler will simply terminate the process. So, in this case -/// any underflow exception would terminate the current process with something -/// like `signal: 8, SIGFPE: erroneous arithmetic operation`. -/// -/// ## Rounding Mode -/// -/// The rounding mode is describe using two bits. It can be read and set using -/// the convenience wrappers `_MM_GET_ROUNDING_MODE()` and -/// `_MM_SET_ROUNDING_MODE(mode)`. -/// -/// The rounding modes are: -/// -/// * `_MM_ROUND_NEAREST`: (default) Round to closest to the infinite precision -/// value. If two values are equally close, round to even (i.e., least -/// significant bit will be zero). -/// -/// * `_MM_ROUND_DOWN`: Round toward negative Infinity. -/// -/// * `_MM_ROUND_UP`: Round toward positive Infinity. -/// -/// * `_MM_ROUND_TOWARD_ZERO`: Round towards zero (truncate). -/// -/// Example: -/// -/// ```rust,ignore -/// _MM_SET_ROUNDING_MODE(_MM_ROUND_DOWN) -/// ``` -/// -/// ## Denormals-are-zero/Flush-to-zero Mode -/// -/// If this bit is set, values that would be denormalized will be set to zero -/// instead. This is turned off by default. -/// -/// You can read and enable/disable this mode via the helper functions -/// `_MM_GET_FLUSH_ZERO_MODE()` and `_MM_SET_FLUSH_ZERO_MODE()`: -/// -/// ```rust,ignore -/// _MM_SET_FLUSH_ZERO_MODE(_MM_FLUSH_ZERO_OFF); // turn off (default) -/// _MM_SET_FLUSH_ZERO_MODE(_MM_FLUSH_ZERO_ON); // turn on -/// ``` -/// +/// This function cannot be used safely as it causes undefined behavior in LLVM. /// /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_setcsr) #[rustc_deprecated( since = "1.40.0", - reason = "modifying MXCSR causes undefined behavior in LLVM, see https://github.com/rust-lang/stdarch/issues/781" + reason = "accessing floating point exception state causes undefined behavior in LLVM, see https://github.com/rust-lang/stdarch/issues/781" )] #[inline] #[target_feature(enable = "sse")] From 6d907875265c006a377e895f99758d301df03594 Mon Sep 17 00:00:00 2001 From: Gabriel Majeri Date: Wed, 22 Dec 2021 18:29:47 +0200 Subject: [PATCH 3/4] Update nightly version tag --- crates/core_arch/src/x86/sse.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/core_arch/src/x86/sse.rs b/crates/core_arch/src/x86/sse.rs index 69f9ad96bf..7e4e998519 100644 --- a/crates/core_arch/src/x86/sse.rs +++ b/crates/core_arch/src/x86/sse.rs @@ -1372,7 +1372,7 @@ pub unsafe fn _mm_sfence() { /// /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_getcsr) #[rustc_deprecated( - since = "1.40.0", + since = "1.59.0", reason = "accessing floating point exception state causes undefined behavior in LLVM, see https://github.com/rust-lang/stdarch/issues/781" )] #[inline] @@ -1391,7 +1391,7 @@ pub unsafe fn _mm_getcsr() -> u32 { /// /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_setcsr) #[rustc_deprecated( - since = "1.40.0", + since = "1.59.0", reason = "accessing floating point exception state causes undefined behavior in LLVM, see https://github.com/rust-lang/stdarch/issues/781" )] #[inline] From 95e3d7c9e693f3623c5edd21386e48635447609c Mon Sep 17 00:00:00 2001 From: Gabriel Majeri Date: Wed, 22 Dec 2021 19:41:57 +0200 Subject: [PATCH 4/4] Deprecated all MXCSR-related functions --- crates/core_arch/src/x86/sse.rs | 116 +++++++++++++------------------- 1 file changed, 48 insertions(+), 68 deletions(-) diff --git a/crates/core_arch/src/x86/sse.rs b/crates/core_arch/src/x86/sse.rs index 7e4e998519..f85807f425 100644 --- a/crates/core_arch/src/x86/sse.rs +++ b/crates/core_arch/src/x86/sse.rs @@ -1371,14 +1371,14 @@ pub unsafe fn _mm_sfence() { /// For more info see [`_mm_setcsr`](fn._mm_setcsr.html) /// /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_getcsr) -#[rustc_deprecated( - since = "1.59.0", - reason = "accessing floating point exception state causes undefined behavior in LLVM, see https://github.com/rust-lang/stdarch/issues/781" -)] #[inline] #[target_feature(enable = "sse")] #[cfg_attr(test, assert_instr(stmxcsr))] #[stable(feature = "simd_x86", since = "1.27.0")] +#[rustc_deprecated( + since = "1.59.0", + reason = "accessing floating point exception state causes undefined behavior in LLVM, see https://github.com/rust-lang/stdarch/issues/781" +)] pub unsafe fn _mm_getcsr() -> u32 { let mut result = 0_i32; stmxcsr((&mut result) as *mut _ as *mut i8); @@ -1390,14 +1390,14 @@ pub unsafe fn _mm_getcsr() -> u32 { /// This function cannot be used safely as it causes undefined behavior in LLVM. /// /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_setcsr) -#[rustc_deprecated( - since = "1.59.0", - reason = "accessing floating point exception state causes undefined behavior in LLVM, see https://github.com/rust-lang/stdarch/issues/781" -)] #[inline] #[target_feature(enable = "sse")] #[cfg_attr(test, assert_instr(ldmxcsr))] #[stable(feature = "simd_x86", since = "1.27.0")] +#[rustc_deprecated( + since = "1.59.0", + reason = "accessing floating point exception state causes undefined behavior in LLVM, see https://github.com/rust-lang/stdarch/issues/781" +)] pub unsafe fn _mm_setcsr(val: u32) { ldmxcsr(&val as *const _ as *const i8); } @@ -1477,9 +1477,13 @@ pub const _MM_FLUSH_ZERO_OFF: u32 = 0x0000; /// /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_MM_GET_EXCEPTION_MASK) #[inline] -#[allow(non_snake_case)] +#[allow(deprecated, non_snake_case)] #[target_feature(enable = "sse")] #[stable(feature = "simd_x86", since = "1.27.0")] +#[rustc_deprecated( + since = "1.59.0", + reason = "accessing floating point exception state causes undefined behavior in LLVM, see https://github.com/rust-lang/stdarch/issues/781" +)] pub unsafe fn _MM_GET_EXCEPTION_MASK() -> u32 { _mm_getcsr() & _MM_MASK_MASK } @@ -1488,9 +1492,13 @@ pub unsafe fn _MM_GET_EXCEPTION_MASK() -> u32 { /// /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_MM_GET_EXCEPTION_STATE) #[inline] -#[allow(non_snake_case)] +#[allow(deprecated, non_snake_case)] #[target_feature(enable = "sse")] #[stable(feature = "simd_x86", since = "1.27.0")] +#[rustc_deprecated( + since = "1.59.0", + reason = "accessing floating point exception state causes undefined behavior in LLVM, see https://github.com/rust-lang/stdarch/issues/781" +)] pub unsafe fn _MM_GET_EXCEPTION_STATE() -> u32 { _mm_getcsr() & _MM_EXCEPT_MASK } @@ -1499,9 +1507,13 @@ pub unsafe fn _MM_GET_EXCEPTION_STATE() -> u32 { /// /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_MM_GET_FLUSH_ZERO_MODE) #[inline] -#[allow(non_snake_case)] +#[allow(deprecated, non_snake_case)] #[target_feature(enable = "sse")] #[stable(feature = "simd_x86", since = "1.27.0")] +#[rustc_deprecated( + since = "1.59.0", + reason = "accessing floating point exception state causes undefined behavior in LLVM, see https://github.com/rust-lang/stdarch/issues/781" +)] pub unsafe fn _MM_GET_FLUSH_ZERO_MODE() -> u32 { _mm_getcsr() & _MM_FLUSH_ZERO_MASK } @@ -1510,9 +1522,13 @@ pub unsafe fn _MM_GET_FLUSH_ZERO_MODE() -> u32 { /// /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_MM_GET_ROUNDING_MODE) #[inline] -#[allow(non_snake_case)] +#[allow(deprecated, non_snake_case)] #[target_feature(enable = "sse")] #[stable(feature = "simd_x86", since = "1.27.0")] +#[rustc_deprecated( + since = "1.59.0", + reason = "accessing floating point exception state causes undefined behavior in LLVM, see https://github.com/rust-lang/stdarch/issues/781" +)] pub unsafe fn _MM_GET_ROUNDING_MODE() -> u32 { _mm_getcsr() & _MM_ROUND_MASK } @@ -1521,9 +1537,13 @@ pub unsafe fn _MM_GET_ROUNDING_MODE() -> u32 { /// /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_MM_SET_EXCEPTION_MASK) #[inline] -#[allow(non_snake_case)] +#[allow(deprecated, non_snake_case)] #[target_feature(enable = "sse")] #[stable(feature = "simd_x86", since = "1.27.0")] +#[rustc_deprecated( + since = "1.59.0", + reason = "accessing floating point exception state causes undefined behavior in LLVM, see https://github.com/rust-lang/stdarch/issues/781" +)] pub unsafe fn _MM_SET_EXCEPTION_MASK(x: u32) { _mm_setcsr((_mm_getcsr() & !_MM_MASK_MASK) | x) } @@ -1532,9 +1552,13 @@ pub unsafe fn _MM_SET_EXCEPTION_MASK(x: u32) { /// /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_MM_SET_EXCEPTION_STATE) #[inline] -#[allow(non_snake_case)] +#[allow(deprecated, non_snake_case)] #[target_feature(enable = "sse")] #[stable(feature = "simd_x86", since = "1.27.0")] +#[rustc_deprecated( + since = "1.59.0", + reason = "accessing floating point exception state causes undefined behavior in LLVM, see https://github.com/rust-lang/stdarch/issues/781" +)] pub unsafe fn _MM_SET_EXCEPTION_STATE(x: u32) { _mm_setcsr((_mm_getcsr() & !_MM_EXCEPT_MASK) | x) } @@ -1543,9 +1567,13 @@ pub unsafe fn _MM_SET_EXCEPTION_STATE(x: u32) { /// /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_MM_SET_FLUSH_ZERO_MODE) #[inline] -#[allow(non_snake_case)] +#[allow(deprecated, non_snake_case)] #[target_feature(enable = "sse")] #[stable(feature = "simd_x86", since = "1.27.0")] +#[rustc_deprecated( + since = "1.59.0", + reason = "accessing floating point exception state causes undefined behavior in LLVM, see https://github.com/rust-lang/stdarch/issues/781" +)] pub unsafe fn _MM_SET_FLUSH_ZERO_MODE(x: u32) { let val = (_mm_getcsr() & !_MM_FLUSH_ZERO_MASK) | x; // println!("setting csr={:x}", val); @@ -1556,9 +1584,13 @@ pub unsafe fn _MM_SET_FLUSH_ZERO_MODE(x: u32) { /// /// [Intel's documentation](https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_MM_SET_ROUNDING_MODE) #[inline] -#[allow(non_snake_case)] +#[allow(deprecated, non_snake_case)] #[target_feature(enable = "sse")] #[stable(feature = "simd_x86", since = "1.27.0")] +#[rustc_deprecated( + since = "1.59.0", + reason = "accessing floating point exception state causes undefined behavior in LLVM, see https://github.com/rust-lang/stdarch/issues/781" +)] pub unsafe fn _MM_SET_ROUNDING_MODE(x: u32) { _mm_setcsr((_mm_getcsr() & !_MM_ROUND_MASK) | x) } @@ -3077,58 +3109,6 @@ mod tests { _mm_sfence(); } - #[simd_test(enable = "sse")] - unsafe fn test_mm_getcsr_setcsr_1() { - let saved_csr = _mm_getcsr(); - - let a = _mm_setr_ps(1.1e-36, 0.0, 0.0, 1.0); - let b = _mm_setr_ps(0.001, 0.0, 0.0, 1.0); - - _MM_SET_FLUSH_ZERO_MODE(_MM_FLUSH_ZERO_ON); - let r = _mm_mul_ps(*black_box(&a), *black_box(&b)); - - _mm_setcsr(saved_csr); - - let exp = _mm_setr_ps(0.0, 0.0, 0.0, 1.0); - assert_eq_m128(r, exp); // first component is a denormalized f32 - } - - #[simd_test(enable = "sse")] - unsafe fn test_mm_getcsr_setcsr_2() { - // Same as _mm_setcsr_1 test, but with opposite flag value. - - let saved_csr = _mm_getcsr(); - - let a = _mm_setr_ps(1.1e-36, 0.0, 0.0, 1.0); - let b = _mm_setr_ps(0.001, 0.0, 0.0, 1.0); - - _MM_SET_FLUSH_ZERO_MODE(_MM_FLUSH_ZERO_OFF); - let r = _mm_mul_ps(*black_box(&a), *black_box(&b)); - - _mm_setcsr(saved_csr); - - let exp = _mm_setr_ps(1.1e-39, 0.0, 0.0, 1.0); - assert_eq_m128(r, exp); // first component is a denormalized f32 - } - - #[simd_test(enable = "sse")] - unsafe fn test_mm_getcsr_setcsr_underflow() { - _MM_SET_EXCEPTION_STATE(0); - - let a = _mm_setr_ps(1.1e-36, 0.0, 0.0, 1.0); - let b = _mm_setr_ps(1e-5, 0.0, 0.0, 1.0); - - assert_eq!(_MM_GET_EXCEPTION_STATE(), 0); // just to be sure - - let r = _mm_mul_ps(*black_box(&a), *black_box(&b)); - - let exp = _mm_setr_ps(1.1e-41, 0.0, 0.0, 1.0); - assert_eq_m128(r, exp); - - let underflow = _MM_GET_EXCEPTION_STATE() & _MM_EXCEPT_UNDERFLOW != 0; - assert_eq!(underflow, true); - } - #[simd_test(enable = "sse")] unsafe fn test_MM_TRANSPOSE4_PS() { let mut a = _mm_setr_ps(1.0, 2.0, 3.0, 4.0);