Skip to content

Commit 0888649

Browse files
committed
Auto merge of #31000 - bluss:efficient-clone-from-slice, r=dotdash
Restore indexed formulation of clone_from_slice For good codegen here, we need a lock step iteration where the loop bound is only checked once per iteration; .zip() unfortunately does not optimize this way. If we use a counted loop, and make sure that llvm sees that the bounds check condition is the same as the loop bound condition, the bounds checks are optimized out. For this reason we need to slice `from` (apparently) redundantly. This commit restores the old formulation of clone_from_slice. In this shape, clone_from_slice will again optimize into calling memcpy where possible (for example for &[u8] or &[i32]).
2 parents a09a604 + 6a7bc47 commit 0888649

File tree

1 file changed

+7
-2
lines changed

1 file changed

+7
-2
lines changed

src/libcore/slice.rs

+7-2
Original file line numberDiff line numberDiff line change
@@ -478,8 +478,13 @@ impl<T> SliceExt for [T] {
478478
fn clone_from_slice(&mut self, src: &[T]) where T: Clone {
479479
assert!(self.len() == src.len(),
480480
"destination and source slices have different lengths");
481-
for (dst, src) in self.iter_mut().zip(src) {
482-
dst.clone_from(src);
481+
// NOTE: We need to explicitly slice them to the same length
482+
// for bounds checking to be elided, and the optimizer will
483+
// generate memcpy for simple cases (for example T = u8).
484+
let len = self.len();
485+
let src = &src[..len];
486+
for i in 0..len {
487+
self[i].clone_from(&src[i]);
483488
}
484489
}
485490
}

0 commit comments

Comments
 (0)