@@ -2359,6 +2359,22 @@ macro_rules! len {
23592359 }
23602360 } }
23612361}
2362+ // To get rid of some bounds checks (see `position`), for some reason it
2363+ // makes a difference to compute the length in this way.
2364+ // (Tested by `codegen/slice-position-bounds-check`.)
2365+ macro_rules! len2 {
2366+ ( $self: ident) => { {
2367+ let start = $self. ptr;
2368+ let diff = ( $self. end as usize ) . wrapping_sub( start as usize ) ;
2369+ let size = size_from_ptr( start) ;
2370+ if size == 0 {
2371+ diff
2372+ } else {
2373+ // Using division instead of `offset_from` helps LLVM remove bounds checks
2374+ diff / size
2375+ }
2376+ } }
2377+ }
23622378
23632379// The shared definition of the `Iter` and `IterMut` iterators
23642380macro_rules! iterator {
@@ -2367,7 +2383,7 @@ macro_rules! iterator {
23672383 // Helper function for creating a slice from the iterator.
23682384 #[ inline( always) ]
23692385 fn make_slice( & self ) -> & ' a [ T ] {
2370- unsafe { from_raw_parts( self . ptr, len !( self ) ) }
2386+ unsafe { from_raw_parts( self . ptr, len2 !( self ) ) }
23712387 }
23722388
23732389 // Helper function for moving the start of the iterator forwards by `offset` elements,
@@ -2510,9 +2526,8 @@ macro_rules! iterator {
25102526 Self : Sized ,
25112527 P : FnMut ( Self :: Item ) -> bool ,
25122528 {
2513- // The addition might panic on overflow
2514- // Use the len of the slice to hint optimizer to remove result index bounds check.
2515- let n = self . make_slice( ) . len( ) ;
2529+ // The addition might panic on overflow.
2530+ let n = len2!( self ) ;
25162531 self . try_fold( 0 , move |i, x| {
25172532 if predicate( x) { Err ( i) }
25182533 else { Ok ( i + 1 ) }
@@ -2529,9 +2544,7 @@ macro_rules! iterator {
25292544 Self : Sized + ExactSizeIterator + DoubleEndedIterator
25302545 {
25312546 // No need for an overflow check here, because `ExactSizeIterator`
2532- // implies that the number of elements fits into a `usize`.
2533- // Use the len of the slice to hint optimizer to remove result index bounds check.
2534- let n = self . make_slice( ) . len( ) ;
2547+ let n = len2!( self ) ;
25352548 self . try_rfold( n, move |i, x| {
25362549 let i = i - 1 ;
25372550 if predicate( x) { Err ( i) }
@@ -2776,7 +2789,7 @@ impl<'a, T> IterMut<'a, T> {
27762789 /// ```
27772790 #[ stable( feature = "iter_to_slice" , since = "1.4.0" ) ]
27782791 pub fn into_slice ( self ) -> & ' a mut [ T ] {
2779- unsafe { from_raw_parts_mut ( self . ptr , len ! ( self ) ) }
2792+ unsafe { from_raw_parts_mut ( self . ptr , len2 ! ( self ) ) }
27802793 }
27812794}
27822795
0 commit comments