From 82914b15192a317c26a0825a69b8680626882d9f Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Sun, 27 Jul 2025 21:22:45 -0700 Subject: [PATCH 1/4] Also allow inlining drop shims --- compiler/rustc_middle/src/mir/visit.rs | 4 +- compiler/rustc_mir_transform/src/inline.rs | 229 +++++++++++--- .../rustc_mir_transform/src/inline/cycle.rs | 46 ++- library/core/src/future/ready.rs | 12 +- tests/codegen-llvm/drop-in-place-noalias.rs | 2 +- tests/codegen-llvm/drop.rs | 2 +- tests/mir-opt/c_unwind_terminate.rs | 5 +- ...n.DataflowConstProp.32bit.panic-abort.diff | 7 +- ....DataflowConstProp.32bit.panic-unwind.diff | 17 +- ...n.DataflowConstProp.64bit.panic-abort.diff | 7 +- ....DataflowConstProp.64bit.panic-unwind.diff | 17 +- ...oxed_slice.main.GVN.32bit.panic-abort.diff | 7 +- ...xed_slice.main.GVN.32bit.panic-unwind.diff | 17 +- ...oxed_slice.main.GVN.64bit.panic-abort.diff | 7 +- ...xed_slice.main.GVN.64bit.panic-unwind.diff | 17 +- ...ng_operand.test.GVN.32bit.panic-abort.diff | 231 +++++++++++++-- ...g_operand.test.GVN.32bit.panic-unwind.diff | 191 +++++++++++- ...ng_operand.test.GVN.64bit.panic-abort.diff | 231 +++++++++++++-- ...g_operand.test.GVN.64bit.panic-unwind.diff | 191 +++++++++++- .../asm_unwind.main.Inline.panic-unwind.diff | 21 +- ...ric_rust_call.call.Inline.panic-abort.diff | 219 +++++++++++++- ...inline_box_fn.call.Inline.panic-abort.diff | 216 +++++++++++++- ...ine_coroutine.main.Inline.panic-abort.diff | 83 ++++-- ...ne_coroutine.main.Inline.panic-unwind.diff | 104 ++++--- .../unsized_argument.caller.Inline.diff | 226 +++++++++++++- ...y.run2-{closure#0}.Inline.panic-abort.diff | 243 ++++++++++----- ....run2-{closure#0}.Inline.panic-unwind.diff | 279 ++++++++++++------ .../loops.vec_move.PreCodegen.after.mir | 19 +- ...t_opt.RemoveUnneededDrops.panic-abort.diff | 88 +++++- 29 files changed, 2291 insertions(+), 447 deletions(-) diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs index 929ebe1aee181..786886ee92f1e 100644 --- a/compiler/rustc_middle/src/mir/visit.rs +++ b/compiler/rustc_middle/src/mir/visit.rs @@ -1328,9 +1328,9 @@ pub enum NonMutatingUseContext { pub enum MutatingUseContext { /// Appears as LHS of an assignment. Store, - /// Appears on `SetDiscriminant` + /// Appears on [`StatementKind::SetDiscriminant`] SetDiscriminant, - /// Appears on `Deinit` + /// Appears on [`StatementKind::Deinit`] Deinit, /// Output operand of an inline assembly block. AsmOutput, diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index 3d49eb4e8ef75..e86a8bcbf7a44 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -5,6 +5,7 @@ use std::iter; use std::ops::{Range, RangeFrom}; use rustc_abi::{ExternAbi, FieldIdx}; +use rustc_hir::LangItem; use rustc_hir::attrs::{InlineAttr, OptimizeAttr}; use rustc_hir::def::DefKind; use rustc_hir::def_id::DefId; @@ -116,6 +117,9 @@ trait Inliner<'tcx> { /// Has the caller body been changed? fn changed(self) -> bool; + /// Whether to also attempt to inline `Drop` terminators (not just `Call`s) + fn consider_drops(&self) -> bool; + /// Should inlining happen for a given callee? fn should_inline_for_callee(&self, def_id: DefId) -> bool; @@ -187,6 +191,10 @@ impl<'tcx> Inliner<'tcx> for ForceInliner<'tcx> { self.changed } + fn consider_drops(&self) -> bool { + false + } + fn should_inline_for_callee(&self, def_id: DefId) -> bool { ForceInline::should_run_pass_for_callee(self.tcx(), def_id) } @@ -272,6 +280,7 @@ struct NormalInliner<'tcx> { typing_env: ty::TypingEnv<'tcx>, /// `DefId` of caller. def_id: DefId, + caller_is_coroutine: bool, /// Stack of inlined instances. /// We only check the `DefId` and not the args because we want to /// avoid inlining cases of polymorphic recursion. @@ -304,6 +313,7 @@ impl<'tcx> Inliner<'tcx> for NormalInliner<'tcx> { tcx, typing_env, def_id, + caller_is_coroutine: tcx.is_coroutine(def_id), history: Vec::new(), top_down_counter: 0, changed: false, @@ -334,6 +344,10 @@ impl<'tcx> Inliner<'tcx> for NormalInliner<'tcx> { self.changed } + fn consider_drops(&self) -> bool { + !self.caller_is_coroutine + } + fn should_inline_for_callee(&self, _: DefId) -> bool { true } @@ -542,6 +556,59 @@ fn process_blocks<'tcx, I: Inliner<'tcx>>( } } +/// Returns a value indicating whether it's worth trying to inline a `drop` for `ty`. +/// +/// We only want to bother inlining things that have a change to need to do something. +/// The `RemoveUnneededDrops` pass will handle things that obviously don't need +/// dropping, and will do it more efficiently since it doesn't need to add inlining +/// metadata, defensively add new blocks, etc. +/// +/// But this isn't the same as `needs_drop` because we want the opposite fallback: +/// while `needs_drop` is true for a (non-Copy) type parameter, here we don't +/// want to attempt inlining its drop because that'll never work. +fn should_attempt_inline_drop_for_type<'tcx>( + tcx: TyCtxt<'tcx>, + typing_env: ty::TypingEnv<'tcx>, + ty: Ty<'tcx>, +) -> bool { + match ty.kind() { + ty::Tuple(elems) if elems.is_empty() => false, + + // Even if these might have drops later, we can't inline them now. + ty::Param(..) | ty::Alias(..) | ty::Dynamic(..) | ty::Foreign(..) => false, + + ty::Array(..) + | ty::Adt(..) + | ty::Slice(..) + | ty::Tuple(..) + | ty::Closure(..) + | ty::CoroutineClosure(..) + | ty::Coroutine(..) + | ty::CoroutineWitness(..) => ty.needs_drop(tcx, typing_env), + + // Primitives we obviously don't need to inline a drop method + ty::Error(..) + | ty::Bool + | ty::Int(..) + | ty::Uint(..) + | ty::Float(..) + | ty::Never + | ty::FnDef(..) + | ty::FnPtr(..) + | ty::Char + | ty::RawPtr(..) + | ty::Ref(..) + | ty::Str => false, + + // FIXME: Unsure what to do with this, but not attempting inlining is safe + ty::Pat(..) | ty::UnsafeBinder(..) => false, + + ty::Infer(..) | ty::Placeholder(..) | ty::Bound(..) => { + bug!("weird type while inlining: {ty:?}") + } + } +} + fn resolve_callsite<'tcx, I: Inliner<'tcx>>( inliner: &I, caller_body: &Body<'tcx>, @@ -549,50 +616,73 @@ fn resolve_callsite<'tcx, I: Inliner<'tcx>>( bb_data: &BasicBlockData<'tcx>, ) -> Option> { let tcx = inliner.tcx(); - // Only consider direct calls to functions let terminator = bb_data.terminator(); // FIXME(explicit_tail_calls): figure out if we can inline tail calls - if let TerminatorKind::Call { ref func, fn_span, .. } = terminator.kind { - let func_ty = func.ty(caller_body, tcx); - if let ty::FnDef(def_id, args) = *func_ty.kind() { - if !inliner.should_inline_for_callee(def_id) { - debug!("not enabled"); - return None; - } + let (def_id, args, fn_span) = match &terminator.kind { + TerminatorKind::Call { func, fn_span, .. } => { + let func_ty = func.ty(caller_body, tcx); + if let ty::FnDef(def_id, args) = *func_ty.kind() { + if !inliner.should_inline_for_callee(def_id) { + debug!("not enabled"); + return None; + } - // To resolve an instance its args have to be fully normalized. - let args = tcx.try_normalize_erasing_regions(inliner.typing_env(), args).ok()?; - let callee = - Instance::try_resolve(tcx, inliner.typing_env(), def_id, args).ok().flatten()?; + // Allow RemoveUnneededDrops to handle these, rather than inlining, + // since it doesn't add the extra locals nor the metadata. + if inliner.consider_drops() + && tcx.is_lang_item(def_id, LangItem::DropInPlace) + && let drop_ty = args.type_at(0) + && !should_attempt_inline_drop_for_type(tcx, inliner.typing_env(), drop_ty) + { + return None; + } - if let InstanceKind::Virtual(..) | InstanceKind::Intrinsic(_) = callee.def { + (def_id, args, *fn_span) + } else { return None; } - - if inliner.history().contains(&callee.def_id()) { + } + TerminatorKind::Drop { place, .. } if inliner.consider_drops() => { + let drop_ty = place.ty(&caller_body.local_decls, tcx).ty; + if !should_attempt_inline_drop_for_type(tcx, inliner.typing_env(), drop_ty) { return None; } - let fn_sig = tcx.fn_sig(def_id).instantiate(tcx, args); + let drop_def_id = + tcx.require_lang_item(LangItem::DropInPlace, terminator.source_info.span); + let args = tcx.mk_args(&[drop_ty.into()]); + (drop_def_id, args, rustc_span::DUMMY_SP) + } + _ => return None, + }; - // Additionally, check that the body that we're inlining actually agrees - // with the ABI of the trait that the item comes from. - if let InstanceKind::Item(instance_def_id) = callee.def - && tcx.def_kind(instance_def_id) == DefKind::AssocFn - && let instance_fn_sig = tcx.fn_sig(instance_def_id).skip_binder() - && instance_fn_sig.abi() != fn_sig.abi() - { - return None; - } + // To resolve an instance its args have to be fully normalized. + let args = tcx.try_normalize_erasing_regions(inliner.typing_env(), args).ok()?; + let callee = Instance::try_resolve(tcx, inliner.typing_env(), def_id, args).ok().flatten()?; + + if let InstanceKind::Virtual(..) | InstanceKind::Intrinsic(_) = callee.def { + return None; + } - let source_info = SourceInfo { span: fn_span, ..terminator.source_info }; + if inliner.history().contains(&callee.def_id()) { + return None; + } - return Some(CallSite { callee, fn_sig, block: bb, source_info }); - } + let fn_sig = tcx.fn_sig(def_id).instantiate(tcx, args); + + // Additionally, check that the body that we're inlining actually agrees + // with the ABI of the trait that the item comes from. + if let InstanceKind::Item(instance_def_id) = callee.def + && tcx.def_kind(instance_def_id) == DefKind::AssocFn + && let instance_fn_sig = tcx.fn_sig(instance_def_id).skip_binder() + && instance_fn_sig.abi() != fn_sig.abi() + { + return None; } - None + let source_info = SourceInfo { span: fn_span, ..terminator.source_info }; + Some(CallSite { callee, fn_sig, block: bb, source_info }) } /// Attempts to inline a callsite into the caller body. When successful returns basic blocks @@ -604,6 +694,7 @@ fn try_inlining<'tcx, I: Inliner<'tcx>>( callsite: &CallSite<'tcx>, ) -> Result, &'static str> { let tcx = inliner.tcx(); + check_mir_is_available(inliner, caller_body, callsite.callee)?; let callee_attrs = tcx.codegen_fn_attrs(callsite.callee.def_id()); @@ -611,16 +702,25 @@ fn try_inlining<'tcx, I: Inliner<'tcx>>( check_codegen_attributes(inliner, callsite, callee_attrs)?; inliner.check_codegen_attributes_extra(callee_attrs)?; - let terminator = caller_body[callsite.block].terminator.as_ref().unwrap(); - let TerminatorKind::Call { args, destination, .. } = &terminator.kind else { bug!() }; - let destination_ty = destination.ty(&caller_body.local_decls, tcx).ty; - for arg in args { - if !arg.node.ty(&caller_body.local_decls, tcx).is_sized(tcx, inliner.typing_env()) { - // We do not allow inlining functions with unsized params. Inlining these functions - // could create unsized locals, which are unsound and being phased out. - return Err("call has unsized argument"); + let (args, destination_ty) = match &caller_body[callsite.block].terminator().kind { + TerminatorKind::Call { args, destination, .. } => { + for arg in args { + if !arg.node.ty(&caller_body.local_decls, tcx).is_sized(tcx, inliner.typing_env()) { + // We do not allow inlining functions with unsized params. Inlining these functions + // could create unsized locals, which are unsound and being phased out. + return Err("call has unsized argument"); + } + } + (&**args, destination.ty(&caller_body.local_decls, tcx).ty) } - } + TerminatorKind::Drop { .. } => { + // We cheat a bit here. Obviously there *is* an argument to the + // `drop_in_place`, but all the checks that look at it are ok to skip + // since we're generating them with always the correct type. + (&[][..], tcx.types.unit) + } + _ => bug!(), + }; let callee_body = try_instance_mir(tcx, callsite.callee.def)?; check_inline::is_inline_valid_on_body(tcx, callee_body)?; @@ -691,6 +791,59 @@ fn try_inlining<'tcx, I: Inliner<'tcx>>( } } + if inliner.consider_drops() { + let block_mut = &mut caller_body.basic_blocks.as_mut()[callsite.block]; + let terminator = block_mut.terminator.as_mut().unwrap(); + if let TerminatorKind::Drop { + place, + target, + unwind, + replace: _, + drop: None, + async_fut: None, + } = terminator.kind + { + // Rather than updating everything after here to also handle `Drop`, + // just replace the terminator with a `Call`, since we'll need things + // like the local for the argument anyway. + let source_info = terminator.source_info; + let drop_ty = place.ty(&caller_body.local_decls, tcx).ty; + + // We shouldn't have gotten here if the shim is empty, though it's + // not actually a *problem* if we do -- it's easy to inline nothing. + debug_assert!(drop_ty.needs_drop(tcx, inliner.typing_env())); + + let drop_ty_mut = Ty::new_mut_ptr(tcx, drop_ty); + let arg = caller_body.local_decls.push(LocalDecl::new(drop_ty_mut, source_info.span)); + block_mut.statements.push(Statement::new( + source_info, + StatementKind::Assign(Box::new(( + Place::from(arg), + Rvalue::RawPtr(RawPtrKind::Mut, place), + ))), + )); + let unit_local = + caller_body.local_decls.push(LocalDecl::new(tcx.types.unit, source_info.span)); + terminator.kind = TerminatorKind::Call { + func: Operand::function_handle( + tcx, + callsite.callee.def_id(), + [drop_ty.into()], + source_info.span, + ), + args: Box::new([Spanned { + node: Operand::Move(Place::from(arg)), + span: source_info.span, + }]), + destination: Place::from(unit_local), + target: Some(target), + unwind, + call_source: CallSource::Misc, + fn_span: source_info.span, + }; + } + } + let old_blocks = caller_body.basic_blocks.next_index(); inline_call(inliner, caller_body, callsite, callee_body); let new_blocks = old_blocks..caller_body.basic_blocks.next_index(); diff --git a/compiler/rustc_mir_transform/src/inline/cycle.rs b/compiler/rustc_mir_transform/src/inline/cycle.rs index 7f9234d1dc891..99f5ab15023c3 100644 --- a/compiler/rustc_mir_transform/src/inline/cycle.rs +++ b/compiler/rustc_mir_transform/src/inline/cycle.rs @@ -1,9 +1,10 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet}; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_data_structures::unord::UnordSet; +use rustc_hir::LangItem; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_middle::mir::TerminatorKind; -use rustc_middle::ty::{self, GenericArgsRef, InstanceKind, TyCtxt, TypeVisitableExt}; +use rustc_middle::ty::{self, GenericArgsRef, InstanceKind, TyCtxt, TypeVisitableExt, TypingEnv}; use rustc_session::Limit; use rustc_span::sym; use tracing::{instrument, trace}; @@ -204,23 +205,40 @@ pub(crate) fn mir_inliner_callees<'tcx>( let mut calls = FxIndexSet::default(); for bb_data in body.basic_blocks.iter() { let terminator = bb_data.terminator(); - if let TerminatorKind::Call { func, args: call_args, .. } = &terminator.kind { - let ty = func.ty(&body.local_decls, tcx); - let ty::FnDef(def_id, generic_args) = ty.kind() else { - continue; - }; - let call = if tcx.is_intrinsic(*def_id, sym::const_eval_select) { - let func = &call_args[2].node; + let call = match &terminator.kind { + TerminatorKind::Call { func, args: call_args, .. } => { let ty = func.ty(&body.local_decls, tcx); let ty::FnDef(def_id, generic_args) = ty.kind() else { continue; }; - (*def_id, *generic_args) - } else { - (*def_id, *generic_args) - }; - calls.insert(call); - } + if tcx.is_intrinsic(*def_id, sym::const_eval_select) { + let func = &call_args[2].node; + let ty = func.ty(&body.local_decls, tcx); + let ty::FnDef(def_id, generic_args) = ty.kind() else { + continue; + }; + (*def_id, *generic_args) + } else { + (*def_id, *generic_args) + } + } + // Coroutines need optimized MIR for layout, so skip them to avoid cycles + TerminatorKind::Drop { place, drop: None, async_fut: None, .. } + if !tcx.is_coroutine(instance.def_id()) => + { + let drop_ty = place.ty(&body.local_decls, tcx).ty; + if !drop_ty.needs_drop(tcx, TypingEnv::post_analysis(tcx, instance.def_id())) { + continue; + } + + let drop_def_id = + tcx.require_lang_item(LangItem::DropInPlace, terminator.source_info.span); + let args = tcx.mk_args(&[drop_ty.into()]); + (drop_def_id, args) + } + _ => continue, + }; + calls.insert(call); } tcx.arena.alloc_from_iter(calls.iter().copied()) } diff --git a/library/core/src/future/ready.rs b/library/core/src/future/ready.rs index b562ad4d8860d..8c31afe1c9227 100644 --- a/library/core/src/future/ready.rs +++ b/library/core/src/future/ready.rs @@ -20,10 +20,20 @@ impl Future for Ready { #[inline] fn poll(mut self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll { - Poll::Ready(self.0.take().expect("`Ready` polled after completion")) + match self.0.take() { + Some(v) => Poll::Ready(v), + None => polled_after_completion(), + } } } +// Have only one of these, rather than mono'ing the panic for every `T` +#[cold] +#[inline] +fn polled_after_completion() -> ! { + panic!("`Ready` polled after completion") +} + impl Ready { /// Consumes the `Ready`, returning the wrapped value. /// diff --git a/tests/codegen-llvm/drop-in-place-noalias.rs b/tests/codegen-llvm/drop-in-place-noalias.rs index bff2f52781f23..fad9300ceef96 100644 --- a/tests/codegen-llvm/drop-in-place-noalias.rs +++ b/tests/codegen-llvm/drop-in-place-noalias.rs @@ -1,4 +1,4 @@ -//@ compile-flags: -Copt-level=3 -C no-prepopulate-passes +//@ compile-flags: -Copt-level=3 -C no-prepopulate-passes -Z inline-mir=no // Tests that the compiler can apply `noalias` and other &mut attributes to `drop_in_place`. // Note that non-Unpin types should not get `noalias`, matching &mut behavior. diff --git a/tests/codegen-llvm/drop.rs b/tests/codegen-llvm/drop.rs index b22a8ef27d239..5980cfbd5b7f3 100644 --- a/tests/codegen-llvm/drop.rs +++ b/tests/codegen-llvm/drop.rs @@ -1,5 +1,5 @@ //@ needs-unwind - this test verifies the amount of drop calls when unwinding is used -//@ compile-flags: -C no-prepopulate-passes +//@ compile-flags: -C no-prepopulate-passes -Z inline-mir=no #![crate_type = "lib"] diff --git a/tests/mir-opt/c_unwind_terminate.rs b/tests/mir-opt/c_unwind_terminate.rs index 64524e74d28e5..fe31f818e8067 100644 --- a/tests/mir-opt/c_unwind_terminate.rs +++ b/tests/mir-opt/c_unwind_terminate.rs @@ -2,6 +2,7 @@ struct Noise; impl Drop for Noise { + #[inline(never)] fn drop(&mut self) { eprintln!("Noisy Drop"); } @@ -14,7 +15,9 @@ fn panic() { // EMIT_MIR c_unwind_terminate.test.AbortUnwindingCalls.after.mir extern "C" fn test() { // CHECK-LABEL: fn test( - // CHECK: drop + // CHECK: inlined drop_in_place:: + // CHECK-NOT: drop + // CHECK: ::drop // CHECK-SAME: unwind: [[unwind:bb.*]]] // CHECK: [[unwind]] (cleanup) // CHECK-NEXT: terminate(abi) 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 2c89670dcf7d7..bbfeb6db72d1f 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 @@ -5,6 +5,8 @@ let mut _0: (); let _1: A; let mut _2: std::boxed::Box<[bool]>; + let mut _8: *mut A; + let mut _9: (); scope 1 { debug a => _1; } @@ -37,6 +39,8 @@ } } } + scope 14 (inlined drop_in_place:: - shim(Some(A))) { + } bb0: { StorageLive(_1); @@ -60,7 +64,8 @@ _1 = const A {{ foo: Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC2, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global) }}; StorageDead(_2); _0 = const (); - drop(_1) -> [return: bb1, unwind unreachable]; + _8 = &raw mut _1; + drop(((*_8).0: std::boxed::Box<[bool]>)) -> [return: bb1, unwind unreachable]; } bb1: { 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 8fecfe224cc69..cf2a71188182f 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 @@ -5,6 +5,8 @@ let mut _0: (); let _1: A; let mut _2: std::boxed::Box<[bool]>; + let mut _8: *mut A; + let mut _9: (); scope 1 { debug a => _1; } @@ -37,6 +39,8 @@ } } } + scope 14 (inlined drop_in_place:: - shim(Some(A))) { + } bb0: { StorageLive(_1); @@ -60,16 +64,17 @@ _1 = const A {{ foo: Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC2, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global) }}; StorageDead(_2); _0 = const (); - drop(_1) -> [return: bb1, unwind: bb2]; + _8 = &raw mut _1; + drop(((*_8).0: std::boxed::Box<[bool]>)) -> [return: bb2, unwind: bb1]; } - bb1: { - StorageDead(_1); - return; + bb1 (cleanup): { + resume; } - bb2 (cleanup): { - resume; + bb2: { + StorageDead(_1); + return; } } 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 976ea252c2f89..7c701ef423fb9 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 @@ -5,6 +5,8 @@ let mut _0: (); let _1: A; let mut _2: std::boxed::Box<[bool]>; + let mut _8: *mut A; + let mut _9: (); scope 1 { debug a => _1; } @@ -37,6 +39,8 @@ } } } + scope 14 (inlined drop_in_place:: - shim(Some(A))) { + } bb0: { StorageLive(_1); @@ -60,7 +64,8 @@ _1 = const A {{ foo: Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC2, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global) }}; StorageDead(_2); _0 = const (); - drop(_1) -> [return: bb1, unwind unreachable]; + _8 = &raw mut _1; + drop(((*_8).0: std::boxed::Box<[bool]>)) -> [return: bb1, unwind unreachable]; } bb1: { 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 6c59f5e3e2e86..96835fb6c6155 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 @@ -5,6 +5,8 @@ let mut _0: (); let _1: A; let mut _2: std::boxed::Box<[bool]>; + let mut _8: *mut A; + let mut _9: (); scope 1 { debug a => _1; } @@ -37,6 +39,8 @@ } } } + scope 14 (inlined drop_in_place:: - shim(Some(A))) { + } bb0: { StorageLive(_1); @@ -60,16 +64,17 @@ _1 = const A {{ foo: Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC2, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global) }}; StorageDead(_2); _0 = const (); - drop(_1) -> [return: bb1, unwind: bb2]; + _8 = &raw mut _1; + drop(((*_8).0: std::boxed::Box<[bool]>)) -> [return: bb2, unwind: bb1]; } - bb1: { - StorageDead(_1); - return; + bb1 (cleanup): { + resume; } - bb2 (cleanup): { - resume; + bb2: { + StorageDead(_1); + return; } } 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 1f9cf6d6aca83..4e8f6467b9d60 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 @@ -5,6 +5,8 @@ let mut _0: (); let _1: A; let mut _2: std::boxed::Box<[bool]>; + let mut _8: *mut A; + let mut _9: (); scope 1 { debug a => _1; } @@ -37,6 +39,8 @@ } } } + scope 14 (inlined drop_in_place:: - shim(Some(A))) { + } bb0: { StorageLive(_1); @@ -67,7 +71,8 @@ + _1 = const A {{ foo: Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC2, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global) }}; StorageDead(_2); _0 = const (); - drop(_1) -> [return: bb1, unwind unreachable]; + _8 = &raw mut _1; + drop(((*_8).0: std::boxed::Box<[bool]>)) -> [return: bb1, unwind unreachable]; } bb1: { 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 a8760285fac11..b5a18aad2f442 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 @@ -5,6 +5,8 @@ let mut _0: (); let _1: A; let mut _2: std::boxed::Box<[bool]>; + let mut _8: *mut A; + let mut _9: (); scope 1 { debug a => _1; } @@ -37,6 +39,8 @@ } } } + scope 14 (inlined drop_in_place:: - shim(Some(A))) { + } bb0: { StorageLive(_1); @@ -67,16 +71,17 @@ + _1 = const A {{ foo: Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC2, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global) }}; StorageDead(_2); _0 = const (); - drop(_1) -> [return: bb1, unwind: bb2]; + _8 = &raw mut _1; + drop(((*_8).0: std::boxed::Box<[bool]>)) -> [return: bb2, unwind: bb1]; } - bb1: { - StorageDead(_1); - return; + bb1 (cleanup): { + resume; } - bb2 (cleanup): { - resume; + bb2: { + StorageDead(_1); + return; } } + 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 c398ae70a1a3e..f55fd750d4092 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 @@ -5,6 +5,8 @@ let mut _0: (); let _1: A; let mut _2: std::boxed::Box<[bool]>; + let mut _8: *mut A; + let mut _9: (); scope 1 { debug a => _1; } @@ -37,6 +39,8 @@ } } } + scope 14 (inlined drop_in_place:: - shim(Some(A))) { + } bb0: { StorageLive(_1); @@ -67,7 +71,8 @@ + _1 = const A {{ foo: Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC2, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global) }}; StorageDead(_2); _0 = const (); - drop(_1) -> [return: bb1, unwind unreachable]; + _8 = &raw mut _1; + drop(((*_8).0: std::boxed::Box<[bool]>)) -> [return: bb1, unwind unreachable]; } bb1: { 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 02934c02587d2..0ce6e800361ea 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 @@ -5,6 +5,8 @@ let mut _0: (); let _1: A; let mut _2: std::boxed::Box<[bool]>; + let mut _8: *mut A; + let mut _9: (); scope 1 { debug a => _1; } @@ -37,6 +39,8 @@ } } } + scope 14 (inlined drop_in_place:: - shim(Some(A))) { + } bb0: { StorageLive(_1); @@ -67,16 +71,17 @@ + _1 = const A {{ foo: Box::<[bool]>(Unique::<[bool]> {{ pointer: NonNull::<[bool]> {{ pointer: Indirect { alloc_id: ALLOC2, offset: Size(0 bytes) }: *const [bool] }}, _marker: PhantomData::<[bool]> }}, std::alloc::Global) }}; StorageDead(_2); _0 = const (); - drop(_1) -> [return: bb1, unwind: bb2]; + _8 = &raw mut _1; + drop(((*_8).0: std::boxed::Box<[bool]>)) -> [return: bb2, unwind: bb1]; } - bb1: { - StorageDead(_1); - return; + bb1 (cleanup): { + resume; } - bb2 (cleanup): { - resume; + bb2: { + StorageDead(_1); + return; } } + diff --git a/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.32bit.panic-abort.diff b/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.32bit.panic-abort.diff index 25ffff619e60b..2d5511dbd289f 100644 --- a/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.32bit.panic-abort.diff +++ b/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.32bit.panic-abort.diff @@ -11,6 +11,8 @@ let mut _9: std::boxed::Box<()>; let mut _10: *const (); let mut _23: usize; + let mut _40: usize; + let mut _42: std::ptr::alignment::AlignmentEnum; scope 1 { debug vp_ctx => _1; let _4: *const (); @@ -66,11 +68,78 @@ } } } + scope 19 (inlined drop_in_place::> - shim(Some(Box<()>))) { + scope 20 (inlined as Drop>::drop) { + let mut _24: *const (); + let mut _25: *mut (); + let _26: (); + let _34: std::ptr::NonNull<()>; + scope 21 { + let _41: usize; + let _43: std::ptr::alignment::AlignmentEnum; + scope 22 { + scope 30 (inlined Layout::size) { + } + scope 31 (inlined Unique::<()>::cast::) { + let mut _32: std::ptr::NonNull; + scope 32 (inlined NonNull::<()>::cast::) { + let mut _33: *const u8; + scope 33 (inlined NonNull::<()>::as_ptr) { + } + } + } + scope 34 (inlined as From>>::from) { + scope 35 (inlined Unique::::as_non_null_ptr) { + } + } + scope 36 (inlined ::deallocate) { + let mut _35: usize; + let mut _36: *mut u8; + scope 37 (inlined Layout::size) { + } + scope 38 (inlined NonNull::::as_ptr) { + } + scope 39 (inlined std::alloc::dealloc) { + let mut _37: usize; + scope 40 (inlined Layout::size) { + } + scope 41 (inlined Layout::align) { + let mut _39: std::ptr::alignment::AlignmentEnum; + scope 42 (inlined std::ptr::Alignment::as_usize) { + let mut _38: u32; + } + } + } + } + } + scope 23 (inlined Unique::<()>::as_ptr) { + scope 24 (inlined NonNull::<()>::as_ptr) { + } + } + scope 25 (inlined Layout::for_value_raw::<()>) { + let mut _27: usize; + let mut _28: usize; + scope 26 { + scope 29 (inlined #[track_caller] Layout::from_size_align_unchecked) { + let mut _29: bool; + let _30: (); + let mut _31: std::ptr::Alignment; + } + } + scope 27 (inlined size_of_val_raw::<()>) { + } + scope 28 (inlined align_of_val_raw::<()>) { + } + } + } + } + } bb0: { StorageLive(_1); StorageLive(_2); - StorageLive(_3); +- StorageLive(_3); ++ nop; StorageLive(_11); StorageLive(_12); StorageLive(_13); @@ -81,28 +150,23 @@ StorageLive(_14); StorageLive(_16); StorageLive(_17); - StorageLive(_19); +- StorageLive(_19); ++ nop; _19 = const false; -- switchInt(move _19) -> [0: bb6, otherwise: bb5]; -+ switchInt(const false) -> [0: bb6, otherwise: bb5]; +- switchInt(move _19) -> [0: bb5, otherwise: bb4]; ++ switchInt(const false) -> [0: bb5, otherwise: bb4]; } bb1: { - StorageDead(_3); - StorageDead(_1); - return; - } - - bb2: { unreachable; } - bb3: { + bb2: { - _18 = handle_alloc_error(move _14) -> unwind unreachable; + _18 = handle_alloc_error(const Layout {{ size: 0_usize, align: std::ptr::Alignment(std::ptr::alignment::AlignmentEnum::_Align1Shl0) }}) -> unwind unreachable; } - bb4: { + bb3: { _17 = copy ((_15 as Ok).0: std::ptr::NonNull<[u8]>); StorageLive(_22); _22 = copy _17 as *mut [u8] (Transmute); @@ -121,8 +185,9 @@ StorageDead(_2); StorageLive(_4); - _9 = deref_copy _3; +- _10 = copy ((_9.0: std::ptr::Unique<()>).0: std::ptr::NonNull<()>) as *const () (Transmute); + _9 = copy _3; - _10 = copy ((_9.0: std::ptr::Unique<()>).0: std::ptr::NonNull<()>) as *const () (Transmute); ++ _10 = copy ((_3.0: std::ptr::Unique<()>).0: std::ptr::NonNull<()>) as *const () (Transmute); _4 = copy _10; - StorageLive(_5); + nop; @@ -135,26 +200,46 @@ + _5 = *const [()] from (copy _10, const 1_usize); StorageDead(_23); StorageDead(_6); - StorageLive(_7); +- StorageLive(_7); ++ nop; StorageLive(_8); _8 = copy _5; - _7 = copy _8 as *mut () (PtrToPtr); -+ _7 = copy ((_9.0: std::ptr::Unique<()>).0: std::ptr::NonNull<()>) as *mut () (Transmute); ++ _7 = copy ((_3.0: std::ptr::Unique<()>).0: std::ptr::NonNull<()>) as *mut () (Transmute); StorageDead(_8); - StorageDead(_7); +- StorageDead(_7); - StorageDead(_5); ++ nop; + nop; StorageDead(_4); - drop(_3) -> [return: bb1, unwind unreachable]; + StorageLive(_41); +- StorageLive(_43); ++ nop; + StorageLive(_25); +- StorageLive(_27); ++ nop; + StorageLive(_32); +- StorageLive(_34); ++ nop; + _34 = copy ((_3.0: std::ptr::Unique<()>).0: std::ptr::NonNull<()>); + StorageLive(_24); +- _25 = copy _34 as *mut () (Transmute); +- _24 = copy _34 as *const () (Transmute); ++ _25 = copy _7; ++ _24 = copy _10; + StorageLive(_28); +- _27 = std::intrinsics::size_of_val::<()>(copy _24) -> [return: bb9, unwind unreachable]; ++ _27 = std::intrinsics::size_of_val::<()>(copy _10) -> [return: bb9, unwind unreachable]; } - bb5: { -- _20 = Layout::from_size_align_unchecked::precondition_check(copy _11, copy _12) -> [return: bb6, unwind unreachable]; -+ _20 = Layout::from_size_align_unchecked::precondition_check(const 0_usize, const 1_usize) -> [return: bb6, unwind unreachable]; + bb4: { +- _20 = Layout::from_size_align_unchecked::precondition_check(copy _11, copy _12) -> [return: bb5, unwind unreachable]; ++ _20 = Layout::from_size_align_unchecked::precondition_check(const 0_usize, const 1_usize) -> [return: bb5, unwind unreachable]; } - bb6: { - StorageDead(_19); + bb5: { +- StorageDead(_19); ++ nop; StorageLive(_21); - _21 = copy _12 as std::ptr::Alignment (Transmute); - _14 = Layout { size: copy _11, align: move _21 }; @@ -162,13 +247,107 @@ + _14 = const Layout {{ size: 0_usize, align: std::ptr::Alignment(std::ptr::alignment::AlignmentEnum::_Align1Shl0) }}; StorageDead(_21); StorageLive(_15); -- _15 = std::alloc::Global::alloc_impl(const alloc::alloc::exchange_malloc::promoted[0], copy _14, const false) -> [return: bb7, unwind unreachable]; -+ _15 = std::alloc::Global::alloc_impl(const alloc::alloc::exchange_malloc::promoted[0], const Layout {{ size: 0_usize, align: std::ptr::Alignment(std::ptr::alignment::AlignmentEnum::_Align1Shl0) }}, const false) -> [return: bb7, unwind unreachable]; +- _15 = std::alloc::Global::alloc_impl(const alloc::alloc::exchange_malloc::promoted[0], copy _14, const false) -> [return: bb6, unwind unreachable]; ++ _15 = std::alloc::Global::alloc_impl(const alloc::alloc::exchange_malloc::promoted[0], const Layout {{ size: 0_usize, align: std::ptr::Alignment(std::ptr::alignment::AlignmentEnum::_Align1Shl0) }}, const false) -> [return: bb6, unwind unreachable]; } - bb7: { + bb6: { _16 = discriminant(_15); - switchInt(move _16) -> [0: bb4, 1: bb3, otherwise: bb2]; + switchInt(move _16) -> [0: bb3, 1: bb2, otherwise: bb1]; + } + + bb7: { + StorageLive(_33); +- _33 = copy _25 as *const u8 (PtrToPtr); ++ _33 = copy _34 as *const u8 (Transmute); + _32 = NonNull:: { pointer: move _33 }; + StorageDead(_33); + StorageLive(_40); + StorageLive(_42); +- _40 = copy _41; ++ _40 = copy _27; + _42 = copy _43; + StorageLive(_35); +- _35 = copy _40; +- switchInt(move _35) -> [0: bb14, otherwise: bb13]; ++ _35 = copy _27; ++ switchInt(copy _27) -> [0: bb14, otherwise: bb13]; + } + + bb8: { +- StorageDead(_34); ++ nop; + StorageDead(_32); +- StorageDead(_27); ++ nop; + StorageDead(_25); + StorageDead(_41); +- StorageDead(_43); +- StorageDead(_3); ++ nop; ++ nop; + StorageDead(_1); + return; + } + + bb9: { +- _28 = std::intrinsics::align_of_val::<()>(move _24) -> [return: bb10, unwind unreachable]; ++ _28 = std::intrinsics::align_of_val::<()>(copy _10) -> [return: bb10, unwind unreachable]; + } + + bb10: { + StorageLive(_29); + _29 = const false; +- switchInt(move _29) -> [0: bb12, otherwise: bb11]; ++ switchInt(const false) -> [0: bb12, otherwise: bb11]; + } + + bb11: { + _30 = Layout::from_size_align_unchecked::precondition_check(copy _27, copy _28) -> [return: bb12, unwind unreachable]; + } + + bb12: { + StorageDead(_29); + StorageLive(_31); + _31 = copy _28 as std::ptr::Alignment (Transmute); + _41 = copy _27; + _43 = move (_31.0: std::ptr::alignment::AlignmentEnum); + StorageDead(_31); + StorageDead(_28); + StorageDead(_24); +- switchInt(move _27) -> [0: bb8, otherwise: bb7]; ++ switchInt(copy _27) -> [0: bb8, otherwise: bb7]; + } + + bb13: { + StorageLive(_36); +- _36 = copy _32 as *mut u8 (Transmute); ++ _36 = copy _34 as *mut u8 (Transmute); + StorageLive(_37); + StorageLive(_39); +- _39 = copy _42; ++ _39 = copy _43; + StorageLive(_38); +- _38 = discriminant(_39); ++ _38 = discriminant(_43); + _37 = move _38 as usize (IntToInt); + StorageDead(_38); + StorageDead(_39); +- _26 = alloc::alloc::__rust_dealloc(move _36, move _35, move _37) -> [return: bb15, unwind unreachable]; ++ _26 = alloc::alloc::__rust_dealloc(move _36, copy _27, move _37) -> [return: bb15, unwind unreachable]; + } + + bb14: { + StorageDead(_35); + StorageDead(_40); + StorageDead(_42); + goto -> bb8; + } + + bb15: { + StorageDead(_37); + StorageDead(_36); + goto -> bb14; } + } + diff --git a/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.32bit.panic-unwind.diff b/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.32bit.panic-unwind.diff index b2085afb71379..05ce3741d88fe 100644 --- a/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.32bit.panic-unwind.diff +++ b/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.32bit.panic-unwind.diff @@ -11,6 +11,8 @@ let mut _9: std::boxed::Box<()>; let mut _10: *const (); let mut _11: usize; + let mut _28: usize; + let mut _30: std::ptr::alignment::AlignmentEnum; scope 1 { debug vp_ctx => _1; let _4: *const (); @@ -32,11 +34,78 @@ } } } + scope 8 (inlined drop_in_place::> - shim(Some(Box<()>))) { + scope 9 (inlined as Drop>::drop) { + let mut _12: *const (); + let mut _13: *mut (); + let _14: (); + let _22: std::ptr::NonNull<()>; + scope 10 { + let _29: usize; + let _31: std::ptr::alignment::AlignmentEnum; + scope 11 { + scope 19 (inlined Layout::size) { + } + scope 20 (inlined Unique::<()>::cast::) { + let mut _20: std::ptr::NonNull; + scope 21 (inlined NonNull::<()>::cast::) { + let mut _21: *const u8; + scope 22 (inlined NonNull::<()>::as_ptr) { + } + } + } + scope 23 (inlined as From>>::from) { + scope 24 (inlined Unique::::as_non_null_ptr) { + } + } + scope 25 (inlined ::deallocate) { + let mut _23: usize; + let mut _24: *mut u8; + scope 26 (inlined Layout::size) { + } + scope 27 (inlined NonNull::::as_ptr) { + } + scope 28 (inlined std::alloc::dealloc) { + let mut _25: usize; + scope 29 (inlined Layout::size) { + } + scope 30 (inlined Layout::align) { + let mut _27: std::ptr::alignment::AlignmentEnum; + scope 31 (inlined std::ptr::Alignment::as_usize) { + let mut _26: u32; + } + } + } + } + } + scope 12 (inlined Unique::<()>::as_ptr) { + scope 13 (inlined NonNull::<()>::as_ptr) { + } + } + scope 14 (inlined Layout::for_value_raw::<()>) { + let mut _15: usize; + let mut _16: usize; + scope 15 { + scope 18 (inlined #[track_caller] Layout::from_size_align_unchecked) { + let mut _17: bool; + let _18: (); + let mut _19: std::ptr::Alignment; + } + } + scope 16 (inlined size_of_val_raw::<()>) { + } + scope 17 (inlined align_of_val_raw::<()>) { + } + } + } + } + } bb0: { StorageLive(_1); StorageLive(_2); - StorageLive(_3); +- StorageLive(_3); ++ nop; _3 = Box::<()>::new(const ()) -> [return: bb1, unwind continue]; } @@ -46,8 +115,9 @@ StorageDead(_2); StorageLive(_4); - _9 = deref_copy _3; +- _10 = copy ((_9.0: std::ptr::Unique<()>).0: std::ptr::NonNull<()>) as *const () (Transmute); + _9 = copy _3; - _10 = copy ((_9.0: std::ptr::Unique<()>).0: std::ptr::NonNull<()>) as *const () (Transmute); ++ _10 = copy ((_3.0: std::ptr::Unique<()>).0: std::ptr::NonNull<()>) as *const () (Transmute); _4 = copy _10; - StorageLive(_5); + nop; @@ -60,27 +130,130 @@ + _5 = *const [()] from (copy _10, const 1_usize); StorageDead(_11); StorageDead(_6); - StorageLive(_7); +- StorageLive(_7); ++ nop; StorageLive(_8); _8 = copy _5; - _7 = copy _8 as *mut () (PtrToPtr); -+ _7 = copy ((_9.0: std::ptr::Unique<()>).0: std::ptr::NonNull<()>) as *mut () (Transmute); ++ _7 = copy ((_3.0: std::ptr::Unique<()>).0: std::ptr::NonNull<()>) as *mut () (Transmute); StorageDead(_8); - StorageDead(_7); +- StorageDead(_7); - StorageDead(_5); ++ nop; + nop; StorageDead(_4); - drop(_3) -> [return: bb2, unwind: bb3]; + StorageLive(_29); +- StorageLive(_31); ++ nop; + StorageLive(_13); +- StorageLive(_15); ++ nop; + StorageLive(_20); +- StorageLive(_22); ++ nop; + _22 = copy ((_3.0: std::ptr::Unique<()>).0: std::ptr::NonNull<()>); + StorageLive(_12); +- _13 = copy _22 as *mut () (Transmute); +- _12 = copy _22 as *const () (Transmute); ++ _13 = copy _7; ++ _12 = copy _10; + StorageLive(_16); +- _15 = std::intrinsics::size_of_val::<()>(copy _12) -> [return: bb4, unwind unreachable]; ++ _15 = std::intrinsics::size_of_val::<()>(copy _10) -> [return: bb4, unwind unreachable]; } bb2: { - StorageDead(_3); + StorageLive(_21); +- _21 = copy _13 as *const u8 (PtrToPtr); ++ _21 = copy _22 as *const u8 (Transmute); + _20 = NonNull:: { pointer: move _21 }; + StorageDead(_21); + StorageLive(_28); + StorageLive(_30); +- _28 = copy _29; ++ _28 = copy _15; + _30 = copy _31; + StorageLive(_23); +- _23 = copy _28; +- switchInt(move _23) -> [0: bb9, otherwise: bb8]; ++ _23 = copy _15; ++ switchInt(copy _15) -> [0: bb9, otherwise: bb8]; + } + + bb3: { +- StorageDead(_22); ++ nop; + StorageDead(_20); +- StorageDead(_15); ++ nop; + StorageDead(_13); + StorageDead(_29); +- StorageDead(_31); +- StorageDead(_3); ++ nop; ++ nop; StorageDead(_1); return; } - bb3 (cleanup): { - resume; + bb4: { +- _16 = std::intrinsics::align_of_val::<()>(move _12) -> [return: bb5, unwind unreachable]; ++ _16 = std::intrinsics::align_of_val::<()>(copy _10) -> [return: bb5, unwind unreachable]; + } + + bb5: { + StorageLive(_17); + _17 = const false; +- switchInt(move _17) -> [0: bb7, otherwise: bb6]; ++ switchInt(const false) -> [0: bb7, otherwise: bb6]; + } + + bb6: { + _18 = Layout::from_size_align_unchecked::precondition_check(copy _15, copy _16) -> [return: bb7, unwind unreachable]; + } + + bb7: { + StorageDead(_17); + StorageLive(_19); + _19 = copy _16 as std::ptr::Alignment (Transmute); + _29 = copy _15; + _31 = move (_19.0: std::ptr::alignment::AlignmentEnum); + StorageDead(_19); + StorageDead(_16); + StorageDead(_12); +- switchInt(move _15) -> [0: bb3, otherwise: bb2]; ++ switchInt(copy _15) -> [0: bb3, otherwise: bb2]; + } + + bb8: { + StorageLive(_24); +- _24 = copy _20 as *mut u8 (Transmute); ++ _24 = copy _22 as *mut u8 (Transmute); + StorageLive(_25); + StorageLive(_27); +- _27 = copy _30; ++ _27 = copy _31; + StorageLive(_26); +- _26 = discriminant(_27); ++ _26 = discriminant(_31); + _25 = move _26 as usize (IntToInt); + StorageDead(_26); + StorageDead(_27); +- _14 = alloc::alloc::__rust_dealloc(move _24, move _23, move _25) -> [return: bb10, unwind unreachable]; ++ _14 = alloc::alloc::__rust_dealloc(move _24, copy _15, move _25) -> [return: bb10, unwind unreachable]; + } + + bb9: { + StorageDead(_23); + StorageDead(_28); + StorageDead(_30); + goto -> bb3; + } + + bb10: { + StorageDead(_25); + StorageDead(_24); + goto -> bb9; } } diff --git a/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.64bit.panic-abort.diff b/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.64bit.panic-abort.diff index 839b53e3b0b3b..cab999f463960 100644 --- a/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.64bit.panic-abort.diff +++ b/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.64bit.panic-abort.diff @@ -11,6 +11,8 @@ let mut _9: std::boxed::Box<()>; let mut _10: *const (); let mut _23: usize; + let mut _40: usize; + let mut _42: std::ptr::alignment::AlignmentEnum; scope 1 { debug vp_ctx => _1; let _4: *const (); @@ -66,11 +68,78 @@ } } } + scope 19 (inlined drop_in_place::> - shim(Some(Box<()>))) { + scope 20 (inlined as Drop>::drop) { + let mut _24: *const (); + let mut _25: *mut (); + let _26: (); + let _34: std::ptr::NonNull<()>; + scope 21 { + let _41: usize; + let _43: std::ptr::alignment::AlignmentEnum; + scope 22 { + scope 30 (inlined Layout::size) { + } + scope 31 (inlined Unique::<()>::cast::) { + let mut _32: std::ptr::NonNull; + scope 32 (inlined NonNull::<()>::cast::) { + let mut _33: *const u8; + scope 33 (inlined NonNull::<()>::as_ptr) { + } + } + } + scope 34 (inlined as From>>::from) { + scope 35 (inlined Unique::::as_non_null_ptr) { + } + } + scope 36 (inlined ::deallocate) { + let mut _35: usize; + let mut _36: *mut u8; + scope 37 (inlined Layout::size) { + } + scope 38 (inlined NonNull::::as_ptr) { + } + scope 39 (inlined std::alloc::dealloc) { + let mut _37: usize; + scope 40 (inlined Layout::size) { + } + scope 41 (inlined Layout::align) { + let mut _39: std::ptr::alignment::AlignmentEnum; + scope 42 (inlined std::ptr::Alignment::as_usize) { + let mut _38: u64; + } + } + } + } + } + scope 23 (inlined Unique::<()>::as_ptr) { + scope 24 (inlined NonNull::<()>::as_ptr) { + } + } + scope 25 (inlined Layout::for_value_raw::<()>) { + let mut _27: usize; + let mut _28: usize; + scope 26 { + scope 29 (inlined #[track_caller] Layout::from_size_align_unchecked) { + let mut _29: bool; + let _30: (); + let mut _31: std::ptr::Alignment; + } + } + scope 27 (inlined size_of_val_raw::<()>) { + } + scope 28 (inlined align_of_val_raw::<()>) { + } + } + } + } + } bb0: { StorageLive(_1); StorageLive(_2); - StorageLive(_3); +- StorageLive(_3); ++ nop; StorageLive(_11); StorageLive(_12); StorageLive(_13); @@ -81,28 +150,23 @@ StorageLive(_14); StorageLive(_16); StorageLive(_17); - StorageLive(_19); +- StorageLive(_19); ++ nop; _19 = const false; -- switchInt(move _19) -> [0: bb6, otherwise: bb5]; -+ switchInt(const false) -> [0: bb6, otherwise: bb5]; +- switchInt(move _19) -> [0: bb5, otherwise: bb4]; ++ switchInt(const false) -> [0: bb5, otherwise: bb4]; } bb1: { - StorageDead(_3); - StorageDead(_1); - return; - } - - bb2: { unreachable; } - bb3: { + bb2: { - _18 = handle_alloc_error(move _14) -> unwind unreachable; + _18 = handle_alloc_error(const Layout {{ size: 0_usize, align: std::ptr::Alignment(std::ptr::alignment::AlignmentEnum::_Align1Shl0) }}) -> unwind unreachable; } - bb4: { + bb3: { _17 = copy ((_15 as Ok).0: std::ptr::NonNull<[u8]>); StorageLive(_22); _22 = copy _17 as *mut [u8] (Transmute); @@ -121,8 +185,9 @@ StorageDead(_2); StorageLive(_4); - _9 = deref_copy _3; +- _10 = copy ((_9.0: std::ptr::Unique<()>).0: std::ptr::NonNull<()>) as *const () (Transmute); + _9 = copy _3; - _10 = copy ((_9.0: std::ptr::Unique<()>).0: std::ptr::NonNull<()>) as *const () (Transmute); ++ _10 = copy ((_3.0: std::ptr::Unique<()>).0: std::ptr::NonNull<()>) as *const () (Transmute); _4 = copy _10; - StorageLive(_5); + nop; @@ -135,26 +200,46 @@ + _5 = *const [()] from (copy _10, const 1_usize); StorageDead(_23); StorageDead(_6); - StorageLive(_7); +- StorageLive(_7); ++ nop; StorageLive(_8); _8 = copy _5; - _7 = copy _8 as *mut () (PtrToPtr); -+ _7 = copy ((_9.0: std::ptr::Unique<()>).0: std::ptr::NonNull<()>) as *mut () (Transmute); ++ _7 = copy ((_3.0: std::ptr::Unique<()>).0: std::ptr::NonNull<()>) as *mut () (Transmute); StorageDead(_8); - StorageDead(_7); +- StorageDead(_7); - StorageDead(_5); ++ nop; + nop; StorageDead(_4); - drop(_3) -> [return: bb1, unwind unreachable]; + StorageLive(_41); +- StorageLive(_43); ++ nop; + StorageLive(_25); +- StorageLive(_27); ++ nop; + StorageLive(_32); +- StorageLive(_34); ++ nop; + _34 = copy ((_3.0: std::ptr::Unique<()>).0: std::ptr::NonNull<()>); + StorageLive(_24); +- _25 = copy _34 as *mut () (Transmute); +- _24 = copy _34 as *const () (Transmute); ++ _25 = copy _7; ++ _24 = copy _10; + StorageLive(_28); +- _27 = std::intrinsics::size_of_val::<()>(copy _24) -> [return: bb9, unwind unreachable]; ++ _27 = std::intrinsics::size_of_val::<()>(copy _10) -> [return: bb9, unwind unreachable]; } - bb5: { -- _20 = Layout::from_size_align_unchecked::precondition_check(copy _11, copy _12) -> [return: bb6, unwind unreachable]; -+ _20 = Layout::from_size_align_unchecked::precondition_check(const 0_usize, const 1_usize) -> [return: bb6, unwind unreachable]; + bb4: { +- _20 = Layout::from_size_align_unchecked::precondition_check(copy _11, copy _12) -> [return: bb5, unwind unreachable]; ++ _20 = Layout::from_size_align_unchecked::precondition_check(const 0_usize, const 1_usize) -> [return: bb5, unwind unreachable]; } - bb6: { - StorageDead(_19); + bb5: { +- StorageDead(_19); ++ nop; StorageLive(_21); - _21 = copy _12 as std::ptr::Alignment (Transmute); - _14 = Layout { size: copy _11, align: move _21 }; @@ -162,13 +247,107 @@ + _14 = const Layout {{ size: 0_usize, align: std::ptr::Alignment(std::ptr::alignment::AlignmentEnum::_Align1Shl0) }}; StorageDead(_21); StorageLive(_15); -- _15 = std::alloc::Global::alloc_impl(const alloc::alloc::exchange_malloc::promoted[0], copy _14, const false) -> [return: bb7, unwind unreachable]; -+ _15 = std::alloc::Global::alloc_impl(const alloc::alloc::exchange_malloc::promoted[0], const Layout {{ size: 0_usize, align: std::ptr::Alignment(std::ptr::alignment::AlignmentEnum::_Align1Shl0) }}, const false) -> [return: bb7, unwind unreachable]; +- _15 = std::alloc::Global::alloc_impl(const alloc::alloc::exchange_malloc::promoted[0], copy _14, const false) -> [return: bb6, unwind unreachable]; ++ _15 = std::alloc::Global::alloc_impl(const alloc::alloc::exchange_malloc::promoted[0], const Layout {{ size: 0_usize, align: std::ptr::Alignment(std::ptr::alignment::AlignmentEnum::_Align1Shl0) }}, const false) -> [return: bb6, unwind unreachable]; } - bb7: { + bb6: { _16 = discriminant(_15); - switchInt(move _16) -> [0: bb4, 1: bb3, otherwise: bb2]; + switchInt(move _16) -> [0: bb3, 1: bb2, otherwise: bb1]; + } + + bb7: { + StorageLive(_33); +- _33 = copy _25 as *const u8 (PtrToPtr); ++ _33 = copy _34 as *const u8 (Transmute); + _32 = NonNull:: { pointer: move _33 }; + StorageDead(_33); + StorageLive(_40); + StorageLive(_42); +- _40 = copy _41; ++ _40 = copy _27; + _42 = copy _43; + StorageLive(_35); +- _35 = copy _40; +- switchInt(move _35) -> [0: bb14, otherwise: bb13]; ++ _35 = copy _27; ++ switchInt(copy _27) -> [0: bb14, otherwise: bb13]; + } + + bb8: { +- StorageDead(_34); ++ nop; + StorageDead(_32); +- StorageDead(_27); ++ nop; + StorageDead(_25); + StorageDead(_41); +- StorageDead(_43); +- StorageDead(_3); ++ nop; ++ nop; + StorageDead(_1); + return; + } + + bb9: { +- _28 = std::intrinsics::align_of_val::<()>(move _24) -> [return: bb10, unwind unreachable]; ++ _28 = std::intrinsics::align_of_val::<()>(copy _10) -> [return: bb10, unwind unreachable]; + } + + bb10: { + StorageLive(_29); + _29 = const false; +- switchInt(move _29) -> [0: bb12, otherwise: bb11]; ++ switchInt(const false) -> [0: bb12, otherwise: bb11]; + } + + bb11: { + _30 = Layout::from_size_align_unchecked::precondition_check(copy _27, copy _28) -> [return: bb12, unwind unreachable]; + } + + bb12: { + StorageDead(_29); + StorageLive(_31); + _31 = copy _28 as std::ptr::Alignment (Transmute); + _41 = copy _27; + _43 = move (_31.0: std::ptr::alignment::AlignmentEnum); + StorageDead(_31); + StorageDead(_28); + StorageDead(_24); +- switchInt(move _27) -> [0: bb8, otherwise: bb7]; ++ switchInt(copy _27) -> [0: bb8, otherwise: bb7]; + } + + bb13: { + StorageLive(_36); +- _36 = copy _32 as *mut u8 (Transmute); ++ _36 = copy _34 as *mut u8 (Transmute); + StorageLive(_37); + StorageLive(_39); +- _39 = copy _42; ++ _39 = copy _43; + StorageLive(_38); +- _38 = discriminant(_39); ++ _38 = discriminant(_43); + _37 = move _38 as usize (IntToInt); + StorageDead(_38); + StorageDead(_39); +- _26 = alloc::alloc::__rust_dealloc(move _36, move _35, move _37) -> [return: bb15, unwind unreachable]; ++ _26 = alloc::alloc::__rust_dealloc(move _36, copy _27, move _37) -> [return: bb15, unwind unreachable]; + } + + bb14: { + StorageDead(_35); + StorageDead(_40); + StorageDead(_42); + goto -> bb8; + } + + bb15: { + StorageDead(_37); + StorageDead(_36); + goto -> bb14; } + } + diff --git a/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.64bit.panic-unwind.diff b/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.64bit.panic-unwind.diff index b2085afb71379..cce8eec87ec53 100644 --- a/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.64bit.panic-unwind.diff +++ b/tests/mir-opt/dont_reset_cast_kind_without_updating_operand.test.GVN.64bit.panic-unwind.diff @@ -11,6 +11,8 @@ let mut _9: std::boxed::Box<()>; let mut _10: *const (); let mut _11: usize; + let mut _28: usize; + let mut _30: std::ptr::alignment::AlignmentEnum; scope 1 { debug vp_ctx => _1; let _4: *const (); @@ -32,11 +34,78 @@ } } } + scope 8 (inlined drop_in_place::> - shim(Some(Box<()>))) { + scope 9 (inlined as Drop>::drop) { + let mut _12: *const (); + let mut _13: *mut (); + let _14: (); + let _22: std::ptr::NonNull<()>; + scope 10 { + let _29: usize; + let _31: std::ptr::alignment::AlignmentEnum; + scope 11 { + scope 19 (inlined Layout::size) { + } + scope 20 (inlined Unique::<()>::cast::) { + let mut _20: std::ptr::NonNull; + scope 21 (inlined NonNull::<()>::cast::) { + let mut _21: *const u8; + scope 22 (inlined NonNull::<()>::as_ptr) { + } + } + } + scope 23 (inlined as From>>::from) { + scope 24 (inlined Unique::::as_non_null_ptr) { + } + } + scope 25 (inlined ::deallocate) { + let mut _23: usize; + let mut _24: *mut u8; + scope 26 (inlined Layout::size) { + } + scope 27 (inlined NonNull::::as_ptr) { + } + scope 28 (inlined std::alloc::dealloc) { + let mut _25: usize; + scope 29 (inlined Layout::size) { + } + scope 30 (inlined Layout::align) { + let mut _27: std::ptr::alignment::AlignmentEnum; + scope 31 (inlined std::ptr::Alignment::as_usize) { + let mut _26: u64; + } + } + } + } + } + scope 12 (inlined Unique::<()>::as_ptr) { + scope 13 (inlined NonNull::<()>::as_ptr) { + } + } + scope 14 (inlined Layout::for_value_raw::<()>) { + let mut _15: usize; + let mut _16: usize; + scope 15 { + scope 18 (inlined #[track_caller] Layout::from_size_align_unchecked) { + let mut _17: bool; + let _18: (); + let mut _19: std::ptr::Alignment; + } + } + scope 16 (inlined size_of_val_raw::<()>) { + } + scope 17 (inlined align_of_val_raw::<()>) { + } + } + } + } + } bb0: { StorageLive(_1); StorageLive(_2); - StorageLive(_3); +- StorageLive(_3); ++ nop; _3 = Box::<()>::new(const ()) -> [return: bb1, unwind continue]; } @@ -46,8 +115,9 @@ StorageDead(_2); StorageLive(_4); - _9 = deref_copy _3; +- _10 = copy ((_9.0: std::ptr::Unique<()>).0: std::ptr::NonNull<()>) as *const () (Transmute); + _9 = copy _3; - _10 = copy ((_9.0: std::ptr::Unique<()>).0: std::ptr::NonNull<()>) as *const () (Transmute); ++ _10 = copy ((_3.0: std::ptr::Unique<()>).0: std::ptr::NonNull<()>) as *const () (Transmute); _4 = copy _10; - StorageLive(_5); + nop; @@ -60,27 +130,130 @@ + _5 = *const [()] from (copy _10, const 1_usize); StorageDead(_11); StorageDead(_6); - StorageLive(_7); +- StorageLive(_7); ++ nop; StorageLive(_8); _8 = copy _5; - _7 = copy _8 as *mut () (PtrToPtr); -+ _7 = copy ((_9.0: std::ptr::Unique<()>).0: std::ptr::NonNull<()>) as *mut () (Transmute); ++ _7 = copy ((_3.0: std::ptr::Unique<()>).0: std::ptr::NonNull<()>) as *mut () (Transmute); StorageDead(_8); - StorageDead(_7); +- StorageDead(_7); - StorageDead(_5); ++ nop; + nop; StorageDead(_4); - drop(_3) -> [return: bb2, unwind: bb3]; + StorageLive(_29); +- StorageLive(_31); ++ nop; + StorageLive(_13); +- StorageLive(_15); ++ nop; + StorageLive(_20); +- StorageLive(_22); ++ nop; + _22 = copy ((_3.0: std::ptr::Unique<()>).0: std::ptr::NonNull<()>); + StorageLive(_12); +- _13 = copy _22 as *mut () (Transmute); +- _12 = copy _22 as *const () (Transmute); ++ _13 = copy _7; ++ _12 = copy _10; + StorageLive(_16); +- _15 = std::intrinsics::size_of_val::<()>(copy _12) -> [return: bb4, unwind unreachable]; ++ _15 = std::intrinsics::size_of_val::<()>(copy _10) -> [return: bb4, unwind unreachable]; } bb2: { - StorageDead(_3); + StorageLive(_21); +- _21 = copy _13 as *const u8 (PtrToPtr); ++ _21 = copy _22 as *const u8 (Transmute); + _20 = NonNull:: { pointer: move _21 }; + StorageDead(_21); + StorageLive(_28); + StorageLive(_30); +- _28 = copy _29; ++ _28 = copy _15; + _30 = copy _31; + StorageLive(_23); +- _23 = copy _28; +- switchInt(move _23) -> [0: bb9, otherwise: bb8]; ++ _23 = copy _15; ++ switchInt(copy _15) -> [0: bb9, otherwise: bb8]; + } + + bb3: { +- StorageDead(_22); ++ nop; + StorageDead(_20); +- StorageDead(_15); ++ nop; + StorageDead(_13); + StorageDead(_29); +- StorageDead(_31); +- StorageDead(_3); ++ nop; ++ nop; StorageDead(_1); return; } - bb3 (cleanup): { - resume; + bb4: { +- _16 = std::intrinsics::align_of_val::<()>(move _12) -> [return: bb5, unwind unreachable]; ++ _16 = std::intrinsics::align_of_val::<()>(copy _10) -> [return: bb5, unwind unreachable]; + } + + bb5: { + StorageLive(_17); + _17 = const false; +- switchInt(move _17) -> [0: bb7, otherwise: bb6]; ++ switchInt(const false) -> [0: bb7, otherwise: bb6]; + } + + bb6: { + _18 = Layout::from_size_align_unchecked::precondition_check(copy _15, copy _16) -> [return: bb7, unwind unreachable]; + } + + bb7: { + StorageDead(_17); + StorageLive(_19); + _19 = copy _16 as std::ptr::Alignment (Transmute); + _29 = copy _15; + _31 = move (_19.0: std::ptr::alignment::AlignmentEnum); + StorageDead(_19); + StorageDead(_16); + StorageDead(_12); +- switchInt(move _15) -> [0: bb3, otherwise: bb2]; ++ switchInt(copy _15) -> [0: bb3, otherwise: bb2]; + } + + bb8: { + StorageLive(_24); +- _24 = copy _20 as *mut u8 (Transmute); ++ _24 = copy _22 as *mut u8 (Transmute); + StorageLive(_25); + StorageLive(_27); +- _27 = copy _30; ++ _27 = copy _31; + StorageLive(_26); +- _26 = discriminant(_27); ++ _26 = discriminant(_31); + _25 = move _26 as usize (IntToInt); + StorageDead(_26); + StorageDead(_27); +- _14 = alloc::alloc::__rust_dealloc(move _24, move _23, move _25) -> [return: bb10, unwind unreachable]; ++ _14 = alloc::alloc::__rust_dealloc(move _24, copy _15, move _25) -> [return: bb10, unwind unreachable]; + } + + bb9: { + StorageDead(_23); + StorageDead(_28); + StorageDead(_30); + goto -> bb3; + } + + bb10: { + StorageDead(_25); + StorageDead(_24); + goto -> bb9; } } diff --git a/tests/mir-opt/inline/asm_unwind.main.Inline.panic-unwind.diff b/tests/mir-opt/inline/asm_unwind.main.Inline.panic-unwind.diff index dc0004105a7b7..6c55e4a8511fd 100644 --- a/tests/mir-opt/inline/asm_unwind.main.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/asm_unwind.main.Inline.panic-unwind.diff @@ -5,35 +5,40 @@ let mut _0: (); let _1: (); + scope 1 (inlined foo) { -+ let _2: D; ++ let mut _2: *mut D; ++ let _3: D; + scope 2 { + debug _d => const D; + } ++ scope 3 (inlined drop_in_place:: - shim(Some(D))) { ++ scope 4 (inlined ::drop) { ++ debug self => _2; ++ } ++ } + } bb0: { StorageLive(_1); - _1 = foo() -> [return: bb1, unwind continue]; + StorageLive(_2); -+ asm!("", options(MAY_UNWIND)) -> [return: bb2, unwind: bb3]; ++ StorageLive(_3); ++ asm!("", options(MAY_UNWIND)) -> [return: bb1, unwind: bb2]; } bb1: { ++ _2 = &raw mut _3; ++ StorageDead(_3); + StorageDead(_2); StorageDead(_1); _0 = const (); return; + } + -+ bb2: { -+ drop(_2) -> [return: bb1, unwind continue]; ++ bb2 (cleanup): { ++ drop(_3) -> [return: bb3, unwind terminate(cleanup)]; + } + + bb3 (cleanup): { -+ drop(_2) -> [return: bb4, unwind terminate(cleanup)]; -+ } -+ -+ bb4 (cleanup): { + resume; } } diff --git a/tests/mir-opt/inline/dont_ice_on_generic_rust_call.call.Inline.panic-abort.diff b/tests/mir-opt/inline/dont_ice_on_generic_rust_call.call.Inline.panic-abort.diff index 0615f8132af00..97c6cf4251d27 100644 --- a/tests/mir-opt/inline/dont_ice_on_generic_rust_call.call.Inline.panic-abort.diff +++ b/tests/mir-opt/inline/dont_ice_on_generic_rust_call.call.Inline.panic-abort.diff @@ -7,10 +7,90 @@ let mut _0: (); let mut _3: &mut std::boxed::Box>; let mut _4: I; ++ let mut _8: *mut std::boxed::Box>; ++ let mut _9: (); ++ let mut _30: std::alloc::Layout; + scope 1 (inlined > as FnMut>::call_mut) { + let mut _5: &mut dyn std::ops::FnMut; + let mut _6: std::boxed::Box>; + let mut _7: *const dyn std::ops::FnMut; ++ } ++ scope 2 (inlined drop_in_place::>> - shim(Some(Box>))) { ++ let mut _10: &mut std::boxed::Box>; ++ let mut _11: (); ++ let mut _12: &mut std::boxed::Box>; ++ let mut _13: (); ++ let mut _14: *const dyn std::ops::FnMut; ++ scope 3 (inlined > as Drop>::drop) { ++ let mut _16: *const dyn std::ops::FnMut; ++ let mut _17: *mut dyn std::ops::FnMut; ++ let mut _18: &std::alloc::Layout; ++ let _19: (); ++ let mut _20: &std::alloc::Global; ++ let _28: std::ptr::NonNull>; ++ let _29: std::marker::PhantomData>; ++ scope 4 { ++ let _15: std::alloc::Layout; ++ scope 5 { ++ scope 13 (inlined Layout::size) { ++ } ++ scope 14 (inlined Unique::>::cast::) { ++ let mut _26: std::ptr::NonNull; ++ scope 15 (inlined NonNull::>::cast::) { ++ let mut _27: *const u8; ++ scope 16 (inlined NonNull::>::as_ptr) { ++ } ++ } ++ } ++ scope 17 (inlined as From>>::from) { ++ scope 18 (inlined Unique::::as_non_null_ptr) { ++ } ++ } ++ scope 19 (inlined ::deallocate) { ++ let mut _31: usize; ++ let mut _32: &std::alloc::Layout; ++ let mut _33: *mut u8; ++ let mut _34: std::alloc::Layout; ++ scope 20 (inlined Layout::size) { ++ } ++ scope 21 (inlined NonNull::::as_ptr) { ++ } ++ scope 22 (inlined std::alloc::dealloc) { ++ let mut _35: &std::alloc::Layout; ++ let mut _36: usize; ++ let mut _37: &std::alloc::Layout; ++ scope 23 (inlined Layout::size) { ++ } ++ scope 24 (inlined Layout::align) { ++ let mut _39: std::ptr::alignment::AlignmentEnum; ++ scope 25 (inlined std::ptr::Alignment::as_usize) { ++ let mut _38: u64; ++ } ++ } ++ } ++ } ++ } ++ scope 6 (inlined Unique::>::as_ptr) { ++ scope 7 (inlined NonNull::>::as_ptr) { ++ } ++ } ++ scope 8 (inlined Layout::for_value_raw::>) { ++ let mut _21: usize; ++ let mut _22: usize; ++ scope 9 { ++ scope 12 (inlined #[track_caller] Layout::from_size_align_unchecked) { ++ let mut _23: bool; ++ let _24: (); ++ let mut _25: std::ptr::Alignment; ++ } ++ } ++ scope 10 (inlined size_of_val_raw::>) { ++ } ++ scope 11 (inlined align_of_val_raw::>) { ++ } ++ } ++ } ++ } + } bb0: { @@ -25,24 +105,141 @@ + _6 = copy (*_3); + _7 = copy ((_6.0: std::ptr::Unique>).0: std::ptr::NonNull>) as *const dyn std::ops::FnMut (Transmute); + _5 = &mut (*_7); -+ _0 = as FnMut>::call_mut(move _5, move _4) -> [return: bb2, unwind unreachable]; ++ _0 = as FnMut>::call_mut(move _5, move _4) -> [return: bb1, unwind unreachable]; } bb1: { -- StorageDead(_4); -- StorageDead(_3); ++ StorageDead(_5); ++ StorageDead(_7); ++ StorageDead(_6); + StorageDead(_4); + StorageDead(_3); - drop(_1) -> [return: bb2, unwind unreachable]; -+ return; ++ _8 = &raw mut _1; ++ StorageLive(_10); ++ StorageLive(_11); ++ StorageLive(_12); ++ StorageLive(_13); ++ StorageLive(_14); ++ _14 = copy (((*_8).0: std::ptr::Unique>).0: std::ptr::NonNull>) as *const dyn std::ops::FnMut (Transmute); ++ drop((*_14)) -> [return: bb2, unwind unreachable]; } bb2: { -- return; -+ StorageDead(_5); -+ StorageDead(_7); -+ StorageDead(_6); -+ StorageDead(_4); -+ StorageDead(_3); -+ drop(_1) -> [return: bb1, unwind unreachable]; ++ _10 = &mut (*_8); ++ StorageLive(_15); ++ StorageLive(_17); ++ StorageLive(_19); ++ StorageLive(_21); ++ StorageLive(_24); ++ StorageLive(_26); ++ StorageLive(_28); ++ StorageLive(_29); ++ _28 = copy (((*_10).0: std::ptr::Unique>).0: std::ptr::NonNull>); ++ _29 = copy (((*_10).0: std::ptr::Unique>).1: std::marker::PhantomData>); ++ StorageLive(_16); ++ _17 = copy _28 as *mut dyn std::ops::FnMut (Transmute); ++ _16 = copy _28 as *const dyn std::ops::FnMut (Transmute); ++ StorageLive(_22); ++ _21 = std::intrinsics::size_of_val::>(copy _16) -> [return: bb5, unwind unreachable]; ++ } ++ ++ bb3: { ++ StorageLive(_20); ++ _20 = &((*_10).1: std::alloc::Global); ++ StorageLive(_27); ++ _27 = copy _17 as *const u8 (PtrToPtr); ++ _26 = NonNull:: { pointer: move _27 }; ++ StorageDead(_27); ++ StorageLive(_30); ++ _30 = copy _15; ++ StorageLive(_31); ++ StorageLive(_32); ++ _32 = &_30; ++ _31 = copy (_30.0: usize); ++ StorageDead(_32); ++ switchInt(move _31) -> [0: bb10, otherwise: bb9]; ++ } ++ ++ bb4: { ++ StorageDead(_29); ++ StorageDead(_28); ++ StorageDead(_26); ++ StorageDead(_24); ++ StorageDead(_21); ++ StorageDead(_19); ++ StorageDead(_17); ++ StorageDead(_15); ++ StorageDead(_14); ++ StorageDead(_13); ++ StorageDead(_12); ++ StorageDead(_11); ++ StorageDead(_10); + return; ++ } ++ ++ bb5: { ++ _22 = std::intrinsics::align_of_val::>(move _16) -> [return: bb6, unwind unreachable]; ++ } ++ ++ bb6: { ++ StorageLive(_23); ++ _23 = UbChecks(); ++ switchInt(move _23) -> [0: bb8, otherwise: bb7]; ++ } ++ ++ bb7: { ++ _24 = Layout::from_size_align_unchecked::precondition_check(copy _21, copy _22) -> [return: bb8, unwind unreachable]; ++ } ++ ++ bb8: { ++ StorageDead(_23); ++ StorageLive(_25); ++ _25 = copy _22 as std::ptr::Alignment (Transmute); ++ _15 = Layout { size: copy _21, align: move _25 }; ++ StorageDead(_25); ++ StorageDead(_22); ++ StorageDead(_16); ++ StorageLive(_18); ++ _18 = &_15; ++ StorageDead(_18); ++ switchInt(move _21) -> [0: bb4, otherwise: bb3]; ++ } ++ ++ bb9: { ++ StorageLive(_33); ++ _33 = copy _26 as *mut u8 (Transmute); ++ StorageLive(_34); ++ _34 = copy _30; ++ StorageLive(_35); ++ _35 = &_34; ++ StorageDead(_35); ++ StorageLive(_36); ++ StorageLive(_37); ++ _37 = &_34; ++ StorageLive(_39); ++ _39 = copy ((_30.1: std::ptr::Alignment).0: std::ptr::alignment::AlignmentEnum); ++ StorageLive(_38); ++ _38 = discriminant(_39); ++ _36 = move _38 as usize (IntToInt); ++ StorageDead(_38); ++ StorageDead(_39); ++ StorageDead(_37); ++ _19 = alloc::alloc::__rust_dealloc(move _33, move _31, move _36) -> [return: bb11, unwind unreachable]; ++ } ++ ++ bb10: { ++ StorageDead(_31); ++ StorageDead(_30); ++ StorageDead(_20); ++ goto -> bb4; ++ } ++ ++ bb11: { ++ StorageDead(_36); ++ StorageDead(_34); ++ StorageDead(_33); ++ goto -> bb10; } } diff --git a/tests/mir-opt/inline/inline_box_fn.call.Inline.panic-abort.diff b/tests/mir-opt/inline/inline_box_fn.call.Inline.panic-abort.diff index ecea7a97513d5..63bcc6835037a 100644 --- a/tests/mir-opt/inline/inline_box_fn.call.Inline.panic-abort.diff +++ b/tests/mir-opt/inline/inline_box_fn.call.Inline.panic-abort.diff @@ -7,10 +7,90 @@ let _2: (); let mut _3: &std::boxed::Box; let mut _4: (i32,); ++ let mut _8: *mut std::boxed::Box; ++ let mut _9: (); ++ let mut _30: std::alloc::Layout; + scope 1 (inlined as Fn<(i32,)>>::call) { + let mut _5: &dyn std::ops::Fn(i32); + let mut _6: std::boxed::Box; + let mut _7: *const dyn std::ops::Fn(i32); ++ } ++ scope 2 (inlined drop_in_place::> - shim(Some(Box))) { ++ let mut _10: &mut std::boxed::Box; ++ let mut _11: (); ++ let mut _12: &mut std::boxed::Box; ++ let mut _13: (); ++ let mut _14: *const dyn std::ops::Fn(i32); ++ scope 3 (inlined as Drop>::drop) { ++ let mut _16: *const dyn std::ops::Fn(i32); ++ let mut _17: *mut dyn std::ops::Fn(i32); ++ let mut _18: &std::alloc::Layout; ++ let _19: (); ++ let mut _20: &std::alloc::Global; ++ let _28: std::ptr::NonNull; ++ let _29: std::marker::PhantomData; ++ scope 4 { ++ let _15: std::alloc::Layout; ++ scope 5 { ++ scope 13 (inlined Layout::size) { ++ } ++ scope 14 (inlined Unique::::cast::) { ++ let mut _26: std::ptr::NonNull; ++ scope 15 (inlined NonNull::::cast::) { ++ let mut _27: *const u8; ++ scope 16 (inlined NonNull::::as_ptr) { ++ } ++ } ++ } ++ scope 17 (inlined as From>>::from) { ++ scope 18 (inlined Unique::::as_non_null_ptr) { ++ } ++ } ++ scope 19 (inlined ::deallocate) { ++ let mut _31: usize; ++ let mut _32: &std::alloc::Layout; ++ let mut _33: *mut u8; ++ let mut _34: std::alloc::Layout; ++ scope 20 (inlined Layout::size) { ++ } ++ scope 21 (inlined NonNull::::as_ptr) { ++ } ++ scope 22 (inlined std::alloc::dealloc) { ++ let mut _35: &std::alloc::Layout; ++ let mut _36: usize; ++ let mut _37: &std::alloc::Layout; ++ scope 23 (inlined Layout::size) { ++ } ++ scope 24 (inlined Layout::align) { ++ let mut _39: std::ptr::alignment::AlignmentEnum; ++ scope 25 (inlined std::ptr::Alignment::as_usize) { ++ let mut _38: u64; ++ } ++ } ++ } ++ } ++ } ++ scope 6 (inlined Unique::::as_ptr) { ++ scope 7 (inlined NonNull::::as_ptr) { ++ } ++ } ++ scope 8 (inlined Layout::for_value_raw::) { ++ let mut _21: usize; ++ let mut _22: usize; ++ scope 9 { ++ scope 12 (inlined #[track_caller] Layout::from_size_align_unchecked) { ++ let mut _23: bool; ++ let _24: (); ++ let mut _25: std::ptr::Alignment; ++ } ++ } ++ scope 10 (inlined size_of_val_raw::) { ++ } ++ scope 11 (inlined align_of_val_raw::) { ++ } ++ } ++ } ++ } + } bb0: { @@ -26,14 +106,10 @@ + _6 = copy (*_3); + _7 = copy ((_6.0: std::ptr::Unique).0: std::ptr::NonNull) as *const dyn std::ops::Fn(i32) (Transmute); + _5 = &(*_7); -+ _2 = >::call(move _5, move _4) -> [return: bb2, unwind unreachable]; ++ _2 = >::call(move _5, move _4) -> [return: bb1, unwind unreachable]; } bb1: { -+ return; -+ } -+ -+ bb2: { + StorageDead(_5); + StorageDead(_7); + StorageDead(_6); @@ -42,11 +118,131 @@ StorageDead(_2); _0 = const (); - drop(_1) -> [return: bb2, unwind unreachable]; -- } -- -- bb2: { -- return; -+ drop(_1) -> [return: bb1, unwind unreachable]; ++ _8 = &raw mut _1; ++ StorageLive(_10); ++ StorageLive(_11); ++ StorageLive(_12); ++ StorageLive(_13); ++ StorageLive(_14); ++ _14 = copy (((*_8).0: std::ptr::Unique).0: std::ptr::NonNull) as *const dyn std::ops::Fn(i32) (Transmute); ++ drop((*_14)) -> [return: bb2, unwind unreachable]; + } + + bb2: { ++ _10 = &mut (*_8); ++ StorageLive(_15); ++ StorageLive(_17); ++ StorageLive(_19); ++ StorageLive(_21); ++ StorageLive(_24); ++ StorageLive(_26); ++ StorageLive(_28); ++ StorageLive(_29); ++ _28 = copy (((*_10).0: std::ptr::Unique).0: std::ptr::NonNull); ++ _29 = copy (((*_10).0: std::ptr::Unique).1: std::marker::PhantomData); ++ StorageLive(_16); ++ _17 = copy _28 as *mut dyn std::ops::Fn(i32) (Transmute); ++ _16 = copy _28 as *const dyn std::ops::Fn(i32) (Transmute); ++ StorageLive(_22); ++ _21 = std::intrinsics::size_of_val::(copy _16) -> [return: bb5, unwind unreachable]; ++ } ++ ++ bb3: { ++ StorageLive(_20); ++ _20 = &((*_10).1: std::alloc::Global); ++ StorageLive(_27); ++ _27 = copy _17 as *const u8 (PtrToPtr); ++ _26 = NonNull:: { pointer: move _27 }; ++ StorageDead(_27); ++ StorageLive(_30); ++ _30 = copy _15; ++ StorageLive(_31); ++ StorageLive(_32); ++ _32 = &_30; ++ _31 = copy (_30.0: usize); ++ StorageDead(_32); ++ switchInt(move _31) -> [0: bb10, otherwise: bb9]; ++ } ++ ++ bb4: { ++ StorageDead(_29); ++ StorageDead(_28); ++ StorageDead(_26); ++ StorageDead(_24); ++ StorageDead(_21); ++ StorageDead(_19); ++ StorageDead(_17); ++ StorageDead(_15); ++ StorageDead(_14); ++ StorageDead(_13); ++ StorageDead(_12); ++ StorageDead(_11); ++ StorageDead(_10); + return; ++ } ++ ++ bb5: { ++ _22 = std::intrinsics::align_of_val::(move _16) -> [return: bb6, unwind unreachable]; ++ } ++ ++ bb6: { ++ StorageLive(_23); ++ _23 = UbChecks(); ++ switchInt(move _23) -> [0: bb8, otherwise: bb7]; ++ } ++ ++ bb7: { ++ _24 = Layout::from_size_align_unchecked::precondition_check(copy _21, copy _22) -> [return: bb8, unwind unreachable]; ++ } ++ ++ bb8: { ++ StorageDead(_23); ++ StorageLive(_25); ++ _25 = copy _22 as std::ptr::Alignment (Transmute); ++ _15 = Layout { size: copy _21, align: move _25 }; ++ StorageDead(_25); ++ StorageDead(_22); ++ StorageDead(_16); ++ StorageLive(_18); ++ _18 = &_15; ++ StorageDead(_18); ++ switchInt(move _21) -> [0: bb4, otherwise: bb3]; ++ } ++ ++ bb9: { ++ StorageLive(_33); ++ _33 = copy _26 as *mut u8 (Transmute); ++ StorageLive(_34); ++ _34 = copy _30; ++ StorageLive(_35); ++ _35 = &_34; ++ StorageDead(_35); ++ StorageLive(_36); ++ StorageLive(_37); ++ _37 = &_34; ++ StorageLive(_39); ++ _39 = copy ((_30.1: std::ptr::Alignment).0: std::ptr::alignment::AlignmentEnum); ++ StorageLive(_38); ++ _38 = discriminant(_39); ++ _36 = move _38 as usize (IntToInt); ++ StorageDead(_38); ++ StorageDead(_39); ++ StorageDead(_37); ++ _19 = alloc::alloc::__rust_dealloc(move _33, move _31, move _36) -> [return: bb11, unwind unreachable]; ++ } ++ ++ bb10: { ++ StorageDead(_31); ++ StorageDead(_30); ++ StorageDead(_20); ++ goto -> bb4; ++ } ++ ++ bb11: { ++ StorageDead(_36); ++ StorageDead(_34); ++ StorageDead(_33); ++ goto -> bb10; } } diff --git a/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-abort.diff b/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-abort.diff index 151580da19e09..ebd1ed5c05aca 100644 --- a/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-abort.diff +++ b/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-abort.diff @@ -8,6 +8,8 @@ let mut _3: &mut {coroutine@$DIR/inline_coroutine.rs:20:5: 20:8}; let mut _4: {coroutine@$DIR/inline_coroutine.rs:20:5: 20:8}; + let mut _5: bool; ++ let mut _9: *mut {coroutine@$DIR/inline_coroutine.rs:20:5: 20:8}; ++ let mut _10: (); scope 1 { debug _r => _1; } @@ -23,6 +25,15 @@ + let mut _6: &mut {coroutine@$DIR/inline_coroutine.rs:20:5: 20:8}; + let mut _7: u32; + let mut _8: i32; ++ } ++ scope 6 (inlined drop_in_place::<{coroutine@$DIR/inline_coroutine.rs:20:5: 20:8}> - shim(Some({coroutine@$DIR/inline_coroutine.rs:20:5: 20:8}))) { ++ debug a => _15; ++ let mut _11: bool; ++ let mut _12: i32; ++ let mut _13: bool; ++ let mut _14: bool; ++ let _15: bool; ++ let mut _16: u32; + } bb0: { @@ -41,70 +52,84 @@ + StorageLive(_7); + _6 = copy (_2.0: &mut {coroutine@$DIR/inline_coroutine.rs:20:5: 20:8}); + _7 = discriminant((*_6)); -+ switchInt(move _7) -> [0: bb3, 1: bb7, 3: bb8, otherwise: bb9]; ++ switchInt(move _7) -> [0: bb2, 1: bb6, 3: bb7, otherwise: bb8]; } bb1: { - _3 = &mut _4; - _2 = Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:20:5: 20:8}>::new(move _3) -> [return: bb2, unwind unreachable]; -+ StorageDead(_4); -+ _0 = const (); -+ StorageDead(_1); -+ return; ++ StorageDead(_7); ++ StorageDead(_6); ++ StorageDead(_5); ++ StorageDead(_2); ++ _9 = &raw mut _4; ++ StorageLive(_11); ++ StorageLive(_13); ++ StorageLive(_14); ++ StorageLive(_15); ++ StorageLive(_16); ++ _16 = discriminant((*_9)); ++ switchInt(move _16) -> [0: bb9, 3: bb10, otherwise: bb9]; } bb2: { - StorageDead(_3); - _1 = <{coroutine@$DIR/inline_coroutine.rs:20:5: 20:8} as Coroutine>::resume(move _2, const false) -> [return: bb3, unwind unreachable]; -+ StorageDead(_7); -+ StorageDead(_6); -+ StorageDead(_5); -+ StorageDead(_2); -+ drop(_4) -> [return: bb1, unwind unreachable]; ++ StorageLive(_8); ++ switchInt(copy _5) -> [0: bb3, otherwise: bb4]; } bb3: { - StorageDead(_2); - drop(_4) -> [return: bb4, unwind unreachable]; -+ StorageLive(_8); -+ switchInt(copy _5) -> [0: bb4, otherwise: bb5]; ++ _8 = const 13_i32; ++ goto -> bb5; } bb4: { -- StorageDead(_4); -- _0 = const (); -- StorageDead(_1); -- return; -+ _8 = const 13_i32; -+ goto -> bb6; -+ } -+ -+ bb5: { + _8 = const 7_i32; -+ goto -> bb6; ++ goto -> bb5; + } + -+ bb6: { ++ bb5: { + _1 = CoroutineState::::Yielded(move _8); + StorageDead(_8); + discriminant((*_6)) = 3; -+ goto -> bb2; ++ goto -> bb1; + } + -+ bb7: { -+ assert(const false, "coroutine resumed after completion") -> [success: bb7, unwind unreachable]; ++ bb6: { ++ assert(const false, "coroutine resumed after completion") -> [success: bb6, unwind unreachable]; + } + -+ bb8: { ++ bb7: { + StorageLive(_8); + StorageDead(_8); + _1 = CoroutineState::::Complete(copy _5); + discriminant((*_6)) = 1; -+ goto -> bb2; ++ goto -> bb1; + } + -+ bb9: { ++ bb8: { + unreachable; ++ } ++ ++ bb9: { ++ StorageDead(_16); ++ StorageDead(_15); ++ StorageDead(_14); ++ StorageDead(_13); ++ StorageDead(_11); + StorageDead(_4); + _0 = const (); + StorageDead(_1); + return; ++ } ++ ++ bb10: { ++ StorageLive(_12); ++ StorageDead(_12); ++ goto -> bb9; } } diff --git a/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-unwind.diff b/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-unwind.diff index 6196fc0d0c6bf..2ff1c2e994f0c 100644 --- a/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/inline_coroutine.main.Inline.panic-unwind.diff @@ -8,6 +8,8 @@ let mut _3: &mut {coroutine@$DIR/inline_coroutine.rs:20:5: 20:8}; let mut _4: {coroutine@$DIR/inline_coroutine.rs:20:5: 20:8}; + let mut _5: bool; ++ let mut _9: *mut {coroutine@$DIR/inline_coroutine.rs:20:5: 20:8}; ++ let mut _10: (); scope 1 { debug _r => _1; } @@ -23,6 +25,15 @@ + let mut _6: &mut {coroutine@$DIR/inline_coroutine.rs:20:5: 20:8}; + let mut _7: u32; + let mut _8: i32; ++ } ++ scope 6 (inlined drop_in_place::<{coroutine@$DIR/inline_coroutine.rs:20:5: 20:8}> - shim(Some({coroutine@$DIR/inline_coroutine.rs:20:5: 20:8}))) { ++ debug a => _15; ++ let mut _11: bool; ++ let mut _12: i32; ++ let mut _13: bool; ++ let mut _14: bool; ++ let _15: bool; ++ let mut _16: u32; + } bb0: { @@ -41,84 +52,99 @@ + StorageLive(_7); + _6 = copy (_2.0: &mut {coroutine@$DIR/inline_coroutine.rs:20:5: 20:8}); + _7 = discriminant((*_6)); -+ switchInt(move _7) -> [0: bb5, 1: bb9, 3: bb10, otherwise: bb11]; ++ switchInt(move _7) -> [0: bb4, 1: bb8, 3: bb9, otherwise: bb10]; } - bb1: { +- bb1: { - _3 = &mut _4; - _2 = Pin::<&mut {coroutine@$DIR/inline_coroutine.rs:20:5: 20:8}>::new(move _3) -> [return: bb2, unwind: bb5]; -+ StorageDead(_4); -+ _0 = const (); -+ StorageDead(_1); -+ return; ++ bb1 (cleanup): { ++ drop(_4) -> [return: bb2, unwind terminate(cleanup)]; } - bb2: { - StorageDead(_3); - _1 = <{coroutine@$DIR/inline_coroutine.rs:20:5: 20:8} as Coroutine>::resume(move _2, const false) -> [return: bb3, unwind: bb5]; + bb2 (cleanup): { -+ drop(_4) -> [return: bb3, unwind terminate(cleanup)]; - } - -- bb3: { -- StorageDead(_2); -- drop(_4) -> [return: bb4, unwind: bb6]; -+ bb3 (cleanup): { + resume; } - bb4: { -- StorageDead(_4); -- _0 = const (); -- StorageDead(_1); -- return; + bb3: { + StorageDead(_7); + StorageDead(_6); + StorageDead(_5); -+ StorageDead(_2); -+ drop(_4) -> [return: bb1, unwind: bb3]; + StorageDead(_2); +- drop(_4) -> [return: bb4, unwind: bb6]; ++ _9 = &raw mut _4; ++ StorageLive(_11); ++ StorageLive(_13); ++ StorageLive(_14); ++ StorageLive(_15); ++ StorageLive(_16); ++ _16 = discriminant((*_9)); ++ switchInt(move _16) -> [0: bb11, 3: bb12, otherwise: bb11]; } -- bb5 (cleanup): { -- drop(_4) -> [return: bb6, unwind terminate(cleanup)]; -+ bb5: { + bb4: { + StorageLive(_8); -+ switchInt(copy _5) -> [0: bb6, otherwise: bb7]; - } - -- bb6 (cleanup): { -- resume; -+ bb6: { ++ switchInt(copy _5) -> [0: bb5, otherwise: bb6]; ++ } ++ ++ bb5: { + _8 = const 13_i32; -+ goto -> bb8; ++ goto -> bb7; + } + -+ bb7: { ++ bb6: { + _8 = const 7_i32; -+ goto -> bb8; ++ goto -> bb7; + } + -+ bb8: { ++ bb7: { + _1 = CoroutineState::::Yielded(move _8); + StorageDead(_8); + discriminant((*_6)) = 3; -+ goto -> bb4; ++ goto -> bb3; + } + -+ bb9: { -+ assert(const false, "coroutine resumed after completion") -> [success: bb9, unwind: bb2]; ++ bb8: { ++ assert(const false, "coroutine resumed after completion") -> [success: bb8, unwind: bb1]; + } + -+ bb10: { ++ bb9: { + StorageLive(_8); + StorageDead(_8); + _1 = CoroutineState::::Complete(copy _5); + discriminant((*_6)) = 1; -+ goto -> bb4; ++ goto -> bb3; + } + -+ bb11: { ++ bb10: { + unreachable; ++ } ++ ++ bb11: { ++ StorageDead(_16); ++ StorageDead(_15); ++ StorageDead(_14); ++ StorageDead(_13); ++ StorageDead(_11); + StorageDead(_4); + _0 = const (); + StorageDead(_1); + return; + } + +- bb5 (cleanup): { +- drop(_4) -> [return: bb6, unwind terminate(cleanup)]; +- } +- +- bb6 (cleanup): { +- resume; ++ bb12: { ++ StorageLive(_12); ++ StorageDead(_12); ++ goto -> bb11; } } diff --git a/tests/mir-opt/inline/unsized_argument.caller.Inline.diff b/tests/mir-opt/inline/unsized_argument.caller.Inline.diff index 644d6d320de04..bc0f306cb96ec 100644 --- a/tests/mir-opt/inline/unsized_argument.caller.Inline.diff +++ b/tests/mir-opt/inline/unsized_argument.caller.Inline.diff @@ -7,32 +7,244 @@ let _2: (); let mut _3: std::boxed::Box<[i32]>; let mut _4: *const [i32]; ++ let mut _5: *mut std::boxed::Box<[i32]>; ++ let mut _6: (); ++ let mut _27: std::alloc::Layout; ++ scope 1 (inlined drop_in_place::> - shim(Some(Box<[i32]>))) { ++ let mut _7: &mut std::boxed::Box<[i32]>; ++ let mut _8: (); ++ let mut _9: &mut std::boxed::Box<[i32]>; ++ let mut _10: (); ++ let mut _11: *const [i32]; ++ scope 2 (inlined as Drop>::drop) { ++ let mut _13: *const [i32]; ++ let mut _14: *mut [i32]; ++ let mut _15: &std::alloc::Layout; ++ let _16: (); ++ let mut _17: &std::alloc::Global; ++ let _25: std::ptr::NonNull<[i32]>; ++ let _26: std::marker::PhantomData<[i32]>; ++ scope 3 { ++ let _12: std::alloc::Layout; ++ scope 4 { ++ scope 12 (inlined Layout::size) { ++ } ++ scope 13 (inlined Unique::<[i32]>::cast::) { ++ let mut _23: std::ptr::NonNull; ++ scope 14 (inlined NonNull::<[i32]>::cast::) { ++ let mut _24: *const u8; ++ scope 15 (inlined NonNull::<[i32]>::as_ptr) { ++ } ++ } ++ } ++ scope 16 (inlined as From>>::from) { ++ scope 17 (inlined Unique::::as_non_null_ptr) { ++ } ++ } ++ scope 18 (inlined ::deallocate) { ++ let mut _28: usize; ++ let mut _29: &std::alloc::Layout; ++ let mut _30: *mut u8; ++ let mut _31: std::alloc::Layout; ++ scope 19 (inlined Layout::size) { ++ } ++ scope 20 (inlined NonNull::::as_ptr) { ++ } ++ scope 21 (inlined std::alloc::dealloc) { ++ let mut _32: &std::alloc::Layout; ++ let mut _33: usize; ++ let mut _34: &std::alloc::Layout; ++ scope 22 (inlined Layout::size) { ++ } ++ scope 23 (inlined Layout::align) { ++ let mut _36: std::ptr::alignment::AlignmentEnum; ++ scope 24 (inlined std::ptr::Alignment::as_usize) { ++ let mut _35: u64; ++ } ++ } ++ } ++ } ++ } ++ scope 5 (inlined Unique::<[i32]>::as_ptr) { ++ scope 6 (inlined NonNull::<[i32]>::as_ptr) { ++ } ++ } ++ scope 7 (inlined Layout::for_value_raw::<[i32]>) { ++ let mut _18: usize; ++ let mut _19: usize; ++ scope 8 { ++ scope 11 (inlined #[track_caller] Layout::from_size_align_unchecked) { ++ let mut _20: bool; ++ let _21: (); ++ let mut _22: std::ptr::Alignment; ++ } ++ } ++ scope 9 (inlined size_of_val_raw::<[i32]>) { ++ } ++ scope 10 (inlined align_of_val_raw::<[i32]>) { ++ } ++ } ++ } ++ } ++ } bb0: { StorageLive(_2); StorageLive(_3); _3 = move _1; _4 = copy ((_3.0: std::ptr::Unique<[i32]>).0: std::ptr::NonNull<[i32]>) as *const [i32] (Transmute); - _2 = callee(move (*_4)) -> [return: bb1, unwind: bb3]; +- _2 = callee(move (*_4)) -> [return: bb1, unwind: bb3]; ++ _2 = callee(move (*_4)) -> [return: bb1, unwind: bb2]; } bb1: { - drop(_3) -> [return: bb2, unwind: bb4]; +- drop(_3) -> [return: bb2, unwind: bb4]; ++ _5 = &raw mut _3; ++ StorageLive(_7); ++ StorageLive(_8); ++ StorageLive(_9); ++ StorageLive(_10); ++ StorageLive(_11); ++ _11 = copy (((*_5).0: std::ptr::Unique<[i32]>).0: std::ptr::NonNull<[i32]>) as *const [i32] (Transmute); ++ drop((*_11)) -> [return: bb4, unwind: bb5]; } - bb2: { +- bb2: { ++ bb2 (cleanup): { ++ drop(_3) -> [return: bb3, unwind terminate(cleanup)]; ++ } ++ ++ bb3 (cleanup): { ++ resume; ++ } ++ ++ bb4: { ++ _7 = &mut (*_5); ++ StorageLive(_12); ++ StorageLive(_14); ++ StorageLive(_16); ++ StorageLive(_18); ++ StorageLive(_21); ++ StorageLive(_23); ++ StorageLive(_25); ++ StorageLive(_26); ++ _25 = copy (((*_7).0: std::ptr::Unique<[i32]>).0: std::ptr::NonNull<[i32]>); ++ _26 = copy (((*_7).0: std::ptr::Unique<[i32]>).1: std::marker::PhantomData<[i32]>); ++ StorageLive(_13); ++ _14 = copy _25 as *mut [i32] (Transmute); ++ _13 = copy _25 as *const [i32] (Transmute); ++ StorageLive(_19); ++ _18 = std::intrinsics::size_of_val::<[i32]>(copy _13) -> [return: bb8, unwind unreachable]; ++ } ++ ++ bb5 (cleanup): { ++ _9 = &mut (*_5); ++ _10 = as Drop>::drop(move _9) -> [return: bb3, unwind terminate(cleanup)]; ++ } ++ ++ bb6: { ++ StorageLive(_17); ++ _17 = &((*_7).1: std::alloc::Global); ++ StorageLive(_24); ++ _24 = copy _14 as *const u8 (PtrToPtr); ++ _23 = NonNull:: { pointer: move _24 }; ++ StorageDead(_24); ++ StorageLive(_27); ++ _27 = copy _12; ++ StorageLive(_28); ++ StorageLive(_29); ++ _29 = &_27; ++ _28 = copy (_27.0: usize); ++ StorageDead(_29); ++ switchInt(move _28) -> [0: bb13, otherwise: bb12]; ++ } ++ ++ bb7: { ++ StorageDead(_26); ++ StorageDead(_25); ++ StorageDead(_23); ++ StorageDead(_21); ++ StorageDead(_18); ++ StorageDead(_16); ++ StorageDead(_14); ++ StorageDead(_12); ++ StorageDead(_11); ++ StorageDead(_10); ++ StorageDead(_9); ++ StorageDead(_8); ++ StorageDead(_7); StorageDead(_3); StorageDead(_2); _0 = const (); return; } - bb3 (cleanup): { - drop(_3) -> [return: bb4, unwind terminate(cleanup)]; +- bb3 (cleanup): { +- drop(_3) -> [return: bb4, unwind terminate(cleanup)]; ++ bb8: { ++ _19 = std::intrinsics::align_of_val::<[i32]>(move _13) -> [return: bb9, unwind unreachable]; } - bb4 (cleanup): { - resume; +- bb4 (cleanup): { +- resume; ++ bb9: { ++ StorageLive(_20); ++ _20 = UbChecks(); ++ switchInt(move _20) -> [0: bb11, otherwise: bb10]; ++ } ++ ++ bb10: { ++ _21 = Layout::from_size_align_unchecked::precondition_check(copy _18, copy _19) -> [return: bb11, unwind unreachable]; ++ } ++ ++ bb11: { ++ StorageDead(_20); ++ StorageLive(_22); ++ _22 = copy _19 as std::ptr::Alignment (Transmute); ++ _12 = Layout { size: copy _18, align: move _22 }; ++ StorageDead(_22); ++ StorageDead(_19); ++ StorageDead(_13); ++ StorageLive(_15); ++ _15 = &_12; ++ StorageDead(_15); ++ switchInt(move _18) -> [0: bb7, otherwise: bb6]; ++ } ++ ++ bb12: { ++ StorageLive(_30); ++ _30 = copy _23 as *mut u8 (Transmute); ++ StorageLive(_31); ++ _31 = copy _27; ++ StorageLive(_32); ++ _32 = &_31; ++ StorageDead(_32); ++ StorageLive(_33); ++ StorageLive(_34); ++ _34 = &_31; ++ StorageLive(_36); ++ _36 = copy ((_27.1: std::ptr::Alignment).0: std::ptr::alignment::AlignmentEnum); ++ StorageLive(_35); ++ _35 = discriminant(_36); ++ _33 = move _35 as usize (IntToInt); ++ StorageDead(_35); ++ StorageDead(_36); ++ StorageDead(_34); ++ _16 = alloc::alloc::__rust_dealloc(move _30, move _28, move _33) -> [return: bb14, unwind unreachable]; ++ } ++ ++ bb13: { ++ StorageDead(_28); ++ StorageDead(_27); ++ StorageDead(_17); ++ goto -> bb7; ++ } ++ ++ bb14: { ++ StorageDead(_33); ++ StorageDead(_31); ++ StorageDead(_30); ++ goto -> bb13; } } diff --git a/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-abort.diff b/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-abort.diff index 22e6ea722ddaf..fe4d6d549e49e 100644 --- a/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-abort.diff +++ b/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-abort.diff @@ -13,6 +13,10 @@ let mut _8: std::pin::Pin<&mut {async fn body of ActionPermit<'_, T>::perform()}>; let mut _9: &mut std::task::Context<'_>; let mut _10: &mut std::task::Context<'_>; ++ let mut _51: *mut ActionPermit<'_, T>; ++ let mut _52: (); ++ let mut _53: *mut {async fn body of ActionPermit<'_, T>::perform()}; ++ let mut _54: (); scope 1 { debug fut => _2; let _4: std::pin::Pin<&mut {async fn body of ActionPermit<'_, T>::perform()}>; @@ -58,35 +62,33 @@ + scope 12 (inlined Pin::<&mut std::future::Ready<()>>::new_unchecked) { + } + scope 13 (inlined as Future>::poll) { -+ let mut _42: (); -+ let mut _43: std::option::Option<()>; -+ let mut _44: &mut std::option::Option<()>; -+ let mut _45: &mut std::future::Ready<()>; -+ let mut _46: &mut std::pin::Pin<&mut std::future::Ready<()>>; -+ scope 14 (inlined > as DerefMut>::deref_mut) { -+ scope 15 (inlined Pin::<&mut std::future::Ready<()>>::as_mut) { -+ let mut _47: &mut &mut std::future::Ready<()>; -+ scope 16 (inlined Pin::<&mut std::future::Ready<()>>::new_unchecked) { ++ let mut _42: std::option::Option<()>; ++ let mut _43: &mut std::option::Option<()>; ++ let mut _44: &mut std::future::Ready<()>; ++ let mut _45: &mut std::pin::Pin<&mut std::future::Ready<()>>; ++ let mut _46: isize; ++ let _47: (); ++ let mut _48: !; ++ scope 14 { ++ } ++ scope 15 (inlined > as DerefMut>::deref_mut) { ++ scope 16 (inlined Pin::<&mut std::future::Ready<()>>::as_mut) { ++ let mut _49: &mut &mut std::future::Ready<()>; ++ scope 17 (inlined Pin::<&mut std::future::Ready<()>>::new_unchecked) { + } -+ scope 18 (inlined <&mut std::future::Ready<()> as DerefMut>::deref_mut) { ++ scope 19 (inlined <&mut std::future::Ready<()> as DerefMut>::deref_mut) { + } + } -+ scope 17 (inlined Pin::<&mut std::future::Ready<()>>::get_mut) { ++ scope 18 (inlined Pin::<&mut std::future::Ready<()>>::get_mut) { + } + } -+ scope 19 (inlined Option::<()>::take) { -+ let mut _48: std::option::Option<()>; -+ scope 20 (inlined std::mem::replace::>) { -+ scope 21 { ++ scope 20 (inlined Option::<()>::take) { ++ let mut _50: std::option::Option<()>; ++ scope 21 (inlined std::mem::replace::>) { ++ scope 22 { + } + } + } -+ scope 22 (inlined #[track_caller] Option::<()>::expect) { -+ let mut _49: isize; -+ let mut _50: !; -+ scope 23 { -+ } -+ } + } + } + scope 10 (inlined ready::<()>) { @@ -95,12 +97,45 @@ + scope 11 (inlined as IntoFuture>::into_future) { + } + } ++ scope 23 (inlined drop_in_place::> - shim(Some(ActionPermit<'_, T>))) { ++ } + } } + scope 5 (inlined Pin::<&mut {async fn body of ActionPermit<'_, T>::perform()}>::new_unchecked) { + } } + scope 4 (inlined ActionPermit::<'_, T>::perform) { ++ } ++ scope 24 (inlined drop_in_place::<{async fn body of ActionPermit<'_, T>::perform()}> - shim(Some({async fn body of ActionPermit<'_, T>::perform()}))) { ++ let mut _55: &mut std::task::Context<'_>; ++ let _56: ActionPermit<'_, T>; ++ let mut _57: std::future::Ready<()>; ++ let mut _58: std::future::Ready<()>; ++ let mut _59: (); ++ let mut _61: (); ++ let _62: (); ++ let mut _63: std::task::Poll<()>; ++ let mut _64: std::pin::Pin<&mut std::future::Ready<()>>; ++ let mut _65: &mut std::future::Ready<()>; ++ let mut _66: &mut std::future::Ready<()>; ++ let mut _67: &mut std::task::Context<'_>; ++ let mut _68: &mut std::task::Context<'_>; ++ let mut _69: &mut std::task::Context<'_>; ++ let mut _70: isize; ++ let mut _72: !; ++ let mut _73: &mut std::task::Context<'_>; ++ let mut _74: (); ++ let mut _75: (); ++ let mut _76: &mut std::task::Context<'_>; ++ let mut _77: u32; ++ scope 25 { ++ let mut _60: std::future::Ready<()>; ++ scope 26 { ++ let _71: (); ++ scope 27 { ++ } ++ } ++ } + } bb0: { @@ -148,16 +183,11 @@ + StorageLive(_40); + _33 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()}); + _32 = discriminant((*_33)); -+ switchInt(move _32) -> [0: bb3, 1: bb10, 3: bb9, otherwise: bb5]; ++ switchInt(move _32) -> [0: bb2, 1: bb8, 3: bb7, otherwise: bb4]; } - bb3: { + bb1: { -+ StorageDead(_2); -+ return; -+ } -+ -+ bb2: { + StorageDead(_40); + StorageDead(_39); + StorageDead(_38); @@ -182,10 +212,32 @@ _0 = const (); StorageDead(_4); - drop(_2) -> [return: bb4, unwind unreachable]; -+ drop(_2) -> [return: bb1, unwind unreachable]; ++ _53 = &raw mut _2; ++ StorageLive(_55); ++ StorageLive(_56); ++ StorageLive(_58); ++ StorageLive(_59); ++ StorageLive(_60); ++ StorageLive(_61); ++ StorageLive(_62); ++ StorageLive(_63); ++ StorageLive(_64); ++ StorageLive(_65); ++ StorageLive(_66); ++ StorageLive(_67); ++ StorageLive(_68); ++ StorageLive(_69); ++ StorageLive(_70); ++ StorageLive(_71); ++ StorageLive(_72); ++ StorageLive(_75); ++ StorageLive(_76); ++ StorageLive(_77); ++ _77 = discriminant((*_53)); ++ switchInt(move _77) -> [0: bb13, 3: bb14, otherwise: bb12]; } -+ bb3: { ++ bb2: { + _31 = move _9; + _34 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()}); + _35 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()}); @@ -203,12 +255,10 @@ + StorageDead(_13); + _36 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()}); + (((*_36) as variant#3).1: std::future::Ready<()>) = move _12; -+ goto -> bb4; ++ goto -> bb3; + } + - bb4: { -- StorageDead(_2); -- return; ++ bb3: { + StorageLive(_17); + StorageLive(_18); + StorageLive(_19); @@ -226,34 +276,34 @@ + _23 = move _24; + _22 = &mut (*_23); + StorageDead(_24); ++ StorageLive(_44); + StorageLive(_45); + StorageLive(_46); -+ StorageLive(_50); -+ StorageLive(_42); -+ StorageLive(_43); -+ StorageLive(_44); -+ _46 = &mut _19; + StorageLive(_47); -+ _47 = &mut (_19.0: &mut std::future::Ready<()>); -+ _45 = copy (_19.0: &mut std::future::Ready<()>); -+ StorageDead(_47); -+ _44 = &mut ((*_45).0: std::option::Option<()>); + StorageLive(_48); -+ _48 = Option::<()>::None; -+ _43 = copy ((*_45).0: std::option::Option<()>); -+ ((*_45).0: std::option::Option<()>) = copy _48; -+ StorageDead(_48); -+ StorageDead(_44); ++ StorageLive(_42); ++ StorageLive(_43); ++ _45 = &mut _19; + StorageLive(_49); -+ _49 = discriminant(_43); -+ switchInt(move _49) -> [0: bb11, 1: bb12, otherwise: bb5]; - } ++ _49 = &mut (_19.0: &mut std::future::Ready<()>); ++ _44 = copy (_19.0: &mut std::future::Ready<()>); ++ StorageDead(_49); ++ _43 = &mut ((*_44).0: std::option::Option<()>); ++ StorageLive(_50); ++ _50 = Option::<()>::None; ++ _42 = copy ((*_44).0: std::option::Option<()>); ++ ((*_44).0: std::option::Option<()>) = copy _50; ++ StorageDead(_50); ++ StorageDead(_43); ++ _46 = discriminant(_42); ++ switchInt(move _46) -> [0: bb9, 1: bb10, otherwise: bb4]; ++ } + -+ bb5: { + bb4: { + unreachable; + } + -+ bb6: { ++ bb5: { + _17 = const (); + StorageDead(_23); + StorageDead(_21); @@ -268,10 +318,10 @@ + StorageDead(_29); + _38 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()}); + discriminant((*_38)) = 3; -+ goto -> bb2; ++ goto -> bb1; + } + -+ bb7: { ++ bb6: { + StorageLive(_26); + _26 = copy ((_18 as Ready).0: ()); + _30 = copy _26; @@ -282,17 +332,11 @@ + StorageDead(_17); + StorageDead(_12); + _39 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()}); -+ drop((((*_39) as variant#3).0: ActionPermit<'_, T>)) -> [return: bb8, unwind unreachable]; ++ _51 = &raw mut (((*_39) as variant#3).0: ActionPermit<'_, T>); ++ drop(((*_51).0: std::cell::Ref<'_, T>)) -> [return: bb11, unwind unreachable]; + } + -+ bb8: { -+ _7 = Poll::<()>::Ready(move _30); -+ _40 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()}); -+ discriminant((*_40)) = 1; -+ goto -> bb2; -+ } -+ -+ bb9: { ++ bb7: { + StorageLive(_12); + StorageLive(_28); + StorageLive(_29); @@ -301,35 +345,76 @@ + _31 = move _28; + StorageDead(_28); + _16 = const (); -+ goto -> bb4; ++ goto -> bb3; + } + -+ bb10: { -+ assert(const false, "`async fn` resumed after completion") -> [success: bb10, unwind unreachable]; ++ bb8: { ++ assert(const false, "`async fn` resumed after completion") -> [success: bb8, unwind unreachable]; + } + -+ bb11: { -+ _50 = option::expect_failed(const "`Ready` polled after completion") -> unwind unreachable; ++ bb9: { ++ _48 = future::ready::polled_after_completion() -> unwind unreachable; + } + -+ bb12: { -+ _42 = move ((_43 as Some).0: ()); -+ StorageDead(_49); -+ StorageDead(_43); -+ _18 = Poll::<()>::Ready(move _42); ++ bb10: { ++ _47 = move ((_42 as Some).0: ()); ++ _18 = Poll::<()>::Ready(copy _47); + StorageDead(_42); -+ StorageDead(_50); ++ StorageDead(_48); ++ StorageDead(_47); + StorageDead(_46); + StorageDead(_45); ++ StorageDead(_44); + StorageDead(_22); + StorageDead(_19); + _25 = discriminant(_18); -+ switchInt(move _25) -> [0: bb7, 1: bb6, otherwise: bb5]; ++ switchInt(move _25) -> [0: bb6, 1: bb5, otherwise: bb4]; + } -+ } + -+ ALLOC0 (size: 31, align: 1) { -+ 0x00 │ 60 52 65 61 64 79 60 20 70 6f 6c 6c 65 64 20 61 │ `Ready` polled a -+ 0x10 │ 66 74 65 72 20 63 6f 6d 70 6c 65 74 69 6f 6e │ fter completion ++ bb11: { ++ _7 = Poll::<()>::Ready(move _30); ++ _40 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()}); ++ discriminant((*_40)) = 1; ++ goto -> bb1; ++ } ++ ++ bb12: { ++ StorageDead(_77); ++ StorageDead(_76); ++ StorageDead(_75); ++ StorageDead(_72); ++ StorageDead(_71); ++ StorageDead(_70); ++ StorageDead(_69); ++ StorageDead(_68); ++ StorageDead(_67); ++ StorageDead(_66); ++ StorageDead(_65); ++ StorageDead(_64); ++ StorageDead(_63); ++ StorageDead(_62); ++ StorageDead(_61); ++ StorageDead(_60); ++ StorageDead(_59); ++ StorageDead(_58); ++ StorageDead(_56); ++ StorageDead(_55); + StorageDead(_2); + return; ++ } ++ ++ bb13: { ++ drop(((*_53).0: ActionPermit<'_, T>)) -> [return: bb12, unwind unreachable]; ++ } ++ ++ bb14: { ++ StorageLive(_57); ++ StorageLive(_73); ++ StorageLive(_74); ++ StorageDead(_74); ++ StorageDead(_73); ++ StorageDead(_57); ++ drop((((*_53) as variant#3).0: ActionPermit<'_, T>)) -> [return: bb12, unwind unreachable]; + } } diff --git a/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-unwind.diff b/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-unwind.diff index 8b027e988b8e8..1297b16fb9d6b 100644 --- a/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-unwind.diff @@ -13,6 +13,10 @@ let mut _8: std::pin::Pin<&mut {async fn body of ActionPermit<'_, T>::perform()}>; let mut _9: &mut std::task::Context<'_>; let mut _10: &mut std::task::Context<'_>; ++ let mut _53: *mut ActionPermit<'_, T>; ++ let mut _54: (); ++ let mut _55: *mut {async fn body of ActionPermit<'_, T>::perform()}; ++ let mut _56: (); scope 1 { debug fut => _2; let _4: std::pin::Pin<&mut {async fn body of ActionPermit<'_, T>::perform()}>; @@ -60,35 +64,33 @@ + scope 12 (inlined Pin::<&mut std::future::Ready<()>>::new_unchecked) { + } + scope 13 (inlined as Future>::poll) { -+ let mut _44: (); -+ let mut _45: std::option::Option<()>; -+ let mut _46: &mut std::option::Option<()>; -+ let mut _47: &mut std::future::Ready<()>; -+ let mut _48: &mut std::pin::Pin<&mut std::future::Ready<()>>; -+ scope 14 (inlined > as DerefMut>::deref_mut) { -+ scope 15 (inlined Pin::<&mut std::future::Ready<()>>::as_mut) { -+ let mut _49: &mut &mut std::future::Ready<()>; -+ scope 16 (inlined Pin::<&mut std::future::Ready<()>>::new_unchecked) { ++ let mut _44: std::option::Option<()>; ++ let mut _45: &mut std::option::Option<()>; ++ let mut _46: &mut std::future::Ready<()>; ++ let mut _47: &mut std::pin::Pin<&mut std::future::Ready<()>>; ++ let mut _48: isize; ++ let _49: (); ++ let mut _50: !; ++ scope 14 { ++ } ++ scope 15 (inlined > as DerefMut>::deref_mut) { ++ scope 16 (inlined Pin::<&mut std::future::Ready<()>>::as_mut) { ++ let mut _51: &mut &mut std::future::Ready<()>; ++ scope 17 (inlined Pin::<&mut std::future::Ready<()>>::new_unchecked) { + } -+ scope 18 (inlined <&mut std::future::Ready<()> as DerefMut>::deref_mut) { ++ scope 19 (inlined <&mut std::future::Ready<()> as DerefMut>::deref_mut) { + } + } -+ scope 17 (inlined Pin::<&mut std::future::Ready<()>>::get_mut) { ++ scope 18 (inlined Pin::<&mut std::future::Ready<()>>::get_mut) { + } + } -+ scope 19 (inlined Option::<()>::take) { -+ let mut _50: std::option::Option<()>; -+ scope 20 (inlined std::mem::replace::>) { -+ scope 21 { ++ scope 20 (inlined Option::<()>::take) { ++ let mut _52: std::option::Option<()>; ++ scope 21 (inlined std::mem::replace::>) { ++ scope 22 { + } + } + } -+ scope 22 (inlined #[track_caller] Option::<()>::expect) { -+ let mut _51: isize; -+ let mut _52: !; -+ scope 23 { -+ } -+ } + } + } + scope 10 (inlined ready::<()>) { @@ -97,12 +99,45 @@ + scope 11 (inlined as IntoFuture>::into_future) { + } + } ++ scope 23 (inlined drop_in_place::> - shim(Some(ActionPermit<'_, T>))) { ++ } + } } + scope 5 (inlined Pin::<&mut {async fn body of ActionPermit<'_, T>::perform()}>::new_unchecked) { + } } + scope 4 (inlined ActionPermit::<'_, T>::perform) { ++ } ++ scope 24 (inlined drop_in_place::<{async fn body of ActionPermit<'_, T>::perform()}> - shim(Some({async fn body of ActionPermit<'_, T>::perform()}))) { ++ let mut _57: &mut std::task::Context<'_>; ++ let _58: ActionPermit<'_, T>; ++ let mut _59: std::future::Ready<()>; ++ let mut _60: std::future::Ready<()>; ++ let mut _61: (); ++ let mut _63: (); ++ let _64: (); ++ let mut _65: std::task::Poll<()>; ++ let mut _66: std::pin::Pin<&mut std::future::Ready<()>>; ++ let mut _67: &mut std::future::Ready<()>; ++ let mut _68: &mut std::future::Ready<()>; ++ let mut _69: &mut std::task::Context<'_>; ++ let mut _70: &mut std::task::Context<'_>; ++ let mut _71: &mut std::task::Context<'_>; ++ let mut _72: isize; ++ let mut _74: !; ++ let mut _75: &mut std::task::Context<'_>; ++ let mut _76: (); ++ let mut _77: (); ++ let mut _78: &mut std::task::Context<'_>; ++ let mut _79: u32; ++ scope 25 { ++ let mut _62: std::future::Ready<()>; ++ scope 26 { ++ let _73: (); ++ scope 27 { ++ } ++ } ++ } + } bb0: { @@ -152,24 +187,18 @@ + StorageLive(_42); + _33 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()}); + _32 = discriminant((*_33)); -+ switchInt(move _32) -> [0: bb5, 1: bb15, 2: bb14, 3: bb13, otherwise: bb7]; ++ switchInt(move _32) -> [0: bb4, 1: bb13, 2: bb12, 3: bb11, otherwise: bb6]; } -- bb3: { -+ bb1: { -+ StorageDead(_2); -+ return; ++ bb1 (cleanup): { ++ drop(_2) -> [return: bb2, unwind terminate(cleanup)]; + } + + bb2 (cleanup): { -+ drop(_2) -> [return: bb3, unwind terminate(cleanup)]; -+ } -+ -+ bb3 (cleanup): { + resume; + } + -+ bb4: { + bb3: { + StorageDead(_42); + StorageDead(_41); + StorageDead(_40); @@ -196,13 +225,32 @@ _0 = const (); StorageDead(_4); - drop(_2) -> [return: bb4, unwind: bb6]; -+ drop(_2) -> [return: bb1, unwind: bb3]; ++ _55 = &raw mut _2; ++ StorageLive(_57); ++ StorageLive(_58); ++ StorageLive(_60); ++ StorageLive(_61); ++ StorageLive(_62); ++ StorageLive(_63); ++ StorageLive(_64); ++ StorageLive(_65); ++ StorageLive(_66); ++ StorageLive(_67); ++ StorageLive(_68); ++ StorageLive(_69); ++ StorageLive(_70); ++ StorageLive(_71); ++ StorageLive(_72); ++ StorageLive(_73); ++ StorageLive(_74); ++ StorageLive(_77); ++ StorageLive(_78); ++ StorageLive(_79); ++ _79 = discriminant((*_55)); ++ switchInt(move _79) -> [0: bb18, 3: bb19, otherwise: bb17]; } -- bb4: { -- StorageDead(_2); -- return; -+ bb5: { + bb4: { + _31 = move _9; + _34 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()}); + _35 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()}); @@ -220,12 +268,10 @@ + StorageDead(_13); + _36 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()}); + (((*_36) as variant#3).1: std::future::Ready<()>) = move _12; -+ goto -> bb6; - } - -- bb5 (cleanup): { -- drop(_2) -> [return: bb6, unwind terminate(cleanup)]; -+ bb6: { ++ goto -> bb5; ++ } ++ ++ bb5: { + StorageLive(_17); + StorageLive(_18); + StorageLive(_19); @@ -243,36 +289,34 @@ + _23 = move _24; + _22 = &mut (*_23); + StorageDead(_24); ++ StorageLive(_46); + StorageLive(_47); + StorageLive(_48); -+ StorageLive(_52); -+ StorageLive(_44); -+ StorageLive(_45); -+ StorageLive(_46); -+ _48 = &mut _19; + StorageLive(_49); -+ _49 = &mut (_19.0: &mut std::future::Ready<()>); -+ _47 = copy (_19.0: &mut std::future::Ready<()>); -+ StorageDead(_49); -+ _46 = &mut ((*_47).0: std::option::Option<()>); + StorageLive(_50); -+ _50 = Option::<()>::None; -+ _45 = copy ((*_47).0: std::option::Option<()>); -+ ((*_47).0: std::option::Option<()>) = copy _50; -+ StorageDead(_50); -+ StorageDead(_46); ++ StorageLive(_44); ++ StorageLive(_45); ++ _47 = &mut _19; + StorageLive(_51); -+ _51 = discriminant(_45); -+ switchInt(move _51) -> [0: bb16, 1: bb17, otherwise: bb7]; - } - -- bb6 (cleanup): { -- resume; -+ bb7: { ++ _51 = &mut (_19.0: &mut std::future::Ready<()>); ++ _46 = copy (_19.0: &mut std::future::Ready<()>); ++ StorageDead(_51); ++ _45 = &mut ((*_46).0: std::option::Option<()>); ++ StorageLive(_52); ++ _52 = Option::<()>::None; ++ _44 = copy ((*_46).0: std::option::Option<()>); ++ ((*_46).0: std::option::Option<()>) = copy _52; ++ StorageDead(_52); ++ StorageDead(_45); ++ _48 = discriminant(_44); ++ switchInt(move _48) -> [0: bb14, 1: bb15, otherwise: bb6]; ++ } ++ ++ bb6: { + unreachable; - } ++ } + -+ bb8: { ++ bb7: { + _17 = const (); + StorageDead(_23); + StorageDead(_21); @@ -287,10 +331,10 @@ + StorageDead(_29); + _38 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()}); + discriminant((*_38)) = 3; -+ goto -> bb4; ++ goto -> bb3; + } + -+ bb9: { ++ bb8: { + StorageLive(_26); + _26 = copy ((_18 as Ready).0: ()); + _30 = copy _26; @@ -301,17 +345,11 @@ + StorageDead(_17); + StorageDead(_12); + _39 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()}); -+ drop((((*_39) as variant#3).0: ActionPermit<'_, T>)) -> [return: bb10, unwind: bb12]; -+ } -+ -+ bb10: { -+ _7 = Poll::<()>::Ready(move _30); -+ _40 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()}); -+ discriminant((*_40)) = 1; -+ goto -> bb4; ++ _53 = &raw mut (((*_39) as variant#3).0: ActionPermit<'_, T>); ++ drop(((*_53).0: std::cell::Ref<'_, T>)) -> [return: bb16, unwind: bb10]; + } + -+ bb11 (cleanup): { ++ bb9 (cleanup): { + StorageDead(_22); + StorageDead(_19); + StorageDead(_23); @@ -320,16 +358,16 @@ + StorageDead(_17); + StorageDead(_12); + _41 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()}); -+ drop((((*_41) as variant#3).0: ActionPermit<'_, T>)) -> [return: bb12, unwind terminate(cleanup)]; ++ drop((((*_41) as variant#3).0: ActionPermit<'_, T>)) -> [return: bb10, unwind terminate(cleanup)]; + } + -+ bb12 (cleanup): { ++ bb10 (cleanup): { + _42 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()}); + discriminant((*_42)) = 2; -+ goto -> bb2; ++ goto -> bb1; + } + -+ bb13: { ++ bb11: { + StorageLive(_12); + StorageLive(_28); + StorageLive(_29); @@ -338,39 +376,84 @@ + _31 = move _28; + StorageDead(_28); + _16 = const (); -+ goto -> bb6; ++ goto -> bb5; + } + -+ bb14: { -+ assert(const false, "`async fn` resumed after panicking") -> [success: bb14, unwind: bb2]; ++ bb12: { ++ assert(const false, "`async fn` resumed after panicking") -> [success: bb12, unwind: bb1]; + } + -+ bb15: { -+ assert(const false, "`async fn` resumed after completion") -> [success: bb15, unwind: bb2]; ++ bb13: { ++ assert(const false, "`async fn` resumed after completion") -> [success: bb13, unwind: bb1]; + } + -+ bb16: { -+ _52 = option::expect_failed(const "`Ready` polled after completion") -> bb11; ++ bb14: { ++ _50 = future::ready::polled_after_completion() -> bb9; + } + -+ bb17: { -+ _44 = move ((_45 as Some).0: ()); -+ StorageDead(_51); -+ StorageDead(_45); -+ _18 = Poll::<()>::Ready(move _44); ++ bb15: { ++ _49 = move ((_44 as Some).0: ()); ++ _18 = Poll::<()>::Ready(copy _49); + StorageDead(_44); -+ StorageDead(_52); ++ StorageDead(_50); ++ StorageDead(_49); + StorageDead(_48); + StorageDead(_47); ++ StorageDead(_46); + StorageDead(_22); + StorageDead(_19); + _25 = discriminant(_18); -+ switchInt(move _25) -> [0: bb9, 1: bb8, otherwise: bb7]; ++ switchInt(move _25) -> [0: bb8, 1: bb7, otherwise: bb6]; ++ } ++ ++ bb16: { ++ _7 = Poll::<()>::Ready(move _30); ++ _40 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()}); ++ discriminant((*_40)) = 1; ++ goto -> bb3; + } -+ } + -+ ALLOC0 (size: 31, align: 1) { -+ 0x00 │ 60 52 65 61 64 79 60 20 70 6f 6c 6c 65 64 20 61 │ `Ready` polled a -+ 0x10 │ 66 74 65 72 20 63 6f 6d 70 6c 65 74 69 6f 6e │ fter completion ++ bb17: { ++ StorageDead(_79); ++ StorageDead(_78); ++ StorageDead(_77); ++ StorageDead(_74); ++ StorageDead(_73); ++ StorageDead(_72); ++ StorageDead(_71); ++ StorageDead(_70); ++ StorageDead(_69); ++ StorageDead(_68); ++ StorageDead(_67); ++ StorageDead(_66); ++ StorageDead(_65); ++ StorageDead(_64); ++ StorageDead(_63); ++ StorageDead(_62); ++ StorageDead(_61); ++ StorageDead(_60); ++ StorageDead(_58); ++ StorageDead(_57); + StorageDead(_2); + return; + } + +- bb5 (cleanup): { +- drop(_2) -> [return: bb6, unwind terminate(cleanup)]; ++ bb18: { ++ drop(((*_55).0: ActionPermit<'_, T>)) -> [return: bb17, unwind: bb2]; + } + +- bb6 (cleanup): { +- resume; ++ bb19: { ++ StorageLive(_59); ++ StorageLive(_75); ++ StorageLive(_76); ++ StorageDead(_76); ++ StorageDead(_75); ++ StorageDead(_59); ++ drop((((*_55) as variant#3).0: ActionPermit<'_, T>)) -> [return: bb17, unwind: bb2]; + } } diff --git a/tests/mir-opt/pre-codegen/loops.vec_move.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/loops.vec_move.PreCodegen.after.mir index e537dd6a28ef8..aecb471971e07 100644 --- a/tests/mir-opt/pre-codegen/loops.vec_move.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/loops.vec_move.PreCodegen.after.mir @@ -8,14 +8,18 @@ fn vec_move(_1: Vec) -> () { let mut _4: &mut std::vec::IntoIter; let mut _5: std::option::Option; let mut _6: isize; - let _8: (); + let _10: (); scope 1 { debug iter => _3; - let _7: impl Sized; + let _9: impl Sized; scope 2 { - debug x => _7; + debug x => _9; } } + scope 3 (inlined drop_in_place::> - shim(Some(std::vec::IntoIter))) { + let mut _7: &mut std::vec::IntoIter; + let mut _8: (); + } bb0: { StorageLive(_2); @@ -41,18 +45,21 @@ fn vec_move(_1: Vec) -> () { bb4: { StorageDead(_5); - drop(_3) -> [return: bb5, unwind continue]; + StorageLive(_7); + _7 = &mut _3; + _8 = as Drop>::drop(move _7) -> [return: bb5, unwind continue]; } bb5: { + StorageDead(_7); StorageDead(_3); StorageDead(_2); return; } bb6: { - _7 = move ((_5 as Some).0: impl Sized); - _8 = opaque::(move _7) -> [return: bb7, unwind: bb9]; + _9 = move ((_5 as Some).0: impl Sized); + _10 = opaque::(move _9) -> [return: bb7, unwind: bb9]; } bb7: { diff --git a/tests/mir-opt/remove_unneeded_drops.dont_opt.RemoveUnneededDrops.panic-abort.diff b/tests/mir-opt/remove_unneeded_drops.dont_opt.RemoveUnneededDrops.panic-abort.diff index 428b366b5a684..ec34343206122 100644 --- a/tests/mir-opt/remove_unneeded_drops.dont_opt.RemoveUnneededDrops.panic-abort.diff +++ b/tests/mir-opt/remove_unneeded_drops.dont_opt.RemoveUnneededDrops.panic-abort.diff @@ -6,21 +6,101 @@ let mut _0: (); let _2: (); let mut _3: std::vec::Vec; + let mut _4: *mut std::vec::Vec; + let mut _5: (); scope 1 (inlined std::mem::drop::>) { + scope 2 (inlined drop_in_place::> - shim(Some(Vec))) { + let mut _6: &mut std::vec::Vec; + let mut _7: (); + scope 3 (inlined as Drop>::drop) { + let mut _8: *mut [bool]; + let mut _9: *mut bool; + let mut _10: usize; + scope 4 (inlined Vec::::as_mut_ptr) { + scope 5 (inlined alloc::raw_vec::RawVec::::ptr) { + scope 6 (inlined alloc::raw_vec::RawVecInner::ptr::) { + scope 7 (inlined alloc::raw_vec::RawVecInner::non_null::) { + let mut _11: std::ptr::NonNull; + scope 8 (inlined Unique::::cast::) { + scope 9 (inlined NonNull::::cast::) { + scope 10 (inlined NonNull::::as_ptr) { + } + } + } + scope 11 (inlined Unique::::as_non_null_ptr) { + } + } + scope 12 (inlined NonNull::::as_ptr) { + } + } + } + } + scope 13 (inlined slice_from_raw_parts_mut::) { + scope 14 (inlined std::ptr::from_raw_parts_mut::<[bool], bool>) { + } + } + scope 15 (inlined drop_in_place::<[bool]> - shim(Some([bool]))) { + let mut _12: usize; + let mut _13: *mut bool; + let mut _14: bool; + } + } + } } bb0: { - nop; +- nop; StorageLive(_3); _3 = move _1; - drop(_3) -> [return: bb1, unwind unreachable]; + _4 = &raw mut _3; + StorageLive(_6); +- nop; + _6 = &mut (*_4); + StorageLive(_10); + StorageLive(_8); + StorageLive(_9); + StorageLive(_11); + _11 = copy (((((*_6).0: alloc::raw_vec::RawVec).0: alloc::raw_vec::RawVecInner).0: std::ptr::Unique).0: std::ptr::NonNull); + _9 = copy _11 as *mut bool (Transmute); + StorageDead(_11); + _10 = copy ((*_6).1: usize); + _8 = *mut [bool] from (copy _9, copy _10); + StorageDead(_9); + StorageLive(_12); + StorageLive(_13); + StorageLive(_14); + _12 = const 0_usize; + goto -> bb4; } bb1: { +- nop; + StorageDead(_6); StorageDead(_3); - nop; - nop; +- nop; +- nop; return; } + + bb2: { + StorageDead(_14); + StorageDead(_13); + StorageDead(_12); + StorageDead(_8); + StorageDead(_10); + drop(((*_4).0: alloc::raw_vec::RawVec)) -> [return: bb1, unwind unreachable]; + } + + bb3: { + _13 = &raw mut (*_8)[_12]; + _12 = Add(move _12, const 1_usize); +- drop((*_13)) -> [return: bb4, unwind unreachable]; ++ goto -> bb4; + } + + bb4: { + _14 = Eq(copy _12, copy _10); + switchInt(move _14) -> [0: bb3, otherwise: bb2]; + } } From bfdee9aeff3ef14dd882021eee147a122dfc75d4 Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Sun, 27 Jul 2025 21:37:17 -0700 Subject: [PATCH 2/4] Add a mir-opt test for an unneeded drop_in_place --- tests/mir-opt/remove_unneeded_drops.rs | 7 +++++++ ...place.RemoveUnneededDrops.panic-abort.diff | 20 +++++++++++++++++++ ...lace.RemoveUnneededDrops.panic-unwind.diff | 20 +++++++++++++++++++ 3 files changed, 47 insertions(+) create mode 100644 tests/mir-opt/remove_unneeded_drops.slice_in_place.RemoveUnneededDrops.panic-abort.diff create mode 100644 tests/mir-opt/remove_unneeded_drops.slice_in_place.RemoveUnneededDrops.panic-unwind.diff diff --git a/tests/mir-opt/remove_unneeded_drops.rs b/tests/mir-opt/remove_unneeded_drops.rs index cad79e0aa0cbc..f3d70e167d291 100644 --- a/tests/mir-opt/remove_unneeded_drops.rs +++ b/tests/mir-opt/remove_unneeded_drops.rs @@ -22,9 +22,16 @@ fn cannot_opt_generic(x: T) { drop(x); } +// EMIT_MIR remove_unneeded_drops.slice_in_place.RemoveUnneededDrops.diff +unsafe fn slice_in_place(ptr: *mut [char]) { + std::ptr::drop_in_place(ptr) +} + fn main() { opt(true); opt_generic_copy(42); cannot_opt_generic(42); dont_opt(vec![true]); + let mut a = ['o', 'k']; + unsafe { slice_in_place(&raw mut a) }; } diff --git a/tests/mir-opt/remove_unneeded_drops.slice_in_place.RemoveUnneededDrops.panic-abort.diff b/tests/mir-opt/remove_unneeded_drops.slice_in_place.RemoveUnneededDrops.panic-abort.diff new file mode 100644 index 0000000000000..60572ebe24995 --- /dev/null +++ b/tests/mir-opt/remove_unneeded_drops.slice_in_place.RemoveUnneededDrops.panic-abort.diff @@ -0,0 +1,20 @@ +- // MIR for `slice_in_place` before RemoveUnneededDrops ++ // MIR for `slice_in_place` after RemoveUnneededDrops + + fn slice_in_place(_1: *mut [char]) -> () { + debug ptr => _1; + let mut _0: (); + let mut _2: *mut [char]; + + bb0: { + StorageLive(_2); + _2 = copy _1; + _0 = drop_in_place::<[char]>(move _2) -> [return: bb1, unwind unreachable]; + } + + bb1: { + StorageDead(_2); + return; + } + } + diff --git a/tests/mir-opt/remove_unneeded_drops.slice_in_place.RemoveUnneededDrops.panic-unwind.diff b/tests/mir-opt/remove_unneeded_drops.slice_in_place.RemoveUnneededDrops.panic-unwind.diff new file mode 100644 index 0000000000000..4068e7940bc6d --- /dev/null +++ b/tests/mir-opt/remove_unneeded_drops.slice_in_place.RemoveUnneededDrops.panic-unwind.diff @@ -0,0 +1,20 @@ +- // MIR for `slice_in_place` before RemoveUnneededDrops ++ // MIR for `slice_in_place` after RemoveUnneededDrops + + fn slice_in_place(_1: *mut [char]) -> () { + debug ptr => _1; + let mut _0: (); + let mut _2: *mut [char]; + + bb0: { + StorageLive(_2); + _2 = copy _1; + _0 = drop_in_place::<[char]>(move _2) -> [return: bb1, unwind continue]; + } + + bb1: { + StorageDead(_2); + return; + } + } + From e3a92cb001583cb30cf59ba70bdd7dc6b922f63d Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Sun, 27 Jul 2025 21:39:56 -0700 Subject: [PATCH 3/4] Let `RemoveUnneededDrops` also remove `drop_in_place` --- .../src/remove_unneeded_drops.rs | 25 +++++++++++++------ ...place.RemoveUnneededDrops.panic-abort.diff | 8 +++--- ...lace.RemoveUnneededDrops.panic-unwind.diff | 8 +++--- 3 files changed, 26 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_mir_transform/src/remove_unneeded_drops.rs b/compiler/rustc_mir_transform/src/remove_unneeded_drops.rs index 43f80508e4a87..c9cc313aac745 100644 --- a/compiler/rustc_mir_transform/src/remove_unneeded_drops.rs +++ b/compiler/rustc_mir_transform/src/remove_unneeded_drops.rs @@ -5,6 +5,7 @@ //! `TypingMode::PostAnalysis` to provide more precise type information, especially about opaque //! types. +use rustc_hir::LangItem; use rustc_middle::mir::*; use rustc_middle::ty::TyCtxt; use tracing::{debug, trace}; @@ -21,15 +22,25 @@ impl<'tcx> crate::MirPass<'tcx> for RemoveUnneededDrops { let mut should_simplify = false; for block in body.basic_blocks.as_mut() { let terminator = block.terminator_mut(); - if let TerminatorKind::Drop { place, target, .. } = terminator.kind { - let ty = place.ty(&body.local_decls, tcx); - if ty.ty.needs_drop(tcx, typing_env) { - continue; + let (ty, target) = match terminator.kind { + TerminatorKind::Drop { place, target, .. } => { + (place.ty(&body.local_decls, tcx).ty, target) } - debug!("SUCCESS: replacing `drop` with goto({:?})", target); - terminator.kind = TerminatorKind::Goto { target }; - should_simplify = true; + TerminatorKind::Call { ref func, target: Some(target), .. } + if let Some((def_id, generics)) = func.const_fn_def() + && tcx.is_lang_item(def_id, LangItem::DropInPlace) => + { + (generics.type_at(0), target) + } + _ => continue, + }; + + if ty.needs_drop(tcx, typing_env) { + continue; } + debug!("SUCCESS: replacing `drop` with goto({:?})", target); + terminator.kind = TerminatorKind::Goto { target }; + should_simplify = true; } // if we applied optimizations, we potentially have some cfg to cleanup to diff --git a/tests/mir-opt/remove_unneeded_drops.slice_in_place.RemoveUnneededDrops.panic-abort.diff b/tests/mir-opt/remove_unneeded_drops.slice_in_place.RemoveUnneededDrops.panic-abort.diff index 60572ebe24995..9cbc1cf621c93 100644 --- a/tests/mir-opt/remove_unneeded_drops.slice_in_place.RemoveUnneededDrops.panic-abort.diff +++ b/tests/mir-opt/remove_unneeded_drops.slice_in_place.RemoveUnneededDrops.panic-abort.diff @@ -9,10 +9,10 @@ bb0: { StorageLive(_2); _2 = copy _1; - _0 = drop_in_place::<[char]>(move _2) -> [return: bb1, unwind unreachable]; - } - - bb1: { +- _0 = drop_in_place::<[char]>(move _2) -> [return: bb1, unwind unreachable]; +- } +- +- bb1: { StorageDead(_2); return; } diff --git a/tests/mir-opt/remove_unneeded_drops.slice_in_place.RemoveUnneededDrops.panic-unwind.diff b/tests/mir-opt/remove_unneeded_drops.slice_in_place.RemoveUnneededDrops.panic-unwind.diff index 4068e7940bc6d..4d70e7151c393 100644 --- a/tests/mir-opt/remove_unneeded_drops.slice_in_place.RemoveUnneededDrops.panic-unwind.diff +++ b/tests/mir-opt/remove_unneeded_drops.slice_in_place.RemoveUnneededDrops.panic-unwind.diff @@ -9,10 +9,10 @@ bb0: { StorageLive(_2); _2 = copy _1; - _0 = drop_in_place::<[char]>(move _2) -> [return: bb1, unwind continue]; - } - - bb1: { +- _0 = drop_in_place::<[char]>(move _2) -> [return: bb1, unwind continue]; +- } +- +- bb1: { StorageDead(_2); return; } From 80895c2712bd4b77827a0726d471bdefe4f4700a Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Sun, 27 Jul 2025 22:08:59 -0700 Subject: [PATCH 4/4] Another MIR test for inlining drops --- ...ps.half_needs_drop.Inline.panic-abort.diff | 34 +++++++++++++++ ...s.half_needs_drop.Inline.panic-unwind.diff | 43 +++++++++++++++++++ tests/mir-opt/inline/inline_drops.rs | 15 +++++++ 3 files changed, 92 insertions(+) create mode 100644 tests/mir-opt/inline/inline_drops.half_needs_drop.Inline.panic-abort.diff create mode 100644 tests/mir-opt/inline/inline_drops.half_needs_drop.Inline.panic-unwind.diff create mode 100644 tests/mir-opt/inline/inline_drops.rs diff --git a/tests/mir-opt/inline/inline_drops.half_needs_drop.Inline.panic-abort.diff b/tests/mir-opt/inline/inline_drops.half_needs_drop.Inline.panic-abort.diff new file mode 100644 index 0000000000000..92f70a99c0589 --- /dev/null +++ b/tests/mir-opt/inline/inline_drops.half_needs_drop.Inline.panic-abort.diff @@ -0,0 +1,34 @@ +- // MIR for `half_needs_drop` before Inline ++ // MIR for `half_needs_drop` after Inline + + fn half_needs_drop(_1: String) -> () { + debug s => _1; + let mut _0: (); + let _2: Pair; + let mut _3: std::string::String; ++ let mut _4: *mut Pair; ++ let mut _5: (); + scope 1 { + debug _x => _2; + } ++ scope 2 (inlined drop_in_place::> - shim(Some(Pair))) { ++ } + + bb0: { + StorageLive(_2); + StorageLive(_3); + _3 = move _1; + _2 = Pair::(const true, move _3); + StorageDead(_3); + _0 = const (); +- drop(_2) -> [return: bb1, unwind unreachable]; ++ _4 = &raw mut _2; ++ drop(((*_4).1: std::string::String)) -> [return: bb1, unwind unreachable]; + } + + bb1: { + StorageDead(_2); + return; + } + } + diff --git a/tests/mir-opt/inline/inline_drops.half_needs_drop.Inline.panic-unwind.diff b/tests/mir-opt/inline/inline_drops.half_needs_drop.Inline.panic-unwind.diff new file mode 100644 index 0000000000000..a8db8842e57b9 --- /dev/null +++ b/tests/mir-opt/inline/inline_drops.half_needs_drop.Inline.panic-unwind.diff @@ -0,0 +1,43 @@ +- // MIR for `half_needs_drop` before Inline ++ // MIR for `half_needs_drop` after Inline + + fn half_needs_drop(_1: String) -> () { + debug s => _1; + let mut _0: (); + let _2: Pair; + let mut _3: std::string::String; ++ let mut _4: *mut Pair; ++ let mut _5: (); + scope 1 { + debug _x => _2; + } ++ scope 2 (inlined drop_in_place::> - shim(Some(Pair))) { ++ } + + bb0: { + StorageLive(_2); + StorageLive(_3); + _3 = move _1; + _2 = Pair::(const true, move _3); + StorageDead(_3); + _0 = const (); +- drop(_2) -> [return: bb1, unwind: bb2]; ++ _4 = &raw mut _2; ++ drop(((*_4).1: std::string::String)) -> [return: bb2, unwind: bb1]; + } + +- bb1: { +- StorageDead(_2); +- return; ++ bb1 (cleanup): { ++ resume; + } + +- bb2 (cleanup): { +- resume; ++ bb2: { ++ StorageDead(_2); ++ return; + } + } + diff --git a/tests/mir-opt/inline/inline_drops.rs b/tests/mir-opt/inline/inline_drops.rs new file mode 100644 index 0000000000000..c7a57b2cae529 --- /dev/null +++ b/tests/mir-opt/inline/inline_drops.rs @@ -0,0 +1,15 @@ +// EMIT_MIR_FOR_EACH_PANIC_STRATEGY +#![crate_type = "lib"] + +struct Pair(T, U); + +// EMIT_MIR inline_drops.half_needs_drop.Inline.diff +pub fn half_needs_drop(s: String) { + // CHECK-LABEL: fn half_needs_drop(_1: String) + // CHECK: inlined drop_in_place::> + // CHECK: _2 = Pair::({{.+}}) + // CHECK-NOT: drop + // CHECK: drop((_2.1: std::string::String)) + // CHECK-NOT: drop + let _x = Pair(true, s); +}