As the name suggests, adding the alwaysinline
attribute to a function or callsite, always causes the function to be inlined. However, LLVM seems to ignore situations when the function cannot be inlined, for example when the caller and the callee have conflicting attributes.
I believe this behaviour is currently broken.
The LangRef documentation [1] for alwaysinline
says:
This attribute indicates that the inliner should attempt to inline this function into callers whenever possible, ignoring any active inlining size threshold for this caller.
The Clang documentation [2] for __attribute__((always_inline))
says:
Inlining heuristics are disabled and inlining is always attempted regardless of optimization level.
[ā¦]
This attribute does not guarantee that inline substitution actually occurs.
This is more lenient than the description in the GNU documentation of the attribute [3], which says:
Failure to inline such a function is diagnosed as an error
The above suggests that Clang/LLVM has the ability not to inline when it shouldnāt do so, and to possibly also emit an error, but LLVM doesnāt take this approach.
There are some attributes where inlining them would result in broken code. For example conflicting target-features
, or conflicting strictfp
attributes, or conflicting attributes around pointer authentication. My actual motivation is to avoid inlining functions with a different āstreaming-modeā, which is a property that is specific to AArch64 SME and has its own set of function attributes. Whether a function can be inlined requires knowledge of the body of the to-be-inlined function, which isnāt easily analyzed in the front-end.
I can imagine that for some of the attributes we may still want to inline them even when theyāre not compatible, such as noprofile
or even the sanitize_*
attributes, as there might be a desire to balance runtime performance and functionality. But Iām still not entirely sure this is desired/correct behaviour.
So Iād like to collect some input on what the desired functionality actually is.
-
Do we want to change the behaviour such that all attributes must be compatible in order for them to be inlined (regardless of the
alwaysinline
attribute)? Or do we want to distinguish between conflicting attributes that do - and conflicting attributes that do not - inline depending on whether thealwaysinline
attribute is set? -
Then orthogonal to this there is the point of generating an
error
diagnostic to the user when LLVM cannot inline. Do we want to do this? Or do we want to silently avoid inlining (possibly with an OptimizationRemark).
Any thoughts?
[1] LLVM Language Reference Manual ā LLVM 19.0.0git documentation
[2] Attributes in Clang ā Clang 19.0.0git documentation
[3] Common Function Attributes (Using the GNU Compiler Collection (GCC))