diff options
| author | Wesley Wiser <wwiser@gmail.com> | 2018-06-26 22:59:10 -0400 |
|---|---|---|
| committer | Wesley Wiser <wwiser@gmail.com> | 2018-06-26 23:04:17 -0400 |
| commit | 202aea5acd61ec9d264defffca09c1377950274f (patch) | |
| tree | fe3f13c9dc8147537e22cd28085ce07f299405b1 /src | |
| parent | 0cf0691ea1879a84d09d53a19e0f0b06827cf95a (diff) | |
| download | rust-202aea5acd61ec9d264defffca09c1377950274f.tar.gz rust-202aea5acd61ec9d264defffca09c1377950274f.zip | |
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.
Diffstat (limited to 'src')
| -rw-r--r-- | src/librustc_mir/interpret/eval_context.rs | 12 | ||||
| -rw-r--r-- | src/librustc_mir/interpret/memory.rs | 26 |
2 files changed, 30 insertions, 8 deletions
diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs index ea667273ece..1faa23637a5 100644 --- a/src/librustc_mir/interpret/eval_context.rs +++ b/src/librustc_mir/interpret/eval_context.rs @@ -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)?; + } } } diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index ad571fbe90d..7a547c406a9 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -595,6 +595,19 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { 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)?; self.check_align(dest, dest_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); |
