Skip to content

Commit 86158f5

Browse files
committed
Make repr(packed) vectors work with SIMD intrinsics
1 parent 959a67a commit 86158f5

File tree

2 files changed

+52
-15
lines changed

2 files changed

+52
-15
lines changed

compiler/rustc_codegen_llvm/src/intrinsic.rs

+48-1
Original file line numberDiff line numberDiff line change
@@ -480,8 +480,55 @@ impl<'ll, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'_, 'll, 'tcx> {
480480
}
481481

482482
_ if name.as_str().starts_with("simd_") => {
483+
// Unpack non-power-of-2 #[repr(packed)]
484+
let mut loaded_args = Vec::new();
485+
for (ty, arg) in arg_tys.iter().zip(args) {
486+
loaded_args.push(
487+
if ty.is_simd()
488+
&& let OperandValue::Ref(place) = arg.val
489+
{
490+
let (size, elem_ty) = ty.simd_size_and_type(self.tcx());
491+
let elem_ll_ty = match elem_ty.kind() {
492+
ty::Float(f) => self.type_float_from_ty(*f),
493+
ty::Int(i) => self.type_int_from_ty(*i),
494+
ty::Uint(u) => self.type_uint_from_ty(*u),
495+
ty::RawPtr(_, _) => self.type_ptr(),
496+
_ => unreachable!(),
497+
};
498+
let loaded =
499+
self.load_from_place(self.type_vector(elem_ll_ty, size), place);
500+
OperandRef::from_immediate_or_packed_pair(self, loaded, arg.layout)
501+
} else {
502+
*arg
503+
},
504+
);
505+
}
506+
507+
let llret_ty = if ret_ty.is_simd()
508+
&& let abi::Abi::Aggregate { .. } = self.layout_of(ret_ty).layout.abi
509+
{
510+
let (size, elem_ty) = ret_ty.simd_size_and_type(self.tcx());
511+
let elem_ll_ty = match elem_ty.kind() {
512+
ty::Float(f) => self.type_float_from_ty(*f),
513+
ty::Int(i) => self.type_int_from_ty(*i),
514+
ty::Uint(u) => self.type_uint_from_ty(*u),
515+
ty::RawPtr(_, _) => self.type_ptr(),
516+
_ => unreachable!(),
517+
};
518+
self.type_vector(elem_ll_ty, size)
519+
} else {
520+
llret_ty
521+
};
522+
483523
match generic_simd_intrinsic(
484-
self, name, callee_ty, fn_args, args, ret_ty, llret_ty, span,
524+
self,
525+
name,
526+
callee_ty,
527+
fn_args,
528+
&loaded_args,
529+
ret_ty,
530+
llret_ty,
531+
span,
485532
) {
486533
Ok(llval) => llval,
487534
Err(()) => return Ok(()),

tests/ui/simd/repr_packed.rs

+4-14
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,6 @@
66
#[repr(simd, packed)]
77
struct Simd<T, const N: usize>([T; N]);
88

9-
#[repr(simd)]
10-
struct FullSimd<T, const N: usize>([T; N]);
11-
129
fn check_size_align<T, const N: usize>() {
1310
use std::mem;
1411
assert_eq!(mem::size_of::<Simd<T, N>>(), mem::size_of::<[T; N]>());
@@ -44,16 +41,9 @@ fn main() {
4441
simd_add(Simd::<f64, 4>([0., 1., 2., 3.]), Simd::<f64, 4>([2., 2., 2., 2.]));
4542
assert_eq!(std::mem::transmute::<_, [f64; 4]>(x), [2., 3., 4., 5.]);
4643

47-
// non-powers-of-two have padding and need to be expanded to full vectors
48-
fn load<T, const N: usize>(v: Simd<T, N>) -> FullSimd<T, N> {
49-
unsafe {
50-
let mut tmp = core::mem::MaybeUninit::<FullSimd<T, N>>::uninit();
51-
std::ptr::copy_nonoverlapping(&v as *const _, tmp.as_mut_ptr().cast(), 1);
52-
tmp.assume_init()
53-
}
54-
}
55-
let x: FullSimd<f64, 3> =
56-
simd_add(load(Simd::<f64, 3>([0., 1., 2.])), load(Simd::<f64, 3>([2., 2., 2.])));
57-
assert_eq!(x.0, [2., 3., 4.]);
44+
// non-powers-of-two have padding and lesser alignment, but the intrinsic handles it
45+
let x: Simd<f64, 3> = simd_add(Simd::<f64, 3>([0., 1., 2.]), Simd::<f64, 3>([2., 2., 2.]));
46+
let arr: [f64; 3] = x.0;
47+
assert_eq!(arr, [2., 3., 4.]);
5848
}
5949
}

0 commit comments

Comments
 (0)