diff options
| -rw-r--r-- | compiler/rustc_codegen_llvm/src/intrinsic.rs | 7 | ||||
| -rw-r--r-- | tests/ui/simd/repr_packed.rs | 5 |
2 files changed, 9 insertions, 3 deletions
diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index 83a71752ffd..87098566f6b 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -480,10 +480,15 @@ impl<'ll, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'_, 'll, 'tcx> { } _ if name.as_str().starts_with("simd_") => { - // Unpack non-power-of-2 #[repr(packed)] + // Unpack non-power-of-2 #[repr(packed, simd)] arguments. + // This gives them the expected layout of a regular #[repr(simd)] vector. let mut loaded_args = Vec::new(); for (ty, arg) in arg_tys.iter().zip(args) { loaded_args.push( + // #[repr(packed, simd)] vectors are passed like arrays (as references, + // with reduced alignment and no padding) rather than as immediates. + // We can use a vector load to fix the layout and turn the argument + // into an immediate. if ty.is_simd() && let OperandValue::Ref(place) = arg.val { diff --git a/tests/ui/simd/repr_packed.rs b/tests/ui/simd/repr_packed.rs index 52c794563de..1ba15bda98d 100644 --- a/tests/ui/simd/repr_packed.rs +++ b/tests/ui/simd/repr_packed.rs @@ -36,12 +36,13 @@ fn main() { check_ty::<f64>(); unsafe { - // powers-of-two have no padding and work as usual + // powers-of-two have no padding and have the same layout as #[repr(simd)] let x: Simd<f64, 4> = simd_add(Simd::<f64, 4>([0., 1., 2., 3.]), Simd::<f64, 4>([2., 2., 2., 2.])); assert_eq!(std::mem::transmute::<_, [f64; 4]>(x), [2., 3., 4., 5.]); - // non-powers-of-two have padding and lesser alignment, but the intrinsic handles it + // non-powers-of-two should have padding (which is removed by #[repr(packed)]), + // but the intrinsic handles it let x: Simd<f64, 3> = simd_add(Simd::<f64, 3>([0., 1., 2.]), Simd::<f64, 3>([2., 2., 2.])); let arr: [f64; 3] = x.0; assert_eq!(arr, [2., 3., 4.]); |
