Skip to content

Commit 9db0134

Browse files
committed
replace manual ptr arithmetic with ptr_sub
1 parent 754f6d4 commit 9db0134

File tree

3 files changed

+8
-23
lines changed

3 files changed

+8
-23
lines changed

library/core/src/slice/iter.rs

+1-7
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ mod macros;
66
use crate::cmp;
77
use crate::cmp::Ordering;
88
use crate::fmt;
9-
use crate::intrinsics::{assume, exact_div, unchecked_sub};
9+
use crate::intrinsics::assume;
1010
use crate::iter::{FusedIterator, TrustedLen, TrustedRandomAccess, TrustedRandomAccessNoCoerce};
1111
use crate::marker::{PhantomData, Send, Sized, Sync};
1212
use crate::mem::{self, SizedTypeProperties};
@@ -35,12 +35,6 @@ impl<'a, T> IntoIterator for &'a mut [T] {
3535
}
3636
}
3737

38-
// Macro helper functions
39-
#[inline(always)]
40-
fn size_from_ptr<T>(_: *const T) -> usize {
41-
mem::size_of::<T>()
42-
}
43-
4438
/// Immutable slice iterator
4539
///
4640
/// This struct is created by the [`iter`] method on [slices].

library/core/src/slice/iter/macros.rs

+6-16
Original file line numberDiff line numberDiff line change
@@ -9,30 +9,20 @@ macro_rules! is_empty {
99
};
1010
}
1111

12-
// To get rid of some bounds checks (see `position`), we compute the length in a somewhat
13-
// unexpected way. (Tested by `codegen/slice-position-bounds-check`.)
1412
macro_rules! len {
1513
($self: ident) => {{
1614
#![allow(unused_unsafe)] // we're sometimes used within an unsafe block
1715

1816
let start = $self.ptr;
19-
let size = size_from_ptr(start.as_ptr());
20-
if size == 0 {
21-
// This _cannot_ use `unchecked_sub` because we depend on wrapping
17+
if T::IS_ZST {
18+
// This _cannot_ use `ptr_sub` because we depend on wrapping
2219
// to represent the length of long ZST slice iterators.
2320
$self.end.addr().wrapping_sub(start.as_ptr().addr())
2421
} else {
25-
// We know that `start <= end`, so can do better than `offset_from`,
26-
// which needs to deal in signed. By setting appropriate flags here
27-
// we can tell LLVM this, which helps it remove bounds checks.
28-
// SAFETY: By the type invariant, `start <= end`
29-
let diff = unsafe { unchecked_sub($self.end.addr(), start.as_ptr().addr()) };
30-
// By also telling LLVM that the pointers are apart by an exact
31-
// multiple of the type size, it can optimize `len() == 0` down to
32-
// `start == end` instead of `(end - start) < size`.
33-
// SAFETY: By the type invariant, the pointers are aligned so the
34-
// distance between them must be a multiple of pointee size
35-
unsafe { exact_div(diff, size) }
22+
// To get rid of some bounds checks (see `position`), we use ptr_sub instead of
23+
// offset_from (Tested by `codegen/slice-position-bounds-check`.)
24+
// SAFETY: by the type invariant pointers are aligned and `start <= end`
25+
unsafe { $self.end.sub_ptr(start.as_ptr()) }
3626
}
3727
}};
3828
}

tests/codegen/issue-45964-bounds-check-slice-pos.rs

+1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// prevent optimizing away bounds checks
33

44
// compile-flags: -O
5+
// ignore-debug: the debug assertions get in the way
56

67
#![crate_type="rlib"]
78

0 commit comments

Comments
 (0)