Skip to content

Introduce OptimizationObjective and fix the entry shim's size attributes - #164784

Open
cezarbbb wants to merge 1 commit into
rust-lang:mainfrom
cezarbbb:overhaul-size-flags
Open

cezarbbb wants to merge 1 commit into
rust-lang:mainfrom
cezarbbb:overhaul-size-flags

Conversation

@cezarbbb

@cezarbbb cezarbbb commented Oct 23, 2026 •

Copy link
Copy Markdown
Contributor

The MIR inliner's 2 => arm allow-lists More | Aggressive by hand. s/z also derive MIR level 2, so the pass never runs there. I could not find why in the source or the history — the gate predates the tiered match and read mir_opt_level() >= 3, which s/z never satisfied either, and Size/SizeMin simply were not among the entries considered when the match was written. There is no revert or regression behind it. Dumping every MIR pass at all four levels, the pass sets at 2/3 and at s/z differ by exactly one name: Inline. So I enabled it through PassPolicy::size_only() and measured.

The general situation is as follows:
For the .text section in rlib files, I tested 24 crates; the results were −3.59% (17/24) for os and −5.78% (16/24) for oz.
Additional test data includes:

76-crate sample, Σ stripped: −0.08% (os), −0.13% (oz)
22 apps, Σ stripped: −0.09% (os), −0.07% (oz)
22 apps, on-disk bytes: −0.40% (7/22) (os), −0.74% (11/22) for (oz)
22 apps, Σ .text: +0.18% (os), +0.84% ​​(oz)

Is enabling MIR inlining at s/z the right direction, given that it clearly shrinks libraries and application binaries on disk while growing application .text?

Update: as @oli-obk asked, the refactoring is now its own commit. The MIR inliner change will move out to another PR. The measurements above are why I still think it is worth doing, but it does not belong in this PR.

When I Split it out I found that LLVM 23 no longer has Os/Oz as pipeline levels, they both build the O2 pipeline now, and what marks a function as size-optimized is the optsize/minsize attribute on it. So at -Copt-level=s/z there is no longer any setting rustc hands to LLVM that says "this is a size build", it is entirely per-function.

It exposed a gap that the C entry shim and __rust_try have no item behind them and never go through the per-item attribute path, so they were the only definitions in a size build that LLVM optimized for speed. They now get the same attributes as everything else.

The refactoring itself gives size-versus-speed a name and moves the sites that are really asking "what is this build optimizing for" onto it. The ones that are asking "how hard" — the linker and pipeline level tables, where s and z map to different strings, still match on OptLevel. CodeGenOptSize was already being discarded at its only call site, so it is gone.

There are codegen tests for each knob that now reads the objective, at 2, s and z.

@rustbot

rustbot commented Oct 23, 2026

Copy link
Copy Markdown
Collaborator

Some changes occurred to MIR optimizations

cc @rust-lang/wg-mir-opt

@rustbot rustbot added A-LLVM Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues. A-run-make Area: port run-make Makefiles to rmake.rs S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Oct 23, 2026
@rustbot

rustbot commented Oct 23, 2026

Copy link
Copy Markdown
Collaborator

r? @jieyouxu

rustbot has assigned @jieyouxu.
They will have a look at your PR within the next two weeks and either review your PR or reassign to another reviewer.

Use r? to explicitly pick a reviewer

Why was this reviewer chosen?

The reviewer was selected based on:

  • Owners of files modified in this PR: compiler
  • compiler expanded to 77 candidates
  • Random selection from 19 candidates

@jieyouxu

Copy link
Copy Markdown
Member

r? mir-opt

@rustbot rustbot assigned oli-obk and unassigned jieyouxu Oct 23, 2026
@oli-obk

oli-obk commented Oct 23, 2026

Copy link
Copy Markdown
Contributor

please pull the refactoring changes out into a separate commit.

do we have anything in the perf test suite that actually uses z or s? I'd love to have some number we change in the perf test suite to track this over time

@oli-obk oli-obk left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

@rustbot rustbot added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Oct 23, 2026
@rustbot

rustbot commented Oct 23, 2026

Copy link
Copy Markdown
Collaborator

Reminder, once the PR becomes ready for a review, use @rustbot ready.

@bjorn3

bjorn3 commented Oct 23, 2026

Copy link
Copy Markdown
Member

Is enabling MIR inlining at s/z the right direction, given that it clearly shrinks libraries and application binaries on disk while growing application .text?

-Copt-level=s/z is most important for embedded applications where the total flash usage (combined size of all sections that will be mapped into memory, so no debuginfo, symbols, ... Generally only .text, .rodata and .data matter in the end) matters, not the size of rlibs or the size of the ELF files of the executable.

@cezarbbb

Copy link
Copy Markdown
Contributor Author

please pull the refactoring changes out into a separate commit.

Alright, I will split this PR into two.

@cezarbbb

Copy link
Copy Markdown
Contributor Author

do we have anything in the perf test suite that actually uses z or s? I'd love to have some number we change in the perf test suite to track this over time

Understood; I will take a look at the perf test suite. Currently, I am conducting tests on my local machine using crates sourced from crates.io.

@cezarbbb

Copy link
Copy Markdown
Contributor Author

-Copt-level=s/z is most important for embedded applications where the total flash usage (combined size of all sections that will be mapped into memory, so no debuginfo, symbols, ... Generally only .text, .rodata and .data matter in the end) matters, not the size of rlibs or the size of the ELF files of the executable.

I will conduct further testing on these sections.

@saethlin

Copy link
Copy Markdown
Member

I don't think this is the right way to improve the size of executables complied with levels s or z. If LLVM is making the wrong inlining decisions we should have an explanation for why LLVM cannot adapt its heuristics to make the right decisions, before we start fighting with its inliner.

What you are trying to do here could be a good idea, but I just want to point out that I have prototyped this change myself and discarded it because I concluded that the MIR inliner is likely to regress code size as often as it helps, because it isn't actually addressing the root cause of the problem inside LLVM.

@cezarbbb

cezarbbb commented Oct 26, 2026 •

Copy link
Copy Markdown
Contributor Author

I don't think this is the right way to improve the size of executables complied with levels s or z. If LLVM is making the wrong inlining decisions we should have an explanation for why LLVM cannot adapt its heuristics to make the right decisions, before we start fighting with its inliner.

What you are trying to do here could be a good idea, but I just want to point out that I have prototyped this change myself and discarded it because I concluded that the MIR inliner is likely to regress code size as often as it helps, because it isn't actually addressing the root cause of the problem inside LLVM.

Hi. I want to separate two questions, because I think they get conflated.

One is whether the inliner makes good decisions and whether it grows code. The other is whether it is right that the MIR inliner has never run at -Os/-Oz at all.

On the second: at -Copt-level=s and z the MIR pass set is the -Copt-level=2 pass set minus inlining and nothing else. At the same time the compiler already treats both levels as level 2 when it decides how much MIR optimisation to do. So one gate, which looks at the global opt level, switches off a single pass that the rest of the pipeline was set up to run.

On the first: I agree the current state is not good, and I am not claiming this change makes executables smaller. LLVM's inliner gives a bonus to a call that is the only remaining call to a local function, because inlining it is known to reduce size. The MIR inliner has no equivalent; it only rewards a callee whose own body contains a single call. The thresholds are not aligned either: at -Oz LLVM lowers its threshold for size-annotated callers to a small number, while the MIR inliner's default is the same at every level. So at z the MIR inliner is considerably more permissive than LLVM while using a weaker model.
So the only thing I want to argue for is the second question. While that gate is closed, any future work on the MIR inliner's size behaviour is dead code at exactly the levels it is meant to serve. Opening it is not a size improvement and I am not presenting it as one. It is a prerequisite for being able to measure one.

@cezarbbb
cezarbbb force-pushed the overhaul-size-flags branch from 4710fdd to 706ca60 Compare October 27, 2026 08:08
@cezarbbb cezarbbb changed the title Run the MIR inliner for os/oz Introduce OptimizationObjective and fix the entry shim's size attributes Oct 27, 2026
@rust-log-analyzer

This comment has been minimized.

@cezarbbb
cezarbbb force-pushed the overhaul-size-flags branch from 706ca60 to 81c0b8e Compare October 27, 2026 09:28
@cezarbbb

Copy link
Copy Markdown
Contributor Author

@rustbot ready

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Oct 27, 2026

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-LLVM Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues. A-run-make Area: port run-make Makefiles to rmake.rs S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants