Rollup merge of #78580 - tmiasko:inline-loop, r=oli-obk

inliner: Break inlining cycles

Keep track of all instances inlined so far. When examining a new call
sites from an inlined body, skip those where callee had been inlined
already to avoid potential inlining cycles.

Fixes #78573.
This commit is contained in:
Dylan DPC 2020-11-09 19:06:53 +01:00 committed by GitHub
commit ee1fedf392
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 248 additions and 123 deletions

View file

@ -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);
}

View file

@ -0,0 +1,27 @@
- // 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:13:10: 13:10
let _1: (); // in scope 0 at $DIR/inline-cycle.rs:14:5: 14:24
+ scope 1 (inlined <C as Call>::call) { // at $DIR/inline-cycle.rs:14:5: 14:24
+ }
bb0: {
StorageLive(_1); // scope 0 at $DIR/inline-cycle.rs:14:5: 14:24
- _1 = <C as Call>::call() -> bb1; // scope 0 at $DIR/inline-cycle.rs:14:5: 14:24
+ _1 = <A<C> as Call>::call() -> bb1; // scope 1 at $DIR/inline-cycle.rs:14:5: 14:24
// mir::Constant
- // + span: $DIR/inline-cycle.rs:14:5: 14:22
- // + literal: Const { ty: fn() {<C as Call>::call}, val: Value(Scalar(<ZST>)) }
+ // + span: $DIR/inline-cycle.rs:14:5: 14:24
+ // + literal: Const { ty: fn() {<A<C> as Call>::call}, val: Value(Scalar(<ZST>)) }
}
bb1: {
StorageDead(_1); // scope 0 at $DIR/inline-cycle.rs:14:24: 14:25
_0 = const (); // scope 0 at $DIR/inline-cycle.rs:13:10: 15:2
return; // scope 0 at $DIR/inline-cycle.rs:15:2: 15:2
}
}

View file

@ -0,0 +1,47 @@
- // 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:48:10: 48:10
let _1: (); // in scope 0 at $DIR/inline-cycle.rs:49:5: 49:12
+ let mut _2: fn() {f}; // in scope 0 at $DIR/inline-cycle.rs:49:5: 49:12
+ let mut _5: (); // in scope 0 at $DIR/inline-cycle.rs:49:5: 49: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:49:5: 49:12
+ let _3: (); // in scope 1 at $DIR/inline-cycle.rs:49:5: 49:12
+ let mut _4: fn() {f}; // in scope 1 at $DIR/inline-cycle.rs:49:5: 49:12
+ scope 2 (inlined <fn() {f} as FnOnce<()>>::call_once - shim(fn() {f})) { // at $DIR/inline-cycle.rs:49:5: 49:12
+ }
+ }
bb0: {
StorageLive(_1); // scope 0 at $DIR/inline-cycle.rs:49:5: 49:12
- _1 = call::<fn() {f}>(f) -> bb1; // scope 0 at $DIR/inline-cycle.rs:49:5: 49:12
+ StorageLive(_2); // scope 0 at $DIR/inline-cycle.rs:49:5: 49:12
+ _2 = f; // scope 0 at $DIR/inline-cycle.rs:49:5: 49:12
// mir::Constant
- // + span: $DIR/inline-cycle.rs:49:5: 49:9
- // + literal: Const { ty: fn(fn() {f}) {call::<fn() {f}>}, val: Value(Scalar(<ZST>)) }
- // mir::Constant
// + span: $DIR/inline-cycle.rs:49:10: 49:11
// + literal: Const { ty: fn() {f}, val: Value(Scalar(<ZST>)) }
+ StorageLive(_3); // scope 1 at $DIR/inline-cycle.rs:49:5: 49:12
+ StorageLive(_4); // scope 1 at $DIR/inline-cycle.rs:49:5: 49:12
+ _4 = move _2; // scope 1 at $DIR/inline-cycle.rs:49:5: 49:12
+ StorageLive(_5); // scope 1 at $DIR/inline-cycle.rs:49:5: 49:12
+ _5 = const (); // scope 1 at $DIR/inline-cycle.rs:49:5: 49:12
+ _3 = move _4() -> bb1; // scope 2 at $DIR/inline-cycle.rs:49:5: 49:12
}
bb1: {
+ StorageDead(_5); // scope 1 at $DIR/inline-cycle.rs:49:5: 49:12
+ StorageDead(_4); // scope 1 at $DIR/inline-cycle.rs:49:5: 49:12
+ StorageDead(_3); // scope 1 at $DIR/inline-cycle.rs:49:5: 49:12
+ _1 = const (); // scope 1 at $DIR/inline-cycle.rs:49:5: 49:12
+ StorageDead(_2); // scope 0 at $DIR/inline-cycle.rs:49:5: 49:12
StorageDead(_1); // scope 0 at $DIR/inline-cycle.rs:49:12: 49:13
_0 = const (); // scope 0 at $DIR/inline-cycle.rs:48:10: 50:2
return; // scope 0 at $DIR/inline-cycle.rs:50:2: 50:2
}
}