Speed up compilation of large constant arrays
This is a different approach to #51672 as suggested by @oli-obk. Rather than write each repeated value one-by-one, we write the first one and then copy its value directly into the remaining memory.
This commit is contained in:
parent
0cf0691ea1
commit
202aea5acd
2 changed files with 30 additions and 8 deletions
|
@ -591,10 +591,14 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M
|
|||
|
||||
let (dest, dest_align) = self.force_allocation(dest)?.to_ptr_align();
|
||||
|
||||
// FIXME: speed up repeat filling
|
||||
for i in 0..length {
|
||||
let elem_dest = dest.ptr_offset(elem_size * i as u64, &self)?;
|
||||
self.write_value_to_ptr(value, elem_dest, dest_align, elem_ty)?;
|
||||
if length > 0 {
|
||||
//write the first value
|
||||
self.write_value_to_ptr(value, dest, dest_align, elem_ty)?;
|
||||
|
||||
if length > 1 {
|
||||
let rest = dest.ptr_offset(elem_size * 1 as u64, &self)?;
|
||||
self.memory.copy_repeatedly(dest, dest_align, rest, dest_align, elem_size, length - 1, false)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -594,6 +594,19 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
|
|||
dest_align: Align,
|
||||
size: Size,
|
||||
nonoverlapping: bool,
|
||||
) -> EvalResult<'tcx> {
|
||||
self.copy_repeatedly(src, src_align, dest, dest_align, size, 1, nonoverlapping)
|
||||
}
|
||||
|
||||
pub fn copy_repeatedly(
|
||||
&mut self,
|
||||
src: Scalar,
|
||||
src_align: Align,
|
||||
dest: Scalar,
|
||||
dest_align: Align,
|
||||
size: Size,
|
||||
length: u64,
|
||||
nonoverlapping: bool,
|
||||
) -> EvalResult<'tcx> {
|
||||
// Empty accesses don't need to be valid pointers, but they should still be aligned
|
||||
self.check_align(src, src_align)?;
|
||||
|
@ -617,7 +630,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
|
|||
.collect();
|
||||
|
||||
let src_bytes = self.get_bytes_unchecked(src, size, src_align)?.as_ptr();
|
||||
let dest_bytes = self.get_bytes_mut(dest, size, dest_align)?.as_mut_ptr();
|
||||
let dest_bytes = self.get_bytes_mut(dest, size * length, dest_align)?.as_mut_ptr();
|
||||
|
||||
// SAFE: The above indexing would have panicked if there weren't at least `size` bytes
|
||||
// behind `src` and `dest`. Also, we use the overlapping-safe `ptr::copy` if `src` and
|
||||
|
@ -634,13 +647,18 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
|
|||
));
|
||||
}
|
||||
}
|
||||
ptr::copy(src_bytes, dest_bytes, size.bytes() as usize);
|
||||
|
||||
for i in 0..length {
|
||||
ptr::copy(src_bytes, dest_bytes.offset((size.bytes() * i) as isize), size.bytes() as usize);
|
||||
}
|
||||
} else {
|
||||
ptr::copy_nonoverlapping(src_bytes, dest_bytes, size.bytes() as usize);
|
||||
for i in 0..length {
|
||||
ptr::copy_nonoverlapping(src_bytes, dest_bytes.offset((size.bytes() * i) as isize), size.bytes() as usize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.copy_undef_mask(src, dest, size)?;
|
||||
self.copy_undef_mask(src, dest, size * length)?;
|
||||
// copy back the relocations
|
||||
self.get_mut(dest.alloc_id)?.relocations.insert_presorted(relocations);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue