about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authoroyvindln <oyvindln@users.noreply.github.com>2017-08-01 19:17:33 +0200
committeroyvindln <oyvindln@users.noreply.github.com>2017-08-01 19:31:50 +0200
commit4bb9a8b4ac27b48fb7989ef2900ec12a0face475 (patch)
tree257af90900d1f7db99edb23a55a51e7f96d71390 /src
parentc2407516ff33d03d0e24c6a4268a5581e9bc8b4d (diff)
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
Diffstat (limited to 'src')
-rw-r--r--src/libcore/iter/range.rs13
1 files changed, 10 insertions, 3 deletions
diff --git a/src/libcore/iter/range.rs b/src/libcore/iter/range.rs
index 32c32e327eb..73d518b570a 100644
--- a/src/libcore/iter/range.rs
+++ b/src/libcore/iter/range.rs
@@ -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
         }