about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2024-02-09 13:33:38 +0000
committerbors <bors@rust-lang.org>2024-02-09 13:33:38 +0000
commit8fb67fb37fed736cb04f307473af7c863be224fb (patch)
tree8e9db92933be14fdb244d7864818505f8bdafff5
parent972452c4473b2d8f6f6415614f915296bfc34f12 (diff)
parentdbf817bae1f25f0fa2fbb1e40ab74afc892d9a60 (diff)
downloadrust-8fb67fb37fed736cb04f307473af7c863be224fb.tar.gz
rust-8fb67fb37fed736cb04f307473af7c863be224fb.zip
Auto merge of #120594 - saethlin:delayed-debug-asserts, r=oli-obk
Toggle assert_unsafe_precondition in codegen instead of expansion

The goal of this PR is to make some of the unsafe precondition checks in the standard library available in debug builds. Some UI tests are included to verify that it does that.

The diff is large, but most of it is blessing mir-opt tests and I've also split up this PR so it can be reviewed commit-by-commit.

This PR:
1. Adds a new intrinsic, `debug_assertions` which is lowered to a new MIR NullOp, and only to a constant after monomorphization
2. Rewrites `assume_unsafe_precondition` to check the new intrinsic, and be monomorphic.
3. Skips codegen of the `assume` intrinsic in unoptimized builds, because that was silly before but with these checks it's *very* silly
4. The checks with the most overhead are `ptr::read`/`ptr::write` and `NonNull::new_unchecked`. I've simply added `#[cfg(debug_assertions)]` to the checks for `ptr::read`/`ptr::write` because I was unable to come up with any (good) ideas for decreasing their impact. But for `NonNull::new_unchecked` I found that the majority of callers can use a different function, often a safe one.

Yes, this PR slows down the compile time of some programs. But in our benchmark suite it's never more than 1% icount, and the average icount change in debug-full programs is 0.22%. I think that is acceptable for such an improvement in developer experience.

https://github.com/rust-lang/rust/issues/120539#issuecomment-1922687101
-rw-r--r--compiler/rustc_borrowck/src/type_check/mod.rs1
-rw-r--r--compiler/rustc_codegen_cranelift/src/base.rs9
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/rvalue.rs14
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/statement.rs7
-rw-r--r--compiler/rustc_const_eval/src/interpret/step.rs20
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/check.rs5
-rw-r--r--compiler/rustc_const_eval/src/transform/validate.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/check/intrinsic.rs5
-rw-r--r--compiler/rustc_middle/src/mir/pretty.rs1
-rw-r--r--compiler/rustc_middle/src/mir/syntax.rs2
-rw-r--r--compiler/rustc_middle/src/mir/tcx.rs1
-rw-r--r--compiler/rustc_mir_dataflow/src/move_paths/builder.rs5
-rw-r--r--compiler/rustc_mir_transform/src/const_prop_lint.rs1
-rw-r--r--compiler/rustc_mir_transform/src/gvn.rs1
-rw-r--r--compiler/rustc_mir_transform/src/instsimplify.rs25
-rw-r--r--compiler/rustc_mir_transform/src/lower_intrinsics.rs11
-rw-r--r--compiler/rustc_mir_transform/src/promote_consts.rs1
-rw-r--r--compiler/rustc_smir/src/rustc_smir/convert/mir.rs1
-rw-r--r--compiler/stable_mir/src/mir/body.rs3
-rw-r--r--library/alloc/src/raw_vec.rs13
-rw-r--r--library/alloc/src/vec/into_iter.rs2
-rw-r--r--library/alloc/src/vec/mod.rs6
-rw-r--r--library/core/src/char/convert.rs2
-rw-r--r--library/core/src/hint.rs2
-rw-r--r--library/core/src/intrinsics.rs134
-rw-r--r--library/core/src/option.rs1
-rw-r--r--library/core/src/ptr/const_ptr.rs8
-rw-r--r--library/core/src/ptr/mod.rs45
-rw-r--r--library/core/src/ptr/non_null.rs17
-rw-r--r--library/core/src/ptr/unique.rs9
-rw-r--r--library/core/src/slice/iter.rs15
-rw-r--r--library/core/src/slice/raw.rs21
-rw-r--r--src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs2
-rw-r--r--src/tools/tidy/src/ui_tests.rs2
-rw-r--r--tests/assembly/is_aligned.rs4
-rw-r--r--tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-abort.diff60
-rw-r--r--tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-unwind.diff68
-rw-r--r--tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-abort.diff60
-rw-r--r--tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-unwind.diff68
-rw-r--r--tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-abort.diff63
-rw-r--r--tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-unwind.diff71
-rw-r--r--tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-abort.diff63
-rw-r--r--tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-unwind.diff71
-rw-r--r--tests/mir-opt/inline/unwrap_unchecked.rs2
-rw-r--r--tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-abort.diff39
-rw-r--r--tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-unwind.diff51
-rw-r--r--tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-abort.mir34
-rw-r--r--tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-unwind.mir34
-rw-r--r--tests/mir-opt/pre-codegen/duplicate_switch_targets.ub_if_b.PreCodegen.after.mir22
-rw-r--r--tests/mir-opt/pre-codegen/mem_replace.manual_replace.PreCodegen.after.panic-abort.mir (renamed from tests/mir-opt/pre-codegen/mem_replace.manual_replace.PreCodegen.after.mir)0
-rw-r--r--tests/mir-opt/pre-codegen/mem_replace.manual_replace.PreCodegen.after.panic-unwind.mir16
-rw-r--r--tests/mir-opt/pre-codegen/mem_replace.mem_replace.PreCodegen.after.mir66
-rw-r--r--tests/mir-opt/pre-codegen/mem_replace.mem_replace.PreCodegen.after.panic-abort.mir33
-rw-r--r--tests/mir-opt/pre-codegen/mem_replace.mem_replace.PreCodegen.after.panic-unwind.mir33
-rw-r--r--tests/mir-opt/pre-codegen/mem_replace.rs3
-rw-r--r--tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir240
-rw-r--r--tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir240
-rw-r--r--tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir216
-rw-r--r--tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir216
-rw-r--r--tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir244
-rw-r--r--tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir244
-rw-r--r--tests/ui/hygiene/panic-location.run.stderr2
-rw-r--r--tests/ui/precondition-checks/misaligned-slice.rs11
-rw-r--r--tests/ui/precondition-checks/null-slice.rs11
-rw-r--r--tests/ui/precondition-checks/out-of-bounds-get-unchecked.rs12
65 files changed, 1439 insertions, 1252 deletions
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index f4ab864a5c3..aab60bfe2ae 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -1983,6 +1983,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                     ConstraintCategory::SizedBound,
                 );
             }
+            &Rvalue::NullaryOp(NullOp::DebugAssertions, _) => {}
 
             Rvalue::ShallowInitBox(operand, ty) => {
                 self.check_operand(operand, location);
diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs
index 0afd6d0e670..a7e76fbc128 100644
--- a/compiler/rustc_codegen_cranelift/src/base.rs
+++ b/compiler/rustc_codegen_cranelift/src/base.rs
@@ -767,6 +767,15 @@ fn codegen_stmt<'tcx>(
                         NullOp::OffsetOf(fields) => {
                             layout.offset_of_subfield(fx, fields.iter()).bytes()
                         }
+                        NullOp::DebugAssertions => {
+                            let val = fx.tcx.sess.opts.debug_assertions;
+                            let val = CValue::by_val(
+                                fx.bcx.ins().iconst(types::I8, i64::try_from(val).unwrap()),
+                                fx.layout_of(fx.tcx.types.bool),
+                            );
+                            lval.write_cvalue(fx, val);
+                            return;
+                        }
                     };
                     let val = CValue::by_val(
                         fx.bcx.ins().iconst(fx.pointer_type, i64::try_from(val).unwrap()),
diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
index 266505d3f26..5c6060a7159 100644
--- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
@@ -672,17 +672,23 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                 let val = match null_op {
                     mir::NullOp::SizeOf => {
                         assert!(bx.cx().type_is_sized(ty));
-                        layout.size.bytes()
+                        let val = layout.size.bytes();
+                        bx.cx().const_usize(val)
                     }
                     mir::NullOp::AlignOf => {
                         assert!(bx.cx().type_is_sized(ty));
-                        layout.align.abi.bytes()
+                        let val = layout.align.abi.bytes();
+                        bx.cx().const_usize(val)
                     }
                     mir::NullOp::OffsetOf(fields) => {
-                        layout.offset_of_subfield(bx.cx(), fields.iter()).bytes()
+                        let val = layout.offset_of_subfield(bx.cx(), fields.iter()).bytes();
+                        bx.cx().const_usize(val)
+                    }
+                    mir::NullOp::DebugAssertions => {
+                        let val = bx.tcx().sess.opts.debug_assertions;
+                        bx.cx().const_bool(val)
                     }
                 };
-                let val = bx.cx().const_usize(val);
                 let tcx = self.cx.tcx();
                 OperandRef {
                     val: OperandValue::Immediate(val),
diff --git a/compiler/rustc_codegen_ssa/src/mir/statement.rs b/compiler/rustc_codegen_ssa/src/mir/statement.rs
index a158fc6e260..ac7dfbb261d 100644
--- a/compiler/rustc_codegen_ssa/src/mir/statement.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/statement.rs
@@ -1,5 +1,6 @@
 use rustc_middle::mir;
 use rustc_middle::mir::NonDivergingIntrinsic;
+use rustc_session::config::OptLevel;
 
 use super::FunctionCx;
 use super::LocalRef;
@@ -67,8 +68,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                 self.codegen_coverage(bx, coverage, statement.source_info.scope);
             }
             mir::StatementKind::Intrinsic(box NonDivergingIntrinsic::Assume(ref op)) => {
-                let op_val = self.codegen_operand(bx, op);
-                bx.assume(op_val.immediate());
+                if !matches!(bx.tcx().sess.opts.optimize, OptLevel::No | OptLevel::Less) {
+                    let op_val = self.codegen_operand(bx, op);
+                    bx.assume(op_val.immediate());
+                }
             }
             mir::StatementKind::Intrinsic(box NonDivergingIntrinsic::CopyNonOverlapping(
                 mir::CopyNonOverlapping { ref count, ref src, ref dst },
diff --git a/compiler/rustc_const_eval/src/interpret/step.rs b/compiler/rustc_const_eval/src/interpret/step.rs
index d48329b6c69..f0f1008aba8 100644
--- a/compiler/rustc_const_eval/src/interpret/step.rs
+++ b/compiler/rustc_const_eval/src/interpret/step.rs
@@ -246,13 +246,25 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                     );
                 }
                 let val = match null_op {
-                    mir::NullOp::SizeOf => layout.size.bytes(),
-                    mir::NullOp::AlignOf => layout.align.abi.bytes(),
+                    mir::NullOp::SizeOf => {
+                        let val = layout.size.bytes();
+                        Scalar::from_target_usize(val, self)
+                    }
+                    mir::NullOp::AlignOf => {
+                        let val = layout.align.abi.bytes();
+                        Scalar::from_target_usize(val, self)
+                    }
                     mir::NullOp::OffsetOf(fields) => {
-                        layout.offset_of_subfield(self, fields.iter()).bytes()
+                        let val = layout.offset_of_subfield(self, fields.iter()).bytes();
+                        Scalar::from_target_usize(val, self)
+                    }
+                    mir::NullOp::DebugAssertions => {
+                        // The checks hidden behind this are always better done by the interpreter
+                        // itself, because it knows the runtime state better.
+                        Scalar::from_bool(false)
                     }
                 };
-                self.write_scalar(Scalar::from_target_usize(val, self), &dest)?;
+                self.write_scalar(val, &dest)?;
             }
 
             ShallowInitBox(ref operand, _) => {
diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs
index 5ff81615552..ee3f349c6b8 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs
@@ -544,7 +544,10 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
 
             Rvalue::Cast(_, _, _) => {}
 
-            Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf | NullOp::OffsetOf(_), _) => {}
+            Rvalue::NullaryOp(
+                NullOp::SizeOf | NullOp::AlignOf | NullOp::OffsetOf(_) | NullOp::DebugAssertions,
+                _,
+            ) => {}
             Rvalue::ShallowInitBox(_, _) => {}
 
             Rvalue::UnaryOp(_, operand) => {
diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs
index c4542aaa7b2..db4d2be5470 100644
--- a/compiler/rustc_const_eval/src/transform/validate.rs
+++ b/compiler/rustc_const_eval/src/transform/validate.rs
@@ -1139,7 +1139,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
             Rvalue::Repeat(_, _)
             | Rvalue::ThreadLocalRef(_)
             | Rvalue::AddressOf(_, _)
-            | Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf, _)
+            | Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf | NullOp::DebugAssertions, _)
             | Rvalue::Discriminant(_) => {}
         }
         self.super_rvalue(rvalue, location);
diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs
index 2d0d6611444..96b0cffc8a3 100644
--- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs
+++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs
@@ -112,7 +112,8 @@ pub fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: DefId) -> hir
         | sym::forget
         | sym::black_box
         | sym::variant_count
-        | sym::ptr_mask => hir::Unsafety::Normal,
+        | sym::ptr_mask
+        | sym::debug_assertions => hir::Unsafety::Normal,
         _ => hir::Unsafety::Unsafe,
     };
 
@@ -461,6 +462,8 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
                 (0, vec![Ty::new_imm_ptr(tcx, Ty::new_unit(tcx))], tcx.types.usize)
             }
 
+            sym::debug_assertions => (0, Vec::new(), tcx.types.bool),
+
             other => {
                 tcx.dcx().emit_err(UnrecognizedIntrinsicFunction { span: it.span, name: other });
                 return;
diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs
index 6f587fdd53c..b601b465668 100644
--- a/compiler/rustc_middle/src/mir/pretty.rs
+++ b/compiler/rustc_middle/src/mir/pretty.rs
@@ -907,6 +907,7 @@ impl<'tcx> Debug for Rvalue<'tcx> {
                     NullOp::SizeOf => write!(fmt, "SizeOf({t})"),
                     NullOp::AlignOf => write!(fmt, "AlignOf({t})"),
                     NullOp::OffsetOf(fields) => write!(fmt, "OffsetOf({t}, {fields:?})"),
+                    NullOp::DebugAssertions => write!(fmt, "cfg!(debug_assertions)"),
                 }
             }
             ThreadLocalRef(did) => ty::tls::with(|tcx| {
diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs
index ca56e1fd92c..40af453f6ce 100644
--- a/compiler/rustc_middle/src/mir/syntax.rs
+++ b/compiler/rustc_middle/src/mir/syntax.rs
@@ -1361,6 +1361,8 @@ pub enum NullOp<'tcx> {
     AlignOf,
     /// Returns the offset of a field
     OffsetOf(&'tcx List<(VariantIdx, FieldIdx)>),
+    /// cfg!(debug_assertions), but expanded in codegen
+    DebugAssertions,
 }
 
 #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
diff --git a/compiler/rustc_middle/src/mir/tcx.rs b/compiler/rustc_middle/src/mir/tcx.rs
index 4780042a510..5bc151de659 100644
--- a/compiler/rustc_middle/src/mir/tcx.rs
+++ b/compiler/rustc_middle/src/mir/tcx.rs
@@ -194,6 +194,7 @@ impl<'tcx> Rvalue<'tcx> {
             Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf | NullOp::OffsetOf(..), _) => {
                 tcx.types.usize
             }
+            Rvalue::NullaryOp(NullOp::DebugAssertions, _) => tcx.types.bool,
             Rvalue::Aggregate(ref ak, ref ops) => match **ak {
                 AggregateKind::Array(ty) => Ty::new_array(tcx, ty, ops.len() as u64),
                 AggregateKind::Tuple => {
diff --git a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs
index 30dd915521c..80e0d0baf57 100644
--- a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs
+++ b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs
@@ -429,7 +429,10 @@ impl<'b, 'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> Gatherer<'b, 'a, 'tcx, F> {
             | Rvalue::AddressOf(..)
             | Rvalue::Discriminant(..)
             | Rvalue::Len(..)
-            | Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf | NullOp::OffsetOf(..), _) => {}
+            | Rvalue::NullaryOp(
+                NullOp::SizeOf | NullOp::AlignOf | NullOp::OffsetOf(..) | NullOp::DebugAssertions,
+                _,
+            ) => {}
         }
     }
 
diff --git a/compiler/rustc_mir_transform/src/const_prop_lint.rs b/compiler/rustc_mir_transform/src/const_prop_lint.rs
index cb8a1273c0b..04d0a4f303f 100644
--- a/compiler/rustc_mir_transform/src/const_prop_lint.rs
+++ b/compiler/rustc_mir_transform/src/const_prop_lint.rs
@@ -634,6 +634,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
                     NullOp::OffsetOf(fields) => {
                         op_layout.offset_of_subfield(self, fields.iter()).bytes()
                     }
+                    NullOp::DebugAssertions => return None,
                 };
                 ImmTy::from_scalar(Scalar::from_target_usize(val, self), layout).into()
             }
diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs
index 6e4f8f710b6..36c441a3945 100644
--- a/compiler/rustc_mir_transform/src/gvn.rs
+++ b/compiler/rustc_mir_transform/src/gvn.rs
@@ -489,6 +489,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
                     NullOp::OffsetOf(fields) => {
                         layout.offset_of_subfield(&self.ecx, fields.iter()).bytes()
                     }
+                    NullOp::DebugAssertions => return None,
                 };
                 let usize_layout = self.ecx.layout_of(self.tcx.types.usize).unwrap();
                 let imm = ImmTy::try_from_uint(val, usize_layout)?;
diff --git a/compiler/rustc_mir_transform/src/instsimplify.rs b/compiler/rustc_mir_transform/src/instsimplify.rs
index a28db0defc9..f65eb5cbea9 100644
--- a/compiler/rustc_mir_transform/src/instsimplify.rs
+++ b/compiler/rustc_mir_transform/src/instsimplify.rs
@@ -2,10 +2,12 @@
 
 use crate::simplify::simplify_duplicate_switch_targets;
 use rustc_middle::mir::*;
+use rustc_middle::ty::layout;
 use rustc_middle::ty::layout::ValidityRequirement;
 use rustc_middle::ty::{self, GenericArgsRef, ParamEnv, Ty, TyCtxt};
 use rustc_span::symbol::Symbol;
 use rustc_target::abi::FieldIdx;
+use rustc_target::spec::abi::Abi;
 
 pub struct InstSimplify;
 
@@ -38,6 +40,7 @@ impl<'tcx> MirPass<'tcx> for InstSimplify {
                 block.terminator.as_mut().unwrap(),
                 &mut block.statements,
             );
+            ctx.simplify_nounwind_call(block.terminator.as_mut().unwrap());
             simplify_duplicate_switch_targets(block.terminator.as_mut().unwrap());
         }
     }
@@ -252,6 +255,28 @@ impl<'tcx> InstSimplifyContext<'tcx, '_> {
         terminator.kind = TerminatorKind::Goto { target: destination_block };
     }
 
+    fn simplify_nounwind_call(&self, terminator: &mut Terminator<'tcx>) {
+        let TerminatorKind::Call { func, unwind, .. } = &mut terminator.kind else {
+            return;
+        };
+
+        let Some((def_id, _)) = func.const_fn_def() else {
+            return;
+        };
+
+        let body_ty = self.tcx.type_of(def_id).skip_binder();
+        let body_abi = match body_ty.kind() {
+            ty::FnDef(..) => body_ty.fn_sig(self.tcx).abi(),
+            ty::Closure(..) => Abi::RustCall,
+            ty::Coroutine(..) => Abi::Rust,
+            _ => bug!("unexpected body ty: {:?}", body_ty),
+        };
+
+        if !layout::fn_can_unwind(self.tcx, Some(def_id), body_abi) {
+            *unwind = UnwindAction::Unreachable;
+        }
+    }
+
     fn simplify_intrinsic_assert(
         &self,
         terminator: &mut Terminator<'tcx>,
diff --git a/compiler/rustc_mir_transform/src/lower_intrinsics.rs b/compiler/rustc_mir_transform/src/lower_intrinsics.rs
index 897375e0e16..f43b85173d4 100644
--- a/compiler/rustc_mir_transform/src/lower_intrinsics.rs
+++ b/compiler/rustc_mir_transform/src/lower_intrinsics.rs
@@ -21,6 +21,17 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics {
                     sym::unreachable => {
                         terminator.kind = TerminatorKind::Unreachable;
                     }
+                    sym::debug_assertions => {
+                        let target = target.unwrap();
+                        block.statements.push(Statement {
+                            source_info: terminator.source_info,
+                            kind: StatementKind::Assign(Box::new((
+                                *destination,
+                                Rvalue::NullaryOp(NullOp::DebugAssertions, tcx.types.bool),
+                            ))),
+                        });
+                        terminator.kind = TerminatorKind::Goto { target };
+                    }
                     sym::forget => {
                         if let Some(target) = *target {
                             block.statements.push(Statement {
diff --git a/compiler/rustc_mir_transform/src/promote_consts.rs b/compiler/rustc_mir_transform/src/promote_consts.rs
index c00093ea27e..577b8f2080f 100644
--- a/compiler/rustc_mir_transform/src/promote_consts.rs
+++ b/compiler/rustc_mir_transform/src/promote_consts.rs
@@ -446,6 +446,7 @@ impl<'tcx> Validator<'_, 'tcx> {
                 NullOp::SizeOf => {}
                 NullOp::AlignOf => {}
                 NullOp::OffsetOf(_) => {}
+                NullOp::DebugAssertions => {}
             },
 
             Rvalue::ShallowInitBox(_, _) => return Err(Unpromotable),
diff --git a/compiler/rustc_smir/src/rustc_smir/convert/mir.rs b/compiler/rustc_smir/src/rustc_smir/convert/mir.rs
index 41a4edfc03b..501d6f7d304 100644
--- a/compiler/rustc_smir/src/rustc_smir/convert/mir.rs
+++ b/compiler/rustc_smir/src/rustc_smir/convert/mir.rs
@@ -257,6 +257,7 @@ impl<'tcx> Stable<'tcx> for mir::NullOp<'tcx> {
             OffsetOf(indices) => stable_mir::mir::NullOp::OffsetOf(
                 indices.iter().map(|idx| idx.stable(tables)).collect(),
             ),
+            DebugAssertions => stable_mir::mir::NullOp::DebugAssertions,
         }
     }
 }
diff --git a/compiler/stable_mir/src/mir/body.rs b/compiler/stable_mir/src/mir/body.rs
index 38877f7a77f..be727f024c6 100644
--- a/compiler/stable_mir/src/mir/body.rs
+++ b/compiler/stable_mir/src/mir/body.rs
@@ -639,6 +639,7 @@ impl Rvalue {
             Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf | NullOp::OffsetOf(..), _) => {
                 Ok(Ty::usize_ty())
             }
+            Rvalue::NullaryOp(NullOp::DebugAssertions, _) => Ok(Ty::bool_ty()),
             Rvalue::Aggregate(ak, ops) => match *ak {
                 AggregateKind::Array(ty) => Ty::try_new_array(ty, ops.len() as u64),
                 AggregateKind::Tuple => Ok(Ty::new_tuple(
@@ -1005,6 +1006,8 @@ pub enum NullOp {
     AlignOf,
     /// Returns the offset of a field.
     OffsetOf(Vec<(VariantIdx, FieldIdx)>),
+    /// cfg!(debug_assertions), but at codegen time
+    DebugAssertions,
 }
 
 impl Operand {
diff --git a/library/alloc/src/raw_vec.rs b/library/alloc/src/raw_vec.rs
index 94e6924f41a..49f5f53f9b3 100644
--- a/library/alloc/src/raw_vec.rs
+++ b/library/alloc/src/raw_vec.rs
@@ -207,11 +207,7 @@ impl<T, A: Allocator> RawVec<T, A> {
             // Allocators currently return a `NonNull<[u8]>` whose length
             // matches the size requested. If that ever changes, the capacity
             // here should change to `ptr.len() / mem::size_of::<T>()`.
-            Self {
-                ptr: unsafe { Unique::new_unchecked(ptr.cast().as_ptr()) },
-                cap: unsafe { Cap(capacity) },
-                alloc,
-            }
+            Self { ptr: Unique::from(ptr.cast()), cap: unsafe { Cap(capacity) }, alloc }
         }
     }
 
@@ -239,6 +235,11 @@ impl<T, A: Allocator> RawVec<T, A> {
         self.ptr.as_ptr()
     }
 
+    #[inline]
+    pub fn non_null(&self) -> NonNull<T> {
+        NonNull::from(self.ptr)
+    }
+
     /// Gets the capacity of the allocation.
     ///
     /// This will always be `usize::MAX` if `T` is zero-sized.
@@ -398,7 +399,7 @@ impl<T, A: Allocator> RawVec<T, A> {
         // Allocators currently return a `NonNull<[u8]>` whose length matches
         // the size requested. If that ever changes, the capacity here should
         // change to `ptr.len() / mem::size_of::<T>()`.
-        self.ptr = unsafe { Unique::new_unchecked(ptr.cast().as_ptr()) };
+        self.ptr = Unique::from(ptr.cast());
         self.cap = unsafe { Cap(cap) };
     }
 
diff --git a/library/alloc/src/vec/into_iter.rs b/library/alloc/src/vec/into_iter.rs
index 654ce09afcd..7800560da94 100644
--- a/library/alloc/src/vec/into_iter.rs
+++ b/library/alloc/src/vec/into_iter.rs
@@ -136,7 +136,7 @@ impl<T, A: Allocator> IntoIter<T, A> {
         // struct and then overwriting &mut self.
         // this creates less assembly
         self.cap = 0;
-        self.buf = unsafe { NonNull::new_unchecked(RawVec::NEW.ptr()) };
+        self.buf = RawVec::NEW.non_null();
         self.ptr = self.buf;
         self.end = self.buf.as_ptr();
 
diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs
index b3e5ecc9240..08e3cdedc66 100644
--- a/library/alloc/src/vec/mod.rs
+++ b/library/alloc/src/vec/mod.rs
@@ -2861,16 +2861,16 @@ impl<T, A: Allocator> IntoIterator for Vec<T, A> {
     #[inline]
     fn into_iter(self) -> Self::IntoIter {
         unsafe {
-            let mut me = ManuallyDrop::new(self);
+            let me = ManuallyDrop::new(self);
             let alloc = ManuallyDrop::new(ptr::read(me.allocator()));
-            let begin = me.as_mut_ptr();
+            let buf = me.buf.non_null();
+            let begin = buf.as_ptr();
             let end = if T::IS_ZST {
                 begin.wrapping_byte_add(me.len())
             } else {
                 begin.add(me.len()) as *const T
             };
             let cap = me.buf.capacity();
-            let buf = NonNull::new_unchecked(begin);
             IntoIter { buf, phantom: PhantomData, cap, alloc, ptr: buf, end }
         }
     }
diff --git a/library/core/src/char/convert.rs b/library/core/src/char/convert.rs
index 177f39b59ae..7bd592492a5 100644
--- a/library/core/src/char/convert.rs
+++ b/library/core/src/char/convert.rs
@@ -27,7 +27,7 @@ pub(super) const unsafe fn from_u32_unchecked(i: u32) -> char {
     unsafe {
         assert_unsafe_precondition!(
             "invalid value for `char`",
-            (i: u32) => char_try_from_u32(i).is_ok()
+            (i: u32 = i) => char_try_from_u32(i).is_ok()
         );
         transmute(i)
     }
diff --git a/library/core/src/hint.rs b/library/core/src/hint.rs
index 5c44ca69451..97c3c9e6fae 100644
--- a/library/core/src/hint.rs
+++ b/library/core/src/hint.rs
@@ -148,7 +148,7 @@ pub const unsafe fn assert_unchecked(cond: bool) {
     unsafe {
         intrinsics::assert_unsafe_precondition!(
             "hint::assert_unchecked must never be called when the condition is false",
-            (cond: bool) => cond,
+            (cond: bool = cond) => cond,
         );
         crate::intrinsics::assume(cond);
     }
diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs
index 6ea80c8d42f..a6311e41633 100644
--- a/library/core/src/intrinsics.rs
+++ b/library/core/src/intrinsics.rs
@@ -56,7 +56,7 @@
 
 use crate::marker::DiscriminantKind;
 use crate::marker::Tuple;
-use crate::mem;
+use crate::mem::{self, align_of};
 
 pub mod mir;
 pub mod simd;
@@ -2569,6 +2569,17 @@ extern "rust-intrinsic" {
     #[rustc_nounwind]
     #[cfg(not(bootstrap))]
     pub fn is_val_statically_known<T: Copy>(arg: T) -> bool;
+
+    #[rustc_const_unstable(feature = "delayed_debug_assertions", issue = "none")]
+    #[rustc_safe_intrinsic]
+    #[cfg(not(bootstrap))]
+    pub(crate) fn debug_assertions() -> bool;
+}
+
+#[cfg(bootstrap)]
+#[rustc_const_unstable(feature = "delayed_debug_assertions", issue = "none")]
+pub(crate) const fn debug_assertions() -> bool {
+    cfg!(debug_assertions)
 }
 
 // FIXME: Seems using `unstable` here completely ignores `rustc_allow_const_fn_unstable`
@@ -2587,10 +2598,27 @@ pub const unsafe fn is_val_statically_known<T: Copy>(_arg: T) -> bool {
 /// Check that the preconditions of an unsafe function are followed, if debug_assertions are on,
 /// and only at runtime.
 ///
-/// This macro should be called as `assert_unsafe_precondition!([Generics](name: Type) => Expression)`
-/// where the names specified will be moved into the macro as captured variables, and defines an item
-/// to call `const_eval_select` on. The tokens inside the square brackets are used to denote generics
-/// for the function declarations and can be omitted if there is no generics.
+/// This macro should be called as
+/// `assert_unsafe_precondition!((expr => name: Type, expr => name: Type) => Expression)`
+/// where each `expr` will be evaluated and passed in as function argument `name: Type`. Then all
+/// those arguments are passed to a function via [`const_eval_select`].
+///
+/// These checks are behind a condition which is evaluated at codegen time, not expansion time like
+/// [`debug_assert`]. This means that a standard library built with optimizations and debug
+/// assertions disabled will have these checks optimized out of its monomorphizations, but if a
+/// a caller of the standard library has debug assertions enabled and monomorphizes an expansion of
+/// this macro, that monomorphization will contain the check.
+///
+/// Since these checks cannot be optimized out in MIR, some care must be taken in both call and
+/// implementation to mitigate their compile-time overhead. The runtime function that we
+/// [`const_eval_select`] to is monomorphic, `#[inline(never)]`, and `#[rustc_nounwind]`. That
+/// combination of properties ensures that the code for the checks is only compiled once, and has a
+/// minimal impact on the caller's code size.
+///
+/// Caller should also introducing any other `let` bindings or any code outside this macro in order
+/// to call it. Since the precompiled standard library is built with full debuginfo and these
+/// variables cannot be optimized out in MIR, an innocent-looking `let` can produce enough
+/// debuginfo to have a measurable compile-time impact on debug builds.
 ///
 /// # Safety
 ///
@@ -2604,26 +2632,24 @@ pub const unsafe fn is_val_statically_known<T: Copy>(_arg: T) -> bool {
 ///
 /// So in a sense it is UB if this macro is useful, but we expect callers of `unsafe fn` to make
 /// the occasional mistake, and this check should help them figure things out.
-#[allow_internal_unstable(const_eval_select)] // permit this to be called in stably-const fn
+#[allow_internal_unstable(const_eval_select, delayed_debug_assertions)] // permit this to be called in stably-const fn
 macro_rules! assert_unsafe_precondition {
-    ($name:expr, $([$($tt:tt)*])?($($i:ident:$ty:ty),*$(,)?) => $e:expr $(,)?) => {
-        if cfg!(debug_assertions) {
-            // allow non_snake_case to allow capturing const generics
-            #[allow(non_snake_case)]
-            #[inline(always)]
-            fn runtime$(<$($tt)*>)?($($i:$ty),*) {
+    ($message:expr, ($($name:ident:$ty:ty = $arg:expr),*$(,)?) => $e:expr $(,)?) => {
+        {
+            #[inline(never)]
+            #[rustc_nounwind]
+            fn precondition_check($($name:$ty),*) {
                 if !$e {
-                    // don't unwind to reduce impact on code size
                     ::core::panicking::panic_nounwind(
-                        concat!("unsafe precondition(s) violated: ", $name)
+                        concat!("unsafe precondition(s) violated: ", $message)
                     );
                 }
             }
-            #[allow(non_snake_case)]
-            #[inline]
-            const fn comptime$(<$($tt)*>)?($(_:$ty),*) {}
+            const fn comptime($(_:$ty),*) {}
 
-            ::core::intrinsics::const_eval_select(($($i,)*), comptime, runtime);
+            if ::core::intrinsics::debug_assertions() {
+                ::core::intrinsics::const_eval_select(($($arg,)*), comptime, precondition_check);
+            }
         }
     };
 }
@@ -2632,30 +2658,47 @@ pub(crate) use assert_unsafe_precondition;
 /// Checks whether `ptr` is properly aligned with respect to
 /// `align_of::<T>()`.
 #[inline]
-pub(crate) fn is_aligned_and_not_null<T>(ptr: *const T) -> bool {
-    !ptr.is_null() && ptr.is_aligned()
+pub(crate) fn is_aligned_and_not_null(ptr: *const (), align: usize) -> bool {
+    !ptr.is_null() && ptr.is_aligned_to(align)
 }
 
-/// Checks whether an allocation of `len` instances of `T` exceeds
-/// the maximum allowed allocation size.
 #[inline]
-pub(crate) fn is_valid_allocation_size<T>(len: usize) -> bool {
-    let max_len = const {
-        let size = crate::mem::size_of::<T>();
-        if size == 0 { usize::MAX } else { isize::MAX as usize / size }
-    };
+pub(crate) fn is_valid_allocation_size(size: usize, len: usize) -> bool {
+    let max_len = if size == 0 { usize::MAX } else { isize::MAX as usize / size };
     len <= max_len
 }
 
+pub(crate) fn is_nonoverlapping_mono(
+    src: *const (),
+    dst: *const (),
+    size: usize,
+    count: usize,
+) -> bool {
+    let src_usize = src.addr();
+    let dst_usize = dst.addr();
+    let Some(size) = size.checked_mul(count) else {
+        crate::panicking::panic_nounwind(
+            "is_nonoverlapping: `size_of::<T>() * count` overflows a usize",
+        )
+    };
+    let diff = src_usize.abs_diff(dst_usize);
+    // If the absolute distance between the ptrs is at least as big as the size of the buffer,
+    // they do not overlap.
+    diff >= size
+}
+
 /// Checks whether the regions of memory starting at `src` and `dst` of size
 /// `count * size_of::<T>()` do *not* overlap.
 #[inline]
 pub(crate) fn is_nonoverlapping<T>(src: *const T, dst: *const T, count: usize) -> bool {
     let src_usize = src.addr();
     let dst_usize = dst.addr();
-    let size = mem::size_of::<T>()
-        .checked_mul(count)
-        .expect("is_nonoverlapping: `size_of::<T>() * count` overflows a usize");
+    let Some(size) = mem::size_of::<T>().checked_mul(count) else {
+        // Use panic_nounwind instead of Option::expect, so that this function is nounwind.
+        crate::panicking::panic_nounwind(
+            "is_nonoverlapping: `size_of::<T>() * count` overflows a usize",
+        )
+    };
     let diff = src_usize.abs_diff(dst_usize);
     // If the absolute distance between the ptrs is at least as big as the size of the buffer,
     // they do not overlap.
@@ -2766,10 +2809,16 @@ pub const unsafe fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: us
         assert_unsafe_precondition!(
             "ptr::copy_nonoverlapping requires that both pointer arguments are aligned and non-null \
             and the specified memory ranges do not overlap",
-            [T](src: *const T, dst: *mut T, count: usize) =>
-            is_aligned_and_not_null(src)
-                && is_aligned_and_not_null(dst)
-                && is_nonoverlapping(src, dst, count)
+            (
+                src: *const () = src as *const (),
+                dst: *mut () = dst as *mut (),
+                size: usize = size_of::<T>(),
+                align: usize = align_of::<T>(),
+                count: usize = count,
+            ) =>
+            is_aligned_and_not_null(src, align)
+                && is_aligned_and_not_null(dst, align)
+                && is_nonoverlapping_mono(src, dst, size, count)
         );
         copy_nonoverlapping(src, dst, count)
     }
@@ -2859,9 +2908,15 @@ pub const unsafe fn copy<T>(src: *const T, dst: *mut T, count: usize) {
     // SAFETY: the safety contract for `copy` must be upheld by the caller.
     unsafe {
         assert_unsafe_precondition!(
-            "ptr::copy requires that both pointer arguments are aligned and non-null",
-            [T](src: *const T, dst: *mut T) =>
-            is_aligned_and_not_null(src) && is_aligned_and_not_null(dst)
+            "ptr::copy_nonoverlapping requires that both pointer arguments are aligned and non-null \
+            and the specified memory ranges do not overlap",
+            (
+                src: *const () = src as *const (),
+                dst: *mut () = dst as *mut (),
+                align: usize = align_of::<T>(),
+            ) =>
+            is_aligned_and_not_null(src, align)
+                && is_aligned_and_not_null(dst, align)
         );
         copy(src, dst, count)
     }
@@ -2934,7 +2989,10 @@ pub const unsafe fn write_bytes<T>(dst: *mut T, val: u8, count: usize) {
     unsafe {
         assert_unsafe_precondition!(
             "ptr::write_bytes requires that the destination pointer is aligned and non-null",
-            [T](dst: *mut T) => is_aligned_and_not_null(dst)
+            (
+                addr: *const () = dst as *const (),
+                align: usize = align_of::<T>(),
+            ) => is_aligned_and_not_null(addr, align)
         );
         write_bytes(dst, val, count)
     }
diff --git a/library/core/src/option.rs b/library/core/src/option.rs
index c94e7d73a2a..ab005228984 100644
--- a/library/core/src/option.rs
+++ b/library/core/src/option.rs
@@ -1033,7 +1033,6 @@ impl<T> Option<T> {
     #[stable(feature = "option_result_unwrap_unchecked", since = "1.58.0")]
     #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")]
     pub const unsafe fn unwrap_unchecked(self) -> T {
-        debug_assert!(self.is_some());
         match self {
             Some(val) => val,
             // SAFETY: the safety contract must be upheld by the caller.
diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs
index 1d5d683fa16..c5e3df07a1c 100644
--- a/library/core/src/ptr/const_ptr.rs
+++ b/library/core/src/ptr/const_ptr.rs
@@ -806,13 +806,15 @@ impl<T: ?Sized> *const T {
     where
         T: Sized,
     {
-        let this = self;
         // SAFETY: The comparison has no side-effects, and the intrinsic
         // does this check internally in the CTFE implementation.
         unsafe {
             assert_unsafe_precondition!(
-                "ptr::sub_ptr requires `this >= origin`",
-                [T](this: *const T, origin: *const T) => this >= origin
+                "ptr::sub_ptr requires `self >= origin`",
+                (
+                    this: *const () = self as *const (),
+                    origin: *const () = origin as *const (),
+                ) => this >= origin
             )
         };
 
diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs
index bc05b5b07de..0fb9017e6d9 100644
--- a/library/core/src/ptr/mod.rs
+++ b/library/core/src/ptr/mod.rs
@@ -381,11 +381,11 @@ use crate::cmp::Ordering;
 use crate::fmt;
 use crate::hash;
 use crate::intrinsics::{
-    self, assert_unsafe_precondition, is_aligned_and_not_null, is_nonoverlapping,
+    self, assert_unsafe_precondition, is_aligned_and_not_null, is_nonoverlapping_mono,
 };
 use crate::marker::FnPtr;
 
-use crate::mem::{self, MaybeUninit};
+use crate::mem::{self, align_of, size_of, MaybeUninit};
 
 mod alignment;
 #[unstable(feature = "ptr_alignment_type", issue = "102070")]
@@ -967,10 +967,16 @@ pub const unsafe fn swap_nonoverlapping<T>(x: *mut T, y: *mut T, count: usize) {
         assert_unsafe_precondition!(
             "ptr::swap_nonoverlapping requires that both pointer arguments are aligned and non-null \
             and the specified memory ranges do not overlap",
-            [T](x: *mut T, y: *mut T, count: usize) =>
-            is_aligned_and_not_null(x)
-                && is_aligned_and_not_null(y)
-                && is_nonoverlapping(x, y, count)
+            (
+                x: *mut () = x as *mut (),
+                y: *mut () = y as *mut (),
+                size: usize = size_of::<T>(),
+                align: usize = align_of::<T>(),
+                count: usize = count,
+            ) =>
+            is_aligned_and_not_null(x, align)
+                && is_aligned_and_not_null(y, align)
+                && is_nonoverlapping_mono(x, y, size, count)
         );
     }
 
@@ -1061,7 +1067,10 @@ pub const unsafe fn replace<T>(dst: *mut T, mut src: T) -> T {
     unsafe {
         assert_unsafe_precondition!(
             "ptr::replace requires that the pointer argument is aligned and non-null",
-            [T](dst: *mut T) => is_aligned_and_not_null(dst)
+            (
+                addr: *const () = dst as *const (),
+                align: usize = align_of::<T>(),
+            ) => is_aligned_and_not_null(addr, align)
         );
         mem::swap(&mut *dst, &mut src); // cannot overlap
     }
@@ -1207,9 +1216,13 @@ pub const unsafe fn read<T>(src: *const T) -> T {
 
     // SAFETY: the caller must guarantee that `src` is valid for reads.
     unsafe {
+        #[cfg(debug_assertions)] // Too expensive to always enable (for now?)
         assert_unsafe_precondition!(
             "ptr::read requires that the pointer argument is aligned and non-null",
-            [T](src: *const T) => is_aligned_and_not_null(src)
+            (
+                addr: *const () = src as *const (),
+                align: usize = align_of::<T>(),
+            ) => is_aligned_and_not_null(addr, align)
         );
         crate::intrinsics::read_via_copy(src)
     }
@@ -1411,9 +1424,13 @@ pub const unsafe fn write<T>(dst: *mut T, src: T) {
     // `dst` cannot overlap `src` because the caller has mutable access
     // to `dst` while `src` is owned by this function.
     unsafe {
+        #[cfg(debug_assertions)] // Too expensive to always enable (for now?)
         assert_unsafe_precondition!(
             "ptr::write requires that the pointer argument is aligned and non-null",
-            [T](dst: *mut T) => is_aligned_and_not_null(dst)
+            (
+                addr: *mut () = dst as *mut (),
+                align: usize = align_of::<T>(),
+            ) => is_aligned_and_not_null(addr, align)
         );
         intrinsics::write_via_move(dst, src)
     }
@@ -1581,7 +1598,10 @@ pub unsafe fn read_volatile<T>(src: *const T) -> T {
     unsafe {
         assert_unsafe_precondition!(
             "ptr::read_volatile requires that the pointer argument is aligned and non-null",
-            [T](src: *const T) => is_aligned_and_not_null(src)
+            (
+                addr: *const () = src as *const (),
+                align: usize = align_of::<T>(),
+            ) => is_aligned_and_not_null(addr, align)
         );
         intrinsics::volatile_load(src)
     }
@@ -1656,7 +1676,10 @@ pub unsafe fn write_volatile<T>(dst: *mut T, src: T) {
     unsafe {
         assert_unsafe_precondition!(
             "ptr::write_volatile requires that the pointer argument is aligned and non-null",
-            [T](dst: *mut T) => is_aligned_and_not_null(dst)
+            (
+                addr: *mut () = dst as *mut (),
+                align: usize = align_of::<T>(),
+            ) => is_aligned_and_not_null(addr, align)
         );
         intrinsics::volatile_store(dst, src);
     }
diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs
index d18082c3048..320cd5eb3b2 100644
--- a/library/core/src/ptr/non_null.rs
+++ b/library/core/src/ptr/non_null.rs
@@ -218,7 +218,10 @@ impl<T: ?Sized> NonNull<T> {
     pub const unsafe fn new_unchecked(ptr: *mut T) -> Self {
         // SAFETY: the caller must guarantee that `ptr` is non-null.
         unsafe {
-            assert_unsafe_precondition!("NonNull::new_unchecked requires that the pointer is non-null", [T: ?Sized](ptr: *mut T) => !ptr.is_null());
+            assert_unsafe_precondition!(
+                "NonNull::new_unchecked requires that the pointer is non-null",
+                (ptr: *mut () = ptr as *mut ()) => !ptr.is_null()
+            );
             NonNull { pointer: ptr as _ }
         }
     }
@@ -470,7 +473,7 @@ impl<T: ?Sized> NonNull<T> {
     #[inline]
     pub const fn cast<U>(self) -> NonNull<U> {
         // SAFETY: `self` is a `NonNull` pointer which is necessarily non-null
-        unsafe { NonNull::new_unchecked(self.as_ptr() as *mut U) }
+        unsafe { NonNull { pointer: self.as_ptr() as *mut U } }
     }
 
     /// Calculates the offset from a pointer.
@@ -1588,8 +1591,7 @@ impl<T> NonNull<[T]> {
     #[unstable(feature = "slice_ptr_get", issue = "74265")]
     #[rustc_const_unstable(feature = "slice_ptr_get", issue = "74265")]
     pub const fn as_non_null_ptr(self) -> NonNull<T> {
-        // SAFETY: We know `self` is non-null.
-        unsafe { NonNull::new_unchecked(self.as_ptr().as_mut_ptr()) }
+        self.cast()
     }
 
     /// Returns a raw pointer to the slice's buffer.
@@ -1825,9 +1827,7 @@ impl<T: ?Sized> hash::Hash for NonNull<T> {
 impl<T: ?Sized> From<Unique<T>> for NonNull<T> {
     #[inline]
     fn from(unique: Unique<T>) -> Self {
-        // SAFETY: A Unique pointer cannot be null, so the conditions for
-        // new_unchecked() are respected.
-        unsafe { NonNull::new_unchecked(unique.as_ptr()) }
+        unique.as_non_null_ptr()
     }
 }
 
@@ -1850,8 +1850,7 @@ impl<T: ?Sized> From<&T> for NonNull<T> {
     /// This conversion is safe and infallible since references cannot be null.
     #[inline]
     fn from(reference: &T) -> Self {
-        // SAFETY: A reference cannot be null, so the conditions for
-        // new_unchecked() are respected.
+        // SAFETY: A reference cannot be null.
         unsafe { NonNull { pointer: reference as *const T } }
     }
 }
diff --git a/library/core/src/ptr/unique.rs b/library/core/src/ptr/unique.rs
index 067f1541e31..b74d691e454 100644
--- a/library/core/src/ptr/unique.rs
+++ b/library/core/src/ptr/unique.rs
@@ -106,6 +106,13 @@ impl<T: ?Sized> Unique<T> {
         self.pointer.as_ptr()
     }
 
+    /// Acquires the underlying `*mut` pointer.
+    #[must_use = "`self` will be dropped if the result is not used"]
+    #[inline]
+    pub const fn as_non_null_ptr(self) -> NonNull<T> {
+        self.pointer
+    }
+
     /// Dereferences the content.
     ///
     /// The resulting lifetime is bound to self so this behaves "as if"
@@ -138,7 +145,7 @@ impl<T: ?Sized> Unique<T> {
     pub const fn cast<U>(self) -> Unique<U> {
         // FIXME(const-hack): replace with `From`
         // SAFETY: is `NonNull`
-        unsafe { Unique::new_unchecked(self.pointer.cast().as_ptr()) }
+        Unique { pointer: self.pointer.cast(), _marker: PhantomData }
     }
 }
 
diff --git a/library/core/src/slice/iter.rs b/library/core/src/slice/iter.rs
index 2d4c7e78aea..1ca4ecbfba9 100644
--- a/library/core/src/slice/iter.rs
+++ b/library/core/src/slice/iter.rs
@@ -87,12 +87,13 @@ unsafe impl<T: Sync> Send for Iter<'_, T> {}
 impl<'a, T> Iter<'a, T> {
     #[inline]
     pub(super) fn new(slice: &'a [T]) -> Self {
-        let ptr = slice.as_ptr();
+        let len = slice.len();
+        let ptr: NonNull<T> = NonNull::from(slice).cast();
         // SAFETY: Similar to `IterMut::new`.
         unsafe {
-            let end_or_len = if T::IS_ZST { invalid(slice.len()) } else { ptr.add(slice.len()) };
+            let end_or_len = if T::IS_ZST { invalid(len) } else { ptr.as_ptr().add(len) };
 
-            Self { ptr: NonNull::new_unchecked(ptr as *mut T), end_or_len, _marker: PhantomData }
+            Self { ptr, end_or_len, _marker: PhantomData }
         }
     }
 
@@ -208,7 +209,8 @@ unsafe impl<T: Send> Send for IterMut<'_, T> {}
 impl<'a, T> IterMut<'a, T> {
     #[inline]
     pub(super) fn new(slice: &'a mut [T]) -> Self {
-        let ptr = slice.as_mut_ptr();
+        let len = slice.len();
+        let ptr: NonNull<T> = NonNull::from(slice).cast();
         // SAFETY: There are several things here:
         //
         // `ptr` has been obtained by `slice.as_ptr()` where `slice` is a valid
@@ -226,10 +228,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 { invalid_mut(slice.len()) } else { ptr.add(slice.len()) };
+            let end_or_len = if T::IS_ZST { invalid_mut(len) } else { ptr.as_ptr().add(len) };
 
-            Self { ptr: NonNull::new_unchecked(ptr), end_or_len, _marker: PhantomData }
+            Self { ptr, end_or_len, _marker: PhantomData }
         }
     }
 
diff --git a/library/core/src/slice/raw.rs b/library/core/src/slice/raw.rs
index 9cdf9b68afb..571abc3e999 100644
--- a/library/core/src/slice/raw.rs
+++ b/library/core/src/slice/raw.rs
@@ -4,6 +4,7 @@ use crate::array;
 use crate::intrinsics::{
     assert_unsafe_precondition, is_aligned_and_not_null, is_valid_allocation_size,
 };
+use crate::mem::{align_of, size_of};
 use crate::ops::Range;
 use crate::ptr;
 
@@ -96,8 +97,14 @@ pub const unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T]
     unsafe {
         assert_unsafe_precondition!(
             "slice::from_raw_parts requires the pointer to be aligned and non-null, and the total size of the slice not to exceed `isize::MAX`",
-            [T](data: *const T, len: usize) => is_aligned_and_not_null(data)
-                && is_valid_allocation_size::<T>(len)
+            (
+                data: *mut () = data as *mut (),
+                size: usize = size_of::<T>(),
+                align: usize = align_of::<T>(),
+                len: usize = len,
+            ) =>
+                is_aligned_and_not_null(data, align)
+                && is_valid_allocation_size(size, len)
         );
         &*ptr::slice_from_raw_parts(data, len)
     }
@@ -143,8 +150,14 @@ pub const unsafe fn from_raw_parts_mut<'a, T>(data: *mut T, len: usize) -> &'a m
     unsafe {
         assert_unsafe_precondition!(
             "slice::from_raw_parts_mut requires the pointer to be aligned and non-null, and the total size of the slice not to exceed `isize::MAX`",
-            [T](data: *mut T, len: usize) => is_aligned_and_not_null(data)
-                && is_valid_allocation_size::<T>(len)
+            (
+                data: *mut () = data as *mut (),
+                size: usize = size_of::<T>(),
+                align: usize = align_of::<T>(),
+                len: usize = len,
+            ) =>
+                is_aligned_and_not_null(data, align)
+                && is_valid_allocation_size(size, len)
         );
         &mut *ptr::slice_from_raw_parts_mut(data, len)
     }
diff --git a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
index 81f4fcc2133..8d5bcd665ad 100644
--- a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
+++ b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
@@ -174,7 +174,7 @@ fn check_rvalue<'tcx>(
                 ))
             }
         },
-        Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf | NullOp::OffsetOf(_), _) | Rvalue::ShallowInitBox(_, _) => {
+        Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf | NullOp::OffsetOf(_) | NullOp::DebugAssertions, _) | Rvalue::ShallowInitBox(_, _) => {
             Ok(())
         },
         Rvalue::UnaryOp(_, operand) => {
diff --git a/src/tools/tidy/src/ui_tests.rs b/src/tools/tidy/src/ui_tests.rs
index 4a44c40debd..d5df05bacd9 100644
--- a/src/tools/tidy/src/ui_tests.rs
+++ b/src/tools/tidy/src/ui_tests.rs
@@ -15,7 +15,7 @@ use std::path::{Path, PathBuf};
 const ENTRY_LIMIT: usize = 900;
 // FIXME: The following limits should be reduced eventually.
 const ISSUES_ENTRY_LIMIT: usize = 1819;
-const ROOT_ENTRY_LIMIT: usize = 871;
+const ROOT_ENTRY_LIMIT: usize = 872;
 
 const EXPECTED_TEST_FILE_EXTENSIONS: &[&str] = &[
     "rs",     // test source files
diff --git a/tests/assembly/is_aligned.rs b/tests/assembly/is_aligned.rs
index d152d200adf..c4a7823ce1a 100644
--- a/tests/assembly/is_aligned.rs
+++ b/tests/assembly/is_aligned.rs
@@ -2,8 +2,8 @@
 // only-x86_64
 // ignore-sgx
 // revisions: opt-speed opt-size
-// [opt-speed] compile-flags: -Copt-level=1
-// [opt-size] compile-flags: -Copt-level=s
+// [opt-speed] compile-flags: -Copt-level=2 -Cdebug-assertions=no
+// [opt-size] compile-flags: -Copt-level=s -Cdebug-assertions=no
 #![crate_type="rlib"]
 
 #![feature(core_intrinsics)]
diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-abort.diff
index ffbd97bb545..94cfb4e63fc 100644
--- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-abort.diff
+++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-abort.diff
@@ -24,29 +24,11 @@
                           debug ptr => _6;
                           scope 11 (inlined NonNull::<[bool; 0]>::new_unchecked) {
                               debug ptr => _6;
-                              let mut _8: *const [bool; 0];
-                              let mut _9: *mut [bool; 0];
+                              let mut _8: bool;
+                              let _9: ();
+                              let mut _10: *mut ();
+                              let mut _11: *const [bool; 0];
                               scope 12 {
-                                  scope 13 (inlined NonNull::<T>::new_unchecked::runtime::<[bool; 0]>) {
-                                      debug ptr => _9;
-                                      scope 14 (inlined std::ptr::mut_ptr::<impl *mut [bool; 0]>::is_null) {
-                                          debug self => _9;
-                                          let mut _10: *mut u8;
-                                          scope 15 {
-                                              scope 16 (inlined std::ptr::mut_ptr::<impl *mut T>::is_null::runtime_impl) {
-                                                  debug ptr => _10;
-                                                  scope 17 (inlined std::ptr::mut_ptr::<impl *mut u8>::addr) {
-                                                      debug self => _10;
-                                                      scope 18 {
-                                                          scope 19 (inlined std::ptr::mut_ptr::<impl *mut u8>::cast::<()>) {
-                                                              debug self => _10;
-                                                          }
-                                                      }
-                                                  }
-                                              }
-                                          }
-                                      }
-                                  }
                               }
                           }
                       }
@@ -66,6 +48,7 @@
           StorageLive(_1);
           StorageLive(_2);
           StorageLive(_3);
+          StorageLive(_9);
           StorageLive(_4);
           StorageLive(_5);
           StorageLive(_6);
@@ -73,30 +56,41 @@
           _7 = const 1_usize;
           _6 = const {0x1 as *mut [bool; 0]};
           StorageDead(_7);
-          StorageLive(_8);
-          StorageLive(_9);
           StorageLive(_10);
-          _8 = const {0x1 as *mut [bool; 0]} as *const [bool; 0] (PointerCoercion(MutToConstPointer));
-          _5 = NonNull::<[bool; 0]> { pointer: _8 };
-          StorageDead(_10);
-          StorageDead(_9);
+          StorageLive(_11);
+          StorageLive(_8);
+          _8 = cfg!(debug_assertions);
+          switchInt(move _8) -> [0: bb3, otherwise: bb2];
+      }
+  
+      bb1: {
+          StorageDead(_1);
+          return;
+      }
+  
+      bb2: {
+          _10 = const {0x1 as *mut [bool; 0]} as *mut () (PtrToPtr);
+          _9 = NonNull::<T>::new_unchecked::precondition_check(move _10) -> [return: bb3, unwind unreachable];
+      }
+  
+      bb3: {
           StorageDead(_8);
+          _11 = const {0x1 as *mut [bool; 0]} as *const [bool; 0] (PointerCoercion(MutToConstPointer));
+          _5 = NonNull::<[bool; 0]> { pointer: _11 };
+          StorageDead(_11);
+          StorageDead(_10);
           StorageDead(_6);
           _4 = Unique::<[bool; 0]> { pointer: move _5, _marker: const PhantomData::<[bool; 0]> };
           StorageDead(_5);
           _3 = move _4 as std::ptr::Unique<[bool]> (PointerCoercion(Unsize));
           StorageDead(_4);
           _2 = Box::<[bool]>(_3, const std::alloc::Global);
+          StorageDead(_9);
           StorageDead(_3);
           _1 = A { foo: move _2 };
           StorageDead(_2);
           _0 = const ();
           drop(_1) -> [return: bb1, unwind unreachable];
       }
-  
-      bb1: {
-          StorageDead(_1);
-          return;
-      }
   }
   
diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-unwind.diff
index 7b6dcf1972b..ee85287882b 100644
--- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-unwind.diff
+++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.32bit.panic-unwind.diff
@@ -24,29 +24,11 @@
                           debug ptr => _6;
                           scope 11 (inlined NonNull::<[bool; 0]>::new_unchecked) {
                               debug ptr => _6;
-                              let mut _8: *const [bool; 0];
-                              let mut _9: *mut [bool; 0];
+                              let mut _8: bool;
+                              let _9: ();
+                              let mut _10: *mut ();
+                              let mut _11: *const [bool; 0];
                               scope 12 {
-                                  scope 13 (inlined NonNull::<T>::new_unchecked::runtime::<[bool; 0]>) {
-                                      debug ptr => _9;
-                                      scope 14 (inlined std::ptr::mut_ptr::<impl *mut [bool; 0]>::is_null) {
-                                          debug self => _9;
-                                          let mut _10: *mut u8;
-                                          scope 15 {
-                                              scope 16 (inlined std::ptr::mut_ptr::<impl *mut T>::is_null::runtime_impl) {
-                                                  debug ptr => _10;
-                                                  scope 17 (inlined std::ptr::mut_ptr::<impl *mut u8>::addr) {
-                                                      debug self => _10;
-                                                      scope 18 {
-                                                          scope 19 (inlined std::ptr::mut_ptr::<impl *mut u8>::cast::<()>) {
-                                                              debug self => _10;
-                                                          }
-                                                      }
-                                                  }
-                                              }
-                                          }
-                                      }
-                                  }
                               }
                           }
                       }
@@ -66,6 +48,7 @@
           StorageLive(_1);
           StorageLive(_2);
           StorageLive(_3);
+          StorageLive(_9);
           StorageLive(_4);
           StorageLive(_5);
           StorageLive(_6);
@@ -73,34 +56,45 @@
           _7 = const 1_usize;
           _6 = const {0x1 as *mut [bool; 0]};
           StorageDead(_7);
-          StorageLive(_8);
-          StorageLive(_9);
           StorageLive(_10);
-          _8 = const {0x1 as *mut [bool; 0]} as *const [bool; 0] (PointerCoercion(MutToConstPointer));
-          _5 = NonNull::<[bool; 0]> { pointer: _8 };
-          StorageDead(_10);
-          StorageDead(_9);
+          StorageLive(_11);
+          StorageLive(_8);
+          _8 = cfg!(debug_assertions);
+          switchInt(move _8) -> [0: bb4, otherwise: bb3];
+      }
+  
+      bb1: {
+          StorageDead(_1);
+          return;
+      }
+  
+      bb2 (cleanup): {
+          resume;
+      }
+  
+      bb3: {
+          _10 = const {0x1 as *mut [bool; 0]} as *mut () (PtrToPtr);
+          _9 = NonNull::<T>::new_unchecked::precondition_check(move _10) -> [return: bb4, unwind unreachable];
+      }
+  
+      bb4: {
           StorageDead(_8);
+          _11 = const {0x1 as *mut [bool; 0]} as *const [bool; 0] (PointerCoercion(MutToConstPointer));
+          _5 = NonNull::<[bool; 0]> { pointer: _11 };
+          StorageDead(_11);
+          StorageDead(_10);
           StorageDead(_6);
           _4 = Unique::<[bool; 0]> { pointer: move _5, _marker: const PhantomData::<[bool; 0]> };
           StorageDead(_5);
           _3 = move _4 as std::ptr::Unique<[bool]> (PointerCoercion(Unsize));
           StorageDead(_4);
           _2 = Box::<[bool]>(_3, const std::alloc::Global);
+          StorageDead(_9);
           StorageDead(_3);
           _1 = A { foo: move _2 };
           StorageDead(_2);
           _0 = const ();
           drop(_1) -> [return: bb1, unwind: bb2];
       }
-  
-      bb1: {
-          StorageDead(_1);
-          return;
-      }
-  
-      bb2 (cleanup): {
-          resume;
-      }
   }
   
diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-abort.diff
index ffbd97bb545..94cfb4e63fc 100644
--- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-abort.diff
+++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-abort.diff
@@ -24,29 +24,11 @@
                           debug ptr => _6;
                           scope 11 (inlined NonNull::<[bool; 0]>::new_unchecked) {
                               debug ptr => _6;
-                              let mut _8: *const [bool; 0];
-                              let mut _9: *mut [bool; 0];
+                              let mut _8: bool;
+                              let _9: ();
+                              let mut _10: *mut ();
+                              let mut _11: *const [bool; 0];
                               scope 12 {
-                                  scope 13 (inlined NonNull::<T>::new_unchecked::runtime::<[bool; 0]>) {
-                                      debug ptr => _9;
-                                      scope 14 (inlined std::ptr::mut_ptr::<impl *mut [bool; 0]>::is_null) {
-                                          debug self => _9;
-                                          let mut _10: *mut u8;
-                                          scope 15 {
-                                              scope 16 (inlined std::ptr::mut_ptr::<impl *mut T>::is_null::runtime_impl) {
-                                                  debug ptr => _10;
-                                                  scope 17 (inlined std::ptr::mut_ptr::<impl *mut u8>::addr) {
-                                                      debug self => _10;
-                                                      scope 18 {
-                                                          scope 19 (inlined std::ptr::mut_ptr::<impl *mut u8>::cast::<()>) {
-                                                              debug self => _10;
-                                                          }
-                                                      }
-                                                  }
-                                              }
-                                          }
-                                      }
-                                  }
                               }
                           }
                       }
@@ -66,6 +48,7 @@
           StorageLive(_1);
           StorageLive(_2);
           StorageLive(_3);
+          StorageLive(_9);
           StorageLive(_4);
           StorageLive(_5);
           StorageLive(_6);
@@ -73,30 +56,41 @@
           _7 = const 1_usize;
           _6 = const {0x1 as *mut [bool; 0]};
           StorageDead(_7);
-          StorageLive(_8);
-          StorageLive(_9);
           StorageLive(_10);
-          _8 = const {0x1 as *mut [bool; 0]} as *const [bool; 0] (PointerCoercion(MutToConstPointer));
-          _5 = NonNull::<[bool; 0]> { pointer: _8 };
-          StorageDead(_10);
-          StorageDead(_9);
+          StorageLive(_11);
+          StorageLive(_8);
+          _8 = cfg!(debug_assertions);
+          switchInt(move _8) -> [0: bb3, otherwise: bb2];
+      }
+  
+      bb1: {
+          StorageDead(_1);
+          return;
+      }
+  
+      bb2: {
+          _10 = const {0x1 as *mut [bool; 0]} as *mut () (PtrToPtr);
+          _9 = NonNull::<T>::new_unchecked::precondition_check(move _10) -> [return: bb3, unwind unreachable];
+      }
+  
+      bb3: {
           StorageDead(_8);
+          _11 = const {0x1 as *mut [bool; 0]} as *const [bool; 0] (PointerCoercion(MutToConstPointer));
+          _5 = NonNull::<[bool; 0]> { pointer: _11 };
+          StorageDead(_11);
+          StorageDead(_10);
           StorageDead(_6);
           _4 = Unique::<[bool; 0]> { pointer: move _5, _marker: const PhantomData::<[bool; 0]> };
           StorageDead(_5);
           _3 = move _4 as std::ptr::Unique<[bool]> (PointerCoercion(Unsize));
           StorageDead(_4);
           _2 = Box::<[bool]>(_3, const std::alloc::Global);
+          StorageDead(_9);
           StorageDead(_3);
           _1 = A { foo: move _2 };
           StorageDead(_2);
           _0 = const ();
           drop(_1) -> [return: bb1, unwind unreachable];
       }
-  
-      bb1: {
-          StorageDead(_1);
-          return;
-      }
   }
   
diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-unwind.diff
index 7b6dcf1972b..ee85287882b 100644
--- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-unwind.diff
+++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.DataflowConstProp.64bit.panic-unwind.diff
@@ -24,29 +24,11 @@
                           debug ptr => _6;
                           scope 11 (inlined NonNull::<[bool; 0]>::new_unchecked) {
                               debug ptr => _6;
-                              let mut _8: *const [bool; 0];
-                              let mut _9: *mut [bool; 0];
+                              let mut _8: bool;
+                              let _9: ();
+                              let mut _10: *mut ();
+                              let mut _11: *const [bool; 0];
                               scope 12 {
-                                  scope 13 (inlined NonNull::<T>::new_unchecked::runtime::<[bool; 0]>) {
-                                      debug ptr => _9;
-                                      scope 14 (inlined std::ptr::mut_ptr::<impl *mut [bool; 0]>::is_null) {
-                                          debug self => _9;
-                                          let mut _10: *mut u8;
-                                          scope 15 {
-                                              scope 16 (inlined std::ptr::mut_ptr::<impl *mut T>::is_null::runtime_impl) {
-                                                  debug ptr => _10;
-                                                  scope 17 (inlined std::ptr::mut_ptr::<impl *mut u8>::addr) {
-                                                      debug self => _10;
-                                                      scope 18 {
-                                                          scope 19 (inlined std::ptr::mut_ptr::<impl *mut u8>::cast::<()>) {
-                                                              debug self => _10;
-                                                          }
-                                                      }
-                                                  }
-                                              }
-                                          }
-                                      }
-                                  }
                               }
                           }
                       }
@@ -66,6 +48,7 @@
           StorageLive(_1);
           StorageLive(_2);
           StorageLive(_3);
+          StorageLive(_9);
           StorageLive(_4);
           StorageLive(_5);
           StorageLive(_6);
@@ -73,34 +56,45 @@
           _7 = const 1_usize;
           _6 = const {0x1 as *mut [bool; 0]};
           StorageDead(_7);
-          StorageLive(_8);
-          StorageLive(_9);
           StorageLive(_10);
-          _8 = const {0x1 as *mut [bool; 0]} as *const [bool; 0] (PointerCoercion(MutToConstPointer));
-          _5 = NonNull::<[bool; 0]> { pointer: _8 };
-          StorageDead(_10);
-          StorageDead(_9);
+          StorageLive(_11);
+          StorageLive(_8);
+          _8 = cfg!(debug_assertions);
+          switchInt(move _8) -> [0: bb4, otherwise: bb3];
+      }
+  
+      bb1: {
+          StorageDead(_1);
+          return;
+      }
+  
+      bb2 (cleanup): {
+          resume;
+      }
+  
+      bb3: {
+          _10 = const {0x1 as *mut [bool; 0]} as *mut () (PtrToPtr);
+          _9 = NonNull::<T>::new_unchecked::precondition_check(move _10) -> [return: bb4, unwind unreachable];
+      }
+  
+      bb4: {
           StorageDead(_8);
+          _11 = const {0x1 as *mut [bool; 0]} as *const [bool; 0] (PointerCoercion(MutToConstPointer));
+          _5 = NonNull::<[bool; 0]> { pointer: _11 };
+          StorageDead(_11);
+          StorageDead(_10);
           StorageDead(_6);
           _4 = Unique::<[bool; 0]> { pointer: move _5, _marker: const PhantomData::<[bool; 0]> };
           StorageDead(_5);
           _3 = move _4 as std::ptr::Unique<[bool]> (PointerCoercion(Unsize));
           StorageDead(_4);
           _2 = Box::<[bool]>(_3, const std::alloc::Global);
+          StorageDead(_9);
           StorageDead(_3);
           _1 = A { foo: move _2 };
           StorageDead(_2);
           _0 = const ();
           drop(_1) -> [return: bb1, unwind: bb2];
       }
-  
-      bb1: {
-          StorageDead(_1);
-          return;
-      }
-  
-      bb2 (cleanup): {
-          resume;
-      }
   }
   
diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-abort.diff
index df68ce496fd..4df38d6e61b 100644
--- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-abort.diff
+++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-abort.diff
@@ -24,29 +24,11 @@
                           debug ptr => _6;
                           scope 11 (inlined NonNull::<[bool; 0]>::new_unchecked) {
                               debug ptr => _6;
-                              let mut _8: *const [bool; 0];
-                              let mut _9: *mut [bool; 0];
+                              let mut _8: bool;
+                              let _9: ();
+                              let mut _10: *mut ();
+                              let mut _11: *const [bool; 0];
                               scope 12 {
-                                  scope 13 (inlined NonNull::<T>::new_unchecked::runtime::<[bool; 0]>) {
-                                      debug ptr => _9;
-                                      scope 14 (inlined std::ptr::mut_ptr::<impl *mut [bool; 0]>::is_null) {
-                                          debug self => _9;
-                                          let mut _10: *mut u8;
-                                          scope 15 {
-                                              scope 16 (inlined std::ptr::mut_ptr::<impl *mut T>::is_null::runtime_impl) {
-                                                  debug ptr => _10;
-                                                  scope 17 (inlined std::ptr::mut_ptr::<impl *mut u8>::addr) {
-                                                      debug self => _10;
-                                                      scope 18 {
-                                                          scope 19 (inlined std::ptr::mut_ptr::<impl *mut u8>::cast::<()>) {
-                                                              debug self => _10;
-                                                          }
-                                                      }
-                                                  }
-                                              }
-                                          }
-                                      }
-                                  }
                               }
                           }
                       }
@@ -66,6 +48,7 @@
           StorageLive(_1);
           StorageLive(_2);
           StorageLive(_3);
+          StorageLive(_9);
           StorageLive(_4);
           StorageLive(_5);
           StorageLive(_6);
@@ -75,31 +58,43 @@
 +         _7 = const 1_usize;
 +         _6 = const {0x1 as *mut [bool; 0]};
           StorageDead(_7);
-          StorageLive(_8);
-          StorageLive(_9);
           StorageLive(_10);
--         _8 = _6 as *const [bool; 0] (PointerCoercion(MutToConstPointer));
-+         _8 = const {0x1 as *mut [bool; 0]} as *const [bool; 0] (PointerCoercion(MutToConstPointer));
-          _5 = NonNull::<[bool; 0]> { pointer: _8 };
-          StorageDead(_10);
-          StorageDead(_9);
+          StorageLive(_11);
+          StorageLive(_8);
+          _8 = cfg!(debug_assertions);
+          switchInt(move _8) -> [0: bb3, otherwise: bb2];
+      }
+  
+      bb1: {
+          StorageDead(_1);
+          return;
+      }
+  
+      bb2: {
+-         _10 = _6 as *mut () (PtrToPtr);
++         _10 = const {0x1 as *mut [bool; 0]} as *mut () (PtrToPtr);
+          _9 = NonNull::<T>::new_unchecked::precondition_check(move _10) -> [return: bb3, unwind unreachable];
+      }
+  
+      bb3: {
           StorageDead(_8);
+-         _11 = _6 as *const [bool; 0] (PointerCoercion(MutToConstPointer));
++         _11 = const {0x1 as *mut [bool; 0]} as *const [bool; 0] (PointerCoercion(MutToConstPointer));
+          _5 = NonNull::<[bool; 0]> { pointer: _11 };
+          StorageDead(_11);
+          StorageDead(_10);
           StorageDead(_6);
           _4 = Unique::<[bool; 0]> { pointer: move _5, _marker: const PhantomData::<[bool; 0]> };
           StorageDead(_5);
           _3 = move _4 as std::ptr::Unique<[bool]> (PointerCoercion(Unsize));
           StorageDead(_4);
           _2 = Box::<[bool]>(_3, const std::alloc::Global);
+          StorageDead(_9);
           StorageDead(_3);
           _1 = A { foo: move _2 };
           StorageDead(_2);
           _0 = const ();
           drop(_1) -> [return: bb1, unwind unreachable];
       }
-  
-      bb1: {
-          StorageDead(_1);
-          return;
-      }
   }
   
diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-unwind.diff
index e16ea22091e..6aac30bcd17 100644
--- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-unwind.diff
+++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.32bit.panic-unwind.diff
@@ -24,29 +24,11 @@
                           debug ptr => _6;
                           scope 11 (inlined NonNull::<[bool; 0]>::new_unchecked) {
                               debug ptr => _6;
-                              let mut _8: *const [bool; 0];
-                              let mut _9: *mut [bool; 0];
+                              let mut _8: bool;
+                              let _9: ();
+                              let mut _10: *mut ();
+                              let mut _11: *const [bool; 0];
                               scope 12 {
-                                  scope 13 (inlined NonNull::<T>::new_unchecked::runtime::<[bool; 0]>) {
-                                      debug ptr => _9;
-                                      scope 14 (inlined std::ptr::mut_ptr::<impl *mut [bool; 0]>::is_null) {
-                                          debug self => _9;
-                                          let mut _10: *mut u8;
-                                          scope 15 {
-                                              scope 16 (inlined std::ptr::mut_ptr::<impl *mut T>::is_null::runtime_impl) {
-                                                  debug ptr => _10;
-                                                  scope 17 (inlined std::ptr::mut_ptr::<impl *mut u8>::addr) {
-                                                      debug self => _10;
-                                                      scope 18 {
-                                                          scope 19 (inlined std::ptr::mut_ptr::<impl *mut u8>::cast::<()>) {
-                                                              debug self => _10;
-                                                          }
-                                                      }
-                                                  }
-                                              }
-                                          }
-                                      }
-                                  }
                               }
                           }
                       }
@@ -66,6 +48,7 @@
           StorageLive(_1);
           StorageLive(_2);
           StorageLive(_3);
+          StorageLive(_9);
           StorageLive(_4);
           StorageLive(_5);
           StorageLive(_6);
@@ -75,35 +58,47 @@
 +         _7 = const 1_usize;
 +         _6 = const {0x1 as *mut [bool; 0]};
           StorageDead(_7);
-          StorageLive(_8);
-          StorageLive(_9);
           StorageLive(_10);
--         _8 = _6 as *const [bool; 0] (PointerCoercion(MutToConstPointer));
-+         _8 = const {0x1 as *mut [bool; 0]} as *const [bool; 0] (PointerCoercion(MutToConstPointer));
-          _5 = NonNull::<[bool; 0]> { pointer: _8 };
-          StorageDead(_10);
-          StorageDead(_9);
+          StorageLive(_11);
+          StorageLive(_8);
+          _8 = cfg!(debug_assertions);
+          switchInt(move _8) -> [0: bb4, otherwise: bb3];
+      }
+  
+      bb1: {
+          StorageDead(_1);
+          return;
+      }
+  
+      bb2 (cleanup): {
+          resume;
+      }
+  
+      bb3: {
+-         _10 = _6 as *mut () (PtrToPtr);
++         _10 = const {0x1 as *mut [bool; 0]} as *mut () (PtrToPtr);
+          _9 = NonNull::<T>::new_unchecked::precondition_check(move _10) -> [return: bb4, unwind unreachable];
+      }
+  
+      bb4: {
           StorageDead(_8);
+-         _11 = _6 as *const [bool; 0] (PointerCoercion(MutToConstPointer));
++         _11 = const {0x1 as *mut [bool; 0]} as *const [bool; 0] (PointerCoercion(MutToConstPointer));
+          _5 = NonNull::<[bool; 0]> { pointer: _11 };
+          StorageDead(_11);
+          StorageDead(_10);
           StorageDead(_6);
           _4 = Unique::<[bool; 0]> { pointer: move _5, _marker: const PhantomData::<[bool; 0]> };
           StorageDead(_5);
           _3 = move _4 as std::ptr::Unique<[bool]> (PointerCoercion(Unsize));
           StorageDead(_4);
           _2 = Box::<[bool]>(_3, const std::alloc::Global);
+          StorageDead(_9);
           StorageDead(_3);
           _1 = A { foo: move _2 };
           StorageDead(_2);
           _0 = const ();
           drop(_1) -> [return: bb1, unwind: bb2];
       }
-  
-      bb1: {
-          StorageDead(_1);
-          return;
-      }
-  
-      bb2 (cleanup): {
-          resume;
-      }
   }
   
diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-abort.diff
index df68ce496fd..4df38d6e61b 100644
--- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-abort.diff
+++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-abort.diff
@@ -24,29 +24,11 @@
                           debug ptr => _6;
                           scope 11 (inlined NonNull::<[bool; 0]>::new_unchecked) {
                               debug ptr => _6;
-                              let mut _8: *const [bool; 0];
-                              let mut _9: *mut [bool; 0];
+                              let mut _8: bool;
+                              let _9: ();
+                              let mut _10: *mut ();
+                              let mut _11: *const [bool; 0];
                               scope 12 {
-                                  scope 13 (inlined NonNull::<T>::new_unchecked::runtime::<[bool; 0]>) {
-                                      debug ptr => _9;
-                                      scope 14 (inlined std::ptr::mut_ptr::<impl *mut [bool; 0]>::is_null) {
-                                          debug self => _9;
-                                          let mut _10: *mut u8;
-                                          scope 15 {
-                                              scope 16 (inlined std::ptr::mut_ptr::<impl *mut T>::is_null::runtime_impl) {
-                                                  debug ptr => _10;
-                                                  scope 17 (inlined std::ptr::mut_ptr::<impl *mut u8>::addr) {
-                                                      debug self => _10;
-                                                      scope 18 {
-                                                          scope 19 (inlined std::ptr::mut_ptr::<impl *mut u8>::cast::<()>) {
-                                                              debug self => _10;
-                                                          }
-                                                      }
-                                                  }
-                                              }
-                                          }
-                                      }
-                                  }
                               }
                           }
                       }
@@ -66,6 +48,7 @@
           StorageLive(_1);
           StorageLive(_2);
           StorageLive(_3);
+          StorageLive(_9);
           StorageLive(_4);
           StorageLive(_5);
           StorageLive(_6);
@@ -75,31 +58,43 @@
 +         _7 = const 1_usize;
 +         _6 = const {0x1 as *mut [bool; 0]};
           StorageDead(_7);
-          StorageLive(_8);
-          StorageLive(_9);
           StorageLive(_10);
--         _8 = _6 as *const [bool; 0] (PointerCoercion(MutToConstPointer));
-+         _8 = const {0x1 as *mut [bool; 0]} as *const [bool; 0] (PointerCoercion(MutToConstPointer));
-          _5 = NonNull::<[bool; 0]> { pointer: _8 };
-          StorageDead(_10);
-          StorageDead(_9);
+          StorageLive(_11);
+          StorageLive(_8);
+          _8 = cfg!(debug_assertions);
+          switchInt(move _8) -> [0: bb3, otherwise: bb2];
+      }
+  
+      bb1: {
+          StorageDead(_1);
+          return;
+      }
+  
+      bb2: {
+-         _10 = _6 as *mut () (PtrToPtr);
++         _10 = const {0x1 as *mut [bool; 0]} as *mut () (PtrToPtr);
+          _9 = NonNull::<T>::new_unchecked::precondition_check(move _10) -> [return: bb3, unwind unreachable];
+      }
+  
+      bb3: {
           StorageDead(_8);
+-         _11 = _6 as *const [bool; 0] (PointerCoercion(MutToConstPointer));
++         _11 = const {0x1 as *mut [bool; 0]} as *const [bool; 0] (PointerCoercion(MutToConstPointer));
+          _5 = NonNull::<[bool; 0]> { pointer: _11 };
+          StorageDead(_11);
+          StorageDead(_10);
           StorageDead(_6);
           _4 = Unique::<[bool; 0]> { pointer: move _5, _marker: const PhantomData::<[bool; 0]> };
           StorageDead(_5);
           _3 = move _4 as std::ptr::Unique<[bool]> (PointerCoercion(Unsize));
           StorageDead(_4);
           _2 = Box::<[bool]>(_3, const std::alloc::Global);
+          StorageDead(_9);
           StorageDead(_3);
           _1 = A { foo: move _2 };
           StorageDead(_2);
           _0 = const ();
           drop(_1) -> [return: bb1, unwind unreachable];
       }
-  
-      bb1: {
-          StorageDead(_1);
-          return;
-      }
   }
   
diff --git a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-unwind.diff
index e16ea22091e..6aac30bcd17 100644
--- a/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-unwind.diff
+++ b/tests/mir-opt/dataflow-const-prop/default_boxed_slice.main.GVN.64bit.panic-unwind.diff
@@ -24,29 +24,11 @@
                           debug ptr => _6;
                           scope 11 (inlined NonNull::<[bool; 0]>::new_unchecked) {
                               debug ptr => _6;
-                              let mut _8: *const [bool; 0];
-                              let mut _9: *mut [bool; 0];
+                              let mut _8: bool;
+                              let _9: ();
+                              let mut _10: *mut ();
+                              let mut _11: *const [bool; 0];
                               scope 12 {
-                                  scope 13 (inlined NonNull::<T>::new_unchecked::runtime::<[bool; 0]>) {
-                                      debug ptr => _9;
-                                      scope 14 (inlined std::ptr::mut_ptr::<impl *mut [bool; 0]>::is_null) {
-                                          debug self => _9;
-                                          let mut _10: *mut u8;
-                                          scope 15 {
-                                              scope 16 (inlined std::ptr::mut_ptr::<impl *mut T>::is_null::runtime_impl) {
-                                                  debug ptr => _10;
-                                                  scope 17 (inlined std::ptr::mut_ptr::<impl *mut u8>::addr) {
-                                                      debug self => _10;
-                                                      scope 18 {
-                                                          scope 19 (inlined std::ptr::mut_ptr::<impl *mut u8>::cast::<()>) {
-                                                              debug self => _10;
-                                                          }
-                                                      }
-                                                  }
-                                              }
-                                          }
-                                      }
-                                  }
                               }
                           }
                       }
@@ -66,6 +48,7 @@
           StorageLive(_1);
           StorageLive(_2);
           StorageLive(_3);
+          StorageLive(_9);
           StorageLive(_4);
           StorageLive(_5);
           StorageLive(_6);
@@ -75,35 +58,47 @@
 +         _7 = const 1_usize;
 +         _6 = const {0x1 as *mut [bool; 0]};
           StorageDead(_7);
-          StorageLive(_8);
-          StorageLive(_9);
           StorageLive(_10);
--         _8 = _6 as *const [bool; 0] (PointerCoercion(MutToConstPointer));
-+         _8 = const {0x1 as *mut [bool; 0]} as *const [bool; 0] (PointerCoercion(MutToConstPointer));
-          _5 = NonNull::<[bool; 0]> { pointer: _8 };
-          StorageDead(_10);
-          StorageDead(_9);
+          StorageLive(_11);
+          StorageLive(_8);
+          _8 = cfg!(debug_assertions);
+          switchInt(move _8) -> [0: bb4, otherwise: bb3];
+      }
+  
+      bb1: {
+          StorageDead(_1);
+          return;
+      }
+  
+      bb2 (cleanup): {
+          resume;
+      }
+  
+      bb3: {
+-         _10 = _6 as *mut () (PtrToPtr);
++         _10 = const {0x1 as *mut [bool; 0]} as *mut () (PtrToPtr);
+          _9 = NonNull::<T>::new_unchecked::precondition_check(move _10) -> [return: bb4, unwind unreachable];
+      }
+  
+      bb4: {
           StorageDead(_8);
+-         _11 = _6 as *const [bool; 0] (PointerCoercion(MutToConstPointer));
++         _11 = const {0x1 as *mut [bool; 0]} as *const [bool; 0] (PointerCoercion(MutToConstPointer));
+          _5 = NonNull::<[bool; 0]> { pointer: _11 };
+          StorageDead(_11);
+          StorageDead(_10);
           StorageDead(_6);
           _4 = Unique::<[bool; 0]> { pointer: move _5, _marker: const PhantomData::<[bool; 0]> };
           StorageDead(_5);
           _3 = move _4 as std::ptr::Unique<[bool]> (PointerCoercion(Unsize));
           StorageDead(_4);
           _2 = Box::<[bool]>(_3, const std::alloc::Global);
+          StorageDead(_9);
           StorageDead(_3);
           _1 = A { foo: move _2 };
           StorageDead(_2);
           _0 = const ();
           drop(_1) -> [return: bb1, unwind: bb2];
       }
-  
-      bb1: {
-          StorageDead(_1);
-          return;
-      }
-  
-      bb2 (cleanup): {
-          resume;
-      }
   }
   
diff --git a/tests/mir-opt/inline/unwrap_unchecked.rs b/tests/mir-opt/inline/unwrap_unchecked.rs
index be133706e5c..1adf2224d97 100644
--- a/tests/mir-opt/inline/unwrap_unchecked.rs
+++ b/tests/mir-opt/inline/unwrap_unchecked.rs
@@ -2,7 +2,7 @@
 
 // EMIT_MIR_FOR_EACH_PANIC_STRATEGY
 // ignore-debug: the debug assertions prevent the inlining we are testing for
-// compile-flags: -Zmir-opt-level=2 -Zinline-mir
+// compile-flags: -Zmir-opt-level=2 -Zinline-mir -Cdebug-assertions=no
 
 // EMIT_MIR unwrap_unchecked.unwrap_unchecked.Inline.diff
 // EMIT_MIR unwrap_unchecked.unwrap_unchecked.PreCodegen.after.mir
diff --git a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-abort.diff b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-abort.diff
index 2a36ad9230e..9358a64b4fa 100644
--- a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-abort.diff
+++ b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-abort.diff
@@ -7,41 +7,44 @@
       let mut _2: std::option::Option<T>;
 +     scope 1 (inlined #[track_caller] Option::<T>::unwrap_unchecked) {
 +         debug self => _2;
-+         let mut _3: &std::option::Option<T>;
-+         let mut _4: isize;
-+         let mut _5: bool;
++         let mut _3: isize;
 +         scope 2 {
 +             debug val => _0;
 +         }
 +         scope 3 {
-+             scope 5 (inlined unreachable_unchecked) {
-+                 scope 6 {
-+                     scope 7 (inlined unreachable_unchecked::runtime) {
-+                     }
++             scope 4 (inlined unreachable_unchecked) {
++                 let mut _4: bool;
++                 let _5: ();
++                 scope 5 {
 +                 }
 +             }
 +         }
-+         scope 4 (inlined Option::<T>::is_some) {
-+             debug self => _3;
-+         }
 +     }
   
       bb0: {
           StorageLive(_2);
           _2 = move _1;
 -         _0 = Option::<T>::unwrap_unchecked(move _2) -> [return: bb1, unwind unreachable];
--     }
-- 
--     bb1: {
 +         StorageLive(_3);
-+         StorageLive(_4);
 +         StorageLive(_5);
-+         _4 = discriminant(_2);
-+         _5 = Eq(_4, const 1_isize);
-+         assume(move _5);
++         _3 = discriminant(_2);
++         switchInt(move _3) -> [0: bb1, 1: bb3, otherwise: bb2];
+      }
+  
+      bb1: {
++         StorageLive(_4);
++         _4 = cfg!(debug_assertions);
++         assume(_4);
++         _5 = unreachable_unchecked::precondition_check() -> [return: bb2, unwind unreachable];
++     }
++ 
++     bb2: {
++         unreachable;
++     }
++ 
++     bb3: {
 +         _0 = move ((_2 as Some).0: T);
 +         StorageDead(_5);
-+         StorageDead(_4);
 +         StorageDead(_3);
           StorageDead(_2);
           return;
diff --git a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-unwind.diff b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-unwind.diff
index 14c8c671d3f..ac33c126155 100644
--- a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-unwind.diff
+++ b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-unwind.diff
@@ -7,48 +7,51 @@
       let mut _2: std::option::Option<T>;
 +     scope 1 (inlined #[track_caller] Option::<T>::unwrap_unchecked) {
 +         debug self => _2;
-+         let mut _3: &std::option::Option<T>;
-+         let mut _4: isize;
-+         let mut _5: bool;
++         let mut _3: isize;
 +         scope 2 {
 +             debug val => _0;
 +         }
 +         scope 3 {
-+             scope 5 (inlined unreachable_unchecked) {
-+                 scope 6 {
-+                     scope 7 (inlined unreachable_unchecked::runtime) {
-+                     }
++             scope 4 (inlined unreachable_unchecked) {
++                 let mut _4: bool;
++                 let _5: ();
++                 scope 5 {
 +                 }
 +             }
 +         }
-+         scope 4 (inlined Option::<T>::is_some) {
-+             debug self => _3;
-+         }
 +     }
   
       bb0: {
           StorageLive(_2);
           _2 = move _1;
 -         _0 = Option::<T>::unwrap_unchecked(move _2) -> [return: bb1, unwind: bb2];
--     }
-- 
--     bb1: {
 +         StorageLive(_3);
-+         StorageLive(_4);
 +         StorageLive(_5);
-+         _4 = discriminant(_2);
-+         _5 = Eq(_4, const 1_isize);
-+         assume(move _5);
++         _3 = discriminant(_2);
++         switchInt(move _3) -> [0: bb1, 1: bb3, otherwise: bb2];
+      }
+  
+      bb1: {
+-         StorageDead(_2);
+-         return;
++         StorageLive(_4);
++         _4 = cfg!(debug_assertions);
++         assume(_4);
++         _5 = unreachable_unchecked::precondition_check() -> [return: bb2, unwind unreachable];
+      }
+  
+-     bb2 (cleanup): {
+-         resume;
++     bb2: {
++         unreachable;
++     }
++ 
++     bb3: {
 +         _0 = move ((_2 as Some).0: T);
 +         StorageDead(_5);
-+         StorageDead(_4);
 +         StorageDead(_3);
-          StorageDead(_2);
-          return;
--     }
-- 
--     bb2 (cleanup): {
--         resume;
++         StorageDead(_2);
++         return;
       }
   }
   
diff --git a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-abort.mir b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-abort.mir
index d6a608476df..8ec65935c66 100644
--- a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-abort.mir
+++ b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-abort.mir
@@ -6,35 +6,39 @@ fn unwrap_unchecked(_1: Option<T>) -> T {
     scope 1 (inlined #[track_caller] Option::<T>::unwrap_unchecked) {
         debug self => _1;
         let mut _2: isize;
-        let mut _3: bool;
-        let mut _4: &std::option::Option<T>;
         scope 2 {
             debug val => _0;
         }
         scope 3 {
-            scope 5 (inlined unreachable_unchecked) {
-                scope 6 {
-                    scope 7 (inlined unreachable_unchecked::runtime) {
-                    }
+            scope 4 (inlined unreachable_unchecked) {
+                let mut _3: bool;
+                let _4: ();
+                scope 5 {
                 }
             }
         }
-        scope 4 (inlined Option::<T>::is_some) {
-            debug self => _4;
-        }
     }
 
     bb0: {
-        StorageLive(_4);
         StorageLive(_2);
-        StorageLive(_3);
         _2 = discriminant(_1);
-        _3 = Eq(_2, const 1_isize);
-        assume(move _3);
+        switchInt(move _2) -> [0: bb1, 1: bb2, otherwise: bb3];
+    }
+
+    bb1: {
+        StorageLive(_3);
+        _3 = cfg!(debug_assertions);
+        assume(_3);
+        _4 = unreachable_unchecked::precondition_check() -> [return: bb3, unwind unreachable];
+    }
+
+    bb2: {
         _0 = ((_1 as Some).0: T);
-        StorageDead(_3);
         StorageDead(_2);
-        StorageDead(_4);
         return;
     }
+
+    bb3: {
+        unreachable;
+    }
 }
diff --git a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-unwind.mir
index d6a608476df..8ec65935c66 100644
--- a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-unwind.mir
+++ b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-unwind.mir
@@ -6,35 +6,39 @@ fn unwrap_unchecked(_1: Option<T>) -> T {
     scope 1 (inlined #[track_caller] Option::<T>::unwrap_unchecked) {
         debug self => _1;
         let mut _2: isize;
-        let mut _3: bool;
-        let mut _4: &std::option::Option<T>;
         scope 2 {
             debug val => _0;
         }
         scope 3 {
-            scope 5 (inlined unreachable_unchecked) {
-                scope 6 {
-                    scope 7 (inlined unreachable_unchecked::runtime) {
-                    }
+            scope 4 (inlined unreachable_unchecked) {
+                let mut _3: bool;
+                let _4: ();
+                scope 5 {
                 }
             }
         }
-        scope 4 (inlined Option::<T>::is_some) {
-            debug self => _4;
-        }
     }
 
     bb0: {
-        StorageLive(_4);
         StorageLive(_2);
-        StorageLive(_3);
         _2 = discriminant(_1);
-        _3 = Eq(_2, const 1_isize);
-        assume(move _3);
+        switchInt(move _2) -> [0: bb1, 1: bb2, otherwise: bb3];
+    }
+
+    bb1: {
+        StorageLive(_3);
+        _3 = cfg!(debug_assertions);
+        assume(_3);
+        _4 = unreachable_unchecked::precondition_check() -> [return: bb3, unwind unreachable];
+    }
+
+    bb2: {
         _0 = ((_1 as Some).0: T);
-        StorageDead(_3);
         StorageDead(_2);
-        StorageDead(_4);
         return;
     }
+
+    bb3: {
+        unreachable;
+    }
 }
diff --git a/tests/mir-opt/pre-codegen/duplicate_switch_targets.ub_if_b.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/duplicate_switch_targets.ub_if_b.PreCodegen.after.mir
index 0114309dbb5..7c038b0ee88 100644
--- a/tests/mir-opt/pre-codegen/duplicate_switch_targets.ub_if_b.PreCodegen.after.mir
+++ b/tests/mir-opt/pre-codegen/duplicate_switch_targets.ub_if_b.PreCodegen.after.mir
@@ -4,19 +4,31 @@ fn ub_if_b(_1: Thing) -> Thing {
     debug t => _1;
     let mut _0: Thing;
     let mut _2: isize;
-    let mut _3: bool;
     scope 1 (inlined unreachable_unchecked) {
+        let mut _3: bool;
+        let _4: ();
         scope 2 {
-            scope 3 (inlined unreachable_unchecked::runtime) {
-            }
         }
     }
 
     bb0: {
         _2 = discriminant(_1);
-        _3 = Eq(_2, const 0_isize);
-        assume(move _3);
+        switchInt(move _2) -> [0: bb1, 1: bb2, otherwise: bb3];
+    }
+
+    bb1: {
         _0 = move _1;
         return;
     }
+
+    bb2: {
+        StorageLive(_3);
+        _3 = cfg!(debug_assertions);
+        assume(_3);
+        _4 = unreachable_unchecked::precondition_check() -> [return: bb3, unwind unreachable];
+    }
+
+    bb3: {
+        unreachable;
+    }
 }
diff --git a/tests/mir-opt/pre-codegen/mem_replace.manual_replace.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/mem_replace.manual_replace.PreCodegen.after.panic-abort.mir
index 3ca24e152a4..3ca24e152a4 100644
--- a/tests/mir-opt/pre-codegen/mem_replace.manual_replace.PreCodegen.after.mir
+++ b/tests/mir-opt/pre-codegen/mem_replace.manual_replace.PreCodegen.after.panic-abort.mir
diff --git a/tests/mir-opt/pre-codegen/mem_replace.manual_replace.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/mem_replace.manual_replace.PreCodegen.after.panic-unwind.mir
new file mode 100644
index 00000000000..3ca24e152a4
--- /dev/null
+++ b/tests/mir-opt/pre-codegen/mem_replace.manual_replace.PreCodegen.after.panic-unwind.mir
@@ -0,0 +1,16 @@
+// MIR for `manual_replace` after PreCodegen
+
+fn manual_replace(_1: &mut u32, _2: u32) -> u32 {
+    debug r => _1;
+    debug v => _2;
+    let mut _0: u32;
+    scope 1 {
+        debug temp => _0;
+    }
+
+    bb0: {
+        _0 = (*_1);
+        (*_1) = _2;
+        return;
+    }
+}
diff --git a/tests/mir-opt/pre-codegen/mem_replace.mem_replace.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/mem_replace.mem_replace.PreCodegen.after.mir
deleted file mode 100644
index f0cb4ca31fe..00000000000
--- a/tests/mir-opt/pre-codegen/mem_replace.mem_replace.PreCodegen.after.mir
+++ /dev/null
@@ -1,66 +0,0 @@
-// MIR for `mem_replace` after PreCodegen
-
-fn mem_replace(_1: &mut u32, _2: u32) -> u32 {
-    debug r => _1;
-    debug v => _2;
-    let mut _0: u32;
-    scope 1 (inlined std::mem::replace::<u32>) {
-        debug dest => _1;
-        debug src => _2;
-        scope 2 {
-            scope 3 {
-                debug result => _0;
-                scope 16 (inlined std::ptr::write::<u32>) {
-                    debug dst => _1;
-                    debug src => _2;
-                    scope 17 {
-                    }
-                }
-            }
-            scope 4 (inlined std::ptr::read::<u32>) {
-                debug src => _1;
-                let mut _3: *const u32;
-                scope 5 {
-                    scope 6 (inlined std::ptr::read::runtime::<u32>) {
-                        debug src => _3;
-                        scope 7 (inlined intrinsics::is_aligned_and_not_null::<u32>) {
-                            debug ptr => _3;
-                            scope 8 (inlined std::ptr::const_ptr::<impl *const u32>::is_null) {
-                                debug self => _3;
-                                let mut _4: *const u8;
-                                scope 9 {
-                                    scope 10 (inlined std::ptr::const_ptr::<impl *const T>::is_null::runtime_impl) {
-                                        debug ptr => _4;
-                                        scope 11 (inlined std::ptr::const_ptr::<impl *const u8>::addr) {
-                                            debug self => _4;
-                                            scope 12 {
-                                                scope 13 (inlined std::ptr::const_ptr::<impl *const u8>::cast::<()>) {
-                                                    debug self => _4;
-                                                }
-                                            }
-                                        }
-                                    }
-                                }
-                            }
-                            scope 14 (inlined std::ptr::const_ptr::<impl *const u32>::is_aligned) {
-                                debug self => _3;
-                                scope 15 (inlined align_of::<u32>) {
-                                }
-                            }
-                        }
-                    }
-                }
-            }
-        }
-    }
-
-    bb0: {
-        StorageLive(_3);
-        StorageLive(_4);
-        _0 = (*_1);
-        StorageDead(_4);
-        StorageDead(_3);
-        (*_1) = _2;
-        return;
-    }
-}
diff --git a/tests/mir-opt/pre-codegen/mem_replace.mem_replace.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/mem_replace.mem_replace.PreCodegen.after.panic-abort.mir
new file mode 100644
index 00000000000..26919dd98dd
--- /dev/null
+++ b/tests/mir-opt/pre-codegen/mem_replace.mem_replace.PreCodegen.after.panic-abort.mir
@@ -0,0 +1,33 @@
+// MIR for `mem_replace` after PreCodegen
+
+fn mem_replace(_1: &mut u32, _2: u32) -> u32 {
+    debug r => _1;
+    debug v => _2;
+    let mut _0: u32;
+    scope 1 (inlined std::mem::replace::<u32>) {
+        debug dest => _1;
+        debug src => _2;
+        scope 2 {
+            scope 3 {
+                debug result => _0;
+                scope 6 (inlined std::ptr::write::<u32>) {
+                    debug dst => _1;
+                    debug src => _2;
+                    scope 7 {
+                    }
+                }
+            }
+            scope 4 (inlined std::ptr::read::<u32>) {
+                debug src => _1;
+                scope 5 {
+                }
+            }
+        }
+    }
+
+    bb0: {
+        _0 = (*_1);
+        (*_1) = _2;
+        return;
+    }
+}
diff --git a/tests/mir-opt/pre-codegen/mem_replace.mem_replace.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/mem_replace.mem_replace.PreCodegen.after.panic-unwind.mir
new file mode 100644
index 00000000000..26919dd98dd
--- /dev/null
+++ b/tests/mir-opt/pre-codegen/mem_replace.mem_replace.PreCodegen.after.panic-unwind.mir
@@ -0,0 +1,33 @@
+// MIR for `mem_replace` after PreCodegen
+
+fn mem_replace(_1: &mut u32, _2: u32) -> u32 {
+    debug r => _1;
+    debug v => _2;
+    let mut _0: u32;
+    scope 1 (inlined std::mem::replace::<u32>) {
+        debug dest => _1;
+        debug src => _2;
+        scope 2 {
+            scope 3 {
+                debug result => _0;
+                scope 6 (inlined std::ptr::write::<u32>) {
+                    debug dst => _1;
+                    debug src => _2;
+                    scope 7 {
+                    }
+                }
+            }
+            scope 4 (inlined std::ptr::read::<u32>) {
+                debug src => _1;
+                scope 5 {
+                }
+            }
+        }
+    }
+
+    bb0: {
+        _0 = (*_1);
+        (*_1) = _2;
+        return;
+    }
+}
diff --git a/tests/mir-opt/pre-codegen/mem_replace.rs b/tests/mir-opt/pre-codegen/mem_replace.rs
index 18c4653d4c6..551afea3ba5 100644
--- a/tests/mir-opt/pre-codegen/mem_replace.rs
+++ b/tests/mir-opt/pre-codegen/mem_replace.rs
@@ -1,7 +1,8 @@
 // skip-filecheck
-// compile-flags: -O -C debuginfo=0 -Zmir-opt-level=2
+// compile-flags: -O -C debuginfo=0 -Zmir-opt-level=2 -Zinline-mir
 // only-64bit
 // ignore-debug the standard library debug assertions leak into this test
+// EMIT_MIR_FOR_EACH_PANIC_STRATEGY
 
 #![crate_type = "lib"]
 
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 26b2663fa35..4906c86f8ed 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,171 +4,165 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () {
     debug slice => _1;
     debug f => _2;
     let mut _0: ();
-    let mut _13: std::slice::Iter<'_, T>;
-    let mut _14: std::iter::Enumerate<std::slice::Iter<'_, T>>;
-    let mut _15: std::iter::Enumerate<std::slice::Iter<'_, T>>;
-    let mut _16: &mut std::iter::Enumerate<std::slice::Iter<'_, T>>;
-    let mut _17: std::option::Option<(usize, &T)>;
-    let mut _18: isize;
-    let mut _21: &impl Fn(usize, &T);
-    let mut _22: (usize, &T);
-    let _23: ();
+    let mut _15: std::slice::Iter<'_, T>;
+    let mut _16: std::iter::Enumerate<std::slice::Iter<'_, T>>;
+    let mut _17: std::iter::Enumerate<std::slice::Iter<'_, T>>;
+    let mut _18: &mut std::iter::Enumerate<std::slice::Iter<'_, T>>;
+    let mut _19: std::option::Option<(usize, &T)>;
+    let mut _20: isize;
+    let mut _23: &impl Fn(usize, &T);
+    let mut _24: (usize, &T);
+    let _25: ();
     scope 1 {
-        debug iter => _15;
-        let _19: usize;
-        let _20: &T;
+        debug iter => _17;
+        let _21: usize;
+        let _22: &T;
         scope 2 {
-            debug i => _19;
-            debug x => _20;
+            debug i => _21;
+            debug x => _22;
         }
     }
     scope 3 (inlined core::slice::<impl [T]>::iter) {
         debug self => _1;
         scope 4 (inlined std::slice::Iter::<'_, T>::new) {
             debug slice => _1;
-            let _4: *const T;
-            let mut _5: bool;
-            let mut _6: usize;
-            let mut _8: usize;
-            let mut _9: *mut T;
-            let mut _11: std::ptr::NonNull<T>;
-            let mut _12: *const T;
+            let _3: usize;
+            let mut _5: std::ptr::NonNull<[T]>;
+            let mut _10: bool;
+            let mut _11: *mut T;
+            let mut _12: *mut T;
+            let mut _14: *const T;
             scope 5 {
-                debug ptr => _4;
+                debug len => _3;
+                let _9: std::ptr::NonNull<T>;
                 scope 6 {
-                    let _7: *const T;
+                    debug ptr => _9;
                     scope 7 {
-                        debug end_or_len => _7;
-                        scope 13 (inlined NonNull::<T>::new_unchecked) {
-                            debug ptr => _9;
-                            let mut _10: *const T;
-                            let mut _24: *mut T;
-                            scope 14 {
-                                scope 15 (inlined NonNull::<T>::new_unchecked::runtime::<T>) {
-                                    debug ptr => _24;
-                                    scope 16 (inlined std::ptr::mut_ptr::<impl *mut T>::is_null) {
-                                        debug self => _24;
-                                        let mut _25: *mut u8;
-                                        scope 17 {
-                                            scope 18 (inlined std::ptr::mut_ptr::<impl *mut T>::is_null::runtime_impl) {
-                                                debug ptr => _25;
-                                                scope 19 (inlined std::ptr::mut_ptr::<impl *mut u8>::addr) {
-                                                    debug self => _25;
-                                                    scope 20 {
-                                                        scope 21 (inlined std::ptr::mut_ptr::<impl *mut u8>::cast::<()>) {
-                                                            debug self => _25;
-                                                        }
-                                                    }
-                                                }
-                                            }
-                                        }
-                                    }
-                                }
+                        let _13: *const T;
+                        scope 8 {
+                            debug end_or_len => _13;
+                        }
+                        scope 14 (inlined invalid::<T>) {
+                            debug addr => _3;
+                            scope 15 {
                             }
                         }
-                    }
-                    scope 9 (inlined invalid::<T>) {
-                        debug addr => _8;
-                        scope 10 {
+                        scope 16 (inlined NonNull::<T>::as_ptr) {
+                            debug self => _9;
+                        }
+                        scope 17 (inlined std::ptr::mut_ptr::<impl *mut T>::add) {
+                            debug self => _11;
+                            debug count => _3;
+                            scope 18 {
+                            }
                         }
                     }
-                    scope 11 (inlined std::ptr::const_ptr::<impl *const T>::add) {
-                        debug self => _4;
-                        debug count => _6;
-                        scope 12 {
+                }
+                scope 9 (inlined <NonNull<[T]> as From<&[T]>>::from) {
+                    debug reference => _1;
+                    let mut _4: *const [T];
+                    scope 10 {
+                    }
+                }
+                scope 11 (inlined NonNull::<[T]>::cast::<T>) {
+                    debug self => _5;
+                    let mut _6: *mut [T];
+                    let mut _7: *mut T;
+                    let mut _8: *const T;
+                    scope 12 {
+                        scope 13 (inlined NonNull::<[T]>::as_ptr) {
+                            debug self => _5;
                         }
                     }
                 }
             }
-            scope 8 (inlined core::slice::<impl [T]>::as_ptr) {
-                debug self => _1;
-                let mut _3: *const [T];
-            }
         }
     }
-    scope 22 (inlined <std::slice::Iter<'_, T> as Iterator>::enumerate) {
-        debug self => _13;
-        scope 23 (inlined Enumerate::<std::slice::Iter<'_, T>>::new) {
-            debug iter => _13;
+    scope 19 (inlined <std::slice::Iter<'_, T> as Iterator>::enumerate) {
+        debug self => _15;
+        scope 20 (inlined Enumerate::<std::slice::Iter<'_, T>>::new) {
+            debug iter => _15;
         }
     }
-    scope 24 (inlined <Enumerate<std::slice::Iter<'_, T>> as IntoIterator>::into_iter) {
-        debug self => _14;
+    scope 21 (inlined <Enumerate<std::slice::Iter<'_, T>> as IntoIterator>::into_iter) {
+        debug self => _16;
     }
 
     bb0: {
-        StorageLive(_13);
-        StorageLive(_4);
+        StorageLive(_15);
         StorageLive(_3);
-        _3 = &raw const (*_1);
-        _4 = move _3 as *const T (PtrToPtr);
-        StorageDead(_3);
-        StorageLive(_7);
+        StorageLive(_9);
+        StorageLive(_4);
+        StorageLive(_8);
+        _3 = Len((*_1));
         StorageLive(_5);
-        _5 = const _;
-        switchInt(move _5) -> [0: bb1, otherwise: bb2];
+        _4 = &raw const (*_1);
+        _5 = NonNull::<[T]> { pointer: _4 };
+        StorageLive(_7);
+        StorageLive(_6);
+        _6 = _4 as *mut [T] (PtrToPtr);
+        _7 = move _6 as *mut T (PtrToPtr);
+        _8 = move _7 as *const T (PointerCoercion(MutToConstPointer));
+        StorageDead(_6);
+        StorageDead(_7);
+        _9 = NonNull::<T> { pointer: _8 };
+        StorageDead(_5);
+        StorageLive(_13);
+        StorageLive(_10);
+        _10 = const _;
+        switchInt(move _10) -> [0: bb1, otherwise: bb2];
     }
 
     bb1: {
-        StorageLive(_6);
-        _6 = Len((*_1));
-        _7 = Offset(_4, _6);
-        StorageDead(_6);
+        StorageLive(_12);
+        StorageLive(_11);
+        _11 = _8 as *mut T (PtrToPtr);
+        _12 = Offset(_11, _3);
+        StorageDead(_11);
+        _13 = move _12 as *const T (PointerCoercion(MutToConstPointer));
+        StorageDead(_12);
         goto -> bb3;
     }
 
     bb2: {
-        StorageLive(_8);
-        _8 = Len((*_1));
-        _7 = _8 as *const T (Transmute);
-        StorageDead(_8);
+        _13 = _3 as *const T (Transmute);
         goto -> bb3;
     }
 
     bb3: {
-        StorageDead(_5);
-        StorageLive(_11);
-        StorageLive(_9);
-        _9 = _4 as *mut T (PtrToPtr);
-        StorageLive(_10);
-        StorageLive(_24);
-        StorageLive(_25);
-        _10 = _9 as *const T (PointerCoercion(MutToConstPointer));
-        _11 = NonNull::<T> { pointer: _10 };
-        StorageDead(_25);
-        StorageDead(_24);
         StorageDead(_10);
-        StorageDead(_9);
-        StorageLive(_12);
-        _12 = _7;
-        _13 = std::slice::Iter::<'_, T> { ptr: move _11, end_or_len: move _12, _marker: const ZeroSized: PhantomData<&T> };
-        StorageDead(_12);
-        StorageDead(_11);
-        StorageDead(_7);
-        StorageDead(_4);
-        _14 = Enumerate::<std::slice::Iter<'_, T>> { iter: _13, count: const 0_usize };
+        StorageLive(_14);
+        _14 = _13;
+        _15 = std::slice::Iter::<'_, T> { ptr: _9, end_or_len: move _14, _marker: const ZeroSized: PhantomData<&T> };
+        StorageDead(_14);
         StorageDead(_13);
-        StorageLive(_15);
-        _15 = _14;
+        StorageDead(_8);
+        StorageDead(_4);
+        StorageDead(_9);
+        StorageDead(_3);
+        _16 = Enumerate::<std::slice::Iter<'_, T>> { iter: _15, count: const 0_usize };
+        StorageDead(_15);
+        StorageLive(_17);
+        _17 = _16;
         goto -> bb4;
     }
 
     bb4: {
-        StorageLive(_17);
-        StorageLive(_16);
-        _16 = &mut _15;
-        _17 = <Enumerate<std::slice::Iter<'_, T>> as Iterator>::next(move _16) -> [return: bb5, unwind unreachable];
+        StorageLive(_19);
+        StorageLive(_18);
+        _18 = &mut _17;
+        _19 = <Enumerate<std::slice::Iter<'_, T>> as Iterator>::next(move _18) -> [return: bb5, unwind unreachable];
     }
 
     bb5: {
-        StorageDead(_16);
-        _18 = discriminant(_17);
-        switchInt(move _18) -> [0: bb6, 1: bb8, otherwise: bb10];
+        StorageDead(_18);
+        _20 = discriminant(_19);
+        switchInt(move _20) -> [0: bb6, 1: bb8, otherwise: bb10];
     }
 
     bb6: {
+        StorageDead(_19);
         StorageDead(_17);
-        StorageDead(_15);
         drop(_2) -> [return: bb7, unwind unreachable];
     }
 
@@ -177,19 +171,19 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () {
     }
 
     bb8: {
-        _19 = (((_17 as Some).0: (usize, &T)).0: usize);
-        _20 = (((_17 as Some).0: (usize, &T)).1: &T);
-        StorageLive(_21);
-        _21 = &_2;
-        StorageLive(_22);
-        _22 = (_19, _20);
-        _23 = <impl Fn(usize, &T) as Fn<(usize, &T)>>::call(move _21, move _22) -> [return: bb9, unwind unreachable];
+        _21 = (((_19 as Some).0: (usize, &T)).0: usize);
+        _22 = (((_19 as Some).0: (usize, &T)).1: &T);
+        StorageLive(_23);
+        _23 = &_2;
+        StorageLive(_24);
+        _24 = (_21, _22);
+        _25 = <impl Fn(usize, &T) as Fn<(usize, &T)>>::call(move _23, move _24) -> [return: bb9, unwind unreachable];
     }
 
     bb9: {
-        StorageDead(_22);
-        StorageDead(_21);
-        StorageDead(_17);
+        StorageDead(_24);
+        StorageDead(_23);
+        StorageDead(_19);
         goto -> bb4;
     }
 
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 a055612bd5f..25a5ecdc6c3 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,171 +4,165 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () {
     debug slice => _1;
     debug f => _2;
     let mut _0: ();
-    let mut _13: std::slice::Iter<'_, T>;
-    let mut _14: std::iter::Enumerate<std::slice::Iter<'_, T>>;
-    let mut _15: std::iter::Enumerate<std::slice::Iter<'_, T>>;
-    let mut _16: &mut std::iter::Enumerate<std::slice::Iter<'_, T>>;
-    let mut _17: std::option::Option<(usize, &T)>;
-    let mut _18: isize;
-    let mut _21: &impl Fn(usize, &T);
-    let mut _22: (usize, &T);
-    let _23: ();
+    let mut _15: std::slice::Iter<'_, T>;
+    let mut _16: std::iter::Enumerate<std::slice::Iter<'_, T>>;
+    let mut _17: std::iter::Enumerate<std::slice::Iter<'_, T>>;
+    let mut _18: &mut std::iter::Enumerate<std::slice::Iter<'_, T>>;
+    let mut _19: std::option::Option<(usize, &T)>;
+    let mut _20: isize;
+    let mut _23: &impl Fn(usize, &T);
+    let mut _24: (usize, &T);
+    let _25: ();
     scope 1 {
-        debug iter => _15;
-        let _19: usize;
-        let _20: &T;
+        debug iter => _17;
+        let _21: usize;
+        let _22: &T;
         scope 2 {
-            debug i => _19;
-            debug x => _20;
+            debug i => _21;
+            debug x => _22;
         }
     }
     scope 3 (inlined core::slice::<impl [T]>::iter) {
         debug self => _1;
         scope 4 (inlined std::slice::Iter::<'_, T>::new) {
             debug slice => _1;
-            let _4: *const T;
-            let mut _5: bool;
-            let mut _6: usize;
-            let mut _8: usize;
-            let mut _9: *mut T;
-            let mut _11: std::ptr::NonNull<T>;
-            let mut _12: *const T;
+            let _3: usize;
+            let mut _5: std::ptr::NonNull<[T]>;
+            let mut _10: bool;
+            let mut _11: *mut T;
+            let mut _12: *mut T;
+            let mut _14: *const T;
             scope 5 {
-                debug ptr => _4;
+                debug len => _3;
+                let _9: std::ptr::NonNull<T>;
                 scope 6 {
-                    let _7: *const T;
+                    debug ptr => _9;
                     scope 7 {
-                        debug end_or_len => _7;
-                        scope 13 (inlined NonNull::<T>::new_unchecked) {
-                            debug ptr => _9;
-                            let mut _10: *const T;
-                            let mut _24: *mut T;
-                            scope 14 {
-                                scope 15 (inlined NonNull::<T>::new_unchecked::runtime::<T>) {
-                                    debug ptr => _24;
-                                    scope 16 (inlined std::ptr::mut_ptr::<impl *mut T>::is_null) {
-                                        debug self => _24;
-                                        let mut _25: *mut u8;
-                                        scope 17 {
-                                            scope 18 (inlined std::ptr::mut_ptr::<impl *mut T>::is_null::runtime_impl) {
-                                                debug ptr => _25;
-                                                scope 19 (inlined std::ptr::mut_ptr::<impl *mut u8>::addr) {
-                                                    debug self => _25;
-                                                    scope 20 {
-                                                        scope 21 (inlined std::ptr::mut_ptr::<impl *mut u8>::cast::<()>) {
-                                                            debug self => _25;
-                                                        }
-                                                    }
-                                                }
-                                            }
-                                        }
-                                    }
-                                }
+                        let _13: *const T;
+                        scope 8 {
+                            debug end_or_len => _13;
+                        }
+                        scope 14 (inlined invalid::<T>) {
+                            debug addr => _3;
+                            scope 15 {
                             }
                         }
-                    }
-                    scope 9 (inlined invalid::<T>) {
-                        debug addr => _8;
-                        scope 10 {
+                        scope 16 (inlined NonNull::<T>::as_ptr) {
+                            debug self => _9;
+                        }
+                        scope 17 (inlined std::ptr::mut_ptr::<impl *mut T>::add) {
+                            debug self => _11;
+                            debug count => _3;
+                            scope 18 {
+                            }
                         }
                     }
-                    scope 11 (inlined std::ptr::const_ptr::<impl *const T>::add) {
-                        debug self => _4;
-                        debug count => _6;
-                        scope 12 {
+                }
+                scope 9 (inlined <NonNull<[T]> as From<&[T]>>::from) {
+                    debug reference => _1;
+                    let mut _4: *const [T];
+                    scope 10 {
+                    }
+                }
+                scope 11 (inlined NonNull::<[T]>::cast::<T>) {
+                    debug self => _5;
+                    let mut _6: *mut [T];
+                    let mut _7: *mut T;
+                    let mut _8: *const T;
+                    scope 12 {
+                        scope 13 (inlined NonNull::<[T]>::as_ptr) {
+                            debug self => _5;
                         }
                     }
                 }
             }
-            scope 8 (inlined core::slice::<impl [T]>::as_ptr) {
-                debug self => _1;
-                let mut _3: *const [T];
-            }
         }
     }
-    scope 22 (inlined <std::slice::Iter<'_, T> as Iterator>::enumerate) {
-        debug self => _13;
-        scope 23 (inlined Enumerate::<std::slice::Iter<'_, T>>::new) {
-            debug iter => _13;
+    scope 19 (inlined <std::slice::Iter<'_, T> as Iterator>::enumerate) {
+        debug self => _15;
+        scope 20 (inlined Enumerate::<std::slice::Iter<'_, T>>::new) {
+            debug iter => _15;
         }
     }
-    scope 24 (inlined <Enumerate<std::slice::Iter<'_, T>> as IntoIterator>::into_iter) {
-        debug self => _14;
+    scope 21 (inlined <Enumerate<std::slice::Iter<'_, T>> as IntoIterator>::into_iter) {
+        debug self => _16;
     }
 
     bb0: {
-        StorageLive(_13);
-        StorageLive(_4);
+        StorageLive(_15);
         StorageLive(_3);
-        _3 = &raw const (*_1);
-        _4 = move _3 as *const T (PtrToPtr);
-        StorageDead(_3);
-        StorageLive(_7);
+        StorageLive(_9);
+        StorageLive(_4);
+        StorageLive(_8);
+        _3 = Len((*_1));
         StorageLive(_5);
-        _5 = const _;
-        switchInt(move _5) -> [0: bb1, otherwise: bb2];
+        _4 = &raw const (*_1);
+        _5 = NonNull::<[T]> { pointer: _4 };
+        StorageLive(_7);
+        StorageLive(_6);
+        _6 = _4 as *mut [T] (PtrToPtr);
+        _7 = move _6 as *mut T (PtrToPtr);
+        _8 = move _7 as *const T (PointerCoercion(MutToConstPointer));
+        StorageDead(_6);
+        StorageDead(_7);
+        _9 = NonNull::<T> { pointer: _8 };
+        StorageDead(_5);
+        StorageLive(_13);
+        StorageLive(_10);
+        _10 = const _;
+        switchInt(move _10) -> [0: bb1, otherwise: bb2];
     }
 
     bb1: {
-        StorageLive(_6);
-        _6 = Len((*_1));
-        _7 = Offset(_4, _6);
-        StorageDead(_6);
+        StorageLive(_12);
+        StorageLive(_11);
+        _11 = _8 as *mut T (PtrToPtr);
+        _12 = Offset(_11, _3);
+        StorageDead(_11);
+        _13 = move _12 as *const T (PointerCoercion(MutToConstPointer));
+        StorageDead(_12);
         goto -> bb3;
     }
 
     bb2: {
-        StorageLive(_8);
-        _8 = Len((*_1));
-        _7 = _8 as *const T (Transmute);
-        StorageDead(_8);
+        _13 = _3 as *const T (Transmute);
         goto -> bb3;
     }
 
     bb3: {
-        StorageDead(_5);
-        StorageLive(_11);
-        StorageLive(_9);
-        _9 = _4 as *mut T (PtrToPtr);
-        StorageLive(_10);
-        StorageLive(_24);
-        StorageLive(_25);
-        _10 = _9 as *const T (PointerCoercion(MutToConstPointer));
-        _11 = NonNull::<T> { pointer: _10 };
-        StorageDead(_25);
-        StorageDead(_24);
         StorageDead(_10);
-        StorageDead(_9);
-        StorageLive(_12);
-        _12 = _7;
-        _13 = std::slice::Iter::<'_, T> { ptr: move _11, end_or_len: move _12, _marker: const ZeroSized: PhantomData<&T> };
-        StorageDead(_12);
-        StorageDead(_11);
-        StorageDead(_7);
-        StorageDead(_4);
-        _14 = Enumerate::<std::slice::Iter<'_, T>> { iter: _13, count: const 0_usize };
+        StorageLive(_14);
+        _14 = _13;
+        _15 = std::slice::Iter::<'_, T> { ptr: _9, end_or_len: move _14, _marker: const ZeroSized: PhantomData<&T> };
+        StorageDead(_14);
         StorageDead(_13);
-        StorageLive(_15);
-        _15 = _14;
+        StorageDead(_8);
+        StorageDead(_4);
+        StorageDead(_9);
+        StorageDead(_3);
+        _16 = Enumerate::<std::slice::Iter<'_, T>> { iter: _15, count: const 0_usize };
+        StorageDead(_15);
+        StorageLive(_17);
+        _17 = _16;
         goto -> bb4;
     }
 
     bb4: {
-        StorageLive(_17);
-        StorageLive(_16);
-        _16 = &mut _15;
-        _17 = <Enumerate<std::slice::Iter<'_, T>> as Iterator>::next(move _16) -> [return: bb5, unwind: bb11];
+        StorageLive(_19);
+        StorageLive(_18);
+        _18 = &mut _17;
+        _19 = <Enumerate<std::slice::Iter<'_, T>> as Iterator>::next(move _18) -> [return: bb5, unwind: bb11];
     }
 
     bb5: {
-        StorageDead(_16);
-        _18 = discriminant(_17);
-        switchInt(move _18) -> [0: bb6, 1: bb8, otherwise: bb10];
+        StorageDead(_18);
+        _20 = discriminant(_19);
+        switchInt(move _20) -> [0: bb6, 1: bb8, otherwise: bb10];
     }
 
     bb6: {
+        StorageDead(_19);
         StorageDead(_17);
-        StorageDead(_15);
         drop(_2) -> [return: bb7, unwind continue];
     }
 
@@ -177,19 +171,19 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () {
     }
 
     bb8: {
-        _19 = (((_17 as Some).0: (usize, &T)).0: usize);
-        _20 = (((_17 as Some).0: (usize, &T)).1: &T);
-        StorageLive(_21);
-        _21 = &_2;
-        StorageLive(_22);
-        _22 = (_19, _20);
-        _23 = <impl Fn(usize, &T) as Fn<(usize, &T)>>::call(move _21, move _22) -> [return: bb9, unwind: bb11];
+        _21 = (((_19 as Some).0: (usize, &T)).0: usize);
+        _22 = (((_19 as Some).0: (usize, &T)).1: &T);
+        StorageLive(_23);
+        _23 = &_2;
+        StorageLive(_24);
+        _24 = (_21, _22);
+        _25 = <impl Fn(usize, &T) as Fn<(usize, &T)>>::call(move _23, move _24) -> [return: bb9, unwind: bb11];
     }
 
     bb9: {
-        StorageDead(_22);
-        StorageDead(_21);
-        StorageDead(_17);
+        StorageDead(_24);
+        StorageDead(_23);
+        StorageDead(_19);
         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 471491108e0..133d6f53fce 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,159 +4,153 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () {
     debug slice => _1;
     debug f => _2;
     let mut _0: ();
-    let mut _13: std::slice::Iter<'_, T>;
-    let mut _14: std::slice::Iter<'_, T>;
-    let mut _15: &mut std::slice::Iter<'_, T>;
-    let mut _16: std::option::Option<&T>;
-    let mut _17: isize;
-    let mut _19: &impl Fn(&T);
-    let mut _20: (&T,);
-    let _21: ();
+    let mut _15: std::slice::Iter<'_, T>;
+    let mut _16: std::slice::Iter<'_, T>;
+    let mut _17: &mut std::slice::Iter<'_, T>;
+    let mut _18: std::option::Option<&T>;
+    let mut _19: isize;
+    let mut _21: &impl Fn(&T);
+    let mut _22: (&T,);
+    let _23: ();
     scope 1 {
-        debug iter => _14;
-        let _18: &T;
+        debug iter => _16;
+        let _20: &T;
         scope 2 {
-            debug x => _18;
+            debug x => _20;
         }
     }
     scope 3 (inlined core::slice::<impl [T]>::iter) {
         debug self => _1;
         scope 4 (inlined std::slice::Iter::<'_, T>::new) {
             debug slice => _1;
-            let _4: *const T;
-            let mut _5: bool;
-            let mut _6: usize;
-            let mut _8: usize;
-            let mut _9: *mut T;
-            let mut _11: std::ptr::NonNull<T>;
-            let mut _12: *const T;
+            let _3: usize;
+            let mut _5: std::ptr::NonNull<[T]>;
+            let mut _10: bool;
+            let mut _11: *mut T;
+            let mut _12: *mut T;
+            let mut _14: *const T;
             scope 5 {
-                debug ptr => _4;
+                debug len => _3;
+                let _9: std::ptr::NonNull<T>;
                 scope 6 {
-                    let _7: *const T;
+                    debug ptr => _9;
                     scope 7 {
-                        debug end_or_len => _7;
-                        scope 13 (inlined NonNull::<T>::new_unchecked) {
-                            debug ptr => _9;
-                            let mut _10: *const T;
-                            let mut _22: *mut T;
-                            scope 14 {
-                                scope 15 (inlined NonNull::<T>::new_unchecked::runtime::<T>) {
-                                    debug ptr => _22;
-                                    scope 16 (inlined std::ptr::mut_ptr::<impl *mut T>::is_null) {
-                                        debug self => _22;
-                                        let mut _23: *mut u8;
-                                        scope 17 {
-                                            scope 18 (inlined std::ptr::mut_ptr::<impl *mut T>::is_null::runtime_impl) {
-                                                debug ptr => _23;
-                                                scope 19 (inlined std::ptr::mut_ptr::<impl *mut u8>::addr) {
-                                                    debug self => _23;
-                                                    scope 20 {
-                                                        scope 21 (inlined std::ptr::mut_ptr::<impl *mut u8>::cast::<()>) {
-                                                            debug self => _23;
-                                                        }
-                                                    }
-                                                }
-                                            }
-                                        }
-                                    }
-                                }
+                        let _13: *const T;
+                        scope 8 {
+                            debug end_or_len => _13;
+                        }
+                        scope 14 (inlined invalid::<T>) {
+                            debug addr => _3;
+                            scope 15 {
                             }
                         }
-                    }
-                    scope 9 (inlined invalid::<T>) {
-                        debug addr => _8;
-                        scope 10 {
+                        scope 16 (inlined NonNull::<T>::as_ptr) {
+                            debug self => _9;
+                        }
+                        scope 17 (inlined std::ptr::mut_ptr::<impl *mut T>::add) {
+                            debug self => _11;
+                            debug count => _3;
+                            scope 18 {
+                            }
                         }
                     }
-                    scope 11 (inlined std::ptr::const_ptr::<impl *const T>::add) {
-                        debug self => _4;
-                        debug count => _6;
-                        scope 12 {
+                }
+                scope 9 (inlined <NonNull<[T]> as From<&[T]>>::from) {
+                    debug reference => _1;
+                    let mut _4: *const [T];
+                    scope 10 {
+                    }
+                }
+                scope 11 (inlined NonNull::<[T]>::cast::<T>) {
+                    debug self => _5;
+                    let mut _6: *mut [T];
+                    let mut _7: *mut T;
+                    let mut _8: *const T;
+                    scope 12 {
+                        scope 13 (inlined NonNull::<[T]>::as_ptr) {
+                            debug self => _5;
                         }
                     }
                 }
             }
-            scope 8 (inlined core::slice::<impl [T]>::as_ptr) {
-                debug self => _1;
-                let mut _3: *const [T];
-            }
         }
     }
-    scope 22 (inlined <std::slice::Iter<'_, T> as IntoIterator>::into_iter) {
-        debug self => _13;
+    scope 19 (inlined <std::slice::Iter<'_, T> as IntoIterator>::into_iter) {
+        debug self => _15;
     }
 
     bb0: {
-        StorageLive(_4);
         StorageLive(_3);
-        _3 = &raw const (*_1);
-        _4 = move _3 as *const T (PtrToPtr);
-        StorageDead(_3);
-        StorageLive(_7);
+        StorageLive(_9);
+        StorageLive(_4);
+        StorageLive(_8);
+        _3 = Len((*_1));
         StorageLive(_5);
-        _5 = const _;
-        switchInt(move _5) -> [0: bb1, otherwise: bb2];
+        _4 = &raw const (*_1);
+        _5 = NonNull::<[T]> { pointer: _4 };
+        StorageLive(_7);
+        StorageLive(_6);
+        _6 = _4 as *mut [T] (PtrToPtr);
+        _7 = move _6 as *mut T (PtrToPtr);
+        _8 = move _7 as *const T (PointerCoercion(MutToConstPointer));
+        StorageDead(_6);
+        StorageDead(_7);
+        _9 = NonNull::<T> { pointer: _8 };
+        StorageDead(_5);
+        StorageLive(_13);
+        StorageLive(_10);
+        _10 = const _;
+        switchInt(move _10) -> [0: bb1, otherwise: bb2];
     }
 
     bb1: {
-        StorageLive(_6);
-        _6 = Len((*_1));
-        _7 = Offset(_4, _6);
-        StorageDead(_6);
+        StorageLive(_12);
+        StorageLive(_11);
+        _11 = _8 as *mut T (PtrToPtr);
+        _12 = Offset(_11, _3);
+        StorageDead(_11);
+        _13 = move _12 as *const T (PointerCoercion(MutToConstPointer));
+        StorageDead(_12);
         goto -> bb3;
     }
 
     bb2: {
-        StorageLive(_8);
-        _8 = Len((*_1));
-        _7 = _8 as *const T (Transmute);
-        StorageDead(_8);
+        _13 = _3 as *const T (Transmute);
         goto -> bb3;
     }
 
     bb3: {
-        StorageDead(_5);
-        StorageLive(_11);
-        StorageLive(_9);
-        _9 = _4 as *mut T (PtrToPtr);
-        StorageLive(_10);
-        StorageLive(_22);
-        StorageLive(_23);
-        _10 = _9 as *const T (PointerCoercion(MutToConstPointer));
-        _11 = NonNull::<T> { pointer: _10 };
-        StorageDead(_23);
-        StorageDead(_22);
         StorageDead(_10);
-        StorageDead(_9);
-        StorageLive(_12);
-        _12 = _7;
-        _13 = std::slice::Iter::<'_, T> { ptr: move _11, end_or_len: move _12, _marker: const ZeroSized: PhantomData<&T> };
-        StorageDead(_12);
-        StorageDead(_11);
-        StorageDead(_7);
-        StorageDead(_4);
         StorageLive(_14);
         _14 = _13;
+        _15 = std::slice::Iter::<'_, T> { ptr: _9, end_or_len: move _14, _marker: const ZeroSized: PhantomData<&T> };
+        StorageDead(_14);
+        StorageDead(_13);
+        StorageDead(_8);
+        StorageDead(_4);
+        StorageDead(_9);
+        StorageDead(_3);
+        StorageLive(_16);
+        _16 = _15;
         goto -> bb4;
     }
 
     bb4: {
-        StorageLive(_16);
-        StorageLive(_15);
-        _15 = &mut _14;
-        _16 = <std::slice::Iter<'_, T> as Iterator>::next(move _15) -> [return: bb5, unwind unreachable];
+        StorageLive(_18);
+        StorageLive(_17);
+        _17 = &mut _16;
+        _18 = <std::slice::Iter<'_, T> as Iterator>::next(move _17) -> [return: bb5, unwind unreachable];
     }
 
     bb5: {
-        StorageDead(_15);
-        _17 = discriminant(_16);
-        switchInt(move _17) -> [0: bb6, 1: bb8, otherwise: bb10];
+        StorageDead(_17);
+        _19 = discriminant(_18);
+        switchInt(move _19) -> [0: bb6, 1: bb8, otherwise: bb10];
     }
 
     bb6: {
+        StorageDead(_18);
         StorageDead(_16);
-        StorageDead(_14);
         drop(_2) -> [return: bb7, unwind unreachable];
     }
 
@@ -165,18 +159,18 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () {
     }
 
     bb8: {
-        _18 = ((_16 as Some).0: &T);
-        StorageLive(_19);
-        _19 = &_2;
-        StorageLive(_20);
-        _20 = (_18,);
-        _21 = <impl Fn(&T) as Fn<(&T,)>>::call(move _19, move _20) -> [return: bb9, unwind unreachable];
+        _20 = ((_18 as Some).0: &T);
+        StorageLive(_21);
+        _21 = &_2;
+        StorageLive(_22);
+        _22 = (_20,);
+        _23 = <impl Fn(&T) as Fn<(&T,)>>::call(move _21, move _22) -> [return: bb9, unwind unreachable];
     }
 
     bb9: {
-        StorageDead(_20);
-        StorageDead(_19);
-        StorageDead(_16);
+        StorageDead(_22);
+        StorageDead(_21);
+        StorageDead(_18);
         goto -> bb4;
     }
 
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 bbf38aba91f..4e74253e541 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,159 +4,153 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () {
     debug slice => _1;
     debug f => _2;
     let mut _0: ();
-    let mut _13: std::slice::Iter<'_, T>;
-    let mut _14: std::slice::Iter<'_, T>;
-    let mut _15: &mut std::slice::Iter<'_, T>;
-    let mut _16: std::option::Option<&T>;
-    let mut _17: isize;
-    let mut _19: &impl Fn(&T);
-    let mut _20: (&T,);
-    let _21: ();
+    let mut _15: std::slice::Iter<'_, T>;
+    let mut _16: std::slice::Iter<'_, T>;
+    let mut _17: &mut std::slice::Iter<'_, T>;
+    let mut _18: std::option::Option<&T>;
+    let mut _19: isize;
+    let mut _21: &impl Fn(&T);
+    let mut _22: (&T,);
+    let _23: ();
     scope 1 {
-        debug iter => _14;
-        let _18: &T;
+        debug iter => _16;
+        let _20: &T;
         scope 2 {
-            debug x => _18;
+            debug x => _20;
         }
     }
     scope 3 (inlined core::slice::<impl [T]>::iter) {
         debug self => _1;
         scope 4 (inlined std::slice::Iter::<'_, T>::new) {
             debug slice => _1;
-            let _4: *const T;
-            let mut _5: bool;
-            let mut _6: usize;
-            let mut _8: usize;
-            let mut _9: *mut T;
-            let mut _11: std::ptr::NonNull<T>;
-            let mut _12: *const T;
+            let _3: usize;
+            let mut _5: std::ptr::NonNull<[T]>;
+            let mut _10: bool;
+            let mut _11: *mut T;
+            let mut _12: *mut T;
+            let mut _14: *const T;
             scope 5 {
-                debug ptr => _4;
+                debug len => _3;
+                let _9: std::ptr::NonNull<T>;
                 scope 6 {
-                    let _7: *const T;
+                    debug ptr => _9;
                     scope 7 {
-                        debug end_or_len => _7;
-                        scope 13 (inlined NonNull::<T>::new_unchecked) {
-                            debug ptr => _9;
-                            let mut _10: *const T;
-                            let mut _22: *mut T;
-                            scope 14 {
-                                scope 15 (inlined NonNull::<T>::new_unchecked::runtime::<T>) {
-                                    debug ptr => _22;
-                                    scope 16 (inlined std::ptr::mut_ptr::<impl *mut T>::is_null) {
-                                        debug self => _22;
-                                        let mut _23: *mut u8;
-                                        scope 17 {
-                                            scope 18 (inlined std::ptr::mut_ptr::<impl *mut T>::is_null::runtime_impl) {
-                                                debug ptr => _23;
-                                                scope 19 (inlined std::ptr::mut_ptr::<impl *mut u8>::addr) {
-                                                    debug self => _23;
-                                                    scope 20 {
-                                                        scope 21 (inlined std::ptr::mut_ptr::<impl *mut u8>::cast::<()>) {
-                                                            debug self => _23;
-                                                        }
-                                                    }
-                                                }
-                                            }
-                                        }
-                                    }
-                                }
+                        let _13: *const T;
+                        scope 8 {
+                            debug end_or_len => _13;
+                        }
+                        scope 14 (inlined invalid::<T>) {
+                            debug addr => _3;
+                            scope 15 {
                             }
                         }
-                    }
-                    scope 9 (inlined invalid::<T>) {
-                        debug addr => _8;
-                        scope 10 {
+                        scope 16 (inlined NonNull::<T>::as_ptr) {
+                            debug self => _9;
+                        }
+                        scope 17 (inlined std::ptr::mut_ptr::<impl *mut T>::add) {
+                            debug self => _11;
+                            debug count => _3;
+                            scope 18 {
+                            }
                         }
                     }
-                    scope 11 (inlined std::ptr::const_ptr::<impl *const T>::add) {
-                        debug self => _4;
-                        debug count => _6;
-                        scope 12 {
+                }
+                scope 9 (inlined <NonNull<[T]> as From<&[T]>>::from) {
+                    debug reference => _1;
+                    let mut _4: *const [T];
+                    scope 10 {
+                    }
+                }
+                scope 11 (inlined NonNull::<[T]>::cast::<T>) {
+                    debug self => _5;
+                    let mut _6: *mut [T];
+                    let mut _7: *mut T;
+                    let mut _8: *const T;
+                    scope 12 {
+                        scope 13 (inlined NonNull::<[T]>::as_ptr) {
+                            debug self => _5;
                         }
                     }
                 }
             }
-            scope 8 (inlined core::slice::<impl [T]>::as_ptr) {
-                debug self => _1;
-                let mut _3: *const [T];
-            }
         }
     }
-    scope 22 (inlined <std::slice::Iter<'_, T> as IntoIterator>::into_iter) {
-        debug self => _13;
+    scope 19 (inlined <std::slice::Iter<'_, T> as IntoIterator>::into_iter) {
+        debug self => _15;
     }
 
     bb0: {
-        StorageLive(_4);
         StorageLive(_3);
-        _3 = &raw const (*_1);
-        _4 = move _3 as *const T (PtrToPtr);
-        StorageDead(_3);
-        StorageLive(_7);
+        StorageLive(_9);
+        StorageLive(_4);
+        StorageLive(_8);
+        _3 = Len((*_1));
         StorageLive(_5);
-        _5 = const _;
-        switchInt(move _5) -> [0: bb1, otherwise: bb2];
+        _4 = &raw const (*_1);
+        _5 = NonNull::<[T]> { pointer: _4 };
+        StorageLive(_7);
+        StorageLive(_6);
+        _6 = _4 as *mut [T] (PtrToPtr);
+        _7 = move _6 as *mut T (PtrToPtr);
+        _8 = move _7 as *const T (PointerCoercion(MutToConstPointer));
+        StorageDead(_6);
+        StorageDead(_7);
+        _9 = NonNull::<T> { pointer: _8 };
+        StorageDead(_5);
+        StorageLive(_13);
+        StorageLive(_10);
+        _10 = const _;
+        switchInt(move _10) -> [0: bb1, otherwise: bb2];
     }
 
     bb1: {
-        StorageLive(_6);
-        _6 = Len((*_1));
-        _7 = Offset(_4, _6);
-        StorageDead(_6);
+        StorageLive(_12);
+        StorageLive(_11);
+        _11 = _8 as *mut T (PtrToPtr);
+        _12 = Offset(_11, _3);
+        StorageDead(_11);
+        _13 = move _12 as *const T (PointerCoercion(MutToConstPointer));
+        StorageDead(_12);
         goto -> bb3;
     }
 
     bb2: {
-        StorageLive(_8);
-        _8 = Len((*_1));
-        _7 = _8 as *const T (Transmute);
-        StorageDead(_8);
+        _13 = _3 as *const T (Transmute);
         goto -> bb3;
     }
 
     bb3: {
-        StorageDead(_5);
-        StorageLive(_11);
-        StorageLive(_9);
-        _9 = _4 as *mut T (PtrToPtr);
-        StorageLive(_10);
-        StorageLive(_22);
-        StorageLive(_23);
-        _10 = _9 as *const T (PointerCoercion(MutToConstPointer));
-        _11 = NonNull::<T> { pointer: _10 };
-        StorageDead(_23);
-        StorageDead(_22);
         StorageDead(_10);
-        StorageDead(_9);
-        StorageLive(_12);
-        _12 = _7;
-        _13 = std::slice::Iter::<'_, T> { ptr: move _11, end_or_len: move _12, _marker: const ZeroSized: PhantomData<&T> };
-        StorageDead(_12);
-        StorageDead(_11);
-        StorageDead(_7);
-        StorageDead(_4);
         StorageLive(_14);
         _14 = _13;
+        _15 = std::slice::Iter::<'_, T> { ptr: _9, end_or_len: move _14, _marker: const ZeroSized: PhantomData<&T> };
+        StorageDead(_14);
+        StorageDead(_13);
+        StorageDead(_8);
+        StorageDead(_4);
+        StorageDead(_9);
+        StorageDead(_3);
+        StorageLive(_16);
+        _16 = _15;
         goto -> bb4;
     }
 
     bb4: {
-        StorageLive(_16);
-        StorageLive(_15);
-        _15 = &mut _14;
-        _16 = <std::slice::Iter<'_, T> as Iterator>::next(move _15) -> [return: bb5, unwind: bb11];
+        StorageLive(_18);
+        StorageLive(_17);
+        _17 = &mut _16;
+        _18 = <std::slice::Iter<'_, T> as Iterator>::next(move _17) -> [return: bb5, unwind: bb11];
     }
 
     bb5: {
-        StorageDead(_15);
-        _17 = discriminant(_16);
-        switchInt(move _17) -> [0: bb6, 1: bb8, otherwise: bb10];
+        StorageDead(_17);
+        _19 = discriminant(_18);
+        switchInt(move _19) -> [0: bb6, 1: bb8, otherwise: bb10];
     }
 
     bb6: {
+        StorageDead(_18);
         StorageDead(_16);
-        StorageDead(_14);
         drop(_2) -> [return: bb7, unwind continue];
     }
 
@@ -165,18 +159,18 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () {
     }
 
     bb8: {
-        _18 = ((_16 as Some).0: &T);
-        StorageLive(_19);
-        _19 = &_2;
-        StorageLive(_20);
-        _20 = (_18,);
-        _21 = <impl Fn(&T) as Fn<(&T,)>>::call(move _19, move _20) -> [return: bb9, unwind: bb11];
+        _20 = ((_18 as Some).0: &T);
+        StorageLive(_21);
+        _21 = &_2;
+        StorageLive(_22);
+        _22 = (_20,);
+        _23 = <impl Fn(&T) as Fn<(&T,)>>::call(move _21, move _22) -> [return: bb9, unwind: bb11];
     }
 
     bb9: {
-        StorageDead(_20);
-        StorageDead(_19);
-        StorageDead(_16);
+        StorageDead(_22);
+        StorageDead(_21);
+        StorageDead(_18);
         goto -> bb4;
     }
 
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 f9c8ab4db60..639e1a51430 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,174 +4,168 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () {
     debug slice => _1;
     debug f => _2;
     let mut _0: ();
-    let mut _13: std::slice::Iter<'_, T>;
-    let mut _14: std::iter::Rev<std::slice::Iter<'_, T>>;
-    let mut _15: std::iter::Rev<std::slice::Iter<'_, T>>;
-    let mut _16: &mut std::iter::Rev<std::slice::Iter<'_, T>>;
-    let mut _18: std::option::Option<&T>;
-    let mut _19: isize;
-    let mut _21: &impl Fn(&T);
-    let mut _22: (&T,);
-    let _23: ();
+    let mut _15: std::slice::Iter<'_, T>;
+    let mut _16: std::iter::Rev<std::slice::Iter<'_, T>>;
+    let mut _17: std::iter::Rev<std::slice::Iter<'_, T>>;
+    let mut _18: &mut std::iter::Rev<std::slice::Iter<'_, T>>;
+    let mut _20: std::option::Option<&T>;
+    let mut _21: isize;
+    let mut _23: &impl Fn(&T);
+    let mut _24: (&T,);
+    let _25: ();
     scope 1 {
-        debug iter => _15;
-        let _20: &T;
+        debug iter => _17;
+        let _22: &T;
         scope 2 {
-            debug x => _20;
+            debug x => _22;
         }
-        scope 25 (inlined <Rev<std::slice::Iter<'_, T>> as Iterator>::next) {
-            debug self => _16;
-            let mut _17: &mut std::slice::Iter<'_, T>;
+        scope 22 (inlined <Rev<std::slice::Iter<'_, T>> as Iterator>::next) {
+            debug self => _18;
+            let mut _19: &mut std::slice::Iter<'_, T>;
         }
     }
     scope 3 (inlined core::slice::<impl [T]>::iter) {
         debug self => _1;
         scope 4 (inlined std::slice::Iter::<'_, T>::new) {
             debug slice => _1;
-            let _4: *const T;
-            let mut _5: bool;
-            let mut _6: usize;
-            let mut _8: usize;
-            let mut _9: *mut T;
-            let mut _11: std::ptr::NonNull<T>;
-            let mut _12: *const T;
+            let _3: usize;
+            let mut _5: std::ptr::NonNull<[T]>;
+            let mut _10: bool;
+            let mut _11: *mut T;
+            let mut _12: *mut T;
+            let mut _14: *const T;
             scope 5 {
-                debug ptr => _4;
+                debug len => _3;
+                let _9: std::ptr::NonNull<T>;
                 scope 6 {
-                    let _7: *const T;
+                    debug ptr => _9;
                     scope 7 {
-                        debug end_or_len => _7;
-                        scope 13 (inlined NonNull::<T>::new_unchecked) {
-                            debug ptr => _9;
-                            let mut _10: *const T;
-                            let mut _24: *mut T;
-                            scope 14 {
-                                scope 15 (inlined NonNull::<T>::new_unchecked::runtime::<T>) {
-                                    debug ptr => _24;
-                                    scope 16 (inlined std::ptr::mut_ptr::<impl *mut T>::is_null) {
-                                        debug self => _24;
-                                        let mut _25: *mut u8;
-                                        scope 17 {
-                                            scope 18 (inlined std::ptr::mut_ptr::<impl *mut T>::is_null::runtime_impl) {
-                                                debug ptr => _25;
-                                                scope 19 (inlined std::ptr::mut_ptr::<impl *mut u8>::addr) {
-                                                    debug self => _25;
-                                                    scope 20 {
-                                                        scope 21 (inlined std::ptr::mut_ptr::<impl *mut u8>::cast::<()>) {
-                                                            debug self => _25;
-                                                        }
-                                                    }
-                                                }
-                                            }
-                                        }
-                                    }
-                                }
+                        let _13: *const T;
+                        scope 8 {
+                            debug end_or_len => _13;
+                        }
+                        scope 14 (inlined invalid::<T>) {
+                            debug addr => _3;
+                            scope 15 {
                             }
                         }
-                    }
-                    scope 9 (inlined invalid::<T>) {
-                        debug addr => _8;
-                        scope 10 {
+                        scope 16 (inlined NonNull::<T>::as_ptr) {
+                            debug self => _9;
+                        }
+                        scope 17 (inlined std::ptr::mut_ptr::<impl *mut T>::add) {
+                            debug self => _11;
+                            debug count => _3;
+                            scope 18 {
+                            }
                         }
                     }
-                    scope 11 (inlined std::ptr::const_ptr::<impl *const T>::add) {
-                        debug self => _4;
-                        debug count => _6;
-                        scope 12 {
+                }
+                scope 9 (inlined <NonNull<[T]> as From<&[T]>>::from) {
+                    debug reference => _1;
+                    let mut _4: *const [T];
+                    scope 10 {
+                    }
+                }
+                scope 11 (inlined NonNull::<[T]>::cast::<T>) {
+                    debug self => _5;
+                    let mut _6: *mut [T];
+                    let mut _7: *mut T;
+                    let mut _8: *const T;
+                    scope 12 {
+                        scope 13 (inlined NonNull::<[T]>::as_ptr) {
+                            debug self => _5;
                         }
                     }
                 }
             }
-            scope 8 (inlined core::slice::<impl [T]>::as_ptr) {
-                debug self => _1;
-                let mut _3: *const [T];
-            }
         }
     }
-    scope 22 (inlined <std::slice::Iter<'_, T> as Iterator>::rev) {
-        debug self => _13;
-        scope 23 (inlined Rev::<std::slice::Iter<'_, T>>::new) {
-            debug iter => _13;
+    scope 19 (inlined <std::slice::Iter<'_, T> as Iterator>::rev) {
+        debug self => _15;
+        scope 20 (inlined Rev::<std::slice::Iter<'_, T>>::new) {
+            debug iter => _15;
         }
     }
-    scope 24 (inlined <Rev<std::slice::Iter<'_, T>> as IntoIterator>::into_iter) {
-        debug self => _14;
+    scope 21 (inlined <Rev<std::slice::Iter<'_, T>> as IntoIterator>::into_iter) {
+        debug self => _16;
     }
 
     bb0: {
-        StorageLive(_13);
-        StorageLive(_4);
+        StorageLive(_15);
         StorageLive(_3);
-        _3 = &raw const (*_1);
-        _4 = move _3 as *const T (PtrToPtr);
-        StorageDead(_3);
-        StorageLive(_7);
+        StorageLive(_9);
+        StorageLive(_4);
+        StorageLive(_8);
+        _3 = Len((*_1));
         StorageLive(_5);
-        _5 = const _;
-        switchInt(move _5) -> [0: bb1, otherwise: bb2];
+        _4 = &raw const (*_1);
+        _5 = NonNull::<[T]> { pointer: _4 };
+        StorageLive(_7);
+        StorageLive(_6);
+        _6 = _4 as *mut [T] (PtrToPtr);
+        _7 = move _6 as *mut T (PtrToPtr);
+        _8 = move _7 as *const T (PointerCoercion(MutToConstPointer));
+        StorageDead(_6);
+        StorageDead(_7);
+        _9 = NonNull::<T> { pointer: _8 };
+        StorageDead(_5);
+        StorageLive(_13);
+        StorageLive(_10);
+        _10 = const _;
+        switchInt(move _10) -> [0: bb1, otherwise: bb2];
     }
 
     bb1: {
-        StorageLive(_6);
-        _6 = Len((*_1));
-        _7 = Offset(_4, _6);
-        StorageDead(_6);
+        StorageLive(_12);
+        StorageLive(_11);
+        _11 = _8 as *mut T (PtrToPtr);
+        _12 = Offset(_11, _3);
+        StorageDead(_11);
+        _13 = move _12 as *const T (PointerCoercion(MutToConstPointer));
+        StorageDead(_12);
         goto -> bb3;
     }
 
     bb2: {
-        StorageLive(_8);
-        _8 = Len((*_1));
-        _7 = _8 as *const T (Transmute);
-        StorageDead(_8);
+        _13 = _3 as *const T (Transmute);
         goto -> bb3;
     }
 
     bb3: {
-        StorageDead(_5);
-        StorageLive(_11);
-        StorageLive(_9);
-        _9 = _4 as *mut T (PtrToPtr);
-        StorageLive(_10);
-        StorageLive(_24);
-        StorageLive(_25);
-        _10 = _9 as *const T (PointerCoercion(MutToConstPointer));
-        _11 = NonNull::<T> { pointer: _10 };
-        StorageDead(_25);
-        StorageDead(_24);
         StorageDead(_10);
-        StorageDead(_9);
-        StorageLive(_12);
-        _12 = _7;
-        _13 = std::slice::Iter::<'_, T> { ptr: move _11, end_or_len: move _12, _marker: const ZeroSized: PhantomData<&T> };
-        StorageDead(_12);
-        StorageDead(_11);
-        StorageDead(_7);
-        StorageDead(_4);
-        _14 = Rev::<std::slice::Iter<'_, T>> { iter: _13 };
+        StorageLive(_14);
+        _14 = _13;
+        _15 = std::slice::Iter::<'_, T> { ptr: _9, end_or_len: move _14, _marker: const ZeroSized: PhantomData<&T> };
+        StorageDead(_14);
         StorageDead(_13);
-        StorageLive(_15);
-        _15 = _14;
+        StorageDead(_8);
+        StorageDead(_4);
+        StorageDead(_9);
+        StorageDead(_3);
+        _16 = Rev::<std::slice::Iter<'_, T>> { iter: _15 };
+        StorageDead(_15);
+        StorageLive(_17);
+        _17 = _16;
         goto -> bb4;
     }
 
     bb4: {
-        StorageLive(_18);
-        _16 = &mut _15;
-        StorageLive(_17);
-        _17 = &mut (_15.0: std::slice::Iter<'_, T>);
-        _18 = <std::slice::Iter<'_, T> as DoubleEndedIterator>::next_back(move _17) -> [return: bb5, unwind unreachable];
+        StorageLive(_20);
+        _18 = &mut _17;
+        StorageLive(_19);
+        _19 = &mut (_17.0: std::slice::Iter<'_, T>);
+        _20 = <std::slice::Iter<'_, T> as DoubleEndedIterator>::next_back(move _19) -> [return: bb5, unwind unreachable];
     }
 
     bb5: {
-        StorageDead(_17);
-        _19 = discriminant(_18);
-        switchInt(move _19) -> [0: bb6, 1: bb8, otherwise: bb10];
+        StorageDead(_19);
+        _21 = discriminant(_20);
+        switchInt(move _21) -> [0: bb6, 1: bb8, otherwise: bb10];
     }
 
     bb6: {
-        StorageDead(_18);
-        StorageDead(_15);
+        StorageDead(_20);
+        StorageDead(_17);
         drop(_2) -> [return: bb7, unwind unreachable];
     }
 
@@ -180,18 +174,18 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () {
     }
 
     bb8: {
-        _20 = ((_18 as Some).0: &T);
-        StorageLive(_21);
-        _21 = &_2;
-        StorageLive(_22);
-        _22 = (_20,);
-        _23 = <impl Fn(&T) as Fn<(&T,)>>::call(move _21, move _22) -> [return: bb9, unwind unreachable];
+        _22 = ((_20 as Some).0: &T);
+        StorageLive(_23);
+        _23 = &_2;
+        StorageLive(_24);
+        _24 = (_22,);
+        _25 = <impl Fn(&T) as Fn<(&T,)>>::call(move _23, move _24) -> [return: bb9, unwind unreachable];
     }
 
     bb9: {
-        StorageDead(_22);
-        StorageDead(_21);
-        StorageDead(_18);
+        StorageDead(_24);
+        StorageDead(_23);
+        StorageDead(_20);
         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 65f423ac326..2237fd7dbd1 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,174 +4,168 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () {
     debug slice => _1;
     debug f => _2;
     let mut _0: ();
-    let mut _13: std::slice::Iter<'_, T>;
-    let mut _14: std::iter::Rev<std::slice::Iter<'_, T>>;
-    let mut _15: std::iter::Rev<std::slice::Iter<'_, T>>;
-    let mut _16: &mut std::iter::Rev<std::slice::Iter<'_, T>>;
-    let mut _18: std::option::Option<&T>;
-    let mut _19: isize;
-    let mut _21: &impl Fn(&T);
-    let mut _22: (&T,);
-    let _23: ();
+    let mut _15: std::slice::Iter<'_, T>;
+    let mut _16: std::iter::Rev<std::slice::Iter<'_, T>>;
+    let mut _17: std::iter::Rev<std::slice::Iter<'_, T>>;
+    let mut _18: &mut std::iter::Rev<std::slice::Iter<'_, T>>;
+    let mut _20: std::option::Option<&T>;
+    let mut _21: isize;
+    let mut _23: &impl Fn(&T);
+    let mut _24: (&T,);
+    let _25: ();
     scope 1 {
-        debug iter => _15;
-        let _20: &T;
+        debug iter => _17;
+        let _22: &T;
         scope 2 {
-            debug x => _20;
+            debug x => _22;
         }
-        scope 25 (inlined <Rev<std::slice::Iter<'_, T>> as Iterator>::next) {
-            debug self => _16;
-            let mut _17: &mut std::slice::Iter<'_, T>;
+        scope 22 (inlined <Rev<std::slice::Iter<'_, T>> as Iterator>::next) {
+            debug self => _18;
+            let mut _19: &mut std::slice::Iter<'_, T>;
         }
     }
     scope 3 (inlined core::slice::<impl [T]>::iter) {
         debug self => _1;
         scope 4 (inlined std::slice::Iter::<'_, T>::new) {
             debug slice => _1;
-            let _4: *const T;
-            let mut _5: bool;
-            let mut _6: usize;
-            let mut _8: usize;
-            let mut _9: *mut T;
-            let mut _11: std::ptr::NonNull<T>;
-            let mut _12: *const T;
+            let _3: usize;
+            let mut _5: std::ptr::NonNull<[T]>;
+            let mut _10: bool;
+            let mut _11: *mut T;
+            let mut _12: *mut T;
+            let mut _14: *const T;
             scope 5 {
-                debug ptr => _4;
+                debug len => _3;
+                let _9: std::ptr::NonNull<T>;
                 scope 6 {
-                    let _7: *const T;
+                    debug ptr => _9;
                     scope 7 {
-                        debug end_or_len => _7;
-                        scope 13 (inlined NonNull::<T>::new_unchecked) {
-                            debug ptr => _9;
-                            let mut _10: *const T;
-                            let mut _24: *mut T;
-                            scope 14 {
-                                scope 15 (inlined NonNull::<T>::new_unchecked::runtime::<T>) {
-                                    debug ptr => _24;
-                                    scope 16 (inlined std::ptr::mut_ptr::<impl *mut T>::is_null) {
-                                        debug self => _24;
-                                        let mut _25: *mut u8;
-                                        scope 17 {
-                                            scope 18 (inlined std::ptr::mut_ptr::<impl *mut T>::is_null::runtime_impl) {
-                                                debug ptr => _25;
-                                                scope 19 (inlined std::ptr::mut_ptr::<impl *mut u8>::addr) {
-                                                    debug self => _25;
-                                                    scope 20 {
-                                                        scope 21 (inlined std::ptr::mut_ptr::<impl *mut u8>::cast::<()>) {
-                                                            debug self => _25;
-                                                        }
-                                                    }
-                                                }
-                                            }
-                                        }
-                                    }
-                                }
+                        let _13: *const T;
+                        scope 8 {
+                            debug end_or_len => _13;
+                        }
+                        scope 14 (inlined invalid::<T>) {
+                            debug addr => _3;
+                            scope 15 {
                             }
                         }
-                    }
-                    scope 9 (inlined invalid::<T>) {
-                        debug addr => _8;
-                        scope 10 {
+                        scope 16 (inlined NonNull::<T>::as_ptr) {
+                            debug self => _9;
+                        }
+                        scope 17 (inlined std::ptr::mut_ptr::<impl *mut T>::add) {
+                            debug self => _11;
+                            debug count => _3;
+                            scope 18 {
+                            }
                         }
                     }
-                    scope 11 (inlined std::ptr::const_ptr::<impl *const T>::add) {
-                        debug self => _4;
-                        debug count => _6;
-                        scope 12 {
+                }
+                scope 9 (inlined <NonNull<[T]> as From<&[T]>>::from) {
+                    debug reference => _1;
+                    let mut _4: *const [T];
+                    scope 10 {
+                    }
+                }
+                scope 11 (inlined NonNull::<[T]>::cast::<T>) {
+                    debug self => _5;
+                    let mut _6: *mut [T];
+                    let mut _7: *mut T;
+                    let mut _8: *const T;
+                    scope 12 {
+                        scope 13 (inlined NonNull::<[T]>::as_ptr) {
+                            debug self => _5;
                         }
                     }
                 }
             }
-            scope 8 (inlined core::slice::<impl [T]>::as_ptr) {
-                debug self => _1;
-                let mut _3: *const [T];
-            }
         }
     }
-    scope 22 (inlined <std::slice::Iter<'_, T> as Iterator>::rev) {
-        debug self => _13;
-        scope 23 (inlined Rev::<std::slice::Iter<'_, T>>::new) {
-            debug iter => _13;
+    scope 19 (inlined <std::slice::Iter<'_, T> as Iterator>::rev) {
+        debug self => _15;
+        scope 20 (inlined Rev::<std::slice::Iter<'_, T>>::new) {
+            debug iter => _15;
         }
     }
-    scope 24 (inlined <Rev<std::slice::Iter<'_, T>> as IntoIterator>::into_iter) {
-        debug self => _14;
+    scope 21 (inlined <Rev<std::slice::Iter<'_, T>> as IntoIterator>::into_iter) {
+        debug self => _16;
     }
 
     bb0: {
-        StorageLive(_13);
-        StorageLive(_4);
+        StorageLive(_15);
         StorageLive(_3);
-        _3 = &raw const (*_1);
-        _4 = move _3 as *const T (PtrToPtr);
-        StorageDead(_3);
-        StorageLive(_7);
+        StorageLive(_9);
+        StorageLive(_4);
+        StorageLive(_8);
+        _3 = Len((*_1));
         StorageLive(_5);
-        _5 = const _;
-        switchInt(move _5) -> [0: bb1, otherwise: bb2];
+        _4 = &raw const (*_1);
+        _5 = NonNull::<[T]> { pointer: _4 };
+        StorageLive(_7);
+        StorageLive(_6);
+        _6 = _4 as *mut [T] (PtrToPtr);
+        _7 = move _6 as *mut T (PtrToPtr);
+        _8 = move _7 as *const T (PointerCoercion(MutToConstPointer));
+        StorageDead(_6);
+        StorageDead(_7);
+        _9 = NonNull::<T> { pointer: _8 };
+        StorageDead(_5);
+        StorageLive(_13);
+        StorageLive(_10);
+        _10 = const _;
+        switchInt(move _10) -> [0: bb1, otherwise: bb2];
     }
 
     bb1: {
-        StorageLive(_6);
-        _6 = Len((*_1));
-        _7 = Offset(_4, _6);
-        StorageDead(_6);
+        StorageLive(_12);
+        StorageLive(_11);
+        _11 = _8 as *mut T (PtrToPtr);
+        _12 = Offset(_11, _3);
+        StorageDead(_11);
+        _13 = move _12 as *const T (PointerCoercion(MutToConstPointer));
+        StorageDead(_12);
         goto -> bb3;
     }
 
     bb2: {
-        StorageLive(_8);
-        _8 = Len((*_1));
-        _7 = _8 as *const T (Transmute);
-        StorageDead(_8);
+        _13 = _3 as *const T (Transmute);
         goto -> bb3;
     }
 
     bb3: {
-        StorageDead(_5);
-        StorageLive(_11);
-        StorageLive(_9);
-        _9 = _4 as *mut T (PtrToPtr);
-        StorageLive(_10);
-        StorageLive(_24);
-        StorageLive(_25);
-        _10 = _9 as *const T (PointerCoercion(MutToConstPointer));
-        _11 = NonNull::<T> { pointer: _10 };
-        StorageDead(_25);
-        StorageDead(_24);
         StorageDead(_10);
-        StorageDead(_9);
-        StorageLive(_12);
-        _12 = _7;
-        _13 = std::slice::Iter::<'_, T> { ptr: move _11, end_or_len: move _12, _marker: const ZeroSized: PhantomData<&T> };
-        StorageDead(_12);
-        StorageDead(_11);
-        StorageDead(_7);
-        StorageDead(_4);
-        _14 = Rev::<std::slice::Iter<'_, T>> { iter: _13 };
+        StorageLive(_14);
+        _14 = _13;
+        _15 = std::slice::Iter::<'_, T> { ptr: _9, end_or_len: move _14, _marker: const ZeroSized: PhantomData<&T> };
+        StorageDead(_14);
         StorageDead(_13);
-        StorageLive(_15);
-        _15 = _14;
+        StorageDead(_8);
+        StorageDead(_4);
+        StorageDead(_9);
+        StorageDead(_3);
+        _16 = Rev::<std::slice::Iter<'_, T>> { iter: _15 };
+        StorageDead(_15);
+        StorageLive(_17);
+        _17 = _16;
         goto -> bb4;
     }
 
     bb4: {
-        StorageLive(_18);
-        _16 = &mut _15;
-        StorageLive(_17);
-        _17 = &mut (_15.0: std::slice::Iter<'_, T>);
-        _18 = <std::slice::Iter<'_, T> as DoubleEndedIterator>::next_back(move _17) -> [return: bb5, unwind: bb11];
+        StorageLive(_20);
+        _18 = &mut _17;
+        StorageLive(_19);
+        _19 = &mut (_17.0: std::slice::Iter<'_, T>);
+        _20 = <std::slice::Iter<'_, T> as DoubleEndedIterator>::next_back(move _19) -> [return: bb5, unwind: bb11];
     }
 
     bb5: {
-        StorageDead(_17);
-        _19 = discriminant(_18);
-        switchInt(move _19) -> [0: bb6, 1: bb8, otherwise: bb10];
+        StorageDead(_19);
+        _21 = discriminant(_20);
+        switchInt(move _21) -> [0: bb6, 1: bb8, otherwise: bb10];
     }
 
     bb6: {
-        StorageDead(_18);
-        StorageDead(_15);
+        StorageDead(_20);
+        StorageDead(_17);
         drop(_2) -> [return: bb7, unwind continue];
     }
 
@@ -180,18 +174,18 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () {
     }
 
     bb8: {
-        _20 = ((_18 as Some).0: &T);
-        StorageLive(_21);
-        _21 = &_2;
-        StorageLive(_22);
-        _22 = (_20,);
-        _23 = <impl Fn(&T) as Fn<(&T,)>>::call(move _21, move _22) -> [return: bb9, unwind: bb11];
+        _22 = ((_20 as Some).0: &T);
+        StorageLive(_23);
+        _23 = &_2;
+        StorageLive(_24);
+        _24 = (_22,);
+        _25 = <impl Fn(&T) as Fn<(&T,)>>::call(move _23, move _24) -> [return: bb9, unwind: bb11];
     }
 
     bb9: {
-        StorageDead(_22);
-        StorageDead(_21);
-        StorageDead(_18);
+        StorageDead(_24);
+        StorageDead(_23);
+        StorageDead(_20);
         goto -> bb4;
     }
 
diff --git a/tests/ui/hygiene/panic-location.run.stderr b/tests/ui/hygiene/panic-location.run.stderr
index 5824ef31211..5c552411da7 100644
--- a/tests/ui/hygiene/panic-location.run.stderr
+++ b/tests/ui/hygiene/panic-location.run.stderr
@@ -1,3 +1,3 @@
-thread 'main' panicked at library/alloc/src/raw_vec.rs:570:5:
+thread 'main' panicked at library/alloc/src/raw_vec.rs:571:5:
 capacity overflow
 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
diff --git a/tests/ui/precondition-checks/misaligned-slice.rs b/tests/ui/precondition-checks/misaligned-slice.rs
new file mode 100644
index 00000000000..c961c800352
--- /dev/null
+++ b/tests/ui/precondition-checks/misaligned-slice.rs
@@ -0,0 +1,11 @@
+// run-fail
+// compile-flags: -Copt-level=3 -Cdebug-assertions=yes
+// error-pattern: unsafe precondition(s) violated: slice::from_raw_parts
+// ignore-debug
+// ignore-wasm32-bare no panic messages
+
+fn main() {
+    unsafe {
+        let _s: &[u64] = std::slice::from_raw_parts(1usize as *const u64, 0);
+    }
+}
diff --git a/tests/ui/precondition-checks/null-slice.rs b/tests/ui/precondition-checks/null-slice.rs
new file mode 100644
index 00000000000..1e67e7f5fb1
--- /dev/null
+++ b/tests/ui/precondition-checks/null-slice.rs
@@ -0,0 +1,11 @@
+// run-fail
+// compile-flags: -Copt-level=3 -Cdebug-assertions=yes
+// error-pattern: unsafe precondition(s) violated: slice::from_raw_parts
+// ignore-debug
+// ignore-wasm32-bare no panic messages
+
+fn main() {
+    unsafe {
+        let _s: &[u8] = std::slice::from_raw_parts(std::ptr::null(), 0);
+    }
+}
diff --git a/tests/ui/precondition-checks/out-of-bounds-get-unchecked.rs b/tests/ui/precondition-checks/out-of-bounds-get-unchecked.rs
new file mode 100644
index 00000000000..1366ba28f1c
--- /dev/null
+++ b/tests/ui/precondition-checks/out-of-bounds-get-unchecked.rs
@@ -0,0 +1,12 @@
+// run-fail
+// compile-flags: -Copt-level=3 -Cdebug-assertions=yes
+// error-pattern: unsafe precondition(s) violated: hint::assert_unchecked
+// ignore-debug
+// ignore-wasm32-bare no panic messages
+
+fn main() {
+    unsafe {
+        let sli: &[u8] = &[0];
+        sli.get_unchecked(1);
+    }
+}