From 2f9f7633a5b9ae8fbde05573cfc3180e18a8e669 Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Sat, 23 Mar 2024 18:24:48 -0700 Subject: [PATCH] Make slice iterators carry only a single provenance Today they carry two, which makes certain optimizations illegal at the LLVM-IR level. In particular, it makes it matter whether an operation is done from the start pointer or the end pointer, since as far as LLVM knows those might have different provenance. For example, this code ```rust pub unsafe fn first_via_nth_back(mut it: std::slice::Iter<'_, i8>) -> &i8 { // CHECK: ret ptr %0 let len = it.len(); it.nth_back(len - 1).unwrap_unchecked() } ``` is ```llvm %2 = ptrtoint ptr %1 to i64 %3 = ptrtoint ptr %0 to i64 %.neg = add i64 %3, 1 %_6.neg = sub i64 %.neg, %2 %_15.i6.i = getelementptr inbounds i8, ptr %1, i64 %_6.neg %_15.i.i = getelementptr inbounds i8, ptr %_15.i6.i, i64 -1 ret ptr %_15.i.i ``` whereas after this PR it's just ```llvm ret ptr %0 ``` (some `assume`s removed in both cases) --- library/core/src/slice/iter.rs | 45 ++- library/core/src/slice/iter/macros.rs | 81 +++-- tests/codegen/issues/issue-37945.rs | 31 +- tests/codegen/slice-iter-len-eq-zero.rs | 18 +- tests/codegen/slice-iter-nonnull.rs | 49 +-- ...ated_loop.PreCodegen.after.panic-abort.mir | 314 ++++++------------ ...ted_loop.PreCodegen.after.panic-unwind.mir | 116 +++---- ...ward_loop.PreCodegen.after.panic-abort.mir | 226 +++---------- ...ard_loop.PreCodegen.after.panic-unwind.mir | 232 +++---------- ...erse_loop.PreCodegen.after.panic-abort.mir | 114 +++---- ...rse_loop.PreCodegen.after.panic-unwind.mir | 114 +++---- ..._is_empty.PreCodegen.after.panic-abort.mir | 99 ++++-- ...is_empty.PreCodegen.after.panic-unwind.mir | 99 ++++-- ...iter_next.PreCodegen.after.panic-abort.mir | 124 +------ ...ter_next.PreCodegen.after.panic-unwind.mir | 124 +------ 15 files changed, 641 insertions(+), 1145 deletions(-) diff --git a/library/core/src/slice/iter.rs b/library/core/src/slice/iter.rs index 33132dcc7148d..5835f0a6e937f 100644 --- a/library/core/src/slice/iter.rs +++ b/library/core/src/slice/iter.rs @@ -11,8 +11,8 @@ use crate::iter::{ use crate::marker::PhantomData; use crate::mem::{self, SizedTypeProperties}; use crate::num::NonZero; -use crate::ptr::{NonNull, without_provenance, without_provenance_mut}; -use crate::{cmp, fmt}; +use crate::ptr::{self, NonNull}; +use crate::{cmp, fmt, intrinsics}; #[stable(feature = "boxed_slice_into_iter", since = "1.80.0")] impl !Iterator for [T] {} @@ -72,10 +72,14 @@ pub struct Iter<'a, T: 'a> { /// /// This address will be used for all ZST elements, never changed. ptr: NonNull, - /// For non-ZSTs, the non-null pointer to the past-the-end element. + /// For non-ZSTs, the address of the past-the-end element. This is + /// intentionally *not* a pointer, so that it doesn't carry provenance. + /// If you're turning this into a pointer, you need to use the provenance from + /// `ptr` instead. (If this carried provenance, the compiler wouldn't know + /// that reads from the start and the end are actually the same provenance.) /// - /// For ZSTs, this is `ptr::without_provenance_mut(len)`. - end_or_len: *const T, + /// For ZSTs, this is the length. + end_addr_or_len: usize, _marker: PhantomData<&'a T>, } @@ -98,10 +102,9 @@ impl<'a, T> Iter<'a, T> { let ptr: NonNull = NonNull::from_ref(slice).cast(); // SAFETY: Similar to `IterMut::new`. unsafe { - let end_or_len = - if T::IS_ZST { without_provenance(len) } else { ptr.as_ptr().add(len) }; + let end_addr_or_len = if T::IS_ZST { len } else { addr_usize(ptr.add(len)) }; - Self { ptr, end_or_len, _marker: PhantomData } + Self { ptr, end_addr_or_len, _marker: PhantomData } } } @@ -153,7 +156,7 @@ iterator! {struct Iter -> *const T, &'a T, const, {/* no mut */}, as_ref, { impl Clone for Iter<'_, T> { #[inline] fn clone(&self) -> Self { - Iter { ptr: self.ptr, end_or_len: self.end_or_len, _marker: self._marker } + Iter { ptr: self.ptr, end_addr_or_len: self.end_addr_or_len, _marker: self._marker } } } @@ -197,10 +200,14 @@ pub struct IterMut<'a, T: 'a> { /// /// This address will be used for all ZST elements, never changed. ptr: NonNull, - /// For non-ZSTs, the non-null pointer to the past-the-end element. + /// For non-ZSTs, the address of the past-the-end element. This is + /// intentionally *not* a pointer, so that it doesn't carry provenance. + /// If you're turning this into a pointer, you need to use the provenance from + /// `ptr` instead. (If this carried provenance, the compiler wouldn't know + /// that reads from the start and the end are actually the same provenance.) /// - /// For ZSTs, this is `ptr::without_provenance_mut(len)`. - end_or_len: *mut T, + /// For ZSTs, this is the length. + end_addr_or_len: usize, _marker: PhantomData<&'a mut T>, } @@ -238,10 +245,9 @@ impl<'a, T> IterMut<'a, T> { // See the `next_unchecked!` and `is_empty!` macros as well as the // `post_inc_start` method for more information. unsafe { - let end_or_len = - if T::IS_ZST { without_provenance_mut(len) } else { ptr.as_ptr().add(len) }; + let end_addr_or_len = if T::IS_ZST { len } else { addr_usize(ptr.add(len)) }; - Self { ptr, end_or_len, _marker: PhantomData } + Self { ptr, end_addr_or_len, _marker: PhantomData } } } @@ -3478,3 +3484,12 @@ impl<'a, T: 'a + fmt::Debug, P> fmt::Debug for ChunkByMut<'a, T, P> { f.debug_struct("ChunkByMut").field("slice", &self.slice).finish() } } + +/// Same as `p.addr().get()`, but faster to compile by avoiding a bunch of +/// intermediate steps and unneeded UB checks, which also inlines better. +#[inline] +const fn addr_usize(p: NonNull) -> usize { + // SAFETY: `NonNull` for a sized type has the same layout as `usize`, + // and we intentionally don't want to expose here. + unsafe { intrinsics::transmute(p) } +} diff --git a/library/core/src/slice/iter/macros.rs b/library/core/src/slice/iter/macros.rs index 7c1ed3fe8a246..19589da8652bc 100644 --- a/library/core/src/slice/iter/macros.rs +++ b/library/core/src/slice/iter/macros.rs @@ -1,36 +1,64 @@ //! Macros used by iterators of slice. -/// Convenience & performance macro for consuming the `end_or_len` field, by +/// Convenience macro for updating the `end_addr_or_len` field for non-ZSTs. +macro_rules! set_end { + ($this:ident . end = $new_end:expr) => {{ + $this.end_addr_or_len = addr_usize($new_end); + }}; +} + +/// Convenience & performance macro for consuming the `end_addr_or_len` field, by /// giving a `(&mut) usize` or `(&mut) NonNull` depending whether `T` is /// or is not a ZST respectively. /// -/// Internally, this reads the `end` through a pointer-to-`NonNull` so that -/// it'll get the appropriate non-null metadata in the backend without needing -/// to call `assume` manually. +/// When giving a `NonNull` for the end, it creates it by offsetting from the +/// `ptr` so that the backend knows that both pointers have the same provenance. macro_rules! if_zst { (mut $this:ident, $len:ident => $zst_body:expr, $end:ident => $other_body:expr,) => {{ #![allow(unused_unsafe)] // we're sometimes used within an unsafe block + let ptr = $this.ptr; if T::IS_ZST { - // SAFETY: for ZSTs, the pointer is storing a provenance-free length, - // so consuming and updating it as a `usize` is fine. - let $len = unsafe { &mut *(&raw mut $this.end_or_len).cast::() }; + let $len = &mut $this.end_addr_or_len; $zst_body } else { - // SAFETY: for non-ZSTs, the type invariant ensures it cannot be null - let $end = unsafe { &mut *(&raw mut $this.end_or_len).cast::>() }; + let $len; + #[allow(unused_unsafe)] // we're sometimes used within an unsafe block + // SAFETY: By type invariant `end >= ptr`, and thus the subtraction + // cannot overflow, and the iter represents a single allocated + // object so the `add` will also be in-range. + let $end = unsafe { + // Need to load as `NonNull` to get `!nonnull` metadata + // (Transmuting gets an assume instead) + let end: NonNull = *ptr::addr_of!($this.end_addr_or_len).cast(); + // Not using `with_addr` because we have ordering information that + // we can take advantage of here that `with_addr` cannot. + $len = intrinsics::ptr_offset_from_unsigned(end.as_ptr(), ptr.as_ptr()); + ptr.add($len) + }; $other_body } }}; ($this:ident, $len:ident => $zst_body:expr, $end:ident => $other_body:expr,) => {{ - #![allow(unused_unsafe)] // we're sometimes used within an unsafe block - if T::IS_ZST { - let $len = $this.end_or_len.addr(); + let $len = $this.end_addr_or_len; $zst_body } else { - // SAFETY: for non-ZSTs, the type invariant ensures it cannot be null - let $end = unsafe { mem::transmute::<*const T, NonNull>($this.end_or_len) }; + let $len; + #[allow(unused_unsafe)] // we're sometimes used within an unsafe block + // SAFETY: By type invariant `end >= ptr`, and thus the subtraction + // cannot overflow, and the iter represents a single allocated + // object so the `add` will also be in-range. + let $end = unsafe { + let ptr = $this.ptr; + // Need to load as `NonNull` to get `!nonnull` metadata + // (Transmuting gets an assume instead) + let end: NonNull = *ptr::addr_of!($this.end_addr_or_len).cast(); + // Not using `with_addr` because we have ordering information that + // we can take advantage of here that `with_addr` cannot. + $len = intrinsics::ptr_offset_from_unsigned(end.as_ptr(), ptr.as_ptr()); + ptr.add($len) + }; $other_body } }}; @@ -50,12 +78,7 @@ macro_rules! len { ($self: ident) => {{ if_zst!($self, len => len, - end => { - // 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 { end.offset_from_unsigned($self.ptr) } - }, + _end => len, ) }}; } @@ -128,8 +151,9 @@ macro_rules! iterator { // which is guaranteed to not overflow an `isize`. Also, the resulting pointer // is in bounds of `slice`, which fulfills the other requirements for `offset`. end => unsafe { - *end = end.sub(offset); - *end + let new_end = end.sub(offset); + set_end!(self.end = new_end); + new_end }, ) } @@ -158,12 +182,11 @@ macro_rules! iterator { // one of the most mono'd things in the library. let ptr = self.ptr; - let end_or_len = self.end_or_len; // SAFETY: See inner comments. (For some reason having multiple // block breaks inlining this -- if you can fix that please do!) unsafe { if T::IS_ZST { - let len = end_or_len.addr(); + let len = self.end_addr_or_len; if len == 0 { return None; } @@ -171,12 +194,12 @@ macro_rules! iterator { // cannot wrap. (Ideally this would be `checked_sub`, which // does the same thing internally, but as of 2025-02 that // doesn't optimize quite as small in MIR.) - self.end_or_len = without_provenance_mut(len.unchecked_sub(1)); + self.end_addr_or_len = intrinsics::unchecked_sub(len, 1); } else { - // SAFETY: by type invariant, the `end_or_len` field is always + // SAFETY: by type invariant, the `end_addr_or_len` field is always // non-null for a non-ZST pointee. (This transmute ensures we // get `!nonnull` metadata on the load of the field.) - if ptr == crate::intrinsics::transmute::<$ptr, NonNull>(end_or_len) { + if ptr == *(&raw const self.end_addr_or_len).cast::>() { return None; } // SAFETY: since it's not empty, per the check above, moving @@ -207,7 +230,7 @@ macro_rules! iterator { // This iterator is now empty. if_zst!(mut self, len => *len = 0, - end => self.ptr = *end, + end => self.ptr = end, ); return None; } @@ -432,7 +455,7 @@ macro_rules! iterator { // This iterator is now empty. if_zst!(mut self, len => *len = 0, - end => *end = self.ptr, + _end => set_end!(self.end = self.ptr), ); return None; } diff --git a/tests/codegen/issues/issue-37945.rs b/tests/codegen/issues/issue-37945.rs index 23d0eab8ae466..9e4f4b6415188 100644 --- a/tests/codegen/issues/issue-37945.rs +++ b/tests/codegen/issues/issue-37945.rs @@ -3,32 +3,33 @@ // Check that LLVM understands that `Iter` pointer is not null. Issue #37945. +// There used to be a comparison against `null`, so we check that it's not there +// and that the appropriate parameter metadata is. + #![crate_type = "lib"] use std::slice::Iter; #[no_mangle] pub fn is_empty_1(xs: Iter) -> bool { - // CHECK-LABEL: @is_empty_1( - // CHECK-NEXT: start: - // CHECK-NEXT: [[A:%.*]] = icmp ne ptr {{%xs.0|%xs.1}}, null - // CHECK-NEXT: tail call void @llvm.assume(i1 [[A]]) - // The order between %xs.0 and %xs.1 on the next line doesn't matter - // and different LLVM versions produce different order. - // CHECK-NEXT: [[B:%.*]] = icmp eq ptr {{%xs.0, %xs.1|%xs.1, %xs.0}} - // CHECK-NEXT: ret i1 [[B:%.*]] + // CHECK-LABEL: @is_empty_1 + // CHECK-SAME: (ptr noundef nonnull{{.*}}%xs.0, {{i32|i64}}{{.+}}%xs.1) + + // CHECK-NOT: null + // CHECK-NOT: i32 0 + // CHECK-NOT: i64 0 + { xs }.next().is_none() } #[no_mangle] pub fn is_empty_2(xs: Iter) -> bool { // CHECK-LABEL: @is_empty_2 - // CHECK-NEXT: start: - // CHECK-NEXT: [[C:%.*]] = icmp ne ptr {{%xs.0|%xs.1}}, null - // CHECK-NEXT: tail call void @llvm.assume(i1 [[C]]) - // The order between %xs.0 and %xs.1 on the next line doesn't matter - // and different LLVM versions produce different order. - // CHECK-NEXT: [[D:%.*]] = icmp eq ptr {{%xs.0, %xs.1|%xs.1, %xs.0}} - // CHECK-NEXT: ret i1 [[D:%.*]] + // CHECK-SAME: (ptr noundef nonnull{{.*}}%xs.0, {{i32|i64}}{{.+}}%xs.1) + + // CHECK-NOT: null + // CHECK-NOT: i32 0 + // CHECK-NOT: i64 0 + xs.map(|&x| x).next().is_none() } diff --git a/tests/codegen/slice-iter-len-eq-zero.rs b/tests/codegen/slice-iter-len-eq-zero.rs index 6998d98e498c9..965a6606112ac 100644 --- a/tests/codegen/slice-iter-len-eq-zero.rs +++ b/tests/codegen/slice-iter-len-eq-zero.rs @@ -1,4 +1,5 @@ //@ compile-flags: -Copt-level=3 +//@ only-64bit //@ needs-deterministic-layouts (opposite scalar pair orders breaks it) #![crate_type = "lib"] @@ -7,8 +8,11 @@ type Demo = [u8; 3]; // CHECK-LABEL: @slice_iter_len_eq_zero #[no_mangle] pub fn slice_iter_len_eq_zero(y: std::slice::Iter<'_, Demo>) -> bool { - // CHECK-NOT: sub - // CHECK: %[[RET:.+]] = icmp eq ptr {{%y.0, %y.1|%y.1, %y.0}} + // CHECK: start: + // CHECK: %[[NOT_ZERO:.+]] = icmp ne i64 %1, 0 + // CHECK: call void @llvm.assume(i1 %[[NOT_ZERO]]) + // CHECK: %[[PTR_ADDR:.+]] = ptrtoint ptr %0 to i64 + // CHECK: %[[RET:.+]] = icmp eq i64 %1, %[[PTR_ADDR]] // CHECK: ret i1 %[[RET]] y.len() == 0 } @@ -21,7 +25,7 @@ pub fn slice_iter_len_eq_zero_ref(y: &mut std::slice::Iter<'_, Demo>) -> bool { // CHECK-SAME: !nonnull // CHECK: %[[B:.+]] = load ptr // CHECK-SAME: !nonnull - // CHECK: %[[RET:.+]] = icmp eq ptr %[[A]], %[[B]] + // CHECK: %[[RET:.+]] = icmp eq ptr %[[B]], %[[A]] // CHECK: ret i1 %[[RET]] y.len() == 0 } @@ -31,7 +35,7 @@ struct MyZST; // CHECK-LABEL: @slice_zst_iter_len_eq_zero #[no_mangle] pub fn slice_zst_iter_len_eq_zero(y: std::slice::Iter<'_, MyZST>) -> bool { - // CHECK: %[[RET:.+]] = icmp eq ptr %y.1, null + // CHECK: %[[RET:.+]] = icmp eq i64 %y.1, 0 // CHECK: ret i1 %[[RET]] y.len() == 0 } @@ -39,9 +43,9 @@ pub fn slice_zst_iter_len_eq_zero(y: std::slice::Iter<'_, MyZST>) -> bool { // CHECK-LABEL: @slice_zst_iter_len_eq_zero_ref #[no_mangle] pub fn slice_zst_iter_len_eq_zero_ref(y: &mut std::slice::Iter<'_, MyZST>) -> bool { - // CHECK: %[[LEN:.+]] = load ptr - // CHECK-NOT: !nonnull - // CHECK: %[[RET:.+]] = icmp eq ptr %[[LEN]], null + // CHECK: %[[LEN:.+]] = load i64 + // CHECK-NOT: !range + // CHECK: %[[RET:.+]] = icmp eq i64 %[[LEN]], 0 // CHECK: ret i1 %[[RET]] y.len() == 0 } diff --git a/tests/codegen/slice-iter-nonnull.rs b/tests/codegen/slice-iter-nonnull.rs index 87907e7ad0a30..5d93245319d07 100644 --- a/tests/codegen/slice-iter-nonnull.rs +++ b/tests/codegen/slice-iter-nonnull.rs @@ -23,7 +23,9 @@ pub fn slice_iter_next<'a>(it: &mut std::slice::Iter<'a, u32>) -> Option<&'a u32 // CHECK-SAME: !noundef // CHECK: icmp eq ptr %[[START]], %[[END]] - // CHECK: store ptr{{.+}}, ptr %it, + // CHECK-NOT: store + // CHECK: store ptr {{.+}}, ptr %it, + // CHECK-NOT: store it.next() } @@ -31,16 +33,18 @@ pub fn slice_iter_next<'a>(it: &mut std::slice::Iter<'a, u32>) -> Option<&'a u32 // 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 inbounds{{( nuw)?}} i8, ptr %it, {{i32 4|i64 8}} - // CHECK: %[[END:.+]] = load ptr, ptr %[[ENDP]] + // CHECK: %[[START:.+]] = load ptr, ptr %it, // CHECK-SAME: !nonnull // CHECK-SAME: !noundef - // CHECK: %[[START:.+]] = load ptr, ptr %it, + // CHECK: %[[ENDP:.+]] = getelementptr inbounds{{( nuw)?}} i8, ptr %it, {{i32 4|i64 8}} + // CHECK: %[[END:.+]] = load ptr, ptr %[[ENDP]] // CHECK-SAME: !nonnull // CHECK-SAME: !noundef // CHECK: icmp eq ptr %[[START]], %[[END]] - // CHECK: store ptr{{.+}}, ptr %[[ENDP]], + // CHECK-NOT: store + // CHECK: store {{i32|i64}} {{.+}}, ptr %[[ENDP]], + // CHECK-NOT: store it.next_back() } @@ -51,30 +55,32 @@ pub fn slice_iter_next_back<'a>(it: &mut std::slice::Iter<'a, u32>) -> Option<&' // attribute is there, and confirms adding the assume back doesn't do anything. // CHECK-LABEL: @slice_iter_new -// CHECK-SAME: (ptr noalias noundef nonnull {{.+}} %slice.0, {{.+}} noundef %slice.1) +// CHECK-SAME: (ptr noalias noundef nonnull {{.+}} %slice.0, [[USIZE:i32|i64]] noundef %slice.1) #[no_mangle] pub fn slice_iter_new(slice: &[u32]) -> std::slice::Iter<'_, u32> { // CHECK-NOT: slice - // CHECK: %[[END:.+]] = getelementptr inbounds{{( nuw)?}} i32{{.+}} %slice.0{{.+}} %slice.1 + // CHECK: %[[END_PTR:.+]] = getelementptr inbounds{{( nuw)?}} i32, ptr %slice.0, [[USIZE]] %slice.1 + // CHECK-NEXT: %[[END_ADDR:.+]] = ptrtoint ptr %[[END_PTR]] to [[USIZE]] // CHECK-NOT: slice // CHECK: insertvalue {{.+}} ptr %slice.0, 0 // CHECK-NOT: slice - // CHECK: insertvalue {{.+}} ptr %[[END]], 1 + // CHECK: insertvalue {{.+}} [[USIZE]] %[[END_ADDR]], 1 // CHECK-NOT: slice // CHECK: } slice.iter() } // CHECK-LABEL: @slice_iter_mut_new -// CHECK-SAME: (ptr noalias noundef nonnull {{.+}} %slice.0, {{.+}} noundef %slice.1) +// CHECK-SAME: (ptr noalias noundef nonnull {{.+}} %slice.0, [[USIZE:i32|i64]] noundef %slice.1) #[no_mangle] pub fn slice_iter_mut_new(slice: &mut [u32]) -> std::slice::IterMut<'_, u32> { // CHECK-NOT: slice - // CHECK: %[[END:.+]] = getelementptr inbounds{{( nuw)?}} i32{{.+}} %slice.0{{.+}} %slice.1 + // CHECK: %[[END_PTR:.+]] = getelementptr inbounds{{( nuw)?}} i32, ptr %slice.0, [[USIZE]] %slice.1 + // CHECK-NEXT: %[[END_ADDR:.+]] = ptrtoint ptr %[[END_PTR]] to [[USIZE]] // CHECK-NOT: slice // CHECK: insertvalue {{.+}} ptr %slice.0, 0 // CHECK-NOT: slice - // CHECK: insertvalue {{.+}} ptr %[[END]], 1 + // CHECK: insertvalue {{.+}} [[USIZE]] %[[END_ADDR]], 1 // CHECK-NOT: slice // CHECK: } slice.iter_mut() @@ -83,11 +89,11 @@ pub fn slice_iter_mut_new(slice: &mut [u32]) -> std::slice::IterMut<'_, u32> { // CHECK-LABEL: @slice_iter_is_empty #[no_mangle] pub fn slice_iter_is_empty(it: &std::slice::Iter<'_, u32>) -> bool { - // CHECK: %[[ENDP:.+]] = getelementptr inbounds{{( nuw)?}} i8, ptr %it, {{i32 4|i64 8}} - // CHECK: %[[END:.+]] = load ptr, ptr %[[ENDP]] + // CHECK: %[[START:.+]] = load ptr, ptr %it, // CHECK-SAME: !nonnull // CHECK-SAME: !noundef - // CHECK: %[[START:.+]] = load ptr, ptr %it, + // CHECK: %[[ENDP:.+]] = getelementptr inbounds{{( nuw)?}} i8, ptr %it, {{i32 4|i64 8}} + // CHECK: %[[END:.+]] = load ptr, ptr %[[ENDP]] // CHECK-SAME: !nonnull // CHECK-SAME: !noundef @@ -99,17 +105,18 @@ pub fn slice_iter_is_empty(it: &std::slice::Iter<'_, u32>) -> bool { // CHECK-LABEL: @slice_iter_len #[no_mangle] pub fn slice_iter_len(it: &std::slice::Iter<'_, u32>) -> usize { - // CHECK: %[[ENDP:.+]] = getelementptr inbounds{{( nuw)?}} i8, ptr %it, {{i32 4|i64 8}} - // CHECK: %[[END:.+]] = load ptr, ptr %[[ENDP]] + // CHECK: %[[START:.+]] = load ptr, ptr %it, // CHECK-SAME: !nonnull // CHECK-SAME: !noundef - // CHECK: %[[START:.+]] = load ptr, ptr %it, + // CHECK: %[[ENDP:.+]] = getelementptr inbounds{{( nuw)?}} i8, ptr %it, {{i32 4|i64 8}} + // CHECK: %[[END:.+]] = load ptr, ptr %[[ENDP]] // CHECK-SAME: !nonnull // CHECK-SAME: !noundef - // CHECK: ptrtoint - // CHECK: ptrtoint - // CHECK: sub nuw - // CHECK: lshr exact + // CHECK: %[[END_ADDR:.+]] = ptrtoint ptr %[[END]] + // CHECK: %[[START_ADDR:.+]] = ptrtoint ptr %[[START]] + // CHECK: %[[BYTES:.+]] = sub nuw [[USIZE]] %[[END_ADDR]], %[[START_ADDR]] + // CHECK: %[[ELEMS:.+]] = lshr exact [[USIZE]] %[[BYTES]], 2 + // CHECK: ret [[USIZE]] %[[ELEMS]] it.len() } diff --git a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir index d389e4069d05a..ae7c0ecca1788 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir @@ -4,95 +4,45 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { debug slice => _1; debug f => _2; let mut _0: (); - let mut _11: std::ptr::NonNull; - let mut _12: *const T; - let mut _13: usize; - let mut _32: std::option::Option<(usize, &T)>; - let mut _35: &impl Fn(usize, &T); - let mut _36: (usize, &T); - let _37: (); + let mut _10: std::slice::Iter<'_, T>; + let mut _11: std::iter::Enumerate>; + let mut _12: std::iter::Enumerate>; + let mut _20: std::option::Option<(usize, &T)>; + let mut _23: &impl Fn(usize, &T); + let mut _24: (usize, &T); + let _25: (); scope 1 { - debug (((iter: Enumerate>).0: std::slice::Iter<'_, T>).0: std::ptr::NonNull) => _11; - debug (((iter: Enumerate>).0: std::slice::Iter<'_, T>).1: *const T) => _12; - debug (((iter: Enumerate>).0: std::slice::Iter<'_, T>).2: std::marker::PhantomData<&T>) => const ZeroSized: PhantomData<&T>; - debug ((iter: Enumerate>).1: usize) => _13; - let _33: usize; - let _34: &T; + debug iter => _12; + let _21: usize; + let _22: &T; scope 2 { - debug i => _33; - debug x => _34; + debug i => _21; + debug x => _22; } - scope 18 (inlined > as Iterator>::next) { - let mut _27: std::option::Option<&T>; - let mut _30: (usize, bool); - let mut _31: (usize, &T); - scope 19 { - let _29: usize; - scope 24 { + scope 17 (inlined > as Iterator>::next) { + let mut _13: &mut std::slice::Iter<'_, T>; + let mut _14: std::option::Option<&T>; + let mut _18: (usize, bool); + let mut _19: (usize, &T); + scope 18 { + let _17: usize; + scope 23 { } } - scope 20 { - scope 21 { - scope 27 (inlined as FromResidual>>::from_residual) { + scope 19 { + scope 20 { + scope 26 (inlined as FromResidual>>::from_residual) { } } } - scope 22 { - scope 23 { - } - } - scope 25 (inlined as Try>::branch) { - let _28: &T; - scope 26 { + scope 21 { + scope 22 { } } - scope 28 (inlined as Iterator>::next) { - let _14: std::ptr::NonNull; - let _16: std::ptr::NonNull; - let mut _19: bool; - let mut _22: std::ptr::NonNull; - let mut _24: usize; - let _26: &T; - scope 29 { - let _15: *const T; - scope 30 { - let _23: usize; - scope 31 { - scope 34 (inlined #[track_caller] core::num::::unchecked_sub) { - scope 35 (inlined core::ub_checks::check_language_ub) { - scope 36 (inlined core::ub_checks::check_language_ub::runtime) { - } - } - } - scope 37 (inlined without_provenance_mut::) { - } - } - scope 32 (inlined std::ptr::const_ptr::::addr) { - scope 33 (inlined std::ptr::const_ptr::::cast::<()>) { - } - } - scope 38 (inlined as PartialEq>::eq) { - let mut _17: *mut T; - let mut _18: *mut T; - scope 39 (inlined NonNull::::as_ptr) { - } - scope 40 (inlined NonNull::::as_ptr) { - } - } - scope 41 (inlined NonNull::::add) { - let mut _20: *const T; - let mut _21: *const T; - scope 42 (inlined NonNull::::as_ptr) { - } - } - scope 43 (inlined NonNull::::as_ref::<'_>) { - let _25: *const T; - scope 44 (inlined NonNull::::as_ptr) { - } - scope 45 (inlined std::ptr::mut_ptr::::cast_const) { - } - } - } + scope 24 (inlined as Try>::branch) { + let mut _15: isize; + let _16: &T; + scope 25 { } } } @@ -100,22 +50,19 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { scope 3 (inlined core::slice::::iter) { scope 4 (inlined std::slice::Iter::<'_, T>::new) { let _3: usize; - let mut _7: *mut T; - let mut _8: *mut T; - let mut _10: *const T; + let mut _9: usize; scope 5 { let _6: std::ptr::NonNull; scope 6 { - let _9: *const T; + let _8: usize; scope 7 { } - scope 11 (inlined std::ptr::without_provenance::) { - scope 12 (inlined without_provenance_mut::) { + scope 11 (inlined NonNull::::add) { + let mut _7: *const T; + scope 12 (inlined NonNull::::as_ptr) { } } - scope 13 (inlined NonNull::::as_ptr) { - } - scope 14 (inlined #[track_caller] std::ptr::mut_ptr::::add) { + scope 13 (inlined core::slice::iter::addr_usize::) { } } scope 8 (inlined NonNull::<[T]>::from_ref) { @@ -129,187 +76,122 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { } } } - scope 15 (inlined as Iterator>::enumerate) { - scope 16 (inlined Enumerate::>::new) { + scope 14 (inlined as Iterator>::enumerate) { + scope 15 (inlined Enumerate::>::new) { } } - scope 17 (inlined > as IntoIterator>::into_iter) { + scope 16 (inlined > as IntoIterator>::into_iter) { } bb0: { + StorageLive(_10); StorageLive(_3); + StorageLive(_6); StorageLive(_4); + StorageLive(_5); + StorageLive(_7); _3 = PtrMetadata(copy _1); _4 = &raw const (*_1); - StorageLive(_5); _5 = copy _4 as *const T (PtrToPtr); - _6 = NonNull:: { pointer: move _5 }; - StorageDead(_5); - StorageLive(_9); + _6 = NonNull:: { pointer: copy _5 }; + StorageLive(_8); switchInt(const ::IS_ZST) -> [0: bb1, otherwise: bb2]; } bb1: { - StorageLive(_8); - StorageLive(_7); - _7 = copy _4 as *mut T (PtrToPtr); - _8 = Offset(copy _7, copy _3); - StorageDead(_7); - _9 = move _8 as *const T (PtrToPtr); - StorageDead(_8); + _7 = Offset(copy _5, copy _3); + _8 = copy _7 as usize (Transmute); goto -> bb3; } bb2: { - _9 = copy _3 as *const T (Transmute); + _8 = copy _3; goto -> bb3; } bb3: { - _10 = copy _9; + StorageLive(_9); + _9 = copy _8; + _10 = std::slice::Iter::<'_, T> { ptr: copy _6, end_addr_or_len: move _9, _marker: const ZeroSized: PhantomData<&T> }; StorageDead(_9); + StorageDead(_8); + StorageDead(_7); + StorageDead(_5); StorageDead(_4); + StorageDead(_6); StorageDead(_3); - StorageLive(_11); + _11 = Enumerate::> { iter: copy _10, count: const 0_usize }; + StorageDead(_10); StorageLive(_12); - StorageLive(_13); - _11 = copy _6; - _12 = copy _10; - _13 = const 0_usize; + _12 = copy _11; goto -> bb4; } bb4: { - StorageLive(_32); - StorageLive(_29); - StorageLive(_30); - StorageLive(_27); + StorageLive(_20); + StorageLive(_17); + StorageLive(_18); StorageLive(_14); - StorageLive(_15); - StorageLive(_23); - StorageLive(_24); - StorageLive(_16); - StorageLive(_26); - _14 = copy _11; - _15 = copy _12; - switchInt(const ::IS_ZST) -> [0: bb5, otherwise: bb8]; + StorageLive(_13); + _13 = &mut (_12.0: std::slice::Iter<'_, T>); + _14 = as Iterator>::next(move _13) -> [return: bb5, unwind unreachable]; } bb5: { - StorageLive(_19); - _16 = copy _15 as std::ptr::NonNull (Transmute); - StorageLive(_17); - _17 = copy _14 as *mut T (Transmute); - StorageLive(_18); - _18 = copy _16 as *mut T (Transmute); - _19 = Eq(move _17, move _18); - StorageDead(_18); - StorageDead(_17); - switchInt(move _19) -> [0: bb6, otherwise: bb7]; + StorageDead(_13); + StorageLive(_15); + _15 = discriminant(_14); + switchInt(move _15) -> [0: bb6, 1: bb8, otherwise: bb11]; } bb6: { - StorageDead(_19); - StorageLive(_22); - StorageLive(_21); - StorageLive(_20); - _20 = copy _14 as *const T (Transmute); - _21 = Offset(move _20, const 1_usize); + StorageDead(_15); + StorageDead(_14); + StorageDead(_18); + StorageDead(_17); StorageDead(_20); - _22 = NonNull:: { pointer: move _21 }; - StorageDead(_21); - _11 = move _22; - StorageDead(_22); - goto -> bb13; + StorageDead(_12); + drop(_2) -> [return: bb7, unwind unreachable]; } bb7: { - StorageDead(_19); - StorageDead(_26); - StorageDead(_16); - StorageDead(_24); - StorageDead(_23); - StorageDead(_15); - StorageDead(_14); - goto -> bb10; + return; } bb8: { - _23 = copy _15 as usize (Transmute); - switchInt(copy _23) -> [0: bb9, otherwise: bb12]; - } - - bb9: { - StorageDead(_26); - StorageDead(_16); - StorageDead(_24); - StorageDead(_23); + _16 = move ((_14 as Some).0: &T); StorageDead(_15); StorageDead(_14); - goto -> bb10; - } - - bb10: { - StorageDead(_27); - StorageDead(_30); - StorageDead(_29); - StorageDead(_32); - StorageDead(_11); - StorageDead(_12); - StorageDead(_13); - drop(_2) -> [return: bb11, unwind unreachable]; - } - - bb11: { - return; + _17 = copy (_12.1: usize); + _18 = AddWithOverflow(copy (_12.1: usize), const 1_usize); + assert(!move (_18.1: bool), "attempt to compute `{} + {}`, which would overflow", copy (_12.1: usize), const 1_usize) -> [success: bb9, unwind unreachable]; } - bb12: { - _24 = SubUnchecked(copy _23, const 1_usize); - _12 = copy _24 as *const T (Transmute); - goto -> bb13; + bb9: { + (_12.1: usize) = move (_18.0: usize); + StorageLive(_19); + _19 = (copy _17, copy _16); + _20 = Option::<(usize, &T)>::Some(move _19); + StorageDead(_19); + StorageDead(_18); + StorageDead(_17); + _21 = copy (((_20 as Some).0: (usize, &T)).0: usize); + _22 = copy (((_20 as Some).0: (usize, &T)).1: &T); + StorageLive(_23); + _23 = &_2; + StorageLive(_24); + _24 = (copy _21, copy _22); + _25 = >::call(move _23, move _24) -> [return: bb10, unwind unreachable]; } - bb13: { - StorageLive(_25); - _25 = copy _14 as *const T (Transmute); - _26 = &(*_25); - StorageDead(_25); - _27 = Option::<&T>::Some(copy _26); - StorageDead(_26); - StorageDead(_16); + bb10: { StorageDead(_24); StorageDead(_23); - StorageDead(_15); - StorageDead(_14); - _28 = move ((_27 as Some).0: &T); - StorageDead(_27); - _29 = copy _13; - _30 = AddWithOverflow(copy _13, const 1_usize); - assert(!move (_30.1: bool), "attempt to compute `{} + {}`, which would overflow", copy _13, const 1_usize) -> [success: bb14, unwind unreachable]; - } - - bb14: { - _13 = move (_30.0: usize); - StorageLive(_31); - _31 = (copy _29, copy _28); - _32 = Option::<(usize, &T)>::Some(move _31); - StorageDead(_31); - StorageDead(_30); - StorageDead(_29); - _33 = copy (((_32 as Some).0: (usize, &T)).0: usize); - _34 = copy (((_32 as Some).0: (usize, &T)).1: &T); - StorageLive(_35); - _35 = &_2; - StorageLive(_36); - _36 = (copy _33, copy _34); - _37 = >::call(move _35, move _36) -> [return: bb15, unwind unreachable]; + StorageDead(_20); + goto -> bb4; } - bb15: { - StorageDead(_36); - StorageDead(_35); - StorageDead(_32); - goto -> bb4; + bb11: { + unreachable; } } diff --git a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir index 3b58f1d61f4bb..bcea0f4b02e04 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir @@ -4,43 +4,40 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { debug slice => _1; debug f => _2; let mut _0: (); - let mut _11: std::slice::Iter<'_, T>; + let mut _10: std::slice::Iter<'_, T>; + let mut _11: std::iter::Enumerate>; let mut _12: std::iter::Enumerate>; - let mut _13: std::iter::Enumerate>; - let mut _14: &mut std::iter::Enumerate>; - let mut _15: std::option::Option<(usize, &T)>; - let mut _16: isize; - let mut _19: &impl Fn(usize, &T); - let mut _20: (usize, &T); - let _21: (); + let mut _13: &mut std::iter::Enumerate>; + let mut _14: std::option::Option<(usize, &T)>; + let mut _15: isize; + let mut _18: &impl Fn(usize, &T); + let mut _19: (usize, &T); + let _20: (); scope 1 { - debug iter => _13; - let _17: usize; - let _18: &T; + debug iter => _12; + let _16: usize; + let _17: &T; scope 2 { - debug i => _17; - debug x => _18; + debug i => _16; + debug x => _17; } } scope 3 (inlined core::slice::::iter) { scope 4 (inlined std::slice::Iter::<'_, T>::new) { let _3: usize; - let mut _7: *mut T; - let mut _8: *mut T; - let mut _10: *const T; + let mut _9: usize; scope 5 { let _6: std::ptr::NonNull; scope 6 { - let _9: *const T; + let _8: usize; scope 7 { } - scope 11 (inlined std::ptr::without_provenance::) { - scope 12 (inlined without_provenance_mut::) { + scope 11 (inlined NonNull::::add) { + let mut _7: *const T; + scope 12 (inlined NonNull::::as_ptr) { } } - scope 13 (inlined NonNull::::as_ptr) { - } - scope 14 (inlined #[track_caller] std::ptr::mut_ptr::::add) { + scope 13 (inlined core::slice::iter::addr_usize::) { } } scope 8 (inlined NonNull::<[T]>::from_ref) { @@ -54,74 +51,71 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { } } } - scope 15 (inlined as Iterator>::enumerate) { - scope 16 (inlined Enumerate::>::new) { + scope 14 (inlined as Iterator>::enumerate) { + scope 15 (inlined Enumerate::>::new) { } } - scope 17 (inlined > as IntoIterator>::into_iter) { + scope 16 (inlined > as IntoIterator>::into_iter) { } bb0: { - StorageLive(_11); + StorageLive(_10); StorageLive(_3); StorageLive(_6); StorageLive(_4); + StorageLive(_5); + StorageLive(_7); _3 = PtrMetadata(copy _1); _4 = &raw const (*_1); - StorageLive(_5); _5 = copy _4 as *const T (PtrToPtr); - _6 = NonNull:: { pointer: move _5 }; - StorageDead(_5); - StorageLive(_9); + _6 = NonNull:: { pointer: copy _5 }; + StorageLive(_8); switchInt(const ::IS_ZST) -> [0: bb1, otherwise: bb2]; } bb1: { - StorageLive(_8); - StorageLive(_7); - _7 = copy _4 as *mut T (PtrToPtr); - _8 = Offset(copy _7, copy _3); - StorageDead(_7); - _9 = move _8 as *const T (PtrToPtr); - StorageDead(_8); + _7 = Offset(copy _5, copy _3); + _8 = copy _7 as usize (Transmute); goto -> bb3; } bb2: { - _9 = copy _3 as *const T (Transmute); + _8 = copy _3; goto -> bb3; } bb3: { - StorageLive(_10); - _10 = copy _9; - _11 = std::slice::Iter::<'_, T> { ptr: copy _6, end_or_len: move _10, _marker: const ZeroSized: PhantomData<&T> }; - StorageDead(_10); + StorageLive(_9); + _9 = copy _8; + _10 = std::slice::Iter::<'_, T> { ptr: copy _6, end_addr_or_len: move _9, _marker: const ZeroSized: PhantomData<&T> }; StorageDead(_9); + StorageDead(_8); + StorageDead(_7); + StorageDead(_5); StorageDead(_4); StorageDead(_6); StorageDead(_3); - _12 = Enumerate::> { iter: copy _11, count: const 0_usize }; - StorageDead(_11); - StorageLive(_13); - _13 = copy _12; + _11 = Enumerate::> { iter: copy _10, count: const 0_usize }; + StorageDead(_10); + StorageLive(_12); + _12 = copy _11; goto -> bb4; } bb4: { - StorageLive(_15); - _14 = &mut _13; - _15 = > as Iterator>::next(move _14) -> [return: bb5, unwind: bb11]; + StorageLive(_14); + _13 = &mut _12; + _14 = > as Iterator>::next(move _13) -> [return: bb5, unwind: bb11]; } bb5: { - _16 = discriminant(_15); - switchInt(move _16) -> [0: bb6, 1: bb8, otherwise: bb10]; + _15 = discriminant(_14); + switchInt(move _15) -> [0: bb6, 1: bb8, otherwise: bb10]; } bb6: { - StorageDead(_15); - StorageDead(_13); + StorageDead(_14); + StorageDead(_12); drop(_2) -> [return: bb7, unwind continue]; } @@ -130,19 +124,19 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { } bb8: { - _17 = copy (((_15 as Some).0: (usize, &T)).0: usize); - _18 = copy (((_15 as Some).0: (usize, &T)).1: &T); + _16 = copy (((_14 as Some).0: (usize, &T)).0: usize); + _17 = copy (((_14 as Some).0: (usize, &T)).1: &T); + StorageLive(_18); + _18 = &_2; StorageLive(_19); - _19 = &_2; - StorageLive(_20); - _20 = (copy _17, copy _18); - _21 = >::call(move _19, move _20) -> [return: bb9, unwind: bb11]; + _19 = (copy _16, copy _17); + _20 = >::call(move _18, move _19) -> [return: bb9, unwind: bb11]; } bb9: { - StorageDead(_20); StorageDead(_19); - StorageDead(_15); + StorageDead(_18); + StorageDead(_14); goto -> bb4; } diff --git a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir index 216e05ec5b79c..09d23d7c867e0 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir @@ -4,89 +4,37 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { debug slice => _1; debug f => _2; let mut _0: (); - let mut _11: std::ptr::NonNull; - let mut _12: *const T; - let mut _26: std::option::Option<&T>; - let mut _28: &impl Fn(&T); - let mut _29: (&T,); - let _30: (); + let mut _10: std::slice::Iter<'_, T>; + let mut _11: std::slice::Iter<'_, T>; + let mut _12: &mut std::slice::Iter<'_, T>; + let mut _13: std::option::Option<&T>; + let mut _14: isize; + let mut _16: &impl Fn(&T); + let mut _17: (&T,); + let _18: (); scope 1 { - debug ((iter: std::slice::Iter<'_, T>).0: std::ptr::NonNull) => _11; - debug ((iter: std::slice::Iter<'_, T>).1: *const T) => _12; - debug ((iter: std::slice::Iter<'_, T>).2: std::marker::PhantomData<&T>) => const ZeroSized: PhantomData<&T>; - let _27: &T; + debug iter => _11; + let _15: &T; scope 2 { - debug x => _27; - } - scope 16 (inlined as Iterator>::next) { - let _13: std::ptr::NonNull; - let _15: std::ptr::NonNull; - let mut _18: bool; - let mut _21: std::ptr::NonNull; - let mut _23: usize; - let _25: &T; - scope 17 { - let _14: *const T; - scope 18 { - let _22: usize; - scope 19 { - scope 22 (inlined #[track_caller] core::num::::unchecked_sub) { - scope 23 (inlined core::ub_checks::check_language_ub) { - scope 24 (inlined core::ub_checks::check_language_ub::runtime) { - } - } - } - scope 25 (inlined without_provenance_mut::) { - } - } - scope 20 (inlined std::ptr::const_ptr::::addr) { - scope 21 (inlined std::ptr::const_ptr::::cast::<()>) { - } - } - scope 26 (inlined as PartialEq>::eq) { - let mut _16: *mut T; - let mut _17: *mut T; - scope 27 (inlined NonNull::::as_ptr) { - } - scope 28 (inlined NonNull::::as_ptr) { - } - } - scope 29 (inlined NonNull::::add) { - let mut _19: *const T; - let mut _20: *const T; - scope 30 (inlined NonNull::::as_ptr) { - } - } - scope 31 (inlined NonNull::::as_ref::<'_>) { - let _24: *const T; - scope 32 (inlined NonNull::::as_ptr) { - } - scope 33 (inlined std::ptr::mut_ptr::::cast_const) { - } - } - } - } + debug x => _15; } } scope 3 (inlined core::slice::::iter) { scope 4 (inlined std::slice::Iter::<'_, T>::new) { let _3: usize; - let mut _7: *mut T; - let mut _8: *mut T; - let mut _10: *const T; + let mut _9: usize; scope 5 { let _6: std::ptr::NonNull; scope 6 { - let _9: *const T; + let _8: usize; scope 7 { } - scope 11 (inlined std::ptr::without_provenance::) { - scope 12 (inlined without_provenance_mut::) { + scope 11 (inlined NonNull::::add) { + let mut _7: *const T; + scope 12 (inlined NonNull::::as_ptr) { } } - scope 13 (inlined NonNull::::as_ptr) { - } - scope 14 (inlined #[track_caller] std::ptr::mut_ptr::::add) { + scope 13 (inlined core::slice::iter::addr_usize::) { } } scope 8 (inlined NonNull::<[T]>::from_ref) { @@ -100,158 +48,88 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { } } } - scope 15 (inlined as IntoIterator>::into_iter) { + scope 14 (inlined as IntoIterator>::into_iter) { } bb0: { StorageLive(_3); + StorageLive(_6); StorageLive(_4); + StorageLive(_5); + StorageLive(_7); _3 = PtrMetadata(copy _1); _4 = &raw const (*_1); - StorageLive(_5); _5 = copy _4 as *const T (PtrToPtr); - _6 = NonNull:: { pointer: move _5 }; - StorageDead(_5); - StorageLive(_9); + _6 = NonNull:: { pointer: copy _5 }; + StorageLive(_8); switchInt(const ::IS_ZST) -> [0: bb1, otherwise: bb2]; } bb1: { - StorageLive(_8); - StorageLive(_7); - _7 = copy _4 as *mut T (PtrToPtr); - _8 = Offset(copy _7, copy _3); - StorageDead(_7); - _9 = move _8 as *const T (PtrToPtr); - StorageDead(_8); + _7 = Offset(copy _5, copy _3); + _8 = copy _7 as usize (Transmute); goto -> bb3; } bb2: { - _9 = copy _3 as *const T (Transmute); + _8 = copy _3; goto -> bb3; } bb3: { - _10 = copy _9; + StorageLive(_9); + _9 = copy _8; + _10 = std::slice::Iter::<'_, T> { ptr: copy _6, end_addr_or_len: move _9, _marker: const ZeroSized: PhantomData<&T> }; StorageDead(_9); + StorageDead(_8); + StorageDead(_7); + StorageDead(_5); StorageDead(_4); + StorageDead(_6); StorageDead(_3); StorageLive(_11); - StorageLive(_12); - _11 = copy _6; - _12 = copy _10; + _11 = copy _10; goto -> bb4; } bb4: { - StorageLive(_26); StorageLive(_13); - StorageLive(_14); - StorageLive(_22); - StorageLive(_23); - StorageLive(_15); - StorageLive(_25); - _13 = copy _11; - _14 = copy _12; - switchInt(const ::IS_ZST) -> [0: bb5, otherwise: bb8]; + _12 = &mut _11; + _13 = as Iterator>::next(move _12) -> [return: bb5, unwind unreachable]; } bb5: { - StorageLive(_18); - _15 = copy _14 as std::ptr::NonNull (Transmute); - StorageLive(_16); - _16 = copy _13 as *mut T (Transmute); - StorageLive(_17); - _17 = copy _15 as *mut T (Transmute); - _18 = Eq(move _16, move _17); - StorageDead(_17); - StorageDead(_16); - switchInt(move _18) -> [0: bb6, otherwise: bb7]; + _14 = discriminant(_13); + switchInt(move _14) -> [0: bb6, 1: bb8, otherwise: bb10]; } bb6: { - StorageDead(_18); - StorageLive(_21); - StorageLive(_20); - StorageLive(_19); - _19 = copy _13 as *const T (Transmute); - _20 = Offset(move _19, const 1_usize); - StorageDead(_19); - _21 = NonNull:: { pointer: move _20 }; - StorageDead(_20); - _11 = move _21; - StorageDead(_21); - goto -> bb13; + StorageDead(_13); + StorageDead(_11); + drop(_2) -> [return: bb7, unwind unreachable]; } bb7: { - StorageDead(_18); - StorageDead(_25); - StorageDead(_15); - StorageDead(_23); - StorageDead(_22); - StorageDead(_14); - StorageDead(_13); - goto -> bb10; + return; } bb8: { - _22 = copy _14 as usize (Transmute); - switchInt(copy _22) -> [0: bb9, otherwise: bb12]; + _15 = copy ((_13 as Some).0: &T); + StorageLive(_16); + _16 = &_2; + StorageLive(_17); + _17 = (copy _15,); + _18 = >::call(move _16, move _17) -> [return: bb9, unwind unreachable]; } bb9: { - StorageDead(_25); - StorageDead(_15); - StorageDead(_23); - StorageDead(_22); - StorageDead(_14); + StorageDead(_17); + StorageDead(_16); StorageDead(_13); - goto -> bb10; + goto -> bb4; } bb10: { - StorageDead(_26); - StorageDead(_11); - StorageDead(_12); - drop(_2) -> [return: bb11, unwind unreachable]; - } - - bb11: { - return; - } - - bb12: { - _23 = SubUnchecked(copy _22, const 1_usize); - _12 = copy _23 as *const T (Transmute); - goto -> bb13; - } - - bb13: { - StorageLive(_24); - _24 = copy _13 as *const T (Transmute); - _25 = &(*_24); - StorageDead(_24); - _26 = Option::<&T>::Some(copy _25); - StorageDead(_25); - StorageDead(_15); - StorageDead(_23); - StorageDead(_22); - StorageDead(_14); - StorageDead(_13); - _27 = copy ((_26 as Some).0: &T); - StorageLive(_28); - _28 = &_2; - StorageLive(_29); - _29 = (copy _27,); - _30 = >::call(move _28, move _29) -> [return: bb14, unwind unreachable]; - } - - bb14: { - StorageDead(_29); - StorageDead(_28); - StorageDead(_26); - goto -> bb4; + unreachable; } } diff --git a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir index 001023919804a..028b844354e79 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir @@ -4,89 +4,37 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { debug slice => _1; debug f => _2; let mut _0: (); - let mut _11: std::ptr::NonNull; - let mut _12: *const T; - let mut _26: std::option::Option<&T>; - let mut _28: &impl Fn(&T); - let mut _29: (&T,); - let _30: (); + let mut _10: std::slice::Iter<'_, T>; + let mut _11: std::slice::Iter<'_, T>; + let mut _12: &mut std::slice::Iter<'_, T>; + let mut _13: std::option::Option<&T>; + let mut _14: isize; + let mut _16: &impl Fn(&T); + let mut _17: (&T,); + let _18: (); scope 1 { - debug ((iter: std::slice::Iter<'_, T>).0: std::ptr::NonNull) => _11; - debug ((iter: std::slice::Iter<'_, T>).1: *const T) => _12; - debug ((iter: std::slice::Iter<'_, T>).2: std::marker::PhantomData<&T>) => const ZeroSized: PhantomData<&T>; - let _27: &T; + debug iter => _11; + let _15: &T; scope 2 { - debug x => _27; - } - scope 16 (inlined as Iterator>::next) { - let _13: std::ptr::NonNull; - let _15: std::ptr::NonNull; - let mut _18: bool; - let mut _21: std::ptr::NonNull; - let mut _23: usize; - let _25: &T; - scope 17 { - let _14: *const T; - scope 18 { - let _22: usize; - scope 19 { - scope 22 (inlined #[track_caller] core::num::::unchecked_sub) { - scope 23 (inlined core::ub_checks::check_language_ub) { - scope 24 (inlined core::ub_checks::check_language_ub::runtime) { - } - } - } - scope 25 (inlined without_provenance_mut::) { - } - } - scope 20 (inlined std::ptr::const_ptr::::addr) { - scope 21 (inlined std::ptr::const_ptr::::cast::<()>) { - } - } - scope 26 (inlined as PartialEq>::eq) { - let mut _16: *mut T; - let mut _17: *mut T; - scope 27 (inlined NonNull::::as_ptr) { - } - scope 28 (inlined NonNull::::as_ptr) { - } - } - scope 29 (inlined NonNull::::add) { - let mut _19: *const T; - let mut _20: *const T; - scope 30 (inlined NonNull::::as_ptr) { - } - } - scope 31 (inlined NonNull::::as_ref::<'_>) { - let _24: *const T; - scope 32 (inlined NonNull::::as_ptr) { - } - scope 33 (inlined std::ptr::mut_ptr::::cast_const) { - } - } - } - } + debug x => _15; } } scope 3 (inlined core::slice::::iter) { scope 4 (inlined std::slice::Iter::<'_, T>::new) { let _3: usize; - let mut _7: *mut T; - let mut _8: *mut T; - let mut _10: *const T; + let mut _9: usize; scope 5 { let _6: std::ptr::NonNull; scope 6 { - let _9: *const T; + let _8: usize; scope 7 { } - scope 11 (inlined std::ptr::without_provenance::) { - scope 12 (inlined without_provenance_mut::) { + scope 11 (inlined NonNull::::add) { + let mut _7: *const T; + scope 12 (inlined NonNull::::as_ptr) { } } - scope 13 (inlined NonNull::::as_ptr) { - } - scope 14 (inlined #[track_caller] std::ptr::mut_ptr::::add) { + scope 13 (inlined core::slice::iter::addr_usize::) { } } scope 8 (inlined NonNull::<[T]>::from_ref) { @@ -100,166 +48,96 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () { } } } - scope 15 (inlined as IntoIterator>::into_iter) { + scope 14 (inlined as IntoIterator>::into_iter) { } bb0: { StorageLive(_3); + StorageLive(_6); StorageLive(_4); + StorageLive(_5); + StorageLive(_7); _3 = PtrMetadata(copy _1); _4 = &raw const (*_1); - StorageLive(_5); _5 = copy _4 as *const T (PtrToPtr); - _6 = NonNull:: { pointer: move _5 }; - StorageDead(_5); - StorageLive(_9); + _6 = NonNull:: { pointer: copy _5 }; + StorageLive(_8); switchInt(const ::IS_ZST) -> [0: bb1, otherwise: bb2]; } bb1: { - StorageLive(_8); - StorageLive(_7); - _7 = copy _4 as *mut T (PtrToPtr); - _8 = Offset(copy _7, copy _3); - StorageDead(_7); - _9 = move _8 as *const T (PtrToPtr); - StorageDead(_8); + _7 = Offset(copy _5, copy _3); + _8 = copy _7 as usize (Transmute); goto -> bb3; } bb2: { - _9 = copy _3 as *const T (Transmute); + _8 = copy _3; goto -> bb3; } bb3: { - _10 = copy _9; + StorageLive(_9); + _9 = copy _8; + _10 = std::slice::Iter::<'_, T> { ptr: copy _6, end_addr_or_len: move _9, _marker: const ZeroSized: PhantomData<&T> }; StorageDead(_9); + StorageDead(_8); + StorageDead(_7); + StorageDead(_5); StorageDead(_4); + StorageDead(_6); StorageDead(_3); StorageLive(_11); - StorageLive(_12); - _11 = copy _6; - _12 = copy _10; + _11 = copy _10; goto -> bb4; } bb4: { - StorageLive(_26); StorageLive(_13); - StorageLive(_14); - StorageLive(_22); - StorageLive(_23); - StorageLive(_15); - StorageLive(_25); - _13 = copy _11; - _14 = copy _12; - switchInt(const ::IS_ZST) -> [0: bb5, otherwise: bb8]; + _12 = &mut _11; + _13 = as Iterator>::next(move _12) -> [return: bb5, unwind: bb11]; } bb5: { - StorageLive(_18); - _15 = copy _14 as std::ptr::NonNull (Transmute); - StorageLive(_16); - _16 = copy _13 as *mut T (Transmute); - StorageLive(_17); - _17 = copy _15 as *mut T (Transmute); - _18 = Eq(move _16, move _17); - StorageDead(_17); - StorageDead(_16); - switchInt(move _18) -> [0: bb6, otherwise: bb7]; + _14 = discriminant(_13); + switchInt(move _14) -> [0: bb6, 1: bb8, otherwise: bb10]; } bb6: { - StorageDead(_18); - StorageLive(_21); - StorageLive(_20); - StorageLive(_19); - _19 = copy _13 as *const T (Transmute); - _20 = Offset(move _19, const 1_usize); - StorageDead(_19); - _21 = NonNull:: { pointer: move _20 }; - StorageDead(_20); - _11 = move _21; - StorageDead(_21); - goto -> bb13; + StorageDead(_13); + StorageDead(_11); + drop(_2) -> [return: bb7, unwind continue]; } bb7: { - StorageDead(_18); - StorageDead(_25); - StorageDead(_15); - StorageDead(_23); - StorageDead(_22); - StorageDead(_14); - StorageDead(_13); - goto -> bb10; + return; } bb8: { - _22 = copy _14 as usize (Transmute); - switchInt(copy _22) -> [0: bb9, otherwise: bb12]; + _15 = copy ((_13 as Some).0: &T); + StorageLive(_16); + _16 = &_2; + StorageLive(_17); + _17 = (copy _15,); + _18 = >::call(move _16, move _17) -> [return: bb9, unwind: bb11]; } bb9: { - StorageDead(_25); - StorageDead(_15); - StorageDead(_23); - StorageDead(_22); - StorageDead(_14); + StorageDead(_17); + StorageDead(_16); StorageDead(_13); - goto -> bb10; + goto -> bb4; } bb10: { - StorageDead(_26); - StorageDead(_11); - StorageDead(_12); - drop(_2) -> [return: bb11, unwind continue]; - } - - bb11: { - return; - } - - bb12: { - _23 = SubUnchecked(copy _22, const 1_usize); - _12 = copy _23 as *const T (Transmute); - goto -> bb13; - } - - bb13: { - StorageLive(_24); - _24 = copy _13 as *const T (Transmute); - _25 = &(*_24); - StorageDead(_24); - _26 = Option::<&T>::Some(copy _25); - StorageDead(_25); - StorageDead(_15); - StorageDead(_23); - StorageDead(_22); - StorageDead(_14); - StorageDead(_13); - _27 = copy ((_26 as Some).0: &T); - StorageLive(_28); - _28 = &_2; - StorageLive(_29); - _29 = (copy _27,); - _30 = >::call(move _28, move _29) -> [return: bb14, unwind: bb15]; - } - - bb14: { - StorageDead(_29); - StorageDead(_28); - StorageDead(_26); - goto -> bb4; + unreachable; } - bb15 (cleanup): { - drop(_2) -> [return: bb16, unwind terminate(cleanup)]; + bb11 (cleanup): { + drop(_2) -> [return: bb12, unwind terminate(cleanup)]; } - bb16 (cleanup): { + bb12 (cleanup): { resume; } } diff --git a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir index b09e36223441a..5bd5467c8eaa8 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir @@ -4,43 +4,40 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { debug slice => _1; debug f => _2; let mut _0: (); - let mut _11: std::slice::Iter<'_, T>; + let mut _10: std::slice::Iter<'_, T>; + let mut _11: std::iter::Rev>; let mut _12: std::iter::Rev>; - let mut _13: std::iter::Rev>; - let mut _15: std::option::Option<&T>; - let mut _16: isize; - let mut _18: &impl Fn(&T); - let mut _19: (&T,); - let _20: (); + let mut _14: std::option::Option<&T>; + let mut _15: isize; + let mut _17: &impl Fn(&T); + let mut _18: (&T,); + let _19: (); scope 1 { - debug iter => _13; - let _17: &T; + debug iter => _12; + let _16: &T; scope 2 { - debug x => _17; + debug x => _16; } - scope 18 (inlined > as Iterator>::next) { - let mut _14: &mut std::slice::Iter<'_, T>; + scope 17 (inlined > as Iterator>::next) { + let mut _13: &mut std::slice::Iter<'_, T>; } } scope 3 (inlined core::slice::::iter) { scope 4 (inlined std::slice::Iter::<'_, T>::new) { let _3: usize; - let mut _7: *mut T; - let mut _8: *mut T; - let mut _10: *const T; + let mut _9: usize; scope 5 { let _6: std::ptr::NonNull; scope 6 { - let _9: *const T; + let _8: usize; scope 7 { } - scope 11 (inlined std::ptr::without_provenance::) { - scope 12 (inlined without_provenance_mut::) { + scope 11 (inlined NonNull::::add) { + let mut _7: *const T; + scope 12 (inlined NonNull::::as_ptr) { } } - scope 13 (inlined NonNull::::as_ptr) { - } - scope 14 (inlined #[track_caller] std::ptr::mut_ptr::::add) { + scope 13 (inlined core::slice::iter::addr_usize::) { } } scope 8 (inlined NonNull::<[T]>::from_ref) { @@ -54,76 +51,73 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { } } } - scope 15 (inlined as Iterator>::rev) { - scope 16 (inlined Rev::>::new) { + scope 14 (inlined as Iterator>::rev) { + scope 15 (inlined Rev::>::new) { } } - scope 17 (inlined > as IntoIterator>::into_iter) { + scope 16 (inlined > as IntoIterator>::into_iter) { } bb0: { - StorageLive(_11); + StorageLive(_10); StorageLive(_3); StorageLive(_6); StorageLive(_4); + StorageLive(_5); + StorageLive(_7); _3 = PtrMetadata(copy _1); _4 = &raw const (*_1); - StorageLive(_5); _5 = copy _4 as *const T (PtrToPtr); - _6 = NonNull:: { pointer: move _5 }; - StorageDead(_5); - StorageLive(_9); + _6 = NonNull:: { pointer: copy _5 }; + StorageLive(_8); switchInt(const ::IS_ZST) -> [0: bb1, otherwise: bb2]; } bb1: { - StorageLive(_8); - StorageLive(_7); - _7 = copy _4 as *mut T (PtrToPtr); - _8 = Offset(copy _7, copy _3); - StorageDead(_7); - _9 = move _8 as *const T (PtrToPtr); - StorageDead(_8); + _7 = Offset(copy _5, copy _3); + _8 = copy _7 as usize (Transmute); goto -> bb3; } bb2: { - _9 = copy _3 as *const T (Transmute); + _8 = copy _3; goto -> bb3; } bb3: { - StorageLive(_10); - _10 = copy _9; - _11 = std::slice::Iter::<'_, T> { ptr: copy _6, end_or_len: move _10, _marker: const ZeroSized: PhantomData<&T> }; - StorageDead(_10); + StorageLive(_9); + _9 = copy _8; + _10 = std::slice::Iter::<'_, T> { ptr: copy _6, end_addr_or_len: move _9, _marker: const ZeroSized: PhantomData<&T> }; StorageDead(_9); + StorageDead(_8); + StorageDead(_7); + StorageDead(_5); StorageDead(_4); StorageDead(_6); StorageDead(_3); - _12 = Rev::> { iter: copy _11 }; - StorageDead(_11); - StorageLive(_13); - _13 = copy _12; + _11 = Rev::> { iter: copy _10 }; + StorageDead(_10); + StorageLive(_12); + _12 = copy _11; goto -> bb4; } bb4: { - StorageLive(_15); StorageLive(_14); - _14 = &mut (_13.0: std::slice::Iter<'_, T>); - _15 = as DoubleEndedIterator>::next_back(move _14) -> [return: bb5, unwind unreachable]; + StorageLive(_13); + _13 = &mut (_12.0: std::slice::Iter<'_, T>); + _14 = as DoubleEndedIterator>::next_back(move _13) -> [return: bb5, unwind unreachable]; } bb5: { - StorageDead(_14); - _16 = discriminant(_15); - switchInt(move _16) -> [0: bb6, 1: bb8, otherwise: bb10]; + StorageDead(_13); + _15 = discriminant(_14); + switchInt(move _15) -> [0: bb6, 1: bb8, otherwise: bb10]; } bb6: { - StorageDead(_15); - StorageDead(_13); + StorageDead(_14); + StorageDead(_12); drop(_2) -> [return: bb7, unwind unreachable]; } @@ -132,18 +126,18 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { } bb8: { - _17 = copy ((_15 as Some).0: &T); + _16 = copy ((_14 as Some).0: &T); + StorageLive(_17); + _17 = &_2; StorageLive(_18); - _18 = &_2; - StorageLive(_19); - _19 = (copy _17,); - _20 = >::call(move _18, move _19) -> [return: bb9, unwind unreachable]; + _18 = (copy _16,); + _19 = >::call(move _17, move _18) -> [return: bb9, unwind unreachable]; } bb9: { - StorageDead(_19); StorageDead(_18); - StorageDead(_15); + StorageDead(_17); + StorageDead(_14); goto -> bb4; } diff --git a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir index 12b54b57b8448..9d5f9430e30d5 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir @@ -4,43 +4,40 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { debug slice => _1; debug f => _2; let mut _0: (); - let mut _11: std::slice::Iter<'_, T>; + let mut _10: std::slice::Iter<'_, T>; + let mut _11: std::iter::Rev>; let mut _12: std::iter::Rev>; - let mut _13: std::iter::Rev>; - let mut _15: std::option::Option<&T>; - let mut _16: isize; - let mut _18: &impl Fn(&T); - let mut _19: (&T,); - let _20: (); + let mut _14: std::option::Option<&T>; + let mut _15: isize; + let mut _17: &impl Fn(&T); + let mut _18: (&T,); + let _19: (); scope 1 { - debug iter => _13; - let _17: &T; + debug iter => _12; + let _16: &T; scope 2 { - debug x => _17; + debug x => _16; } - scope 18 (inlined > as Iterator>::next) { - let mut _14: &mut std::slice::Iter<'_, T>; + scope 17 (inlined > as Iterator>::next) { + let mut _13: &mut std::slice::Iter<'_, T>; } } scope 3 (inlined core::slice::::iter) { scope 4 (inlined std::slice::Iter::<'_, T>::new) { let _3: usize; - let mut _7: *mut T; - let mut _8: *mut T; - let mut _10: *const T; + let mut _9: usize; scope 5 { let _6: std::ptr::NonNull; scope 6 { - let _9: *const T; + let _8: usize; scope 7 { } - scope 11 (inlined std::ptr::without_provenance::) { - scope 12 (inlined without_provenance_mut::) { + scope 11 (inlined NonNull::::add) { + let mut _7: *const T; + scope 12 (inlined NonNull::::as_ptr) { } } - scope 13 (inlined NonNull::::as_ptr) { - } - scope 14 (inlined #[track_caller] std::ptr::mut_ptr::::add) { + scope 13 (inlined core::slice::iter::addr_usize::) { } } scope 8 (inlined NonNull::<[T]>::from_ref) { @@ -54,76 +51,73 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { } } } - scope 15 (inlined as Iterator>::rev) { - scope 16 (inlined Rev::>::new) { + scope 14 (inlined as Iterator>::rev) { + scope 15 (inlined Rev::>::new) { } } - scope 17 (inlined > as IntoIterator>::into_iter) { + scope 16 (inlined > as IntoIterator>::into_iter) { } bb0: { - StorageLive(_11); + StorageLive(_10); StorageLive(_3); StorageLive(_6); StorageLive(_4); + StorageLive(_5); + StorageLive(_7); _3 = PtrMetadata(copy _1); _4 = &raw const (*_1); - StorageLive(_5); _5 = copy _4 as *const T (PtrToPtr); - _6 = NonNull:: { pointer: move _5 }; - StorageDead(_5); - StorageLive(_9); + _6 = NonNull:: { pointer: copy _5 }; + StorageLive(_8); switchInt(const ::IS_ZST) -> [0: bb1, otherwise: bb2]; } bb1: { - StorageLive(_8); - StorageLive(_7); - _7 = copy _4 as *mut T (PtrToPtr); - _8 = Offset(copy _7, copy _3); - StorageDead(_7); - _9 = move _8 as *const T (PtrToPtr); - StorageDead(_8); + _7 = Offset(copy _5, copy _3); + _8 = copy _7 as usize (Transmute); goto -> bb3; } bb2: { - _9 = copy _3 as *const T (Transmute); + _8 = copy _3; goto -> bb3; } bb3: { - StorageLive(_10); - _10 = copy _9; - _11 = std::slice::Iter::<'_, T> { ptr: copy _6, end_or_len: move _10, _marker: const ZeroSized: PhantomData<&T> }; - StorageDead(_10); + StorageLive(_9); + _9 = copy _8; + _10 = std::slice::Iter::<'_, T> { ptr: copy _6, end_addr_or_len: move _9, _marker: const ZeroSized: PhantomData<&T> }; StorageDead(_9); + StorageDead(_8); + StorageDead(_7); + StorageDead(_5); StorageDead(_4); StorageDead(_6); StorageDead(_3); - _12 = Rev::> { iter: copy _11 }; - StorageDead(_11); - StorageLive(_13); - _13 = copy _12; + _11 = Rev::> { iter: copy _10 }; + StorageDead(_10); + StorageLive(_12); + _12 = copy _11; goto -> bb4; } bb4: { - StorageLive(_15); StorageLive(_14); - _14 = &mut (_13.0: std::slice::Iter<'_, T>); - _15 = as DoubleEndedIterator>::next_back(move _14) -> [return: bb5, unwind: bb11]; + StorageLive(_13); + _13 = &mut (_12.0: std::slice::Iter<'_, T>); + _14 = as DoubleEndedIterator>::next_back(move _13) -> [return: bb5, unwind: bb11]; } bb5: { - StorageDead(_14); - _16 = discriminant(_15); - switchInt(move _16) -> [0: bb6, 1: bb8, otherwise: bb10]; + StorageDead(_13); + _15 = discriminant(_14); + switchInt(move _15) -> [0: bb6, 1: bb8, otherwise: bb10]; } bb6: { - StorageDead(_15); - StorageDead(_13); + StorageDead(_14); + StorageDead(_12); drop(_2) -> [return: bb7, unwind continue]; } @@ -132,18 +126,18 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () { } bb8: { - _17 = copy ((_15 as Some).0: &T); + _16 = copy ((_14 as Some).0: &T); + StorageLive(_17); + _17 = &_2; StorageLive(_18); - _18 = &_2; - StorageLive(_19); - _19 = (copy _17,); - _20 = >::call(move _18, move _19) -> [return: bb9, unwind: bb11]; + _18 = (copy _16,); + _19 = >::call(move _17, move _18) -> [return: bb9, unwind: bb11]; } bb9: { - StorageDead(_19); StorageDead(_18); - StorageDead(_15); + StorageDead(_17); + StorageDead(_14); goto -> bb4; } diff --git a/tests/mir-opt/pre-codegen/slice_iter.slice_iter_generic_is_empty.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.slice_iter_generic_is_empty.PreCodegen.after.panic-abort.mir index 38d00cfbabdda..c2a0a4edaf03d 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.slice_iter_generic_is_empty.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.slice_iter_generic_is_empty.PreCodegen.after.panic-abort.mir @@ -4,67 +4,102 @@ fn slice_iter_generic_is_empty(_1: &std::slice::Iter<'_, T>) -> bool { debug it => _1; let mut _0: bool; scope 1 (inlined as ExactSizeIterator>::is_empty) { - let mut _2: *const T; + let mut _3: *const usize; + let mut _4: *const std::ptr::NonNull; + let mut _6: *const T; let mut _7: *const T; + let mut _8: usize; + let _13: usize; scope 2 { - let _3: std::ptr::NonNull; - let _8: usize; - scope 3 { - } + } + scope 3 { scope 4 { - scope 7 (inlined as PartialEq>::eq) { - let mut _4: std::ptr::NonNull; - let mut _5: *mut T; - let mut _6: *mut T; - scope 8 (inlined NonNull::::as_ptr) { + scope 13 (inlined as PartialEq>::eq) { + let mut _10: std::ptr::NonNull; + let mut _11: *mut T; + let mut _12: *mut T; + scope 14 (inlined NonNull::::as_ptr) { } - scope 9 (inlined NonNull::::as_ptr) { + scope 15 (inlined NonNull::::as_ptr) { } } } - scope 5 (inlined std::ptr::const_ptr::::addr) { - scope 6 (inlined std::ptr::const_ptr::::cast::<()>) { + scope 5 { + let _2: std::ptr::NonNull; + scope 6 { + let _5: std::ptr::NonNull; + scope 7 { + scope 9 (inlined NonNull::::as_ptr) { + } + scope 10 (inlined NonNull::::as_ptr) { + } + scope 11 (inlined NonNull::::add) { + let mut _9: *const T; + scope 12 (inlined NonNull::::as_ptr) { + } + } + } + scope 8 (inlined std::ptr::const_ptr::::cast::>) { + } } } } } bb0: { + StorageLive(_13); + StorageLive(_2); + StorageLive(_5); StorageLive(_8); StorageLive(_7); - StorageLive(_3); - switchInt(const ::IS_ZST) -> [0: bb1, otherwise: bb2]; + StorageLive(_9); + switchInt(const ::IS_ZST) -> [0: bb1, otherwise: bb3]; } bb1: { - StorageLive(_2); - _2 = copy ((*_1).1: *const T); - _3 = move _2 as std::ptr::NonNull (Transmute); - StorageDead(_2); - StorageLive(_5); + _2 = copy ((*_1).0: std::ptr::NonNull); StorageLive(_4); - _4 = copy ((*_1).0: std::ptr::NonNull); - _5 = copy _4 as *mut T (Transmute); + StorageLive(_3); + _3 = &raw const ((*_1).1: usize); + _4 = copy _3 as *const std::ptr::NonNull (PtrToPtr); + StorageDead(_3); + _5 = copy (*_4); StorageDead(_4); StorageLive(_6); - _6 = copy _3 as *mut T (Transmute); - _0 = Eq(move _5, move _6); - StorageDead(_6); - StorageDead(_5); - goto -> bb3; + _6 = copy _5 as *const T (Transmute); + _7 = copy _2 as *const T (Transmute); + _8 = ptr_offset_from_unsigned::(move _6, copy _7) -> [return: bb2, unwind unreachable]; } bb2: { - _7 = copy ((*_1).1: *const T); - _8 = copy _7 as usize (Transmute); - _0 = Eq(copy _8, const 0_usize); - goto -> bb3; + StorageDead(_6); + _9 = Offset(copy _7, copy _8); + StorageLive(_11); + StorageLive(_10); + _10 = copy ((*_1).0: std::ptr::NonNull); + _11 = copy _10 as *mut T (Transmute); + StorageDead(_10); + StorageLive(_12); + _12 = copy _9 as *mut T (PtrToPtr); + _0 = Eq(move _11, move _12); + StorageDead(_12); + StorageDead(_11); + goto -> bb4; } bb3: { - StorageDead(_3); + _13 = copy ((*_1).1: usize); + _0 = Eq(copy _13, const 0_usize); + goto -> bb4; + } + + bb4: { + StorageDead(_9); StorageDead(_7); StorageDead(_8); + StorageDead(_5); + StorageDead(_2); + StorageDead(_13); return; } } diff --git a/tests/mir-opt/pre-codegen/slice_iter.slice_iter_generic_is_empty.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.slice_iter_generic_is_empty.PreCodegen.after.panic-unwind.mir index 38d00cfbabdda..c2a0a4edaf03d 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.slice_iter_generic_is_empty.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.slice_iter_generic_is_empty.PreCodegen.after.panic-unwind.mir @@ -4,67 +4,102 @@ fn slice_iter_generic_is_empty(_1: &std::slice::Iter<'_, T>) -> bool { debug it => _1; let mut _0: bool; scope 1 (inlined as ExactSizeIterator>::is_empty) { - let mut _2: *const T; + let mut _3: *const usize; + let mut _4: *const std::ptr::NonNull; + let mut _6: *const T; let mut _7: *const T; + let mut _8: usize; + let _13: usize; scope 2 { - let _3: std::ptr::NonNull; - let _8: usize; - scope 3 { - } + } + scope 3 { scope 4 { - scope 7 (inlined as PartialEq>::eq) { - let mut _4: std::ptr::NonNull; - let mut _5: *mut T; - let mut _6: *mut T; - scope 8 (inlined NonNull::::as_ptr) { + scope 13 (inlined as PartialEq>::eq) { + let mut _10: std::ptr::NonNull; + let mut _11: *mut T; + let mut _12: *mut T; + scope 14 (inlined NonNull::::as_ptr) { } - scope 9 (inlined NonNull::::as_ptr) { + scope 15 (inlined NonNull::::as_ptr) { } } } - scope 5 (inlined std::ptr::const_ptr::::addr) { - scope 6 (inlined std::ptr::const_ptr::::cast::<()>) { + scope 5 { + let _2: std::ptr::NonNull; + scope 6 { + let _5: std::ptr::NonNull; + scope 7 { + scope 9 (inlined NonNull::::as_ptr) { + } + scope 10 (inlined NonNull::::as_ptr) { + } + scope 11 (inlined NonNull::::add) { + let mut _9: *const T; + scope 12 (inlined NonNull::::as_ptr) { + } + } + } + scope 8 (inlined std::ptr::const_ptr::::cast::>) { + } } } } } bb0: { + StorageLive(_13); + StorageLive(_2); + StorageLive(_5); StorageLive(_8); StorageLive(_7); - StorageLive(_3); - switchInt(const ::IS_ZST) -> [0: bb1, otherwise: bb2]; + StorageLive(_9); + switchInt(const ::IS_ZST) -> [0: bb1, otherwise: bb3]; } bb1: { - StorageLive(_2); - _2 = copy ((*_1).1: *const T); - _3 = move _2 as std::ptr::NonNull (Transmute); - StorageDead(_2); - StorageLive(_5); + _2 = copy ((*_1).0: std::ptr::NonNull); StorageLive(_4); - _4 = copy ((*_1).0: std::ptr::NonNull); - _5 = copy _4 as *mut T (Transmute); + StorageLive(_3); + _3 = &raw const ((*_1).1: usize); + _4 = copy _3 as *const std::ptr::NonNull (PtrToPtr); + StorageDead(_3); + _5 = copy (*_4); StorageDead(_4); StorageLive(_6); - _6 = copy _3 as *mut T (Transmute); - _0 = Eq(move _5, move _6); - StorageDead(_6); - StorageDead(_5); - goto -> bb3; + _6 = copy _5 as *const T (Transmute); + _7 = copy _2 as *const T (Transmute); + _8 = ptr_offset_from_unsigned::(move _6, copy _7) -> [return: bb2, unwind unreachable]; } bb2: { - _7 = copy ((*_1).1: *const T); - _8 = copy _7 as usize (Transmute); - _0 = Eq(copy _8, const 0_usize); - goto -> bb3; + StorageDead(_6); + _9 = Offset(copy _7, copy _8); + StorageLive(_11); + StorageLive(_10); + _10 = copy ((*_1).0: std::ptr::NonNull); + _11 = copy _10 as *mut T (Transmute); + StorageDead(_10); + StorageLive(_12); + _12 = copy _9 as *mut T (PtrToPtr); + _0 = Eq(move _11, move _12); + StorageDead(_12); + StorageDead(_11); + goto -> bb4; } bb3: { - StorageDead(_3); + _13 = copy ((*_1).1: usize); + _0 = Eq(copy _13, const 0_usize); + goto -> bb4; + } + + bb4: { + StorageDead(_9); StorageDead(_7); StorageDead(_8); + StorageDead(_5); + StorageDead(_2); + StorageDead(_13); return; } } diff --git a/tests/mir-opt/pre-codegen/slice_iter.slice_iter_next.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.slice_iter_next.PreCodegen.after.panic-abort.mir index c0ed0aea1e260..8edac638ccdd6 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.slice_iter_next.PreCodegen.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.slice_iter_next.PreCodegen.after.panic-abort.mir @@ -3,134 +3,12 @@ fn slice_iter_next(_1: &mut std::slice::Iter<'_, T>) -> Option<&T> { debug it => _1; let mut _0: std::option::Option<&T>; - scope 1 (inlined as Iterator>::next) { - let _2: std::ptr::NonNull; - let _4: std::ptr::NonNull; - let mut _7: bool; - let mut _10: std::ptr::NonNull; - let mut _12: usize; - let _14: &T; - scope 2 { - let _3: *const T; - scope 3 { - let _11: usize; - scope 4 { - scope 7 (inlined #[track_caller] core::num::::unchecked_sub) { - scope 8 (inlined core::ub_checks::check_language_ub) { - scope 9 (inlined core::ub_checks::check_language_ub::runtime) { - } - } - } - scope 10 (inlined without_provenance_mut::) { - } - } - scope 5 (inlined std::ptr::const_ptr::::addr) { - scope 6 (inlined std::ptr::const_ptr::::cast::<()>) { - } - } - scope 11 (inlined as PartialEq>::eq) { - let mut _5: *mut T; - let mut _6: *mut T; - scope 12 (inlined NonNull::::as_ptr) { - } - scope 13 (inlined NonNull::::as_ptr) { - } - } - scope 14 (inlined NonNull::::add) { - let mut _8: *const T; - let mut _9: *const T; - scope 15 (inlined NonNull::::as_ptr) { - } - } - scope 16 (inlined NonNull::::as_ref::<'_>) { - let _13: *const T; - scope 17 (inlined NonNull::::as_ptr) { - } - scope 18 (inlined std::ptr::mut_ptr::::cast_const) { - } - } - } - } - } bb0: { - StorageLive(_2); - StorageLive(_3); - StorageLive(_11); - StorageLive(_12); - StorageLive(_4); - StorageLive(_14); - _2 = copy ((*_1).0: std::ptr::NonNull); - _3 = copy ((*_1).1: *const T); - switchInt(const ::IS_ZST) -> [0: bb1, otherwise: bb4]; + _0 = as Iterator>::next(move _1) -> [return: bb1, unwind unreachable]; } bb1: { - StorageLive(_7); - _4 = copy _3 as std::ptr::NonNull (Transmute); - StorageLive(_5); - _5 = copy _2 as *mut T (Transmute); - StorageLive(_6); - _6 = copy _4 as *mut T (Transmute); - _7 = Eq(move _5, move _6); - StorageDead(_6); - StorageDead(_5); - switchInt(move _7) -> [0: bb2, otherwise: bb3]; - } - - bb2: { - StorageDead(_7); - StorageLive(_10); - StorageLive(_9); - StorageLive(_8); - _8 = copy _2 as *const T (Transmute); - _9 = Offset(move _8, const 1_usize); - StorageDead(_8); - _10 = NonNull:: { pointer: move _9 }; - StorageDead(_9); - ((*_1).0: std::ptr::NonNull) = move _10; - StorageDead(_10); - goto -> bb7; - } - - bb3: { - _0 = const {transmute(0x0000000000000000): Option<&T>}; - StorageDead(_7); - goto -> bb8; - } - - bb4: { - _11 = copy _3 as usize (Transmute); - switchInt(copy _11) -> [0: bb5, otherwise: bb6]; - } - - bb5: { - _0 = const {transmute(0x0000000000000000): Option<&T>}; - goto -> bb8; - } - - bb6: { - _12 = SubUnchecked(copy _11, const 1_usize); - ((*_1).1: *const T) = copy _12 as *const T (Transmute); - goto -> bb7; - } - - bb7: { - StorageLive(_13); - _13 = copy _2 as *const T (Transmute); - _14 = &(*_13); - StorageDead(_13); - _0 = Option::<&T>::Some(copy _14); - goto -> bb8; - } - - bb8: { - StorageDead(_14); - StorageDead(_4); - StorageDead(_12); - StorageDead(_11); - StorageDead(_3); - StorageDead(_2); return; } } diff --git a/tests/mir-opt/pre-codegen/slice_iter.slice_iter_next.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.slice_iter_next.PreCodegen.after.panic-unwind.mir index c0ed0aea1e260..fdde07173437b 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.slice_iter_next.PreCodegen.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.slice_iter_next.PreCodegen.after.panic-unwind.mir @@ -3,134 +3,12 @@ fn slice_iter_next(_1: &mut std::slice::Iter<'_, T>) -> Option<&T> { debug it => _1; let mut _0: std::option::Option<&T>; - scope 1 (inlined as Iterator>::next) { - let _2: std::ptr::NonNull; - let _4: std::ptr::NonNull; - let mut _7: bool; - let mut _10: std::ptr::NonNull; - let mut _12: usize; - let _14: &T; - scope 2 { - let _3: *const T; - scope 3 { - let _11: usize; - scope 4 { - scope 7 (inlined #[track_caller] core::num::::unchecked_sub) { - scope 8 (inlined core::ub_checks::check_language_ub) { - scope 9 (inlined core::ub_checks::check_language_ub::runtime) { - } - } - } - scope 10 (inlined without_provenance_mut::) { - } - } - scope 5 (inlined std::ptr::const_ptr::::addr) { - scope 6 (inlined std::ptr::const_ptr::::cast::<()>) { - } - } - scope 11 (inlined as PartialEq>::eq) { - let mut _5: *mut T; - let mut _6: *mut T; - scope 12 (inlined NonNull::::as_ptr) { - } - scope 13 (inlined NonNull::::as_ptr) { - } - } - scope 14 (inlined NonNull::::add) { - let mut _8: *const T; - let mut _9: *const T; - scope 15 (inlined NonNull::::as_ptr) { - } - } - scope 16 (inlined NonNull::::as_ref::<'_>) { - let _13: *const T; - scope 17 (inlined NonNull::::as_ptr) { - } - scope 18 (inlined std::ptr::mut_ptr::::cast_const) { - } - } - } - } - } bb0: { - StorageLive(_2); - StorageLive(_3); - StorageLive(_11); - StorageLive(_12); - StorageLive(_4); - StorageLive(_14); - _2 = copy ((*_1).0: std::ptr::NonNull); - _3 = copy ((*_1).1: *const T); - switchInt(const ::IS_ZST) -> [0: bb1, otherwise: bb4]; + _0 = as Iterator>::next(move _1) -> [return: bb1, unwind continue]; } bb1: { - StorageLive(_7); - _4 = copy _3 as std::ptr::NonNull (Transmute); - StorageLive(_5); - _5 = copy _2 as *mut T (Transmute); - StorageLive(_6); - _6 = copy _4 as *mut T (Transmute); - _7 = Eq(move _5, move _6); - StorageDead(_6); - StorageDead(_5); - switchInt(move _7) -> [0: bb2, otherwise: bb3]; - } - - bb2: { - StorageDead(_7); - StorageLive(_10); - StorageLive(_9); - StorageLive(_8); - _8 = copy _2 as *const T (Transmute); - _9 = Offset(move _8, const 1_usize); - StorageDead(_8); - _10 = NonNull:: { pointer: move _9 }; - StorageDead(_9); - ((*_1).0: std::ptr::NonNull) = move _10; - StorageDead(_10); - goto -> bb7; - } - - bb3: { - _0 = const {transmute(0x0000000000000000): Option<&T>}; - StorageDead(_7); - goto -> bb8; - } - - bb4: { - _11 = copy _3 as usize (Transmute); - switchInt(copy _11) -> [0: bb5, otherwise: bb6]; - } - - bb5: { - _0 = const {transmute(0x0000000000000000): Option<&T>}; - goto -> bb8; - } - - bb6: { - _12 = SubUnchecked(copy _11, const 1_usize); - ((*_1).1: *const T) = copy _12 as *const T (Transmute); - goto -> bb7; - } - - bb7: { - StorageLive(_13); - _13 = copy _2 as *const T (Transmute); - _14 = &(*_13); - StorageDead(_13); - _0 = Option::<&T>::Some(copy _14); - goto -> bb8; - } - - bb8: { - StorageDead(_14); - StorageDead(_4); - StorageDead(_12); - StorageDead(_11); - StorageDead(_3); - StorageDead(_2); return; } }