Skip to content

Commit 036954b

Browse files
Optimize large array creation in const-eval
This changes repeated memcpy's to a memset for the case that we're propagating a single byte into a region of memory.
1 parent c58a5da commit 036954b

File tree

1 file changed

+16
-12
lines changed
  • compiler/rustc_const_eval/src/interpret

1 file changed

+16
-12
lines changed

compiler/rustc_const_eval/src/interpret/memory.rs

+16-12
Original file line numberDiff line numberDiff line change
@@ -1209,21 +1209,25 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
12091209
throw_ub_custom!(fluent::const_eval_copy_nonoverlapping_overlapping);
12101210
}
12111211
}
1212+
}
12121213

1213-
for i in 0..num_copies {
1214-
ptr::copy(
1215-
src_bytes,
1216-
dest_bytes.add((size * i).bytes_usize()), // `Size` multiplication
1217-
size.bytes_usize(),
1218-
);
1214+
let size_in_bytes = size.bytes_usize();
1215+
// For particularly large arrays (where this is perf-sensitive) it's common that
1216+
// we're writing a single byte repeatedly. So, optimize that case to a memset.
1217+
if size_in_bytes == 1 {
1218+
let value = *src_bytes;
1219+
dest_bytes.write_bytes(value, (size * num_copies).bytes_usize());
1220+
} else if src_alloc_id == dest_alloc_id {
1221+
let mut dest_ptr = dest_bytes;
1222+
for _ in 0..num_copies {
1223+
ptr::copy(src_bytes, dest_ptr, size_in_bytes);
1224+
dest_ptr = dest_ptr.add(size_in_bytes);
12191225
}
12201226
} else {
1221-
for i in 0..num_copies {
1222-
ptr::copy_nonoverlapping(
1223-
src_bytes,
1224-
dest_bytes.add((size * i).bytes_usize()), // `Size` multiplication
1225-
size.bytes_usize(),
1226-
);
1227+
let mut dest_ptr = dest_bytes;
1228+
for _ in 0..num_copies {
1229+
ptr::copy_nonoverlapping(src_bytes, dest_ptr, size_in_bytes);
1230+
dest_ptr = dest_ptr.add(size_in_bytes);
12271231
}
12281232
}
12291233
}

0 commit comments

Comments
 (0)