This is an archive of the discontinued LLVM Phabricator instance.

(WIP) share template instantiations from PCH in one .o if -building-pch-with-obj
AbandonedPublic

Authored by llunak on Jul 6 2019, 5:08 AM.

Details

Summary

This is a WIP patch that can significantly reduce build time by avoiding needlessly repeatedly instantiating templates when using PCH.

As described in http://lists.llvm.org/pipermail/cfe-dev/2019-May/062371.html / http://llunak.blogspot.com/2019/05/why-precompiled-headers-do-not-improve.html , whenever a compilation uses PCH it instantiates every template that's been instantiated in the PCH, which can add significant build time. This patch allows avoiding that, if -building-pch-with-obj option is used, the templates will be instantiated just once in the object file that should accompany the PCH, and then it can be skipped during normal compilations.

Testcase: I've built an entire debug build of LibreOffice with this patch and it works.

Pending problems/questions:

  • The patch currently skips C++ constructors and destructors, because (at least with the Itanium ABI) they can be emitted in several variants (complete vs base ctor/dtor) and I don't know how to force emitting all variants. Ctors/dtors are a significant portion of PCH template instantiations, so without this the building time improvement is not as large as it could be.
  • The patch currently does not handle function inlining well (=it works only with -O0 builds). This optimization cannot be done with template functions that should be inlined by the compilation, so the code needs to check whether a function would possibly be inlined. The problem is that this depends on settings in CodeGenOptions and Sema (understandably) doesn't have an access to that. How can I access that in Sema? Does it make sense to try to handle this, or is the deciding whether a function will get actually inlined too complex and this should rather be skipped for CodeGen::NormalInlining?
  • In rate circumstances it is possible to get undefined references because of instantiations in the PCH's object file. Specifically this happens if the PCH includes a header providing non-exported code from another module (=shared library), in that case the PCH may refer to it. I think this is conceptually not possible to handle in Clang, either the code should be cleaned up to not provide non-exported code to other modules, or it's possible to use linker's --gc-sections to drop such instantiations.
  • In Sema::InstantiateFunctionDefinition() the code for extern templates still instantiates a function if it has getContainedAutoType(), so my code should probably also check that. But I'm not sure what that is (is that 'auto foo() { return 1; }' ?) or why that would need an instance in every TU.
  • Is there a guideline on when to use data members in class Decl vs functions? The patch uses DeclIsPendingInstantiationFromPCHWithObjectFile() to check whether a FunctionDecl comes from the PCH, which may get called quite often. This could be optimized away by storing a flag in class Decl.

Diff Detail

Repository
rC Clang

Event Timeline

llunak created this revision.Jul 6 2019, 5:08 AM
Herald added a project: Restricted Project. · View Herald TranscriptJul 6 2019, 5:08 AM
Herald added a subscriber: cfe-commits. · View Herald Transcript
llunak abandoned this revision.Oct 29 2019, 2:00 PM

Due to some technical problems with this approach and lack of feedback, I'm scratching this one. A new approach is at https://reviews.llvm.org/D69585 .