@@ -9,30 +9,20 @@ macro_rules! is_empty {
9
9
} ;
10
10
}
11
11
12
- // To get rid of some bounds checks (see `position`), we compute the length in a somewhat
13
- // unexpected way. (Tested by `codegen/slice-position-bounds-check`.)
14
12
macro_rules! len {
15
13
( $self: ident) => { {
16
14
#![ allow( unused_unsafe) ] // we're sometimes used within an unsafe block
17
15
18
16
let start = $self. ptr;
19
- let size = size_from_ptr( start. as_ptr( ) ) ;
20
- if size == 0 {
21
- // This _cannot_ use `unchecked_sub` because we depend on wrapping
17
+ if T :: IS_ZST {
18
+ // This _cannot_ use `ptr_sub` because we depend on wrapping
22
19
// to represent the length of long ZST slice iterators.
23
20
$self. end. addr( ) . wrapping_sub( start. as_ptr( ) . addr( ) )
24
21
} else {
25
- // We know that `start <= end`, so can do better than `offset_from`,
26
- // which needs to deal in signed. By setting appropriate flags here
27
- // we can tell LLVM this, which helps it remove bounds checks.
28
- // SAFETY: By the type invariant, `start <= end`
29
- let diff = unsafe { unchecked_sub( $self. end. addr( ) , start. as_ptr( ) . addr( ) ) } ;
30
- // By also telling LLVM that the pointers are apart by an exact
31
- // multiple of the type size, it can optimize `len() == 0` down to
32
- // `start == end` instead of `(end - start) < size`.
33
- // SAFETY: By the type invariant, the pointers are aligned so the
34
- // distance between them must be a multiple of pointee size
35
- unsafe { exact_div( diff, size) }
22
+ // To get rid of some bounds checks (see `position`), we use ptr_sub instead of
23
+ // offset_from (Tested by `codegen/slice-position-bounds-check`.)
24
+ // SAFETY: by the type invariant pointers are aligned and `start <= end`
25
+ unsafe { $self. end. sub_ptr( start. as_ptr( ) ) }
36
26
}
37
27
} } ;
38
28
}
0 commit comments