X86_64 simd segfault

The code below runs successfully in release mode, but segfaults in debug mode. In debug mode, it can be fixed by adding a print statement (see comment)

use std::arch::x86_64::{_mm256_add_ps, _mm256_set_ps, _mm256_store_ps};

fn main() {
    unsafe { f() };
}

unsafe fn f() {
    let mut x = [0.0; 8];
    let a = _mm256_set_ps(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0);
    let b = _mm256_set_ps(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0);
    let c = _mm256_add_ps(a, b);
    // println!("{c:?}"); // we can avoid segfault by printing here
    _mm256_store_ps(x.as_mut_ptr(), c);
    println!("{x:?}");
}

This is reproducible in the playground

Running coredumpctl debug suggests that the error is at core::core_arch::x86::avx::_mm256_store_ps

What exactly is happening here?

Have a try at getting answer before looking.

    #[repr(align(32))]
    #[derive(Debug)]
    struct A([f32; 8]);
    let mut x = A([0.0; 8]);
6 Likes

thanks :smile:

I wonder if _mm256_store_ps could benefit from more type...

use std::{arch::x86_64::{__m256, _mm256_add_ps, _mm256_set_ps, _mm256_store_ps}, mem::MaybeUninit};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    unsafe { f() };
    Ok(())
}

#[repr(align(32))]
#[derive(Debug)]
pub struct A([f32; 8]);

#[inline]
pub unsafe fn typed_mm256_store_ps(mem_addr: *mut A, a: __m256) {
    _mm256_store_ps(mem_addr as *mut _, a);
}

unsafe fn f() {
    let mut x = MaybeUninit::uninit();
    let a = _mm256_set_ps(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0);
    let b = _mm256_set_ps(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0);
    let c = _mm256_add_ps(a, b);
    typed_mm256_store_ps(x.as_mut_ptr(), c);
    let x = x.assume_init();
    println!("{:?}", x);
}

_mm256_store_ps is meant to be a low-level primitive that allows you to avoid dropping directly to assembly language for SIMD, and is unsafe because there's a pile of preconditions you've got to comply with (but it's supposed to work with all sorts of interesting data structures as long as you meet the preconditions).

The type-safe SIMD stuff lives in std::simd, but it's not yet stable.

1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.