-
Notifications
You must be signed in to change notification settings - Fork 13k
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
#[inline] on generic functions #102539
Comments
I did a bit of crude data analysis, based on calls to non-inlined small functions in ThinLTO inputs. Here's the result: https://gist.github.com/nikic/c1d441ca6468b8c2ee114ff4a11f5667 Some of these are not supposed to be inlined (various panic functions) and there are a lot of But there are also some obvious candidates where per CGU instantiation is likely beneficial, and we'd probably want to add an
|
Do you think that performing thin/fat LTO for |
Generic functions are not included in the same cgu as the user by default. Partitioning produces two cgu's for each module before merging. One containing functions that are actually part of the module and one containing all generic functions used by the module. |
Mark Cell::replace() as #[inline] Giving this a try based on rust-lang#102539 (comment).
I closed #103499 as a duplicate, but reading this again, I'm not so sure. If I read it correctly, this issue is not so much about the behavior of
What are your thoughts on excluding inline generics from sharing? Personally, I would have expected that instantiations of generic inline functions behave the same way as inline functions, and was surprised to learn that this is not the case. But then again, I just recently took a look at how generics are exactly codegened, so take that with a grain of salt. |
Mark Cell::replace() as #[inline] Giving this a try based on rust-lang/rust#102539 (comment).
Can we have some compiler heuristic that applies |
Common Rust wisdom says that
#[inline]
does not need to be placed on small generic functions. This is because generic functions will get monomorphized in each crate anyway, so the attribute is not necessary for cross-crate inlining.However, we also know that in practice placing
#[inline]
on generic functions does help optimization, even for tiny functions where the additionalinlinehint
this gives to LLVM really shouldn't be relevant. What gives? I believe there are two complications:The main problem is that
#[inline]
forces an instantiation of the function in each CGU, while generic functions are normally only instantiated once per crate. This means that a definition of generic functions is available to crate-local LTO, but not to the pre-link optimization pipeline. Especially for trivial generic functions, this may significantly hamper pre-link optimization, and post-link optimization may not be able to recover from this.The second complication occurs when optimizing for size. In this case, we currently enable
-Z share-generics
by default, which means that generic functions only get monomorphized once and are exported for downstream crates. This means that the function definition is not available even to crate-local LTO. It only becomes available during full cross-crate LTO.The second point is something we can fix: We probably should not be enabling
-Z share-generics
by default in any optimized builds, including size-optimized builds.The first one is trickier, as instantiating monomorphizations in each CGU by default is likely not desirable. Possibly we should just stop considering whether a function is generic or not when it comes to
#[inline]
placement.The text was updated successfully, but these errors were encountered: