@inline(__always) is being liberally applied across the stdlib out of necessity to achieve some level of performance stability with respect to basic language features. Independently, I'm trying to cleanup the inlining heuristics (without doing a massive overhaul). Even if the situation isn't ideal, I at least want the attributes and heuristics to fundamentally make sense. To that end I need to add an
@inline(__optimize) attribute. This will replace most uses of
@inline(__always) in the stdlib and will have the intended behavior for the purpose of stdlib performance.
Underscored attributes are unsupported. They may disappear or be
@inlineattributes aren't semantic attributes. They are used for
manual control of compiler behavior, mostly to bootstrap the
implementation of language features in the stdlib. In an ideal
world, they wouldn't be needed.
** Always include a comment explaining why the
@inlineattribute was necessary **
@inline(__always) will do what it says, as originally intended. It will force inlining independent of heuristics. It should very rarely be used in production code, but it is helpful for writing deterministic tests and controlling -Onone performance.
[This is not what
@_transparent is for.
@_transparent is a form of inlining that happens in the mandatory SIL pipeline and should be strictly limited to supporting diagnostic features. i.e. it is necessary to produce valid SIL. It should never be used for performance reasons.]
@inline(__optimize) will strongly encourage inlining into already optimized code. Philosophically, rather than proving the benefit of inlining, the compiler will need to prove the harm.
@inline(__always)will be inlined at
-Onone(this is currently a bug).
@inline(__optimize)will only be inlined at
@inline(__always)will apply to unspecialized generic functions.
@inline(__optimize)will only be inlined after full specialization.
@inline(__always)bypasses inlining size limits, so can easily cause pathological compile time.
@inline(__optimize)is subject to code size heuristics and will be
prevented if the size increase is considered harmful.
Other attributes we could add in the future:
@inline(__early): Inline all of these (along with __always) before other functions to work around some of the problems we have with bottom-up inlining. This could makes sense for certain thunks.
@inline(__late): Don't inline this until "late" inlining. Along with __early, this could help divide stdlib routines into the more/less likely to inline paths.
@inline(__large): Same is
@inline(__optimize) but doesn't kick in at -Osize. I'm not in favor of forking -O vs. -Osize, but this could be a useful complement to an
@optimize attribute that selectively disables size constraints for certain functions. Hopefully it won't be needed.