about summary refs log tree commit diff
path: root/src/libcore
diff options
context:
space:
mode:
authorScott McMurray <scottmcm@users.noreply.github.com>2019-09-18 21:36:30 -0700
committerScott McMurray <scottmcm@users.noreply.github.com>2019-09-21 21:16:24 -0700
commit92e91f7541af929010638355dc16daf27fd28b65 (patch)
tree6f454ae5299a2f7685619ce26d27a566c5023c0a /src/libcore
parenteceec57f72150dd548e05025a05a93381da41385 (diff)
downloadrust-92e91f7541af929010638355dc16daf27fd28b65.tar.gz
rust-92e91f7541af929010638355dc16daf27fd28b65.zip
Remove manual unrolling from slice::Iter(Mut)::try_fold
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).
Diffstat (limited to 'src/libcore')
-rw-r--r--src/libcore/slice/mod.rs20
1 files changed, 7 insertions, 13 deletions
diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs
index 931768564ca..59f95cff5ae 100644
--- a/src/libcore/slice/mod.rs
+++ b/src/libcore/slice/mod.rs
@@ -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)
             }
@@ -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);