Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

There's seemingly no way to construct a __m128i in a const fn #403

Closed
shepmaster opened this issue Mar 27, 2018 · 5 comments
Closed

There's seemingly no way to construct a __m128i in a const fn #403

shepmaster opened this issue Mar 27, 2018 · 5 comments

Comments

@shepmaster
Copy link
Member

My ideal case would be to take a &[u8] and "fill up" a __m128:

let needle: __m128i = bytes.collect(); // Takes the first 16 bytes, zero-initialized otherwise

// or

let mut needle = __m128i::default(); // zero-initialize
needle.extend(bytes); // Takes the first 16 bytes

However, none of the "nice" traits are implemented for these types, and I've gotten the feeling that is no accident. Basically, I can use an intrinsic function to set it (e.g. _mm_setzero_si128), or I can convert from u8x16 and friends.

The intrinsics are not const, so they cannot be used in a const fn context.

The closest I could find was

u8x16::new(
    x0, x1, x2, x3, x4, x5, x6, x7,
    x8, x9, x10, x11, x12, x13, x14, x15,
).into_bits()

but into_bits is likewise not const.

@BurntSushi
Copy link
Member

BurntSushi commented Mar 27, 2018

I'm having trouble connecting the dots in your issue, so I'll just vomit out two things and see what sticks. :-)

My ideal case would be to take a &[u8] and "fill up" a __m128:

Ignoring the "const" part of your request, I would use _mm_loadu_si128 or _mm_load_si128, depending on whether you're loading unaligned or aligned data, respectively.

There's seemingly no way to construct a __m128i in a const fn

I think the way to do this (right now at least) is via a union

union u8x16 {
    vector: __m128i,
    bytes: [u8; 16],
}

const ZERO: __m128i = unsafe { (u8x16 { bytes: [0; 16] }).vector };

playground link

@gnzlbg
Copy link
Contributor

gnzlbg commented Mar 27, 2018

I think the way to do this (right now at least) is via a union

Yes, in the future mem::uninitialized and mem::zero should become const fns, which will allow you to transmute a std::simd::u8x16 type (which has const fn constructors) directly into an __m128i. But that's blocked on rust-lang/rfcs#411 being fixed, and on the portable packed vector types RFC being merged: rust-lang/rfcs#2366

@shepmaster
Copy link
Member Author

mem::uninitialized and mem::zero should become const fns, which will allow you to transmute a std::simd::u8x16 type (which has const fn constructors) directly into an __m128i

I think I'm missing a step here. How do mem::uninitialized or mem::zero allow for transmuting?

@gnzlbg
Copy link
Contributor

gnzlbg commented Mar 27, 2018

I think I'm missing a step here. How do mem::uninitialized or mem::zero allow for transmuting?

Oh sorry, mem::transmute is what should become const fn here.

@alexcrichton
Copy link
Member

I think this has basically been resolved, so closing

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants