Inline FnOnce once again
This commit is contained in:
parent
e081b7b77e
commit
d33946c3ab
23 changed files with 391 additions and 116 deletions
|
@ -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()
|
||||
}
|
||||
|
|
|
@ -7,23 +7,42 @@
|
|||
let mut _0: ();
|
||||
let mut _3: &mut std::boxed::Box<dyn std::ops::FnMut<I, Output = ()>>;
|
||||
let mut _4: I;
|
||||
+ scope 1 (inlined <Box<dyn FnMut<I, Output = ()>> as FnMut<I>>::call_mut) {
|
||||
+ let mut _5: &mut dyn std::ops::FnMut<I, Output = ()>;
|
||||
+ let mut _6: std::boxed::Box<dyn std::ops::FnMut<I, Output = ()>>;
|
||||
+ let mut _7: *const dyn std::ops::FnMut<I, Output = ()>;
|
||||
+ }
|
||||
|
||||
bb0: {
|
||||
StorageLive(_3);
|
||||
_3 = &mut _1;
|
||||
StorageLive(_4);
|
||||
_4 = move _2;
|
||||
_0 = <Box<dyn FnMut<I, Output = ()>> as FnMut<I>>::call_mut(move _3, move _4) -> [return: bb1, unwind unreachable];
|
||||
- _0 = <Box<dyn FnMut<I, Output = ()>> as FnMut<I>>::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<dyn std::ops::FnMut<I, Output = ()>>).0: std::ptr::NonNull<dyn std::ops::FnMut<I, Output = ()>>) as *const dyn std::ops::FnMut<I, Output = ()> (Transmute);
|
||||
+ _5 = &mut (*_7);
|
||||
+ _0 = <dyn FnMut<I, Output = ()> as FnMut<I>>::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];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -7,31 +7,54 @@
|
|||
let mut _0: ();
|
||||
let mut _3: &mut std::boxed::Box<dyn std::ops::FnMut<I, Output = ()>>;
|
||||
let mut _4: I;
|
||||
+ scope 1 (inlined <Box<dyn FnMut<I, Output = ()>> as FnMut<I>>::call_mut) {
|
||||
+ let mut _5: &mut dyn std::ops::FnMut<I, Output = ()>;
|
||||
+ let mut _6: std::boxed::Box<dyn std::ops::FnMut<I, Output = ()>>;
|
||||
+ let mut _7: *const dyn std::ops::FnMut<I, Output = ()>;
|
||||
+ }
|
||||
|
||||
bb0: {
|
||||
StorageLive(_3);
|
||||
_3 = &mut _1;
|
||||
StorageLive(_4);
|
||||
_4 = move _2;
|
||||
_0 = <Box<dyn FnMut<I, Output = ()>> as FnMut<I>>::call_mut(move _3, move _4) -> [return: bb1, unwind: bb3];
|
||||
- _0 = <Box<dyn FnMut<I, Output = ()>> as FnMut<I>>::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<dyn std::ops::FnMut<I, Output = ()>>).0: std::ptr::NonNull<dyn std::ops::FnMut<I, Output = ()>>) as *const dyn std::ops::FnMut<I, Output = ()> (Transmute);
|
||||
+ _5 = &mut (*_7);
|
||||
+ _0 = <dyn FnMut<I, Output = ()> as FnMut<I>>::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];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -8,6 +8,6 @@ use std::marker::Tuple;
|
|||
// EMIT_MIR dont_ice_on_generic_rust_call.call.Inline.diff
|
||||
pub fn call<I: Tuple>(mut mock: Box<dyn FnMut<I, Output = ()>>, input: I) {
|
||||
// CHECK-LABEL: fn call(
|
||||
// CHECK-NOT: inlined
|
||||
// CHECK: (inlined <Box<dyn FnMut<I, Output = ()>> as FnMut<I>>::call_mut)
|
||||
mock.call_mut(input)
|
||||
}
|
||||
|
|
|
@ -7,6 +7,11 @@
|
|||
let _2: ();
|
||||
let mut _3: &std::boxed::Box<dyn std::ops::Fn(i32)>;
|
||||
let mut _4: (i32,);
|
||||
+ scope 1 (inlined <Box<dyn Fn(i32)> as Fn<(i32,)>>::call) {
|
||||
+ let mut _5: &dyn std::ops::Fn(i32);
|
||||
+ let mut _6: std::boxed::Box<dyn std::ops::Fn(i32)>;
|
||||
+ 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 = <Box<dyn Fn(i32)> as Fn<(i32,)>>::call(move _3, move _4) -> [return: bb1, unwind unreachable];
|
||||
- _2 = <Box<dyn Fn(i32)> 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<dyn std::ops::Fn(i32)>).0: std::ptr::NonNull<dyn std::ops::Fn(i32)>) as *const dyn std::ops::Fn(i32) (Transmute);
|
||||
+ _5 = &(*_7);
|
||||
+ _2 = <dyn Fn(i32) as Fn<(i32,)>>::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];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -7,6 +7,11 @@
|
|||
let _2: ();
|
||||
let mut _3: &std::boxed::Box<dyn std::ops::Fn(i32)>;
|
||||
let mut _4: (i32,);
|
||||
+ scope 1 (inlined <Box<dyn Fn(i32)> as Fn<(i32,)>>::call) {
|
||||
+ let mut _5: &dyn std::ops::Fn(i32);
|
||||
+ let mut _6: std::boxed::Box<dyn std::ops::Fn(i32)>;
|
||||
+ 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 = <Box<dyn Fn(i32)> as Fn<(i32,)>>::call(move _3, move _4) -> [return: bb1, unwind: bb3];
|
||||
- _2 = <Box<dyn Fn(i32)> 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<dyn std::ops::Fn(i32)>).0: std::ptr::NonNull<dyn std::ops::Fn(i32)>) as *const dyn std::ops::Fn(i32) (Transmute);
|
||||
+ _5 = &(*_7);
|
||||
+ _2 = <dyn Fn(i32) as Fn<(i32,)>>::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];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -5,6 +5,6 @@
|
|||
// EMIT_MIR inline_box_fn.call.Inline.diff
|
||||
fn call(x: Box<dyn Fn(i32)>) {
|
||||
// CHECK-LABEL: fn call(
|
||||
// CHECK-NOT: inlined
|
||||
// CHECK: (inlined <Box<dyn Fn(i32)> as Fn<(i32,)>>::call)
|
||||
x(1);
|
||||
}
|
||||
|
|
|
@ -5,9 +5,15 @@
|
|||
let mut _0: ();
|
||||
let _1: ();
|
||||
+ let mut _2: fn() {f};
|
||||
+ let mut _4: ();
|
||||
+ scope 1 (inlined call::<fn() {f}>) {
|
||||
+ debug f => _2;
|
||||
+ let _3: ();
|
||||
+ scope 2 (inlined <fn() {f} as FnOnce<()>>::call_once - shim(fn() {f})) {
|
||||
+ scope 3 (inlined f) {
|
||||
+ let _5: ();
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
|
||||
bb0: {
|
||||
|
@ -16,10 +22,15 @@
|
|||
+ StorageLive(_2);
|
||||
+ _2 = f;
|
||||
+ StorageLive(_3);
|
||||
+ _3 = <fn() {f} as FnOnce<()>>::call_once(move _2, const ()) -> [return: bb1, unwind unreachable];
|
||||
+ StorageLive(_4);
|
||||
+ _4 = const ();
|
||||
+ StorageLive(_5);
|
||||
+ _5 = call::<fn() {f}>(f) -> [return: bb1, unwind unreachable];
|
||||
}
|
||||
|
||||
bb1: {
|
||||
+ StorageDead(_5);
|
||||
+ StorageDead(_4);
|
||||
+ StorageDead(_3);
|
||||
+ StorageDead(_2);
|
||||
StorageDead(_1);
|
||||
|
|
|
@ -5,9 +5,15 @@
|
|||
let mut _0: ();
|
||||
let _1: ();
|
||||
+ let mut _2: fn() {f};
|
||||
+ let mut _4: ();
|
||||
+ scope 1 (inlined call::<fn() {f}>) {
|
||||
+ debug f => _2;
|
||||
+ let _3: ();
|
||||
+ scope 2 (inlined <fn() {f} as FnOnce<()>>::call_once - shim(fn() {f})) {
|
||||
+ scope 3 (inlined f) {
|
||||
+ let _5: ();
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
|
||||
bb0: {
|
||||
|
@ -16,10 +22,15 @@
|
|||
+ StorageLive(_2);
|
||||
+ _2 = f;
|
||||
+ StorageLive(_3);
|
||||
+ _3 = <fn() {f} as FnOnce<()>>::call_once(move _2, const ()) -> [return: bb1, unwind continue];
|
||||
+ StorageLive(_4);
|
||||
+ _4 = const ();
|
||||
+ StorageLive(_5);
|
||||
+ _5 = call::<fn() {f}>(f) -> [return: bb1, unwind continue];
|
||||
}
|
||||
|
||||
bb1: {
|
||||
+ StorageDead(_5);
|
||||
+ StorageDead(_4);
|
||||
+ StorageDead(_3);
|
||||
+ StorageDead(_2);
|
||||
StorageDead(_1);
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
let mut _0: ();
|
||||
let _1: (!, !);
|
||||
+ let mut _2: fn() -> ! {sleep};
|
||||
+ let mut _7: ();
|
||||
+ scope 1 (inlined call_twice::<!, fn() -> ! {sleep}>) {
|
||||
+ debug f => _2;
|
||||
+ let mut _3: &fn() -> ! {sleep};
|
||||
|
@ -17,6 +18,10 @@
|
|||
+ debug b => _6;
|
||||
+ }
|
||||
+ }
|
||||
+ scope 4 (inlined <fn() -> ! {sleep} as Fn<()>>::call - shim(fn() -> ! {sleep})) {
|
||||
+ scope 5 (inlined sleep) {
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
|
||||
bb0: {
|
||||
|
@ -28,24 +33,13 @@
|
|||
+ StorageLive(_6);
|
||||
+ StorageLive(_3);
|
||||
+ _3 = &_2;
|
||||
+ _4 = <fn() -> ! {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 = <fn() -> ! {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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
let mut _0: ();
|
||||
let _1: (!, !);
|
||||
+ let mut _2: fn() -> ! {sleep};
|
||||
+ let mut _8: ();
|
||||
+ scope 1 (inlined call_twice::<!, fn() -> ! {sleep}>) {
|
||||
+ debug f => _2;
|
||||
+ let mut _3: &fn() -> ! {sleep};
|
||||
|
@ -18,6 +19,10 @@
|
|||
+ debug b => _6;
|
||||
+ }
|
||||
+ }
|
||||
+ scope 4 (inlined <fn() -> ! {sleep} as Fn<()>>::call - shim(fn() -> ! {sleep})) {
|
||||
+ scope 5 (inlined sleep) {
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
|
||||
bb0: {
|
||||
|
@ -29,40 +34,13 @@
|
|||
+ StorageLive(_4);
|
||||
+ StorageLive(_3);
|
||||
+ _3 = &_2;
|
||||
+ _4 = <fn() -> ! {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 = <fn() -> ! {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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -26,7 +26,8 @@ pub fn g(i: i32) -> u32 {
|
|||
pub fn h() {
|
||||
// CHECK-LABEL: fn h(
|
||||
// CHECK: (inlined call_twice::<!, fn() -> ! {sleep}>)
|
||||
// CHECK-NOT: inlined
|
||||
// CHECK: (inlined <fn() -> ! {sleep} as Fn<()>>::call - shim(fn() -> ! {sleep}))
|
||||
// CHECK: (inlined sleep)
|
||||
call_twice(sleep);
|
||||
}
|
||||
|
||||
|
|
|
@ -9,6 +9,10 @@
|
|||
let _4: fn() {foo};
|
||||
let mut _5: ();
|
||||
+ scope 1 (inlined hide_foo) {
|
||||
+ }
|
||||
+ scope 2 (inlined <fn() {foo} as Fn<()>>::call - shim(fn() {foo})) {
|
||||
+ scope 3 (inlined foo) {
|
||||
+ }
|
||||
+ }
|
||||
|
||||
bb0: {
|
||||
|
@ -23,22 +27,20 @@
|
|||
StorageLive(_5);
|
||||
_5 = ();
|
||||
- _2 = <fn() {foo} as Fn<()>>::call(move _3, move _5) -> [return: bb2, unwind unreachable];
|
||||
+ _2 = <fn() {foo} as Fn<()>>::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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,6 +9,10 @@
|
|||
let _4: fn() {foo};
|
||||
let mut _5: ();
|
||||
+ scope 1 (inlined hide_foo) {
|
||||
+ }
|
||||
+ scope 2 (inlined <fn() {foo} as Fn<()>>::call - shim(fn() {foo})) {
|
||||
+ scope 3 (inlined foo) {
|
||||
+ }
|
||||
+ }
|
||||
|
||||
bb0: {
|
||||
|
@ -23,33 +27,29 @@
|
|||
StorageLive(_5);
|
||||
_5 = ();
|
||||
- _2 = <fn() {foo} as Fn<()>>::call(move _3, move _5) -> [return: bb2, unwind: bb4];
|
||||
+ _2 = <fn() {foo} as Fn<()>>::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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,10 +9,9 @@ pub fn bar<P>(
|
|||
_baz: P,
|
||||
) {
|
||||
// CHECK-LABEL: fn bar(
|
||||
// CHECK: let mut {{.*}}: &fn() {foo};
|
||||
// CHECK: let {{.*}}: fn() {foo};
|
||||
// CHECK: (inlined hide_foo)
|
||||
// CHECK-NOT: inlined
|
||||
// CHECK: (inlined <fn() {foo} as Fn<()>>::call - shim(fn() {foo}))
|
||||
// CHECK: (inlined foo)
|
||||
hide_foo()();
|
||||
}
|
||||
|
||||
|
|
19
tests/mir-opt/inline_fn_call_for_fn_def.rs
Normal file
19
tests/mir-opt/inline_fn_call_for_fn_def.rs
Normal file
|
@ -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::<fn() -> i32 {yield_number}>)
|
||||
// CHECK: (inlined <fn() -> i32 {yield_number} as FnOnce<()>>::call_once - shim(fn() -> i32 {yield_number}))
|
||||
// CHECK: (inlined yield_number)
|
||||
inline_fn(yield_number)
|
||||
}
|
34
tests/mir-opt/inline_fn_call_for_fn_def.test.Inline.diff
Normal file
34
tests/mir-opt/inline_fn_call_for_fn_def.test.Inline.diff
Normal file
|
@ -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::<fn() -> i32 {yield_number}>(yield_number) -> [return: bb1, unwind unreachable];
|
||||
+ let mut _1: fn() -> i32 {yield_number};
|
||||
+ scope 1 (inlined inline_fn::<fn() -> i32 {yield_number}>) {
|
||||
+ let mut _2: fn() -> i32 {yield_number};
|
||||
+ let mut _3: ();
|
||||
+ scope 2 (inlined <fn() -> 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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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<u32>;
|
||||
scope 1 (inlined char::methods::<impl char>::is_digit) {
|
||||
let _2: std::option::Option<u32>;
|
||||
scope 2 (inlined Option::<u32>::is_some) {
|
||||
let mut _3: isize;
|
||||
}
|
||||
}
|
||||
scope 3 (inlined #[track_caller] Option::<u32>::unwrap) {
|
||||
let mut _5: isize;
|
||||
let mut _6: !;
|
||||
scope 4 {
|
||||
}
|
||||
}
|
||||
|
||||
bb0: {
|
||||
StorageLive(_2);
|
||||
_2 = char::methods::<impl char>::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::<impl char>::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;
|
||||
}
|
||||
}
|
|
@ -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<u32>;
|
||||
scope 1 (inlined char::methods::<impl char>::is_digit) {
|
||||
let _2: std::option::Option<u32>;
|
||||
scope 2 (inlined Option::<u32>::is_some) {
|
||||
let mut _3: isize;
|
||||
}
|
||||
}
|
||||
scope 3 (inlined #[track_caller] Option::<u32>::unwrap) {
|
||||
let mut _5: isize;
|
||||
let mut _6: !;
|
||||
scope 4 {
|
||||
}
|
||||
}
|
||||
|
||||
bb0: {
|
||||
StorageLive(_2);
|
||||
_2 = char::methods::<impl char>::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::<impl char>::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;
|
||||
}
|
||||
}
|
|
@ -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 }`.
|
||||
|
|
|
@ -29,6 +29,10 @@ fn mapped(_1: impl Iterator<Item = T>, _2: impl Fn(T) -> U) -> () {
|
|||
let mut _12: U;
|
||||
scope 6 {
|
||||
debug x => _10;
|
||||
scope 7 (inlined ops::function::impls::<impl FnOnce<(T,)> for &mut impl Fn(T) -> U>::call_once) {
|
||||
debug self => _8;
|
||||
debug args => _11;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -85,7 +89,7 @@ fn mapped(_1: impl Iterator<Item = T>, _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 = <impl Fn(T) -> U as FnMut<(T,)>>::call_mut(move _8, move _11) -> [return: bb7, unwind: bb10];
|
||||
}
|
||||
|
||||
bb7: {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue