about summary refs log tree commit diff
diff options
context:
space:
mode:
authorScott McMurray <scottmcm@users.noreply.github.com>2025-03-29 02:34:15 -0700
committerScott McMurray <scottmcm@users.noreply.github.com>2025-05-30 12:04:41 -0700
commit4668124cc709372c76a0a9a0b2108a3cadd98b78 (patch)
tree3ae187809faba3a393894b4b100c23026cbf3ba7
parentaa5832b142a2bfd322659d60f5d57e25d2a1bd5d (diff)
downloadrust-4668124cc709372c76a0a9a0b2108a3cadd98b78.tar.gz
rust-4668124cc709372c76a0a9a0b2108a3cadd98b78.zip
`slice.get(i)` should use a slice projection in MIR, like `slice[i]` does
-rw-r--r--compiler/rustc_hir_analysis/src/check/intrinsic.rs1
-rw-r--r--compiler/rustc_mir_transform/src/lower_intrinsics.rs46
-rw-r--r--compiler/rustc_span/src/symbol.rs1
-rw-r--r--library/core/src/intrinsics/bounds.rs39
-rw-r--r--library/core/src/intrinsics/mod.rs45
-rw-r--r--library/core/src/slice/index.rs56
-rw-r--r--tests/mir-opt/lower_intrinsics.rs21
-rw-r--r--tests/mir-opt/lower_intrinsics.slice_get.LowerIntrinsics.panic-abort.diff85
-rw-r--r--tests/mir-opt/lower_intrinsics.slice_get.LowerIntrinsics.panic-unwind.diff85
-rw-r--r--tests/mir-opt/pre-codegen/slice_index.slice_get_mut_usize.PreCodegen.after.panic-abort.mir22
-rw-r--r--tests/mir-opt/pre-codegen/slice_index.slice_get_mut_usize.PreCodegen.after.panic-unwind.mir22
-rw-r--r--tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-abort.mir12
-rw-r--r--tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-unwind.mir12
-rw-r--r--tests/mir-opt/pre-codegen/slice_index.slice_ptr_get_unchecked_range.PreCodegen.after.panic-abort.mir12
-rw-r--r--tests/mir-opt/pre-codegen/slice_index.slice_ptr_get_unchecked_range.PreCodegen.after.panic-unwind.mir12
15 files changed, 385 insertions, 86 deletions
diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs
index 54bb3ac4113..09610a2f3ec 100644
--- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs
+++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs
@@ -265,6 +265,7 @@ pub(crate) fn check_intrinsic_type(
                 vec![Ty::new_imm_ptr(tcx, param(0)), tcx.types.isize],
                 Ty::new_imm_ptr(tcx, param(0)),
             ),
+            sym::slice_get_unchecked => (3, 0, vec![param(1), tcx.types.usize], param(0)),
             sym::ptr_mask => (
                 1,
                 0,
diff --git a/compiler/rustc_mir_transform/src/lower_intrinsics.rs b/compiler/rustc_mir_transform/src/lower_intrinsics.rs
index 9c21bcfc0d2..52f4c39c09b 100644
--- a/compiler/rustc_mir_transform/src/lower_intrinsics.rs
+++ b/compiler/rustc_mir_transform/src/lower_intrinsics.rs
@@ -262,6 +262,52 @@ impl<'tcx> crate::MirPass<'tcx> for LowerIntrinsics {
                         });
                         terminator.kind = TerminatorKind::Goto { target };
                     }
+                    sym::slice_get_unchecked => {
+                        let target = target.unwrap();
+                        let Ok([ptrish, index]) = take_array(args) else {
+                            span_bug!(
+                                terminator.source_info.span,
+                                "Wrong number of arguments for {intrinsic:?}",
+                            );
+                        };
+
+                        let place = ptrish.node.place().unwrap();
+                        assert!(!place.is_indirect());
+                        let updated_place = place.project_deeper(
+                            &[
+                                ProjectionElem::Deref,
+                                ProjectionElem::Index(
+                                    index.node.place().unwrap().as_local().unwrap(),
+                                ),
+                            ],
+                            tcx,
+                        );
+
+                        let ret_ty = generic_args.type_at(0);
+                        let rvalue = match *ret_ty.kind() {
+                            ty::RawPtr(_, Mutability::Not) => {
+                                Rvalue::RawPtr(RawPtrKind::Const, updated_place)
+                            }
+                            ty::RawPtr(_, Mutability::Mut) => {
+                                Rvalue::RawPtr(RawPtrKind::Mut, updated_place)
+                            }
+                            ty::Ref(region, _, Mutability::Not) => {
+                                Rvalue::Ref(region, BorrowKind::Shared, updated_place)
+                            }
+                            ty::Ref(region, _, Mutability::Mut) => Rvalue::Ref(
+                                region,
+                                BorrowKind::Mut { kind: MutBorrowKind::Default },
+                                updated_place,
+                            ),
+                            _ => bug!("Unknown return type {ret_ty:?}"),
+                        };
+
+                        block.statements.push(Statement {
+                            source_info: terminator.source_info,
+                            kind: StatementKind::Assign(Box::new((*destination, rvalue))),
+                        });
+                        terminator.kind = TerminatorKind::Goto { target };
+                    }
                     sym::transmute | sym::transmute_unchecked => {
                         let dst_ty = destination.ty(local_decls, tcx).ty;
                         let Ok([arg]) = take_array(args) else {
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index ae94169b01d..970faf2997c 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -2000,6 +2000,7 @@ symbols! {
         slice,
         slice_from_raw_parts,
         slice_from_raw_parts_mut,
+        slice_get_unchecked,
         slice_into_vec,
         slice_iter,
         slice_len_fn,
diff --git a/library/core/src/intrinsics/bounds.rs b/library/core/src/intrinsics/bounds.rs
new file mode 100644
index 00000000000..046e191212c
--- /dev/null
+++ b/library/core/src/intrinsics/bounds.rs
@@ -0,0 +1,39 @@
+//! Various traits used to restrict intrinsics to not-completely-wrong types.
+
+/// Types with a built-in dereference operator in runtime MIR,
+/// aka references and raw pointers.
+///
+/// # Safety
+/// Must actually *be* such a type.
+pub unsafe trait BuiltinDeref: Sized {
+    type Pointee: ?Sized;
+}
+
+unsafe impl<T: ?Sized> BuiltinDeref for &mut T {
+    type Pointee = T;
+}
+unsafe impl<T: ?Sized> BuiltinDeref for &T {
+    type Pointee = T;
+}
+unsafe impl<T: ?Sized> BuiltinDeref for *mut T {
+    type Pointee = T;
+}
+unsafe impl<T: ?Sized> BuiltinDeref for *const T {
+    type Pointee = T;
+}
+
+pub trait ChangePointee<U: ?Sized>: BuiltinDeref {
+    type Output;
+}
+impl<'a, T: ?Sized + 'a, U: ?Sized + 'a> ChangePointee<U> for &'a mut T {
+    type Output = &'a mut U;
+}
+impl<'a, T: ?Sized + 'a, U: ?Sized + 'a> ChangePointee<U> for &'a T {
+    type Output = &'a U;
+}
+impl<T: ?Sized, U: ?Sized> ChangePointee<U> for *mut T {
+    type Output = *mut U;
+}
+impl<T: ?Sized, U: ?Sized> ChangePointee<U> for *const T {
+    type Output = *const U;
+}
diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs
index f89baef76f0..10c5ab10390 100644
--- a/library/core/src/intrinsics/mod.rs
+++ b/library/core/src/intrinsics/mod.rs
@@ -53,6 +53,7 @@
 use crate::marker::{ConstParamTy, DiscriminantKind, Tuple};
 use crate::ptr;
 
+mod bounds;
 pub mod fallback;
 pub mod mir;
 pub mod simd;
@@ -1730,7 +1731,7 @@ pub const fn needs_drop<T: ?Sized>() -> bool;
 #[rustc_intrinsic_const_stable_indirect]
 #[rustc_nounwind]
 #[rustc_intrinsic]
-pub const unsafe fn offset<Ptr, Delta>(dst: Ptr, offset: Delta) -> Ptr;
+pub const unsafe fn offset<Ptr: bounds::BuiltinDeref, Delta>(dst: Ptr, offset: Delta) -> Ptr;
 
 /// Calculates the offset from a pointer, potentially wrapping.
 ///
@@ -1751,6 +1752,33 @@ pub const unsafe fn offset<Ptr, Delta>(dst: Ptr, offset: Delta) -> Ptr;
 #[rustc_intrinsic]
 pub const unsafe fn arith_offset<T>(dst: *const T, offset: isize) -> *const T;
 
+/// Projects to the `index`-th element of `slice_ptr`, as the same kind of pointer
+/// as the slice was provided -- so `&mut [T] → &mut T`, `&[T] → &T`,
+/// `*mut [T] → *mut T`, or `*const [T] → *const T` -- without a bounds check.
+///
+/// This is exposed via `<usize as SliceIndex>::get(_unchecked)(_mut)`,
+/// and isn't intended to be used elsewhere.
+///
+/// Expands in MIR to `{&, &mut, &raw const, &raw mut} (*slice_ptr)[index]`,
+/// depending on the types involved, so no backend support is needed.
+///
+/// # Safety
+///
+/// - `index < PtrMetadata(slice_ptr)`, so the indexing is in-bounds for the slice
+/// - the resulting offsetting is in-bounds of the allocated object, which is
+///   always the case for references, but needs to be upheld manually for pointers
+#[cfg(not(bootstrap))]
+#[rustc_nounwind]
+#[rustc_intrinsic]
+pub const unsafe fn slice_get_unchecked<
+    ItemPtr: bounds::ChangePointee<[T], Pointee = T, Output = SlicePtr>,
+    SlicePtr,
+    T,
+>(
+    slice_ptr: SlicePtr,
+    index: usize,
+) -> ItemPtr;
+
 /// Masks out bits of the pointer according to a mask.
 ///
 /// Note that, unlike most intrinsics, this is safe to call;
@@ -3575,18 +3603,9 @@ pub const fn type_id<T: ?Sized + 'static>() -> u128;
 #[unstable(feature = "core_intrinsics", issue = "none")]
 #[rustc_intrinsic_const_stable_indirect]
 #[rustc_intrinsic]
-pub const fn aggregate_raw_ptr<P: AggregateRawPtr<D, Metadata = M>, D, M>(data: D, meta: M) -> P;
-
-#[unstable(feature = "core_intrinsics", issue = "none")]
-pub trait AggregateRawPtr<D> {
-    type Metadata: Copy;
-}
-impl<P: ?Sized, T: ptr::Thin> AggregateRawPtr<*const T> for *const P {
-    type Metadata = <P as ptr::Pointee>::Metadata;
-}
-impl<P: ?Sized, T: ptr::Thin> AggregateRawPtr<*mut T> for *mut P {
-    type Metadata = <P as ptr::Pointee>::Metadata;
-}
+pub const fn aggregate_raw_ptr<P: bounds::BuiltinDeref, D, M>(data: D, meta: M) -> P
+where
+    <P as bounds::BuiltinDeref>::Pointee: ptr::Pointee<Metadata = M>;
 
 /// Lowers in MIR to `Rvalue::UnaryOp` with `UnOp::PtrMetadata`.
 ///
diff --git a/library/core/src/slice/index.rs b/library/core/src/slice/index.rs
index b18d316c73a..69160a911b2 100644
--- a/library/core/src/slice/index.rs
+++ b/library/core/src/slice/index.rs
@@ -1,5 +1,7 @@
 //! Indexing implementations for `[T]`.
 
+#[cfg(not(bootstrap))]
+use crate::intrinsics::slice_get_unchecked;
 use crate::panic::const_panic;
 use crate::ub_checks::assert_unsafe_precondition;
 use crate::{ops, range};
@@ -83,6 +85,7 @@ const fn slice_end_index_overflow_fail() -> ! {
 // Both the safe and unsafe public methods share these helpers,
 // which use intrinsics directly to get *no* extra checks.
 
+#[cfg(bootstrap)]
 #[inline(always)]
 const unsafe fn get_noubcheck<T>(ptr: *const [T], index: usize) -> *const T {
     let ptr = ptr as *const T;
@@ -90,6 +93,7 @@ const unsafe fn get_noubcheck<T>(ptr: *const [T], index: usize) -> *const T {
     unsafe { crate::intrinsics::offset(ptr, index) }
 }
 
+#[cfg(bootstrap)]
 #[inline(always)]
 const unsafe fn get_mut_noubcheck<T>(ptr: *mut [T], index: usize) -> *mut T {
     let ptr = ptr as *mut T;
@@ -103,8 +107,9 @@ const unsafe fn get_offset_len_noubcheck<T>(
     offset: usize,
     len: usize,
 ) -> *const [T] {
+    let ptr = ptr as *const T;
     // SAFETY: The caller already checked these preconditions
-    let ptr = unsafe { get_noubcheck(ptr, offset) };
+    let ptr = unsafe { crate::intrinsics::offset(ptr, offset) };
     crate::intrinsics::aggregate_raw_ptr(ptr, len)
 }
 
@@ -114,8 +119,9 @@ const unsafe fn get_offset_len_mut_noubcheck<T>(
     offset: usize,
     len: usize,
 ) -> *mut [T] {
+    let ptr = ptr as *mut T;
     // SAFETY: The caller already checked these preconditions
-    let ptr = unsafe { get_mut_noubcheck(ptr, offset) };
+    let ptr = unsafe { crate::intrinsics::offset(ptr, offset) };
     crate::intrinsics::aggregate_raw_ptr(ptr, len)
 }
 
@@ -224,15 +230,35 @@ unsafe impl<T> SliceIndex<[T]> for usize {
 
     #[inline]
     fn get(self, slice: &[T]) -> Option<&T> {
-        // SAFETY: `self` is checked to be in bounds.
-        if self < slice.len() { unsafe { Some(&*get_noubcheck(slice, self)) } } else { None }
+        if self < slice.len() {
+            #[cfg(bootstrap)]
+            // SAFETY: `self` is checked to be in bounds.
+            unsafe {
+                Some(&*get_noubcheck(slice, self))
+            }
+            #[cfg(not(bootstrap))]
+            // SAFETY: `self` is checked to be in bounds.
+            unsafe {
+                Some(slice_get_unchecked(slice, self))
+            }
+        } else {
+            None
+        }
     }
 
     #[inline]
     fn get_mut(self, slice: &mut [T]) -> Option<&mut T> {
         if self < slice.len() {
+            #[cfg(bootstrap)]
+            // SAFETY: `self` is checked to be in bounds.
+            unsafe {
+                Some(&mut *get_mut_noubcheck(slice, self))
+            }
+            #[cfg(not(bootstrap))]
             // SAFETY: `self` is checked to be in bounds.
-            unsafe { Some(&mut *get_mut_noubcheck(slice, self)) }
+            unsafe {
+                Some(slice_get_unchecked(slice, self))
+            }
         } else {
             None
         }
@@ -254,7 +280,14 @@ unsafe impl<T> SliceIndex<[T]> for usize {
             // Use intrinsics::assume instead of hint::assert_unchecked so that we don't check the
             // precondition of this function twice.
             crate::intrinsics::assume(self < slice.len());
-            get_noubcheck(slice, self)
+            #[cfg(bootstrap)]
+            {
+                get_noubcheck(slice, self)
+            }
+            #[cfg(not(bootstrap))]
+            {
+                slice_get_unchecked(slice, self)
+            }
         }
     }
 
@@ -267,7 +300,16 @@ unsafe impl<T> SliceIndex<[T]> for usize {
             (this: usize = self, len: usize = slice.len()) => this < len
         );
         // SAFETY: see comments for `get_unchecked` above.
-        unsafe { get_mut_noubcheck(slice, self) }
+        unsafe {
+            #[cfg(bootstrap)]
+            {
+                get_mut_noubcheck(slice, self)
+            }
+            #[cfg(not(bootstrap))]
+            {
+                slice_get_unchecked(slice, self)
+            }
+        }
     }
 
     #[inline]
diff --git a/tests/mir-opt/lower_intrinsics.rs b/tests/mir-opt/lower_intrinsics.rs
index 4e000b05a4b..1e4f2024194 100644
--- a/tests/mir-opt/lower_intrinsics.rs
+++ b/tests/mir-opt/lower_intrinsics.rs
@@ -263,3 +263,24 @@ pub fn get_metadata(a: *const i32, b: *const [u8], c: *const dyn std::fmt::Debug
     let _usize = ptr_metadata(b);
     let _vtable = ptr_metadata(c);
 }
+
+// EMIT_MIR lower_intrinsics.slice_get.LowerIntrinsics.diff
+pub unsafe fn slice_get<'a, 'b>(
+    r: &'a [i8],
+    rm: &'b mut [i16],
+    p: *const [i32],
+    pm: *mut [i64],
+    i: usize,
+) -> (&'a i8, &'b mut i16, *const i32, *mut i64) {
+    use std::intrinsics::slice_get_unchecked;
+    // CHECK: = &(*_{{[0-9]+}})[_{{[0-9]+}}]
+    // CHECK: = &mut (*_{{[0-9]+}})[_{{[0-9]+}}]
+    // CHECK: = &raw const (*_{{[0-9]+}})[_{{[0-9]+}}]
+    // CHECK: = &raw mut (*_{{[0-9]+}})[_{{[0-9]+}}]
+    (
+        slice_get_unchecked(r, i),
+        slice_get_unchecked(rm, i),
+        slice_get_unchecked(p, i),
+        slice_get_unchecked(pm, i),
+    )
+}
diff --git a/tests/mir-opt/lower_intrinsics.slice_get.LowerIntrinsics.panic-abort.diff b/tests/mir-opt/lower_intrinsics.slice_get.LowerIntrinsics.panic-abort.diff
new file mode 100644
index 00000000000..d18bdc43168
--- /dev/null
+++ b/tests/mir-opt/lower_intrinsics.slice_get.LowerIntrinsics.panic-abort.diff
@@ -0,0 +1,85 @@
+- // MIR for `slice_get` before LowerIntrinsics
++ // MIR for `slice_get` after LowerIntrinsics
+  
+  fn slice_get(_1: &[i8], _2: &mut [i16], _3: *const [i32], _4: *mut [i64], _5: usize) -> (&i8, &mut i16, *const i32, *mut i64) {
+      debug r => _1;
+      debug rm => _2;
+      debug p => _3;
+      debug pm => _4;
+      debug i => _5;
+      let mut _0: (&i8, &mut i16, *const i32, *mut i64);
+      let mut _6: &i8;
+      let mut _7: &[i8];
+      let mut _8: usize;
+      let mut _9: &mut i16;
+      let mut _10: &mut [i16];
+      let mut _11: usize;
+      let mut _12: *const i32;
+      let mut _13: *const [i32];
+      let mut _14: usize;
+      let mut _15: *mut i64;
+      let mut _16: *mut [i64];
+      let mut _17: usize;
+  
+      bb0: {
+          StorageLive(_6);
+          StorageLive(_7);
+          _7 = copy _1;
+          StorageLive(_8);
+          _8 = copy _5;
+-         _6 = slice_get_unchecked::<&i8, &[i8], i8>(move _7, move _8) -> [return: bb1, unwind unreachable];
++         _6 = &(*_7)[_8];
++         goto -> bb1;
+      }
+  
+      bb1: {
+          StorageDead(_8);
+          StorageDead(_7);
+          StorageLive(_9);
+          StorageLive(_10);
+          _10 = move _2;
+          StorageLive(_11);
+          _11 = copy _5;
+-         _9 = slice_get_unchecked::<&mut i16, &mut [i16], i16>(move _10, move _11) -> [return: bb2, unwind unreachable];
++         _9 = &mut (*_10)[_11];
++         goto -> bb2;
+      }
+  
+      bb2: {
+          StorageDead(_11);
+          StorageDead(_10);
+          StorageLive(_12);
+          StorageLive(_13);
+          _13 = copy _3;
+          StorageLive(_14);
+          _14 = copy _5;
+-         _12 = slice_get_unchecked::<*const i32, *const [i32], i32>(move _13, move _14) -> [return: bb3, unwind unreachable];
++         _12 = &raw const (*_13)[_14];
++         goto -> bb3;
+      }
+  
+      bb3: {
+          StorageDead(_14);
+          StorageDead(_13);
+          StorageLive(_15);
+          StorageLive(_16);
+          _16 = copy _4;
+          StorageLive(_17);
+          _17 = copy _5;
+-         _15 = slice_get_unchecked::<*mut i64, *mut [i64], i64>(move _16, move _17) -> [return: bb4, unwind unreachable];
++         _15 = &raw mut (*_16)[_17];
++         goto -> bb4;
+      }
+  
+      bb4: {
+          StorageDead(_17);
+          StorageDead(_16);
+          _0 = (move _6, move _9, move _12, move _15);
+          StorageDead(_15);
+          StorageDead(_12);
+          StorageDead(_9);
+          StorageDead(_6);
+          return;
+      }
+  }
+  
diff --git a/tests/mir-opt/lower_intrinsics.slice_get.LowerIntrinsics.panic-unwind.diff b/tests/mir-opt/lower_intrinsics.slice_get.LowerIntrinsics.panic-unwind.diff
new file mode 100644
index 00000000000..d18bdc43168
--- /dev/null
+++ b/tests/mir-opt/lower_intrinsics.slice_get.LowerIntrinsics.panic-unwind.diff
@@ -0,0 +1,85 @@
+- // MIR for `slice_get` before LowerIntrinsics
++ // MIR for `slice_get` after LowerIntrinsics
+  
+  fn slice_get(_1: &[i8], _2: &mut [i16], _3: *const [i32], _4: *mut [i64], _5: usize) -> (&i8, &mut i16, *const i32, *mut i64) {
+      debug r => _1;
+      debug rm => _2;
+      debug p => _3;
+      debug pm => _4;
+      debug i => _5;
+      let mut _0: (&i8, &mut i16, *const i32, *mut i64);
+      let mut _6: &i8;
+      let mut _7: &[i8];
+      let mut _8: usize;
+      let mut _9: &mut i16;
+      let mut _10: &mut [i16];
+      let mut _11: usize;
+      let mut _12: *const i32;
+      let mut _13: *const [i32];
+      let mut _14: usize;
+      let mut _15: *mut i64;
+      let mut _16: *mut [i64];
+      let mut _17: usize;
+  
+      bb0: {
+          StorageLive(_6);
+          StorageLive(_7);
+          _7 = copy _1;
+          StorageLive(_8);
+          _8 = copy _5;
+-         _6 = slice_get_unchecked::<&i8, &[i8], i8>(move _7, move _8) -> [return: bb1, unwind unreachable];
++         _6 = &(*_7)[_8];
++         goto -> bb1;
+      }
+  
+      bb1: {
+          StorageDead(_8);
+          StorageDead(_7);
+          StorageLive(_9);
+          StorageLive(_10);
+          _10 = move _2;
+          StorageLive(_11);
+          _11 = copy _5;
+-         _9 = slice_get_unchecked::<&mut i16, &mut [i16], i16>(move _10, move _11) -> [return: bb2, unwind unreachable];
++         _9 = &mut (*_10)[_11];
++         goto -> bb2;
+      }
+  
+      bb2: {
+          StorageDead(_11);
+          StorageDead(_10);
+          StorageLive(_12);
+          StorageLive(_13);
+          _13 = copy _3;
+          StorageLive(_14);
+          _14 = copy _5;
+-         _12 = slice_get_unchecked::<*const i32, *const [i32], i32>(move _13, move _14) -> [return: bb3, unwind unreachable];
++         _12 = &raw const (*_13)[_14];
++         goto -> bb3;
+      }
+  
+      bb3: {
+          StorageDead(_14);
+          StorageDead(_13);
+          StorageLive(_15);
+          StorageLive(_16);
+          _16 = copy _4;
+          StorageLive(_17);
+          _17 = copy _5;
+-         _15 = slice_get_unchecked::<*mut i64, *mut [i64], i64>(move _16, move _17) -> [return: bb4, unwind unreachable];
++         _15 = &raw mut (*_16)[_17];
++         goto -> bb4;
+      }
+  
+      bb4: {
+          StorageDead(_17);
+          StorageDead(_16);
+          _0 = (move _6, move _9, move _12, move _15);
+          StorageDead(_15);
+          StorageDead(_12);
+          StorageDead(_9);
+          StorageDead(_6);
+          return;
+      }
+  }
+  
diff --git a/tests/mir-opt/pre-codegen/slice_index.slice_get_mut_usize.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_index.slice_get_mut_usize.PreCodegen.after.panic-abort.mir
index ec67193bc79..d1b1e3d7dd7 100644
--- a/tests/mir-opt/pre-codegen/slice_index.slice_get_mut_usize.PreCodegen.after.panic-abort.mir
+++ b/tests/mir-opt/pre-codegen/slice_index.slice_get_mut_usize.PreCodegen.after.panic-abort.mir
@@ -8,19 +8,11 @@ fn slice_get_mut_usize(_1: &mut [u32], _2: usize) -> Option<&mut u32> {
         scope 2 (inlined <usize as SliceIndex<[u32]>>::get_mut) {
             let mut _3: usize;
             let mut _4: bool;
-            let mut _5: *mut [u32];
-            let mut _7: *mut u32;
-            let mut _8: &mut u32;
-            scope 3 (inlined core::slice::index::get_mut_noubcheck::<u32>) {
-                let _6: *mut u32;
-                scope 4 {
-                }
-            }
+            let mut _5: &mut u32;
         }
     }
 
     bb0: {
-        StorageLive(_8);
         StorageLive(_4);
         StorageLive(_3);
         _3 = PtrMetadata(copy _1);
@@ -36,23 +28,15 @@ fn slice_get_mut_usize(_1: &mut [u32], _2: usize) -> Option<&mut u32> {
 
     bb2: {
         StorageDead(_3);
-        StorageLive(_7);
         StorageLive(_5);
-        _5 = &raw mut (*_1);
-        StorageLive(_6);
-        _6 = copy _5 as *mut u32 (PtrToPtr);
-        _7 = Offset(copy _6, copy _2);
-        StorageDead(_6);
+        _5 = &mut (*_1)[_2];
+        _0 = Option::<&mut u32>::Some(move _5);
         StorageDead(_5);
-        _8 = &mut (*_7);
-        _0 = Option::<&mut u32>::Some(copy _8);
-        StorageDead(_7);
         goto -> bb3;
     }
 
     bb3: {
         StorageDead(_4);
-        StorageDead(_8);
         return;
     }
 }
diff --git a/tests/mir-opt/pre-codegen/slice_index.slice_get_mut_usize.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_index.slice_get_mut_usize.PreCodegen.after.panic-unwind.mir
index ec67193bc79..d1b1e3d7dd7 100644
--- a/tests/mir-opt/pre-codegen/slice_index.slice_get_mut_usize.PreCodegen.after.panic-unwind.mir
+++ b/tests/mir-opt/pre-codegen/slice_index.slice_get_mut_usize.PreCodegen.after.panic-unwind.mir
@@ -8,19 +8,11 @@ fn slice_get_mut_usize(_1: &mut [u32], _2: usize) -> Option<&mut u32> {
         scope 2 (inlined <usize as SliceIndex<[u32]>>::get_mut) {
             let mut _3: usize;
             let mut _4: bool;
-            let mut _5: *mut [u32];
-            let mut _7: *mut u32;
-            let mut _8: &mut u32;
-            scope 3 (inlined core::slice::index::get_mut_noubcheck::<u32>) {
-                let _6: *mut u32;
-                scope 4 {
-                }
-            }
+            let mut _5: &mut u32;
         }
     }
 
     bb0: {
-        StorageLive(_8);
         StorageLive(_4);
         StorageLive(_3);
         _3 = PtrMetadata(copy _1);
@@ -36,23 +28,15 @@ fn slice_get_mut_usize(_1: &mut [u32], _2: usize) -> Option<&mut u32> {
 
     bb2: {
         StorageDead(_3);
-        StorageLive(_7);
         StorageLive(_5);
-        _5 = &raw mut (*_1);
-        StorageLive(_6);
-        _6 = copy _5 as *mut u32 (PtrToPtr);
-        _7 = Offset(copy _6, copy _2);
-        StorageDead(_6);
+        _5 = &mut (*_1)[_2];
+        _0 = Option::<&mut u32>::Some(move _5);
         StorageDead(_5);
-        _8 = &mut (*_7);
-        _0 = Option::<&mut u32>::Some(copy _8);
-        StorageDead(_7);
         goto -> bb3;
     }
 
     bb3: {
         StorageDead(_4);
-        StorageDead(_8);
         return;
     }
 }
diff --git a/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-abort.mir
index 597f02e837a..6fb1637a6e0 100644
--- a/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-abort.mir
+++ b/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-abort.mir
@@ -15,12 +15,10 @@ fn slice_get_unchecked_mut_range(_1: &mut [u32], _2: std::ops::Range<usize>) ->
             let _8: usize;
             scope 3 {
                 scope 6 (inlined core::slice::index::get_offset_len_mut_noubcheck::<u32>) {
-                    let _10: *mut u32;
+                    let _9: *mut u32;
                     scope 7 {
-                    }
-                    scope 8 (inlined core::slice::index::get_mut_noubcheck::<u32>) {
-                        let _9: *mut u32;
-                        scope 9 {
+                        let _10: *mut u32;
+                        scope 8 {
                         }
                     }
                 }
@@ -47,13 +45,13 @@ fn slice_get_unchecked_mut_range(_1: &mut [u32], _2: std::ops::Range<usize>) ->
     bb1: {
         StorageDead(_6);
         _8 = SubUnchecked(copy _4, copy _3);
-        StorageLive(_10);
         StorageLive(_9);
+        StorageLive(_10);
         _9 = copy _5 as *mut u32 (PtrToPtr);
         _10 = Offset(copy _9, copy _3);
-        StorageDead(_9);
         _11 = *mut [u32] from (copy _10, copy _8);
         StorageDead(_10);
+        StorageDead(_9);
         StorageDead(_8);
         StorageDead(_5);
         _0 = &mut (*_11);
diff --git a/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-unwind.mir
index 597f02e837a..6fb1637a6e0 100644
--- a/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-unwind.mir
+++ b/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.panic-unwind.mir
@@ -15,12 +15,10 @@ fn slice_get_unchecked_mut_range(_1: &mut [u32], _2: std::ops::Range<usize>) ->
             let _8: usize;
             scope 3 {
                 scope 6 (inlined core::slice::index::get_offset_len_mut_noubcheck::<u32>) {
-                    let _10: *mut u32;
+                    let _9: *mut u32;
                     scope 7 {
-                    }
-                    scope 8 (inlined core::slice::index::get_mut_noubcheck::<u32>) {
-                        let _9: *mut u32;
-                        scope 9 {
+                        let _10: *mut u32;
+                        scope 8 {
                         }
                     }
                 }
@@ -47,13 +45,13 @@ fn slice_get_unchecked_mut_range(_1: &mut [u32], _2: std::ops::Range<usize>) ->
     bb1: {
         StorageDead(_6);
         _8 = SubUnchecked(copy _4, copy _3);
-        StorageLive(_10);
         StorageLive(_9);
+        StorageLive(_10);
         _9 = copy _5 as *mut u32 (PtrToPtr);
         _10 = Offset(copy _9, copy _3);
-        StorageDead(_9);
         _11 = *mut [u32] from (copy _10, copy _8);
         StorageDead(_10);
+        StorageDead(_9);
         StorageDead(_8);
         StorageDead(_5);
         _0 = &mut (*_11);
diff --git a/tests/mir-opt/pre-codegen/slice_index.slice_ptr_get_unchecked_range.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_index.slice_ptr_get_unchecked_range.PreCodegen.after.panic-abort.mir
index e34723898e4..ad1ca5dff43 100644
--- a/tests/mir-opt/pre-codegen/slice_index.slice_ptr_get_unchecked_range.PreCodegen.after.panic-abort.mir
+++ b/tests/mir-opt/pre-codegen/slice_index.slice_ptr_get_unchecked_range.PreCodegen.after.panic-abort.mir
@@ -13,12 +13,10 @@ fn slice_ptr_get_unchecked_range(_1: *const [u32], _2: std::ops::Range<usize>) -
             let _7: usize;
             scope 3 {
                 scope 6 (inlined core::slice::index::get_offset_len_noubcheck::<u32>) {
-                    let _9: *const u32;
+                    let _8: *const u32;
                     scope 7 {
-                    }
-                    scope 8 (inlined core::slice::index::get_noubcheck::<u32>) {
-                        let _8: *const u32;
-                        scope 9 {
+                        let _9: *const u32;
+                        scope 8 {
                         }
                     }
                 }
@@ -42,13 +40,13 @@ fn slice_ptr_get_unchecked_range(_1: *const [u32], _2: std::ops::Range<usize>) -
     bb1: {
         StorageDead(_5);
         _7 = SubUnchecked(copy _4, copy _3);
-        StorageLive(_9);
         StorageLive(_8);
+        StorageLive(_9);
         _8 = copy _1 as *const u32 (PtrToPtr);
         _9 = Offset(copy _8, copy _3);
-        StorageDead(_8);
         _0 = *const [u32] from (copy _9, copy _7);
         StorageDead(_9);
+        StorageDead(_8);
         StorageDead(_7);
         return;
     }
diff --git a/tests/mir-opt/pre-codegen/slice_index.slice_ptr_get_unchecked_range.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_index.slice_ptr_get_unchecked_range.PreCodegen.after.panic-unwind.mir
index e34723898e4..ad1ca5dff43 100644
--- a/tests/mir-opt/pre-codegen/slice_index.slice_ptr_get_unchecked_range.PreCodegen.after.panic-unwind.mir
+++ b/tests/mir-opt/pre-codegen/slice_index.slice_ptr_get_unchecked_range.PreCodegen.after.panic-unwind.mir
@@ -13,12 +13,10 @@ fn slice_ptr_get_unchecked_range(_1: *const [u32], _2: std::ops::Range<usize>) -
             let _7: usize;
             scope 3 {
                 scope 6 (inlined core::slice::index::get_offset_len_noubcheck::<u32>) {
-                    let _9: *const u32;
+                    let _8: *const u32;
                     scope 7 {
-                    }
-                    scope 8 (inlined core::slice::index::get_noubcheck::<u32>) {
-                        let _8: *const u32;
-                        scope 9 {
+                        let _9: *const u32;
+                        scope 8 {
                         }
                     }
                 }
@@ -42,13 +40,13 @@ fn slice_ptr_get_unchecked_range(_1: *const [u32], _2: std::ops::Range<usize>) -
     bb1: {
         StorageDead(_5);
         _7 = SubUnchecked(copy _4, copy _3);
-        StorageLive(_9);
         StorageLive(_8);
+        StorageLive(_9);
         _8 = copy _1 as *const u32 (PtrToPtr);
         _9 = Offset(copy _8, copy _3);
-        StorageDead(_8);
         _0 = *const [u32] from (copy _9, copy _7);
         StorageDead(_9);
+        StorageDead(_8);
         StorageDead(_7);
         return;
     }