[llvm-dev] [RFC] AlwaysInline codegen

Richard Smith via llvm-dev llvm-dev at lists.llvm.org
Thu Aug 20 17:53:37 PDT 2015

On Thu, Aug 20, 2015 at 5:36 PM, David Blaikie <dblaikie at gmail.com> wrote:

> On Thu, Aug 20, 2015 at 5:19 PM, Evgenii Stepanov via llvm-dev <
> llvm-dev at lists.llvm.org> wrote:
>> Hi,
>> There is a problem with the handling of alwaysinline functions in
>> Clang: they are not always inlined. AFAIK, this may only happen when
>> the caller is in the dead code, but then we don't always successfully
>> remove all dead code.
>> Because of this, we may end up emitting an undefined reference
> Why would the failure to inline produced an undefined reference? Wouldn't
> we just keep the body around?

No, if it's available_externally we'll discard it before we emit code.

> The following example seems to demonstrate this
> void f1();
> inline __attribute__((always_inline)) void f2() {
> Try:

extern inline __attribute__((gnu_inline, always_inline)) void f2() {

>   f1();
> }
> void (*f3())() {
>   return f2;
> }
>> for an
>> "inline __attribute__((always_inline))" function. Libc++ relies on the
>> compiler never doing that - it has lots of functions in the headers
>> marked this way and does _not_ export them from libc++.so.
>> Current implementation in clang emits alwaysinline+inline functions as
>> available_externally definitions.
> I heard this mentioned in another thread - and I'm not seeing that
> behavior. Is there an extra step missing necessary to produce that behavior?

You need to first arrange a situation where you'd get an
available_externally definition without the always_inline.

> The inliner is an SCC pass, and as
>> such it does not process unreachable functions at all. This means that
>> AlwaysInliner may leave some alwaysinline functions not inlined. If
>> such function has an available_externally linkage, it is not emitted
>> into the binary, and all calls to it are emitted as undefined symbol
>> references.
>> Some time ago I've made an attempt to add a DCE pass before the
>> AlwaysInliner pass to fix this. Thst
>>  (a) caused a big churn in the existing tests
>>  (b) must be done at -O0 as well, which is probably undesirable and
>> could inflate compilation time
>>  (c) feels like patching over a bigger problem.
>> The following, better, idea was suggested by Chandler Carruth and Richard
>> Smith.
>> Instead of emitting an available_externally definition for an
>> alwaysinline function, we emit a pair of
>>  1. internal alwaysinline definition (let's call it F.inlinefunction -
>> it demangles nicely)
>>  2a. A stub F() { musttail call F.inlinefunction }
>>   -- or --
>>  2b. A declaration of F.
>> The frontend ensures that F.inlinefunction is only used for direct
>> calls, and the stub is used for everything else (taking the address of
>> the function, really). Declaration (2b) is emitted in the case when
>> "inline" is meant for inlining only (like __gnu_inline__ and some
>> other cases).
>> This way has a number of useful properties that are easy to enforce.
>> 1. alwaysinline functions are always internal
>> 2. AlwaysInliner can be split from normal inliner; it would be a super
>> simple implementation that would ensure that there are no alwaysinline
>> functions remaining after it's done.
>> 3. alwaysinline functions must never reach backend and can be rejected
>> before machine code generation (in SelectionDAG?).
>> As this changes the semantics of alwaysinline attribute in the IR, we
>> would need to reserve a new attribute ID, rename the current ID to
>> legacy_alwaysinline or something similar and only enforce the above
>> properties on the new attribute.
>> There is a proposed Clang patch here: http://reviews.llvm.org/D12087
>> The patch only implements the Clang codegen part of the proposal and
>> does not do any of the backend improvements.
>> _______________________________________________
>> LLVM Developers mailing list
>> llvm-dev at lists.llvm.org
>> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20150820/69d99fc2/attachment.html>

More information about the llvm-dev mailing list