diff options
| author | Caleb Zulawski <caleb.zulawski@gmail.com> | 2024-05-20 01:09:29 -0400 |
|---|---|---|
| committer | Caleb Zulawski <caleb.zulawski@gmail.com> | 2024-05-20 01:09:29 -0400 |
| commit | 86158f581d20948507bef65e6162e3bbf5f4fa91 (patch) | |
| tree | 4e9a96982519fac2fdb654a9790420defa138276 /compiler/rustc_codegen_llvm | |
| parent | 959a67a7f2215d80b55e765d6c4b3f5a711ad484 (diff) | |
| download | rust-86158f581d20948507bef65e6162e3bbf5f4fa91.tar.gz rust-86158f581d20948507bef65e6162e3bbf5f4fa91.zip | |
Make repr(packed) vectors work with SIMD intrinsics
Diffstat (limited to 'compiler/rustc_codegen_llvm')
| -rw-r--r-- | compiler/rustc_codegen_llvm/src/intrinsic.rs | 49 |
1 files changed, 48 insertions, 1 deletions
diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index c0a1208a8c7..83a71752ffd 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -480,8 +480,55 @@ impl<'ll, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'_, 'll, 'tcx> { } _ if name.as_str().starts_with("simd_") => { + // Unpack non-power-of-2 #[repr(packed)] + let mut loaded_args = Vec::new(); + for (ty, arg) in arg_tys.iter().zip(args) { + loaded_args.push( + if ty.is_simd() + && let OperandValue::Ref(place) = arg.val + { + let (size, elem_ty) = ty.simd_size_and_type(self.tcx()); + let elem_ll_ty = match elem_ty.kind() { + ty::Float(f) => self.type_float_from_ty(*f), + ty::Int(i) => self.type_int_from_ty(*i), + ty::Uint(u) => self.type_uint_from_ty(*u), + ty::RawPtr(_, _) => self.type_ptr(), + _ => unreachable!(), + }; + let loaded = + self.load_from_place(self.type_vector(elem_ll_ty, size), place); + OperandRef::from_immediate_or_packed_pair(self, loaded, arg.layout) + } else { + *arg + }, + ); + } + + let llret_ty = if ret_ty.is_simd() + && let abi::Abi::Aggregate { .. } = self.layout_of(ret_ty).layout.abi + { + let (size, elem_ty) = ret_ty.simd_size_and_type(self.tcx()); + let elem_ll_ty = match elem_ty.kind() { + ty::Float(f) => self.type_float_from_ty(*f), + ty::Int(i) => self.type_int_from_ty(*i), + ty::Uint(u) => self.type_uint_from_ty(*u), + ty::RawPtr(_, _) => self.type_ptr(), + _ => unreachable!(), + }; + self.type_vector(elem_ll_ty, size) + } else { + llret_ty + }; + match generic_simd_intrinsic( - self, name, callee_ty, fn_args, args, ret_ty, llret_ty, span, + self, + name, + callee_ty, + fn_args, + &loaded_args, + ret_ty, + llret_ty, + span, ) { Ok(llval) => llval, Err(()) => return Ok(()), |
