Skip to content

Commit

Permalink
Remove manual unrolling from slice::Iter(Mut)::try_fold
Browse files Browse the repository at this point in the history
While this definitely helps sometimes (particularly for trivial closures), it's also a pessimization sometimes, so it's better to leave this to (hypothetical) future LLVM improvements instead of forcing this on everyone.

I think it's better for the advice to be that sometimes you need to unroll manually than you sometimes need to not-unroll manually (like #64545).
  • Loading branch information
scottmcm committed Sep 22, 2019
1 parent eceec57 commit 92e91f7
Showing 1 changed file with 7 additions and 13 deletions.
20 changes: 7 additions & 13 deletions src/libcore/slice/mod.rs
Expand Up @@ -3184,18 +3184,14 @@ macro_rules! iterator {
fn try_fold<B, F, R>(&mut self, init: B, mut f: F) -> R where
Self: Sized, F: FnMut(B, Self::Item) -> R, R: Try<Ok=B>
{
// manual unrolling is needed when there are conditional exits from the loop
// This method historically was unrolled, for as of 2019-09 LLVM
// is not capable of unrolling or vectorizing multiple-exit loops.
// However, doing it always proved to often be a pessimization,
// especially when called with large closures, so it was removed.

let mut accum = init;
unsafe {
while len!(self) >= 4 {
accum = f(accum, next_unchecked!(self))?;
accum = f(accum, next_unchecked!(self))?;
accum = f(accum, next_unchecked!(self))?;
accum = f(accum, next_unchecked!(self))?;
}
while !is_empty!(self) {
accum = f(accum, next_unchecked!(self))?;
}
while let Some(x) = self.next() {
accum = f(accum, x)?;
}
Try::from_ok(accum)
}
Expand All @@ -3204,8 +3200,6 @@ macro_rules! iterator {
fn fold<Acc, Fold>(mut self, init: Acc, mut f: Fold) -> Acc
where Fold: FnMut(Acc, Self::Item) -> Acc,
{
// Let LLVM unroll this, rather than using the default
// impl that would force the manual unrolling above
let mut accum = init;
while let Some(x) = self.next() {
accum = f(accum, x);
Expand Down

0 comments on commit 92e91f7

Please sign in to comment.