Add -Zdead-fn-elimination: skip codegen of functions unreachable from the entry point#158220
Add -Zdead-fn-elimination: skip codegen of functions unreachable from the entry point#158220yijunyu wants to merge 1 commit into
Conversation
|
Thanks for the pull request, and welcome! The Rust Project is excited to review your changes, and you should hear from @oli-obk (or someone else) some time within the next two weeks. Please see the contribution instructions for more information. Namely, in order to ensure the minimum review times lag, PR authors and assigned reviewers should ensure that the review label (
|
This comment has been minimized.
This comment has been minimized.
… the entry point Adds an unstable flag that, for binary crates, computes the set of functions reachable from the entry point (via a MIR call-graph BFS seeded with the reachability set, the entry fn, and vtable-constructed trait methods) and excludes the rest from codegen by filtering them out of the mono item set before partitioning. The analysis is conservative: it never eliminates a function in the collected mono set, lang items, exported symbols, the entry fn, drop glue, generics, or async fns. A debug-assertions invariant checks reachable_set is a subset of the post-BFS set. The flag is inert when unset.
|
This PR was rebased onto a different main commit. Here's a range-diff highlighting what actually changed. Rebasing is a normal part of keeping PRs up to date, so no action is needed—this note is just to help reviewers. |
|
I still don't get what you are trying to do. If functions are unreachable from monomorphization roots (
Can you show a list of functions that are actually eliminated? |
Implements the accepted MCP compiler-team#976: an unstable flag that skips codegen of functions a binary cannot reach from its entry point.
What it does
-Zdead-fn-elimination(off by default) adds, for binary crates only, a reachability analysis that runs after monomorphization collection and before partitioning. Functions unreachable from the entry point are dropped from the mono item set, so the backend never generates LLVM IR for them.The flag is inert when unset.
How it works
In
collect_and_partition_mono_items, aftercollect_crate_mono_itemsand beforepartition:optimized_mir), recording direct calls, function references in constants/statics, address-taken functions, and inline-asmsymoperands.reachable_set(covers exported/pub/lang-item/#[no_mangle]/#[used]items), the entry fn, and the methods of anydyn-constructed trait (dynamic dispatch is invisible to a call-graph walk, so vtable methods are seeded explicitly).retainthe mono item set, dropping only localMonoItem::Fns that are eliminable.Conservatism
The analysis never eliminates:
A
#[cfg(debug_assertions)]invariant checks thatreachable_setis a subset of the post-BFS reachable set.Soundness testing
Verified on a stage1 build by compiling real binaries with and without the flag using the same compiler and diffing the output:
-n/-i/-c/-w/-v/-o,--json, recursive)math sum,strops,sort, record access,eachclosures)Edge cases checked: flag-off and flag-on both produce reproducible binaries; library crates are inert (no entry seed); the
#[test]harness still runs;panic=abortworks;-C link-dead-codecorrectly defers (no elimination). Functions reached only through a closure (Iterator::map), a trait object (Box<dyn Fn>), or a function pointer are kept — only genuinely-unreachable functions are removed.tests/codegen-units(46) andtests/ui/codegen(147) pass; tidy is clean.Scope
This is the in-rustc flag only. It is self-contained and reviewable in isolation; there is no build-system or cross-crate coordination in this PR.
r? @oli-obk