From 4bb9a8b4ac27b48fb7989ef2900ec12a0face475 Mon Sep 17 00:00:00 2001 From: oyvindln Date: Tue, 1 Aug 2017 19:17:33 +0200 Subject: [PATCH] Add an overflow check in the Iter::next() impl for Range<_> This helps with vectorization in some cases, such as (0..u16::MAX).collect::>(), as LLVM is able to change the loop condition to use equality instead of less than --- src/libcore/iter/range.rs | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/libcore/iter/range.rs b/src/libcore/iter/range.rs index 32c32e327eb2d..73d518b570a11 100644 --- a/src/libcore/iter/range.rs +++ b/src/libcore/iter/range.rs @@ -214,9 +214,16 @@ impl Iterator for ops::Range { #[inline] fn next(&mut self) -> Option { 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 }