Skip to content

Commit

Permalink
Optimize large array creation in const-eval
Browse files Browse the repository at this point in the history
This changes repeated memcpy's to a memset for the case that we're
propagating a single byte into a region of memory.
  • Loading branch information
Mark-Simulacrum committed Jan 17, 2024
1 parent c58a5da commit 4106d71
Showing 1 changed file with 16 additions and 12 deletions.
28 changes: 16 additions & 12 deletions compiler/rustc_const_eval/src/interpret/memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1209,21 +1209,25 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
throw_ub_custom!(fluent::const_eval_copy_nonoverlapping_overlapping);
}
}
}

for i in 0..num_copies {
ptr::copy(
src_bytes,
dest_bytes.add((size * i).bytes_usize()), // `Size` multiplication
size.bytes_usize(),
);
let size_in_bytes = size.bytes_usize();
// For particularly large arrays (where this is perf-sensitive) it's common that
// we're writing a single byte repeatedly. So, optimize that case to a memset.
if size_in_bytes == 1 && num_copies >= 1 {
let value = *src_bytes;
dest_bytes.write_bytes(value, (size * num_copies).bytes_usize());
} else if src_alloc_id == dest_alloc_id {
let mut dest_ptr = dest_bytes;
for _ in 0..num_copies {
ptr::copy(src_bytes, dest_ptr, size_in_bytes);
dest_ptr = dest_ptr.add(size_in_bytes);
}
} else {
for i in 0..num_copies {
ptr::copy_nonoverlapping(
src_bytes,
dest_bytes.add((size * i).bytes_usize()), // `Size` multiplication
size.bytes_usize(),
);
let mut dest_ptr = dest_bytes;
for _ in 0..num_copies {
ptr::copy_nonoverlapping(src_bytes, dest_ptr, size_in_bytes);
dest_ptr = dest_ptr.add(size_in_bytes);
}
}
}
Expand Down

0 comments on commit 4106d71

Please sign in to comment.