@@ -2359,6 +2359,22 @@ macro_rules! len {
2359
2359
}
2360
2360
} }
2361
2361
}
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
+ }
2362
2378
2363
2379
// The shared definition of the `Iter` and `IterMut` iterators
2364
2380
macro_rules! iterator {
@@ -2367,7 +2383,7 @@ macro_rules! iterator {
2367
2383
// Helper function for creating a slice from the iterator.
2368
2384
#[ inline( always) ]
2369
2385
fn make_slice( & self ) -> & ' a [ T ] {
2370
- unsafe { from_raw_parts( self . ptr, len !( self ) ) }
2386
+ unsafe { from_raw_parts( self . ptr, len2 !( self ) ) }
2371
2387
}
2372
2388
2373
2389
// Helper function for moving the start of the iterator forwards by `offset` elements,
@@ -2510,9 +2526,8 @@ macro_rules! iterator {
2510
2526
Self : Sized ,
2511
2527
P : FnMut ( Self :: Item ) -> bool ,
2512
2528
{
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 ) ;
2516
2531
self . try_fold( 0 , move |i, x| {
2517
2532
if predicate( x) { Err ( i) }
2518
2533
else { Ok ( i + 1 ) }
@@ -2529,9 +2544,7 @@ macro_rules! iterator {
2529
2544
Self : Sized + ExactSizeIterator + DoubleEndedIterator
2530
2545
{
2531
2546
// 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 ) ;
2535
2548
self . try_rfold( n, move |i, x| {
2536
2549
let i = i - 1 ;
2537
2550
if predicate( x) { Err ( i) }
@@ -2776,7 +2789,7 @@ impl<'a, T> IterMut<'a, T> {
2776
2789
/// ```
2777
2790
#[ stable( feature = "iter_to_slice" , since = "1.4.0" ) ]
2778
2791
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 ) ) }
2780
2793
}
2781
2794
}
2782
2795
0 commit comments