Skip to content

Commit

Permalink
Rollup merge of #111282 - scottmcm:remove-unneeded-assumes, r=working…
Browse files Browse the repository at this point in the history
…jubilee

Remove some `assume`s from slice iterators that don't do anything

Because the start pointer is iterators is already a `NonNull`, we emit the appropriate `!nonnull` metadata when loading the pointer to tell LLVM that it's non-null.

Probably the best way to see that it's the metadata that's important (and not the `assume`) is to observe that LLVM actually *removes* the `assume` from the optimized IR: <https://rust.godbolt.org/z/KhE6G963n>.

(I also checked that, yes, the if-not-ZST `assume` on `end` is still doing something: it's how there's a `!nonnull` metadata on its load, even though it's an ordinary raw pointer.  The codegen test added in this PR fails if the other `assume` is  removed.)
  • Loading branch information
matthiaskrgr authored May 9, 2023
2 parents efe697e + ec3a9bc commit 273fbf4
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 10 deletions.
16 changes: 6 additions & 10 deletions library/core/src/slice/iter/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,12 +124,10 @@ macro_rules! iterator {
fn next(&mut self) -> Option<$elem> {
// could be implemented with slices, but this avoids bounds checks

// SAFETY: `assume` calls are safe since a slice's start pointer
// must be non-null, and slices over non-ZSTs must also have a
// non-null end pointer. The call to `next_unchecked!` is safe
// since we check if the iterator is empty first.
// SAFETY: `assume` call is safe because slices over non-ZSTs must
// have a non-null end pointer. The call to `next_unchecked!` is
// safe since we check if the iterator is empty first.
unsafe {
assume(!self.ptr.as_ptr().is_null());
if !<T>::IS_ZST {
assume(!self.end.is_null());
}
Expand Down Expand Up @@ -339,12 +337,10 @@ macro_rules! iterator {
fn next_back(&mut self) -> Option<$elem> {
// could be implemented with slices, but this avoids bounds checks

// SAFETY: `assume` calls are safe since a slice's start pointer must be non-null,
// and slices over non-ZSTs must also have a non-null end pointer.
// The call to `next_back_unchecked!` is safe since we check if the iterator is
// empty first.
// SAFETY: `assume` call is safe because slices over non-ZSTs must
// have a non-null end pointer. The call to `next_back_unchecked!`
// is safe since we check if the iterator is empty first.
unsafe {
assume(!self.ptr.as_ptr().is_null());
if !<T>::IS_ZST {
assume(!self.end.is_null());
}
Expand Down
42 changes: 42 additions & 0 deletions tests/codegen/slice-iter-nonnull.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// no-system-llvm
// compile-flags: -O
// ignore-debug (these add extra checks that make it hard to verify)
#![crate_type = "lib"]

// The slice iterator used to `assume` that the `start` pointer was non-null.
// That ought to be unneeded, though, since the type is `NonNull`, so this test
// confirms that the appropriate metadata is included to denote that.

// CHECK-LABEL: @slice_iter_next(
#[no_mangle]
pub fn slice_iter_next<'a>(it: &mut std::slice::Iter<'a, u32>) -> Option<&'a u32> {
// CHECK: %[[ENDP:.+]] = getelementptr{{.+}}ptr %it,{{.+}} 1
// CHECK: %[[END:.+]] = load ptr, ptr %[[ENDP]]
// CHECK-SAME: !nonnull
// CHECK-SAME: !noundef
// CHECK: %[[START:.+]] = load ptr, ptr %it,
// CHECK-SAME: !nonnull
// CHECK-SAME: !noundef
// CHECK: icmp eq ptr %[[START]], %[[END]]

// CHECK: store ptr{{.+}}, ptr %it,

it.next()
}

// CHECK-LABEL: @slice_iter_next_back(
#[no_mangle]
pub fn slice_iter_next_back<'a>(it: &mut std::slice::Iter<'a, u32>) -> Option<&'a u32> {
// CHECK: %[[ENDP:.+]] = getelementptr{{.+}}ptr %it,{{.+}} 1
// CHECK: %[[END:.+]] = load ptr, ptr %[[ENDP]]
// CHECK-SAME: !nonnull
// CHECK-SAME: !noundef
// CHECK: %[[START:.+]] = load ptr, ptr %it,
// CHECK-SAME: !nonnull
// CHECK-SAME: !noundef
// CHECK: icmp eq ptr %[[START]], %[[END]]

// CHECK: store ptr{{.+}}, ptr %[[ENDP]],

it.next_back()
}

0 comments on commit 273fbf4

Please sign in to comment.