Description
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 additional inlinehint
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.