From 3128b8f261e00b773cabba88fb64b2e81290e25a Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Tue, 26 Jul 2022 22:20:46 +0200 Subject: [PATCH] Enable MIR inlining on generators. --- compiler/rustc_mir_transform/src/inline.rs | 6 ---- src/test/mir-opt/inline/inline-async.rs | 17 +++++----- .../mir-opt/inline/inline_async.g.Inline.diff | 34 +++++++++++++++++++ .../mir-opt/inline/inline_async.h.Inline.diff | 29 ++++++++++++++++ 4 files changed, 72 insertions(+), 14 deletions(-) create mode 100644 src/test/mir-opt/inline/inline_async.g.Inline.diff create mode 100644 src/test/mir-opt/inline/inline_async.h.Inline.diff diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index 5b676714109cd..c6c4f9701294f 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -79,12 +79,6 @@ fn inline<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) -> bool { if body.source.promoted.is_some() { return false; } - // Avoid inlining into generators, since their `optimized_mir` is used for layout computation, - // which can create a cycle, even when no attempt is made to inline the function in the other - // direction. - if tcx.generator_kind(def_id).is_some() { - return false; - } let param_env = tcx.param_env_reveal_all_normalized(def_id); diff --git a/src/test/mir-opt/inline/inline-async.rs b/src/test/mir-opt/inline/inline-async.rs index 5c838159b986c..079ef5ded8767 100644 --- a/src/test/mir-opt/inline/inline-async.rs +++ b/src/test/mir-opt/inline/inline-async.rs @@ -1,5 +1,4 @@ // 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 @@ -8,11 +7,13 @@ pub struct S; -impl S { - pub async fn g(&mut self) { - self.h(); - } - pub fn h(&mut self) { - let _ = self.g(); - } +// EMIT_MIR inline_async.g.Inline.diff +pub async fn g(s: &mut S) { + h(s); +} + +// EMIT_MIR inline_async.h.Inline.diff +#[inline(always)] +pub fn h(s: &mut S) { + let _ = g(s); } diff --git a/src/test/mir-opt/inline/inline_async.g.Inline.diff b/src/test/mir-opt/inline/inline_async.g.Inline.diff new file mode 100644 index 0000000000000..1c4cbcf052abc --- /dev/null +++ b/src/test/mir-opt/inline/inline_async.g.Inline.diff @@ -0,0 +1,34 @@ +- // MIR for `g` before Inline ++ // MIR for `g` after Inline + + fn g(_1: &mut S) -> std::future::from_generator::GenFuture<[static generator@$DIR/inline-async.rs:11:27: 13:2]> { + debug s => _1; // in scope 0 at $DIR/inline-async.rs:+0:16: +0:17 + let mut _0: std::future::from_generator::GenFuture<[static generator@$DIR/inline-async.rs:11:27: 13:2]>; // return place in scope 0 at $DIR/inline-async.rs:+0:27: +0:27 + let mut _2: [static generator@$DIR/inline-async.rs:11:27: 13:2]; // in scope 0 at $DIR/inline-async.rs:+0:27: +2:2 ++ scope 1 (inlined std::future::from_generator::<[static generator@$DIR/inline-async.rs:11:27: 13:2]>) { // at $DIR/inline-async.rs:11:27: 13:2 ++ debug gen => _2; // in scope 1 at $SRC_DIR/core/src/future/mod.rs:LL:COL ++ let mut _3: [static generator@$DIR/inline-async.rs:11:27: 13:2]; // in scope 1 at $SRC_DIR/core/src/future/mod.rs:LL:COL ++ } + + bb0: { + StorageLive(_2); // scope 0 at $DIR/inline-async.rs:+0:27: +2:2 + Deinit(_2); // scope 0 at $DIR/inline-async.rs:+0:27: +2:2 + (_2.0: &mut S) = move _1; // scope 0 at $DIR/inline-async.rs:+0:27: +2:2 + discriminant(_2) = 0; // scope 0 at $DIR/inline-async.rs:+0:27: +2:2 +- _0 = std::future::from_generator::<[static generator@$DIR/inline-async.rs:11:27: 13:2]>(move _2) -> bb1; // scope 0 at $DIR/inline-async.rs:+0:27: +2:2 +- // mir::Constant +- // + span: $DIR/inline-async.rs:11:27: 13:2 +- // + literal: Const { ty: fn([static generator@$DIR/inline-async.rs:11:27: 13:2]) -> impl Future {std::future::from_generator::<[static generator@$DIR/inline-async.rs:11:27: 13:2]>}, val: Value() } +- } +- +- bb1: { ++ StorageLive(_3); // scope 1 at $SRC_DIR/core/src/future/mod.rs:LL:COL ++ _3 = move _2; // scope 1 at $SRC_DIR/core/src/future/mod.rs:LL:COL ++ Deinit(_0); // scope 1 at $SRC_DIR/core/src/future/mod.rs:LL:COL ++ (_0.0: [static generator@$DIR/inline-async.rs:11:27: 13:2]) = move _3; // scope 1 at $SRC_DIR/core/src/future/mod.rs:LL:COL ++ StorageDead(_3); // scope 1 at $SRC_DIR/core/src/future/mod.rs:LL:COL + StorageDead(_2); // scope 0 at $DIR/inline-async.rs:+2:1: +2:2 + return; // scope 0 at $DIR/inline-async.rs:+2:2: +2:2 + } + } + diff --git a/src/test/mir-opt/inline/inline_async.h.Inline.diff b/src/test/mir-opt/inline/inline_async.h.Inline.diff new file mode 100644 index 0000000000000..f0e13389f2387 --- /dev/null +++ b/src/test/mir-opt/inline/inline_async.h.Inline.diff @@ -0,0 +1,29 @@ +- // MIR for `h` before Inline ++ // MIR for `h` after Inline + + fn h(_1: &mut S) -> () { + debug s => _1; // in scope 0 at $DIR/inline-async.rs:+0:10: +0:11 + let mut _0: (); // return place in scope 0 at $DIR/inline-async.rs:+0:21: +0:21 + let mut _2: std::future::from_generator::GenFuture<[static generator@$DIR/inline-async.rs:11:27: 13:2]>; // in scope 0 at $DIR/inline-async.rs:+1:13: +1:17 + let mut _3: &mut S; // in scope 0 at $DIR/inline-async.rs:+1:15: +1:16 + scope 1 { + } + + bb0: { + StorageLive(_2); // scope 0 at $DIR/inline-async.rs:+1:13: +1:17 + StorageLive(_3); // scope 0 at $DIR/inline-async.rs:+1:15: +1:16 + _3 = &mut (*_1); // scope 0 at $DIR/inline-async.rs:+1:15: +1:16 + _2 = g(move _3) -> bb1; // scope 0 at $DIR/inline-async.rs:+1:13: +1:17 + // mir::Constant + // + span: $DIR/inline-async.rs:18:13: 18:14 + // + literal: Const { ty: for<'r> fn(&'r mut S) -> impl for<'r> Future {g}, val: Value() } + } + + bb1: { + StorageDead(_3); // scope 0 at $DIR/inline-async.rs:+1:16: +1:17 + StorageDead(_2); // scope 0 at $DIR/inline-async.rs:+1:17: +1:18 + _0 = const (); // scope 0 at $DIR/inline-async.rs:+0:21: +2:2 + return; // scope 0 at $DIR/inline-async.rs:+2:2: +2:2 + } + } +