diff options
Diffstat (limited to 'tests/mir-opt/inline')
71 files changed, 2727 insertions, 0 deletions
diff --git a/tests/mir-opt/inline/asm_unwind.main.Inline.diff b/tests/mir-opt/inline/asm_unwind.main.Inline.diff new file mode 100644 index 000000000..f1b62ac38 --- /dev/null +++ b/tests/mir-opt/inline/asm_unwind.main.Inline.diff @@ -0,0 +1,45 @@ +- // MIR for `main` before Inline ++ // MIR for `main` after Inline + + fn main() -> () { + let mut _0: (); // return place in scope 0 at $DIR/asm_unwind.rs:+0:15: +0:15 + let _1: (); // in scope 0 at $DIR/asm_unwind.rs:+1:5: +1:10 ++ scope 1 (inlined foo) { // at $DIR/asm_unwind.rs:21:5: 21:10 ++ let _2: D; // in scope 1 at $DIR/asm_unwind.rs:15:9: 15:11 ++ scope 2 { ++ debug _d => _2; // in scope 2 at $DIR/asm_unwind.rs:15:9: 15:11 ++ scope 3 { ++ } ++ } ++ } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/asm_unwind.rs:+1:5: +1:10 +- _1 = foo() -> bb1; // scope 0 at $DIR/asm_unwind.rs:+1:5: +1:10 +- // mir::Constant +- // + span: $DIR/asm_unwind.rs:21:5: 21:8 +- // + literal: Const { ty: fn() {foo}, val: Value(<ZST>) } ++ StorageLive(_2); // scope 1 at $DIR/asm_unwind.rs:15:9: 15:11 ++ asm!("", options(MAY_UNWIND)) -> [return: bb1, unwind: bb3]; // scope 3 at $DIR/asm_unwind.rs:16:14: 16:54 + } + + bb1: { ++ drop(_2) -> bb2; // scope 1 at $DIR/asm_unwind.rs:17:1: 17:2 ++ } ++ ++ bb2: { ++ StorageDead(_2); // scope 1 at $DIR/asm_unwind.rs:17:1: 17:2 + StorageDead(_1); // scope 0 at $DIR/asm_unwind.rs:+1:10: +1:11 + _0 = const (); // scope 0 at $DIR/asm_unwind.rs:+0:15: +2:2 + return; // scope 0 at $DIR/asm_unwind.rs:+2:2: +2:2 ++ } ++ ++ bb3 (cleanup): { ++ drop(_2) -> bb4; // scope 1 at $DIR/asm_unwind.rs:17:1: 17:2 ++ } ++ ++ bb4 (cleanup): { ++ resume; // scope 1 at $DIR/asm_unwind.rs:14:1: 17:2 + } + } + diff --git a/tests/mir-opt/inline/asm_unwind.rs b/tests/mir-opt/inline/asm_unwind.rs new file mode 100644 index 000000000..c03feb433 --- /dev/null +++ b/tests/mir-opt/inline/asm_unwind.rs @@ -0,0 +1,22 @@ +// Tests inlining of `may_unwind` inline assembly. +// +// ignore-wasm32-bare compiled with panic=abort by default +// needs-asm-support +#![feature(asm_unwind)] + +struct D; + +impl Drop for D { + fn drop(&mut self) {} +} + +#[inline(always)] +fn foo() { + let _d = D; + unsafe { std::arch::asm!("", options(may_unwind)) }; +} + +// EMIT_MIR asm_unwind.main.Inline.diff +pub fn main() { + foo(); +} diff --git a/tests/mir-opt/inline/caller_with_trivial_bound.foo.Inline.diff b/tests/mir-opt/inline/caller_with_trivial_bound.foo.Inline.diff new file mode 100644 index 000000000..8b0300678 --- /dev/null +++ b/tests/mir-opt/inline/caller_with_trivial_bound.foo.Inline.diff @@ -0,0 +1,33 @@ +- // MIR for `foo` before Inline ++ // MIR for `foo` after Inline + + fn foo() -> () { + let mut _0: (); // return place in scope 0 at $DIR/caller_with_trivial_bound.rs:+1:1: +1:1 + let mut _1: <IntFactory as Factory<T>>::Item; // in scope 0 at $DIR/caller_with_trivial_bound.rs:+4:9: +4:14 + scope 1 { + debug x => _1; // in scope 1 at $DIR/caller_with_trivial_bound.rs:+4:9: +4:14 + } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/caller_with_trivial_bound.rs:+4:9: +4:14 + _1 = bar::<T>() -> bb1; // scope 0 at $DIR/caller_with_trivial_bound.rs:+4:51: +4:61 + // mir::Constant + // + span: $DIR/caller_with_trivial_bound.rs:20:51: 20:59 + // + literal: Const { ty: fn() -> <IntFactory as Factory<T>>::Item {bar::<T>}, val: Value(<ZST>) } + } + + bb1: { + _0 = const (); // scope 0 at $DIR/caller_with_trivial_bound.rs:+3:1: +5:2 + drop(_1) -> [return: bb2, unwind: bb3]; // scope 0 at $DIR/caller_with_trivial_bound.rs:+5:1: +5:2 + } + + bb2: { + StorageDead(_1); // scope 0 at $DIR/caller_with_trivial_bound.rs:+5:1: +5:2 + return; // scope 0 at $DIR/caller_with_trivial_bound.rs:+5:2: +5:2 + } + + bb3 (cleanup): { + resume; // scope 0 at $DIR/caller_with_trivial_bound.rs:+0:1: +5:2 + } + } + diff --git a/tests/mir-opt/inline/caller_with_trivial_bound.rs b/tests/mir-opt/inline/caller_with_trivial_bound.rs new file mode 100644 index 000000000..8545db894 --- /dev/null +++ b/tests/mir-opt/inline/caller_with_trivial_bound.rs @@ -0,0 +1,26 @@ +// ignore-wasm32 compiled with panic=abort by default +// needs-unwind + +#![crate_type = "lib"] +pub trait Factory<T> { + type Item; +} + +pub struct IntFactory; + +impl<T> Factory<T> for IntFactory { + type Item = usize; +} + +// EMIT_MIR caller_with_trivial_bound.foo.Inline.diff +pub fn foo<T>() +where + IntFactory: Factory<T>, +{ + let mut x: <IntFactory as Factory<T>>::Item = bar::<T>(); +} + +#[inline(always)] +pub fn bar<T>() -> <IntFactory as Factory<T>>::Item { + 0usize +} diff --git a/tests/mir-opt/inline/cycle.f.Inline.diff b/tests/mir-opt/inline/cycle.f.Inline.diff new file mode 100644 index 000000000..75ea69a42 --- /dev/null +++ b/tests/mir-opt/inline/cycle.f.Inline.diff @@ -0,0 +1,43 @@ +- // MIR for `f` before Inline ++ // MIR for `f` after Inline + + fn f(_1: impl Fn()) -> () { + debug g => _1; // in scope 0 at $DIR/cycle.rs:+0:6: +0:7 + let mut _0: (); // return place in scope 0 at $DIR/cycle.rs:+0:20: +0:20 + let _2: (); // in scope 0 at $DIR/cycle.rs:+1:5: +1:8 + let mut _3: &impl Fn(); // in scope 0 at $DIR/cycle.rs:+1:5: +1:6 + let mut _4: (); // in scope 0 at $DIR/cycle.rs:+1:5: +1:8 + + bb0: { + StorageLive(_2); // scope 0 at $DIR/cycle.rs:+1:5: +1:8 + StorageLive(_3); // scope 0 at $DIR/cycle.rs:+1:5: +1:6 + _3 = &_1; // scope 0 at $DIR/cycle.rs:+1:5: +1:6 + StorageLive(_4); // scope 0 at $DIR/cycle.rs:+1:5: +1:8 + Deinit(_4); // scope 0 at $DIR/cycle.rs:+1:5: +1:8 + _2 = <impl Fn() as Fn<()>>::call(move _3, move _4) -> [return: bb1, unwind: bb3]; // scope 0 at $DIR/cycle.rs:+1:5: +1:8 + // mir::Constant + // + span: $DIR/cycle.rs:6:5: 6:6 + // + literal: Const { ty: for<'a> extern "rust-call" fn(&'a impl Fn(), ()) -> <impl Fn() as FnOnce<()>>::Output {<impl Fn() as Fn<()>>::call}, val: Value(<ZST>) } + } + + bb1: { + StorageDead(_4); // scope 0 at $DIR/cycle.rs:+1:7: +1:8 + StorageDead(_3); // scope 0 at $DIR/cycle.rs:+1:7: +1:8 + StorageDead(_2); // scope 0 at $DIR/cycle.rs:+1:8: +1:9 + _0 = const (); // scope 0 at $DIR/cycle.rs:+0:20: +2:2 + drop(_1) -> [return: bb2, unwind: bb4]; // scope 0 at $DIR/cycle.rs:+2:1: +2:2 + } + + bb2: { + return; // scope 0 at $DIR/cycle.rs:+2:2: +2:2 + } + + bb3 (cleanup): { + drop(_1) -> bb4; // scope 0 at $DIR/cycle.rs:+2:1: +2:2 + } + + bb4 (cleanup): { + resume; // scope 0 at $DIR/cycle.rs:+0:1: +2:2 + } + } + diff --git a/tests/mir-opt/inline/cycle.g.Inline.diff b/tests/mir-opt/inline/cycle.g.Inline.diff new file mode 100644 index 000000000..5f3ee467c --- /dev/null +++ b/tests/mir-opt/inline/cycle.g.Inline.diff @@ -0,0 +1,57 @@ +- // MIR for `g` before Inline ++ // MIR for `g` after Inline + + fn g() -> () { + let mut _0: (); // return place in scope 0 at $DIR/cycle.rs:+0:8: +0:8 + let _1: (); // in scope 0 at $DIR/cycle.rs:+1:5: +1:12 ++ let mut _2: fn() {main}; // in scope 0 at $DIR/cycle.rs:+1:5: +1:12 ++ scope 1 (inlined f::<fn() {main}>) { // at $DIR/cycle.rs:12:5: 12:12 ++ debug g => _2; // in scope 1 at $DIR/cycle.rs:5:6: 5:7 ++ let _3: (); // in scope 1 at $DIR/cycle.rs:6:5: 6:8 ++ let mut _4: &fn() {main}; // in scope 1 at $DIR/cycle.rs:6:5: 6:6 ++ let mut _5: (); // in scope 1 at $DIR/cycle.rs:6:5: 6:8 ++ scope 2 (inlined <fn() {main} as Fn<()>>::call - shim(fn() {main})) { // at $DIR/cycle.rs:6:5: 6:8 ++ } ++ } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/cycle.rs:+1:5: +1:12 +- _1 = f::<fn() {main}>(main) -> bb1; // scope 0 at $DIR/cycle.rs:+1:5: +1:12 ++ StorageLive(_2); // scope 0 at $DIR/cycle.rs:+1:5: +1:12 ++ _2 = main; // scope 0 at $DIR/cycle.rs:+1:5: +1:12 + // mir::Constant +- // + span: $DIR/cycle.rs:12:5: 12:6 +- // + literal: Const { ty: fn(fn() {main}) {f::<fn() {main}>}, val: Value(<ZST>) } +- // mir::Constant + // + span: $DIR/cycle.rs:12:7: 12:11 + // + literal: Const { ty: fn() {main}, val: Value(<ZST>) } ++ StorageLive(_3); // scope 1 at $DIR/cycle.rs:6:5: 6:8 ++ StorageLive(_4); // scope 1 at $DIR/cycle.rs:6:5: 6:6 ++ _4 = &_2; // scope 1 at $DIR/cycle.rs:6:5: 6:6 ++ StorageLive(_5); // scope 1 at $DIR/cycle.rs:6:5: 6:8 ++ _3 = move (*_4)() -> [return: bb4, unwind: bb2]; // scope 2 at $SRC_DIR/core/src/ops/function.rs:LL:COL + } + + bb1: { ++ StorageDead(_2); // scope 0 at $DIR/cycle.rs:+1:5: +1:12 + StorageDead(_1); // scope 0 at $DIR/cycle.rs:+1:12: +1:13 + _0 = const (); // scope 0 at $DIR/cycle.rs:+0:8: +2:2 + return; // scope 0 at $DIR/cycle.rs:+2:2: +2:2 ++ } ++ ++ bb2 (cleanup): { ++ drop(_2) -> bb3; // scope 1 at $DIR/cycle.rs:7:1: 7:2 ++ } ++ ++ bb3 (cleanup): { ++ resume; // scope 1 at $DIR/cycle.rs:5:1: 7:2 ++ } ++ ++ bb4: { ++ StorageDead(_5); // scope 1 at $DIR/cycle.rs:6:7: 6:8 ++ StorageDead(_4); // scope 1 at $DIR/cycle.rs:6:7: 6:8 ++ StorageDead(_3); // scope 1 at $DIR/cycle.rs:6:8: 6:9 ++ drop(_2) -> bb1; // scope 1 at $DIR/cycle.rs:7:1: 7:2 + } + } + diff --git a/tests/mir-opt/inline/cycle.main.Inline.diff b/tests/mir-opt/inline/cycle.main.Inline.diff new file mode 100644 index 000000000..6b4c63bbd --- /dev/null +++ b/tests/mir-opt/inline/cycle.main.Inline.diff @@ -0,0 +1,57 @@ +- // MIR for `main` before Inline ++ // MIR for `main` after Inline + + fn main() -> () { + let mut _0: (); // return place in scope 0 at $DIR/cycle.rs:+0:11: +0:11 + let _1: (); // in scope 0 at $DIR/cycle.rs:+1:5: +1:9 ++ let mut _2: fn() {g}; // in scope 0 at $DIR/cycle.rs:+1:5: +1:9 ++ scope 1 (inlined f::<fn() {g}>) { // at $DIR/cycle.rs:17:5: 17:9 ++ debug g => _2; // in scope 1 at $DIR/cycle.rs:5:6: 5:7 ++ let _3: (); // in scope 1 at $DIR/cycle.rs:6:5: 6:8 ++ let mut _4: &fn() {g}; // in scope 1 at $DIR/cycle.rs:6:5: 6:6 ++ let mut _5: (); // in scope 1 at $DIR/cycle.rs:6:5: 6:8 ++ scope 2 (inlined <fn() {g} as Fn<()>>::call - shim(fn() {g})) { // at $DIR/cycle.rs:6:5: 6:8 ++ } ++ } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/cycle.rs:+1:5: +1:9 +- _1 = f::<fn() {g}>(g) -> bb1; // scope 0 at $DIR/cycle.rs:+1:5: +1:9 ++ StorageLive(_2); // scope 0 at $DIR/cycle.rs:+1:5: +1:9 ++ _2 = g; // scope 0 at $DIR/cycle.rs:+1:5: +1:9 + // mir::Constant +- // + span: $DIR/cycle.rs:17:5: 17:6 +- // + literal: Const { ty: fn(fn() {g}) {f::<fn() {g}>}, val: Value(<ZST>) } +- // mir::Constant + // + span: $DIR/cycle.rs:17:7: 17:8 + // + literal: Const { ty: fn() {g}, val: Value(<ZST>) } ++ StorageLive(_3); // scope 1 at $DIR/cycle.rs:6:5: 6:8 ++ StorageLive(_4); // scope 1 at $DIR/cycle.rs:6:5: 6:6 ++ _4 = &_2; // scope 1 at $DIR/cycle.rs:6:5: 6:6 ++ StorageLive(_5); // scope 1 at $DIR/cycle.rs:6:5: 6:8 ++ _3 = move (*_4)() -> [return: bb4, unwind: bb2]; // scope 2 at $SRC_DIR/core/src/ops/function.rs:LL:COL + } + + bb1: { ++ StorageDead(_2); // scope 0 at $DIR/cycle.rs:+1:5: +1:9 + StorageDead(_1); // scope 0 at $DIR/cycle.rs:+1:9: +1:10 + _0 = const (); // scope 0 at $DIR/cycle.rs:+0:11: +2:2 + return; // scope 0 at $DIR/cycle.rs:+2:2: +2:2 ++ } ++ ++ bb2 (cleanup): { ++ drop(_2) -> bb3; // scope 1 at $DIR/cycle.rs:7:1: 7:2 ++ } ++ ++ bb3 (cleanup): { ++ resume; // scope 1 at $DIR/cycle.rs:5:1: 7:2 ++ } ++ ++ bb4: { ++ StorageDead(_5); // scope 1 at $DIR/cycle.rs:6:7: 6:8 ++ StorageDead(_4); // scope 1 at $DIR/cycle.rs:6:7: 6:8 ++ StorageDead(_3); // scope 1 at $DIR/cycle.rs:6:8: 6:9 ++ drop(_2) -> bb1; // scope 1 at $DIR/cycle.rs:7:1: 7:2 + } + } + diff --git a/tests/mir-opt/inline/cycle.rs b/tests/mir-opt/inline/cycle.rs new file mode 100644 index 000000000..9e8950d8a --- /dev/null +++ b/tests/mir-opt/inline/cycle.rs @@ -0,0 +1,18 @@ +// ignore-wasm32-bare compiled with panic=abort by default + +// EMIT_MIR cycle.f.Inline.diff +#[inline(always)] +fn f(g: impl Fn()) { + g(); +} + +// EMIT_MIR cycle.g.Inline.diff +#[inline(always)] +fn g() { + f(main); +} + +// EMIT_MIR cycle.main.Inline.diff +fn main() { + f(g); +} diff --git a/tests/mir-opt/inline/dyn_trait.get_query.Inline.diff b/tests/mir-opt/inline/dyn_trait.get_query.Inline.diff new file mode 100644 index 000000000..8ea1a0757 --- /dev/null +++ b/tests/mir-opt/inline/dyn_trait.get_query.Inline.diff @@ -0,0 +1,54 @@ +- // MIR for `get_query` before Inline ++ // MIR for `get_query` after Inline + + fn get_query(_1: &T) -> () { + debug t => _1; // in scope 0 at $DIR/dyn_trait.rs:+0:31: +0:32 + let mut _0: (); // return place in scope 0 at $DIR/dyn_trait.rs:+0:38: +0:38 + let _2: &<Q as Query>::C; // in scope 0 at $DIR/dyn_trait.rs:+1:9: +1:10 + let mut _3: &T; // in scope 0 at $DIR/dyn_trait.rs:+1:22: +1:23 + let mut _4: &<Q as Query>::C; // in scope 0 at $DIR/dyn_trait.rs:+2:23: +2:24 + scope 1 { + debug c => _2; // in scope 1 at $DIR/dyn_trait.rs:+1:9: +1:10 ++ scope 2 (inlined try_execute_query::<<Q as Query>::C>) { // at $DIR/dyn_trait.rs:34:5: 34:25 ++ debug c => _4; // in scope 2 at $DIR/dyn_trait.rs:26:36: 26:37 ++ let mut _5: &dyn Cache<V = <Q as Query>::V>; // in scope 2 at $DIR/dyn_trait.rs:27:14: 27:15 ++ scope 3 (inlined mk_cycle::<<Q as Query>::V>) { // at $DIR/dyn_trait.rs:27:5: 27:16 ++ debug c => _5; // in scope 3 at $DIR/dyn_trait.rs:20:27: 20:28 ++ } ++ } + } + + bb0: { + StorageLive(_2); // scope 0 at $DIR/dyn_trait.rs:+1:9: +1:10 + StorageLive(_3); // scope 0 at $DIR/dyn_trait.rs:+1:22: +1:23 + _3 = &(*_1); // scope 0 at $DIR/dyn_trait.rs:+1:22: +1:23 + _2 = <Q as Query>::cache::<T>(move _3) -> bb1; // scope 0 at $DIR/dyn_trait.rs:+1:13: +1:24 + // mir::Constant + // + span: $DIR/dyn_trait.rs:33:13: 33:21 + // + user_ty: UserType(0) + // + literal: Const { ty: for<'a> fn(&'a T) -> &'a <Q as Query>::C {<Q as Query>::cache::<T>}, val: Value(<ZST>) } + } + + bb1: { + StorageDead(_3); // scope 0 at $DIR/dyn_trait.rs:+1:23: +1:24 + StorageLive(_4); // scope 1 at $DIR/dyn_trait.rs:+2:23: +2:24 + _4 = &(*_2); // scope 1 at $DIR/dyn_trait.rs:+2:23: +2:24 +- _0 = try_execute_query::<<Q as Query>::C>(move _4) -> bb2; // scope 1 at $DIR/dyn_trait.rs:+2:5: +2:25 ++ StorageLive(_5); // scope 2 at $DIR/dyn_trait.rs:27:14: 27:15 ++ _5 = move _4 as &dyn Cache<V = <Q as Query>::V> (Pointer(Unsize)); // scope 2 at $DIR/dyn_trait.rs:27:14: 27:15 ++ _0 = <dyn Cache<V = <Q as Query>::V> as Cache>::store_nocache(move _5) -> bb2; // scope 3 at $DIR/dyn_trait.rs:21:5: 21:22 + // mir::Constant +- // + span: $DIR/dyn_trait.rs:34:5: 34:22 +- // + literal: Const { ty: for<'a> fn(&'a <Q as Query>::C) {try_execute_query::<<Q as Query>::C>}, val: Value(<ZST>) } ++ // + span: $DIR/dyn_trait.rs:21:7: 21:20 ++ // + literal: Const { ty: for<'a> fn(&'a dyn Cache<V = <Q as Query>::V>) {<dyn Cache<V = <Q as Query>::V> as Cache>::store_nocache}, val: Value(<ZST>) } + } + + bb2: { ++ StorageDead(_5); // scope 2 at $DIR/dyn_trait.rs:27:15: 27:16 + StorageDead(_4); // scope 1 at $DIR/dyn_trait.rs:+2:24: +2:25 + StorageDead(_2); // scope 0 at $DIR/dyn_trait.rs:+3:1: +3:2 + return; // scope 0 at $DIR/dyn_trait.rs:+3:2: +3:2 + } + } + diff --git a/tests/mir-opt/inline/dyn_trait.mk_cycle.Inline.diff b/tests/mir-opt/inline/dyn_trait.mk_cycle.Inline.diff new file mode 100644 index 000000000..7653a5ded --- /dev/null +++ b/tests/mir-opt/inline/dyn_trait.mk_cycle.Inline.diff @@ -0,0 +1,23 @@ +- // MIR for `mk_cycle` before Inline ++ // MIR for `mk_cycle` after Inline + + fn mk_cycle(_1: &dyn Cache<V = V>) -> () { + debug c => _1; // in scope 0 at $DIR/dyn_trait.rs:+0:27: +0:28 + let mut _0: (); // return place in scope 0 at $DIR/dyn_trait.rs:+0:49: +0:49 + let mut _2: &dyn Cache<V = V>; // in scope 0 at $DIR/dyn_trait.rs:+1:5: +1:22 + + bb0: { + StorageLive(_2); // scope 0 at $DIR/dyn_trait.rs:+1:5: +1:22 + _2 = &(*_1); // scope 0 at $DIR/dyn_trait.rs:+1:5: +1:22 + _0 = <dyn Cache<V = V> as Cache>::store_nocache(move _2) -> bb1; // scope 0 at $DIR/dyn_trait.rs:+1:5: +1:22 + // mir::Constant + // + span: $DIR/dyn_trait.rs:21:7: 21:20 + // + literal: Const { ty: for<'a> fn(&'a dyn Cache<V = V>) {<dyn Cache<V = V> as Cache>::store_nocache}, val: Value(<ZST>) } + } + + bb1: { + StorageDead(_2); // scope 0 at $DIR/dyn_trait.rs:+1:21: +1:22 + return; // scope 0 at $DIR/dyn_trait.rs:+2:2: +2:2 + } + } + diff --git a/tests/mir-opt/inline/dyn_trait.rs b/tests/mir-opt/inline/dyn_trait.rs new file mode 100644 index 000000000..6a46e1e07 --- /dev/null +++ b/tests/mir-opt/inline/dyn_trait.rs @@ -0,0 +1,35 @@ +#![crate_type = "lib"] + +use std::fmt::Debug; + +pub trait Cache { + type V: Debug; + + fn store_nocache(&self); +} + +pub trait Query { + type V; + type C: Cache<V = Self::V>; + + fn cache<T>(s: &T) -> &Self::C; +} + +// EMIT_MIR dyn_trait.mk_cycle.Inline.diff +#[inline(always)] +pub fn mk_cycle<V: Debug>(c: &dyn Cache<V = V>) { + c.store_nocache() +} + +// EMIT_MIR dyn_trait.try_execute_query.Inline.diff +#[inline(always)] +pub fn try_execute_query<C: Cache>(c: &C) { + mk_cycle(c) +} + +// EMIT_MIR dyn_trait.get_query.Inline.diff +#[inline(always)] +pub fn get_query<Q: Query, T>(t: &T) { + let c = Q::cache(t); + try_execute_query(c) +} diff --git a/tests/mir-opt/inline/dyn_trait.try_execute_query.Inline.diff b/tests/mir-opt/inline/dyn_trait.try_execute_query.Inline.diff new file mode 100644 index 000000000..a71d73b74 --- /dev/null +++ b/tests/mir-opt/inline/dyn_trait.try_execute_query.Inline.diff @@ -0,0 +1,33 @@ +- // MIR for `try_execute_query` before Inline ++ // MIR for `try_execute_query` after Inline + + fn try_execute_query(_1: &C) -> () { + debug c => _1; // in scope 0 at $DIR/dyn_trait.rs:+0:36: +0:37 + let mut _0: (); // return place in scope 0 at $DIR/dyn_trait.rs:+0:43: +0:43 + let mut _2: &dyn Cache<V = <C as Cache>::V>; // in scope 0 at $DIR/dyn_trait.rs:+1:14: +1:15 + let mut _3: &C; // in scope 0 at $DIR/dyn_trait.rs:+1:14: +1:15 ++ scope 1 (inlined mk_cycle::<<C as Cache>::V>) { // at $DIR/dyn_trait.rs:27:5: 27:16 ++ debug c => _2; // in scope 1 at $DIR/dyn_trait.rs:20:27: 20:28 ++ } + + bb0: { + StorageLive(_2); // scope 0 at $DIR/dyn_trait.rs:+1:14: +1:15 + StorageLive(_3); // scope 0 at $DIR/dyn_trait.rs:+1:14: +1:15 + _3 = &(*_1); // scope 0 at $DIR/dyn_trait.rs:+1:14: +1:15 + _2 = move _3 as &dyn Cache<V = <C as Cache>::V> (Pointer(Unsize)); // scope 0 at $DIR/dyn_trait.rs:+1:14: +1:15 + StorageDead(_3); // scope 0 at $DIR/dyn_trait.rs:+1:14: +1:15 +- _0 = mk_cycle::<<C as Cache>::V>(move _2) -> bb1; // scope 0 at $DIR/dyn_trait.rs:+1:5: +1:16 ++ _0 = <dyn Cache<V = <C as Cache>::V> as Cache>::store_nocache(move _2) -> bb1; // scope 1 at $DIR/dyn_trait.rs:21:5: 21:22 + // mir::Constant +- // + span: $DIR/dyn_trait.rs:27:5: 27:13 +- // + literal: Const { ty: for<'a> fn(&'a (dyn Cache<V = <C as Cache>::V> + 'a)) {mk_cycle::<<C as Cache>::V>}, val: Value(<ZST>) } ++ // + span: $DIR/dyn_trait.rs:21:7: 21:20 ++ // + literal: Const { ty: for<'a> fn(&'a dyn Cache<V = <C as Cache>::V>) {<dyn Cache<V = <C as Cache>::V> as Cache>::store_nocache}, val: Value(<ZST>) } + } + + bb1: { + StorageDead(_2); // scope 0 at $DIR/dyn_trait.rs:+1:15: +1:16 + return; // scope 0 at $DIR/dyn_trait.rs:+2:2: +2:2 + } + } + diff --git a/tests/mir-opt/inline/exponential_runtime.main.Inline.diff b/tests/mir-opt/inline/exponential_runtime.main.Inline.diff new file mode 100644 index 000000000..7fd62be7a --- /dev/null +++ b/tests/mir-opt/inline/exponential_runtime.main.Inline.diff @@ -0,0 +1,75 @@ +- // MIR for `main` before Inline ++ // MIR for `main` after Inline + + fn main() -> () { + let mut _0: (); // return place in scope 0 at $DIR/exponential_runtime.rs:+0:11: +0:11 + let _1: (); // in scope 0 at $DIR/exponential_runtime.rs:+1:5: +1:22 ++ scope 1 (inlined <() as G>::call) { // at $DIR/exponential_runtime.rs:86:5: 86:22 ++ let _2: (); // in scope 1 at $DIR/exponential_runtime.rs:73:9: 73:25 ++ let _3: (); // in scope 1 at $DIR/exponential_runtime.rs:74:9: 74:25 ++ let _4: (); // in scope 1 at $DIR/exponential_runtime.rs:75:9: 75:25 ++ scope 2 (inlined <() as F>::call) { // at $DIR/exponential_runtime.rs:73:9: 73:25 ++ let _5: (); // in scope 2 at $DIR/exponential_runtime.rs:61:9: 61:25 ++ let _6: (); // in scope 2 at $DIR/exponential_runtime.rs:62:9: 62:25 ++ let _7: (); // in scope 2 at $DIR/exponential_runtime.rs:63:9: 63:25 ++ } ++ } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/exponential_runtime.rs:+1:5: +1:22 +- _1 = <() as G>::call() -> bb1; // scope 0 at $DIR/exponential_runtime.rs:+1:5: +1:22 ++ StorageLive(_2); // scope 1 at $DIR/exponential_runtime.rs:73:9: 73:25 ++ StorageLive(_5); // scope 2 at $DIR/exponential_runtime.rs:61:9: 61:25 ++ _5 = <() as E>::call() -> bb3; // scope 2 at $DIR/exponential_runtime.rs:61:9: 61:25 + // mir::Constant +- // + span: $DIR/exponential_runtime.rs:86:5: 86:20 +- // + literal: Const { ty: fn() {<() as G>::call}, val: Value(<ZST>) } ++ // + span: $DIR/exponential_runtime.rs:61:9: 61:23 ++ // + literal: Const { ty: fn() {<() as E>::call}, val: Value(<ZST>) } + } + + bb1: { ++ StorageDead(_3); // scope 1 at $DIR/exponential_runtime.rs:74:25: 74:26 ++ StorageLive(_4); // scope 1 at $DIR/exponential_runtime.rs:75:9: 75:25 ++ _4 = <() as F>::call() -> bb2; // scope 1 at $DIR/exponential_runtime.rs:75:9: 75:25 ++ // mir::Constant ++ // + span: $DIR/exponential_runtime.rs:75:9: 75:23 ++ // + literal: Const { ty: fn() {<() as F>::call}, val: Value(<ZST>) } ++ } ++ ++ bb2: { ++ StorageDead(_4); // scope 1 at $DIR/exponential_runtime.rs:75:25: 75:26 + StorageDead(_1); // scope 0 at $DIR/exponential_runtime.rs:+1:22: +1:23 + _0 = const (); // scope 0 at $DIR/exponential_runtime.rs:+0:11: +2:2 + return; // scope 0 at $DIR/exponential_runtime.rs:+2:2: +2:2 ++ } ++ ++ bb3: { ++ StorageDead(_5); // scope 2 at $DIR/exponential_runtime.rs:61:25: 61:26 ++ StorageLive(_6); // scope 2 at $DIR/exponential_runtime.rs:62:9: 62:25 ++ _6 = <() as E>::call() -> bb4; // scope 2 at $DIR/exponential_runtime.rs:62:9: 62:25 ++ // mir::Constant ++ // + span: $DIR/exponential_runtime.rs:62:9: 62:23 ++ // + literal: Const { ty: fn() {<() as E>::call}, val: Value(<ZST>) } ++ } ++ ++ bb4: { ++ StorageDead(_6); // scope 2 at $DIR/exponential_runtime.rs:62:25: 62:26 ++ StorageLive(_7); // scope 2 at $DIR/exponential_runtime.rs:63:9: 63:25 ++ _7 = <() as E>::call() -> bb5; // scope 2 at $DIR/exponential_runtime.rs:63:9: 63:25 ++ // mir::Constant ++ // + span: $DIR/exponential_runtime.rs:63:9: 63:23 ++ // + literal: Const { ty: fn() {<() as E>::call}, val: Value(<ZST>) } ++ } ++ ++ bb5: { ++ StorageDead(_7); // scope 2 at $DIR/exponential_runtime.rs:63:25: 63:26 ++ StorageDead(_2); // scope 1 at $DIR/exponential_runtime.rs:73:25: 73:26 ++ StorageLive(_3); // scope 1 at $DIR/exponential_runtime.rs:74:9: 74:25 ++ _3 = <() as F>::call() -> bb1; // scope 1 at $DIR/exponential_runtime.rs:74:9: 74:25 ++ // mir::Constant ++ // + span: $DIR/exponential_runtime.rs:74:9: 74:23 ++ // + literal: Const { ty: fn() {<() as F>::call}, val: Value(<ZST>) } + } + } + diff --git a/tests/mir-opt/inline/exponential_runtime.rs b/tests/mir-opt/inline/exponential_runtime.rs new file mode 100644 index 000000000..d9219d76a --- /dev/null +++ b/tests/mir-opt/inline/exponential_runtime.rs @@ -0,0 +1,87 @@ +// Checks that code with exponential runtime does not have exponential behavior in inlining. + +trait A { + fn call(); +} + +trait B { + fn call(); +} +impl<T: A> B for T { + #[inline] + fn call() { + <T as A>::call(); + <T as A>::call(); + <T as A>::call(); + } +} + +trait C { + fn call(); +} +impl<T: B> C for T { + #[inline] + fn call() { + <T as B>::call(); + <T as B>::call(); + <T as B>::call(); + } +} + +trait D { + fn call(); +} +impl<T: C> D for T { + #[inline] + fn call() { + <T as C>::call(); + <T as C>::call(); + <T as C>::call(); + } +} + +trait E { + fn call(); +} +impl<T: D> E for T { + #[inline] + fn call() { + <T as D>::call(); + <T as D>::call(); + <T as D>::call(); + } +} + +trait F { + fn call(); +} +impl<T: E> F for T { + #[inline] + fn call() { + <T as E>::call(); + <T as E>::call(); + <T as E>::call(); + } +} + +trait G { + fn call(); +} +impl<T: F> G for T { + #[inline] + fn call() { + <T as F>::call(); + <T as F>::call(); + <T as F>::call(); + } +} + +impl A for () { + #[inline(never)] + fn call() {} +} + +// EMIT_MIR exponential_runtime.main.Inline.diff +fn main() { + <() as G>::call(); +} diff --git a/tests/mir-opt/inline/inline_any_operand.bar.Inline.after.mir b/tests/mir-opt/inline/inline_any_operand.bar.Inline.after.mir new file mode 100644 index 000000000..3502c2586 --- /dev/null +++ b/tests/mir-opt/inline/inline_any_operand.bar.Inline.after.mir @@ -0,0 +1,36 @@ +// MIR for `bar` after Inline + +fn bar() -> bool { + let mut _0: bool; // return place in scope 0 at $DIR/inline_any_operand.rs:+0:13: +0:17 + let _1: fn(i32, i32) -> bool {foo}; // in scope 0 at $DIR/inline_any_operand.rs:+1:9: +1:10 + let mut _2: fn(i32, i32) -> bool {foo}; // in scope 0 at $DIR/inline_any_operand.rs:+2:5: +2:6 + let mut _3: i32; // in scope 0 at $DIR/inline_any_operand.rs:+2:5: +2:13 + let mut _4: i32; // in scope 0 at $DIR/inline_any_operand.rs:+2:5: +2:13 + scope 1 { + debug f => _1; // in scope 1 at $DIR/inline_any_operand.rs:+1:9: +1:10 + scope 2 (inlined foo) { // at $DIR/inline_any_operand.rs:12:5: 12:13 + debug x => _3; // in scope 2 at $DIR/inline_any_operand.rs:16:8: 16:9 + debug y => _4; // in scope 2 at $DIR/inline_any_operand.rs:16:16: 16:17 + } + } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/inline_any_operand.rs:+1:9: +1:10 + _1 = foo; // scope 0 at $DIR/inline_any_operand.rs:+1:13: +1:16 + // mir::Constant + // + span: $DIR/inline_any_operand.rs:11:13: 11:16 + // + literal: Const { ty: fn(i32, i32) -> bool {foo}, val: Value(<ZST>) } + StorageLive(_2); // scope 1 at $DIR/inline_any_operand.rs:+2:5: +2:6 + _2 = _1; // scope 1 at $DIR/inline_any_operand.rs:+2:5: +2:6 + StorageLive(_3); // scope 1 at $DIR/inline_any_operand.rs:+2:5: +2:13 + _3 = const 1_i32; // scope 1 at $DIR/inline_any_operand.rs:+2:5: +2:13 + StorageLive(_4); // scope 1 at $DIR/inline_any_operand.rs:+2:5: +2:13 + _4 = const -1_i32; // scope 1 at $DIR/inline_any_operand.rs:+2:5: +2:13 + _0 = Eq(move _3, move _4); // scope 2 at $DIR/inline_any_operand.rs:17:5: 17:11 + StorageDead(_4); // scope 1 at $DIR/inline_any_operand.rs:+2:5: +2:13 + StorageDead(_3); // scope 1 at $DIR/inline_any_operand.rs:+2:5: +2:13 + StorageDead(_2); // scope 1 at $DIR/inline_any_operand.rs:+2:12: +2:13 + StorageDead(_1); // scope 0 at $DIR/inline_any_operand.rs:+3:1: +3:2 + return; // scope 0 at $DIR/inline_any_operand.rs:+3:2: +3:2 + } +} diff --git a/tests/mir-opt/inline/inline_any_operand.rs b/tests/mir-opt/inline/inline_any_operand.rs new file mode 100644 index 000000000..fb0de020f --- /dev/null +++ b/tests/mir-opt/inline/inline_any_operand.rs @@ -0,0 +1,18 @@ +// compile-flags: -Z span_free_formats + +// Tests that MIR inliner works for any operand + +fn main() { + println!("{}", bar()); +} + +// EMIT_MIR inline_any_operand.bar.Inline.after.mir +fn bar() -> bool { + let f = foo; + f(1, -1) +} + +#[inline(always)] +fn foo(x: i32, y: i32) -> bool { + x == y +} diff --git a/tests/mir-opt/inline/inline_async.rs b/tests/mir-opt/inline/inline_async.rs new file mode 100644 index 000000000..5c838159b --- /dev/null +++ b/tests/mir-opt/inline/inline_async.rs @@ -0,0 +1,18 @@ +// Checks that inliner doesn't introduce cycles when optimizing generators. +// The outcome of optimization is not verfied, just the absence of the cycle. +// Regression test for #76181. +// +// edition:2018 + +#![crate_type = "lib"] + +pub struct S; + +impl S { + pub async fn g(&mut self) { + self.h(); + } + pub fn h(&mut self) { + let _ = self.g(); + } +} diff --git a/tests/mir-opt/inline/inline_closure.foo.Inline.after.mir b/tests/mir-opt/inline/inline_closure.foo.Inline.after.mir new file mode 100644 index 000000000..9eb3a01ee --- /dev/null +++ b/tests/mir-opt/inline/inline_closure.foo.Inline.after.mir @@ -0,0 +1,49 @@ +// MIR for `foo` after Inline + +fn foo(_1: T, _2: i32) -> i32 { + debug _t => _1; // in scope 0 at $DIR/inline_closure.rs:+0:17: +0:19 + debug q => _2; // in scope 0 at $DIR/inline_closure.rs:+0:24: +0:25 + let mut _0: i32; // return place in scope 0 at $DIR/inline_closure.rs:+0:35: +0:38 + let _3: [closure@foo<T>::{closure#0}]; // in scope 0 at $DIR/inline_closure.rs:+1:9: +1:10 + let mut _4: &[closure@foo<T>::{closure#0}]; // in scope 0 at $DIR/inline_closure.rs:+2:5: +2:6 + let mut _5: (i32, i32); // in scope 0 at $DIR/inline_closure.rs:+2:5: +2:12 + let mut _6: i32; // in scope 0 at $DIR/inline_closure.rs:+2:7: +2:8 + let mut _7: i32; // in scope 0 at $DIR/inline_closure.rs:+2:10: +2:11 + let mut _8: i32; // in scope 0 at $DIR/inline_closure.rs:+2:5: +2:12 + let mut _9: i32; // in scope 0 at $DIR/inline_closure.rs:+2:5: +2:12 + scope 1 { + debug x => _3; // in scope 1 at $DIR/inline_closure.rs:+1:9: +1:10 + scope 2 (inlined foo::<T>::{closure#0}) { // at $DIR/inline_closure.rs:12:5: 12:12 + debug _t => _8; // in scope 2 at $DIR/inline_closure.rs:+1:14: +1:16 + debug _q => _9; // in scope 2 at $DIR/inline_closure.rs:+1:18: +1:20 + } + } + + bb0: { + StorageLive(_3); // scope 0 at $DIR/inline_closure.rs:+1:9: +1:10 + Deinit(_3); // scope 0 at $DIR/inline_closure.rs:+1:13: +1:24 + StorageLive(_4); // scope 1 at $DIR/inline_closure.rs:+2:5: +2:6 + _4 = &_3; // scope 1 at $DIR/inline_closure.rs:+2:5: +2:6 + StorageLive(_5); // scope 1 at $DIR/inline_closure.rs:+2:5: +2:12 + StorageLive(_6); // scope 1 at $DIR/inline_closure.rs:+2:7: +2:8 + _6 = _2; // scope 1 at $DIR/inline_closure.rs:+2:7: +2:8 + StorageLive(_7); // scope 1 at $DIR/inline_closure.rs:+2:10: +2:11 + _7 = _2; // scope 1 at $DIR/inline_closure.rs:+2:10: +2:11 + Deinit(_5); // scope 1 at $DIR/inline_closure.rs:+2:5: +2:12 + (_5.0: i32) = move _6; // scope 1 at $DIR/inline_closure.rs:+2:5: +2:12 + (_5.1: i32) = move _7; // scope 1 at $DIR/inline_closure.rs:+2:5: +2:12 + StorageLive(_8); // scope 1 at $DIR/inline_closure.rs:+2:5: +2:12 + _8 = move (_5.0: i32); // scope 1 at $DIR/inline_closure.rs:+2:5: +2:12 + StorageLive(_9); // scope 1 at $DIR/inline_closure.rs:+2:5: +2:12 + _9 = move (_5.1: i32); // scope 1 at $DIR/inline_closure.rs:+2:5: +2:12 + _0 = _8; // scope 2 at $DIR/inline_closure.rs:+1:22: +1:24 + StorageDead(_9); // scope 1 at $DIR/inline_closure.rs:+2:5: +2:12 + StorageDead(_8); // scope 1 at $DIR/inline_closure.rs:+2:5: +2:12 + StorageDead(_7); // scope 1 at $DIR/inline_closure.rs:+2:11: +2:12 + StorageDead(_6); // scope 1 at $DIR/inline_closure.rs:+2:11: +2:12 + StorageDead(_5); // scope 1 at $DIR/inline_closure.rs:+2:11: +2:12 + StorageDead(_4); // scope 1 at $DIR/inline_closure.rs:+2:11: +2:12 + StorageDead(_3); // scope 0 at $DIR/inline_closure.rs:+3:1: +3:2 + return; // scope 0 at $DIR/inline_closure.rs:+3:2: +3:2 + } +} diff --git a/tests/mir-opt/inline/inline_closure.rs b/tests/mir-opt/inline/inline_closure.rs new file mode 100644 index 000000000..715fd0138 --- /dev/null +++ b/tests/mir-opt/inline/inline_closure.rs @@ -0,0 +1,13 @@ +// compile-flags: -Z span_free_formats + +// Tests that MIR inliner can handle closure arguments. (#45894) + +fn main() { + println!("{}", foo(0, 14)); +} + +// EMIT_MIR inline_closure.foo.Inline.after.mir +fn foo<T: Copy>(_t: T, q: i32) -> i32 { + let x = |_t, _q| _t; + x(q, q) +} diff --git a/tests/mir-opt/inline/inline_closure_borrows_arg.foo.Inline.after.mir b/tests/mir-opt/inline/inline_closure_borrows_arg.foo.Inline.after.mir new file mode 100644 index 000000000..dd32eb2d8 --- /dev/null +++ b/tests/mir-opt/inline/inline_closure_borrows_arg.foo.Inline.after.mir @@ -0,0 +1,52 @@ +// MIR for `foo` after Inline + +fn foo(_1: T, _2: &i32) -> i32 { + debug _t => _1; // in scope 0 at $DIR/inline_closure_borrows_arg.rs:+0:17: +0:19 + debug q => _2; // in scope 0 at $DIR/inline_closure_borrows_arg.rs:+0:24: +0:25 + let mut _0: i32; // return place in scope 0 at $DIR/inline_closure_borrows_arg.rs:+0:36: +0:39 + let _3: [closure@foo<T>::{closure#0}]; // in scope 0 at $DIR/inline_closure_borrows_arg.rs:+1:9: +1:10 + let mut _4: &[closure@foo<T>::{closure#0}]; // in scope 0 at $DIR/inline_closure_borrows_arg.rs:+5:5: +5:6 + let mut _5: (&i32, &i32); // in scope 0 at $DIR/inline_closure_borrows_arg.rs:+5:5: +5:12 + let mut _6: &i32; // in scope 0 at $DIR/inline_closure_borrows_arg.rs:+5:7: +5:8 + let mut _7: &i32; // in scope 0 at $DIR/inline_closure_borrows_arg.rs:+5:10: +5:11 + let mut _8: &i32; // in scope 0 at $DIR/inline_closure_borrows_arg.rs:+5:5: +5:12 + let mut _9: &i32; // in scope 0 at $DIR/inline_closure_borrows_arg.rs:+5:5: +5:12 + scope 1 { + debug x => _3; // in scope 1 at $DIR/inline_closure_borrows_arg.rs:+1:9: +1:10 + scope 2 (inlined foo::<T>::{closure#0}) { // at $DIR/inline_closure_borrows_arg.rs:16:5: 16:12 + debug r => _8; // in scope 2 at $DIR/inline_closure_borrows_arg.rs:+1:14: +1:15 + debug _s => _9; // in scope 2 at $DIR/inline_closure_borrows_arg.rs:+1:23: +1:25 + scope 3 { + debug variable => _8; // in scope 3 at $DIR/inline_closure_borrows_arg.rs:+2:13: +2:21 + } + } + } + + bb0: { + StorageLive(_3); // scope 0 at $DIR/inline_closure_borrows_arg.rs:+1:9: +1:10 + Deinit(_3); // scope 0 at $DIR/inline_closure_borrows_arg.rs:+1:13: +4:6 + StorageLive(_4); // scope 1 at $DIR/inline_closure_borrows_arg.rs:+5:5: +5:6 + _4 = &_3; // scope 1 at $DIR/inline_closure_borrows_arg.rs:+5:5: +5:6 + StorageLive(_5); // scope 1 at $DIR/inline_closure_borrows_arg.rs:+5:5: +5:12 + StorageLive(_6); // scope 1 at $DIR/inline_closure_borrows_arg.rs:+5:7: +5:8 + _6 = &(*_2); // scope 1 at $DIR/inline_closure_borrows_arg.rs:+5:7: +5:8 + StorageLive(_7); // scope 1 at $DIR/inline_closure_borrows_arg.rs:+5:10: +5:11 + _7 = &(*_2); // scope 1 at $DIR/inline_closure_borrows_arg.rs:+5:10: +5:11 + Deinit(_5); // scope 1 at $DIR/inline_closure_borrows_arg.rs:+5:5: +5:12 + (_5.0: &i32) = move _6; // scope 1 at $DIR/inline_closure_borrows_arg.rs:+5:5: +5:12 + (_5.1: &i32) = move _7; // scope 1 at $DIR/inline_closure_borrows_arg.rs:+5:5: +5:12 + StorageLive(_8); // scope 1 at $DIR/inline_closure_borrows_arg.rs:+5:5: +5:12 + _8 = move (_5.0: &i32); // scope 1 at $DIR/inline_closure_borrows_arg.rs:+5:5: +5:12 + StorageLive(_9); // scope 1 at $DIR/inline_closure_borrows_arg.rs:+5:5: +5:12 + _9 = move (_5.1: &i32); // scope 1 at $DIR/inline_closure_borrows_arg.rs:+5:5: +5:12 + _0 = (*_8); // scope 3 at $DIR/inline_closure_borrows_arg.rs:+3:9: +3:18 + StorageDead(_9); // scope 1 at $DIR/inline_closure_borrows_arg.rs:+5:5: +5:12 + StorageDead(_8); // scope 1 at $DIR/inline_closure_borrows_arg.rs:+5:5: +5:12 + StorageDead(_7); // scope 1 at $DIR/inline_closure_borrows_arg.rs:+5:11: +5:12 + StorageDead(_6); // scope 1 at $DIR/inline_closure_borrows_arg.rs:+5:11: +5:12 + StorageDead(_5); // scope 1 at $DIR/inline_closure_borrows_arg.rs:+5:11: +5:12 + StorageDead(_4); // scope 1 at $DIR/inline_closure_borrows_arg.rs:+5:11: +5:12 + StorageDead(_3); // scope 0 at $DIR/inline_closure_borrows_arg.rs:+6:1: +6:2 + return; // scope 0 at $DIR/inline_closure_borrows_arg.rs:+6:2: +6:2 + } +} diff --git a/tests/mir-opt/inline/inline_closure_borrows_arg.rs b/tests/mir-opt/inline/inline_closure_borrows_arg.rs new file mode 100644 index 000000000..d76bc33f5 --- /dev/null +++ b/tests/mir-opt/inline/inline_closure_borrows_arg.rs @@ -0,0 +1,17 @@ +// compile-flags: -Z span_free_formats -Zunsound-mir-opts + +// Tests that MIR inliner can handle closure arguments, +// even when (#45894) + +fn main() { + println!("{}", foo(0, &14)); +} + +// EMIT_MIR inline_closure_borrows_arg.foo.Inline.after.mir +fn foo<T: Copy>(_t: T, q: &i32) -> i32 { + let x = |r: &i32, _s: &i32| { + let variable = &*r; + *variable + }; + x(q, q) +} diff --git a/tests/mir-opt/inline/inline_closure_captures.foo.Inline.after.mir b/tests/mir-opt/inline/inline_closure_captures.foo.Inline.after.mir new file mode 100644 index 000000000..fd19c2886 --- /dev/null +++ b/tests/mir-opt/inline/inline_closure_captures.foo.Inline.after.mir @@ -0,0 +1,65 @@ +// MIR for `foo` after Inline + +fn foo(_1: T, _2: i32) -> (i32, T) { + debug t => _1; // in scope 0 at $DIR/inline_closure_captures.rs:+0:17: +0:18 + debug q => _2; // in scope 0 at $DIR/inline_closure_captures.rs:+0:23: +0:24 + let mut _0: (i32, T); // return place in scope 0 at $DIR/inline_closure_captures.rs:+0:34: +0:42 + let _3: [closure@foo<T>::{closure#0}]; // in scope 0 at $DIR/inline_closure_captures.rs:+1:9: +1:10 + let mut _4: &i32; // in scope 0 at $DIR/inline_closure_captures.rs:+1:13: +1:24 + let mut _5: &T; // in scope 0 at $DIR/inline_closure_captures.rs:+1:13: +1:24 + let mut _6: &[closure@foo<T>::{closure#0}]; // in scope 0 at $DIR/inline_closure_captures.rs:+2:5: +2:6 + let mut _7: (i32,); // in scope 0 at $DIR/inline_closure_captures.rs:+2:5: +2:9 + let mut _8: i32; // in scope 0 at $DIR/inline_closure_captures.rs:+2:7: +2:8 + let mut _9: i32; // in scope 0 at $DIR/inline_closure_captures.rs:+2:5: +2:9 + scope 1 { + debug x => _3; // in scope 1 at $DIR/inline_closure_captures.rs:+1:9: +1:10 + scope 2 (inlined foo::<T>::{closure#0}) { // at $DIR/inline_closure_captures.rs:12:5: 12:9 + debug _q => _9; // in scope 2 at $DIR/inline_closure_captures.rs:+1:14: +1:16 + debug q => (*((*_6).0: &i32)); // in scope 2 at $DIR/inline_closure_captures.rs:+0:23: +0:24 + debug t => (*((*_6).1: &T)); // in scope 2 at $DIR/inline_closure_captures.rs:+0:17: +0:18 + let mut _10: i32; // in scope 2 at $DIR/inline_closure_captures.rs:+1:19: +1:20 + let mut _11: T; // in scope 2 at $DIR/inline_closure_captures.rs:+1:22: +1:23 + let mut _12: &i32; // in scope 2 at $DIR/inline_closure_captures.rs:+1:13: +1:24 + let mut _13: &T; // in scope 2 at $DIR/inline_closure_captures.rs:+1:13: +1:24 + } + } + + bb0: { + StorageLive(_3); // scope 0 at $DIR/inline_closure_captures.rs:+1:9: +1:10 + StorageLive(_4); // scope 0 at $DIR/inline_closure_captures.rs:+1:13: +1:24 + _4 = &_2; // scope 0 at $DIR/inline_closure_captures.rs:+1:13: +1:24 + StorageLive(_5); // scope 0 at $DIR/inline_closure_captures.rs:+1:13: +1:24 + _5 = &_1; // scope 0 at $DIR/inline_closure_captures.rs:+1:13: +1:24 + Deinit(_3); // scope 0 at $DIR/inline_closure_captures.rs:+1:13: +1:24 + (_3.0: &i32) = move _4; // scope 0 at $DIR/inline_closure_captures.rs:+1:13: +1:24 + (_3.1: &T) = move _5; // scope 0 at $DIR/inline_closure_captures.rs:+1:13: +1:24 + StorageDead(_5); // scope 0 at $DIR/inline_closure_captures.rs:+1:16: +1:17 + StorageDead(_4); // scope 0 at $DIR/inline_closure_captures.rs:+1:16: +1:17 + StorageLive(_6); // scope 1 at $DIR/inline_closure_captures.rs:+2:5: +2:6 + _6 = &_3; // scope 1 at $DIR/inline_closure_captures.rs:+2:5: +2:6 + StorageLive(_7); // scope 1 at $DIR/inline_closure_captures.rs:+2:5: +2:9 + StorageLive(_8); // scope 1 at $DIR/inline_closure_captures.rs:+2:7: +2:8 + _8 = _2; // scope 1 at $DIR/inline_closure_captures.rs:+2:7: +2:8 + Deinit(_7); // scope 1 at $DIR/inline_closure_captures.rs:+2:5: +2:9 + (_7.0: i32) = move _8; // scope 1 at $DIR/inline_closure_captures.rs:+2:5: +2:9 + StorageLive(_9); // scope 1 at $DIR/inline_closure_captures.rs:+2:5: +2:9 + _9 = move (_7.0: i32); // scope 1 at $DIR/inline_closure_captures.rs:+2:5: +2:9 + StorageLive(_10); // scope 2 at $DIR/inline_closure_captures.rs:+1:19: +1:20 + _12 = deref_copy ((*_6).0: &i32); // scope 2 at $DIR/inline_closure_captures.rs:+1:19: +1:20 + _10 = (*_12); // scope 2 at $DIR/inline_closure_captures.rs:+1:19: +1:20 + StorageLive(_11); // scope 2 at $DIR/inline_closure_captures.rs:+1:22: +1:23 + _13 = deref_copy ((*_6).1: &T); // scope 2 at $DIR/inline_closure_captures.rs:+1:22: +1:23 + _11 = (*_13); // scope 2 at $DIR/inline_closure_captures.rs:+1:22: +1:23 + Deinit(_0); // scope 2 at $DIR/inline_closure_captures.rs:+1:18: +1:24 + (_0.0: i32) = move _10; // scope 2 at $DIR/inline_closure_captures.rs:+1:18: +1:24 + (_0.1: T) = move _11; // scope 2 at $DIR/inline_closure_captures.rs:+1:18: +1:24 + StorageDead(_11); // scope 2 at $DIR/inline_closure_captures.rs:+1:23: +1:24 + StorageDead(_10); // scope 2 at $DIR/inline_closure_captures.rs:+1:23: +1:24 + StorageDead(_9); // scope 1 at $DIR/inline_closure_captures.rs:+2:5: +2:9 + StorageDead(_8); // scope 1 at $DIR/inline_closure_captures.rs:+2:8: +2:9 + StorageDead(_7); // scope 1 at $DIR/inline_closure_captures.rs:+2:8: +2:9 + StorageDead(_6); // scope 1 at $DIR/inline_closure_captures.rs:+2:8: +2:9 + StorageDead(_3); // scope 0 at $DIR/inline_closure_captures.rs:+3:1: +3:2 + return; // scope 0 at $DIR/inline_closure_captures.rs:+3:2: +3:2 + } +} diff --git a/tests/mir-opt/inline/inline_closure_captures.rs b/tests/mir-opt/inline/inline_closure_captures.rs new file mode 100644 index 000000000..52b6817e4 --- /dev/null +++ b/tests/mir-opt/inline/inline_closure_captures.rs @@ -0,0 +1,13 @@ +// compile-flags: -Z span_free_formats + +// Tests that MIR inliner can handle closure captures. + +fn main() { + println!("{:?}", foo(0, 14)); +} + +// EMIT_MIR inline_closure_captures.foo.Inline.after.mir +fn foo<T: Copy>(t: T, q: i32) -> (i32, T) { + let x = |_q| (q, t); + x(q) +} diff --git a/tests/mir-opt/inline/inline_compatibility.inlined_no_sanitize.Inline.diff b/tests/mir-opt/inline/inline_compatibility.inlined_no_sanitize.Inline.diff new file mode 100644 index 000000000..e30a5e116 --- /dev/null +++ b/tests/mir-opt/inline/inline_compatibility.inlined_no_sanitize.Inline.diff @@ -0,0 +1,24 @@ +- // MIR for `inlined_no_sanitize` before Inline ++ // MIR for `inlined_no_sanitize` after Inline + + fn inlined_no_sanitize() -> () { + let mut _0: (); // return place in scope 0 at $DIR/inline_compatibility.rs:+0:37: +0:37 + let _1: (); // in scope 0 at $DIR/inline_compatibility.rs:+1:5: +1:18 ++ scope 1 (inlined no_sanitize) { // at $DIR/inline_compatibility.rs:24:5: 24:18 ++ } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/inline_compatibility.rs:+1:5: +1:18 +- _1 = no_sanitize() -> bb1; // scope 0 at $DIR/inline_compatibility.rs:+1:5: +1:18 +- // mir::Constant +- // + span: $DIR/inline_compatibility.rs:24:5: 24:16 +- // + literal: Const { ty: unsafe fn() {no_sanitize}, val: Value(<ZST>) } +- } +- +- bb1: { + StorageDead(_1); // scope 0 at $DIR/inline_compatibility.rs:+1:18: +1:19 + _0 = const (); // scope 0 at $DIR/inline_compatibility.rs:+0:37: +2:2 + return; // scope 0 at $DIR/inline_compatibility.rs:+2:2: +2:2 + } + } + diff --git a/tests/mir-opt/inline/inline_compatibility.inlined_target_feature.Inline.diff b/tests/mir-opt/inline/inline_compatibility.inlined_target_feature.Inline.diff new file mode 100644 index 000000000..c2b3c46a3 --- /dev/null +++ b/tests/mir-opt/inline/inline_compatibility.inlined_target_feature.Inline.diff @@ -0,0 +1,24 @@ +- // MIR for `inlined_target_feature` before Inline ++ // MIR for `inlined_target_feature` after Inline + + fn inlined_target_feature() -> () { + let mut _0: (); // return place in scope 0 at $DIR/inline_compatibility.rs:+0:40: +0:40 + let _1: (); // in scope 0 at $DIR/inline_compatibility.rs:+1:5: +1:21 ++ scope 1 (inlined target_feature) { // at $DIR/inline_compatibility.rs:13:5: 13:21 ++ } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/inline_compatibility.rs:+1:5: +1:21 +- _1 = target_feature() -> bb1; // scope 0 at $DIR/inline_compatibility.rs:+1:5: +1:21 +- // mir::Constant +- // + span: $DIR/inline_compatibility.rs:13:5: 13:19 +- // + literal: Const { ty: unsafe fn() {target_feature}, val: Value(<ZST>) } +- } +- +- bb1: { + StorageDead(_1); // scope 0 at $DIR/inline_compatibility.rs:+1:21: +1:22 + _0 = const (); // scope 0 at $DIR/inline_compatibility.rs:+0:40: +2:2 + return; // scope 0 at $DIR/inline_compatibility.rs:+2:2: +2:2 + } + } + diff --git a/tests/mir-opt/inline/inline_compatibility.not_inlined_c_variadic.Inline.diff b/tests/mir-opt/inline/inline_compatibility.not_inlined_c_variadic.Inline.diff new file mode 100644 index 000000000..0ca5a5f70 --- /dev/null +++ b/tests/mir-opt/inline/inline_compatibility.not_inlined_c_variadic.Inline.diff @@ -0,0 +1,25 @@ +- // MIR for `not_inlined_c_variadic` before Inline ++ // MIR for `not_inlined_c_variadic` after Inline + + fn not_inlined_c_variadic() -> () { + let mut _0: (); // return place in scope 0 at $DIR/inline_compatibility.rs:+0:40: +0:40 + let _1: u32; // in scope 0 at $DIR/inline_compatibility.rs:+1:9: +1:10 + scope 1 { + debug s => _1; // in scope 1 at $DIR/inline_compatibility.rs:+1:9: +1:10 + } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/inline_compatibility.rs:+1:9: +1:10 + _1 = sum(const 4_u32, const 4_u32, const 30_u32, const 200_u32, const 1000_u32) -> bb1; // scope 0 at $DIR/inline_compatibility.rs:+1:13: +1:52 + // mir::Constant + // + span: $DIR/inline_compatibility.rs:42:13: 42:16 + // + literal: Const { ty: unsafe extern "C" fn(u32, ...) -> u32 {sum}, val: Value(<ZST>) } + } + + bb1: { + _0 = const (); // scope 0 at $DIR/inline_compatibility.rs:+0:40: +2:2 + StorageDead(_1); // scope 0 at $DIR/inline_compatibility.rs:+2:1: +2:2 + return; // scope 0 at $DIR/inline_compatibility.rs:+2:2: +2:2 + } + } + diff --git a/tests/mir-opt/inline/inline_compatibility.not_inlined_no_sanitize.Inline.diff b/tests/mir-opt/inline/inline_compatibility.not_inlined_no_sanitize.Inline.diff new file mode 100644 index 000000000..00d405c77 --- /dev/null +++ b/tests/mir-opt/inline/inline_compatibility.not_inlined_no_sanitize.Inline.diff @@ -0,0 +1,22 @@ +- // MIR for `not_inlined_no_sanitize` before Inline ++ // MIR for `not_inlined_no_sanitize` after Inline + + fn not_inlined_no_sanitize() -> () { + let mut _0: (); // return place in scope 0 at $DIR/inline_compatibility.rs:+0:41: +0:41 + let _1: (); // in scope 0 at $DIR/inline_compatibility.rs:+1:5: +1:18 + + bb0: { + StorageLive(_1); // scope 0 at $DIR/inline_compatibility.rs:+1:5: +1:18 + _1 = no_sanitize() -> bb1; // scope 0 at $DIR/inline_compatibility.rs:+1:5: +1:18 + // mir::Constant + // + span: $DIR/inline_compatibility.rs:29:5: 29:16 + // + literal: Const { ty: unsafe fn() {no_sanitize}, val: Value(<ZST>) } + } + + bb1: { + StorageDead(_1); // scope 0 at $DIR/inline_compatibility.rs:+1:18: +1:19 + _0 = const (); // scope 0 at $DIR/inline_compatibility.rs:+0:41: +2:2 + return; // scope 0 at $DIR/inline_compatibility.rs:+2:2: +2:2 + } + } + diff --git a/tests/mir-opt/inline/inline_compatibility.not_inlined_target_feature.Inline.diff b/tests/mir-opt/inline/inline_compatibility.not_inlined_target_feature.Inline.diff new file mode 100644 index 000000000..8b9c86f55 --- /dev/null +++ b/tests/mir-opt/inline/inline_compatibility.not_inlined_target_feature.Inline.diff @@ -0,0 +1,22 @@ +- // MIR for `not_inlined_target_feature` before Inline ++ // MIR for `not_inlined_target_feature` after Inline + + fn not_inlined_target_feature() -> () { + let mut _0: (); // return place in scope 0 at $DIR/inline_compatibility.rs:+0:44: +0:44 + let _1: (); // in scope 0 at $DIR/inline_compatibility.rs:+1:5: +1:21 + + bb0: { + StorageLive(_1); // scope 0 at $DIR/inline_compatibility.rs:+1:5: +1:21 + _1 = target_feature() -> bb1; // scope 0 at $DIR/inline_compatibility.rs:+1:5: +1:21 + // mir::Constant + // + span: $DIR/inline_compatibility.rs:18:5: 18:19 + // + literal: Const { ty: unsafe fn() {target_feature}, val: Value(<ZST>) } + } + + bb1: { + StorageDead(_1); // scope 0 at $DIR/inline_compatibility.rs:+1:21: +1:22 + _0 = const (); // scope 0 at $DIR/inline_compatibility.rs:+0:44: +2:2 + return; // scope 0 at $DIR/inline_compatibility.rs:+2:2: +2:2 + } + } + diff --git a/tests/mir-opt/inline/inline_compatibility.rs b/tests/mir-opt/inline/inline_compatibility.rs new file mode 100644 index 000000000..30aff0a64 --- /dev/null +++ b/tests/mir-opt/inline/inline_compatibility.rs @@ -0,0 +1,55 @@ +// Checks that only functions with compatible attributes are inlined. +// +// only-x86_64 + +#![crate_type = "lib"] +#![feature(no_sanitize)] +#![feature(target_feature_11)] +#![feature(c_variadic)] + +// EMIT_MIR inline_compatibility.inlined_target_feature.Inline.diff +#[target_feature(enable = "sse2")] +pub unsafe fn inlined_target_feature() { + target_feature(); +} + +// EMIT_MIR inline_compatibility.not_inlined_target_feature.Inline.diff +pub unsafe fn not_inlined_target_feature() { + target_feature(); +} + +// EMIT_MIR inline_compatibility.inlined_no_sanitize.Inline.diff +#[no_sanitize(address)] +pub unsafe fn inlined_no_sanitize() { + no_sanitize(); +} + +// EMIT_MIR inline_compatibility.not_inlined_no_sanitize.Inline.diff +pub unsafe fn not_inlined_no_sanitize() { + no_sanitize(); +} + +#[inline] +#[target_feature(enable = "sse2")] +pub unsafe fn target_feature() {} + +#[inline] +#[no_sanitize(address)] +pub unsafe fn no_sanitize() {} + +// EMIT_MIR inline_compatibility.not_inlined_c_variadic.Inline.diff +pub unsafe fn not_inlined_c_variadic() { + let s = sum(4u32, 4u32, 30u32, 200u32, 1000u32); +} + +#[no_mangle] +#[inline(always)] +unsafe extern "C" fn sum(n: u32, mut vs: ...) -> u32 { + let mut s = 0; + let mut i = 0; + while i != n { + s += vs.arg::<u32>(); + i += 1; + } + s +} diff --git a/tests/mir-opt/inline/inline_cycle.one.Inline.diff b/tests/mir-opt/inline/inline_cycle.one.Inline.diff new file mode 100644 index 000000000..5510cd7bc --- /dev/null +++ b/tests/mir-opt/inline/inline_cycle.one.Inline.diff @@ -0,0 +1,30 @@ +- // MIR for `one` before Inline ++ // MIR for `one` after Inline + + fn one() -> () { + let mut _0: (); // return place in scope 0 at $DIR/inline_cycle.rs:+0:10: +0:10 + let _1: (); // in scope 0 at $DIR/inline_cycle.rs:+1:5: +1:24 ++ scope 1 (inlined <C as Call>::call) { // at $DIR/inline_cycle.rs:14:5: 14:24 ++ scope 2 (inlined <A<C> as Call>::call) { // at $DIR/inline_cycle.rs:43:9: 43:23 ++ scope 3 (inlined <B<C> as Call>::call) { // at $DIR/inline_cycle.rs:28:9: 28:31 ++ } ++ } ++ } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/inline_cycle.rs:+1:5: +1:24 +- _1 = <C as Call>::call() -> bb1; // scope 0 at $DIR/inline_cycle.rs:+1:5: +1:24 ++ _1 = <C as Call>::call() -> bb1; // scope 3 at $DIR/inline_cycle.rs:36:9: 36:28 + // mir::Constant +- // + span: $DIR/inline_cycle.rs:14:5: 14:22 ++ // + span: $DIR/inline_cycle.rs:36:9: 36:26 + // + literal: Const { ty: fn() {<C as Call>::call}, val: Value(<ZST>) } + } + + bb1: { + StorageDead(_1); // scope 0 at $DIR/inline_cycle.rs:+1:24: +1:25 + _0 = const (); // scope 0 at $DIR/inline_cycle.rs:+0:10: +2:2 + return; // scope 0 at $DIR/inline_cycle.rs:+2:2: +2:2 + } + } + diff --git a/tests/mir-opt/inline/inline_cycle.rs b/tests/mir-opt/inline/inline_cycle.rs new file mode 100644 index 000000000..63ad57de1 --- /dev/null +++ b/tests/mir-opt/inline/inline_cycle.rs @@ -0,0 +1,60 @@ +// Check that inliner handles various forms of recursion and doesn't fall into +// an infinite inlining cycle. The particular outcome of inlining is not +// crucial otherwise. +// +// Regression test for issue #78573. + +fn main() { + one(); + two(); +} + +// EMIT_MIR inline_cycle.one.Inline.diff +fn one() { + <C as Call>::call(); +} + +pub trait Call { + fn call(); +} + +pub struct A<T>(T); +pub struct B<T>(T); +pub struct C; + +impl<T: Call> Call for A<T> { + #[inline] + fn call() { + <B<T> as Call>::call() + } +} + + +impl<T: Call> Call for B<T> { + #[inline] + fn call() { + <T as Call>::call() + } +} + +impl Call for C { + #[inline] + fn call() { + A::<C>::call() + } +} + +// EMIT_MIR inline_cycle.two.Inline.diff +fn two() { + call(f); +} + +#[inline] +fn call<F: FnOnce()>(f: F) { + f(); +} + +#[inline] +fn f() { + call(f); +} diff --git a/tests/mir-opt/inline/inline_cycle.two.Inline.diff b/tests/mir-opt/inline/inline_cycle.two.Inline.diff new file mode 100644 index 000000000..64c0065b5 --- /dev/null +++ b/tests/mir-opt/inline/inline_cycle.two.Inline.diff @@ -0,0 +1,41 @@ +- // MIR for `two` before Inline ++ // MIR for `two` after Inline + + fn two() -> () { + let mut _0: (); // return place in scope 0 at $DIR/inline_cycle.rs:+0:10: +0:10 + let _1: (); // in scope 0 at $DIR/inline_cycle.rs:+1:5: +1:12 ++ let mut _2: fn() {f}; // in scope 0 at $DIR/inline_cycle.rs:+1:5: +1:12 ++ scope 1 (inlined call::<fn() {f}>) { // at $DIR/inline_cycle.rs:49:5: 49:12 ++ debug f => _2; // in scope 1 at $DIR/inline_cycle.rs:53:22: 53:23 ++ let _3: (); // in scope 1 at $DIR/inline_cycle.rs:54:5: 54:8 ++ let mut _4: (); // in scope 1 at $DIR/inline_cycle.rs:54:5: 54:8 ++ scope 2 (inlined <fn() {f} as FnOnce<()>>::call_once - shim(fn() {f})) { // at $DIR/inline_cycle.rs:54:5: 54:8 ++ } ++ } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/inline_cycle.rs:+1:5: +1:12 +- _1 = call::<fn() {f}>(f) -> bb1; // scope 0 at $DIR/inline_cycle.rs:+1:5: +1:12 ++ StorageLive(_2); // scope 0 at $DIR/inline_cycle.rs:+1:5: +1:12 ++ _2 = f; // scope 0 at $DIR/inline_cycle.rs:+1:5: +1:12 + // mir::Constant +- // + span: $DIR/inline_cycle.rs:49:5: 49:9 +- // + literal: Const { ty: fn(fn() {f}) {call::<fn() {f}>}, val: Value(<ZST>) } +- // mir::Constant + // + span: $DIR/inline_cycle.rs:49:10: 49:11 + // + literal: Const { ty: fn() {f}, val: Value(<ZST>) } ++ StorageLive(_3); // scope 1 at $DIR/inline_cycle.rs:54:5: 54:8 ++ StorageLive(_4); // scope 1 at $DIR/inline_cycle.rs:54:5: 54:8 ++ _3 = move _2() -> bb1; // scope 2 at $SRC_DIR/core/src/ops/function.rs:LL:COL + } + + bb1: { ++ StorageDead(_4); // scope 1 at $DIR/inline_cycle.rs:54:7: 54:8 ++ StorageDead(_3); // scope 1 at $DIR/inline_cycle.rs:54:8: 54:9 ++ StorageDead(_2); // scope 0 at $DIR/inline_cycle.rs:+1:5: +1:12 + StorageDead(_1); // scope 0 at $DIR/inline_cycle.rs:+1:12: +1:13 + _0 = const (); // scope 0 at $DIR/inline_cycle.rs:+0:10: +2:2 + return; // scope 0 at $DIR/inline_cycle.rs:+2:2: +2:2 + } + } + diff --git a/tests/mir-opt/inline/inline_cycle_generic.main.Inline.diff b/tests/mir-opt/inline/inline_cycle_generic.main.Inline.diff new file mode 100644 index 000000000..52debab4d --- /dev/null +++ b/tests/mir-opt/inline/inline_cycle_generic.main.Inline.diff @@ -0,0 +1,32 @@ +- // MIR for `main` before Inline ++ // MIR for `main` after Inline + + fn main() -> () { + let mut _0: (); // return place in scope 0 at $DIR/inline_cycle_generic.rs:+0:11: +0:11 + let _1: (); // in scope 0 at $DIR/inline_cycle_generic.rs:+1:5: +1:24 ++ scope 1 (inlined <C as Call>::call) { // at $DIR/inline_cycle_generic.rs:9:5: 9:24 ++ scope 2 (inlined <B<A> as Call>::call) { // at $DIR/inline_cycle_generic.rs:38:9: 38:31 ++ scope 3 (inlined <A as Call>::call) { // at $DIR/inline_cycle_generic.rs:31:9: 31:28 ++ scope 4 (inlined <B<C> as Call>::call) { // at $DIR/inline_cycle_generic.rs:23:9: 23:31 ++ } ++ } ++ } ++ } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/inline_cycle_generic.rs:+1:5: +1:24 +- _1 = <C as Call>::call() -> bb1; // scope 0 at $DIR/inline_cycle_generic.rs:+1:5: +1:24 ++ _1 = <C as Call>::call() -> bb1; // scope 4 at $DIR/inline_cycle_generic.rs:31:9: 31:28 + // mir::Constant +- // + span: $DIR/inline_cycle_generic.rs:9:5: 9:22 ++ // + span: $DIR/inline_cycle_generic.rs:31:9: 31:26 + // + literal: Const { ty: fn() {<C as Call>::call}, val: Value(<ZST>) } + } + + bb1: { + StorageDead(_1); // scope 0 at $DIR/inline_cycle_generic.rs:+1:24: +1:25 + _0 = const (); // scope 0 at $DIR/inline_cycle_generic.rs:+0:11: +2:2 + return; // scope 0 at $DIR/inline_cycle_generic.rs:+2:2: +2:2 + } + } + diff --git a/tests/mir-opt/inline/inline_cycle_generic.rs b/tests/mir-opt/inline/inline_cycle_generic.rs new file mode 100644 index 000000000..24b4f3793 --- /dev/null +++ b/tests/mir-opt/inline/inline_cycle_generic.rs @@ -0,0 +1,40 @@ +// Check that inliner handles various forms of recursion and doesn't fall into +// an infinite inlining cycle. The particular outcome of inlining is not +// crucial otherwise. +// +// Regression test for issue #78573. + +// EMIT_MIR inline_cycle_generic.main.Inline.diff +fn main() { + <C as Call>::call(); +} + +pub trait Call { + fn call(); +} + +pub struct A; +pub struct B<T>(T); +pub struct C; + +impl Call for A { + #[inline] + fn call() { + <B<C> as Call>::call() + } +} + + +impl<T: Call> Call for B<T> { + #[inline] + fn call() { + <T as Call>::call() + } +} + +impl Call for C { + #[inline] + fn call() { + <B<A> as Call>::call() + } +} diff --git a/tests/mir-opt/inline/inline_diverging.f.Inline.diff b/tests/mir-opt/inline/inline_diverging.f.Inline.diff new file mode 100644 index 000000000..b49191f49 --- /dev/null +++ b/tests/mir-opt/inline/inline_diverging.f.Inline.diff @@ -0,0 +1,24 @@ +- // MIR for `f` before Inline ++ // MIR for `f` after Inline + + fn f() -> () { + let mut _0: (); // return place in scope 0 at $DIR/inline_diverging.rs:+0:12: +0:12 + let mut _1: !; // in scope 0 at $DIR/inline_diverging.rs:+0:12: +2:2 + let _2: !; // in scope 0 at $DIR/inline_diverging.rs:+1:5: +1:12 ++ scope 1 (inlined sleep) { // at $DIR/inline_diverging.rs:8:5: 8:12 ++ } + + bb0: { + StorageLive(_2); // scope 0 at $DIR/inline_diverging.rs:+1:5: +1:12 +- _2 = sleep(); // scope 0 at $DIR/inline_diverging.rs:+1:5: +1:12 +- // mir::Constant +- // + span: $DIR/inline_diverging.rs:8:5: 8:10 +- // + literal: Const { ty: fn() -> ! {sleep}, val: Value(<ZST>) } ++ goto -> bb1; // scope 0 at $DIR/inline_diverging.rs:+1:5: +1:12 ++ } ++ ++ bb1: { ++ goto -> bb1; // scope 1 at $DIR/inline_diverging.rs:39:5: 39:12 + } + } + diff --git a/tests/mir-opt/inline/inline_diverging.g.Inline.diff b/tests/mir-opt/inline/inline_diverging.g.Inline.diff new file mode 100644 index 000000000..b787a19f4 --- /dev/null +++ b/tests/mir-opt/inline/inline_diverging.g.Inline.diff @@ -0,0 +1,49 @@ +- // MIR for `g` before Inline ++ // MIR for `g` after Inline + + fn g(_1: i32) -> u32 { + debug i => _1; // in scope 0 at $DIR/inline_diverging.rs:+0:10: +0:11 + let mut _0: u32; // return place in scope 0 at $DIR/inline_diverging.rs:+0:21: +0:24 + let mut _2: bool; // in scope 0 at $DIR/inline_diverging.rs:+1:8: +1:13 + let mut _3: i32; // in scope 0 at $DIR/inline_diverging.rs:+1:8: +1:9 + let mut _4: i32; // in scope 0 at $DIR/inline_diverging.rs:+2:9: +2:10 + let mut _5: !; // in scope 0 at $DIR/inline_diverging.rs:+3:12: +5:6 + let _6: !; // in scope 0 at $DIR/inline_diverging.rs:+4:9: +4:16 ++ scope 1 (inlined panic) { // at $DIR/inline_diverging.rs:16:9: 16:16 ++ let mut _7: !; // in scope 1 at $SRC_DIR/std/src/panic.rs:LL:COL ++ } + + bb0: { + StorageLive(_2); // scope 0 at $DIR/inline_diverging.rs:+1:8: +1:13 + StorageLive(_3); // scope 0 at $DIR/inline_diverging.rs:+1:8: +1:9 + _3 = _1; // scope 0 at $DIR/inline_diverging.rs:+1:8: +1:9 + _2 = Gt(move _3, const 0_i32); // scope 0 at $DIR/inline_diverging.rs:+1:8: +1:13 + StorageDead(_3); // scope 0 at $DIR/inline_diverging.rs:+1:12: +1:13 + switchInt(move _2) -> [0: bb2, otherwise: bb1]; // scope 0 at $DIR/inline_diverging.rs:+1:8: +1:13 + } + + bb1: { + StorageLive(_4); // scope 0 at $DIR/inline_diverging.rs:+2:9: +2:10 + _4 = _1; // scope 0 at $DIR/inline_diverging.rs:+2:9: +2:10 + _0 = move _4 as u32 (IntToInt); // scope 0 at $DIR/inline_diverging.rs:+2:9: +2:17 + StorageDead(_4); // scope 0 at $DIR/inline_diverging.rs:+2:16: +2:17 + StorageDead(_2); // scope 0 at $DIR/inline_diverging.rs:+5:5: +5:6 + return; // scope 0 at $DIR/inline_diverging.rs:+6:2: +6:2 + } + + bb2: { + StorageLive(_6); // scope 0 at $DIR/inline_diverging.rs:+4:9: +4:16 +- _6 = panic(); // scope 0 at $DIR/inline_diverging.rs:+4:9: +4:16 ++ StorageLive(_7); // scope 1 at $SRC_DIR/std/src/panic.rs:LL:COL ++ _7 = begin_panic::<&str>(const "explicit panic"); // scope 1 at $SRC_DIR/std/src/panic.rs:LL:COL + // mir::Constant +- // + span: $DIR/inline_diverging.rs:16:9: 16:14 +- // + literal: Const { ty: fn() -> ! {panic}, val: Value(<ZST>) } ++ // + span: $SRC_DIR/std/src/panic.rs:LL:COL ++ // + literal: Const { ty: fn(&str) -> ! {begin_panic::<&str>}, val: Value(<ZST>) } ++ // mir::Constant ++ // + span: $SRC_DIR/std/src/panic.rs:LL:COL ++ // + literal: Const { ty: &str, val: Value(Slice(..)) } + } + } + diff --git a/tests/mir-opt/inline/inline_diverging.h.Inline.diff b/tests/mir-opt/inline/inline_diverging.h.Inline.diff new file mode 100644 index 000000000..f82fcf4c8 --- /dev/null +++ b/tests/mir-opt/inline/inline_diverging.h.Inline.diff @@ -0,0 +1,87 @@ +- // MIR for `h` before Inline ++ // MIR for `h` after Inline + + fn h() -> () { + let mut _0: (); // return place in scope 0 at $DIR/inline_diverging.rs:+0:12: +0:12 + let _1: (!, !); // in scope 0 at $DIR/inline_diverging.rs:+1:5: +1:22 ++ let mut _2: fn() -> ! {sleep}; // in scope 0 at $DIR/inline_diverging.rs:+1:5: +1:22 ++ scope 1 (inlined call_twice::<!, fn() -> ! {sleep}>) { // at $DIR/inline_diverging.rs:22:5: 22:22 ++ debug f => _2; // in scope 1 at $DIR/inline_diverging.rs:26:36: 26:37 ++ let _3: !; // in scope 1 at $DIR/inline_diverging.rs:27:9: 27:10 ++ let mut _4: &fn() -> ! {sleep}; // in scope 1 at $DIR/inline_diverging.rs:27:13: 27:14 ++ let mut _5: (); // in scope 1 at $DIR/inline_diverging.rs:27:13: 27:16 ++ let mut _6: &fn() -> ! {sleep}; // in scope 1 at $DIR/inline_diverging.rs:28:13: 28:14 ++ let mut _7: (); // in scope 1 at $DIR/inline_diverging.rs:28:13: 28:16 ++ let mut _8: !; // in scope 1 at $DIR/inline_diverging.rs:29:6: 29:7 ++ let mut _9: !; // in scope 1 at $DIR/inline_diverging.rs:29:9: 29:10 ++ scope 2 { ++ debug a => _3; // in scope 2 at $DIR/inline_diverging.rs:27:9: 27:10 ++ scope 3 { ++ debug b => _9; // in scope 3 at $DIR/inline_diverging.rs:28:9: 28:10 ++ } ++ } ++ scope 4 (inlined <fn() -> ! {sleep} as Fn<()>>::call - shim(fn() -> ! {sleep})) { // at $DIR/inline_diverging.rs:27:13: 27:16 ++ } ++ } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/inline_diverging.rs:+1:5: +1:22 +- _1 = call_twice::<!, fn() -> ! {sleep}>(sleep); // scope 0 at $DIR/inline_diverging.rs:+1:5: +1:22 ++ StorageLive(_2); // scope 0 at $DIR/inline_diverging.rs:+1:5: +1:22 ++ _2 = sleep; // scope 0 at $DIR/inline_diverging.rs:+1:5: +1:22 + // mir::Constant +- // + span: $DIR/inline_diverging.rs:22:5: 22:15 +- // + literal: Const { ty: fn(fn() -> ! {sleep}) -> (!, !) {call_twice::<!, fn() -> ! {sleep}>}, val: Value(<ZST>) } +- // mir::Constant + // + span: $DIR/inline_diverging.rs:22:16: 22:21 + // + literal: Const { ty: fn() -> ! {sleep}, val: Value(<ZST>) } ++ StorageLive(_9); // scope 0 at $DIR/inline_diverging.rs:+1:5: +1:22 ++ StorageLive(_3); // scope 1 at $DIR/inline_diverging.rs:27:9: 27:10 ++ StorageLive(_4); // scope 1 at $DIR/inline_diverging.rs:27:13: 27:14 ++ _4 = &_2; // scope 1 at $DIR/inline_diverging.rs:27:13: 27:14 ++ StorageLive(_5); // scope 1 at $DIR/inline_diverging.rs:27:13: 27:16 ++ _3 = move (*_4)() -> [return: bb6, unwind: bb4]; // scope 4 at $SRC_DIR/core/src/ops/function.rs:LL:COL ++ } ++ ++ bb1: { ++ StorageDead(_7); // scope 2 at $DIR/inline_diverging.rs:28:15: 28:16 ++ StorageDead(_6); // scope 2 at $DIR/inline_diverging.rs:28:15: 28:16 ++ StorageLive(_8); // scope 3 at $DIR/inline_diverging.rs:29:6: 29:7 ++ _8 = move _3; // scope 3 at $DIR/inline_diverging.rs:29:6: 29:7 ++ Deinit(_1); // scope 3 at $DIR/inline_diverging.rs:29:5: 29:11 ++ (_1.0: !) = move _8; // scope 3 at $DIR/inline_diverging.rs:29:5: 29:11 ++ (_1.1: !) = move _9; // scope 3 at $DIR/inline_diverging.rs:29:5: 29:11 ++ StorageDead(_8); // scope 3 at $DIR/inline_diverging.rs:29:10: 29:11 ++ StorageDead(_3); // scope 1 at $DIR/inline_diverging.rs:30:1: 30:2 ++ drop(_2) -> bb2; // scope 1 at $DIR/inline_diverging.rs:30:1: 30:2 ++ } ++ ++ bb2: { ++ unreachable; // scope 0 at $DIR/inline_diverging.rs:30:2: 30:2 ++ } ++ ++ bb3 (cleanup): { ++ drop(_3) -> bb4; // scope 1 at $DIR/inline_diverging.rs:30:1: 30:2 ++ } ++ ++ bb4 (cleanup): { ++ drop(_2) -> bb5; // scope 1 at $DIR/inline_diverging.rs:30:1: 30:2 ++ } ++ ++ bb5 (cleanup): { ++ resume; // scope 1 at $DIR/inline_diverging.rs:26:1: 30:2 ++ } ++ ++ bb6: { ++ StorageDead(_5); // scope 1 at $DIR/inline_diverging.rs:27:15: 27:16 ++ StorageDead(_4); // scope 1 at $DIR/inline_diverging.rs:27:15: 27:16 ++ StorageLive(_6); // scope 2 at $DIR/inline_diverging.rs:28:13: 28:14 ++ _6 = &_2; // scope 2 at $DIR/inline_diverging.rs:28:13: 28:14 ++ StorageLive(_7); // scope 2 at $DIR/inline_diverging.rs:28:13: 28:16 ++ _9 = <fn() -> ! {sleep} as Fn<()>>::call(move _6, move _7) -> [return: bb1, unwind: bb3]; // scope 2 at $DIR/inline_diverging.rs:28:13: 28:16 ++ // mir::Constant ++ // + span: $DIR/inline_diverging.rs:28:13: 28:14 ++ // + literal: Const { ty: for<'a> extern "rust-call" fn(&'a fn() -> ! {sleep}, ()) -> <fn() -> ! {sleep} as FnOnce<()>>::Output {<fn() -> ! {sleep} as Fn<()>>::call}, val: Value(<ZST>) } + } + } + diff --git a/tests/mir-opt/inline/inline_diverging.rs b/tests/mir-opt/inline/inline_diverging.rs new file mode 100644 index 000000000..ae6f814c2 --- /dev/null +++ b/tests/mir-opt/inline/inline_diverging.rs @@ -0,0 +1,40 @@ +// Tests inlining of diverging calls. +// +// ignore-wasm32-bare compiled with panic=abort by default +#![crate_type = "lib"] + +// EMIT_MIR inline_diverging.f.Inline.diff +pub fn f() { + sleep(); +} + +// EMIT_MIR inline_diverging.g.Inline.diff +pub fn g(i: i32) -> u32 { + if i > 0 { + i as u32 + } else { + panic(); + } +} + +// EMIT_MIR inline_diverging.h.Inline.diff +pub fn h() { + call_twice(sleep); +} + +#[inline(always)] +pub fn call_twice<R, F: Fn() -> R>(f: F) -> (R, R) { + let a = f(); + let b = f(); + (a, b) +} + +#[inline(always)] +fn panic() -> ! { + panic!(); +} + +#[inline(always)] +fn sleep() -> ! { + loop {} +} diff --git a/tests/mir-opt/inline/inline_generator.main.Inline.diff b/tests/mir-opt/inline/inline_generator.main.Inline.diff new file mode 100644 index 000000000..f27b64c30 --- /dev/null +++ b/tests/mir-opt/inline/inline_generator.main.Inline.diff @@ -0,0 +1,136 @@ +- // MIR for `main` before Inline ++ // MIR for `main` after Inline + + fn main() -> () { + let mut _0: (); // return place in scope 0 at $DIR/inline_generator.rs:+0:11: +0:11 + let _1: std::ops::GeneratorState<i32, bool>; // in scope 0 at $DIR/inline_generator.rs:+1:9: +1:11 + let mut _2: std::pin::Pin<&mut [generator@$DIR/inline_generator.rs:15:5: 15:8]>; // in scope 0 at $DIR/inline_generator.rs:+1:14: +1:32 + let mut _3: &mut [generator@$DIR/inline_generator.rs:15:5: 15:8]; // in scope 0 at $DIR/inline_generator.rs:+1:23: +1:31 + let mut _4: [generator@$DIR/inline_generator.rs:15:5: 15:8]; // in scope 0 at $DIR/inline_generator.rs:+1:28: +1:31 ++ let mut _7: bool; // in scope 0 at $DIR/inline_generator.rs:+1:33: +1:46 + scope 1 { + debug _r => _1; // in scope 1 at $DIR/inline_generator.rs:+1:9: +1:11 + } ++ scope 2 (inlined g) { // at $DIR/inline_generator.rs:9:28: 9:31 ++ } ++ scope 3 (inlined Pin::<&mut [generator@$DIR/inline_generator.rs:15:5: 15:8]>::new) { // at $DIR/inline_generator.rs:9:14: 9:32 ++ debug pointer => _3; // in scope 3 at $SRC_DIR/core/src/pin.rs:LL:COL ++ let mut _5: &mut [generator@$DIR/inline_generator.rs:15:5: 15:8]; // in scope 3 at $SRC_DIR/core/src/pin.rs:LL:COL ++ scope 4 { ++ scope 5 (inlined Pin::<&mut [generator@$DIR/inline_generator.rs:15:5: 15:8]>::new_unchecked) { // at $SRC_DIR/core/src/pin.rs:LL:COL ++ debug pointer => _5; // in scope 5 at $SRC_DIR/core/src/pin.rs:LL:COL ++ let mut _6: &mut [generator@$DIR/inline_generator.rs:15:5: 15:8]; // in scope 5 at $SRC_DIR/core/src/pin.rs:LL:COL ++ } ++ } ++ } ++ scope 6 (inlined g::{closure#0}) { // at $DIR/inline_generator.rs:9:33: 9:46 ++ debug a => _7; // in scope 6 at $DIR/inline_generator.rs:15:6: 15:7 ++ let mut _8: i32; // in scope 6 at $DIR/inline_generator.rs:15:17: 15:39 ++ let mut _9: u32; // in scope 6 at $DIR/inline_generator.rs:15:5: 15:41 ++ let mut _10: &mut [generator@$DIR/inline_generator.rs:15:5: 15:8]; // in scope 6 at $DIR/inline_generator.rs:15:5: 15:41 ++ let mut _11: &mut [generator@$DIR/inline_generator.rs:15:5: 15:8]; // in scope 6 at $DIR/inline_generator.rs:15:5: 15:41 ++ let mut _12: &mut [generator@$DIR/inline_generator.rs:15:5: 15:8]; // in scope 6 at $DIR/inline_generator.rs:15:5: 15:41 ++ } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/inline_generator.rs:+1:9: +1:11 + StorageLive(_2); // scope 0 at $DIR/inline_generator.rs:+1:14: +1:32 + StorageLive(_3); // scope 0 at $DIR/inline_generator.rs:+1:23: +1:31 + StorageLive(_4); // scope 0 at $DIR/inline_generator.rs:+1:28: +1:31 +- _4 = g() -> bb1; // scope 0 at $DIR/inline_generator.rs:+1:28: +1:31 +- // mir::Constant +- // + span: $DIR/inline_generator.rs:9:28: 9:29 +- // + literal: Const { ty: fn() -> impl Generator<bool> {g}, val: Value(<ZST>) } +- } +- +- bb1: { ++ Deinit(_4); // scope 2 at $DIR/inline_generator.rs:15:5: 15:41 ++ discriminant(_4) = 0; // scope 2 at $DIR/inline_generator.rs:15:5: 15:41 + _3 = &mut _4; // scope 0 at $DIR/inline_generator.rs:+1:23: +1:31 +- _2 = Pin::<&mut [generator@$DIR/inline_generator.rs:15:5: 15:8]>::new(move _3) -> [return: bb2, unwind: bb4]; // scope 0 at $DIR/inline_generator.rs:+1:14: +1:32 +- // mir::Constant +- // + span: $DIR/inline_generator.rs:9:14: 9:22 +- // + user_ty: UserType(0) +- // + literal: Const { ty: fn(&mut [generator@$DIR/inline_generator.rs:15:5: 15:8]) -> Pin<&mut [generator@$DIR/inline_generator.rs:15:5: 15:8]> {Pin::<&mut [generator@$DIR/inline_generator.rs:15:5: 15:8]>::new}, val: Value(<ZST>) } +- } +- +- bb2: { ++ StorageLive(_5); // scope 4 at $SRC_DIR/core/src/pin.rs:LL:COL ++ _5 = move _3; // scope 4 at $SRC_DIR/core/src/pin.rs:LL:COL ++ StorageLive(_6); // scope 5 at $SRC_DIR/core/src/pin.rs:LL:COL ++ _6 = move _5; // scope 5 at $SRC_DIR/core/src/pin.rs:LL:COL ++ Deinit(_2); // scope 5 at $SRC_DIR/core/src/pin.rs:LL:COL ++ (_2.0: &mut [generator@$DIR/inline_generator.rs:15:5: 15:8]) = move _6; // scope 5 at $SRC_DIR/core/src/pin.rs:LL:COL ++ StorageDead(_6); // scope 5 at $SRC_DIR/core/src/pin.rs:LL:COL ++ StorageDead(_5); // scope 4 at $SRC_DIR/core/src/pin.rs:LL:COL + StorageDead(_3); // scope 0 at $DIR/inline_generator.rs:+1:31: +1:32 +- _1 = <[generator@$DIR/inline_generator.rs:15:5: 15:8] as Generator<bool>>::resume(move _2, const false) -> [return: bb3, unwind: bb4]; // scope 0 at $DIR/inline_generator.rs:+1:14: +1:46 +- // mir::Constant +- // + span: $DIR/inline_generator.rs:9:33: 9:39 +- // + literal: Const { ty: for<'a> fn(Pin<&'a mut [generator@$DIR/inline_generator.rs:15:5: 15:8]>, bool) -> GeneratorState<<[generator@$DIR/inline_generator.rs:15:5: 15:8] as Generator<bool>>::Yield, <[generator@$DIR/inline_generator.rs:15:5: 15:8] as Generator<bool>>::Return> {<[generator@$DIR/inline_generator.rs:15:5: 15:8] as Generator<bool>>::resume}, val: Value(<ZST>) } ++ StorageLive(_7); // scope 0 at $DIR/inline_generator.rs:+1:33: +1:46 ++ _7 = const false; // scope 0 at $DIR/inline_generator.rs:+1:33: +1:46 ++ _10 = deref_copy (_2.0: &mut [generator@$DIR/inline_generator.rs:15:5: 15:8]); // scope 6 at $DIR/inline_generator.rs:15:5: 15:41 ++ _9 = discriminant((*_10)); // scope 6 at $DIR/inline_generator.rs:15:5: 15:41 ++ switchInt(move _9) -> [0: bb3, 1: bb8, 3: bb7, otherwise: bb9]; // scope 6 at $DIR/inline_generator.rs:15:5: 15:41 + } + +- bb3: { ++ bb1: { ++ StorageDead(_7); // scope 0 at $DIR/inline_generator.rs:+1:33: +1:46 + StorageDead(_2); // scope 0 at $DIR/inline_generator.rs:+1:45: +1:46 + StorageDead(_4); // scope 0 at $DIR/inline_generator.rs:+1:46: +1:47 + _0 = const (); // scope 0 at $DIR/inline_generator.rs:+0:11: +2:2 + StorageDead(_1); // scope 0 at $DIR/inline_generator.rs:+2:1: +2:2 + return; // scope 0 at $DIR/inline_generator.rs:+2:2: +2:2 + } + +- bb4 (cleanup): { ++ bb2 (cleanup): { + resume; // scope 0 at $DIR/inline_generator.rs:+0:1: +2:2 ++ } ++ ++ bb3: { ++ StorageLive(_8); // scope 6 at $DIR/inline_generator.rs:15:17: 15:39 ++ switchInt(move _7) -> [0: bb5, otherwise: bb4]; // scope 6 at $DIR/inline_generator.rs:15:20: 15:21 ++ } ++ ++ bb4: { ++ _8 = const 7_i32; // scope 6 at $DIR/inline_generator.rs:15:24: 15:25 ++ goto -> bb6; // scope 6 at $DIR/inline_generator.rs:15:17: 15:39 ++ } ++ ++ bb5: { ++ _8 = const 13_i32; // scope 6 at $DIR/inline_generator.rs:15:35: 15:37 ++ goto -> bb6; // scope 6 at $DIR/inline_generator.rs:15:17: 15:39 ++ } ++ ++ bb6: { ++ Deinit(_1); // scope 6 at $DIR/inline_generator.rs:15:11: 15:39 ++ ((_1 as Yielded).0: i32) = move _8; // scope 6 at $DIR/inline_generator.rs:15:11: 15:39 ++ discriminant(_1) = 0; // scope 6 at $DIR/inline_generator.rs:15:11: 15:39 ++ _11 = deref_copy (_2.0: &mut [generator@$DIR/inline_generator.rs:15:5: 15:8]); // scope 6 at $DIR/inline_generator.rs:15:11: 15:39 ++ discriminant((*_11)) = 3; // scope 6 at $DIR/inline_generator.rs:15:11: 15:39 ++ goto -> bb1; // scope 0 at $DIR/inline_generator.rs:15:11: 15:39 ++ } ++ ++ bb7: { ++ StorageLive(_8); // scope 6 at $DIR/inline_generator.rs:15:5: 15:41 ++ StorageDead(_8); // scope 6 at $DIR/inline_generator.rs:15:38: 15:39 ++ Deinit(_1); // scope 6 at $DIR/inline_generator.rs:15:41: 15:41 ++ ((_1 as Complete).0: bool) = move _7; // scope 6 at $DIR/inline_generator.rs:15:41: 15:41 ++ discriminant(_1) = 1; // scope 6 at $DIR/inline_generator.rs:15:41: 15:41 ++ _12 = deref_copy (_2.0: &mut [generator@$DIR/inline_generator.rs:15:5: 15:8]); // scope 6 at $DIR/inline_generator.rs:15:41: 15:41 ++ discriminant((*_12)) = 1; // scope 6 at $DIR/inline_generator.rs:15:41: 15:41 ++ goto -> bb1; // scope 0 at $DIR/inline_generator.rs:15:41: 15:41 ++ } ++ ++ bb8: { ++ assert(const false, "generator resumed after completion") -> [success: bb8, unwind: bb2]; // scope 6 at $DIR/inline_generator.rs:15:5: 15:41 ++ } ++ ++ bb9: { ++ unreachable; // scope 6 at $DIR/inline_generator.rs:15:5: 15:41 + } + } + diff --git a/tests/mir-opt/inline/inline_generator.rs b/tests/mir-opt/inline/inline_generator.rs new file mode 100644 index 000000000..d11b3e548 --- /dev/null +++ b/tests/mir-opt/inline/inline_generator.rs @@ -0,0 +1,16 @@ +// ignore-wasm32-bare compiled with panic=abort by default +#![feature(generators, generator_trait)] + +use std::ops::Generator; +use std::pin::Pin; + +// EMIT_MIR inline_generator.main.Inline.diff +fn main() { + let _r = Pin::new(&mut g()).resume(false); +} + +#[inline(always)] +pub fn g() -> impl Generator<bool> { + #[inline(always)] + |a| { yield if a { 7 } else { 13 } } +} diff --git a/tests/mir-opt/inline/inline_instruction_set.default.Inline.diff b/tests/mir-opt/inline/inline_instruction_set.default.Inline.diff new file mode 100644 index 000000000..f1988ea4b --- /dev/null +++ b/tests/mir-opt/inline/inline_instruction_set.default.Inline.diff @@ -0,0 +1,60 @@ +- // MIR for `default` before Inline ++ // MIR for `default` after Inline + + fn default() -> () { + let mut _0: (); // return place in scope 0 at $DIR/inline_instruction_set.rs:+0:18: +0:18 + let _1: (); // in scope 0 at $DIR/inline_instruction_set.rs:+1:5: +1:26 + let _2: (); // in scope 0 at $DIR/inline_instruction_set.rs:+2:5: +2:26 + let _3: (); // in scope 0 at $DIR/inline_instruction_set.rs:+3:5: +3:30 + let _4: (); // in scope 0 at $DIR/inline_instruction_set.rs:+4:5: +4:41 ++ scope 1 (inlined instruction_set_default) { // at $DIR/inline_instruction_set.rs:59:5: 59:30 ++ } ++ scope 2 (inlined inline_always_and_using_inline_asm) { // at $DIR/inline_instruction_set.rs:60:5: 60:41 ++ scope 3 { ++ } ++ } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/inline_instruction_set.rs:+1:5: +1:26 + _1 = instruction_set_a32() -> bb1; // scope 0 at $DIR/inline_instruction_set.rs:+1:5: +1:26 + // mir::Constant + // + span: $DIR/inline_instruction_set.rs:57:5: 57:24 + // + literal: Const { ty: fn() {instruction_set_a32}, val: Value(<ZST>) } + } + + bb1: { + StorageDead(_1); // scope 0 at $DIR/inline_instruction_set.rs:+1:26: +1:27 + StorageLive(_2); // scope 0 at $DIR/inline_instruction_set.rs:+2:5: +2:26 + _2 = instruction_set_t32() -> bb2; // scope 0 at $DIR/inline_instruction_set.rs:+2:5: +2:26 + // mir::Constant + // + span: $DIR/inline_instruction_set.rs:58:5: 58:24 + // + literal: Const { ty: fn() {instruction_set_t32}, val: Value(<ZST>) } + } + + bb2: { + StorageDead(_2); // scope 0 at $DIR/inline_instruction_set.rs:+2:26: +2:27 + StorageLive(_3); // scope 0 at $DIR/inline_instruction_set.rs:+3:5: +3:30 +- _3 = instruction_set_default() -> bb3; // scope 0 at $DIR/inline_instruction_set.rs:+3:5: +3:30 +- // mir::Constant +- // + span: $DIR/inline_instruction_set.rs:59:5: 59:28 +- // + literal: Const { ty: fn() {instruction_set_default}, val: Value(<ZST>) } +- } +- +- bb3: { + StorageDead(_3); // scope 0 at $DIR/inline_instruction_set.rs:+3:30: +3:31 + StorageLive(_4); // scope 0 at $DIR/inline_instruction_set.rs:+4:5: +4:41 +- _4 = inline_always_and_using_inline_asm() -> bb4; // scope 0 at $DIR/inline_instruction_set.rs:+4:5: +4:41 +- // mir::Constant +- // + span: $DIR/inline_instruction_set.rs:60:5: 60:39 +- // + literal: Const { ty: fn() {inline_always_and_using_inline_asm}, val: Value(<ZST>) } ++ asm!("/* do nothing */", options((empty))) -> bb3; // scope 3 at $DIR/inline_instruction_set.rs:43:14: 43:38 + } + +- bb4: { ++ bb3: { + StorageDead(_4); // scope 0 at $DIR/inline_instruction_set.rs:+4:41: +4:42 + _0 = const (); // scope 0 at $DIR/inline_instruction_set.rs:+0:18: +5:2 + return; // scope 0 at $DIR/inline_instruction_set.rs:+5:2: +5:2 + } + } + diff --git a/tests/mir-opt/inline/inline_instruction_set.rs b/tests/mir-opt/inline/inline_instruction_set.rs new file mode 100644 index 000000000..5dfb04943 --- /dev/null +++ b/tests/mir-opt/inline/inline_instruction_set.rs @@ -0,0 +1,61 @@ +// Checks that only functions with the compatible instruction_set attributes are inlined. +// +// A function is "compatible" when the *callee* has the same attribute or no attribute. +// +// compile-flags: --target thumbv4t-none-eabi +// needs-llvm-components: arm + +#![crate_type = "lib"] +#![feature(rustc_attrs)] +#![feature(no_core, lang_items)] +#![feature(isa_attribute)] +#![no_core] + +#[rustc_builtin_macro] +#[macro_export] +macro_rules! asm { + ("assembly template", + $(operands,)* + $(options($(option),*))? + ) => { + /* compiler built-in */ + }; +} + +#[lang = "sized"] +trait Sized {} +#[lang = "copy"] +trait Copy {} + +#[instruction_set(arm::a32)] +#[inline] +fn instruction_set_a32() {} + +#[instruction_set(arm::t32)] +#[inline] +fn instruction_set_t32() {} + +#[inline] +fn instruction_set_default() {} + +#[inline(always)] +fn inline_always_and_using_inline_asm() { + unsafe { asm!("/* do nothing */") }; +} + +// EMIT_MIR inline_instruction_set.t32.Inline.diff +#[instruction_set(arm::t32)] +pub fn t32() { + instruction_set_a32(); + instruction_set_t32(); + instruction_set_default(); + inline_always_and_using_inline_asm(); +} + +// EMIT_MIR inline_instruction_set.default.Inline.diff +pub fn default() { + instruction_set_a32(); + instruction_set_t32(); + instruction_set_default(); + inline_always_and_using_inline_asm(); +} diff --git a/tests/mir-opt/inline/inline_instruction_set.t32.Inline.diff b/tests/mir-opt/inline/inline_instruction_set.t32.Inline.diff new file mode 100644 index 000000000..e777b2cc2 --- /dev/null +++ b/tests/mir-opt/inline/inline_instruction_set.t32.Inline.diff @@ -0,0 +1,58 @@ +- // MIR for `t32` before Inline ++ // MIR for `t32` after Inline + + fn t32() -> () { + let mut _0: (); // return place in scope 0 at $DIR/inline_instruction_set.rs:+0:14: +0:14 + let _1: (); // in scope 0 at $DIR/inline_instruction_set.rs:+1:5: +1:26 + let _2: (); // in scope 0 at $DIR/inline_instruction_set.rs:+2:5: +2:26 + let _3: (); // in scope 0 at $DIR/inline_instruction_set.rs:+3:5: +3:30 + let _4: (); // in scope 0 at $DIR/inline_instruction_set.rs:+4:5: +4:41 ++ scope 1 (inlined instruction_set_t32) { // at $DIR/inline_instruction_set.rs:50:5: 50:26 ++ } ++ scope 2 (inlined instruction_set_default) { // at $DIR/inline_instruction_set.rs:51:5: 51:30 ++ } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/inline_instruction_set.rs:+1:5: +1:26 + _1 = instruction_set_a32() -> bb1; // scope 0 at $DIR/inline_instruction_set.rs:+1:5: +1:26 + // mir::Constant + // + span: $DIR/inline_instruction_set.rs:49:5: 49:24 + // + literal: Const { ty: fn() {instruction_set_a32}, val: Value(<ZST>) } + } + + bb1: { + StorageDead(_1); // scope 0 at $DIR/inline_instruction_set.rs:+1:26: +1:27 + StorageLive(_2); // scope 0 at $DIR/inline_instruction_set.rs:+2:5: +2:26 +- _2 = instruction_set_t32() -> bb2; // scope 0 at $DIR/inline_instruction_set.rs:+2:5: +2:26 +- // mir::Constant +- // + span: $DIR/inline_instruction_set.rs:50:5: 50:24 +- // + literal: Const { ty: fn() {instruction_set_t32}, val: Value(<ZST>) } +- } +- +- bb2: { + StorageDead(_2); // scope 0 at $DIR/inline_instruction_set.rs:+2:26: +2:27 + StorageLive(_3); // scope 0 at $DIR/inline_instruction_set.rs:+3:5: +3:30 +- _3 = instruction_set_default() -> bb3; // scope 0 at $DIR/inline_instruction_set.rs:+3:5: +3:30 +- // mir::Constant +- // + span: $DIR/inline_instruction_set.rs:51:5: 51:28 +- // + literal: Const { ty: fn() {instruction_set_default}, val: Value(<ZST>) } +- } +- +- bb3: { + StorageDead(_3); // scope 0 at $DIR/inline_instruction_set.rs:+3:30: +3:31 + StorageLive(_4); // scope 0 at $DIR/inline_instruction_set.rs:+4:5: +4:41 +- _4 = inline_always_and_using_inline_asm() -> bb4; // scope 0 at $DIR/inline_instruction_set.rs:+4:5: +4:41 ++ _4 = inline_always_and_using_inline_asm() -> bb2; // scope 0 at $DIR/inline_instruction_set.rs:+4:5: +4:41 + // mir::Constant + // + span: $DIR/inline_instruction_set.rs:52:5: 52:39 + // + literal: Const { ty: fn() {inline_always_and_using_inline_asm}, val: Value(<ZST>) } + } + +- bb4: { ++ bb2: { + StorageDead(_4); // scope 0 at $DIR/inline_instruction_set.rs:+4:41: +4:42 + _0 = const (); // scope 0 at $DIR/inline_instruction_set.rs:+0:14: +5:2 + return; // scope 0 at $DIR/inline_instruction_set.rs:+5:2: +5:2 + } + } + diff --git a/tests/mir-opt/inline/inline_into_box_place.main.Inline.diff b/tests/mir-opt/inline/inline_into_box_place.main.Inline.diff new file mode 100644 index 000000000..a28da146e --- /dev/null +++ b/tests/mir-opt/inline/inline_into_box_place.main.Inline.diff @@ -0,0 +1,86 @@ +- // MIR for `main` before Inline ++ // MIR for `main` after Inline + + fn main() -> () { + let mut _0: (); // return place in scope 0 at $DIR/inline_into_box_place.rs:+0:11: +0:11 + let _1: std::boxed::Box<std::vec::Vec<u32>>; // in scope 0 at $DIR/inline_into_box_place.rs:+1:9: +1:11 + let mut _2: usize; // in scope 0 at $DIR/inline_into_box_place.rs:+1:29: +1:43 + let mut _3: usize; // in scope 0 at $DIR/inline_into_box_place.rs:+1:29: +1:43 + let mut _4: *mut u8; // in scope 0 at $DIR/inline_into_box_place.rs:+1:29: +1:43 + let mut _5: std::boxed::Box<std::vec::Vec<u32>>; // in scope 0 at $DIR/inline_into_box_place.rs:+1:29: +1:43 + let mut _6: (); // in scope 0 at $DIR/inline_into_box_place.rs:+1:42: +1:43 + let mut _7: *const std::vec::Vec<u32>; // in scope 0 at $DIR/inline_into_box_place.rs:+1:29: +1:43 ++ let mut _8: &mut std::vec::Vec<u32>; // in scope 0 at $DIR/inline_into_box_place.rs:+1:33: +1:43 ++ let mut _9: std::vec::Vec<u32>; // in scope 0 at $DIR/inline_into_box_place.rs:+1:33: +1:43 + scope 1 { + debug _x => _1; // in scope 1 at $DIR/inline_into_box_place.rs:+1:9: +1:11 + } + scope 2 { + } ++ scope 3 (inlined Vec::<u32>::new) { // at $DIR/inline_into_box_place.rs:8:33: 8:43 ++ let mut _10: alloc::raw_vec::RawVec<u32>; // in scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL ++ } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/inline_into_box_place.rs:+1:9: +1:11 + _2 = SizeOf(std::vec::Vec<u32>); // scope 2 at $DIR/inline_into_box_place.rs:+1:29: +1:43 + _3 = AlignOf(std::vec::Vec<u32>); // scope 2 at $DIR/inline_into_box_place.rs:+1:29: +1:43 + _4 = alloc::alloc::exchange_malloc(move _2, move _3) -> bb1; // scope 2 at $DIR/inline_into_box_place.rs:+1:29: +1:43 + // mir::Constant + // + span: $DIR/inline_into_box_place.rs:8:29: 8:43 + // + literal: Const { ty: unsafe fn(usize, usize) -> *mut u8 {alloc::alloc::exchange_malloc}, val: Value(<ZST>) } + } + + bb1: { + StorageLive(_5); // scope 0 at $DIR/inline_into_box_place.rs:+1:29: +1:43 + _5 = ShallowInitBox(move _4, std::vec::Vec<u32>); // scope 0 at $DIR/inline_into_box_place.rs:+1:29: +1:43 + _7 = (((_5.0: std::ptr::Unique<std::vec::Vec<u32>>).0: std::ptr::NonNull<std::vec::Vec<u32>>).0: *const std::vec::Vec<u32>); // scope 0 at $DIR/inline_into_box_place.rs:+1:33: +1:43 +- (*_7) = Vec::<u32>::new() -> [return: bb2, unwind: bb5]; // scope 0 at $DIR/inline_into_box_place.rs:+1:33: +1:43 ++ StorageLive(_8); // scope 0 at $DIR/inline_into_box_place.rs:+1:33: +1:43 ++ _8 = &mut (*_7); // scope 0 at $DIR/inline_into_box_place.rs:+1:33: +1:43 ++ StorageLive(_9); // scope 0 at $DIR/inline_into_box_place.rs:+1:33: +1:43 ++ StorageLive(_10); // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL ++ _10 = const _; // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL + // mir::Constant +- // + span: $DIR/inline_into_box_place.rs:8:33: 8:41 +- // + user_ty: UserType(1) +- // + literal: Const { ty: fn() -> Vec<u32> {Vec::<u32>::new}, val: Value(<ZST>) } +- } +- +- bb2: { ++ // + span: $SRC_DIR/alloc/src/vec/mod.rs:LL:COL ++ // + user_ty: UserType(0) ++ // + literal: Const { ty: alloc::raw_vec::RawVec<u32>, val: Unevaluated(alloc::raw_vec::RawVec::<T>::NEW, [u32], None) } ++ Deinit(_9); // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL ++ (_9.0: alloc::raw_vec::RawVec<u32>) = move _10; // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL ++ (_9.1: usize) = const 0_usize; // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL ++ StorageDead(_10); // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL ++ (*_8) = move _9; // scope 0 at $DIR/inline_into_box_place.rs:+1:33: +1:43 ++ StorageDead(_9); // scope 0 at $DIR/inline_into_box_place.rs:+1:33: +1:43 ++ StorageDead(_8); // scope 0 at $DIR/inline_into_box_place.rs:+1:33: +1:43 + _1 = move _5; // scope 0 at $DIR/inline_into_box_place.rs:+1:29: +1:43 + StorageDead(_5); // scope 0 at $DIR/inline_into_box_place.rs:+1:42: +1:43 + _0 = const (); // scope 0 at $DIR/inline_into_box_place.rs:+0:11: +2:2 +- drop(_1) -> [return: bb3, unwind: bb4]; // scope 0 at $DIR/inline_into_box_place.rs:+2:1: +2:2 ++ drop(_1) -> [return: bb2, unwind: bb3]; // scope 0 at $DIR/inline_into_box_place.rs:+2:1: +2:2 + } + +- bb3: { ++ bb2: { + StorageDead(_1); // scope 0 at $DIR/inline_into_box_place.rs:+2:1: +2:2 + return; // scope 0 at $DIR/inline_into_box_place.rs:+2:2: +2:2 + } + +- bb4 (cleanup): { ++ bb3 (cleanup): { + resume; // scope 0 at $DIR/inline_into_box_place.rs:+0:1: +2:2 +- } +- +- bb5 (cleanup): { +- _6 = alloc::alloc::box_free::<Vec<u32>, std::alloc::Global>(move (_5.0: std::ptr::Unique<std::vec::Vec<u32>>), move (_5.1: std::alloc::Global)) -> bb4; // scope 0 at $DIR/inline_into_box_place.rs:+1:42: +1:43 +- // mir::Constant +- // + span: $DIR/inline_into_box_place.rs:8:42: 8:43 +- // + literal: Const { ty: unsafe fn(Unique<Vec<u32>>, std::alloc::Global) {alloc::alloc::box_free::<Vec<u32>, std::alloc::Global>}, val: Value(<ZST>) } + } + } + diff --git a/tests/mir-opt/inline/inline_into_box_place.rs b/tests/mir-opt/inline/inline_into_box_place.rs new file mode 100644 index 000000000..232bcc7b2 --- /dev/null +++ b/tests/mir-opt/inline/inline_into_box_place.rs @@ -0,0 +1,9 @@ +// ignore-endian-big +// ignore-wasm32-bare compiled with panic=abort by default +// compile-flags: -Z mir-opt-level=4 + +#![feature(box_syntax)] +// EMIT_MIR inline_into_box_place.main.Inline.diff +fn main() { + let _x: Box<Vec<u32>> = box Vec::new(); +} diff --git a/tests/mir-opt/inline/inline_options.main.Inline.after.mir b/tests/mir-opt/inline/inline_options.main.Inline.after.mir new file mode 100644 index 000000000..1c590be94 --- /dev/null +++ b/tests/mir-opt/inline/inline_options.main.Inline.after.mir @@ -0,0 +1,55 @@ +// MIR for `main` after Inline + +fn main() -> () { + let mut _0: (); // return place in scope 0 at $DIR/inline_options.rs:+0:11: +0:11 + let _1: (); // in scope 0 at $DIR/inline_options.rs:+1:5: +1:18 + let _2: (); // in scope 0 at $DIR/inline_options.rs:+2:5: +2:21 + scope 1 (inlined inlined::<u32>) { // at $DIR/inline_options.rs:10:5: 10:21 + let _3: (); // in scope 1 at $DIR/inline_options.rs:16:23: 16:26 + let _4: (); // in scope 1 at $DIR/inline_options.rs:16:28: 16:31 + let _5: (); // in scope 1 at $DIR/inline_options.rs:16:33: 16:36 + } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/inline_options.rs:+1:5: +1:18 + _1 = not_inlined() -> bb1; // scope 0 at $DIR/inline_options.rs:+1:5: +1:18 + // mir::Constant + // + span: $DIR/inline_options.rs:9:5: 9:16 + // + literal: Const { ty: fn() {not_inlined}, val: Value(<ZST>) } + } + + bb1: { + StorageDead(_1); // scope 0 at $DIR/inline_options.rs:+1:18: +1:19 + StorageLive(_2); // scope 0 at $DIR/inline_options.rs:+2:5: +2:21 + StorageLive(_3); // scope 1 at $DIR/inline_options.rs:16:23: 16:26 + _3 = g() -> bb2; // scope 1 at $DIR/inline_options.rs:16:23: 16:26 + // mir::Constant + // + span: $DIR/inline_options.rs:16:23: 16:24 + // + literal: Const { ty: fn() {g}, val: Value(<ZST>) } + } + + bb2: { + StorageDead(_3); // scope 1 at $DIR/inline_options.rs:16:26: 16:27 + StorageLive(_4); // scope 1 at $DIR/inline_options.rs:16:28: 16:31 + _4 = g() -> bb3; // scope 1 at $DIR/inline_options.rs:16:28: 16:31 + // mir::Constant + // + span: $DIR/inline_options.rs:16:28: 16:29 + // + literal: Const { ty: fn() {g}, val: Value(<ZST>) } + } + + bb3: { + StorageDead(_4); // scope 1 at $DIR/inline_options.rs:16:31: 16:32 + StorageLive(_5); // scope 1 at $DIR/inline_options.rs:16:33: 16:36 + _5 = g() -> bb4; // scope 1 at $DIR/inline_options.rs:16:33: 16:36 + // mir::Constant + // + span: $DIR/inline_options.rs:16:33: 16:34 + // + literal: Const { ty: fn() {g}, val: Value(<ZST>) } + } + + bb4: { + StorageDead(_5); // scope 1 at $DIR/inline_options.rs:16:36: 16:37 + StorageDead(_2); // scope 0 at $DIR/inline_options.rs:+2:21: +2:22 + _0 = const (); // scope 0 at $DIR/inline_options.rs:+0:11: +3:2 + return; // scope 0 at $DIR/inline_options.rs:+3:2: +3:2 + } +} diff --git a/tests/mir-opt/inline/inline_options.rs b/tests/mir-opt/inline/inline_options.rs new file mode 100644 index 000000000..477f050b6 --- /dev/null +++ b/tests/mir-opt/inline/inline_options.rs @@ -0,0 +1,19 @@ +// Checks that inlining threshold can be controlled with +// inline-mir-threshold and inline-hint-threshold options. +// +// compile-flags: -Zinline-mir-threshold=90 +// compile-flags: -Zinline-mir-hint-threshold=50 + +// EMIT_MIR inline_options.main.Inline.after.mir +fn main() { + not_inlined(); + inlined::<u32>(); +} + +// Cost is approximately 3 * 25 + 5 = 80. +#[inline] +pub fn not_inlined() { g(); g(); g(); } +pub fn inlined<T>() { g(); g(); g(); } + +#[inline(never)] +fn g() {} diff --git a/tests/mir-opt/inline/inline_retag.bar.Inline.after.mir b/tests/mir-opt/inline/inline_retag.bar.Inline.after.mir new file mode 100644 index 000000000..60149ff36 --- /dev/null +++ b/tests/mir-opt/inline/inline_retag.bar.Inline.after.mir @@ -0,0 +1,68 @@ +// MIR for `bar` after Inline + +fn bar() -> bool { + let mut _0: bool; // return place in scope 0 at $DIR/inline_retag.rs:+0:13: +0:17 + let _1: for<'a, 'b> fn(&'a i32, &'b i32) -> bool {foo}; // in scope 0 at $DIR/inline_retag.rs:+1:9: +1:10 + let mut _2: for<'a, 'b> fn(&'a i32, &'b i32) -> bool {foo}; // in scope 0 at $DIR/inline_retag.rs:+2:5: +2:6 + let mut _3: &i32; // in scope 0 at $DIR/inline_retag.rs:+2:7: +2:9 + let _4: &i32; // in scope 0 at $DIR/inline_retag.rs:+2:7: +2:9 + let _5: i32; // in scope 0 at $DIR/inline_retag.rs:+2:8: +2:9 + let mut _6: &i32; // in scope 0 at $DIR/inline_retag.rs:+2:11: +2:14 + let _7: &i32; // in scope 0 at $DIR/inline_retag.rs:+2:11: +2:14 + let _8: i32; // in scope 0 at $DIR/inline_retag.rs:+2:12: +2:14 + scope 1 { + debug f => _1; // in scope 1 at $DIR/inline_retag.rs:+1:9: +1:10 + let mut _9: &i32; // in scope 1 at $DIR/inline_retag.rs:+2:11: +2:14 + let mut _10: &i32; // in scope 1 at $DIR/inline_retag.rs:+2:7: +2:9 + scope 2 (inlined foo) { // at $DIR/inline_retag.rs:12:5: 12:15 + debug x => _3; // in scope 2 at $DIR/inline_retag.rs:16:8: 16:9 + debug y => _6; // in scope 2 at $DIR/inline_retag.rs:16:17: 16:18 + let mut _11: i32; // in scope 2 at $DIR/inline_retag.rs:17:5: 17:7 + let mut _12: i32; // in scope 2 at $DIR/inline_retag.rs:17:11: 17:13 + } + } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/inline_retag.rs:+1:9: +1:10 + _1 = foo; // scope 0 at $DIR/inline_retag.rs:+1:13: +1:16 + // mir::Constant + // + span: $DIR/inline_retag.rs:11:13: 11:16 + // + literal: Const { ty: for<'a, 'b> fn(&'a i32, &'b i32) -> bool {foo}, val: Value(<ZST>) } + StorageLive(_2); // scope 1 at $DIR/inline_retag.rs:+2:5: +2:6 + _2 = _1; // scope 1 at $DIR/inline_retag.rs:+2:5: +2:6 + StorageLive(_3); // scope 1 at $DIR/inline_retag.rs:+2:7: +2:9 + StorageLive(_4); // scope 1 at $DIR/inline_retag.rs:+2:7: +2:9 + _10 = const _; // scope 1 at $DIR/inline_retag.rs:+2:7: +2:9 + // mir::Constant + // + span: $DIR/inline_retag.rs:12:7: 12:9 + // + literal: Const { ty: &i32, val: Unevaluated(bar, [], Some(promoted[1])) } + Retag(_10); // scope 1 at $DIR/inline_retag.rs:+2:7: +2:9 + _4 = &(*_10); // scope 1 at $DIR/inline_retag.rs:+2:7: +2:9 + _3 = &(*_4); // scope 1 at $DIR/inline_retag.rs:+2:7: +2:9 + StorageLive(_6); // scope 1 at $DIR/inline_retag.rs:+2:11: +2:14 + StorageLive(_7); // scope 1 at $DIR/inline_retag.rs:+2:11: +2:14 + _9 = const _; // scope 1 at $DIR/inline_retag.rs:+2:11: +2:14 + // mir::Constant + // + span: $DIR/inline_retag.rs:12:11: 12:14 + // + literal: Const { ty: &i32, val: Unevaluated(bar, [], Some(promoted[0])) } + Retag(_9); // scope 1 at $DIR/inline_retag.rs:+2:11: +2:14 + _7 = &(*_9); // scope 1 at $DIR/inline_retag.rs:+2:11: +2:14 + _6 = &(*_7); // scope 1 at $DIR/inline_retag.rs:+2:11: +2:14 + Retag(_3); // scope 2 at $DIR/inline_retag.rs:16:8: 16:9 + Retag(_6); // scope 2 at $DIR/inline_retag.rs:16:17: 16:18 + StorageLive(_11); // scope 2 at $DIR/inline_retag.rs:17:5: 17:7 + _11 = (*_3); // scope 2 at $DIR/inline_retag.rs:17:5: 17:7 + StorageLive(_12); // scope 2 at $DIR/inline_retag.rs:17:11: 17:13 + _12 = (*_6); // scope 2 at $DIR/inline_retag.rs:17:11: 17:13 + _0 = Eq(move _11, move _12); // scope 2 at $DIR/inline_retag.rs:17:5: 17:13 + StorageDead(_12); // scope 2 at $DIR/inline_retag.rs:17:12: 17:13 + StorageDead(_11); // scope 2 at $DIR/inline_retag.rs:17:12: 17:13 + StorageDead(_6); // scope 1 at $DIR/inline_retag.rs:+2:14: +2:15 + StorageDead(_3); // scope 1 at $DIR/inline_retag.rs:+2:14: +2:15 + StorageDead(_2); // scope 1 at $DIR/inline_retag.rs:+2:14: +2:15 + StorageDead(_1); // scope 0 at $DIR/inline_retag.rs:+3:1: +3:2 + StorageDead(_7); // scope 0 at $DIR/inline_retag.rs:+3:1: +3:2 + StorageDead(_4); // scope 0 at $DIR/inline_retag.rs:+3:1: +3:2 + return; // scope 0 at $DIR/inline_retag.rs:+3:2: +3:2 + } +} diff --git a/tests/mir-opt/inline/inline_retag.rs b/tests/mir-opt/inline/inline_retag.rs new file mode 100644 index 000000000..c6950f269 --- /dev/null +++ b/tests/mir-opt/inline/inline_retag.rs @@ -0,0 +1,18 @@ +// compile-flags: -Z span_free_formats -Z mir-emit-retag + +// Tests that MIR inliner fixes up `Retag`'s `fn_entry` flag + +fn main() { + println!("{}", bar()); +} + +// EMIT_MIR inline_retag.bar.Inline.after.mir +fn bar() -> bool { + let f = foo; + f(&1, &-1) +} + +#[inline(always)] +fn foo(x: &i32, y: &i32) -> bool { + *x == *y +} diff --git a/tests/mir-opt/inline/inline_shims.clone.Inline.diff b/tests/mir-opt/inline/inline_shims.clone.Inline.diff new file mode 100644 index 000000000..09dd35c4c --- /dev/null +++ b/tests/mir-opt/inline/inline_shims.clone.Inline.diff @@ -0,0 +1,26 @@ +- // MIR for `clone` before Inline ++ // MIR for `clone` after Inline + + fn clone(_1: fn(A, B)) -> fn(A, B) { + debug f => _1; // in scope 0 at $DIR/inline_shims.rs:+0:20: +0:21 + let mut _0: fn(A, B); // return place in scope 0 at $DIR/inline_shims.rs:+0:36: +0:44 + let mut _2: &fn(A, B); // in scope 0 at $DIR/inline_shims.rs:+1:5: +1:14 ++ scope 1 (inlined <fn(A, B) as Clone>::clone - shim(fn(A, B))) { // at $DIR/inline_shims.rs:6:7: 6:14 ++ } + + bb0: { + StorageLive(_2); // scope 0 at $DIR/inline_shims.rs:+1:5: +1:14 + _2 = &_1; // scope 0 at $DIR/inline_shims.rs:+1:5: +1:14 +- _0 = <fn(A, B) as Clone>::clone(move _2) -> bb1; // scope 0 at $DIR/inline_shims.rs:+1:5: +1:14 +- // mir::Constant +- // + span: $DIR/inline_shims.rs:6:7: 6:12 +- // + literal: Const { ty: for<'a> fn(&'a fn(A, B)) -> fn(A, B) {<fn(A, B) as Clone>::clone}, val: Value(<ZST>) } +- } +- +- bb1: { ++ _0 = (*_2); // scope 1 at $SRC_DIR/core/src/clone.rs:LL:COL + StorageDead(_2); // scope 0 at $DIR/inline_shims.rs:+1:13: +1:14 + return; // scope 0 at $DIR/inline_shims.rs:+2:2: +2:2 + } + } + diff --git a/tests/mir-opt/inline/inline_shims.drop.Inline.diff b/tests/mir-opt/inline/inline_shims.drop.Inline.diff new file mode 100644 index 000000000..36ddb189e --- /dev/null +++ b/tests/mir-opt/inline/inline_shims.drop.Inline.diff @@ -0,0 +1,56 @@ +- // MIR for `drop` before Inline ++ // MIR for `drop` after Inline + + fn drop(_1: *mut Vec<A>, _2: *mut Option<B>) -> () { + debug a => _1; // in scope 0 at $DIR/inline_shims.rs:+0:19: +0:20 + debug b => _2; // in scope 0 at $DIR/inline_shims.rs:+0:35: +0:36 + let mut _0: (); // return place in scope 0 at $DIR/inline_shims.rs:+0:54: +0:54 + let _3: (); // in scope 0 at $DIR/inline_shims.rs:+1:14: +1:40 + let mut _4: *mut std::vec::Vec<A>; // in scope 0 at $DIR/inline_shims.rs:+1:38: +1:39 + let mut _5: *mut std::option::Option<B>; // in scope 0 at $DIR/inline_shims.rs:+2:38: +2:39 + scope 1 { + } + scope 2 { ++ scope 3 (inlined std::ptr::drop_in_place::<Option<B>> - shim(Some(Option<B>))) { // at $DIR/inline_shims.rs:12:14: 12:40 ++ let mut _6: isize; // in scope 3 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL ++ let mut _7: isize; // in scope 3 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL ++ } + } + + bb0: { + StorageLive(_3); // scope 0 at $DIR/inline_shims.rs:+1:5: +1:42 + StorageLive(_4); // scope 1 at $DIR/inline_shims.rs:+1:38: +1:39 + _4 = _1; // scope 1 at $DIR/inline_shims.rs:+1:38: +1:39 + _3 = std::ptr::drop_in_place::<Vec<A>>(move _4) -> bb1; // scope 1 at $DIR/inline_shims.rs:+1:14: +1:40 + // mir::Constant + // + span: $DIR/inline_shims.rs:11:14: 11:37 + // + literal: Const { ty: unsafe fn(*mut Vec<A>) {std::ptr::drop_in_place::<Vec<A>>}, val: Value(<ZST>) } + } + + bb1: { + StorageDead(_4); // scope 1 at $DIR/inline_shims.rs:+1:39: +1:40 + StorageDead(_3); // scope 0 at $DIR/inline_shims.rs:+1:41: +1:42 + StorageLive(_5); // scope 2 at $DIR/inline_shims.rs:+2:38: +2:39 + _5 = _2; // scope 2 at $DIR/inline_shims.rs:+2:38: +2:39 +- _0 = std::ptr::drop_in_place::<Option<B>>(move _5) -> bb2; // scope 2 at $DIR/inline_shims.rs:+2:14: +2:40 +- // mir::Constant +- // + span: $DIR/inline_shims.rs:12:14: 12:37 +- // + literal: Const { ty: unsafe fn(*mut Option<B>) {std::ptr::drop_in_place::<Option<B>>}, val: Value(<ZST>) } ++ StorageLive(_6); // scope 2 at $DIR/inline_shims.rs:+2:14: +2:40 ++ StorageLive(_7); // scope 2 at $DIR/inline_shims.rs:+2:14: +2:40 ++ _6 = discriminant((*_5)); // scope 3 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL ++ switchInt(move _6) -> [0: bb2, otherwise: bb3]; // scope 3 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL + } + + bb2: { ++ StorageDead(_7); // scope 2 at $DIR/inline_shims.rs:+2:14: +2:40 ++ StorageDead(_6); // scope 2 at $DIR/inline_shims.rs:+2:14: +2:40 + StorageDead(_5); // scope 2 at $DIR/inline_shims.rs:+2:39: +2:40 + return; // scope 0 at $DIR/inline_shims.rs:+3:2: +3:2 ++ } ++ ++ bb3: { ++ drop((((*_5) as Some).0: B)) -> bb2; // scope 3 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL + } + } + diff --git a/tests/mir-opt/inline/inline_shims.rs b/tests/mir-opt/inline/inline_shims.rs new file mode 100644 index 000000000..7c8618f71 --- /dev/null +++ b/tests/mir-opt/inline/inline_shims.rs @@ -0,0 +1,13 @@ +// ignore-wasm32-bare compiled with panic=abort by default +#![crate_type = "lib"] + +// EMIT_MIR inline_shims.clone.Inline.diff +pub fn clone<A, B>(f: fn(A, B)) -> fn(A, B) { + f.clone() +} + +// EMIT_MIR inline_shims.drop.Inline.diff +pub fn drop<A, B>(a: *mut Vec<A>, b: *mut Option<B>) { + unsafe { std::ptr::drop_in_place(a) } + unsafe { std::ptr::drop_in_place(b) } +} diff --git a/tests/mir-opt/inline/inline_specialization.main.Inline.diff b/tests/mir-opt/inline/inline_specialization.main.Inline.diff new file mode 100644 index 000000000..af08296ed --- /dev/null +++ b/tests/mir-opt/inline/inline_specialization.main.Inline.diff @@ -0,0 +1,28 @@ +- // MIR for `main` before Inline ++ // MIR for `main` after Inline + + fn main() -> () { + let mut _0: (); // return place in scope 0 at $DIR/inline_specialization.rs:+0:11: +0:11 + let _1: u32; // in scope 0 at $DIR/inline_specialization.rs:+1:9: +1:10 + scope 1 { + debug x => _1; // in scope 1 at $DIR/inline_specialization.rs:+1:9: +1:10 + } ++ scope 2 (inlined <Vec<()> as Foo>::bar) { // at $DIR/inline_specialization.rs:5:13: 5:38 ++ } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/inline_specialization.rs:+1:9: +1:10 +- _1 = <Vec<()> as Foo>::bar() -> bb1; // scope 0 at $DIR/inline_specialization.rs:+1:13: +1:38 +- // mir::Constant +- // + span: $DIR/inline_specialization.rs:5:13: 5:36 +- // + literal: Const { ty: fn() -> u32 {<Vec<()> as Foo>::bar}, val: Value(<ZST>) } +- } +- +- bb1: { ++ _1 = const 123_u32; // scope 2 at $DIR/inline_specialization.rs:14:31: 14:34 + _0 = const (); // scope 0 at $DIR/inline_specialization.rs:+0:11: +2:2 + StorageDead(_1); // scope 0 at $DIR/inline_specialization.rs:+2:1: +2:2 + return; // scope 0 at $DIR/inline_specialization.rs:+2:2: +2:2 + } + } + diff --git a/tests/mir-opt/inline/inline_specialization.rs b/tests/mir-opt/inline/inline_specialization.rs new file mode 100644 index 000000000..87275b4e5 --- /dev/null +++ b/tests/mir-opt/inline/inline_specialization.rs @@ -0,0 +1,15 @@ +#![feature(specialization)] + +// EMIT_MIR inline_specialization.main.Inline.diff +fn main() { + let x = <Vec::<()> as Foo>::bar(); +} + +trait Foo { + fn bar() -> u32; +} + +impl<T> Foo for Vec<T> { + #[inline(always)] + default fn bar() -> u32 { 123 } +} diff --git a/tests/mir-opt/inline/inline_trait_method.rs b/tests/mir-opt/inline/inline_trait_method.rs new file mode 100644 index 000000000..74be53f55 --- /dev/null +++ b/tests/mir-opt/inline/inline_trait_method.rs @@ -0,0 +1,22 @@ +// compile-flags: -Z span_free_formats + +fn main() { + println!("{}", test(&())); +} + +// EMIT_MIR inline_trait_method.test.Inline.after.mir +fn test(x: &dyn X) -> u32 { + x.y() +} + +trait X { + fn y(&self) -> u32 { + 1 + } +} + +impl X for () { + fn y(&self) -> u32 { + 2 + } +} diff --git a/tests/mir-opt/inline/inline_trait_method.test.Inline.after.mir b/tests/mir-opt/inline/inline_trait_method.test.Inline.after.mir new file mode 100644 index 000000000..637bf282a --- /dev/null +++ b/tests/mir-opt/inline/inline_trait_method.test.Inline.after.mir @@ -0,0 +1,21 @@ +// MIR for `test` after Inline + +fn test(_1: &dyn X) -> u32 { + debug x => _1; // in scope 0 at $DIR/inline_trait_method.rs:+0:9: +0:10 + let mut _0: u32; // return place in scope 0 at $DIR/inline_trait_method.rs:+0:23: +0:26 + let mut _2: &dyn X; // in scope 0 at $DIR/inline_trait_method.rs:+1:5: +1:10 + + bb0: { + StorageLive(_2); // scope 0 at $DIR/inline_trait_method.rs:+1:5: +1:10 + _2 = &(*_1); // scope 0 at $DIR/inline_trait_method.rs:+1:5: +1:10 + _0 = <dyn X as X>::y(move _2) -> bb1; // scope 0 at $DIR/inline_trait_method.rs:+1:5: +1:10 + // mir::Constant + // + span: $DIR/inline_trait_method.rs:9:7: 9:8 + // + literal: Const { ty: for<'a> fn(&'a dyn X) -> u32 {<dyn X as X>::y}, val: Value(<ZST>) } + } + + bb1: { + StorageDead(_2); // scope 0 at $DIR/inline_trait_method.rs:+1:9: +1:10 + return; // scope 0 at $DIR/inline_trait_method.rs:+2:2: +2:2 + } +} diff --git a/tests/mir-opt/inline/inline_trait_method_2.rs b/tests/mir-opt/inline/inline_trait_method_2.rs new file mode 100644 index 000000000..378e71a25 --- /dev/null +++ b/tests/mir-opt/inline/inline_trait_method_2.rs @@ -0,0 +1,27 @@ +// compile-flags: -Z span_free_formats -Z mir-opt-level=4 + +// EMIT_MIR inline_trait_method_2.test2.Inline.after.mir +fn test2(x: &dyn X) -> bool { + test(x) +} + +#[inline] +fn test(x: &dyn X) -> bool { + x.y() +} + +trait X { + fn y(&self) -> bool { + false + } +} + +impl X for () { + fn y(&self) -> bool { + true + } +} + +fn main() { + println!("Should be true: {}", test2(&())); +} diff --git a/tests/mir-opt/inline/inline_trait_method_2.test2.Inline.after.mir b/tests/mir-opt/inline/inline_trait_method_2.test2.Inline.after.mir new file mode 100644 index 000000000..73aea719e --- /dev/null +++ b/tests/mir-opt/inline/inline_trait_method_2.test2.Inline.after.mir @@ -0,0 +1,28 @@ +// MIR for `test2` after Inline + +fn test2(_1: &dyn X) -> bool { + debug x => _1; // in scope 0 at $DIR/inline_trait_method_2.rs:+0:10: +0:11 + let mut _0: bool; // return place in scope 0 at $DIR/inline_trait_method_2.rs:+0:24: +0:28 + let mut _2: &dyn X; // in scope 0 at $DIR/inline_trait_method_2.rs:+1:10: +1:11 + let mut _3: &dyn X; // in scope 0 at $DIR/inline_trait_method_2.rs:+1:10: +1:11 + scope 1 (inlined test) { // at $DIR/inline_trait_method_2.rs:5:5: 5:12 + debug x => _2; // in scope 1 at $DIR/inline_trait_method_2.rs:9:9: 9:10 + } + + bb0: { + StorageLive(_2); // scope 0 at $DIR/inline_trait_method_2.rs:+1:10: +1:11 + StorageLive(_3); // scope 0 at $DIR/inline_trait_method_2.rs:+1:10: +1:11 + _3 = &(*_1); // scope 0 at $DIR/inline_trait_method_2.rs:+1:10: +1:11 + _2 = move _3 as &dyn X (Pointer(Unsize)); // scope 0 at $DIR/inline_trait_method_2.rs:+1:10: +1:11 + StorageDead(_3); // scope 0 at $DIR/inline_trait_method_2.rs:+1:10: +1:11 + _0 = <dyn X as X>::y(move _2) -> bb1; // scope 1 at $DIR/inline_trait_method_2.rs:10:5: 10:10 + // mir::Constant + // + span: $DIR/inline_trait_method_2.rs:10:7: 10:8 + // + literal: Const { ty: for<'a> fn(&'a dyn X) -> bool {<dyn X as X>::y}, val: Value(<ZST>) } + } + + bb1: { + StorageDead(_2); // scope 0 at $DIR/inline_trait_method_2.rs:+1:11: +1:12 + return; // scope 0 at $DIR/inline_trait_method_2.rs:+2:2: +2:2 + } +} diff --git a/tests/mir-opt/inline/issue_106141.outer.Inline.diff b/tests/mir-opt/inline/issue_106141.outer.Inline.diff new file mode 100644 index 000000000..97361fa5f --- /dev/null +++ b/tests/mir-opt/inline/issue_106141.outer.Inline.diff @@ -0,0 +1,55 @@ +- // MIR for `outer` before Inline ++ // MIR for `outer` after Inline + + fn outer() -> usize { + let mut _0: usize; // return place in scope 0 at $DIR/issue_106141.rs:+0:19: +0:24 ++ scope 1 (inlined inner) { // at $DIR/issue_106141.rs:2:5: 2:12 ++ let mut _1: bool; // in scope 1 at $DIR/issue_106141.rs:13:8: 13:21 ++ let mut _2: bool; // in scope 1 at $DIR/issue_106141.rs:13:8: 13:21 ++ let mut _3: &[bool; 1]; // in scope 1 at $DIR/issue_106141.rs:11:18: 11:25 ++ scope 2 { ++ debug buffer => _3; // in scope 2 at $DIR/issue_106141.rs:11:9: 11:15 ++ scope 3 { ++ debug index => _0; // in scope 3 at $DIR/issue_106141.rs:12:9: 12:14 ++ } ++ } ++ } + + bb0: { +- _0 = inner() -> bb1; // scope 0 at $DIR/issue_106141.rs:+1:5: +1:12 ++ StorageLive(_3); // scope 0 at $DIR/issue_106141.rs:+1:5: +1:12 ++ _3 = const _; // scope 1 at $DIR/issue_106141.rs:11:18: 11:25 + // mir::Constant +- // + span: $DIR/issue_106141.rs:2:5: 2:10 +- // + literal: Const { ty: fn() -> usize {inner}, val: Value(<ZST>) } ++ // + span: $DIR/issue_106141.rs:11:18: 11:25 ++ // + literal: Const { ty: &[bool; 1], val: Unevaluated(inner, [], Some(promoted[0])) } ++ _0 = index() -> bb1; // scope 2 at $DIR/issue_106141.rs:12:17: 12:24 ++ // mir::Constant ++ // + span: $DIR/issue_106141.rs:12:17: 12:22 ++ // + literal: Const { ty: fn() -> usize {index}, val: Value(<ZST>) } + } + + bb1: { ++ StorageLive(_1); // scope 3 at $DIR/issue_106141.rs:13:8: 13:21 ++ _2 = Lt(_0, const 1_usize); // scope 3 at $DIR/issue_106141.rs:13:8: 13:21 ++ assert(move _2, "index out of bounds: the length is {} but the index is {}", const 1_usize, _0) -> bb2; // scope 3 at $DIR/issue_106141.rs:13:8: 13:21 ++ } ++ ++ bb2: { ++ _1 = (*_3)[_0]; // scope 3 at $DIR/issue_106141.rs:13:8: 13:21 ++ switchInt(move _1) -> [0: bb3, otherwise: bb4]; // scope 3 at $DIR/issue_106141.rs:13:8: 13:21 ++ } ++ ++ bb3: { ++ _0 = const 0_usize; // scope 3 at $DIR/issue_106141.rs:16:9: 16:10 ++ goto -> bb4; // scope 3 at $DIR/issue_106141.rs:13:5: 17:6 ++ } ++ ++ bb4: { ++ StorageDead(_1); // scope 3 at $DIR/issue_106141.rs:17:5: 17:6 ++ StorageDead(_3); // scope 0 at $DIR/issue_106141.rs:+1:5: +1:12 + return; // scope 0 at $DIR/issue_106141.rs:+2:2: +2:2 + } + } + diff --git a/tests/mir-opt/inline/issue_106141.rs b/tests/mir-opt/inline/issue_106141.rs new file mode 100644 index 000000000..c8288b7f3 --- /dev/null +++ b/tests/mir-opt/inline/issue_106141.rs @@ -0,0 +1,24 @@ +pub fn outer() -> usize { + inner() +} + +fn index() -> usize { + loop {} +} + +#[inline] +fn inner() -> usize { + let buffer = &[true]; + let index = index(); + if buffer[index] { + index + } else { + 0 + } +} + +fn main() { + outer(); +} + +// EMIT_MIR issue_106141.outer.Inline.diff diff --git a/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.a.Inline.after.mir b/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.a.Inline.after.mir new file mode 100644 index 000000000..dc0c32350 --- /dev/null +++ b/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.a.Inline.after.mir @@ -0,0 +1,30 @@ +// MIR for `a` after Inline + +fn a(_1: &mut [T]) -> &mut [T] { + debug x => _1; // in scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+0:13: +0:14 + let mut _0: &mut [T]; // return place in scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+0:29: +0:37 + let mut _2: &mut [T]; // in scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15 + let mut _3: &mut [T]; // in scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15 + let mut _4: &mut [T]; // in scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15 + scope 1 (inlined <[T] as AsMut<[T]>>::as_mut) { // at $DIR/issue_58867_inline_as_ref_as_mut.rs:3:7: 3:15 + debug self => _4; // in scope 1 at $SRC_DIR/core/src/convert/mod.rs:LL:COL + let mut _5: &mut [T]; // in scope 1 at $SRC_DIR/core/src/convert/mod.rs:LL:COL + } + + bb0: { + StorageLive(_2); // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15 + StorageLive(_3); // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15 + StorageLive(_4); // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15 + _4 = &mut (*_1); // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15 + StorageLive(_5); // scope 1 at $SRC_DIR/core/src/convert/mod.rs:LL:COL + _5 = &mut (*_4); // scope 1 at $SRC_DIR/core/src/convert/mod.rs:LL:COL + _3 = &mut (*_5); // scope 1 at $SRC_DIR/core/src/convert/mod.rs:LL:COL + StorageDead(_5); // scope 1 at $SRC_DIR/core/src/convert/mod.rs:LL:COL + _2 = &mut (*_3); // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15 + StorageDead(_4); // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:14: +1:15 + _0 = &mut (*_2); // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15 + StorageDead(_3); // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+2:1: +2:2 + StorageDead(_2); // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+2:1: +2:2 + return; // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+2:2: +2:2 + } +} diff --git a/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.b.Inline.after.mir b/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.b.Inline.after.mir new file mode 100644 index 000000000..b6aff3014 --- /dev/null +++ b/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.b.Inline.after.mir @@ -0,0 +1,38 @@ +// MIR for `b` after Inline + +fn b(_1: &mut Box<T>) -> &mut T { + debug x => _1; // in scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+0:13: +0:14 + let mut _0: &mut T; // return place in scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+0:32: +0:38 + let mut _2: &mut T; // in scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15 + let mut _3: &mut T; // in scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15 + let mut _4: &mut std::boxed::Box<T>; // in scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15 + scope 1 (inlined <Box<T> as AsMut<T>>::as_mut) { // at $DIR/issue_58867_inline_as_ref_as_mut.rs:8:7: 8:15 + debug self => _4; // in scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL + let mut _5: &mut T; // in scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL + let mut _6: &mut T; // in scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL + let mut _7: std::boxed::Box<T>; // in scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL + let mut _8: *const T; // in scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL + } + + bb0: { + StorageLive(_2); // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15 + StorageLive(_3); // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15 + StorageLive(_4); // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15 + _4 = &mut (*_1); // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15 + StorageLive(_5); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL + StorageLive(_6); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL + _7 = deref_copy (*_4); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL + _8 = (((_7.0: std::ptr::Unique<T>).0: std::ptr::NonNull<T>).0: *const T); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL + _6 = &mut (*_8); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL + _5 = &mut (*_6); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL + _3 = &mut (*_5); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL + StorageDead(_6); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL + StorageDead(_5); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL + _2 = &mut (*_3); // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15 + StorageDead(_4); // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:14: +1:15 + _0 = &mut (*_2); // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15 + StorageDead(_3); // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+2:1: +2:2 + StorageDead(_2); // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+2:1: +2:2 + return; // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+2:2: +2:2 + } +} diff --git a/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.c.Inline.after.mir b/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.c.Inline.after.mir new file mode 100644 index 000000000..af830d249 --- /dev/null +++ b/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.c.Inline.after.mir @@ -0,0 +1,22 @@ +// MIR for `c` after Inline + +fn c(_1: &[T]) -> &[T] { + debug x => _1; // in scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+0:13: +0:14 + let mut _0: &[T]; // return place in scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+0:25: +0:29 + let _2: &[T]; // in scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15 + let mut _3: &[T]; // in scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15 + scope 1 (inlined <[T] as AsRef<[T]>>::as_ref) { // at $DIR/issue_58867_inline_as_ref_as_mut.rs:13:7: 13:15 + debug self => _3; // in scope 1 at $SRC_DIR/core/src/convert/mod.rs:LL:COL + } + + bb0: { + StorageLive(_2); // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15 + StorageLive(_3); // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15 + _3 = &(*_1); // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15 + _2 = _3; // scope 1 at $SRC_DIR/core/src/convert/mod.rs:LL:COL + _0 = &(*_2); // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15 + StorageDead(_3); // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:14: +1:15 + StorageDead(_2); // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+2:1: +2:2 + return; // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+2:2: +2:2 + } +} diff --git a/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.d.Inline.after.mir b/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.d.Inline.after.mir new file mode 100644 index 000000000..4f9342247 --- /dev/null +++ b/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.d.Inline.after.mir @@ -0,0 +1,26 @@ +// MIR for `d` after Inline + +fn d(_1: &Box<T>) -> &T { + debug x => _1; // in scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+0:13: +0:14 + let mut _0: &T; // return place in scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+0:28: +0:30 + let _2: &T; // in scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15 + let mut _3: &std::boxed::Box<T>; // in scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15 + scope 1 (inlined <Box<T> as AsRef<T>>::as_ref) { // at $DIR/issue_58867_inline_as_ref_as_mut.rs:18:7: 18:15 + debug self => _3; // in scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL + let mut _4: std::boxed::Box<T>; // in scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL + let mut _5: *const T; // in scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL + } + + bb0: { + StorageLive(_2); // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15 + StorageLive(_3); // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15 + _3 = &(*_1); // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15 + _4 = deref_copy (*_3); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL + _5 = (((_4.0: std::ptr::Unique<T>).0: std::ptr::NonNull<T>).0: *const T); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL + _2 = &(*_5); // scope 1 at $SRC_DIR/alloc/src/boxed.rs:LL:COL + _0 = &(*_2); // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:5: +1:15 + StorageDead(_3); // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+1:14: +1:15 + StorageDead(_2); // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+2:1: +2:2 + return; // scope 0 at $DIR/issue_58867_inline_as_ref_as_mut.rs:+2:2: +2:2 + } +} diff --git a/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.rs b/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.rs new file mode 100644 index 000000000..94f926d39 --- /dev/null +++ b/tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.rs @@ -0,0 +1,27 @@ +// EMIT_MIR issue_58867_inline_as_ref_as_mut.a.Inline.after.mir +pub fn a<T>(x: &mut [T]) -> &mut [T] { + x.as_mut() +} + +// EMIT_MIR issue_58867_inline_as_ref_as_mut.b.Inline.after.mir +pub fn b<T>(x: &mut Box<T>) -> &mut T { + x.as_mut() +} + +// EMIT_MIR issue_58867_inline_as_ref_as_mut.c.Inline.after.mir +pub fn c<T>(x: &[T]) -> &[T] { + x.as_ref() +} + +// EMIT_MIR issue_58867_inline_as_ref_as_mut.d.Inline.after.mir +pub fn d<T>(x: &Box<T>) -> &T { + x.as_ref() +} + +fn main() { + let mut boxed = Box::new(1); + println!("{:?}", a(&mut [1])); + println!("{:?}", b(&mut boxed)); + println!("{:?}", c(&[1])); + println!("{:?}", d(&boxed)); +} diff --git a/tests/mir-opt/inline/issue_76997_inline_scopes_parenting.main.Inline.after.mir b/tests/mir-opt/inline/issue_76997_inline_scopes_parenting.main.Inline.after.mir new file mode 100644 index 000000000..d99ae1a6c --- /dev/null +++ b/tests/mir-opt/inline/issue_76997_inline_scopes_parenting.main.Inline.after.mir @@ -0,0 +1,42 @@ +// MIR for `main` after Inline + +fn main() -> () { + let mut _0: (); // return place in scope 0 at $DIR/issue_76997_inline_scopes_parenting.rs:+0:11: +0:11 + let _1: [closure@$DIR/issue_76997_inline_scopes_parenting.rs:5:13: 5:16]; // in scope 0 at $DIR/issue_76997_inline_scopes_parenting.rs:+1:9: +1:10 + let mut _2: &[closure@$DIR/issue_76997_inline_scopes_parenting.rs:5:13: 5:16]; // in scope 0 at $DIR/issue_76997_inline_scopes_parenting.rs:+2:5: +2:6 + let mut _3: ((),); // in scope 0 at $DIR/issue_76997_inline_scopes_parenting.rs:+2:5: +2:10 + let mut _4: (); // in scope 0 at $DIR/issue_76997_inline_scopes_parenting.rs:+2:7: +2:9 + let mut _5: (); // in scope 0 at $DIR/issue_76997_inline_scopes_parenting.rs:+2:5: +2:10 + scope 1 { + debug f => _1; // in scope 1 at $DIR/issue_76997_inline_scopes_parenting.rs:+1:9: +1:10 + scope 2 (inlined main::{closure#0}) { // at $DIR/issue_76997_inline_scopes_parenting.rs:6:5: 6:10 + debug x => _5; // in scope 2 at $DIR/issue_76997_inline_scopes_parenting.rs:+1:14: +1:15 + let _6: (); // in scope 2 at $DIR/issue_76997_inline_scopes_parenting.rs:+1:23: +1:24 + scope 3 { + debug y => _6; // in scope 3 at $DIR/issue_76997_inline_scopes_parenting.rs:+1:23: +1:24 + } + } + } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/issue_76997_inline_scopes_parenting.rs:+1:9: +1:10 + Deinit(_1); // scope 0 at $DIR/issue_76997_inline_scopes_parenting.rs:+1:13: +1:33 + StorageLive(_2); // scope 1 at $DIR/issue_76997_inline_scopes_parenting.rs:+2:5: +2:6 + _2 = &_1; // scope 1 at $DIR/issue_76997_inline_scopes_parenting.rs:+2:5: +2:6 + StorageLive(_3); // scope 1 at $DIR/issue_76997_inline_scopes_parenting.rs:+2:5: +2:10 + StorageLive(_4); // scope 1 at $DIR/issue_76997_inline_scopes_parenting.rs:+2:7: +2:9 + Deinit(_4); // scope 1 at $DIR/issue_76997_inline_scopes_parenting.rs:+2:7: +2:9 + Deinit(_3); // scope 1 at $DIR/issue_76997_inline_scopes_parenting.rs:+2:5: +2:10 + (_3.0: ()) = move _4; // scope 1 at $DIR/issue_76997_inline_scopes_parenting.rs:+2:5: +2:10 + StorageLive(_5); // scope 1 at $DIR/issue_76997_inline_scopes_parenting.rs:+2:5: +2:10 + _5 = move (_3.0: ()); // scope 1 at $DIR/issue_76997_inline_scopes_parenting.rs:+2:5: +2:10 + StorageLive(_6); // scope 2 at $DIR/issue_76997_inline_scopes_parenting.rs:+1:23: +1:24 + StorageDead(_6); // scope 2 at $DIR/issue_76997_inline_scopes_parenting.rs:+1:32: +1:33 + StorageDead(_5); // scope 1 at $DIR/issue_76997_inline_scopes_parenting.rs:+2:5: +2:10 + StorageDead(_4); // scope 1 at $DIR/issue_76997_inline_scopes_parenting.rs:+2:9: +2:10 + StorageDead(_3); // scope 1 at $DIR/issue_76997_inline_scopes_parenting.rs:+2:9: +2:10 + StorageDead(_2); // scope 1 at $DIR/issue_76997_inline_scopes_parenting.rs:+2:9: +2:10 + StorageDead(_1); // scope 0 at $DIR/issue_76997_inline_scopes_parenting.rs:+3:1: +3:2 + return; // scope 0 at $DIR/issue_76997_inline_scopes_parenting.rs:+3:2: +3:2 + } +} diff --git a/tests/mir-opt/inline/issue_76997_inline_scopes_parenting.rs b/tests/mir-opt/inline/issue_76997_inline_scopes_parenting.rs new file mode 100644 index 000000000..76d806acc --- /dev/null +++ b/tests/mir-opt/inline/issue_76997_inline_scopes_parenting.rs @@ -0,0 +1,7 @@ +// Tests that MIR inliner can handle `SourceScopeData` parenting correctly. (#76997) + +// EMIT_MIR issue_76997_inline_scopes_parenting.main.Inline.after.mir +fn main() { + let f = |x| { let y = x; y }; + f(()) +} diff --git a/tests/mir-opt/inline/issue_78442.bar.Inline.diff b/tests/mir-opt/inline/issue_78442.bar.Inline.diff new file mode 100644 index 000000000..51a98465f --- /dev/null +++ b/tests/mir-opt/inline/issue_78442.bar.Inline.diff @@ -0,0 +1,68 @@ +- // MIR for `bar` before Inline ++ // MIR for `bar` after Inline + + fn bar(_1: P) -> () { + debug _baz => _1; // in scope 0 at $DIR/issue_78442.rs:+2:5: +2:9 + let mut _0: (); // return place in scope 0 at $DIR/issue_78442.rs:+3:3: +3:3 + let _2: (); // in scope 0 at $DIR/issue_78442.rs:+4:5: +4:17 + let mut _3: &fn() {foo}; // in scope 0 at $DIR/issue_78442.rs:+4:5: +4:15 + let _4: fn() {foo}; // in scope 0 at $DIR/issue_78442.rs:+4:5: +4:15 + let mut _5: (); // in scope 0 at $DIR/issue_78442.rs:+4:5: +4:17 ++ scope 1 (inlined <fn() {foo} as Fn<()>>::call - shim(fn() {foo})) { // at $DIR/issue_78442.rs:11:5: 11:17 ++ } + + bb0: { + StorageLive(_2); // scope 0 at $DIR/issue_78442.rs:+4:5: +4:17 + StorageLive(_3); // scope 0 at $DIR/issue_78442.rs:+4:5: +4:15 + StorageLive(_4); // scope 0 at $DIR/issue_78442.rs:+4:5: +4:15 +- _4 = hide_foo() -> [return: bb1, unwind: bb4]; // scope 0 at $DIR/issue_78442.rs:+4:5: +4:15 ++ _4 = hide_foo() -> [return: bb1, unwind: bb3]; // scope 0 at $DIR/issue_78442.rs:+4:5: +4:15 + // mir::Constant + // + span: $DIR/issue_78442.rs:11:5: 11:13 + // + literal: Const { ty: fn() -> impl Fn() {hide_foo}, val: Value(<ZST>) } + } + + bb1: { + _3 = &_4; // scope 0 at $DIR/issue_78442.rs:+4:5: +4:15 + StorageLive(_5); // scope 0 at $DIR/issue_78442.rs:+4:5: +4:17 + Deinit(_5); // scope 0 at $DIR/issue_78442.rs:+4:5: +4:17 +- _2 = <fn() {foo} as Fn<()>>::call(move _3, move _5) -> [return: bb2, unwind: bb4]; // scope 0 at $DIR/issue_78442.rs:+4:5: +4:17 +- // mir::Constant +- // + span: $DIR/issue_78442.rs:11:5: 11:15 +- // + literal: Const { ty: for<'a> extern "rust-call" fn(&'a fn() {foo}, ()) -> <fn() {foo} as FnOnce<()>>::Output {<fn() {foo} as Fn<()>>::call}, val: Value(<ZST>) } ++ _2 = move (*_3)() -> [return: bb5, unwind: bb3]; // scope 1 at $SRC_DIR/core/src/ops/function.rs:LL:COL + } + + bb2: { +- StorageDead(_5); // scope 0 at $DIR/issue_78442.rs:+4:16: +4:17 +- StorageDead(_3); // scope 0 at $DIR/issue_78442.rs:+4:16: +4:17 +- StorageDead(_4); // scope 0 at $DIR/issue_78442.rs:+4:17: +4:18 +- StorageDead(_2); // scope 0 at $DIR/issue_78442.rs:+4:17: +4:18 +- _0 = const (); // scope 0 at $DIR/issue_78442.rs:+3:3: +5:2 +- drop(_1) -> [return: bb3, unwind: bb5]; // scope 0 at $DIR/issue_78442.rs:+5:1: +5:2 ++ return; // scope 0 at $DIR/issue_78442.rs:+5:2: +5:2 + } + +- bb3: { +- return; // scope 0 at $DIR/issue_78442.rs:+5:2: +5:2 ++ bb3 (cleanup): { ++ drop(_1) -> bb4; // scope 0 at $DIR/issue_78442.rs:+5:1: +5:2 + } + + bb4 (cleanup): { +- drop(_1) -> bb5; // scope 0 at $DIR/issue_78442.rs:+5:1: +5:2 ++ resume; // scope 0 at $DIR/issue_78442.rs:+0:1: +5:2 + } + +- bb5 (cleanup): { +- resume; // scope 0 at $DIR/issue_78442.rs:+0:1: +5:2 ++ bb5: { ++ StorageDead(_5); // scope 0 at $DIR/issue_78442.rs:+4:16: +4:17 ++ StorageDead(_3); // scope 0 at $DIR/issue_78442.rs:+4:16: +4:17 ++ StorageDead(_4); // scope 0 at $DIR/issue_78442.rs:+4:17: +4:18 ++ StorageDead(_2); // scope 0 at $DIR/issue_78442.rs:+4:17: +4:18 ++ _0 = const (); // scope 0 at $DIR/issue_78442.rs:+3:3: +5:2 ++ drop(_1) -> [return: bb2, unwind: bb4]; // scope 0 at $DIR/issue_78442.rs:+5:1: +5:2 + } + } + diff --git a/tests/mir-opt/inline/issue_78442.bar.RevealAll.diff b/tests/mir-opt/inline/issue_78442.bar.RevealAll.diff new file mode 100644 index 000000000..e47466c5e --- /dev/null +++ b/tests/mir-opt/inline/issue_78442.bar.RevealAll.diff @@ -0,0 +1,57 @@ +- // MIR for `bar` before RevealAll ++ // MIR for `bar` after RevealAll + + fn bar(_1: P) -> () { + debug _baz => _1; // in scope 0 at $DIR/issue_78442.rs:+2:5: +2:9 + let mut _0: (); // return place in scope 0 at $DIR/issue_78442.rs:+3:3: +3:3 + let _2: (); // in scope 0 at $DIR/issue_78442.rs:+4:5: +4:17 +- let mut _3: &impl Fn(); // in scope 0 at $DIR/issue_78442.rs:+4:5: +4:15 +- let _4: impl Fn(); // in scope 0 at $DIR/issue_78442.rs:+4:5: +4:15 ++ let mut _3: &fn() {foo}; // in scope 0 at $DIR/issue_78442.rs:+4:5: +4:15 ++ let _4: fn() {foo}; // in scope 0 at $DIR/issue_78442.rs:+4:5: +4:15 + let mut _5: (); // in scope 0 at $DIR/issue_78442.rs:+4:5: +4:17 + + bb0: { + StorageLive(_2); // scope 0 at $DIR/issue_78442.rs:+4:5: +4:17 + StorageLive(_3); // scope 0 at $DIR/issue_78442.rs:+4:5: +4:15 + StorageLive(_4); // scope 0 at $DIR/issue_78442.rs:+4:5: +4:15 + _4 = hide_foo() -> [return: bb1, unwind: bb4]; // scope 0 at $DIR/issue_78442.rs:+4:5: +4:15 + // mir::Constant + // + span: $DIR/issue_78442.rs:11:5: 11:13 + // + literal: Const { ty: fn() -> impl Fn() {hide_foo}, val: Value(<ZST>) } + } + + bb1: { + _3 = &_4; // scope 0 at $DIR/issue_78442.rs:+4:5: +4:15 + StorageLive(_5); // scope 0 at $DIR/issue_78442.rs:+4:5: +4:17 + Deinit(_5); // scope 0 at $DIR/issue_78442.rs:+4:5: +4:17 +- _2 = <impl Fn() as Fn<()>>::call(move _3, move _5) -> [return: bb2, unwind: bb4]; // scope 0 at $DIR/issue_78442.rs:+4:5: +4:17 ++ _2 = <fn() {foo} as Fn<()>>::call(move _3, move _5) -> [return: bb2, unwind: bb4]; // scope 0 at $DIR/issue_78442.rs:+4:5: +4:17 + // mir::Constant + // + span: $DIR/issue_78442.rs:11:5: 11:15 +- // + literal: Const { ty: for<'a> extern "rust-call" fn(&'a impl Fn(), ()) -> <impl Fn() as FnOnce<()>>::Output {<impl Fn() as Fn<()>>::call}, val: Value(<ZST>) } ++ // + literal: Const { ty: for<'a> extern "rust-call" fn(&'a fn() {foo}, ()) -> <fn() {foo} as FnOnce<()>>::Output {<fn() {foo} as Fn<()>>::call}, val: Value(<ZST>) } + } + + bb2: { + StorageDead(_5); // scope 0 at $DIR/issue_78442.rs:+4:16: +4:17 + StorageDead(_3); // scope 0 at $DIR/issue_78442.rs:+4:16: +4:17 + StorageDead(_4); // scope 0 at $DIR/issue_78442.rs:+4:17: +4:18 + StorageDead(_2); // scope 0 at $DIR/issue_78442.rs:+4:17: +4:18 + _0 = const (); // scope 0 at $DIR/issue_78442.rs:+3:3: +5:2 + drop(_1) -> [return: bb3, unwind: bb5]; // scope 0 at $DIR/issue_78442.rs:+5:1: +5:2 + } + + bb3: { + return; // scope 0 at $DIR/issue_78442.rs:+5:2: +5:2 + } + + bb4 (cleanup): { + drop(_1) -> bb5; // scope 0 at $DIR/issue_78442.rs:+5:1: +5:2 + } + + bb5 (cleanup): { + resume; // scope 0 at $DIR/issue_78442.rs:+0:1: +5:2 + } + } + diff --git a/tests/mir-opt/inline/issue_78442.rs b/tests/mir-opt/inline/issue_78442.rs new file mode 100644 index 000000000..aa8ede2df --- /dev/null +++ b/tests/mir-opt/inline/issue_78442.rs @@ -0,0 +1,20 @@ +// compile-flags: -Z mir-opt-level=3 -Z inline-mir +// ignore-wasm32-bare compiled with panic=abort by default +#![crate_type = "lib"] + +// EMIT_MIR issue_78442.bar.RevealAll.diff +// EMIT_MIR issue_78442.bar.Inline.diff +pub fn bar<P>( + // Error won't happen if "bar" is not generic + _baz: P, +) { + hide_foo()(); +} + +fn hide_foo() -> impl Fn() { + // Error won't happen if "iterate" hasn't impl Trait or has generics + foo +} + +fn foo() { // Error won't happen if "foo" isn't used in "iterate" or has generics +} diff --git a/tests/mir-opt/inline/polymorphic_recursion.rs b/tests/mir-opt/inline/polymorphic_recursion.rs new file mode 100644 index 000000000..7388722b7 --- /dev/null +++ b/tests/mir-opt/inline/polymorphic_recursion.rs @@ -0,0 +1,25 @@ +// Make sure that the MIR inliner does not loop indefinitely on polymorphic recursion. +// compile-flags: --crate-type lib + +// Randomize `def_path_hash` by defining them under a module with different names +macro_rules! emit { + ($($m:ident)*) => {$( + pub mod $m { + pub trait Tr { type Next: Tr; } + + pub fn hoge<const N: usize, T: Tr>() { + inner::<N, T>(); + } + + #[inline(always)] + fn inner<const N: usize, T: Tr>() + { + inner::<N, T::Next>(); + inner::<N, T::Next>(); + } + } + )*}; +} + +// Increase the chance of triggering the bug +emit!(m00 m01 m02 m03 m04 m05 m06 m07 m08 m09 m10 m11 m12 m13 m14 m15 m16 m17 m18 m19); |