Skip to content

de-stabilize optimize(speed) - #165592

Open
RalfJung wants to merge 1 commit into
rust-lang:mainfrom
RalfJung:opt-not-speed
Open

RalfJung wants to merge 1 commit into
rust-lang:mainfrom
RalfJung:opt-not-speed

Conversation

@RalfJung

@RalfJung RalfJung commented Nov 7, 2026 •

Copy link
Copy Markdown
Member

View all comments

Reverts parts of #157273.
We don't actually know what this attribute should do (see Zulip). In LLVM, the opt-level is used to configure the entire pass pipeline, it is not possible to overwrite this for a single function. Correspondingly, it currently does very little: it suppresses a global -Copt-level=s/z, but that's it.

Cc @rust-lang/lang
Tracking issue: #165590

@rustbot

rustbot commented Nov 7, 2026

Copy link
Copy Markdown
Collaborator

Some changes occurred in compiler/rustc_attr_parsing

cc @jdonszelmann, @JonathanBrouwer

@rustbot rustbot added A-attributes Area: Attributes (`#[…]`, `#![…]`) 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 Nov 7, 2026
@rustbot

rustbot commented Nov 7, 2026

Copy link
Copy Markdown
Collaborator

r? @mu001999

rustbot has assigned @mu001999.
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 79 candidates
  • Random selection from 23 candidates

@rustbot rustbot added the A-LLVM Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues. label Nov 7, 2026
@veluca93

veluca93 commented Nov 7, 2026 •

Copy link
Copy Markdown
Contributor

If I understand correctly that code, it does do something: it omits default_optimisation_attrs when optimizing for speed. That means that optimize(speed) makes LLVM not optimize for size functions with #[optimize(speed)] even if globally configured for optimizing for size.

@RalfJung RalfJung added the beta-nominated Nominated for backporting to the compiler in the beta channel. label Nov 7, 2026
@RalfJung

RalfJung commented Nov 7, 2026 •

Copy link
Copy Markdown
Member Author

Fair, I updated the description.

@traviscross traviscross added T-lang Relevant to the language team I-lang-radar Items that are on lang's radar and will need eventual work or consideration. labels Nov 7, 2026
@traviscross

traviscross commented Nov 7, 2026 •

Copy link
Copy Markdown
Contributor

I'm OK either way on this, but I'll ask: is this worth reverting? It's just a hint. We're allowed to ignore it.

I feel as though we do know what this is supposed to do.1 To the degree that it's not yet doing that, it seems something we could fix post-stabilization.

Footnotes

  1. Though maybe not how it's supposed to do that, given the way LLVM works currently. ↩

@hanna-kruppe

hanna-kruppe commented Nov 7, 2026 •

Copy link
Copy Markdown
Contributor

In LLVM, the opt-level is used to configure the entire pass pipeline, it is not possible to overwrite this for a single function. Correspondingly, it currently does very little: it suppresses a global -Copt-level=s/z, but that's it.

To elaborate on this: to some extent it's fine and expected that optimize(speed) only cancels out the global opt-level=s/z because LLVM no longer has separate pipelines for s/z (see llvm/llvm-project#191363), it runs the same pipeline with different defaults for functions that don't have an attribute one way or another. So what we currently do in rustc indeed gives optimize(speed) functions the opt-level=2 experience under opt-level=s/z. However, there's still the distinction between the numeric opt-levels. Which means:

  • With global opt-level = 0, we can run more MIR opt passes on optimize(speed) functions, but LLVM passes won't run.
  • With global opt-level > 0, optimize(speed) also doesn't do anything in LLVM terms. In particular, global opt-level=1 can't be "locally upgraded" to opt-level=2 via the attribute.
  • With global opt-level = s/z, optimize(speed) will affect optimization passes that are in the -O2 pipeline but not enable those that are only in the -O3. There aren't actually that many -O3-exclusive passes currently (e.g., I previously mentioned LoopVectorizer on Zulip, but that one's actually in the -O2 pipeline), but there are some. Also, any passes that are in the -O2 pipeline but "try harder" at -O3 will behave like -O2 under opt-level=s/z + optimize(speed).

@rust-log-analyzer

Copy link
Copy Markdown
Collaborator

The job test-aarch64-gnu-llvm-22-1 failed! Check out the build log: (web) (plain enhanced) (plain)

Click to see the possible cause of the failure (guessed by this bot)

---- [codegen] tests/codegen-llvm/optimize-attr-1.rs#NO-OPT stdout ----
------rustc stdout------------------------------

------rustc stderr------------------------------
error[E0658]: `#[optimize(speed)]` is currently unstable
##[error]  --> /checkout/tests/codegen-llvm/optimize-attr-1.rs:33:1
   |
33 | #[optimize(speed)]
   | ^^^^^^^^^^^^^^^^^^
   |
   = note: see issue #165590 <https://github.com/rust-lang/rust/issues/165590> for more information
   = help: add `#![feature(optimize_speed)]` to the crate attributes to enable
   = note: this compiler was built on 2026-11-07; consider upgrading it if it is out of date

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0658`.

------------------------------------------

error in revision `NO-OPT`: compilation failed!
status: exit status: 1
command: env -u RUSTC_LOG_COLOR RUSTC_ICE="0" RUST_BACKTRACE="short" "/checkout/obj/build/aarch64-unknown-linux-gnu/stage2/bin/rustc" "/checkout/tests/codegen-llvm/optimize-attr-1.rs" "-Zsimulate-remapped-rust-src-base=/rustc/FAKE_PREFIX" "-Ztranslate-remapped-path-to-local-path=no" "-Z" "ignore-directory-in-diagnostics-source-blocks=/cargo" "-Z" "ignore-directory-in-diagnostics-source-blocks=/checkout/vendor" "--sysroot" "/checkout/obj/build/aarch64-unknown-linux-gnu/stage2" "--target=aarch64-unknown-linux-gnu" "--cfg" "no_opt" "--check-cfg" "cfg(test,FALSE,no_opt,size_opt,speed_opt)" "-O" "-Cdebug-assertions=no" "-Zcodegen-source-order" "--emit" "llvm-ir" "-C" "prefer-dynamic" "-o" "/checkout/obj/build/aarch64-unknown-linux-gnu/test/codegen-llvm/optimize-attr-1.NO-OPT/optimize-attr-1.ll" "-Znext-solver=coherence" "-A" "internal_features" "-A" "incomplete_features" "-A" "unused_parens" "-A" "unused_braces" "-Crpath" "-Cdebuginfo=0" "--edition=2015" "-Copt-level=0" "-Ccodegen-units=1"
stdout: none
--- stderr -------------------------------
error[E0658]: `#[optimize(speed)]` is currently unstable
##[error]  --> /checkout/tests/codegen-llvm/optimize-attr-1.rs:33:1
   |
33 | #[optimize(speed)]
   | ^^^^^^^^^^^^^^^^^^
   |
   = note: see issue #165590 <https://github.com/rust-lang/rust/issues/165590> for more information
   = help: add `#![feature(optimize_speed)]` to the crate attributes to enable
   = note: this compiler was built on 2026-11-07; consider upgrading it if it is out of date
---
---- [codegen] tests/codegen-llvm/optimize-attr-1.rs#NO-OPT stdout end ----
---- [codegen] tests/codegen-llvm/optimize-attr-1.rs#SIZE-OPT stdout ----
------rustc stdout------------------------------

------rustc stderr------------------------------
error[E0658]: `#[optimize(speed)]` is currently unstable
##[error]  --> /checkout/tests/codegen-llvm/optimize-attr-1.rs:33:1
   |
33 | #[optimize(speed)]
   | ^^^^^^^^^^^^^^^^^^
   |
   = note: see issue #165590 <https://github.com/rust-lang/rust/issues/165590> for more information
   = help: add `#![feature(optimize_speed)]` to the crate attributes to enable
   = note: this compiler was built on 2026-11-07; consider upgrading it if it is out of date
---
------------------------------------------

error in revision `SIZE-OPT`: compilation failed!
status: exit status: 1
command: env -u RUSTC_LOG_COLOR RUSTC_ICE="0" RUST_BACKTRACE="short" "/checkout/obj/build/aarch64-unknown-linux-gnu/stage2/bin/rustc" "/checkout/tests/codegen-llvm/optimize-attr-1.rs" "-Zsimulate-remapped-rust-src-base=/rustc/FAKE_PREFIX" "-Ztranslate-remapped-path-to-local-path=no" "-Z" "ignore-directory-in-diagnostics-source-blocks=/cargo" "-Z" "ignore-directory-in-diagnostics-source-blocks=/checkout/vendor" "--sysroot" "/checkout/obj/build/aarch64-unknown-linux-gnu/stage2" "--target=aarch64-unknown-linux-gnu" "--cfg" "size_opt" "--check-cfg" "cfg(test,FALSE,no_opt,size_opt,speed_opt)" "-O" "-Cdebug-assertions=no" "-Zcodegen-source-order" "--emit" "llvm-ir" "-C" "prefer-dynamic" "-o" "/checkout/obj/build/aarch64-unknown-linux-gnu/test/codegen-llvm/optimize-attr-1.SIZE-OPT/optimize-attr-1.ll" "-Znext-solver=coherence" "-A" "internal_features" "-A" "incomplete_features" "-A" "unused_parens" "-A" "unused_braces" "-Crpath" "-Cdebuginfo=0" "--edition=2015" "-Copt-level=s" "-Ccodegen-units=1"
stdout: none
--- stderr -------------------------------
error[E0658]: `#[optimize(speed)]` is currently unstable
##[error]  --> /checkout/tests/codegen-llvm/optimize-attr-1.rs:33:1
   |
33 | #[optimize(speed)]
   | ^^^^^^^^^^^^^^^^^^
   |
   = note: see issue #165590 <https://github.com/rust-lang/rust/issues/165590> for more information
   = help: add `#![feature(optimize_speed)]` to the crate attributes to enable
   = note: this compiler was built on 2026-11-07; consider upgrading it if it is out of date
---
---- [codegen] tests/codegen-llvm/optimize-attr-1.rs#SIZE-OPT stdout end ----
---- [codegen] tests/codegen-llvm/optimize-attr-1.rs#SPEED-OPT stdout ----
------rustc stdout------------------------------

------rustc stderr------------------------------
error[E0658]: `#[optimize(speed)]` is currently unstable
##[error]  --> /checkout/tests/codegen-llvm/optimize-attr-1.rs:33:1
   |
33 | #[optimize(speed)]
   | ^^^^^^^^^^^^^^^^^^
   |
   = note: see issue #165590 <https://github.com/rust-lang/rust/issues/165590> for more information
   = help: add `#![feature(optimize_speed)]` to the crate attributes to enable
   = note: this compiler was built on 2026-11-07; consider upgrading it if it is out of date

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0658`.

------------------------------------------

error in revision `SPEED-OPT`: compilation failed!
status: exit status: 1
command: env -u RUSTC_LOG_COLOR RUSTC_ICE="0" RUST_BACKTRACE="short" "/checkout/obj/build/aarch64-unknown-linux-gnu/stage2/bin/rustc" "/checkout/tests/codegen-llvm/optimize-attr-1.rs" "-Zsimulate-remapped-rust-src-base=/rustc/FAKE_PREFIX" "-Ztranslate-remapped-path-to-local-path=no" "-Z" "ignore-directory-in-diagnostics-source-blocks=/cargo" "-Z" "ignore-directory-in-diagnostics-source-blocks=/checkout/vendor" "--sysroot" "/checkout/obj/build/aarch64-unknown-linux-gnu/stage2" "--target=aarch64-unknown-linux-gnu" "--cfg" "speed_opt" "--check-cfg" "cfg(test,FALSE,no_opt,size_opt,speed_opt)" "-O" "-Cdebug-assertions=no" "-Zcodegen-source-order" "--emit" "llvm-ir" "-C" "prefer-dynamic" "-o" "/checkout/obj/build/aarch64-unknown-linux-gnu/test/codegen-llvm/optimize-attr-1.SPEED-OPT/optimize-attr-1.ll" "-Znext-solver=coherence" "-A" "internal_features" "-A" "incomplete_features" "-A" "unused_parens" "-A" "unused_braces" "-Crpath" "-Cdebuginfo=0" "--edition=2015" "-Copt-level=3" "-Ccodegen-units=1"
stdout: none
--- stderr -------------------------------
error[E0658]: `#[optimize(speed)]` is currently unstable
##[error]  --> /checkout/tests/codegen-llvm/optimize-attr-1.rs:33:1
   |
33 | #[optimize(speed)]
   | ^^^^^^^^^^^^^^^^^^
   |
   = note: see issue #165590 <https://github.com/rust-lang/rust/issues/165590> for more information
   = help: add `#![feature(optimize_speed)]` to the crate attributes to enable
   = note: this compiler was built on 2026-11-07; consider upgrading it if it is out of date

@nikic

nikic commented Nov 7, 2026

Copy link
Copy Markdown
Contributor

Do I understand correctly that you want to destabilize optimize(speed) because it does not "work" at -C opt-level=0? If so, you could destabilize optimize(size) based on the same argument.

At -C opt-level=2/3, optimize(size) allows you to optimize some functions as if you used -C opt-level=z for them. At -C opt-level=s/z, optimize(speed) allows you to optimize some functions as if you used -C opt-level=2 for them. Their behavior is entirely symmetric.

So I don't think this PR makes sense.

@hanna-kruppe

hanna-kruppe commented Nov 7, 2026 •

Copy link
Copy Markdown
Contributor

@traviscross

I feel as though we do know what this is supposed to do. To the degree that it's not yet doing that, it seems something we could fix post-stabilization.

So, what exactly is it supposed to do that it's not doing today? If there's a conflict between what "we know" it's supposed to do vs. how it actually works, then that should give us pause and prompt us to reconsider. After all, there are good reasons why LLVM works the way it does. Of course the attribute is a hint that is allowed to do nothing, but we do want it to do something that is both useful and actually implementable.

So, for example, if people "know" that putting optimize(speed) on a function is supposed to make its runtime performance similar to opt-level=1/2 builds even with global opt-level=0 (like a fine-grained version of changing opt-level for one crate in Cargo via profile overrides), then I don't think we should stabilize that because it's not clear that this will ever be implementable without very regrettable trade-offs.

@nikic

Do I understand correctly that you want to destabilize optimize(speed) because it does not "work" at -C opt-level=0? If so, you could destabilize optimize(size) based on the same argument.

Per the recent Zulip discussion, the difference is in expectations: some people would like optimize(speed) to be usable for cases where some code is unbearably slow to run at opt-level=0. Like a finer grained equivalent of crate-level opt-level overrides in Cargo profiles. In contrast, I haven't seen anyone notice or complain about optimize(size) doing nothing at opt-level=0. I think that's because nobody directly cares about code size in unoptimized builds, but rather they add optimize(sized) to prevent excessive code size in optimized builds resulting from specific optimization passes going ham.

@RalfJung

RalfJung commented Nov 7, 2026 •

Copy link
Copy Markdown
Member Author

but I'll ask: is this worth reverting? It's just a hint. We're allowed to ignore it.

Yes, we are, but I don't see who we are helping by having an attribute that basically never does what people expect it to do.

Do I understand correctly that you want to destabilize optimize(speed) because it does not "work" at -C opt-level=0?

No, I want to destabilize it because it basically never works.

optimize(size) at least doe something for release builds. We should probably mention in the docs that at the moment, it has basically no effect on opt-level 0.

@traviscross

traviscross commented Nov 7, 2026 •

Copy link
Copy Markdown
Contributor

At -C opt-level=2/3, optimize(size) allows you to optimize some functions as if you used -C opt-level=z for them. At -C opt-level=s/z, optimize(speed) allows you to optimize some functions as if you used -C opt-level=2 for them. Their behavior is entirely symmetric.

Following @nikic's logic above about symmetry,1 my feeling is that either we should be leaning into the idea that these attributes are just hints, or we should be reverting the entire stabilization.

Footnotes

  1. Regarding expectations, I don't find one direction particularly more surprising than the other here. ↩

@RalfJung

RalfJung commented Nov 7, 2026

Copy link
Copy Markdown
Member Author

I think that's throwing out the baby with the bathwater.

At -C opt-level=s/z, optimize(speed) allows you to optimize some functions as if you used -C opt-level=2 for them.

I thought we'd not have all the right passes in the pipeline for optimize(speed) to do anything useful there?

Also FWIW on mir-opts the behavior is quite different from what you describe.

@hanna-kruppe

Copy link
Copy Markdown
Contributor

No, I want to destabilize it because it basically never works.

optimize(size) at least doe something for release builds.

FWIW I do have projects where “release build” means opt-level=s, and optimize(speed) does something in release builds in those cases. It’s not doing anything in the default release profile, but it’s not “basically never” either. I think the symmetry that @nikic mentions is fine, it gives a useful knob without making an even bigger mess of the pass pipeline and making opt-level=0 builds slower.

But since the implications of this for optimize(speed) are surprising to several people and apparently weren’t fully understood by everyone during the FCP, I guess it does make sense to go back and try to get everyone on the same page about what optimize(speed) actually does. Probably we don’t need to actually agree on which behavior would be most desirable in theory, and probably we should stabilize the actual behavior anyway sooner rather than later, but it’s easier to have the conversation without the time pressure of the stabilization being in beta already.

@rust-log-analyzer

Copy link
Copy Markdown
Collaborator

The job test-x86_64-gnu-tools failed! Check out the build log: (web) (plain enhanced) (plain)

Click to see the possible cause of the failure (guessed by this bot)
---- attributes/codegen.md - Code_generation_attributes::The_ (line 1000) stdout ----
error[E0658]: `#[optimize(speed)]` is currently unstable
##[error]    --> attributes/codegen.md:1004:5
     |
1004 |     #[optimize(speed)] || (); // A closure.
     |     ^^^^^^^^^^^^^^^^^^
     |
     = note: see issue #165590 <https://github.com/rust-lang/rust/issues/165590> for more information
     = help: add `#![feature(optimize_speed)]` to the crate attributes to enable
     = note: this compiler was built on 2026-11-07; consider upgrading it if it is out of date

error[E0658]: `#[optimize(speed)]` is currently unstable
##[error]    --> attributes/codegen.md:1017:5
     |
1017 |     #[optimize(speed)]
     |     ^^^^^^^^^^^^^^^^^^
     |
     = note: see issue #165590 <https://github.com/rust-lang/rust/issues/165590> for more information
     = help: add `#![feature(optimize_speed)]` to the crate attributes to enable
     = note: this compiler was built on 2026-11-07; consider upgrading it if it is out of date
---
---- attributes/codegen.md - Code_generation_attributes::The_ (line 887) stdout ----
error[E0658]: `#[optimize(speed)]` is currently unstable
##[error]   --> attributes/codegen.md:891:1
    |
891 | #[optimize(speed)]
    | ^^^^^^^^^^^^^^^^^^
    |
    = note: see issue #165590 <https://github.com/rust-lang/rust/issues/165590> for more information
    = help: add `#![feature(optimize_speed)]` to the crate attributes to enable
    = note: this compiler was built on 2026-11-07; consider upgrading it if it is out of date

@traviscross traviscross added I-lang-nominated Nominated for discussion during a lang team meeting. P-lang-drag-0 Lang team prioritization drag level 0.https://rust-lang.zulipchat.com/#narrow/channel/410516-t-lang. labels Nov 7, 2026
@hanna-kruppe

hanna-kruppe commented Nov 7, 2026 •

Copy link
Copy Markdown
Contributor

I thought we'd not have all the right passes in the pipeline for optimize(speed) to do anything useful there?

We do have all the opt-level=2 passes (which is almost all of them) in the pipeline at opt-level=s. Although as I mentioned before, they may have other knobs besides the one encoded in optsize/optiminsize. For example, I found a loop that gets vectorized under opt-level=2 but doesn't get vectorized with opt-level=s + optimize(speed): https://rust.godbolt.org/z/c6nzYPKqW

Not sure if that's a problem in LLVM itself (and if so, whether it's already fixed in main) or due to one of the places in rustc that branches on opt-level. #155656 only updated the mapping to LLVM's enum, but I recall that we do a lot more decisions in configuring the pipeline.

@hanna-kruppe

hanna-kruppe commented Nov 7, 2026 •

Copy link
Copy Markdown
Contributor

Oh yeah we do tell LLVM to disable some passes including loop unrolling and vectorization based on rustc's own -Copt-level rather than the LLVM pipeline level.

@RalfJung

RalfJung commented Nov 7, 2026

Copy link
Copy Markdown
Member Author

We do have all the opt-level=2 passes (which is almost all of them) in the pipeline at opt-level=s.

Ah I see, I was not aware of that.

FWIW I do have projects where “release build” means opt-level=s, and optimize(speed) does something in release builds in those cases. It’s not doing anything in the default release profile, but it’s not “basically never” either. I think the symmetry that @nikic mentions is fine, it gives a useful knob without making an even bigger mess of the pass pipeline and making opt-level=0 builds slower.

Hm, that does make sense.

I would however argue it then also makes sense to do something similar for MIR opts, i.e. a -Copt-level=0 run should not suddenly apply the full suite of MIR opts to an #[optimize(speed)] function.

@hanna-kruppe

hanna-kruppe commented Nov 7, 2026 •

Copy link
Copy Markdown
Contributor

I would however argue it then also makes sense to do something similar for MIR opts, i.e. a -Copt-level=0 run should not suddenly apply the full suite of MIR opts to an #[optimize(speed)] function.

Yeah that would be more consistent. I don't think there's currently much harm in running more mir-opt passes, if it's easy to support and doesn't cost much compile time (especially not for the vast majority of code not annotated optimize(speed)). But we should definitely be ready to run fewer passes if it causes any problems for other work on the MIR pipeline (e.g., I think we don't currently run the MIR inliner there, we shouldn't complicate the code to be able to run it) or if for any reason rustc-perf shows significant compile time improvements from running fewer passes.

@hanna-kruppe

Copy link
Copy Markdown
Contributor

For example, I found a loop that gets vectorized under opt-level=2 but doesn't get vectorized with opt-level=s + optimize(speed): https://rust.godbolt.org/z/c6nzYPKqW

I reported this as #165601. It's not a fundamental problem with what the attribute means, but as long as we have that bug, optimize(speed) pretty useless IMO. Loop unrolling and loop vectorization are among the biggest culprits for "trading a lot of code size for a lot of speed" (along with inlining), and we don't have stable attributes for controlling them (unlike for inlining), so optimize(speed) is mainly useful for opting into those optimizations for the hottest loops of projects that otherwise get built with opt-level=s.

The fact that this wasn't noticed before indicates to me that nobody actually used this attribute in anger yet, which is maybe a bad sign for stabilizing it.

@RalfJung

RalfJung commented Nov 7, 2026

Copy link
Copy Markdown
Member Author

(e.g., I think we don't currently run the MIR inliner there, we shouldn't complicate the code to be able to run it)

I think we should de-complicate the code so that the inliner runs.^^ The current logic is strange.

@traviscross

Copy link
Copy Markdown
Contributor

On Zulip, @RalfJung suggested:

so... I guess we close that PR as optimize(speed) actually makes sense after all? I need to re-read the Reference to see whether that could be clarified. And also I still think we should make mir-opts consistent, and basically make optimize(speed) a NOP for debug builds (-Copt-level=0).

Since we have a lang meeting upcoming, I'll therefore unnominate. Please, of course, renominate if there is more for the team to do or consider here.

@traviscross traviscross removed I-lang-nominated Nominated for discussion during a lang team meeting. P-lang-drag-0 Lang team prioritization drag level 0.https://rust-lang.zulipchat.com/#narrow/channel/410516-t-lang. labels Nov 11, 2026
@RalfJung

RalfJung commented Nov 11, 2026 •

Copy link
Copy Markdown
Member Author

@traviscross @tmandry the vibe on Zulip was "let's make sure t-lang is on board with the intuition described by @nikic above", since that wasn't really very clear at all during the stabilization.

That intuition is

At -C opt-level=2/3, optimize(size) allows you to optimize some functions as if you used -C opt-level=z for them. At -C opt-level=s/z, optimize(speed) allows you to optimize some functions as if you used -C opt-level=2 for them. Their behavior is entirely symmetric.

Notably, at -Copt-level=0/1, both of them do basically nothing. (Well currently they do something for MIR opts but I'd like to change that for consistency with LLVM opts.)

So there is a (probably small) team ask here, unless you consider that already covered by the existing FCP for the attribute.

@traviscross traviscross added I-lang-nominated Nominated for discussion during a lang team meeting. P-lang-drag-0 Lang team prioritization drag level 0.https://rust-lang.zulipchat.com/#narrow/channel/410516-t-lang. labels Nov 11, 2026
@traviscross

Copy link
Copy Markdown
Contributor

the vibe on Zulip was "let's make sure t-lang is on board with the intuition described by @nikic above", since that wasn't really very clear at all during the stabilization.

That intuition is

At -C opt-level=2/3, optimize(size) allows you to optimize some functions as if you used -C opt-level=z for them. At -C opt-level=s/z, optimize(speed) allows you to optimize some functions as if you used -C opt-level=2 for them. Their behavior is entirely symmetric.

Notably, at -Copt-level=0/1, both of them do basically nothing. (Well currently they do something for MIR opts but I'd like to change that for consistency with LLVM opts.)

Thanks for that summary. Nominated to confirm that.

@scottmcm

scottmcm commented Nov 11, 2026 •

Copy link
Copy Markdown
Member

We had a chat about this in the lang triage meeting today.

The room was happy with this from the lang perspective (in terms of the intent and spelling and such), since at the spec level this "does nothing" (in the technical observable sense) and it's usable per previous comments.

That said, we did have a bunch of conversation about quality of life/implementation issues, such as whether people will immediately try to use this to [optimize(speed)] a few things in opt-level=0 and find out that it doesn't work. (Rather than separating those things into a different crate that could use a different cargo profile in debug, which does work without this.)

As such, nominating to compiler to take a look. If you think this would lead to excessive noise in the tracker and you'd rather not have it until it works differently, then accepting this de-stabilization would be fine by lang. On the other hand if you're happy with it working this way and don't expect that it's likely to change given a bunch more time anyway, then lang is happy to have it go out to stable.

@scottmcm scottmcm added I-compiler-nominated Nominated for discussion during a compiler team meeting. and removed I-lang-nominated Nominated for discussion during a lang team meeting. labels Nov 11, 2026
@hanna-kruppe

Copy link
Copy Markdown
Contributor

As such, nominating to compiler to take a look. If you think this would lead to excessive noise in the tracker and you'd rather not have it until it works differently, then accepting this de-stabilization would be fine by lang. On the other hand if you're happy with it working this way and don't expect that it's likely to change given a bunch more time anyway, then lang is happy to have it go out to stable.

With my compiler hat on: I don't believe that "optimize(speed) overrides opt-level=0" is implementable without unreasonable trade-offs such as hurting opt-level=0 compile times for everyone, neither in the short term (using an opt-level>0 pipeline in LLVM and putting optnone on most functions) nor in the longer term. Even if I thought that overriding opt-level=0 would be nicer1, I think we only have a choice between (1) let people have this useful attribute on stable and deal with the disappointment of those who wanted it to override opt-level=0, or (2) keep it unstable indefinitely and deal with the disappointment of everyone who wants to use the attribute on stable. The first is clearly more useful, and we can mitigate issue tracker noise by making the documentation clearer. We might want to improve docs first before stabilizing, but for purpose of issue wrangling, having better docs on nightly is probably good enough.

Footnotes

  1. I don't think this is actually desirable. If libraries start using a "optimize even at opt-level=0" attribute a bunch, then that will be the wrong trade-off for some builds and downstream users, and then we'd want a way to override the attribute from outside the crate, and at that point we're re-building an even more fine grained version of what crate-level opt-level overrides can do, for unclear benefit. ↩

@traviscross

Copy link
Copy Markdown
Contributor

As such, nominating to compiler to take a look. If you think this would lead to excessive noise in the tracker and you'd rather not have it until it works differently, then accepting this de-stabilization would be fine by lang. On the other hand if you're happy with it working this way and don't expect that it's likely to change given a bunch more time anyway, then lang is happy to have it go out to stable.

To clarify, for my part, given that the behavior is symmetric, I'd expect compiler to fully destabilize the optimize attribute (or at least both of speed and size) if they had concerns rather than accepting the partial destabilization originally proposed here.

@RalfJung

Copy link
Copy Markdown
Member Author

@BoxyUwU @davidtwco for the best way to get some t-compiler feedback here; not sure if just adding the nomination label is the right thing to do.

@veluca93

Copy link
Copy Markdown
Contributor

My 2 cents as a library author / the person that pushed for stabilization in the first place: I think the main usefulness of the optimize attribute comes from making it possible to instruct the compiler to optimize cold functions for size and hot functions for speed in release builds (i.e. to reduce the size of release binaries without sacrificing speed)

This is not something you can (easily, if at all) get in Rust otherwise, and I think it would be disappointing to make this functionality only available on nightly builds for the foreseeable future, waiting for some way to coerce LLVM to do something that it is not designed to do and that, as @hanna-kruppe pointed out, is not even something we agree we want to be possible.

@traviscross traviscross removed the P-lang-drag-0 Lang team prioritization drag level 0.https://rust-lang.zulipchat.com/#narrow/channel/410516-t-lang. label Nov 12, 2026
@jieyouxu

Copy link
Copy Markdown
Member

We visited this during the triage meeting (#t-compiler/meetings > [weekly] 2026-11-12 @ 💬) today. Since attendance was light, we didn't reach any conclusion this week and will revisit next week if needed, given this is still early into 1.101 cycle.

More discussions are happening in the backport nomination thread #t-compiler/backports > #165592: beta-nominated.

@rust-bors

rust-bors Bot commented Nov 13, 2026

Copy link
Copy Markdown
Contributor

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

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-attributes Area: Attributes (`#[…]`, `#![…]`) A-LLVM Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues. beta-nominated Nominated for backporting to the compiler in the beta channel. I-compiler-nominated Nominated for discussion during a compiler team meeting. I-lang-radar Items that are on lang's radar and will need eventual work or consideration. 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. T-lang Relevant to the language team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

10 participants