# Unaligned SIMD (SSE2 in particular) loads/stores

**URL:** <https://internals.rust-lang.org/t/unaligned-simd-sse2-in-particular-loads-stores/4336>\
**Category:** Unsafe Code Guidelines\
**Created:** [November 7, 2016, 9:18am UTC](https://internals.rust-lang.org/t/unaligned-simd-sse2-in-particular-loads-stores/4336 "2016-11-07T09:18:36Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![hsivonen](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/hsivonen/32/4080_2.png) [@hsivonen](https://internals.rust-lang.org/u/hsivonen)\
**Post date:** [November 7, 2016, 9:18am UTC](https://internals.rust-lang.org/t/unaligned-simd-sse2-in-particular-loads-stores/4336/1 "2016-11-07T09:18:36Z")

</div>

It appears that LLVM doesn’t have intrinsics for unaligned loads and stores, so the user of a high-level language can’t talk directly to LLVM to request unaligned loads and stores via something like the `link_llvm_intrinsics` feature. Instead, the compiler for the high-level language needs to provide the means to have the kind of LLVM IR generated that eventually compiles to unaligned load/store instructions.

[Looking at `emmintrin.h`](http://clang.llvm.org/doxygen/emmintrin_8h_source.html#l03408), e.g. the Intel-defined `_mm_loadu_si128` SSE2 intrinsic doesn’t map to a ` __builtin` call but to a dereference of a pointer to a single-member struct annotated with `__ attribute__((__packed __,__ may_alias__))`.

The [`simd` crate](https://github.com/huonw/simd/blob/master/src/common.rs#L111) uses the same pattern for the same purpose with a single-member `#[repr(packed)]` Rust struct. In debug builds, this works if the result of the dereference is assigned to a local variable before extracting the single member. [Using an expression without the intermediate variable fails, though.](https://github.com/rust-lang/rust/issues/27060) Furthermore, AFAICT, debug mode doesn’t actually emit a `MOVDQU` instruction but accomplishes the results of the computation by other means.

At present (did it work pre-MIR?), that pattern fails in release mode. The load is emitted as `MOVDQA`, which requires 16-byte alignment.

Given the past and the clang approach, the obvious way forward would be to make the `#[repr(packed)]` pattern work with MIR. However, making things work for packed structs generally seems over-complex considering the narrower goal of accomplishing unaligned SIMD loads/stores and too much of an obscure incantation from the language user perspective.

From the language user perspective, it seems to me that having `read_unaligned()` on `*const` and `*mut` and `write_unaligned()` on `*mut` would be more obvious and would be consistent with `read_volatile()` and `write_volatile()`.

Looking at the LLVM IR clang generates for `_mm_loadu_si128` vs. `_mm_loadu_si128`, it seems that the difference between eventual `MOVDQU` vs. `MOVDQA` instruction generation is annotating the LLVM `load` and `store` instructions with `align 1` instead of `align 16`. It seems to me that it should be possible to add `rust-intrinsic`s `unaligned_load` and `unaligned_store` next to `volatile_load` and `volatile_store` and make the new intrinsics generate LLVM `load` and `store` with `align 1`. Then these could be exposed on `*const` and `*mut` in the same manner as the volatile variants.

Does this seem like an OK way forward?

---

<div class="post-metadata">

**Author:** ![jneem](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jneem/32/3459_2.png) [@jneem](https://internals.rust-lang.org/u/jneem)\
**Post date:** [November 7, 2016, 1:54pm UTC](https://internals.rust-lang.org/t/unaligned-simd-sse2-in-particular-loads-stores/4336/2 "2016-11-07T13:54:51Z")

</div>

Having `read_unaligned()` and `write_unaligned()` would be a nice convenience. It seems, though, that you can currently get unaligned loads by casting the source pointer to `*const u8` and the target pointer to `*mut u8`. For example, see [this](https://github.com/jneem/teddy/blob/master/src/x86/teddy_simd.rs#L120).

---

<div class="post-metadata">

**Author:** ![Amanieu](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/amanieu/32/4095_2.png) [@Amanieu](https://internals.rust-lang.org/u/Amanieu)\
**Post date:** [November 7, 2016, 5:40pm UTC](https://internals.rust-lang.org/t/unaligned-simd-sse2-in-particular-loads-stores/4336/3 "2016-11-07T17:40:04Z")

</div>

I have already opened a [RFC](https://github.com/rust-lang/rfcs/pull/1725) for `read_unaligned` and `write_unaligned`.

---

<div class="post-metadata">

**Author:** ![hsivonen](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/hsivonen/32/4080_2.png) [@hsivonen](https://internals.rust-lang.org/u/hsivonen)\
**Post date:** [November 8, 2016, 7:55am UTC](https://internals.rust-lang.org/t/unaligned-simd-sse2-in-particular-loads-stores/4336/4 "2016-11-08T07:55:38Z")

</div>

Thank you @jneem and @Amanieu. `copy_nonoverlapping` addresses my use case.

---

<div class="post-metadata">

**Author:** ![system](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/system/32/14092_2.png) [@system](https://internals.rust-lang.org/u/system)\
**Post date:** [March 25, 2019, 8:27am UTC](https://internals.rust-lang.org/t/unaligned-simd-sse2-in-particular-loads-stores/4336/5 "2019-03-25T08:27:18Z")

</div>

Closed on March 25, 2019, 8:27am UTC

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.
