While playing around with some complex numbers (structures with two f64s), I noticed Rust was generating unaligned loads, so I added the #[repr(align(16))] parameter to them. But Rust was still generating unaligned operations.
I redeclared the parameter as a local variable, and it got fixed. It only seems to happen when using a pattern to unpack the fields of an aligned structure.
Minimal repro (also on play.rust-lang.org):
#[repr(align(16))]
pub struct Complex {
real: f64,
imag: f64,
}
pub struct Compound {
a: Complex,
}
pub fn load_unaligned(cmp: Compound) -> f64 {
let Complex { real, imag } = cmp.a;
(real * real) + (imag * imag)
}
pub fn load_aligned(cmp: Compound) -> f64 {
let cmp = cmp;
let Complex { real, imag } = cmp.a;
(real * real) + (imag * imag)
}
While the functions look nearly the same, the disassembly differs:
playground::load_unaligned:
; unaligned loads
movupd xmm1, xmmword ptr [rdi]
mulpd xmm1, xmm1
movapd xmm0, xmm1
movhlps xmm0, xmm0
addsd xmm0, xmm1
ret
playground::load_aligned:
; this one generates faster, aligned loads:
movapd xmm1, xmmword ptr [rdi]
mulpd xmm1, xmm1
movapd xmm0, xmm1
movhlps xmm0, xmm0
addsd xmm0, xmm1
ret
This bug occurs on stable 1.28, beta and nightly.
While playing around with some complex numbers (structures with two
f64s), I noticed Rust was generating unaligned loads, so I added the#[repr(align(16))]parameter to them. But Rust was still generating unaligned operations.I redeclared the parameter as a local variable, and it got fixed. It only seems to happen when using a pattern to unpack the fields of an aligned structure.
Minimal repro (also on play.rust-lang.org):
While the functions look nearly the same, the disassembly differs:
This bug occurs on stable 1.28, beta and nightly.