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;
|
||||||
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].
|
||||||
|
@ -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) }
|
|
||||||
}
|
}
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
|
@ -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"]
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user