From 0b4af1614d91152564b852572afa63fab71162a1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= <tomasz.miasko@gmail.com>
Date: Wed, 11 Nov 2020 00:00:00 +0000
Subject: [PATCH 1/6] Never inline when `no_sanitize` attributes differ

The inliner looks if a sanitizer is enabled before considering
`no_sanitize` attribute as possible source of incompatibility.

The MIR inlining could happen in a crate with sanitizer disabled, but
code generation in a crate with sanitizer enabled, thus the attribute
would be incorrectly ignored.

To avoid the issue never inline functions with different `no_sanitize`
attributes.
---
 compiler/rustc_mir/src/transform/inline.rs      | 6 +-----
 src/test/mir-opt/inline/inline-compatibility.rs | 4 +---
 2 files changed, 2 insertions(+), 8 deletions(-)

diff --git a/compiler/rustc_mir/src/transform/inline.rs b/compiler/rustc_mir/src/transform/inline.rs
index 7737672dbde66..7332d4194944e 100644
--- a/compiler/rustc_mir/src/transform/inline.rs
+++ b/compiler/rustc_mir/src/transform/inline.rs
@@ -218,11 +218,7 @@ impl Inliner<'tcx> {
             return false;
         }
 
-        let self_no_sanitize =
-            self.codegen_fn_attrs.no_sanitize & self.tcx.sess.opts.debugging_opts.sanitizer;
-        let callee_no_sanitize =
-            codegen_fn_attrs.no_sanitize & self.tcx.sess.opts.debugging_opts.sanitizer;
-        if self_no_sanitize != callee_no_sanitize {
+        if self.codegen_fn_attrs.no_sanitize != codegen_fn_attrs.no_sanitize {
             debug!("`callee has incompatible no_sanitize attribute - not inlining");
             return false;
         }
diff --git a/src/test/mir-opt/inline/inline-compatibility.rs b/src/test/mir-opt/inline/inline-compatibility.rs
index ff9049edb4f2c..2e9edf5260f53 100644
--- a/src/test/mir-opt/inline/inline-compatibility.rs
+++ b/src/test/mir-opt/inline/inline-compatibility.rs
@@ -1,8 +1,6 @@
 // Checks that only functions with compatible attributes are inlined.
 //
 // only-x86_64
-// needs-sanitizer-address
-// compile-flags: -Zsanitizer=address
 
 #![crate_type = "lib"]
 #![feature(no_sanitize)]
@@ -35,5 +33,5 @@ pub unsafe fn not_inlined_no_sanitize() {
 pub unsafe fn target_feature() {}
 
 #[inline]
-#[no_sanitize(address, memory)]
+#[no_sanitize(address)]
 pub unsafe fn no_sanitize() {}

From ae4332643de6a672ab3aefd62a3063c9af21166c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= <tomasz.miasko@gmail.com>
Date: Wed, 11 Nov 2020 00:00:00 +0000
Subject: [PATCH 2/6] Never inline cold functions

The information about cold attribute is lost during inlining,
Avoid the issue by never inlining cold functions.
---
 compiler/rustc_mir/src/transform/inline.rs | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/compiler/rustc_mir/src/transform/inline.rs b/compiler/rustc_mir/src/transform/inline.rs
index 7332d4194944e..5023e49df3abb 100644
--- a/compiler/rustc_mir/src/transform/inline.rs
+++ b/compiler/rustc_mir/src/transform/inline.rs
@@ -252,9 +252,9 @@ impl Inliner<'tcx> {
             self.tcx.sess.opts.debugging_opts.inline_mir_threshold
         };
 
-        // Significantly lower the threshold for inlining cold functions
         if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::COLD) {
-            threshold /= 5;
+            debug!("#[cold] present - not inlining");
+            return false;
         }
 
         // Give a bonus functions with a small number of blocks,

From 9bb3d6b7d472e2116312ea45db07a5338af205fb Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= <tomasz.miasko@gmail.com>
Date: Wed, 11 Nov 2020 00:00:00 +0000
Subject: [PATCH 3/6] Remove check for impossible condition

The callee body is already transformed; the condition is always false.
---
 compiler/rustc_mir/src/transform/inline.rs | 6 ------
 1 file changed, 6 deletions(-)

diff --git a/compiler/rustc_mir/src/transform/inline.rs b/compiler/rustc_mir/src/transform/inline.rs
index 5023e49df3abb..0d6d9e397ac9f 100644
--- a/compiler/rustc_mir/src/transform/inline.rs
+++ b/compiler/rustc_mir/src/transform/inline.rs
@@ -203,12 +203,6 @@ impl Inliner<'tcx> {
         debug!("should_inline({:?})", callsite);
         let tcx = self.tcx;
 
-        // Cannot inline generators which haven't been transformed yet
-        if callee_body.yield_ty.is_some() {
-            debug!("    yield ty present - not inlining");
-            return false;
-        }
-
         let codegen_fn_attrs = tcx.codegen_fn_attrs(callsite.callee.def_id());
 
         let self_features = &self.codegen_fn_attrs.target_features;

From 66cadec1763ac645337c1ac58f06ea48b9b72a26 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= <tomasz.miasko@gmail.com>
Date: Wed, 11 Nov 2020 00:00:00 +0000
Subject: [PATCH 4/6] Fix generator inlining by checking for rust-call abi and
 spread arg

---
 compiler/rustc_mir/src/transform/inline.rs  | 26 +++++++++++----------
 src/test/mir-opt/inline/inline-generator.rs | 16 +++++++++++++
 2 files changed, 30 insertions(+), 12 deletions(-)
 create mode 100644 src/test/mir-opt/inline/inline-generator.rs

diff --git a/compiler/rustc_mir/src/transform/inline.rs b/compiler/rustc_mir/src/transform/inline.rs
index 0d6d9e397ac9f..2ccb9b3709f2f 100644
--- a/compiler/rustc_mir/src/transform/inline.rs
+++ b/compiler/rustc_mir/src/transform/inline.rs
@@ -7,6 +7,7 @@ use rustc_index::vec::Idx;
 use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
 use rustc_middle::mir::visit::*;
 use rustc_middle::mir::*;
+use rustc_middle::ty::subst::Subst;
 use rustc_middle::ty::{self, ConstKind, Instance, InstanceDef, ParamEnv, Ty, TyCtxt};
 use rustc_span::{hygiene::ExpnKind, ExpnData, Span};
 use rustc_target::spec::abi::Abi;
@@ -28,6 +29,7 @@ pub struct Inline;
 #[derive(Copy, Clone, Debug)]
 struct CallSite<'tcx> {
     callee: Instance<'tcx>,
+    fn_sig: ty::PolyFnSig<'tcx>,
     block: BasicBlock,
     target: Option<BasicBlock>,
     source_info: SourceInfo,
@@ -173,22 +175,23 @@ impl Inliner<'tcx> {
 
         // Only consider direct calls to functions
         let terminator = bb_data.terminator();
-        if let TerminatorKind::Call { func: ref op, ref destination, .. } = terminator.kind {
-            if let ty::FnDef(callee_def_id, substs) = *op.ty(caller_body, self.tcx).kind() {
-                // To resolve an instance its substs have to be fully normalized, so
-                // we do this here.
-                let normalized_substs = self.tcx.normalize_erasing_regions(self.param_env, substs);
+        if let TerminatorKind::Call { ref func, ref destination, .. } = terminator.kind {
+            let func_ty = func.ty(caller_body, self.tcx);
+            if let ty::FnDef(def_id, substs) = *func_ty.kind() {
+                // To resolve an instance its substs have to be fully normalized.
+                let substs = self.tcx.normalize_erasing_regions(self.param_env, substs);
                 let callee =
-                    Instance::resolve(self.tcx, self.param_env, callee_def_id, normalized_substs)
-                        .ok()
-                        .flatten()?;
+                    Instance::resolve(self.tcx, self.param_env, def_id, substs).ok().flatten()?;
 
                 if let InstanceDef::Virtual(..) | InstanceDef::Intrinsic(_) = callee.def {
                     return None;
                 }
 
+                let fn_sig = self.tcx.fn_sig(def_id).subst(self.tcx, substs);
+
                 return Some(CallSite {
                     callee,
+                    fn_sig,
                     block: bb,
                     target: destination.map(|(_, target)| target),
                     source_info: terminator.source_info,
@@ -437,7 +440,7 @@ impl Inliner<'tcx> {
                 };
 
                 // Copy the arguments if needed.
-                let args: Vec<_> = self.make_call_args(args, &callsite, caller_body);
+                let args: Vec<_> = self.make_call_args(args, &callsite, caller_body, &callee_body);
 
                 let mut integrator = Integrator {
                     args: &args,
@@ -518,6 +521,7 @@ impl Inliner<'tcx> {
         args: Vec<Operand<'tcx>>,
         callsite: &CallSite<'tcx>,
         caller_body: &mut Body<'tcx>,
+        callee_body: &Body<'tcx>,
     ) -> Vec<Local> {
         let tcx = self.tcx;
 
@@ -544,9 +548,7 @@ impl Inliner<'tcx> {
         //     tmp2 = tuple_tmp.2
         //
         // and the vector is `[closure_ref, tmp0, tmp1, tmp2]`.
-        // FIXME(eddyb) make this check for `"rust-call"` ABI combined with
-        // `callee_body.spread_arg == None`, instead of special-casing closures.
-        if tcx.is_closure(callsite.callee.def_id()) {
+        if callsite.fn_sig.abi() == Abi::RustCall && callee_body.spread_arg.is_none() {
             let mut args = args.into_iter();
             let self_ = self.create_temp_if_necessary(args.next().unwrap(), callsite, caller_body);
             let tuple = self.create_temp_if_necessary(args.next().unwrap(), callsite, caller_body);
diff --git a/src/test/mir-opt/inline/inline-generator.rs b/src/test/mir-opt/inline/inline-generator.rs
new file mode 100644
index 0000000000000..d11b3e548f721
--- /dev/null
+++ b/src/test/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 } }
+}

From 79d853eccebf6d9704adeea45f20f11bae0d7396 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= <tomasz.miasko@gmail.com>
Date: Wed, 11 Nov 2020 00:00:00 +0000
Subject: [PATCH 5/6] Never inline C variadic functions

---
 compiler/rustc_mir/src/transform/inline.rs     |  5 +++++
 .../mir-opt/inline/inline-compatibility.rs     | 18 ++++++++++++++++++
 2 files changed, 23 insertions(+)

diff --git a/compiler/rustc_mir/src/transform/inline.rs b/compiler/rustc_mir/src/transform/inline.rs
index 2ccb9b3709f2f..aae98f5b6d8d6 100644
--- a/compiler/rustc_mir/src/transform/inline.rs
+++ b/compiler/rustc_mir/src/transform/inline.rs
@@ -206,6 +206,11 @@ impl Inliner<'tcx> {
         debug!("should_inline({:?})", callsite);
         let tcx = self.tcx;
 
+        if callsite.fn_sig.c_variadic() {
+            debug!("callee is variadic - not inlining");
+            return false;
+        }
+
         let codegen_fn_attrs = tcx.codegen_fn_attrs(callsite.callee.def_id());
 
         let self_features = &self.codegen_fn_attrs.target_features;
diff --git a/src/test/mir-opt/inline/inline-compatibility.rs b/src/test/mir-opt/inline/inline-compatibility.rs
index 2e9edf5260f53..30aff0a64efb9 100644
--- a/src/test/mir-opt/inline/inline-compatibility.rs
+++ b/src/test/mir-opt/inline/inline-compatibility.rs
@@ -5,6 +5,7 @@
 #![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")]
@@ -35,3 +36,20 @@ 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
+}

From 2a010dd3404256ea774e5338ad1952d09ab2cf03 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= <tomasz.miasko@gmail.com>
Date: Wed, 11 Nov 2020 00:00:00 +0000
Subject: [PATCH 6/6] ./x.py test --bless

---
 ...patibility.inlined_no_sanitize.Inline.diff |  20 +--
 ...ibility.inlined_target_feature.Inline.diff |  20 +--
 ...ibility.not_inlined_c_variadic.Inline.diff |  25 ++++
 ...bility.not_inlined_no_sanitize.Inline.diff |  16 +--
 ...ity.not_inlined_target_feature.Inline.diff |  16 +--
 .../inline/inline_generator.main.Inline.diff  | 123 ++++++++++++++++++
 6 files changed, 184 insertions(+), 36 deletions(-)
 create mode 100644 src/test/mir-opt/inline/inline_compatibility.not_inlined_c_variadic.Inline.diff
 create mode 100644 src/test/mir-opt/inline/inline_generator.main.Inline.diff

diff --git a/src/test/mir-opt/inline/inline_compatibility.inlined_no_sanitize.Inline.diff b/src/test/mir-opt/inline/inline_compatibility.inlined_no_sanitize.Inline.diff
index 451ec39422fc4..c95cf47695785 100644
--- a/src/test/mir-opt/inline/inline_compatibility.inlined_no_sanitize.Inline.diff
+++ b/src/test/mir-opt/inline/inline_compatibility.inlined_no_sanitize.Inline.diff
@@ -2,24 +2,24 @@
 + // MIR for `inlined_no_sanitize` after Inline
   
   fn inlined_no_sanitize() -> () {
-      let mut _0: ();                      // return place in scope 0 at $DIR/inline-compatibility.rs:24:37: 24:37
-      let _1: ();                          // in scope 0 at $DIR/inline-compatibility.rs:25:5: 25:18
-+     scope 1 (inlined no_sanitize) {      // at $DIR/inline-compatibility.rs:25:5: 25:18
+      let mut _0: ();                      // return place in scope 0 at $DIR/inline-compatibility.rs:23:37: 23:37
+      let _1: ();                          // in scope 0 at $DIR/inline-compatibility.rs:24:5: 24: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:25:5: 25:18
--         _1 = no_sanitize() -> bb1;       // scope 0 at $DIR/inline-compatibility.rs:25:5: 25:18
+          StorageLive(_1);                 // scope 0 at $DIR/inline-compatibility.rs:24:5: 24:18
+-         _1 = no_sanitize() -> bb1;       // scope 0 at $DIR/inline-compatibility.rs:24:5: 24:18
 -                                          // mir::Constant
--                                          // + span: $DIR/inline-compatibility.rs:25:5: 25:16
+-                                          // + span: $DIR/inline-compatibility.rs:24:5: 24:16
 -                                          // + literal: Const { ty: unsafe fn() {no_sanitize}, val: Value(Scalar(<ZST>)) }
 -     }
 - 
 -     bb1: {
-+         _1 = const ();                   // scope 1 at $DIR/inline-compatibility.rs:25:5: 25:18
-          StorageDead(_1);                 // scope 0 at $DIR/inline-compatibility.rs:25:18: 25:19
-          _0 = const ();                   // scope 0 at $DIR/inline-compatibility.rs:24:37: 26:2
-          return;                          // scope 0 at $DIR/inline-compatibility.rs:26:2: 26:2
++         _1 = const ();                   // scope 1 at $DIR/inline-compatibility.rs:24:5: 24:18
+          StorageDead(_1);                 // scope 0 at $DIR/inline-compatibility.rs:24:18: 24:19
+          _0 = const ();                   // scope 0 at $DIR/inline-compatibility.rs:23:37: 25:2
+          return;                          // scope 0 at $DIR/inline-compatibility.rs:25:2: 25:2
       }
   }
   
diff --git a/src/test/mir-opt/inline/inline_compatibility.inlined_target_feature.Inline.diff b/src/test/mir-opt/inline/inline_compatibility.inlined_target_feature.Inline.diff
index a59ddd344cb26..2bb928343229f 100644
--- a/src/test/mir-opt/inline/inline_compatibility.inlined_target_feature.Inline.diff
+++ b/src/test/mir-opt/inline/inline_compatibility.inlined_target_feature.Inline.diff
@@ -2,24 +2,24 @@
 + // MIR for `inlined_target_feature` after Inline
   
   fn inlined_target_feature() -> () {
-      let mut _0: ();                      // return place in scope 0 at $DIR/inline-compatibility.rs:13:40: 13:40
-      let _1: ();                          // in scope 0 at $DIR/inline-compatibility.rs:14:5: 14:21
-+     scope 1 (inlined target_feature) {   // at $DIR/inline-compatibility.rs:14:5: 14:21
+      let mut _0: ();                      // return place in scope 0 at $DIR/inline-compatibility.rs:12:40: 12:40
+      let _1: ();                          // in scope 0 at $DIR/inline-compatibility.rs:13:5: 13: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:14:5: 14:21
--         _1 = target_feature() -> bb1;    // scope 0 at $DIR/inline-compatibility.rs:14:5: 14:21
+          StorageLive(_1);                 // scope 0 at $DIR/inline-compatibility.rs:13:5: 13:21
+-         _1 = target_feature() -> bb1;    // scope 0 at $DIR/inline-compatibility.rs:13:5: 13:21
 -                                          // mir::Constant
--                                          // + span: $DIR/inline-compatibility.rs:14:5: 14:19
+-                                          // + span: $DIR/inline-compatibility.rs:13:5: 13:19
 -                                          // + literal: Const { ty: unsafe fn() {target_feature}, val: Value(Scalar(<ZST>)) }
 -     }
 - 
 -     bb1: {
-+         _1 = const ();                   // scope 1 at $DIR/inline-compatibility.rs:14:5: 14:21
-          StorageDead(_1);                 // scope 0 at $DIR/inline-compatibility.rs:14:21: 14:22
-          _0 = const ();                   // scope 0 at $DIR/inline-compatibility.rs:13:40: 15:2
-          return;                          // scope 0 at $DIR/inline-compatibility.rs:15:2: 15:2
++         _1 = const ();                   // scope 1 at $DIR/inline-compatibility.rs:13:5: 13:21
+          StorageDead(_1);                 // scope 0 at $DIR/inline-compatibility.rs:13:21: 13:22
+          _0 = const ();                   // scope 0 at $DIR/inline-compatibility.rs:12:40: 14:2
+          return;                          // scope 0 at $DIR/inline-compatibility.rs:14:2: 14:2
       }
   }
   
diff --git a/src/test/mir-opt/inline/inline_compatibility.not_inlined_c_variadic.Inline.diff b/src/test/mir-opt/inline/inline_compatibility.not_inlined_c_variadic.Inline.diff
new file mode 100644
index 0000000000000..09bca903c80e8
--- /dev/null
+++ b/src/test/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:41:40: 41:40
+      let _1: u32;                         // in scope 0 at $DIR/inline-compatibility.rs:42:9: 42:10
+      scope 1 {
+          debug s => _1;                   // in scope 1 at $DIR/inline-compatibility.rs:42:9: 42:10
+      }
+  
+      bb0: {
+          StorageLive(_1);                 // scope 0 at $DIR/inline-compatibility.rs:42:9: 42: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:42:13: 42:52
+                                           // mir::Constant
+                                           // + span: $DIR/inline-compatibility.rs:42:13: 42:16
+                                           // + literal: Const { ty: unsafe extern "C" fn(u32, ...) -> u32 {sum}, val: Value(Scalar(<ZST>)) }
+      }
+  
+      bb1: {
+          _0 = const ();                   // scope 0 at $DIR/inline-compatibility.rs:41:40: 43:2
+          StorageDead(_1);                 // scope 0 at $DIR/inline-compatibility.rs:43:1: 43:2
+          return;                          // scope 0 at $DIR/inline-compatibility.rs:43:2: 43:2
+      }
+  }
+  
diff --git a/src/test/mir-opt/inline/inline_compatibility.not_inlined_no_sanitize.Inline.diff b/src/test/mir-opt/inline/inline_compatibility.not_inlined_no_sanitize.Inline.diff
index 651eadc1e849c..5af3946f2e501 100644
--- a/src/test/mir-opt/inline/inline_compatibility.not_inlined_no_sanitize.Inline.diff
+++ b/src/test/mir-opt/inline/inline_compatibility.not_inlined_no_sanitize.Inline.diff
@@ -2,21 +2,21 @@
 + // 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:29:41: 29:41
-      let _1: ();                          // in scope 0 at $DIR/inline-compatibility.rs:30:5: 30:18
+      let mut _0: ();                      // return place in scope 0 at $DIR/inline-compatibility.rs:28:41: 28:41
+      let _1: ();                          // in scope 0 at $DIR/inline-compatibility.rs:29:5: 29:18
   
       bb0: {
-          StorageLive(_1);                 // scope 0 at $DIR/inline-compatibility.rs:30:5: 30:18
-          _1 = no_sanitize() -> bb1;       // scope 0 at $DIR/inline-compatibility.rs:30:5: 30:18
+          StorageLive(_1);                 // scope 0 at $DIR/inline-compatibility.rs:29:5: 29:18
+          _1 = no_sanitize() -> bb1;       // scope 0 at $DIR/inline-compatibility.rs:29:5: 29:18
                                            // mir::Constant
-                                           // + span: $DIR/inline-compatibility.rs:30:5: 30:16
+                                           // + span: $DIR/inline-compatibility.rs:29:5: 29:16
                                            // + literal: Const { ty: unsafe fn() {no_sanitize}, val: Value(Scalar(<ZST>)) }
       }
   
       bb1: {
-          StorageDead(_1);                 // scope 0 at $DIR/inline-compatibility.rs:30:18: 30:19
-          _0 = const ();                   // scope 0 at $DIR/inline-compatibility.rs:29:41: 31:2
-          return;                          // scope 0 at $DIR/inline-compatibility.rs:31:2: 31:2
+          StorageDead(_1);                 // scope 0 at $DIR/inline-compatibility.rs:29:18: 29:19
+          _0 = const ();                   // scope 0 at $DIR/inline-compatibility.rs:28:41: 30:2
+          return;                          // scope 0 at $DIR/inline-compatibility.rs:30:2: 30:2
       }
   }
   
diff --git a/src/test/mir-opt/inline/inline_compatibility.not_inlined_target_feature.Inline.diff b/src/test/mir-opt/inline/inline_compatibility.not_inlined_target_feature.Inline.diff
index 55b9edf3adc1f..8c9fa573ce218 100644
--- a/src/test/mir-opt/inline/inline_compatibility.not_inlined_target_feature.Inline.diff
+++ b/src/test/mir-opt/inline/inline_compatibility.not_inlined_target_feature.Inline.diff
@@ -2,21 +2,21 @@
 + // 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:18:44: 18:44
-      let _1: ();                          // in scope 0 at $DIR/inline-compatibility.rs:19:5: 19:21
+      let mut _0: ();                      // return place in scope 0 at $DIR/inline-compatibility.rs:17:44: 17:44
+      let _1: ();                          // in scope 0 at $DIR/inline-compatibility.rs:18:5: 18:21
   
       bb0: {
-          StorageLive(_1);                 // scope 0 at $DIR/inline-compatibility.rs:19:5: 19:21
-          _1 = target_feature() -> bb1;    // scope 0 at $DIR/inline-compatibility.rs:19:5: 19:21
+          StorageLive(_1);                 // scope 0 at $DIR/inline-compatibility.rs:18:5: 18:21
+          _1 = target_feature() -> bb1;    // scope 0 at $DIR/inline-compatibility.rs:18:5: 18:21
                                            // mir::Constant
-                                           // + span: $DIR/inline-compatibility.rs:19:5: 19:19
+                                           // + span: $DIR/inline-compatibility.rs:18:5: 18:19
                                            // + literal: Const { ty: unsafe fn() {target_feature}, val: Value(Scalar(<ZST>)) }
       }
   
       bb1: {
-          StorageDead(_1);                 // scope 0 at $DIR/inline-compatibility.rs:19:21: 19:22
-          _0 = const ();                   // scope 0 at $DIR/inline-compatibility.rs:18:44: 20:2
-          return;                          // scope 0 at $DIR/inline-compatibility.rs:20:2: 20:2
+          StorageDead(_1);                 // scope 0 at $DIR/inline-compatibility.rs:18:21: 18:22
+          _0 = const ();                   // scope 0 at $DIR/inline-compatibility.rs:17:44: 19:2
+          return;                          // scope 0 at $DIR/inline-compatibility.rs:19:2: 19:2
       }
   }
   
diff --git a/src/test/mir-opt/inline/inline_generator.main.Inline.diff b/src/test/mir-opt/inline/inline_generator.main.Inline.diff
new file mode 100644
index 0000000000000..aa32daa82dd51
--- /dev/null
+++ b/src/test/mir-opt/inline/inline_generator.main.Inline.diff
@@ -0,0 +1,123 @@
+- // 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:8:11: 8:11
+      let _1: std::ops::GeneratorState<<impl std::ops::Generator<bool> as std::ops::Generator<bool>>::Yield, <impl std::ops::Generator<bool> as std::ops::Generator<bool>>::Return>; // in scope 0 at $DIR/inline-generator.rs:9:9: 9:11
+      let mut _2: std::pin::Pin<&mut impl std::ops::Generator<bool>>; // in scope 0 at $DIR/inline-generator.rs:9:14: 9:32
+      let mut _3: &mut impl std::ops::Generator<bool>; // in scope 0 at $DIR/inline-generator.rs:9:23: 9:31
+      let mut _4: impl std::ops::Generator<bool>; // in scope 0 at $DIR/inline-generator.rs:9:28: 9:31
++     let mut _7: bool;                    // in scope 0 at $DIR/inline-generator.rs:9:14: 9:46
+      scope 1 {
+          debug _r => _1;                  // in scope 1 at $DIR/inline-generator.rs:9:9: 9: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:41 {bool, i32}]>::new) { // at $DIR/inline-generator.rs:9:14: 9:32
++         debug pointer => _3;             // in scope 3 at $DIR/inline-generator.rs:9:14: 9:32
++         let mut _5: &mut [generator@$DIR/inline-generator.rs:15:5: 15:41 {bool, i32}]; // in scope 3 at $DIR/inline-generator.rs:9:14: 9:32
++         scope 4 {
++             scope 5 (inlined Pin::<&mut [generator@$DIR/inline-generator.rs:15:5: 15:41 {bool, i32}]>::new_unchecked) { // at $DIR/inline-generator.rs:9:14: 9:32
++                 debug pointer => _5;     // in scope 5 at $DIR/inline-generator.rs:9:14: 9:32
++                 let mut _6: &mut [generator@$DIR/inline-generator.rs:15:5: 15:41 {bool, i32}]; // in scope 5 at $DIR/inline-generator.rs:9:14: 9:32
++             }
++         }
++     }
++     scope 6 (inlined g::{closure#0}) {   // at $DIR/inline-generator.rs:9:14: 9:46
++         debug a => _8;                   // in scope 6 at $DIR/inline-generator.rs:9:14: 9:46
++         let mut _8: bool;                // in scope 6 at $DIR/inline-generator.rs:9:14: 9:46
++         let mut _9: u32;                 // in scope 6 at $DIR/inline-generator.rs:9:14: 9:46
++     }
+  
+      bb0: {
+          StorageLive(_1);                 // scope 0 at $DIR/inline-generator.rs:9:9: 9:11
+          StorageLive(_2);                 // scope 0 at $DIR/inline-generator.rs:9:14: 9:32
+          StorageLive(_3);                 // scope 0 at $DIR/inline-generator.rs:9:23: 9:31
+          StorageLive(_4);                 // scope 0 at $DIR/inline-generator.rs:9:28: 9:31
+-         _4 = g() -> bb1;                 // scope 0 at $DIR/inline-generator.rs:9:28: 9:31
+-                                          // mir::Constant
+-                                          // + span: $DIR/inline-generator.rs:9:28: 9:29
+-                                          // + literal: Const { ty: fn() -> impl std::ops::Generator<bool> {g}, val: Value(Scalar(<ZST>)) }
+-     }
+- 
+-     bb1: {
++         discriminant(_4) = 0;            // scope 2 at $DIR/inline-generator.rs:9:28: 9:31
+          _3 = &mut _4;                    // scope 0 at $DIR/inline-generator.rs:9:23: 9:31
+-         _2 = Pin::<&mut impl Generator<bool>>::new(move _3) -> [return: bb2, unwind: bb4]; // scope 0 at $DIR/inline-generator.rs:9:14: 9:32
+-                                          // mir::Constant
+-                                          // + span: $DIR/inline-generator.rs:9:14: 9:22
+-                                          // + user_ty: UserType(0)
+-                                          // + literal: Const { ty: fn(&mut impl std::ops::Generator<bool>) -> std::pin::Pin<&mut impl std::ops::Generator<bool>> {std::pin::Pin::<&mut impl std::ops::Generator<bool>>::new}, val: Value(Scalar(<ZST>)) }
+-     }
+- 
+-     bb2: {
++         StorageLive(_5);                 // scope 4 at $DIR/inline-generator.rs:9:14: 9:32
++         _5 = move _3;                    // scope 4 at $DIR/inline-generator.rs:9:14: 9:32
++         StorageLive(_6);                 // scope 5 at $DIR/inline-generator.rs:9:14: 9:32
++         _6 = move _5;                    // scope 5 at $DIR/inline-generator.rs:9:14: 9:32
++         (_2.0: &mut [generator@$DIR/inline-generator.rs:15:5: 15:41 {bool, i32}]) = move _6; // scope 5 at $DIR/inline-generator.rs:9:14: 9:32
++         StorageDead(_6);                 // scope 5 at $DIR/inline-generator.rs:9:14: 9:32
++         StorageDead(_5);                 // scope 4 at $DIR/inline-generator.rs:9:14: 9:32
+          StorageDead(_3);                 // scope 0 at $DIR/inline-generator.rs:9:31: 9:32
+-         _1 = <impl Generator<bool> as Generator<bool>>::resume(move _2, const false) -> [return: bb3, unwind: bb4]; // scope 0 at $DIR/inline-generator.rs:9:14: 9:46
+-                                          // mir::Constant
+-                                          // + span: $DIR/inline-generator.rs:9:33: 9:39
+-                                          // + literal: Const { ty: for<'r> fn(std::pin::Pin<&'r mut impl std::ops::Generator<bool>>, bool) -> std::ops::GeneratorState<<impl std::ops::Generator<bool> as std::ops::Generator<bool>>::Yield, <impl std::ops::Generator<bool> as std::ops::Generator<bool>>::Return> {<impl std::ops::Generator<bool> as std::ops::Generator<bool>>::resume}, val: Value(Scalar(<ZST>)) }
++         StorageLive(_7);                 // scope 0 at $DIR/inline-generator.rs:9:14: 9:46
++         _7 = const false;                // scope 0 at $DIR/inline-generator.rs:9:14: 9:46
++         _9 = discriminant((*(_2.0: &mut [generator@$DIR/inline-generator.rs:15:5: 15:41 {bool, i32}]))); // scope 6 at $DIR/inline-generator.rs:9:14: 9:46
++         switchInt(move _9) -> [0_u32: bb3, 1_u32: bb8, 3_u32: bb7, otherwise: bb9]; // scope 6 at $DIR/inline-generator.rs:9:14: 9:46
+      }
+  
+-     bb3: {
++     bb1: {
++         StorageDead(_7);                 // scope 0 at $DIR/inline-generator.rs:9:14: 9:46
+          StorageDead(_2);                 // scope 0 at $DIR/inline-generator.rs:9:45: 9:46
+          StorageDead(_4);                 // scope 0 at $DIR/inline-generator.rs:9:46: 9:47
+          _0 = const ();                   // scope 0 at $DIR/inline-generator.rs:8:11: 10:2
+          StorageDead(_1);                 // scope 0 at $DIR/inline-generator.rs:10:1: 10:2
+          return;                          // scope 0 at $DIR/inline-generator.rs:10:2: 10:2
+      }
+  
+-     bb4 (cleanup): {
++     bb2 (cleanup): {
+          resume;                          // scope 0 at $DIR/inline-generator.rs:8:1: 10:2
++     }
++ 
++     bb3: {
++         _8 = move _7;                    // scope 6 at $DIR/inline-generator.rs:9:14: 9:46
++         switchInt(_8) -> [false: bb4, otherwise: bb5]; // scope 6 at $DIR/inline-generator.rs:9:14: 9:46
++     }
++ 
++     bb4: {
++         ((_1 as Yielded).0: i32) = const 13_i32; // scope 6 at $DIR/inline-generator.rs:9:14: 9:46
++         goto -> bb6;                     // scope 6 at $DIR/inline-generator.rs:9:14: 9:46
++     }
++ 
++     bb5: {
++         ((_1 as Yielded).0: i32) = const 7_i32; // scope 6 at $DIR/inline-generator.rs:9:14: 9:46
++         goto -> bb6;                     // scope 6 at $DIR/inline-generator.rs:9:14: 9:46
++     }
++ 
++     bb6: {
++         discriminant(_1) = 0;            // scope 6 at $DIR/inline-generator.rs:9:14: 9:46
++         discriminant((*(_2.0: &mut [generator@$DIR/inline-generator.rs:15:5: 15:41 {bool, i32}]))) = 3; // scope 6 at $DIR/inline-generator.rs:9:14: 9:46
++         goto -> bb1;                     // scope 0 at $DIR/inline-generator.rs:15:11: 15:39
++     }
++ 
++     bb7: {
++         ((_1 as Complete).0: bool) = move _7; // scope 6 at $DIR/inline-generator.rs:9:14: 9:46
++         discriminant(_1) = 1;            // scope 6 at $DIR/inline-generator.rs:9:14: 9:46
++         discriminant((*(_2.0: &mut [generator@$DIR/inline-generator.rs:15:5: 15:41 {bool, i32}]))) = 1; // scope 6 at $DIR/inline-generator.rs:9:14: 9:46
++         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:9:14: 9:46
++     }
++ 
++     bb9: {
++         unreachable;                     // scope 6 at $DIR/inline-generator.rs:9:14: 9:46
+      }
+  }
+