From e081b7b77e54a23ae11a95aaf2845446630cec42 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 3 Mar 2025 03:16:53 +0000 Subject: [PATCH 1/2] Better reasons for inline failure --- compiler/rustc_mir_transform/src/inline.rs | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index 5981b5031c649..c043a9850dd86 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -606,14 +606,14 @@ fn try_inlining<'tcx, I: Inliner<'tcx>>( ty::EarlyBinder::bind(callee_body.clone()), ) else { debug!("failed to normalize callee body"); - return Err("implementation limitation"); + return Err("implementation limitation -- could not normalize callee body"); }; // Normally, this shouldn't be required, but trait normalization failure can create a // validation ICE. if !validate_types(tcx, inliner.typing_env(), &callee_body, &caller_body).is_empty() { debug!("failed to validate callee body"); - return Err("implementation limitation"); + return Err("implementation limitation -- callee body failed validation"); } // Check call signature compatibility. @@ -622,8 +622,7 @@ fn try_inlining<'tcx, I: Inliner<'tcx>>( let output_type = callee_body.return_ty(); if !util::sub_types(tcx, inliner.typing_env(), output_type, destination_ty) { trace!(?output_type, ?destination_ty); - debug!("failed to normalize return type"); - return Err("implementation limitation"); + return Err("implementation limitation -- return type mismatch"); } if callsite.fn_sig.abi() == ExternAbi::RustCall { // FIXME: Don't inline user-written `extern "rust-call"` functions, @@ -653,7 +652,7 @@ fn try_inlining<'tcx, I: Inliner<'tcx>>( if !util::sub_types(tcx, inliner.typing_env(), input_type, arg_ty) { trace!(?arg_ty, ?input_type); debug!("failed to normalize tuple argument type"); - return Err("implementation limitation"); + return Err("implementation limitation -- arg mismatch"); } } } else { @@ -663,7 +662,7 @@ fn try_inlining<'tcx, I: Inliner<'tcx>>( if !util::sub_types(tcx, inliner.typing_env(), input_type, arg_ty) { trace!(?arg_ty, ?input_type); debug!("failed to normalize argument type"); - return Err("implementation limitation"); + return Err("implementation limitation -- arg mismatch"); } } } @@ -693,13 +692,13 @@ fn check_mir_is_available<'tcx, I: Inliner<'tcx>>( // won't cause cycles on this. if !inliner.tcx().is_mir_available(callee_def_id) { debug!("item MIR unavailable"); - return Err("implementation limitation"); + return Err("implementation limitation -- MIR unavailable"); } } // These have no own callable MIR. InstanceKind::Intrinsic(_) | InstanceKind::Virtual(..) => { debug!("instance without MIR (intrinsic / virtual)"); - return Err("implementation limitation"); + return Err("implementation limitation -- cannot inline intrinsic"); } // FIXME(#127030): `ConstParamHasTy` has bad interactions with @@ -709,7 +708,7 @@ fn check_mir_is_available<'tcx, I: Inliner<'tcx>>( // substituted. InstanceKind::DropGlue(_, Some(ty)) if ty.has_type_flags(TypeFlags::HAS_CT_PARAM) => { debug!("still needs substitution"); - return Err("implementation limitation"); + return Err("implementation limitation -- HACK for dropping polymorphic type"); } // This cannot result in an immediate cycle since the callee MIR is a shim, which does From d33946c3ab1e818d07ec9ac8198fbe958f1985c6 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 3 Mar 2025 02:12:28 +0000 Subject: [PATCH 2/2] Inline FnOnce once again --- compiler/rustc_mir_transform/src/inline.rs | 23 +++---- ...ric_rust_call.call.Inline.panic-abort.diff | 29 ++++++-- ...ic_rust_call.call.Inline.panic-unwind.diff | 41 ++++++++--- .../inline/dont_ice_on_generic_rust_call.rs | 2 +- ...inline_box_fn.call.Inline.panic-abort.diff | 32 +++++++-- ...nline_box_fn.call.Inline.panic-unwind.diff | 47 ++++++++++--- tests/mir-opt/inline/inline_box_fn.rs | 2 +- .../inline_cycle.two.Inline.panic-abort.diff | 13 +++- .../inline_cycle.two.Inline.panic-unwind.diff | 13 +++- ...inline_diverging.h.Inline.panic-abort.diff | 24 +++---- ...nline_diverging.h.Inline.panic-unwind.diff | 40 +++-------- tests/mir-opt/inline/inline_diverging.rs | 3 +- .../issue_78442.bar.Inline.panic-abort.diff | 14 ++-- .../issue_78442.bar.Inline.panic-unwind.diff | 22 +++--- tests/mir-opt/inline/issue_78442.rs | 5 +- tests/mir-opt/inline_fn_call_for_fn_def.rs | 19 ++++++ ...inline_fn_call_for_fn_def.test.Inline.diff | 34 ++++++++++ ...it.PreCodegen.after.32bit.panic-abort.mir} | 0 ...t.PreCodegen.after.32bit.panic-unwind.mir} | 0 ...git.PreCodegen.after.64bit.panic-abort.mir | 68 +++++++++++++++++++ ...it.PreCodegen.after.64bit.panic-unwind.mir | 68 +++++++++++++++++++ tests/mir-opt/issues/issue_59352.rs | 2 + .../loops.mapped.PreCodegen.after.mir | 6 +- 23 files changed, 391 insertions(+), 116 deletions(-) create mode 100644 tests/mir-opt/inline_fn_call_for_fn_def.rs create mode 100644 tests/mir-opt/inline_fn_call_for_fn_def.test.Inline.diff rename tests/mir-opt/issues/{issue_59352.num_to_digit.PreCodegen.after.panic-abort.mir => issue_59352.num_to_digit.PreCodegen.after.32bit.panic-abort.mir} (100%) rename tests/mir-opt/issues/{issue_59352.num_to_digit.PreCodegen.after.panic-unwind.mir => issue_59352.num_to_digit.PreCodegen.after.32bit.panic-unwind.mir} (100%) create mode 100644 tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.64bit.panic-abort.mir create mode 100644 tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.64bit.panic-unwind.mir diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index c043a9850dd86..0183ba19475c1 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -625,13 +625,6 @@ fn try_inlining<'tcx, I: Inliner<'tcx>>( return Err("implementation limitation -- return type mismatch"); } if callsite.fn_sig.abi() == ExternAbi::RustCall { - // FIXME: Don't inline user-written `extern "rust-call"` functions, - // since this is generally perf-negative on rustc, and we hope that - // LLVM will inline these functions instead. - if callee_body.spread_arg.is_some() { - return Err("user-written rust-call functions"); - } - let (self_arg, arg_tuple) = match &args[..] { [arg_tuple] => (None, arg_tuple), [self_arg, arg_tuple] => (Some(self_arg), arg_tuple), @@ -641,18 +634,23 @@ fn try_inlining<'tcx, I: Inliner<'tcx>>( let self_arg_ty = self_arg.map(|self_arg| self_arg.node.ty(&caller_body.local_decls, tcx)); let arg_tuple_ty = arg_tuple.node.ty(&caller_body.local_decls, tcx); - let ty::Tuple(arg_tuple_tys) = *arg_tuple_ty.kind() else { - bug!("Closure arguments are not passed as a tuple"); + let arg_tys = if callee_body.spread_arg.is_some() { + std::slice::from_ref(&arg_tuple_ty) + } else { + let ty::Tuple(arg_tuple_tys) = *arg_tuple_ty.kind() else { + bug!("Closure arguments are not passed as a tuple"); + }; + arg_tuple_tys.as_slice() }; for (arg_ty, input) in - self_arg_ty.into_iter().chain(arg_tuple_tys).zip(callee_body.args_iter()) + self_arg_ty.into_iter().chain(arg_tys.iter().copied()).zip(callee_body.args_iter()) { let input_type = callee_body.local_decls[input].ty; if !util::sub_types(tcx, inliner.typing_env(), input_type, arg_ty) { trace!(?arg_ty, ?input_type); debug!("failed to normalize tuple argument type"); - return Err("implementation limitation -- arg mismatch"); + return Err("implementation limitation"); } } } else { @@ -1059,8 +1057,7 @@ fn make_call_args<'tcx, I: Inliner<'tcx>>( closure_ref_arg.chain(tuple_tmp_args).collect() } else { - // FIXME(edition_2024): switch back to a normal method call. - <_>::into_iter(args) + args.into_iter() .map(|a| create_temp_if_necessary(inliner, a.node, callsite, caller_body, return_block)) .collect() } 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 757617e594021..0615f8132af00 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,23 +7,42 @@ let mut _0: (); let mut _3: &mut std::boxed::Box>; let mut _4: I; ++ 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; ++ } bb0: { StorageLive(_3); _3 = &mut _1; StorageLive(_4); _4 = move _2; - _0 = > as FnMut>::call_mut(move _3, move _4) -> [return: bb1, unwind unreachable]; +- _0 = > as FnMut>::call_mut(move _3, move _4) -> [return: bb1, unwind unreachable]; ++ StorageLive(_6); ++ StorageLive(_7); ++ StorageLive(_5); ++ _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]; } bb1: { - StorageDead(_4); - StorageDead(_3); - drop(_1) -> [return: bb2, unwind unreachable]; +- StorageDead(_4); +- StorageDead(_3); +- drop(_1) -> [return: bb2, unwind unreachable]; ++ return; } bb2: { - return; +- return; ++ StorageDead(_5); ++ StorageDead(_7); ++ StorageDead(_6); ++ StorageDead(_4); ++ StorageDead(_3); ++ drop(_1) -> [return: bb1, unwind unreachable]; } } diff --git a/tests/mir-opt/inline/dont_ice_on_generic_rust_call.call.Inline.panic-unwind.diff b/tests/mir-opt/inline/dont_ice_on_generic_rust_call.call.Inline.panic-unwind.diff index b82961c2815d6..21b20329d4fa9 100644 --- a/tests/mir-opt/inline/dont_ice_on_generic_rust_call.call.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/dont_ice_on_generic_rust_call.call.Inline.panic-unwind.diff @@ -7,31 +7,54 @@ let mut _0: (); let mut _3: &mut std::boxed::Box>; let mut _4: I; ++ 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; ++ } bb0: { StorageLive(_3); _3 = &mut _1; StorageLive(_4); _4 = move _2; - _0 = > as FnMut>::call_mut(move _3, move _4) -> [return: bb1, unwind: bb3]; +- _0 = > as FnMut>::call_mut(move _3, move _4) -> [return: bb1, unwind: bb3]; ++ StorageLive(_6); ++ StorageLive(_7); ++ StorageLive(_5); ++ _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: bb4, unwind: bb2]; } bb1: { - StorageDead(_4); - StorageDead(_3); - drop(_1) -> [return: bb2, unwind: bb4]; +- StorageDead(_4); +- StorageDead(_3); +- drop(_1) -> [return: bb2, unwind: bb4]; ++ return; } - bb2: { - return; +- bb2: { +- return; ++ bb2 (cleanup): { ++ drop(_1) -> [return: bb3, unwind terminate(cleanup)]; } bb3 (cleanup): { - drop(_1) -> [return: bb4, unwind terminate(cleanup)]; +- drop(_1) -> [return: bb4, unwind terminate(cleanup)]; ++ resume; } - bb4 (cleanup): { - resume; +- bb4 (cleanup): { +- resume; ++ bb4: { ++ StorageDead(_5); ++ StorageDead(_7); ++ StorageDead(_6); ++ StorageDead(_4); ++ StorageDead(_3); ++ drop(_1) -> [return: bb1, unwind: bb3]; } } diff --git a/tests/mir-opt/inline/dont_ice_on_generic_rust_call.rs b/tests/mir-opt/inline/dont_ice_on_generic_rust_call.rs index abc0ef5c61d5f..ac0c3ddac764c 100644 --- a/tests/mir-opt/inline/dont_ice_on_generic_rust_call.rs +++ b/tests/mir-opt/inline/dont_ice_on_generic_rust_call.rs @@ -8,6 +8,6 @@ use std::marker::Tuple; // EMIT_MIR dont_ice_on_generic_rust_call.call.Inline.diff pub fn call(mut mock: Box>, input: I) { // CHECK-LABEL: fn call( - // CHECK-NOT: inlined + // CHECK: (inlined > as FnMut>::call_mut) mock.call_mut(input) } 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 4fa04b05e8993..ecea7a97513d5 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,6 +7,11 @@ let _2: (); let mut _3: &std::boxed::Box; let mut _4: (i32,); ++ 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); ++ } bb0: { StorageLive(_2); @@ -14,19 +19,34 @@ _3 = &_1; StorageLive(_4); _4 = (const 1_i32,); - _2 = as Fn<(i32,)>>::call(move _3, move _4) -> [return: bb1, unwind unreachable]; +- _2 = as Fn<(i32,)>>::call(move _3, move _4) -> [return: bb1, unwind unreachable]; ++ StorageLive(_6); ++ StorageLive(_7); ++ StorageLive(_5); ++ _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]; } bb1: { ++ return; ++ } ++ ++ bb2: { ++ StorageDead(_5); ++ StorageDead(_7); ++ StorageDead(_6); StorageDead(_4); StorageDead(_3); StorageDead(_2); _0 = const (); - drop(_1) -> [return: bb2, unwind unreachable]; - } - - bb2: { - return; +- drop(_1) -> [return: bb2, unwind unreachable]; +- } +- +- bb2: { +- return; ++ drop(_1) -> [return: bb1, unwind unreachable]; } } diff --git a/tests/mir-opt/inline/inline_box_fn.call.Inline.panic-unwind.diff b/tests/mir-opt/inline/inline_box_fn.call.Inline.panic-unwind.diff index 47fd0ed079995..3a4a528e879fb 100644 --- a/tests/mir-opt/inline/inline_box_fn.call.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/inline_box_fn.call.Inline.panic-unwind.diff @@ -7,6 +7,11 @@ let _2: (); let mut _3: &std::boxed::Box; let mut _4: (i32,); ++ 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); ++ } bb0: { StorageLive(_2); @@ -14,27 +19,47 @@ _3 = &_1; StorageLive(_4); _4 = (const 1_i32,); - _2 = as Fn<(i32,)>>::call(move _3, move _4) -> [return: bb1, unwind: bb3]; +- _2 = as Fn<(i32,)>>::call(move _3, move _4) -> [return: bb1, unwind: bb3]; ++ StorageLive(_6); ++ StorageLive(_7); ++ StorageLive(_5); ++ _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: bb4, unwind: bb2]; } bb1: { - StorageDead(_4); - StorageDead(_3); - StorageDead(_2); - _0 = const (); - drop(_1) -> [return: bb2, unwind: bb4]; +- StorageDead(_4); +- StorageDead(_3); +- StorageDead(_2); +- _0 = const (); +- drop(_1) -> [return: bb2, unwind: bb4]; ++ return; } - bb2: { - return; +- bb2: { +- return; ++ bb2 (cleanup): { ++ drop(_1) -> [return: bb3, unwind terminate(cleanup)]; } bb3 (cleanup): { - drop(_1) -> [return: bb4, unwind terminate(cleanup)]; +- drop(_1) -> [return: bb4, unwind terminate(cleanup)]; ++ resume; } - bb4 (cleanup): { - resume; +- bb4 (cleanup): { +- resume; ++ bb4: { ++ StorageDead(_5); ++ StorageDead(_7); ++ StorageDead(_6); ++ StorageDead(_4); ++ StorageDead(_3); ++ StorageDead(_2); ++ _0 = const (); ++ drop(_1) -> [return: bb1, unwind: bb3]; } } diff --git a/tests/mir-opt/inline/inline_box_fn.rs b/tests/mir-opt/inline/inline_box_fn.rs index bb2da3ac51576..e9ab3bef01fbe 100644 --- a/tests/mir-opt/inline/inline_box_fn.rs +++ b/tests/mir-opt/inline/inline_box_fn.rs @@ -5,6 +5,6 @@ // EMIT_MIR inline_box_fn.call.Inline.diff fn call(x: Box) { // CHECK-LABEL: fn call( - // CHECK-NOT: inlined + // CHECK: (inlined as Fn<(i32,)>>::call) x(1); } diff --git a/tests/mir-opt/inline/inline_cycle.two.Inline.panic-abort.diff b/tests/mir-opt/inline/inline_cycle.two.Inline.panic-abort.diff index 8a6eec3352a34..c878b8b632414 100644 --- a/tests/mir-opt/inline/inline_cycle.two.Inline.panic-abort.diff +++ b/tests/mir-opt/inline/inline_cycle.two.Inline.panic-abort.diff @@ -5,9 +5,15 @@ let mut _0: (); let _1: (); + let mut _2: fn() {f}; ++ let mut _4: (); + scope 1 (inlined call::) { + debug f => _2; + let _3: (); ++ scope 2 (inlined >::call_once - shim(fn() {f})) { ++ scope 3 (inlined f) { ++ let _5: (); ++ } ++ } + } bb0: { @@ -16,10 +22,15 @@ + StorageLive(_2); + _2 = f; + StorageLive(_3); -+ _3 = >::call_once(move _2, const ()) -> [return: bb1, unwind unreachable]; ++ StorageLive(_4); ++ _4 = const (); ++ StorageLive(_5); ++ _5 = call::(f) -> [return: bb1, unwind unreachable]; } bb1: { ++ StorageDead(_5); ++ StorageDead(_4); + StorageDead(_3); + StorageDead(_2); StorageDead(_1); diff --git a/tests/mir-opt/inline/inline_cycle.two.Inline.panic-unwind.diff b/tests/mir-opt/inline/inline_cycle.two.Inline.panic-unwind.diff index a24649c1ebd57..072b7ab3fa491 100644 --- a/tests/mir-opt/inline/inline_cycle.two.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/inline_cycle.two.Inline.panic-unwind.diff @@ -5,9 +5,15 @@ let mut _0: (); let _1: (); + let mut _2: fn() {f}; ++ let mut _4: (); + scope 1 (inlined call::) { + debug f => _2; + let _3: (); ++ scope 2 (inlined >::call_once - shim(fn() {f})) { ++ scope 3 (inlined f) { ++ let _5: (); ++ } ++ } + } bb0: { @@ -16,10 +22,15 @@ + StorageLive(_2); + _2 = f; + StorageLive(_3); -+ _3 = >::call_once(move _2, const ()) -> [return: bb1, unwind continue]; ++ StorageLive(_4); ++ _4 = const (); ++ StorageLive(_5); ++ _5 = call::(f) -> [return: bb1, unwind continue]; } bb1: { ++ StorageDead(_5); ++ StorageDead(_4); + StorageDead(_3); + StorageDead(_2); StorageDead(_1); diff --git a/tests/mir-opt/inline/inline_diverging.h.Inline.panic-abort.diff b/tests/mir-opt/inline/inline_diverging.h.Inline.panic-abort.diff index 338dca85e5c9f..75fc2ea16e3d9 100644 --- a/tests/mir-opt/inline/inline_diverging.h.Inline.panic-abort.diff +++ b/tests/mir-opt/inline/inline_diverging.h.Inline.panic-abort.diff @@ -5,6 +5,7 @@ let mut _0: (); let _1: (!, !); + let mut _2: fn() -> ! {sleep}; ++ let mut _7: (); + scope 1 (inlined call_twice:: ! {sleep}>) { + debug f => _2; + let mut _3: &fn() -> ! {sleep}; @@ -17,6 +18,10 @@ + debug b => _6; + } + } ++ scope 4 (inlined ! {sleep} as Fn<()>>::call - shim(fn() -> ! {sleep})) { ++ scope 5 (inlined sleep) { ++ } ++ } + } bb0: { @@ -28,24 +33,13 @@ + StorageLive(_6); + StorageLive(_3); + _3 = &_2; -+ _4 = ! {sleep} as Fn<()>>::call(move _3, const ()) -> [return: bb1, unwind unreachable]; ++ StorageLive(_7); ++ _7 = const (); ++ goto -> bb1; + } + + bb1: { -+ StorageDead(_3); -+ StorageLive(_5); -+ _5 = &_2; -+ _6 = ! {sleep} as Fn<()>>::call(move _5, const ()) -> [return: bb2, unwind unreachable]; -+ } -+ -+ bb2: { -+ StorageDead(_5); -+ _1 = (copy _4, copy _6); -+ drop(_2) -> [return: bb3, unwind unreachable]; -+ } -+ -+ bb3: { -+ unreachable; ++ goto -> bb1; } } diff --git a/tests/mir-opt/inline/inline_diverging.h.Inline.panic-unwind.diff b/tests/mir-opt/inline/inline_diverging.h.Inline.panic-unwind.diff index a77cb913bfd03..407cb24df6751 100644 --- a/tests/mir-opt/inline/inline_diverging.h.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/inline_diverging.h.Inline.panic-unwind.diff @@ -5,6 +5,7 @@ let mut _0: (); let _1: (!, !); + let mut _2: fn() -> ! {sleep}; ++ let mut _8: (); + scope 1 (inlined call_twice:: ! {sleep}>) { + debug f => _2; + let mut _3: &fn() -> ! {sleep}; @@ -18,6 +19,10 @@ + debug b => _6; + } + } ++ scope 4 (inlined ! {sleep} as Fn<()>>::call - shim(fn() -> ! {sleep})) { ++ scope 5 (inlined sleep) { ++ } ++ } + } bb0: { @@ -29,40 +34,13 @@ + StorageLive(_4); + StorageLive(_3); + _3 = &_2; -+ _4 = ! {sleep} as Fn<()>>::call(move _3, const ()) -> [return: bb1, unwind: bb5]; ++ StorageLive(_8); ++ _8 = const (); ++ goto -> bb1; + } + + bb1: { -+ StorageDead(_3); -+ StorageLive(_5); -+ _5 = &_2; -+ _6 = ! {sleep} as Fn<()>>::call(move _5, const ()) -> [return: bb2, unwind: bb4]; -+ } -+ -+ bb2: { -+ StorageDead(_5); -+ StorageLive(_7); -+ _7 = move _4; -+ _1 = (move _7, copy _6); -+ StorageDead(_7); -+ StorageDead(_4); -+ drop(_2) -> [return: bb3, unwind continue]; -+ } -+ -+ bb3: { -+ unreachable; -+ } -+ -+ bb4 (cleanup): { -+ drop(_4) -> [return: bb5, unwind terminate(cleanup)]; -+ } -+ -+ bb5 (cleanup): { -+ drop(_2) -> [return: bb6, unwind terminate(cleanup)]; -+ } -+ -+ bb6 (cleanup): { -+ resume; ++ goto -> bb1; } } diff --git a/tests/mir-opt/inline/inline_diverging.rs b/tests/mir-opt/inline/inline_diverging.rs index e1cea3618f176..04ff943e74657 100644 --- a/tests/mir-opt/inline/inline_diverging.rs +++ b/tests/mir-opt/inline/inline_diverging.rs @@ -26,7 +26,8 @@ pub fn g(i: i32) -> u32 { pub fn h() { // CHECK-LABEL: fn h( // CHECK: (inlined call_twice:: ! {sleep}>) - // CHECK-NOT: inlined + // CHECK: (inlined ! {sleep} as Fn<()>>::call - shim(fn() -> ! {sleep})) + // CHECK: (inlined sleep) call_twice(sleep); } diff --git a/tests/mir-opt/inline/issue_78442.bar.Inline.panic-abort.diff b/tests/mir-opt/inline/issue_78442.bar.Inline.panic-abort.diff index b9f268df35150..14a0c639c3abd 100644 --- a/tests/mir-opt/inline/issue_78442.bar.Inline.panic-abort.diff +++ b/tests/mir-opt/inline/issue_78442.bar.Inline.panic-abort.diff @@ -9,6 +9,10 @@ let _4: fn() {foo}; let mut _5: (); + scope 1 (inlined hide_foo) { ++ } ++ scope 2 (inlined >::call - shim(fn() {foo})) { ++ scope 3 (inlined foo) { ++ } + } bb0: { @@ -23,22 +27,20 @@ StorageLive(_5); _5 = (); - _2 = >::call(move _3, move _5) -> [return: bb2, unwind unreachable]; -+ _2 = >::call(move _3, move _5) -> [return: bb1, unwind unreachable]; - } - +- } +- - bb2: { -+ bb1: { StorageDead(_5); StorageDead(_3); StorageDead(_4); StorageDead(_2); _0 = const (); - drop(_1) -> [return: bb3, unwind unreachable]; -+ drop(_1) -> [return: bb2, unwind unreachable]; ++ drop(_1) -> [return: bb1, unwind unreachable]; } - bb3: { -+ bb2: { ++ bb1: { return; } } diff --git a/tests/mir-opt/inline/issue_78442.bar.Inline.panic-unwind.diff b/tests/mir-opt/inline/issue_78442.bar.Inline.panic-unwind.diff index 8495164df9c62..e0a273eb13f50 100644 --- a/tests/mir-opt/inline/issue_78442.bar.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/issue_78442.bar.Inline.panic-unwind.diff @@ -9,6 +9,10 @@ let _4: fn() {foo}; let mut _5: (); + scope 1 (inlined hide_foo) { ++ } ++ scope 2 (inlined >::call - shim(fn() {foo})) { ++ scope 3 (inlined foo) { ++ } + } bb0: { @@ -23,33 +27,29 @@ StorageLive(_5); _5 = (); - _2 = >::call(move _3, move _5) -> [return: bb2, unwind: bb4]; -+ _2 = >::call(move _3, move _5) -> [return: bb1, unwind: bb3]; - } - +- } +- - bb2: { -+ bb1: { StorageDead(_5); StorageDead(_3); StorageDead(_4); StorageDead(_2); _0 = const (); - drop(_1) -> [return: bb3, unwind: bb5]; -+ drop(_1) -> [return: bb2, unwind: bb4]; ++ drop(_1) -> [return: bb1, unwind: bb2]; } - bb3: { -+ bb2: { ++ bb1: { return; } - bb4 (cleanup): { - drop(_1) -> [return: bb5, unwind terminate(cleanup)]; -+ bb3 (cleanup): { -+ drop(_1) -> [return: bb4, unwind terminate(cleanup)]; - } - +- } +- - bb5 (cleanup): { -+ bb4 (cleanup): { ++ bb2 (cleanup): { resume; } } diff --git a/tests/mir-opt/inline/issue_78442.rs b/tests/mir-opt/inline/issue_78442.rs index 4eb5c142034c2..a142d45737748 100644 --- a/tests/mir-opt/inline/issue_78442.rs +++ b/tests/mir-opt/inline/issue_78442.rs @@ -9,10 +9,9 @@ pub fn bar

( _baz: P, ) { // CHECK-LABEL: fn bar( - // CHECK: let mut {{.*}}: &fn() {foo}; - // CHECK: let {{.*}}: fn() {foo}; // CHECK: (inlined hide_foo) - // CHECK-NOT: inlined + // CHECK: (inlined >::call - shim(fn() {foo})) + // CHECK: (inlined foo) hide_foo()(); } diff --git a/tests/mir-opt/inline_fn_call_for_fn_def.rs b/tests/mir-opt/inline_fn_call_for_fn_def.rs new file mode 100644 index 0000000000000..7601feda57325 --- /dev/null +++ b/tests/mir-opt/inline_fn_call_for_fn_def.rs @@ -0,0 +1,19 @@ +//@ test-mir-pass: Inline +//@ compile-flags: --crate-type=lib -C panic=abort + +// EMIT_MIR inline_fn_call_for_fn_def.test.Inline.diff + +fn inline_fn(x: impl FnOnce() -> i32) -> i32 { + x() +} + +fn yield_number() -> i32 { + 64 +} + +fn test() -> i32 { + // CHECK: (inlined inline_fn:: i32 {yield_number}>) + // CHECK: (inlined i32 {yield_number} as FnOnce<()>>::call_once - shim(fn() -> i32 {yield_number})) + // CHECK: (inlined yield_number) + inline_fn(yield_number) +} diff --git a/tests/mir-opt/inline_fn_call_for_fn_def.test.Inline.diff b/tests/mir-opt/inline_fn_call_for_fn_def.test.Inline.diff new file mode 100644 index 0000000000000..aef7aa2397095 --- /dev/null +++ b/tests/mir-opt/inline_fn_call_for_fn_def.test.Inline.diff @@ -0,0 +1,34 @@ +- // MIR for `test` before Inline ++ // MIR for `test` after Inline + + fn test() -> i32 { + let mut _0: i32; +- +- bb0: { +- _0 = inline_fn:: i32 {yield_number}>(yield_number) -> [return: bb1, unwind unreachable]; ++ let mut _1: fn() -> i32 {yield_number}; ++ scope 1 (inlined inline_fn:: i32 {yield_number}>) { ++ let mut _2: fn() -> i32 {yield_number}; ++ let mut _3: (); ++ scope 2 (inlined i32 {yield_number} as FnOnce<()>>::call_once - shim(fn() -> i32 {yield_number})) { ++ scope 3 (inlined yield_number) { ++ } ++ } + } + +- bb1: { ++ bb0: { ++ StorageLive(_1); ++ _1 = yield_number; ++ StorageLive(_2); ++ _2 = move _1; ++ StorageLive(_3); ++ _3 = (); ++ _0 = const 64_i32; ++ StorageDead(_3); ++ StorageDead(_2); ++ StorageDead(_1); + return; + } + } + diff --git a/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-abort.mir b/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.32bit.panic-abort.mir similarity index 100% rename from tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-abort.mir rename to tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.32bit.panic-abort.mir diff --git a/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.32bit.panic-unwind.mir similarity index 100% rename from tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-unwind.mir rename to tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.32bit.panic-unwind.mir diff --git a/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.64bit.panic-abort.mir b/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.64bit.panic-abort.mir new file mode 100644 index 0000000000000..5876c55c52b94 --- /dev/null +++ b/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.64bit.panic-abort.mir @@ -0,0 +1,68 @@ +// MIR for `num_to_digit` after PreCodegen + +fn num_to_digit(_1: char) -> u32 { + debug num => _1; + let mut _0: u32; + let mut _4: std::option::Option; + scope 1 (inlined char::methods::::is_digit) { + let _2: std::option::Option; + scope 2 (inlined Option::::is_some) { + let mut _3: isize; + } + } + scope 3 (inlined #[track_caller] Option::::unwrap) { + let mut _5: isize; + let mut _6: !; + scope 4 { + } + } + + bb0: { + StorageLive(_2); + _2 = char::methods::::to_digit(copy _1, const 8_u32) -> [return: bb1, unwind unreachable]; + } + + bb1: { + StorageLive(_3); + _3 = discriminant(_2); + StorageDead(_2); + switchInt(move _3) -> [1: bb2, otherwise: bb7]; + } + + bb2: { + StorageDead(_3); + StorageLive(_4); + _4 = char::methods::::to_digit(move _1, const 8_u32) -> [return: bb3, unwind unreachable]; + } + + bb3: { + StorageLive(_5); + _5 = discriminant(_4); + switchInt(move _5) -> [0: bb4, 1: bb5, otherwise: bb6]; + } + + bb4: { + _6 = option::unwrap_failed() -> unwind unreachable; + } + + bb5: { + _0 = move ((_4 as Some).0: u32); + StorageDead(_5); + StorageDead(_4); + goto -> bb8; + } + + bb6: { + unreachable; + } + + bb7: { + StorageDead(_3); + _0 = const 0_u32; + goto -> bb8; + } + + bb8: { + return; + } +} diff --git a/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.64bit.panic-unwind.mir b/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.64bit.panic-unwind.mir new file mode 100644 index 0000000000000..f1185353a43c8 --- /dev/null +++ b/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.64bit.panic-unwind.mir @@ -0,0 +1,68 @@ +// MIR for `num_to_digit` after PreCodegen + +fn num_to_digit(_1: char) -> u32 { + debug num => _1; + let mut _0: u32; + let mut _4: std::option::Option; + scope 1 (inlined char::methods::::is_digit) { + let _2: std::option::Option; + scope 2 (inlined Option::::is_some) { + let mut _3: isize; + } + } + scope 3 (inlined #[track_caller] Option::::unwrap) { + let mut _5: isize; + let mut _6: !; + scope 4 { + } + } + + bb0: { + StorageLive(_2); + _2 = char::methods::::to_digit(copy _1, const 8_u32) -> [return: bb1, unwind continue]; + } + + bb1: { + StorageLive(_3); + _3 = discriminant(_2); + StorageDead(_2); + switchInt(move _3) -> [1: bb2, otherwise: bb7]; + } + + bb2: { + StorageDead(_3); + StorageLive(_4); + _4 = char::methods::::to_digit(move _1, const 8_u32) -> [return: bb3, unwind continue]; + } + + bb3: { + StorageLive(_5); + _5 = discriminant(_4); + switchInt(move _5) -> [0: bb4, 1: bb5, otherwise: bb6]; + } + + bb4: { + _6 = option::unwrap_failed() -> unwind continue; + } + + bb5: { + _0 = move ((_4 as Some).0: u32); + StorageDead(_5); + StorageDead(_4); + goto -> bb8; + } + + bb6: { + unreachable; + } + + bb7: { + StorageDead(_3); + _0 = const 0_u32; + goto -> bb8; + } + + bb8: { + return; + } +} diff --git a/tests/mir-opt/issues/issue_59352.rs b/tests/mir-opt/issues/issue_59352.rs index 9024dc976e494..516a712f1db16 100644 --- a/tests/mir-opt/issues/issue_59352.rs +++ b/tests/mir-opt/issues/issue_59352.rs @@ -1,4 +1,6 @@ // EMIT_MIR_FOR_EACH_PANIC_STRATEGY +// EMIT_MIR_FOR_EACH_BIT_WIDTH + // This test is a mirror of codegen/issue-59352.rs. // The LLVM inliner doesn't inline `char::method::is_digit()` and so it doesn't recognize this case // as effectively `if x.is_some() { x.unwrap() } else { 0 }`. diff --git a/tests/mir-opt/pre-codegen/loops.mapped.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/loops.mapped.PreCodegen.after.mir index 4977f39ccefe8..d22ea54004c91 100644 --- a/tests/mir-opt/pre-codegen/loops.mapped.PreCodegen.after.mir +++ b/tests/mir-opt/pre-codegen/loops.mapped.PreCodegen.after.mir @@ -29,6 +29,10 @@ fn mapped(_1: impl Iterator, _2: impl Fn(T) -> U) -> () { let mut _12: U; scope 6 { debug x => _10; + scope 7 (inlined ops::function::impls:: for &mut impl Fn(T) -> U>::call_once) { + debug self => _8; + debug args => _11; + } } } } @@ -85,7 +89,7 @@ fn mapped(_1: impl Iterator, _2: impl Fn(T) -> U) -> () { StorageLive(_12); StorageLive(_11); _11 = (copy _10,); - _12 = <&mut impl Fn(T) -> U as FnOnce<(T,)>>::call_once(move _8, move _11) -> [return: bb7, unwind: bb10]; + _12 = U as FnMut<(T,)>>::call_mut(move _8, move _11) -> [return: bb7, unwind: bb10]; } bb7: {