sse2.rs - source
Description: Source of the Rust file `library/core/src/../../stdarch/crates/core_arch/src/x86_64/sse2.rs`.

#
core/stdarch/crates/core_arch/src/x86_64/
sse2.rs

    1//! `x86_64`'s Streaming SIMD Extensions 2 (SSE2)
    2
    3use crate::core_arch::x86::*;
    4
    5#[cfg(test)]
    6use stdarch_test::assert_instr;
    7
    8#[allow(improper_ctypes)]
    9unsafe extern "C" {
    10    #[link_name = "llvm.x86.sse2.cvtsd2si64"]
    11    fn cvtsd2si64(a: __m128d) -> i64;
    12    #[link_name = "llvm.x86.sse2.cvttsd2si64"]
    13    fn cvttsd2si64(a: __m128d) -> i64;
    14}
    15
    16/// Converts the lower double-precision (64-bit) floating-point element in a to
    17/// a 64-bit integer.
    18///
    19/// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_cvtsd_si64)
    20#[inline]
    21#[target_feature(enable = "sse2")]
    22#[cfg_attr(test, assert_instr(cvtsd2si))]
    23#[stable(feature = "simd_x86", since = "1.27.0")]
    24pub fn _mm_cvtsd_si64(a: __m128d) -> i64 {
    25    unsafe { cvtsd2si64(a) }
    26}
    27
    28/// Alias for `_mm_cvtsd_si64`
    29///
    30/// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_cvtsd_si64x)
    31#[inline]
    32#[target_feature(enable = "sse2")]
    33#[cfg_attr(test, assert_instr(cvtsd2si))]
    34#[stable(feature = "simd_x86", since = "1.27.0")]
    35pub fn _mm_cvtsd_si64x(a: __m128d) -> i64 {
    36    _mm_cvtsd_si64(a)
    37}
    38
    39/// Converts the lower double-precision (64-bit) floating-point element in `a`
    40/// to a 64-bit integer with truncation.
    41///
    42/// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_cvttsd_si64)
    43#[inline]
    44#[target_feature(enable = "sse2")]
    45#[cfg_attr(test, assert_instr(cvttsd2si))]
    46#[stable(feature = "simd_x86", since = "1.27.0")]
    47pub fn _mm_cvttsd_si64(a: __m128d) -> i64 {
    48    unsafe { cvttsd2si64(a) }
    49}
    50
    51/// Alias for `_mm_cvttsd_si64`
    52///
    53/// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_cvttsd_si64x)
    54#[inline]
    55#[target_feature(enable = "sse2")]
    56#[cfg_attr(test, assert_instr(cvttsd2si))]
    57#[stable(feature = "simd_x86", since = "1.27.0")]
    58pub fn _mm_cvttsd_si64x(a: __m128d) -> i64 {
    59    _mm_cvttsd_si64(a)
    60}
    61
    62/// Stores a 64-bit integer value in the specified memory location.
    63/// To minimize caching, the data is flagged as non-temporal (unlikely to be
    64/// used again soon).
    65///
    66/// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_stream_si64)
    67///
    68/// # Safety of non-temporal stores
    69///
    70/// After using this intrinsic, but before any other access to the memory that this intrinsic
    71/// mutates, a call to [`_mm_sfence`] must be performed by the thread that used the intrinsic. In
    72/// particular, functions that call this intrinsic should generally call `_mm_sfence` before they
    73/// return.
    74///
    75/// See [`_mm_sfence`] for details.
    76#[inline]
    77#[target_feature(enable = "sse2")]
    78#[cfg_attr(test, assert_instr(movnti))]
    79#[stable(feature = "simd_x86", since = "1.27.0")]
    80pub unsafe fn _mm_stream_si64(mem_addr: *mut i64, a: i64) {
    81    // see #1541, we should use inline asm to be sure, because LangRef isn't clear enough
    82    crate::arch::asm!(
    83        vps!("movnti", ",{a}"),
    84        p = in(reg) mem_addr,
    85        a = in(reg) a,
    86        options(nostack, preserves_flags),
    87    );
    88}
    89
    90/// Returns a vector whose lowest element is `a` and all higher elements are
    91/// `0`.
    92///
    93/// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_cvtsi64_si128)
    94#[inline]
    95#[target_feature(enable = "sse2")]
    96#[cfg_attr(test, assert_instr(movq))]
    97#[stable(feature = "simd_x86", since = "1.27.0")]
    98#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")]
    99pub const fn _mm_cvtsi64_si128(a: i64) -> __m128i {
    100    _mm_set_epi64x(0, a)
    101}
    102
    103/// Returns a vector whose lowest element is `a` and all higher elements are
    104/// `0`.
    105///
    106/// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_cvtsi64x_si128)
    107#[inline]
    108#[target_feature(enable = "sse2")]
    109#[cfg_attr(test, assert_instr(movq))]
    110#[stable(feature = "simd_x86", since = "1.27.0")]
    111#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")]
    112pub const fn _mm_cvtsi64x_si128(a: i64) -> __m128i {
    113    _mm_cvtsi64_si128(a)
    114}
    115
    116/// Returns the lowest element of `a`.
    117///
    118/// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_cvtsi128_si64)
    119#[inline]
    120#[target_feature(enable = "sse2")]
    121#[cfg_attr(test, assert_instr(movq))]
    122#[stable(feature = "simd_x86", since = "1.27.0")]
    123#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")]
    124pub const fn _mm_cvtsi128_si64(a: __m128i) -> i64 {
    125    unsafe { simd_extract!(a.as_i64x2(), 0) }
    126}
    127
    128/// Returns the lowest element of `a`.
    129///
    130/// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_cvtsi128_si64x)
    131#[inline]
    132#[target_feature(enable = "sse2")]
    133#[cfg_attr(test, assert_instr(movq))]
    134#[stable(feature = "simd_x86", since = "1.27.0")]
    135#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")]
    136pub const fn _mm_cvtsi128_si64x(a: __m128i) -> i64 {
    137    _mm_cvtsi128_si64(a)
    138}
    139
    140/// Returns `a` with its lower element replaced by `b` after converting it to
    141/// an `f64`.
    142///
    143/// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_cvtsi64_sd)
    144#[inline]
    145#[target_feature(enable = "sse2")]
    146#[cfg_attr(test, assert_instr(cvtsi2sd))]
    147#[stable(feature = "simd_x86", since = "1.27.0")]
    148#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")]
    149pub const fn _mm_cvtsi64_sd(a: __m128d, b: i64) -> __m128d {
    150    unsafe { simd_insert!(a, 0, b as f64) }
    151}
    152
    153/// Returns `a` with its lower element replaced by `b` after converting it to
    154/// an `f64`.
    155///
    156/// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_cvtsi64x_sd)
    157#[inline]
    158#[target_feature(enable = "sse2")]
    159#[cfg_attr(test, assert_instr(cvtsi2sd))]
    160#[stable(feature = "simd_x86", since = "1.27.0")]
    161#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")]
    162pub const fn _mm_cvtsi64x_sd(a: __m128d, b: i64) -> __m128d {
    163    _mm_cvtsi64_sd(a, b)
    164}
    165
    166#[cfg(test)]
    167mod tests {
    168    use crate::core_arch::arch::x86_64::*;
    169    use crate::core_arch::assert_eq_const as assert_eq;
    170    use std::boxed;
    171    use std::ptr;
    172    use stdarch_test::simd_test;
    173
    174    #[simd_test(enable = "sse2")]
    175    fn test_mm_cvtsd_si64() {
    176        let r = _mm_cvtsd_si64(_mm_setr_pd(-2.0, 5.0));
    177        assert_eq!(r, -2_i64);
    178
    179        let r = _mm_cvtsd_si64(_mm_setr_pd(f64::MAX, f64::MIN));
    180        assert_eq!(r, i64::MIN);
    181    }
    182
    183    #[simd_test(enable = "sse2")]
    184    fn test_mm_cvtsd_si64x() {
    185        let r = _mm_cvtsd_si64x(_mm_setr_pd(f64::NAN, f64::NAN));
    186        assert_eq!(r, i64::MIN);
    187    }
    188
    189    #[simd_test(enable = "sse2")]
    190    fn test_mm_cvttsd_si64() {
    191        let a = _mm_setr_pd(-1.1, 2.2);
    192        let r = _mm_cvttsd_si64(a);
    193        assert_eq!(r, -1_i64);
    194    }
    195
    196    #[simd_test(enable = "sse2")]
    197    fn test_mm_cvttsd_si64x() {
    198        let a = _mm_setr_pd(f64::NEG_INFINITY, f64::NAN);
    199        let r = _mm_cvttsd_si64x(a);
    200        assert_eq!(r, i64::MIN);
    201    }
    202
    203    #[simd_test(enable = "sse2")]
    204    // Miri cannot support this until it is clear how it fits in the Rust memory model
    205    // (non-temporal store)
    206    #[cfg_attr(miri, ignore)]
    207    unsafe fn test_mm_stream_si64() {
    208        let a: i64 = 7;
    209        let mut mem = boxed::Box::<i64>::new(-1);
    210        _mm_stream_si64(ptr::addr_of_mut!(*mem), a);
    211        _mm_sfence();
    212        assert_eq!(a, *mem);
    213    }
    214
    215    #[simd_test(enable = "sse2")]
    216    const fn test_mm_cvtsi64_si128() {
    217        let r = _mm_cvtsi64_si128(5);
    218        assert_eq_m128i(r, _mm_setr_epi64x(5, 0));
    219    }
    220
    221    #[simd_test(enable = "sse2")]
    222    const fn test_mm_cvtsi128_si64() {
    223        let r = _mm_cvtsi128_si64(_mm_setr_epi64x(5, 0));
    224        assert_eq!(r, 5);
    225    }
    226
    227    #[simd_test(enable = "sse2")]
    228    const fn test_mm_cvtsi64_sd() {
    229        let a = _mm_set1_pd(3.5);
    230        let r = _mm_cvtsi64_sd(a, 5);
    231        assert_eq_m128d(r, _mm_setr_pd(5.0, 3.5));
    232    }
    233}