Created
July 13, 2019 22:37
-
-
Save rust-play/c97f79a6c5ee81b82d044349cd267acb to your computer and use it in GitHub Desktop.
Code shared from the Rust Playground
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#[test] | |
#[allow(clippy::float_cmp)] | |
fn sse_sanity_tests() { | |
// Note(Lokathor): Here is where many sanity checks for our assumptions of | |
// `__m128` will go. | |
#[cfg(target_arch = "x86")] | |
use core::arch::x86::*; | |
#[cfg(target_arch = "x86_64")] | |
use core::arch::x86_64::*; | |
use core::mem::*; | |
unsafe { | |
// An `__m128` is "basically" an `[f32;4]`, and if you inspect the inside | |
// with pointer math stuff you get floats at each offset that are the same | |
// as the indexes of the array you transmuted to get the `__m128`. | |
let m: __m128 = transmute([5.0_f32, 6.0, 7.0, 8.0]); | |
let m_ptr: *const f32 = &m as *const __m128 as *const f32; | |
assert_eq!(*m_ptr.offset(0), 5.0); | |
assert_eq!(*m_ptr.offset(1), 6.0); | |
assert_eq!(*m_ptr.offset(2), 7.0); | |
assert_eq!(*m_ptr.offset(3), 8.0); | |
// Confusingly, the `set` order places the data into the lanes _backwards_ | |
// from the array index ordering. | |
let m: __m128 = _mm_set_ps(5.0, 6.0, 7.0, 8.0); | |
let m_ptr: *const f32 = &m as *const __m128 as *const f32; | |
assert_eq!(*m_ptr.offset(0), 8.0); | |
assert_eq!(*m_ptr.offset(1), 7.0); | |
assert_eq!(*m_ptr.offset(2), 6.0); | |
assert_eq!(*m_ptr.offset(3), 5.0); | |
// And then the `setr` order places the data into the lanes the same as the | |
// array index ordering. | |
let m: __m128 = _mm_setr_ps(5.0, 6.0, 7.0, 8.0); | |
let m_ptr: *const f32 = &m as *const __m128 as *const f32; | |
assert_eq!(*m_ptr.offset(0), 5.0); | |
assert_eq!(*m_ptr.offset(1), 6.0); | |
assert_eq!(*m_ptr.offset(2), 7.0); | |
assert_eq!(*m_ptr.offset(3), 8.0); | |
// The "low" lane is offset 0 | |
let m: __m128 = _mm_set_ss(5.0); | |
let m_ptr: *const f32 = &m as *const __m128 as *const f32; | |
assert_eq!(*m_ptr.offset(0), 5.0); | |
assert_eq!(*m_ptr.offset(1), 0.0); | |
assert_eq!(*m_ptr.offset(2), 0.0); | |
assert_eq!(*m_ptr.offset(3), 0.0); | |
// Some operations affect only the low lane. | |
{ | |
let b: __m128 = _mm_set1_ps(3.0); | |
// PACKED (adds all lanes) | |
let m_b = _mm_add_ps(m, b); | |
let m_b_ptr: *const f32 = &m_b as *const __m128 as *const f32; | |
assert_eq!(*m_b_ptr.offset(0), 8.0); | |
assert_eq!(*m_b_ptr.offset(1), 3.0); | |
assert_eq!(*m_b_ptr.offset(2), 3.0); | |
assert_eq!(*m_b_ptr.offset(3), 3.0); | |
// SINGLE (adds only offset0, other lanes copy "self", `m`) | |
let m_b = _mm_add_ss(m, b); | |
let m_b_ptr: *const f32 = &m_b as *const __m128 as *const f32; | |
assert_eq!(*m_b_ptr.offset(0), 8.0); | |
assert_eq!(*m_b_ptr.offset(1), 0.0); | |
assert_eq!(*m_b_ptr.offset(2), 0.0); | |
assert_eq!(*m_b_ptr.offset(3), 0.0); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment