From a61f5e379675732666744bcba25efbc9922e016a Mon Sep 17 00:00:00 2001 From: Teresa Johnson Date: Fri, 16 Dec 2016 21:25:01 +0000 Subject: [ThinLTO] Import composite types as declarations Summary: When reading the metadata bitcode, create a type declaration when possible for composite types when we are importing. Doing this in the bitcode reader saves memory. Also it works naturally in the case when the type ODR map contains a definition for the same composite type because it was used in the importing module (buildODRType will automatically use the existing definition and not create a type declaration). For Chromium built with -g2, this reduces the aggregate size of the generated native object files by 66% (from 31G to 10G). It reduced the time through the ThinLTO link and backend phases by about 20% on my machine. Reviewers: mehdi_amini, dblaikie, aprantl Subscribers: llvm-commits Differential Revision: https://reviews.llvm.org/D27775 llvm-svn: 289993 --- llvm/lib/Bitcode/Reader/MetadataLoader.cpp | 49 ++++++++++++++++++++++++------ 1 file changed, 39 insertions(+), 10 deletions(-) (limited to 'llvm/lib/Bitcode/Reader/MetadataLoader.cpp') diff --git a/llvm/lib/Bitcode/Reader/MetadataLoader.cpp b/llvm/lib/Bitcode/Reader/MetadataLoader.cpp index 1e28411d01e..eb24ac6def1 100644 --- a/llvm/lib/Bitcode/Reader/MetadataLoader.cpp +++ b/llvm/lib/Bitcode/Reader/MetadataLoader.cpp @@ -86,6 +86,12 @@ using namespace llvm; +/// Flag whether we need to import full type definitions for ThinLTO. +/// Currently needed for Darwin and LLDB. +static cl::opt ImportFullTypeDefinitions( + "import-full-type-definitions", cl::init(false), cl::Hidden, + cl::desc("Import full type definitions for ThinLTO.")); + namespace { static int64_t unrotateSign(uint64_t U) { return U & 1 ? ~(U >> 1) : U >> 1; } @@ -399,7 +405,7 @@ public: Stream(Stream), Context(TheModule.getContext()), TheModule(TheModule), getTypeByID(getTypeByID) {} - Error parseMetadata(bool ModuleLevel); + Error parseMetadata(bool ModuleLevel, bool IsImporting); bool hasFwdRefs() const { return MetadataList.hasFwdRefs(); } Metadata *getMetadataFwdRef(unsigned Idx) { @@ -435,7 +441,8 @@ Error error(const Twine &Message) { /// Parse a METADATA_BLOCK. If ModuleLevel is true then we are parsing /// module level metadata. -Error MetadataLoader::MetadataLoaderImpl::parseMetadata(bool ModuleLevel) { +Error MetadataLoader::MetadataLoaderImpl::parseMetadata(bool ModuleLevel, + bool IsImporting) { if (!ModuleLevel && MetadataList.hasFwdRefs()) return error("Invalid metadata: fwd refs into function blocks"); @@ -709,18 +716,38 @@ Error MetadataLoader::MetadataLoaderImpl::parseMetadata(bool ModuleLevel) { Metadata *File = getMDOrNull(Record[3]); unsigned Line = Record[4]; Metadata *Scope = getDITypeRefOrNull(Record[5]); - Metadata *BaseType = getDITypeRefOrNull(Record[6]); + Metadata *BaseType = nullptr; uint64_t SizeInBits = Record[7]; if (Record[8] > (uint64_t)std::numeric_limits::max()) return error("Alignment value is too large"); uint32_t AlignInBits = Record[8]; - uint64_t OffsetInBits = Record[9]; + uint64_t OffsetInBits = 0; DINode::DIFlags Flags = static_cast(Record[10]); - Metadata *Elements = getMDOrNull(Record[11]); + Metadata *Elements = nullptr; unsigned RuntimeLang = Record[12]; - Metadata *VTableHolder = getDITypeRefOrNull(Record[13]); - Metadata *TemplateParams = getMDOrNull(Record[14]); + Metadata *VTableHolder = nullptr; + Metadata *TemplateParams = nullptr; auto *Identifier = getMDString(Record[15]); + // If this module is being parsed so that it can be ThinLTO imported + // into another module, composite types only need to be imported + // as type declarations (unless full type definitions requested). + // Create type declarations up front to save memory. Also, buildODRType + // handles the case where this is type ODRed with a definition needed + // by the importing module, in which case the existing definition is + // used. + if (IsImporting && !ImportFullTypeDefinitions && + (Tag == dwarf::DW_TAG_enumeration_type || + Tag == dwarf::DW_TAG_class_type || + Tag == dwarf::DW_TAG_structure_type || + Tag == dwarf::DW_TAG_union_type)) { + Flags = Flags | DINode::FlagFwdDecl; + } else { + BaseType = getDITypeRefOrNull(Record[6]); + OffsetInBits = Record[9]; + Elements = getMDOrNull(Record[11]); + VTableHolder = getDITypeRefOrNull(Record[13]); + TemplateParams = getMDOrNull(Record[14]); + } DICompositeType *CT = nullptr; if (Identifier) CT = DICompositeType::buildODRType( @@ -1281,17 +1308,19 @@ MetadataLoader &MetadataLoader::operator=(MetadataLoader &&RHS) { return *this; } MetadataLoader::MetadataLoader(MetadataLoader &&RHS) - : Pimpl(std::move(RHS.Pimpl)) {} + : Pimpl(std::move(RHS.Pimpl)), IsImporting(RHS.IsImporting) {} MetadataLoader::~MetadataLoader() = default; MetadataLoader::MetadataLoader(BitstreamCursor &Stream, Module &TheModule, BitcodeReaderValueList &ValueList, + bool IsImporting, std::function getTypeByID) : Pimpl(llvm::make_unique(Stream, TheModule, ValueList, - getTypeByID)) {} + getTypeByID)), + IsImporting(IsImporting) {} Error MetadataLoader::parseMetadata(bool ModuleLevel) { - return Pimpl->parseMetadata(ModuleLevel); + return Pimpl->parseMetadata(ModuleLevel, IsImporting); } bool MetadataLoader::hasFwdRefs() const { return Pimpl->hasFwdRefs(); } -- cgit v1.2.3