replace manual ptr arithmetic with ptr_sub

This commit is contained in:
The 8472 2023-01-03 02:39:13 +01:00
parent 754f6d4a8c
commit 9db0134018
3 changed files with 8 additions and 23 deletions

View File

@ -6,7 +6,7 @@ mod macros;
use crate::cmp; use crate::cmp;
use crate::cmp::Ordering; use crate::cmp::Ordering;
use crate::fmt; use crate::fmt;
use crate::intrinsics::{assume, exact_div, unchecked_sub}; use crate::intrinsics::assume;
use crate::iter::{FusedIterator, TrustedLen, TrustedRandomAccess, TrustedRandomAccessNoCoerce}; use crate::iter::{FusedIterator, TrustedLen, TrustedRandomAccess, TrustedRandomAccessNoCoerce};
use crate::marker::{PhantomData, Send, Sized, Sync}; use crate::marker::{PhantomData, Send, Sized, Sync};
use crate::mem::{self, SizedTypeProperties}; use crate::mem::{self, SizedTypeProperties};
@ -35,12 +35,6 @@ impl<'a, T> IntoIterator for &'a mut [T] {
} }
} }
// Macro helper functions
#[inline(always)]
fn size_from_ptr<T>(_: *const T) -> usize {
mem::size_of::<T>()
}
/// Immutable slice iterator /// Immutable slice iterator
/// ///
/// This struct is created by the [`iter`] method on [slices]. /// This struct is created by the [`iter`] method on [slices].

View File

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

View File

@ -2,6 +2,7 @@
// prevent optimizing away bounds checks // prevent optimizing away bounds checks
// compile-flags: -O // compile-flags: -O
// ignore-debug: the debug assertions get in the way
#![crate_type="rlib"] #![crate_type="rlib"]