Specialize array cloning for Copy types

Because after PR 86041, the optimizer no longer load-merges at the LLVM IR level, which might be part of the perf loss.  (I'll run perf and see if this makes a difference.)

Also I added a codegen test so this hopefully won't regress in future -- it passes on stable and with my change here, but not on the 2021-11-09 nightly.
This commit is contained in:
Scott McMurray
2021-11-09 21:43:20 -08:00
parent 8b09ba6a5d
commit cc7d8014d7
2 changed files with 37 additions and 3 deletions

View File

@@ -339,9 +339,7 @@ impl<T: Copy, const N: usize> Copy for [T; N] {}
impl<T: Clone, const N: usize> Clone for [T; N] {
#[inline]
fn clone(&self) -> Self {
// SAFETY: we know for certain that this iterator will yield exactly `N`
// items.
unsafe { collect_into_array_unchecked(&mut self.iter().cloned()) }
SpecArrayClone::clone(self)
}
#[inline]
@@ -350,6 +348,27 @@ impl<T: Clone, const N: usize> Clone for [T; N] {
}
}
#[cfg(not(bootstrap))]
trait SpecArrayClone: Clone {
fn clone<const N: usize>(array: &[Self; N]) -> [Self; N];
}
#[cfg(not(bootstrap))]
impl<T: Clone> SpecArrayClone for T {
default fn clone<const N: usize>(array: &[T; N]) -> [T; N] {
// SAFETY: we know for certain that this iterator will yield exactly `N`
// items.
unsafe { collect_into_array_unchecked(&mut array.iter().cloned()) }
}
}
#[cfg(not(bootstrap))]
impl<T: Copy> SpecArrayClone for T {
fn clone<const N: usize>(array: &[T; N]) -> [T; N] {
*array
}
}
// The Default impls cannot be done with const generics because `[T; 0]` doesn't
// require Default to be implemented, and having different impl blocks for
// different numbers isn't supported yet.