]> git.lizzy.rs Git - rust.git/commitdiff
Auto merge of #37972 - bluss:iter-find-is-on-a-roll, r=sfackler
authorbors <bors@rust-lang.org>
Tue, 17 Jan 2017 21:52:03 +0000 (21:52 +0000)
committerbors <bors@rust-lang.org>
Tue, 17 Jan 2017 21:52:03 +0000 (21:52 +0000)
Improve the slice iterator's searching methods

Improve all, any, find, position, rposition by explicitly unrolling the loop for the slice iterators.

- Introduce a few extension methods and functions for raw pointers make the new code easy to express
- Introduce helper methods `search_while, rsearch_while` that generalize all the searching methods

LLVM doesn't unroll the loop in `.find()` by default (clang is the same), so performance benefits a lot from explicit unrolling here. An iterator method without conditional exits (like `.fold()`) does not need this on the other hand.

One of the raw pointer extension methods is `fn post_inc(&mut self) -> Self` which is the rustic equivalent of “`ptr++`”, and it is a nice way to express the raw pointer loop (see commit 3).

Specific development notes about `search_while`: I tried both computing an end pointer "rounded" to 4, as well as the `ptrdistance >= 4` loop condition, ptrdistance was better. I tried handling the last 0-3 elements unrolled or with a while loop, the loop was better.

1  2 
src/libcore/slice.rs

index 4d4c5129e602d54c42048705c3b44017dda7d687,263b9c22621735d7e87aa0e7c2822a7e33da7bf4..b942d85f9808bd8147b8dd5d79ecf36c3559bde4
@@@ -1147,14 -1107,10 +1274,14 @@@ impl<'a, T> Iter<'a, T> 
      }
  }
  
- iterator!{struct Iter -> *const T, &'a T}
+ iterator!{struct Iter -> *const T, &'a T, make_ref}
  
  #[stable(feature = "rust1", since = "1.0.0")]
 -impl<'a, T> ExactSizeIterator for Iter<'a, T> {}
 +impl<'a, T> ExactSizeIterator for Iter<'a, T> {
 +    fn is_empty(&self) -> bool {
 +        self.ptr == self.end
 +    }
 +}
  
  #[unstable(feature = "fused", issue = "35602")]
  impl<'a, T> FusedIterator for Iter<'a, T> {}
@@@ -1275,14 -1231,10 +1402,14 @@@ impl<'a, T> IterMut<'a, T> 
      }
  }
  
- iterator!{struct IterMut -> *mut T, &'a mut T}
+ iterator!{struct IterMut -> *mut T, &'a mut T, make_ref_mut}
  
  #[stable(feature = "rust1", since = "1.0.0")]
 -impl<'a, T> ExactSizeIterator for IterMut<'a, T> {}
 +impl<'a, T> ExactSizeIterator for IterMut<'a, T> {
 +    fn is_empty(&self) -> bool {
 +        self.ptr == self.end
 +    }
 +}
  
  #[unstable(feature = "fused", issue = "35602")]
  impl<'a, T> FusedIterator for IterMut<'a, T> {}