Add an overflow check in the Iter::next() impl for Range<_>

This helps with vectorization in some cases, such as (0..u16::MAX).collect::<Vec<u16>>(),
 as LLVM is able to change the loop condition to use equality instead of less than
This commit is contained in:
oyvindln 2017-08-01 19:17:33 +02:00
parent c2407516ff
commit 4bb9a8b4ac

View File

@ -214,9 +214,16 @@ impl<A: Step> Iterator for ops::Range<A> {
#[inline]
fn next(&mut self) -> Option<A> {
if self.start < self.end {
let mut n = self.start.add_one();
mem::swap(&mut n, &mut self.start);
Some(n)
// We check for overflow here, even though it can't actually
// happen. Adding this check does however help llvm vectorize loops
// for some ranges that don't get vectorized otherwise,
// and this won't actually result in an extra check in an optimized build.
if let Some(mut n) = self.start.add_usize(1) {
mem::swap(&mut n, &mut self.start);
Some(n)
} else {
None
}
} else {
None
}