Fix array::IntoIter::fold to use the optimized Range::fold
It was using `Iterator::by_ref` in the implementation, which ended up pessimizing it enough that, for example, it didn't vectorize when we tried it in the <https://rust-lang.zulipchat.com/#narrow/stream/257879-project-portable-simd/topic/Reducing.20sum.20into.20wider.20types> conversation. Demonstration that the codegen test doesn't pass on the current nightly: <https://rust.godbolt.org/z/Taxev5eMn>
This commit is contained in:
@@ -266,7 +266,7 @@ impl<T, const N: usize> Iterator for IntoIter<T, N> {
|
||||
Fold: FnMut(Acc, Self::Item) -> Acc,
|
||||
{
|
||||
let data = &mut self.data;
|
||||
self.alive.by_ref().fold(init, |acc, idx| {
|
||||
iter::ByRefSized(&mut self.alive).fold(init, |acc, idx| {
|
||||
// SAFETY: idx is obtained by folding over the `alive` range, which implies the
|
||||
// value is currently considered alive but as the range is being consumed each value
|
||||
// we read here will only be read once and then considered dead.
|
||||
@@ -323,6 +323,20 @@ impl<T, const N: usize> DoubleEndedIterator for IntoIter<T, N> {
|
||||
})
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn rfold<Acc, Fold>(mut self, init: Acc, mut rfold: Fold) -> Acc
|
||||
where
|
||||
Fold: FnMut(Acc, Self::Item) -> Acc,
|
||||
{
|
||||
let data = &mut self.data;
|
||||
iter::ByRefSized(&mut self.alive).rfold(init, |acc, idx| {
|
||||
// SAFETY: idx is obtained by folding over the `alive` range, which implies the
|
||||
// value is currently considered alive but as the range is being consumed each value
|
||||
// we read here will only be read once and then considered dead.
|
||||
rfold(acc, unsafe { data.get_unchecked(idx).assume_init_read() })
|
||||
})
|
||||
}
|
||||
|
||||
fn advance_back_by(&mut self, n: usize) -> Result<(), usize> {
|
||||
let len = self.len();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user