Use load
-store
instead of memcpy
for short integer arrays
This commit is contained in:
parent
cce0b52e7b
commit
e1b020df9f
8 changed files with 136 additions and 16 deletions
|
@ -288,6 +288,9 @@ impl<'ll, 'tcx> LayoutTypeMethods<'tcx> for CodegenCx<'ll, 'tcx> {
|
|||
fn reg_backend_type(&self, ty: &Reg) -> &'ll Type {
|
||||
ty.llvm_type(self)
|
||||
}
|
||||
fn scalar_copy_backend_type(&self, layout: TyAndLayout<'tcx>) -> Option<Self::Type> {
|
||||
layout.scalar_copy_llvm_type(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ll, 'tcx> TypeMembershipMethods<'tcx> for CodegenCx<'ll, 'tcx> {
|
||||
|
|
|
@ -6,6 +6,7 @@ use rustc_middle::bug;
|
|||
use rustc_middle::ty::layout::{FnAbiOf, LayoutOf, TyAndLayout};
|
||||
use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths};
|
||||
use rustc_middle::ty::{self, Ty, TypeVisitableExt};
|
||||
use rustc_target::abi::HasDataLayout;
|
||||
use rustc_target::abi::{Abi, Align, FieldsShape};
|
||||
use rustc_target::abi::{Int, Pointer, F32, F64};
|
||||
use rustc_target::abi::{PointeeInfo, Scalar, Size, TyAbiInterface, Variants};
|
||||
|
@ -192,6 +193,7 @@ pub trait LayoutLlvmExt<'tcx> {
|
|||
) -> &'a Type;
|
||||
fn llvm_field_index<'a>(&self, cx: &CodegenCx<'a, 'tcx>, index: usize) -> u64;
|
||||
fn pointee_info_at<'a>(&self, cx: &CodegenCx<'a, 'tcx>, offset: Size) -> Option<PointeeInfo>;
|
||||
fn scalar_copy_llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> Option<&'a Type>;
|
||||
}
|
||||
|
||||
impl<'tcx> LayoutLlvmExt<'tcx> for TyAndLayout<'tcx> {
|
||||
|
@ -414,4 +416,35 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyAndLayout<'tcx> {
|
|||
cx.pointee_infos.borrow_mut().insert((self.ty, offset), result);
|
||||
result
|
||||
}
|
||||
|
||||
fn scalar_copy_llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> Option<&'a Type> {
|
||||
debug_assert!(self.is_sized());
|
||||
|
||||
// FIXME: this is a fairly arbitrary choice, but 128 bits on WASM
|
||||
// (matching the 128-bit SIMD types proposal) and 256 bits on x64
|
||||
// (like AVX2 registers) seems at least like a tolerable starting point.
|
||||
let threshold = cx.data_layout().pointer_size * 4;
|
||||
if self.layout.size() > threshold {
|
||||
return None;
|
||||
}
|
||||
|
||||
// Vectors, even for non-power-of-two sizes, have the same layout as
|
||||
// arrays but don't count as aggregate types
|
||||
if let FieldsShape::Array { count, .. } = self.layout.fields()
|
||||
&& let element = self.field(cx, 0)
|
||||
&& element.ty.is_integral()
|
||||
{
|
||||
// `cx.type_ix(bits)` is tempting here, but while that works great
|
||||
// for things that *stay* as memory-to-memory copies, it also ends
|
||||
// up suppressing vectorization as it introduces shifts when it
|
||||
// extracts all the individual values.
|
||||
|
||||
let ety = element.llvm_type(cx);
|
||||
return Some(cx.type_vector(ety, *count));
|
||||
}
|
||||
|
||||
// FIXME: The above only handled integer arrays; surely more things
|
||||
// would also be possible. Be careful about provenance, though!
|
||||
None
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue