<div dir="ltr"><div dir="ltr"><br></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Tue, May 28, 2019 at 2:31 AM Lubos Lunak <<a href="mailto:l.lunak@centrum.cz">l.lunak@centrum.cz</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">On Tuesday 28 of May 2019, David Blaikie wrote:<br>
> So I'm not sure I understand this comment:<br>
><br>
> "And, if you look carefully, 4 seconds more to generate code, most of it<br>
> for those templates. And after the compiler spends all this time on<br>
> templates in all the source files, it gets all passed to the linker, which<br>
> will shrug and then throw most of it away (and that will too take a load of<br>
> time, if you still happen to use the BFD linker instead of gold/lld<br>
> <<a href="https://lists.freedesktop.org/archives/libreoffice/2018-July/080484.html" rel="noreferrer" target="_blank">https://lists.freedesktop.org/archives/libreoffice/2018-July/080484.html</a>><br>
>  with -gsplit-dwarf -Wl,--gdb-index<br>
> <<a href="https://lists.freedesktop.org/archives/libreoffice/2018-June/080437.html" rel="noreferrer" target="_blank">https://lists.freedesktop.org/archives/libreoffice/2018-June/080437.html</a>>)<br>
>. What a marvel."<br>
><br>
> What extra code generation occurred with the PCH? Any change in generated<br>
> code with a PCH would surprise me.<br>
<br>
<br>
 If I understand it correctly, the small testcase from me means that adding a <br>
PCH generally does not change the resulting object file, only make Clang <br>
spend more time processing something it throws away as unused somewhen in the <br>
later stages of creating the object file, so there's no extra code generation <br>
caused by the PCH. So, to make it more clean what I meant there, it's more <br>
like saying that there's a missed opportunity:<br>
<br>
- Let's say that I have a library built from a.cpp and b.cpp, and both those <br>
sources use std::vector< int >. As in, they really use it, so both a.o and <br>
b.o end up with weak copies of std::vector< int > code.<br>
- That seems to be basically inevitable with the normal non-PCH code, as the <br>
Clang instance compiling a.cpp cannot know that std::vector< int > code will <br>
be also present in b.o, and so both compiling a.cpp and b.cpp results in <br>
generating std::vector< int >, even though we can clearly see it's <br>
unnecessary.<br>
- I say it's basically inevitable in the non-PCH case, because I don't know a <br>
reasonable way to avoid that in practice. There is extern template, which <br>
would work in this minimal testcase, but for a real-world large codebase I <br>
find that impractical, tedious and what not (please correct if I'm wrong and <br>
there is a reasonable way, but beware that I've already tried that and <br>
decided that writing a compiler patch was an easier way of going about it).<br>
- However, in the PCH case, both Clang instances do know that they share all <br>
the template instantiations from the PCH. And that's where my patch steps in <br>
and -fpch-template-instantiation=force tell one instance "take care of it <br>
all" and -fpch-template-instantiation=skip tells all the other <br>
instance "don't bother with those, somebody else will take care of that". So <br>
all but one Clang instances can skip all those numerous <br>
Sema::InstantiateFunctionDefinition() and also code generation for all of <br>
those instances that actually are used in that TU.<br>
- To put it differently, you can also view -fpch-template-instantiation=skip <br>
as automatic extern template for whatever is used by the PCH, <br>
and -fpch-template-instantiation=force as explicit instantiation for it, <br>
where all the hassle of extern template is replaced by just putting all the <br>
template stuff in the PCH. (To be precise, it's not exactly like explicit <br>
instantiation, because it involves only what is instantiated by the PCH, but <br>
if wanted that can be handled by actually explicitly instantiating in the <br>
PCH, without having to bother with the extern template stuff).<br></blockquote><div><br>Ah, OK. Was this an indirect benefit of the feature/patch you created - or did you specifically code for that in addition to the moving the pending instantiations out to the separate PCH processing stage, rather than in every compilation that uses the PCH - or did it come out as a happy coincidence?<br><br>In any case, talking to Richard Smith about all this, here's some things:<br><br>* Clang header modules don't have the pending instantiation performance problem described here - because they handle the pending instantiations at the end of building the module, rather than in every consumer.<br>* It's possible moving PCH to the modules semantics might be valid in general, or good enough to put behind a flag. (doing this in general would of course be easier, code-wise - fewer supported code paths, etc)<br>* Moving the pending instantiation processing to the end of the PCH would make PCH generation a little slower, but given a project would only have one PCH that might not be a huge problem.<br>* In addition to that, we could support -fmodules-codegen/debuginfo - which would implement the "building an object from the PCH" step you've described using existing infrastructure in Clang (& that would then include other non-template inline functions, so it'd be a bit broader)<br>* Then we could potentially do something more like what you're proposing here - if modules-codegen is used, defer pending instantiations from the initial module/PCH creation step, to the module/PCH-to-object step, to speed up module/PCH generation & unblock the downstream compilations that use it<br><br>- Dave<br><br></div></div></div>