about summary refs log tree commit diff
path: root/tests/mir-opt/inline
diff options
context:
space:
mode:
authorAlbert Larsan <74931857+albertlarsan68@users.noreply.github.com>2023-01-05 09:13:28 +0100
committerAlbert Larsan <74931857+albertlarsan68@users.noreply.github.com>2023-01-11 09:32:08 +0000
commitcf2dff2b1e3fa55fa5415d524200070d0d7aacfe (patch)
tree40a88d9a46aaf3e8870676eb2538378b75a263eb /tests/mir-opt/inline
parentca855e6e42787ecd062d81d53336fe6788ef51a9 (diff)
downloadrust-cf2dff2b1e3fa55fa5415d524200070d0d7aacfe.tar.gz
rust-cf2dff2b1e3fa55fa5415d524200070d0d7aacfe.zip
Move /src/test to /tests
Diffstat (limited to 'tests/mir-opt/inline')
-rw-r--r--tests/mir-opt/inline/asm_unwind.main.Inline.diff45
-rw-r--r--tests/mir-opt/inline/asm_unwind.rs22
-rw-r--r--tests/mir-opt/inline/caller_with_trivial_bound.foo.Inline.diff33
-rw-r--r--tests/mir-opt/inline/caller_with_trivial_bound.rs26
-rw-r--r--tests/mir-opt/inline/cycle.f.Inline.diff43
-rw-r--r--tests/mir-opt/inline/cycle.g.Inline.diff57
-rw-r--r--tests/mir-opt/inline/cycle.main.Inline.diff57
-rw-r--r--tests/mir-opt/inline/cycle.rs18
-rw-r--r--tests/mir-opt/inline/dyn_trait.get_query.Inline.diff54
-rw-r--r--tests/mir-opt/inline/dyn_trait.mk_cycle.Inline.diff23
-rw-r--r--tests/mir-opt/inline/dyn_trait.rs35
-rw-r--r--tests/mir-opt/inline/dyn_trait.try_execute_query.Inline.diff33
-rw-r--r--tests/mir-opt/inline/exponential_runtime.main.Inline.diff75
-rw-r--r--tests/mir-opt/inline/exponential_runtime.rs87
-rw-r--r--tests/mir-opt/inline/inline_any_operand.bar.Inline.after.mir36
-rw-r--r--tests/mir-opt/inline/inline_any_operand.rs18
-rw-r--r--tests/mir-opt/inline/inline_async.rs18
-rw-r--r--tests/mir-opt/inline/inline_closure.foo.Inline.after.mir49
-rw-r--r--tests/mir-opt/inline/inline_closure.rs13
-rw-r--r--tests/mir-opt/inline/inline_closure_borrows_arg.foo.Inline.after.mir52
-rw-r--r--tests/mir-opt/inline/inline_closure_borrows_arg.rs17
-rw-r--r--tests/mir-opt/inline/inline_closure_captures.foo.Inline.after.mir65
-rw-r--r--tests/mir-opt/inline/inline_closure_captures.rs13
-rw-r--r--tests/mir-opt/inline/inline_compatibility.inlined_no_sanitize.Inline.diff24
-rw-r--r--tests/mir-opt/inline/inline_compatibility.inlined_target_feature.Inline.diff24
-rw-r--r--tests/mir-opt/inline/inline_compatibility.not_inlined_c_variadic.Inline.diff25
-rw-r--r--tests/mir-opt/inline/inline_compatibility.not_inlined_no_sanitize.Inline.diff22
-rw-r--r--tests/mir-opt/inline/inline_compatibility.not_inlined_target_feature.Inline.diff22
-rw-r--r--tests/mir-opt/inline/inline_compatibility.rs55
-rw-r--r--tests/mir-opt/inline/inline_cycle.one.Inline.diff30
-rw-r--r--tests/mir-opt/inline/inline_cycle.rs60
-rw-r--r--tests/mir-opt/inline/inline_cycle.two.Inline.diff41
-rw-r--r--tests/mir-opt/inline/inline_cycle_generic.main.Inline.diff32
-rw-r--r--tests/mir-opt/inline/inline_cycle_generic.rs40
-rw-r--r--tests/mir-opt/inline/inline_diverging.f.Inline.diff24
-rw-r--r--tests/mir-opt/inline/inline_diverging.g.Inline.diff49
-rw-r--r--tests/mir-opt/inline/inline_diverging.h.Inline.diff87
-rw-r--r--tests/mir-opt/inline/inline_diverging.rs40
-rw-r--r--tests/mir-opt/inline/inline_generator.main.Inline.diff136
-rw-r--r--tests/mir-opt/inline/inline_generator.rs16
-rw-r--r--tests/mir-opt/inline/inline_instruction_set.default.Inline.diff60
-rw-r--r--tests/mir-opt/inline/inline_instruction_set.rs61
-rw-r--r--tests/mir-opt/inline/inline_instruction_set.t32.Inline.diff58
-rw-r--r--tests/mir-opt/inline/inline_into_box_place.main.Inline.diff82
-rw-r--r--tests/mir-opt/inline/inline_into_box_place.rs9
-rw-r--r--tests/mir-opt/inline/inline_options.main.Inline.after.mir55
-rw-r--r--tests/mir-opt/inline/inline_options.rs19
-rw-r--r--tests/mir-opt/inline/inline_retag.bar.Inline.after.mir68
-rw-r--r--tests/mir-opt/inline/inline_retag.rs18
-rw-r--r--tests/mir-opt/inline/inline_shims.clone.Inline.diff26
-rw-r--r--tests/mir-opt/inline/inline_shims.drop.Inline.diff56
-rw-r--r--tests/mir-opt/inline/inline_shims.rs13
-rw-r--r--tests/mir-opt/inline/inline_specialization.main.Inline.diff28
-rw-r--r--tests/mir-opt/inline/inline_specialization.rs15
-rw-r--r--tests/mir-opt/inline/inline_trait_method.rs22
-rw-r--r--tests/mir-opt/inline/inline_trait_method.test.Inline.after.mir21
-rw-r--r--tests/mir-opt/inline/inline_trait_method_2.rs27
-rw-r--r--tests/mir-opt/inline/inline_trait_method_2.test2.Inline.after.mir28
-rw-r--r--tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.a.Inline.after.mir30
-rw-r--r--tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.b.Inline.after.mir38
-rw-r--r--tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.c.Inline.after.mir22
-rw-r--r--tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.d.Inline.after.mir26
-rw-r--r--tests/mir-opt/inline/issue_58867_inline_as_ref_as_mut.rs27
-rw-r--r--tests/mir-opt/inline/issue_76997_inline_scopes_parenting.main.Inline.after.mir42
-rw-r--r--tests/mir-opt/inline/issue_76997_inline_scopes_parenting.rs7
-rw-r--r--tests/mir-opt/inline/issue_78442.bar.Inline.diff68
-rw-r--r--tests/mir-opt/inline/issue_78442.bar.RevealAll.diff57
-rw-r--r--tests/mir-opt/inline/issue_78442.rs20
-rw-r--r--tests/mir-opt/inline/polymorphic_recursion.rs25
69 files changed, 2644 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 00000000000..f1b62ac38ba
--- /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 00000000000..c03feb43312
--- /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 00000000000..8b03006782b
--- /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 00000000000..8545db89414
--- /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 00000000000..75ea69a42eb
--- /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 00000000000..5f3ee467c88
--- /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 00000000000..6b4c63bbd91
--- /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 00000000000..9e8950d8a3d
--- /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 00000000000..8ea1a0757f2
--- /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 00000000000..7653a5ded44
--- /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 00000000000..6a46e1e07b1
--- /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 00000000000..a71d73b7453
--- /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 00000000000..7fd62be7ab9
--- /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 00000000000..d9219d76a98
--- /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 00000000000..3502c25864b
--- /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 00000000000..fb0de020f73
--- /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 00000000000..5c838159b98
--- /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 00000000000..9eb3a01eef9
--- /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 00000000000..715fd0138a7
--- /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 00000000000..dd32eb2d8d1
--- /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 00000000000..d76bc33f52e
--- /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 00000000000..fd19c288666
--- /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 00000000000..52b6817e401
--- /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 00000000000..e30a5e116ea
--- /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 00000000000..c2b3c46a30c
--- /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 00000000000..0ca5a5f70b7
--- /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 00000000000..00d405c77f9
--- /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 00000000000..8b9c86f5515
--- /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 00000000000..30aff0a64ef
--- /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 00000000000..5510cd7bc8c
--- /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 00000000000..63ad57de1d4
--- /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 00000000000..64c0065b543
--- /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 00000000000..52debab4dd1
--- /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 00000000000..24b4f37939a
--- /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 00000000000..b49191f495b
--- /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 00000000000..b787a19f4b2
--- /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 00000000000..f82fcf4c821
--- /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 00000000000..ae6f814c290
--- /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 00000000000..f27b64c3054
--- /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 00000000000..d11b3e548f7
--- /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 00000000000..f1988ea4bd6
--- /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 00000000000..5dfb04943e3
--- /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 00000000000..e777b2cc29e
--- /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 00000000000..2a4dc9e3e80
--- /dev/null
+++ b/tests/mir-opt/inline/inline_into_box_place.main.Inline.diff
@@ -0,0 +1,82 @@
+- // 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
+      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 _9: 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 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
++         _9 = 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((*_8));                   // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
++         ((*_8).0: alloc::raw_vec::RawVec<u32>) = move _9; // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
++         ((*_8).1: usize) = const 0_usize; // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
++         StorageDead(_9);                 // scope 3 at $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
++         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 00000000000..232bcc7b27d
--- /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 00000000000..1c590be945c
--- /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 00000000000..477f050b69e
--- /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 00000000000..60149ff3606
--- /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 00000000000..c6950f26925
--- /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 00000000000..09dd35c4c68
--- /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 00000000000..36ddb189e0d
--- /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 00000000000..7c8618f71e5
--- /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 00000000000..af08296edea
--- /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 00000000000..87275b4e514
--- /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 00000000000..74be53f5512
--- /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 00000000000..637bf282a65
--- /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 00000000000..378e71a2567
--- /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 00000000000..73aea719eed
--- /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_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 00000000000..dc0c3235043
--- /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 00000000000..b6aff30149f
--- /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 00000000000..af830d2494e
--- /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 00000000000..4f9342247d7
--- /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 00000000000..94f926d3964
--- /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 00000000000..d99ae1a6c7c
--- /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 00000000000..76d806acc63
--- /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 00000000000..51a98465fd9
--- /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 00000000000..e47466c5e80
--- /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 00000000000..aa8ede2df9e
--- /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 00000000000..7388722b776
--- /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);