|
25 | 25 | use crate::cmp::Ordering::{self, Less, Equal, Greater};
|
26 | 26 | use crate::cmp;
|
27 | 27 | use crate::fmt;
|
28 |
| -use crate::intrinsics::assume; |
| 28 | +use crate::intrinsics::{assume, exact_div, unchecked_sub}; |
29 | 29 | use crate::isize;
|
30 | 30 | use crate::iter::*;
|
31 | 31 | use crate::ops::{FnMut, Try, self};
|
@@ -2998,14 +2998,27 @@ macro_rules! is_empty {
|
2998 | 2998 | // unexpected way. (Tested by `codegen/slice-position-bounds-check`.)
|
2999 | 2999 | macro_rules! len {
|
3000 | 3000 | ($self: ident) => {{
|
| 3001 | + #![allow(unused_unsafe)] // we're sometimes used within an unsafe block |
| 3002 | + |
3001 | 3003 | let start = $self.ptr;
|
3002 |
| - let diff = ($self.end as usize).wrapping_sub(start as usize); |
3003 | 3004 | let size = size_from_ptr(start);
|
3004 | 3005 | if size == 0 {
|
| 3006 | + // This _cannot_ use `unchecked_sub` because we depend on wrapping |
| 3007 | + // to represent the length of long ZST slice iterators. |
| 3008 | + let diff = ($self.end as usize).wrapping_sub(start as usize); |
3005 | 3009 | diff
|
3006 | 3010 | } else {
|
3007 |
| - // Using division instead of `offset_from` helps LLVM remove bounds checks |
3008 |
| - diff / size |
| 3011 | + // We know that `start <= end`, so can do better than `offset_from`, |
| 3012 | + // which needs to deal in signed. By setting appropriate flags here |
| 3013 | + // we can tell LLVM this, which helps it remove bounds checks. |
| 3014 | + // SAFETY: By the type invariant, `start <= end` |
| 3015 | + let diff = unsafe { unchecked_sub($self.end as usize, start as usize) }; |
| 3016 | + // By also telling LLVM that the pointers are apart by an exact |
| 3017 | + // multiple of the type size, it can optimize `len() == 0` down to |
| 3018 | + // `start == end` instead of `(end - start) < size`. |
| 3019 | + // SAFETY: By the type invariant, the pointers are aligned so the |
| 3020 | + // distance between them must be a multiple of pointee size |
| 3021 | + unsafe { exact_div(diff, size) } |
3009 | 3022 | }
|
3010 | 3023 | }}
|
3011 | 3024 | }
|
|
0 commit comments