clang currently implements the 'flatten' function attribute by marking
all calls to not 'noinline' functions with 'always_inline'. In effect,
only the first level of calls is inlined, not all calls recursively
(like gcc does).
We briefly discussed possible solutions on IRC:
We could add an equivalent LLVM attribute for functions (e.g.
'flatten'). The main problem with this approach occurs when we're
inlining the function marked with 'flatten'. In this case we could
either drop the attribute, move it to the function we're inlining into
(both would lose the scope of the original 'flatten' annotation), or
distribute it to all calls within the 'flatten' function (which would
require a new call site attribute).
The other approach is to add or modify a call site attribute. We could
add a specific attribute (e.g. 'flatten' or
'always_inline_recursively'), but a more general solution is adding a
new 'depth' parameter to the existing 'always_inline' attribute. When a
call site marked 'always_inline' is inlined, the attribute will then be
duplicated to all new call sites (with decremented depth and only if the
depth is greater than zero).
With this solution, one problem remains: an 'always_inline' on the call
site is currently stronger than a 'noinline' on the callee. Thus, a
recursive 'always_inline' would ignore 'noinline'. To fix this, we can
make 'always_inline' weaker than 'noinline'. If that breaks backwards
compatibility too much, we could add a second parameter (boolean 'weak'
or 'strong') to 'always_inline'.
I've never worked on LLVM before, but if someone confirms what the
preferred solution to this is, I will start working on a patch.
Thanks for your time