Introduce another way to compute the length, to fix position codegen regression
This commit is contained in:
parent
b0a82d9314
commit
e1471cf41f
1 changed files with 21 additions and 8 deletions
|
@ -2359,6 +2359,22 @@ macro_rules! len {
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
|
// To get rid of some bounds checks (see `position`), for some reason it
|
||||||
|
// makes a difference to compute the length in this way.
|
||||||
|
// (Tested by `codegen/slice-position-bounds-check`.)
|
||||||
|
macro_rules! len2 {
|
||||||
|
($self: ident) => {{
|
||||||
|
let start = $self.ptr;
|
||||||
|
let diff = ($self.end as usize).wrapping_sub(start as usize);
|
||||||
|
let size = size_from_ptr(start);
|
||||||
|
if size == 0 {
|
||||||
|
diff
|
||||||
|
} else {
|
||||||
|
// Using division instead of `offset_from` helps LLVM remove bounds checks
|
||||||
|
diff / size
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
}
|
||||||
|
|
||||||
// The shared definition of the `Iter` and `IterMut` iterators
|
// The shared definition of the `Iter` and `IterMut` iterators
|
||||||
macro_rules! iterator {
|
macro_rules! iterator {
|
||||||
|
@ -2367,7 +2383,7 @@ macro_rules! iterator {
|
||||||
// Helper function for creating a slice from the iterator.
|
// Helper function for creating a slice from the iterator.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn make_slice(&self) -> &'a [T] {
|
fn make_slice(&self) -> &'a [T] {
|
||||||
unsafe { from_raw_parts(self.ptr, len!(self)) }
|
unsafe { from_raw_parts(self.ptr, len2!(self)) }
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper function for moving the start of the iterator forwards by `offset` elements,
|
// Helper function for moving the start of the iterator forwards by `offset` elements,
|
||||||
|
@ -2510,9 +2526,8 @@ macro_rules! iterator {
|
||||||
Self: Sized,
|
Self: Sized,
|
||||||
P: FnMut(Self::Item) -> bool,
|
P: FnMut(Self::Item) -> bool,
|
||||||
{
|
{
|
||||||
// The addition might panic on overflow
|
// The addition might panic on overflow.
|
||||||
// Use the len of the slice to hint optimizer to remove result index bounds check.
|
let n = len2!(self);
|
||||||
let n = self.make_slice().len();
|
|
||||||
self.try_fold(0, move |i, x| {
|
self.try_fold(0, move |i, x| {
|
||||||
if predicate(x) { Err(i) }
|
if predicate(x) { Err(i) }
|
||||||
else { Ok(i + 1) }
|
else { Ok(i + 1) }
|
||||||
|
@ -2529,9 +2544,7 @@ macro_rules! iterator {
|
||||||
Self: Sized + ExactSizeIterator + DoubleEndedIterator
|
Self: Sized + ExactSizeIterator + DoubleEndedIterator
|
||||||
{
|
{
|
||||||
// No need for an overflow check here, because `ExactSizeIterator`
|
// No need for an overflow check here, because `ExactSizeIterator`
|
||||||
// implies that the number of elements fits into a `usize`.
|
let n = len2!(self);
|
||||||
// Use the len of the slice to hint optimizer to remove result index bounds check.
|
|
||||||
let n = self.make_slice().len();
|
|
||||||
self.try_rfold(n, move |i, x| {
|
self.try_rfold(n, move |i, x| {
|
||||||
let i = i - 1;
|
let i = i - 1;
|
||||||
if predicate(x) { Err(i) }
|
if predicate(x) { Err(i) }
|
||||||
|
@ -2776,7 +2789,7 @@ impl<'a, T> IterMut<'a, T> {
|
||||||
/// ```
|
/// ```
|
||||||
#[stable(feature = "iter_to_slice", since = "1.4.0")]
|
#[stable(feature = "iter_to_slice", since = "1.4.0")]
|
||||||
pub fn into_slice(self) -> &'a mut [T] {
|
pub fn into_slice(self) -> &'a mut [T] {
|
||||||
unsafe { from_raw_parts_mut(self.ptr, len!(self)) }
|
unsafe { from_raw_parts_mut(self.ptr, len2!(self)) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue