mirror of
https://github.com/rust-lang/rust.git
synced 2024-10-31 22:41:50 +00:00
replace manual ptr arithmetic with ptr_sub
This commit is contained in:
parent
754f6d4a8c
commit
9db0134018
@ -6,7 +6,7 @@ mod macros;
|
||||
use crate::cmp;
|
||||
use crate::cmp::Ordering;
|
||||
use crate::fmt;
|
||||
use crate::intrinsics::{assume, exact_div, unchecked_sub};
|
||||
use crate::intrinsics::assume;
|
||||
use crate::iter::{FusedIterator, TrustedLen, TrustedRandomAccess, TrustedRandomAccessNoCoerce};
|
||||
use crate::marker::{PhantomData, Send, Sized, Sync};
|
||||
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
|
||||
///
|
||||
/// This struct is created by the [`iter`] method on [slices].
|
||||
|
@ -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 {
|
||||
($self: ident) => {{
|
||||
#![allow(unused_unsafe)] // we're sometimes used within an unsafe block
|
||||
|
||||
let start = $self.ptr;
|
||||
let size = size_from_ptr(start.as_ptr());
|
||||
if size == 0 {
|
||||
// This _cannot_ use `unchecked_sub` because we depend on wrapping
|
||||
if T::IS_ZST {
|
||||
// This _cannot_ use `ptr_sub` because we depend on wrapping
|
||||
// to represent the length of long ZST slice iterators.
|
||||
$self.end.addr().wrapping_sub(start.as_ptr().addr())
|
||||
} else {
|
||||
// We know that `start <= end`, so can do better than `offset_from`,
|
||||
// which needs to deal in signed. By setting appropriate flags here
|
||||
// we can tell LLVM this, which helps it remove bounds checks.
|
||||
// SAFETY: By the type invariant, `start <= end`
|
||||
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) }
|
||||
// To get rid of some bounds checks (see `position`), we use ptr_sub instead of
|
||||
// offset_from (Tested by `codegen/slice-position-bounds-check`.)
|
||||
// SAFETY: by the type invariant pointers are aligned and `start <= end`
|
||||
unsafe { $self.end.sub_ptr(start.as_ptr()) }
|
||||
}
|
||||
}};
|
||||
}
|
||||
|
@ -2,6 +2,7 @@
|
||||
// prevent optimizing away bounds checks
|
||||
|
||||
// compile-flags: -O
|
||||
// ignore-debug: the debug assertions get in the way
|
||||
|
||||
#![crate_type="rlib"]
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user