Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

inliner: Break inlining cycles #78580

Merged
merged 2 commits into from
Nov 10, 2020
Merged

inliner: Break inlining cycles #78580

merged 2 commits into from
Nov 10, 2020

Conversation

tmiasko
Copy link
Contributor

@tmiasko tmiasko commented Oct 30, 2020

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.

@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Oct 30, 2020
@camelid camelid added the A-mir-opt-inlining Area: MIR inlining label Oct 30, 2020
@lcnr
Copy link
Contributor

lcnr commented Oct 31, 2020

LTGM, r? @oli-obk for final approval

@rust-highfive rust-highfive assigned oli-obk and unassigned lcnr Oct 31, 2020
Copy link

@antonholmberg antonholmberg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi! I am really new to the rust community so I am not sure if it's okay to review things that you aren't assigned to so feel free to ignore my comment if you want to.

compiler/rustc_mir/src/transform/inline.rs Outdated Show resolved Hide resolved
@oli-obk
Copy link
Contributor

oli-obk commented Nov 1, 2020

I am not sure if it's okay to review things that you aren't assigned to so feel free to ignore my comment if you want to.

It's totally ok. I found it especially good that your review was asking whether a change would be good, instead of saying "do XYZ".

@oli-obk
Copy link
Contributor

oli-obk commented Nov 1, 2020

Hmm... will #68828 automatically prevent these situations? Or could we somehow extend that to also catch this case?

@tmiasko
Copy link
Contributor Author

tmiasko commented Nov 1, 2020

This addresses inlining cycles that become apparent only after the substitution or between functions from a different crate. For #68828 to address this issue, it would have to never inline a body where Instance::resolve had failed (including both local and non-local crates).

@oli-obk
Copy link
Contributor

oli-obk commented Nov 1, 2020

We could also list generic params which are used in function calls together with concrete function calls. This way the inliner can decide directly whether to inline, and not do it "after the fact". The main reason I'm asking this is src/test/mir-opt/inline/inline_cycle.one.Inline.diff which has

-         _1 = <C as Call>::call() -> bb1; // scope 0 at $DIR/inline-cycle.rs:14:5: 14:24
+         _1 = <C as Call>::call() -> bb1; // scope 3 at $DIR/inline-cycle.rs:36:9: 36:28

which, imo should never happen.

@tmiasko
Copy link
Contributor Author

tmiasko commented Nov 1, 2020

What exactly should never happen?

@antonholmberg
Copy link

antonholmberg commented Nov 1, 2020

it would have to never inline a body where Instance::resolve had failed (including both local and non-local crates).

Isn't this already the case since get_valid_function_call runs?

let callee =
    Instance::resolve(self.tcx, self.param_env, callee_def_id, normalized_substs)
        .ok()
        .flatten()?;

@tmiasko tmiasko changed the title inliner: Skip calls that could be recursive inliner: Break inlining cycles Nov 1, 2020
@oli-obk
Copy link
Contributor

oli-obk commented Nov 2, 2020

What exactly should never happen?

In this case we are inlining a function call, only to end up with the exact same function call again. All this does is to change the spans and debug info on the call, which will make the debugging experience weird

@tmiasko
Copy link
Contributor Author

tmiasko commented Nov 2, 2020

In this case we are inlining a function call, only to end up with the exact same function call again. All this does is to change the spans and debug info on the call, which will make the debugging experience weird

Yes, it this case decision to inline is a bad one. We could prevent such direct self-recursion by looking ahead in the callee body (the body is already optimized, so it is self-recursion after applying the substs). Generally speaking the aspiration of this PR is to stop the inlining cycles, rather than modify the inlining heuristic, but I can modify the heuristic as well.

@oli-obk
Copy link
Contributor

oli-obk commented Nov 2, 2020

but I can modify the heuristic as well.

Instead of doing both, could just modifying the heuristic to detect inlining cycles also fix the infinite loop?

@bors
Copy link
Contributor

bors commented Nov 3, 2020

☔ The latest upstream changes (presumably #78697) made this pull request unmergeable. Please resolve the merge conflicts.

Note that reviewers usually do not review pull requests until merge conflicts are resolved! Once you resolve the conflicts, you should change the labels applied by bors to indicate that your PR is ready for review. Post this as a comment to change the labels:

@rustbot modify labels: +S-waiting-on-review -S-waiting-on-author

@tmiasko
Copy link
Contributor Author

tmiasko commented Nov 6, 2020

could just modifying the heuristic to detect inlining cycles also fix the infinite loop?

I can modify the approach to look for self-recursive calls and calls to instances that are already part of inlining history one step ahead in should_inline.

@tmiasko tmiasko force-pushed the inline-loop branch 3 times, most recently from 063dff5 to 018fd86 Compare November 6, 2020 23:29
@bors
Copy link
Contributor

bors commented Nov 9, 2020

☔ The latest upstream changes (presumably #78889) made this pull request unmergeable. Please resolve the merge conflicts.

Note that reviewers usually do not review pull requests until merge conflicts are resolved! Once you resolve the conflicts, you should change the labels applied by bors to indicate that your PR is ready for review. Post this as a comment to change the labels:

@rustbot modify labels: +S-waiting-on-review -S-waiting-on-author

Copy link
Contributor

@oli-obk oli-obk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like this approach much better. Thanks!

Just a nit, then this lgtm

compiler/rustc_mir/src/transform/inline.rs Outdated Show resolved Hide resolved
The inliner does not support inlining of divering calls. Reject them
early on and turn `inline_call` into an infallible operation.
When examining candidates for inlining, reject those that are determined
to be recursive either because of self-recursive calls or calls to any
instances already inlined.
@oli-obk
Copy link
Contributor

oli-obk commented Nov 9, 2020

@bors r+

@bors
Copy link
Contributor

bors commented Nov 9, 2020

📌 Commit dc4d74d has been approved by oli-obk

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Nov 9, 2020
bors added a commit to rust-lang-ci/rust that referenced this pull request Nov 10, 2020
Rollup of 12 pull requests

Successful merges:

 - rust-lang#74754 (Add `#[cfg(panic = '...')]`)
 - rust-lang#76468 (Improve lifetime name annotations for closures & async functions)
 - rust-lang#77016 (Test clippy on PR CI on changes)
 - rust-lang#78480 (BTreeMap: fix pointer provenance rules)
 - rust-lang#78502 (Update Chalk to 0.36.0)
 - rust-lang#78513 (Infer the default host target from the host toolchain if possible)
 - rust-lang#78566 (Enable LLVM Polly via llvm-args.)
 - rust-lang#78580 (inliner: Break inlining cycles)
 - rust-lang#78710 (rustc_ast: Do not panic by default when visiting macro calls)
 - rust-lang#78746 (Demote i686-unknown-freebsd to tier 2 compiler target)
 - rust-lang#78830 (fix `super_visit_with` for `Terminator`)
 - rust-lang#78844 (Monomorphize a type argument of size-of operation during codegen)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
@bors bors merged commit ee1fedf into rust-lang:master Nov 10, 2020
@rustbot rustbot added this to the 1.49.0 milestone Nov 10, 2020
@tmiasko tmiasko deleted the inline-loop branch November 10, 2020 13:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-mir-opt-inlining Area: MIR inlining S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Infinite loop when inlining
8 participants