<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Fri, Aug 21, 2015 at 1:23 PM, John McCall <span dir="ltr"><<a href="mailto:rjmccall@apple.com" target="_blank">rjmccall@apple.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word"><div><div><div class="h5"><blockquote type="cite"><div>On Aug 20, 2015, at 7:36 PM, Richard Smith <<a href="mailto:richard@metafoo.co.uk" target="_blank">richard@metafoo.co.uk</a>> wrote:</div><br><div><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Thu, Aug 20, 2015 at 7:17 PM, John McCall <span dir="ltr"><<a href="mailto:rjmccall@apple.com" target="_blank">rjmccall@apple.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div><div>> On Aug 20, 2015, at 5:19 PM, Evgenii Stepanov via cfe-dev <<a href="mailto:cfe-dev@lists.llvm.org" target="_blank">cfe-dev@lists.llvm.org</a>> wrote:<br>
> Hi,<br>
><br>
> There is a problem with the handling of alwaysinline functions in<br>
> Clang: they are not always inlined. AFAIK, this may only happen when<br>
> the caller is in the dead code, but then we don't always successfully<br>
> remove all dead code.<br>
><br>
> Because of this, we may end up emitting an undefined reference for an<br>
> "inline __attribute__((always_inline))" function. Libc++ relies on the<br>
> compiler never doing that - it has lots of functions in the headers<br>
> marked this way and does _not_ export them from libc++.so.<br>
><br>
> Current implementation in clang emits alwaysinline+inline functions as<br>
> available_externally definitions. The inliner is an SCC pass, and as<br>
> such it does not process unreachable functions at all. This means that<br>
> AlwaysInliner may leave some alwaysinline functions not inlined. If<br>
> such function has an available_externally linkage, it is not emitted<br>
> into the binary, and all calls to it are emitted as undefined symbol<br>
> references.<br>
><br>
> Some time ago I've made an attempt to add a DCE pass before the<br>
> AlwaysInliner pass to fix this. Thst<br>
> (a) caused a big churn in the existing tests<br>
> (b) must be done at -O0 as well, which is probably undesirable and<br>
> could inflate compilation time<br>
> (c) feels like patching over a bigger problem.<br>
><br>
> The following, better, idea was suggested by Chandler Carruth and Richard Smith.<br>
><br>
> Instead of emitting an available_externally definition for an<br>
> alwaysinline function, we emit a pair of<br>
> 1. internal alwaysinline definition (let's call it F.inlinefunction -<br>
> it demangles nicely)<br>
> 2a. A stub F() { musttail call F.inlinefunction }<br>
>  -- or --<br>
> 2b. A declaration of F.<br>
<br>
</div></div>I have no idea why always_inline function definitions are being marked as<br>
available_externally.  There is zero reason to think that they’re actually<br>
available externally, and there’s zero benefit to the optimizer from this<br>
information because inlining is forced anyway, so this lie is both terrible<br>
and pointless.<br></blockquote><div><br></div><div>The interesting case is a declaration like this:</div><div><br></div><div>  extern inline __attribute__((gnu_inline, always_inline)) void f() { /*...*/ }</div><div><br></div><div>These are common in the glibc headers, and they mean:</div><div><br></div><div>1) This is a body just for inlining, and there is a strong definition provided elsewhere (gnu_inline + extern inline), probably with an entirely different body.</div><div>2) If you see a direct call to this function, you must inline it.</div><div><br></div><div>The intention appears to be to create a function definition that is only used for inlining, and is never itself emitted. Taking the address of the function should give the address of the strong definition from elsewhere, not the address of this local definition of f.</div><div><br></div><div>So, if we only want a single IR-level function for this case, it must be available_externally (for (1)), and must be always_inline (for (2)). But that results in the problem that Evgeniy reported.</div></div></div></div></div></blockquote><div><br></div></div></div>How so?  You have a call that doesn’t get inlined for whatever reason, and it resolves against an external symbol that’s guaranteed to exist.  Sub-optimal, but easily fixable by DCE'ing the dead call.  I don’t see how this fails to link unless, what, the program is using the libc headers and not linking against libc?  Do we really need to fall over ourselves to support that?</div><div><br></div><div>Evgeniy seemed to be describing a situation where the external symbol *wasn’t* guaranteed to exist; but in that case, gnu_inline is a clear lie.</div></div></blockquote><div><br></div><div>The combination of flags above implies that if all calls are direct calls, then no external definition is required. Some headers rely on that, such as clang's own <htmxlintrin.h>.</div></div></div></div>