Pre-RFC: optimise(size) and optimise(no) attributes

That’s true, and I don’t think optimise(none) is applicable for the crypto use-case.

That’s an interesting suggestion, but is also something that would be prone to "breakage" every LLVM upgrade, if anybody ended up relying on this attribute in any way.

optimise(no/never) is just opt_level=0 (with the caveat that the cross-function optimisations still may do stuff with it) and inline(never).

This is something that rustc would have to implement by itself, I believe, by constructing a pass pipeline that would optimise in a debugging friendly manner.

I do not consider optimise(none) to be equivalent to optimise(debugging).


All that being said, I don’t see much commentary on optimise(size). Does this mean the optimise(size) is rather fine? I’m considering removing optimise(no/never) from the RFC altogether, so that the attribute that really matters (the optimise(size)) can go through RFC process faster and with less bikeshedding.

All that being said, I don’t see much commentary on optimise(size). Does this mean the optimise(size) is rather fine? I’m considering removing optimise(no/never) from the RFC altogether, so that the attribute that really matters (the optimise(size)) can go through RFC process faster and with less bikeshedding.

Yeah, #[optimize(size)] is much more about intent. Thinking about it a little more though, I do have a few more questions.

When should users use it?

If someone starts with "I care about code size", I assume the next step should generally be "so I use -C opt_level=s", rather than "so I put #[optimize(size)] all over my code base". And for library maintainers starting with "my users care about code size", "so they should use -C opt_level=s" is probably a better starting point than "so I use #[optimize(size)] for them".

How does it interact with opt_level?

If you put #[optimize(size)] in your Rust code and then compile it with opt_level=0, which one should win? How about opt_level=z?

Here's a possible approach:

  • Both opt_level=0 or opt_level=z override any #[optimize(size)] directives in the code.
  • #[optimize(size)] overrides opt_level=1, 2, or 3.
Do you want a #[optimize(speed)] too?

Similar to how you sometimes want to set opt_level=2 but override it to optsize for individual functions, sometimes you might want to do the inverse: set opt_level=s and override it to optimize for speed in individual functions.

The questions above would apply here too. Users that care about performance probably shouldn't default to putting #[optimize(speed)] all over their codebase. And, you might want opt_level=0 to override #[optimize(speed)].

4 Likes

The specific rationale provided by this Pre-RFC focuses around the case where users are using opt-level=2 or opt-evel=3, but they want to avoid a size explosion on the confirmed-to-become-huge-when-optimised functions.

I imagine it would end up being applied to a specific function after noticing that the function was optimised in a undesirable way – loops were unrolled, inlining thresholds were too lax, matches were tableised, etc.

Applying opt-level=s or similar universally here is not always desirable, because one still might focus on speed everywhere, except that one function or module.

An interesting question. It probably should only have any effect in opt-level={1,2,3}.

Maybe. While it seems like a logical extension, it seems way less applicable than #[optimise(speed)]. Also cannot be implemented in current LLVM, and would in general be less "good" than the global optimise-for-speed options.

To me, this argues more for the #[unroll] alternative, the same way control over inlining is #[inline]. And having things like #[unroll(full)] sounds really nice in certain situations. (Really everything in LLVM Language Reference Manual — LLVM 18.0.0git documentation...)

At the function level, transforming <T: Foo> to dyn Foo automatically makes little sense, however, on a whole module or whole crate transformation level I think it makes sense to use a library, and then aggressively transform everything (that you can) to dynamic dispatch?

Did you intend to say, "Static Dispatch"?

No; I meant dynamic dispatch (for inhibiting monomorphization, and reducing the size of the binary).

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.