[llvm-dev] [RFC] AlwaysInline codegen

David Blaikie via llvm-dev llvm-dev at lists.llvm.org
Thu Aug 20 17:36:44 PDT 2015


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? The following example seems to demonstrate
this

void f1();
inline __attribute__((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?


> 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/711762fd/attachment.html>


More information about the llvm-dev mailing list