llvm.org GIT mirror llvm / f638013
[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 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@289993 91177308-0d34-0410-b5e6-96231b3b80d8 Teresa Johnson 3 years ago
10 changed file(s) with 175 addition(s) and 53 deletion(s). Raw diff Collapse all Expand all
6060 friend Expected>
6161 getBitcodeModuleList(MemoryBufferRef Buffer);
6262
63 Expected>
64 getModuleImpl(LLVMContext &Context, bool MaterializeAll,
65 bool ShouldLazyLoadMetadata);
63 Expected> getModuleImpl(LLVMContext &Context,
64 bool MaterializeAll,
65 bool ShouldLazyLoadMetadata,
66 bool IsImporting);
6667
6768 public:
6869 StringRef getBuffer() const {
7374
7475 /// Read the bitcode module and prepare for lazy deserialization of function
7576 /// bodies. If ShouldLazyLoadMetadata is true, lazily load metadata as well.
76 Expected>
77 getLazyModule(LLVMContext &Context, bool ShouldLazyLoadMetadata);
77 /// If IsImporting is true, this module is being parsed for ThinLTO
78 /// importing into another module.
79 Expected> getLazyModule(LLVMContext &Context,
80 bool ShouldLazyLoadMetadata,
81 bool IsImporting);
7882
7983 /// Read the entire bitcode module and return it.
8084 Expected> parseModule(LLVMContext &Context);
9296
9397 /// Read the header of the specified bitcode buffer and prepare for lazy
9498 /// deserialization of function bodies. If ShouldLazyLoadMetadata is true,
95 /// lazily load metadata as well.
99 /// lazily load metadata as well. If IsImporting is true, this module is
100 /// being parsed for ThinLTO importing into another module.
96101 Expected>
97102 getLazyBitcodeModule(MemoryBufferRef Buffer, LLVMContext &Context,
98 bool ShouldLazyLoadMetadata = false);
103 bool ShouldLazyLoadMetadata = false,
104 bool IsImporting = false);
99105
100106 /// Like getLazyBitcodeModule, except that the module takes ownership of
101107 /// the memory buffer if successful. If successful, this moves Buffer. On
102 /// error, this *does not* move Buffer.
103 Expected>
104 getOwningLazyBitcodeModule(std::unique_ptr &&Buffer,
105 LLVMContext &Context,
106 bool ShouldLazyLoadMetadata = false);
108 /// error, this *does not* move Buffer. If IsImporting is true, this module is
109 /// being parsed for ThinLTO importing into another module.
110 Expected> getOwningLazyBitcodeModule(
111 std::unique_ptr &&Buffer, LLVMContext &Context,
112 bool ShouldLazyLoadMetadata = false, bool IsImporting = false);
107113
108114 /// Read the header of the specified bitcode buffer and extract just the
109115 /// triple information. If successful, this returns a string. On error, this
487487
488488 /// \brief Main interface to parsing a bitcode buffer.
489489 /// \returns true if an error occurred.
490 Error parseBitcodeInto(Module *M, bool ShouldLazyLoadMetadata = false);
490 Error parseBitcodeInto(Module *M, bool ShouldLazyLoadMetadata = false,
491 bool IsImporting = false);
491492
492493 static uint64_t decodeSignRotatedValue(uint64_t V);
493494
30833084 }
30843085 }
30853086
3086 Error BitcodeReader::parseBitcodeInto(Module *M, bool ShouldLazyLoadMetadata) {
3087 Error BitcodeReader::parseBitcodeInto(Module *M, bool ShouldLazyLoadMetadata,
3088 bool IsImporting) {
30873089 TheModule = M;
3088 MDLoader = MetadataLoader(Stream, *M, ValueList,
3090 MDLoader = MetadataLoader(Stream, *M, ValueList, IsImporting,
30893091 [&](unsigned ID) { return getTypeByID(ID); });
30903092 return parseModule(0, ShouldLazyLoadMetadata);
30913093 }
52195221 /// everything.
52205222 Expected>
52215223 BitcodeModule::getModuleImpl(LLVMContext &Context, bool MaterializeAll,
5222 bool ShouldLazyLoadMetadata) {
5224 bool ShouldLazyLoadMetadata, bool IsImporting) {
52235225 BitstreamCursor Stream(Buffer);
52245226
52255227 std::string ProducerIdentification;
52425244 M->setMaterializer(R);
52435245
52445246 // Delay parsing Metadata if ShouldLazyLoadMetadata is true.
5245 if (Error Err = R->parseBitcodeInto(M.get(), ShouldLazyLoadMetadata))
5247 if (Error Err =
5248 R->parseBitcodeInto(M.get(), ShouldLazyLoadMetadata, IsImporting))
52465249 return std::move(Err);
52475250
52485251 if (MaterializeAll) {
52585261 }
52595262
52605263 Expected>
5261 BitcodeModule::getLazyModule(LLVMContext &Context,
5262 bool ShouldLazyLoadMetadata) {
5263 return getModuleImpl(Context, false, ShouldLazyLoadMetadata);
5264 BitcodeModule::getLazyModule(LLVMContext &Context, bool ShouldLazyLoadMetadata,
5265 bool IsImporting) {
5266 return getModuleImpl(Context, false, ShouldLazyLoadMetadata, IsImporting);
52645267 }
52655268
52665269 // Parse the specified bitcode buffer, returning the function info index.
53225325 }
53235326
53245327 Expected>
5325 llvm::getLazyBitcodeModule(MemoryBufferRef Buffer,
5326 LLVMContext &Context, bool ShouldLazyLoadMetadata) {
5328 llvm::getLazyBitcodeModule(MemoryBufferRef Buffer, LLVMContext &Context,
5329 bool ShouldLazyLoadMetadata, bool IsImporting) {
53275330 Expected BM = getSingleModule(Buffer);
53285331 if (!BM)
53295332 return BM.takeError();
53305333
5331 return BM->getLazyModule(Context, ShouldLazyLoadMetadata);
5332 }
5333
5334 Expected>
5335 llvm::getOwningLazyBitcodeModule(std::unique_ptr &&Buffer,
5336 LLVMContext &Context,
5337 bool ShouldLazyLoadMetadata) {
5338 auto MOrErr = getLazyBitcodeModule(*Buffer, Context, ShouldLazyLoadMetadata);
5334 return BM->getLazyModule(Context, ShouldLazyLoadMetadata, IsImporting);
5335 }
5336
5337 Expected> llvm::getOwningLazyBitcodeModule(
5338 std::unique_ptr &&Buffer, LLVMContext &Context,
5339 bool ShouldLazyLoadMetadata, bool IsImporting) {
5340 auto MOrErr = getLazyBitcodeModule(*Buffer, Context, ShouldLazyLoadMetadata,
5341 IsImporting);
53395342 if (MOrErr)
53405343 (*MOrErr)->setOwnedMemoryBuffer(std::move(Buffer));
53415344 return MOrErr;
53435346
53445347 Expected>
53455348 BitcodeModule::parseModule(LLVMContext &Context) {
5346 return getModuleImpl(Context, true, false);
5349 return getModuleImpl(Context, true, false, false);
53475350 // TODO: Restore the use-lists to the in-memory state when the bitcode was
53485351 // written. We must defer until the Module has been fully materialized.
53495352 }
8585
8686 using namespace llvm;
8787
88 /// Flag whether we need to import full type definitions for ThinLTO.
89 /// Currently needed for Darwin and LLDB.
90 static cl::opt ImportFullTypeDefinitions(
91 "import-full-type-definitions", cl::init(false), cl::Hidden,
92 cl::desc("Import full type definitions for ThinLTO."));
93
8894 namespace {
8995
9096 static int64_t unrotateSign(uint64_t U) { return U & 1 ? ~(U >> 1) : U >> 1; }
398404 Stream(Stream), Context(TheModule.getContext()), TheModule(TheModule),
399405 getTypeByID(getTypeByID) {}
400406
401 Error parseMetadata(bool ModuleLevel);
407 Error parseMetadata(bool ModuleLevel, bool IsImporting);
402408
403409 bool hasFwdRefs() const { return MetadataList.hasFwdRefs(); }
404410 Metadata *getMetadataFwdRef(unsigned Idx) {
434440
435441 /// Parse a METADATA_BLOCK. If ModuleLevel is true then we are parsing
436442 /// module level metadata.
437 Error MetadataLoader::MetadataLoaderImpl::parseMetadata(bool ModuleLevel) {
443 Error MetadataLoader::MetadataLoaderImpl::parseMetadata(bool ModuleLevel,
444 bool IsImporting) {
438445 if (!ModuleLevel && MetadataList.hasFwdRefs())
439446 return error("Invalid metadata: fwd refs into function blocks");
440447
708715 Metadata *File = getMDOrNull(Record[3]);
709716 unsigned Line = Record[4];
710717 Metadata *Scope = getDITypeRefOrNull(Record[5]);
711 Metadata *BaseType = getDITypeRefOrNull(Record[6]);
718 Metadata *BaseType = nullptr;
712719 uint64_t SizeInBits = Record[7];
713720 if (Record[8] > (uint64_t)std::numeric_limits::max())
714721 return error("Alignment value is too large");
715722 uint32_t AlignInBits = Record[8];
716 uint64_t OffsetInBits = Record[9];
723 uint64_t OffsetInBits = 0;
717724 DINode::DIFlags Flags = static_cast(Record[10]);
718 Metadata *Elements = getMDOrNull(Record[11]);
725 Metadata *Elements = nullptr;
719726 unsigned RuntimeLang = Record[12];
720 Metadata *VTableHolder = getDITypeRefOrNull(Record[13]);
721 Metadata *TemplateParams = getMDOrNull(Record[14]);
727 Metadata *VTableHolder = nullptr;
728 Metadata *TemplateParams = nullptr;
722729 auto *Identifier = getMDString(Record[15]);
730 // If this module is being parsed so that it can be ThinLTO imported
731 // into another module, composite types only need to be imported
732 // as type declarations (unless full type definitions requested).
733 // Create type declarations up front to save memory. Also, buildODRType
734 // handles the case where this is type ODRed with a definition needed
735 // by the importing module, in which case the existing definition is
736 // used.
737 if (IsImporting && !ImportFullTypeDefinitions &&
738 (Tag == dwarf::DW_TAG_enumeration_type ||
739 Tag == dwarf::DW_TAG_class_type ||
740 Tag == dwarf::DW_TAG_structure_type ||
741 Tag == dwarf::DW_TAG_union_type)) {
742 Flags = Flags | DINode::FlagFwdDecl;
743 } else {
744 BaseType = getDITypeRefOrNull(Record[6]);
745 OffsetInBits = Record[9];
746 Elements = getMDOrNull(Record[11]);
747 VTableHolder = getDITypeRefOrNull(Record[13]);
748 TemplateParams = getMDOrNull(Record[14]);
749 }
723750 DICompositeType *CT = nullptr;
724751 if (Identifier)
725752 CT = DICompositeType::buildODRType(
12801307 return *this;
12811308 }
12821309 MetadataLoader::MetadataLoader(MetadataLoader &&RHS)
1283 : Pimpl(std::move(RHS.Pimpl)) {}
1310 : Pimpl(std::move(RHS.Pimpl)), IsImporting(RHS.IsImporting) {}
12841311
12851312 MetadataLoader::~MetadataLoader() = default;
12861313 MetadataLoader::MetadataLoader(BitstreamCursor &Stream, Module &TheModule,
12871314 BitcodeReaderValueList &ValueList,
1315 bool IsImporting,
12881316 std::function getTypeByID)
12891317 : Pimpl(llvm::make_unique(Stream, TheModule, ValueList,
1290 getTypeByID)) {}
1318 getTypeByID)),
1319 IsImporting(IsImporting) {}
12911320
12921321 Error MetadataLoader::parseMetadata(bool ModuleLevel) {
1293 return Pimpl->parseMetadata(ModuleLevel);
1322 return Pimpl->parseMetadata(ModuleLevel, IsImporting);
12941323 }
12951324
12961325 bool MetadataLoader::hasFwdRefs() const { return Pimpl->hasFwdRefs(); }
3535 class MetadataLoader {
3636 class MetadataLoaderImpl;
3737 std::unique_ptr Pimpl;
38 /// True if metadata is being parsed for a module being ThinLTO imported.
39 bool IsImporting = false;
3840 Error parseMetadata(bool ModuleLevel);
3941
4042 public:
4143 ~MetadataLoader();
4244 MetadataLoader(BitstreamCursor &Stream, Module &TheModule,
43 BitcodeReaderValueList &ValueList,
45 BitcodeReaderValueList &ValueList, bool IsImporting,
4446 std::function getTypeByID);
4547 MetadataLoader &operator=(MetadataLoader &&);
4648 MetadataLoader(MetadataLoader &&);
251251 // ModuleSymbolTable.
252252 for (auto BM : *BMsOrErr) {
253253 Expected> MOrErr =
254 BM.getLazyModule(File->Ctx, /*ShouldLazyLoadMetadata*/ true);
254 BM.getLazyModule(File->Ctx, /*ShouldLazyLoadMetadata*/ true,
255 /*IsImporting*/ false);
255256 if (!MOrErr)
256257 return MOrErr.takeError();
257258
414415 RegularLTO.Mover = llvm::make_unique(*RegularLTO.CombinedModule);
415416 }
416417 Expected> MOrErr =
417 BM.getLazyModule(RegularLTO.Ctx, /*ShouldLazyLoadMetadata*/ true);
418 BM.getLazyModule(RegularLTO.Ctx, /*ShouldLazyLoadMetadata*/ true,
419 /*IsImporting*/ false);
418420 if (!MOrErr)
419421 return MOrErr.takeError();
420422
355355 auto I = ModuleMap.find(Identifier);
356356 assert(I != ModuleMap.end());
357357 return I->second.getLazyModule(Mod.getContext(),
358 /*ShouldLazyLoadMetadata=*/true);
358 /*ShouldLazyLoadMetadata=*/true,
359 /*IsImporting*/ true);
359360 };
360361
361362 FunctionImporter Importer(CombinedIndex, ModuleLoader);
167167
168168 static std::unique_ptr
169169 loadModuleFromBuffer(const MemoryBufferRef &Buffer, LLVMContext &Context,
170 bool Lazy) {
170 bool Lazy, bool IsImporting) {
171171 SMDiagnostic Err;
172172 Expected> ModuleOrErr =
173 Lazy ? getLazyBitcodeModule(Buffer, Context,
174 /* ShouldLazyLoadMetadata */ true)
175 : parseBitcodeFile(Buffer, Context);
173 Lazy
174 ? getLazyBitcodeModule(Buffer, Context,
175 /* ShouldLazyLoadMetadata */ true, IsImporting)
176 : parseBitcodeFile(Buffer, Context);
176177 if (!ModuleOrErr) {
177178 handleAllErrors(ModuleOrErr.takeError(), [&](ErrorInfoBase &EIB) {
178179 SMDiagnostic Err = SMDiagnostic(Buffer.getBufferIdentifier(),
190191 const FunctionImporter::ImportMapTy &ImportList) {
191192 auto Loader = [&](StringRef Identifier) {
192193 return loadModuleFromBuffer(ModuleMap[Identifier], TheModule.getContext(),
193 /*Lazy=*/true);
194 /*Lazy=*/true, /*IsImporting*/ true);
194195 };
195196
196197 FunctionImporter Importer(Index, Loader);
786787 Context.setDiscardValueNames(LTODiscardValueNames);
787788
788789 // Parse module now
789 auto TheModule = loadModuleFromBuffer(ModuleBuffer, Context, false);
790 auto TheModule = loadModuleFromBuffer(ModuleBuffer, Context, false,
791 /*IsImporting*/ false);
790792
791793 // CodeGen
792794 ProducedBinaries[count] = codegen(*TheModule);
932934 }
933935
934936 // Parse module now
935 auto TheModule = loadModuleFromBuffer(ModuleBuffer, Context, false);
937 auto TheModule = loadModuleFromBuffer(ModuleBuffer, Context, false,
938 /*IsImporting*/ false);
936939
937940 // Save temps: original file.
938941 saveTempBitcode(*TheModule, SaveTempsDir, count, ".0.original.bc");
126126 std::vector> Mods;
127127 for (auto BM : *BMsOrErr) {
128128 Expected> MOrErr =
129 BM.getLazyModule(Context, /*ShouldLazyLoadMetadata*/ true);
129 BM.getLazyModule(Context, /*ShouldLazyLoadMetadata*/ true,
130 /*IsImporting*/ false);
130131 if (!MOrErr)
131132 return MOrErr.takeError();
132133
0 ; ModuleID = 'debuginfo-compositetype-import2.c'
1 source_filename = "debuginfo-compositetype-import2.c"
2 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
3 target triple = "x86_64-unknown-linux-gnu"
4
5 ; Function Attrs: nounwind uwtable
6 define i32 @main() {
7 entry:
8 call void (...) @foo()
9 ret i32 0
10 }
11
12 declare void @foo(...) #1
0 ; Test to ensure DICompositeType are imported as type declarations
1 ; for ThinLTO
2
3 ; RUN: opt -module-summary %s -o %t1.bc
4 ; RUN: opt -module-summary %p/Inputs/debuginfo-compositetype-import.ll -o %t2.bc
5 ; RUN: llvm-lto -thinlto-action=thinlink -o %t.index.bc %t1.bc %t2.bc
6
7 ; By default, composite types are imported as type declarations
8 ; RUN: llvm-lto -thinlto-action=import %t2.bc -thinlto-index=%t.index.bc -o - | llvm-dis -o - | FileCheck %s
9 ; RUN: llvm-lto2 %t1.bc %t2.bc -o %t.out -save-temps \
10 ; RUN: -r %t2.bc,main,plx \
11 ; RUN: -r %t2.bc,foo,l \
12 ; RUN: -r %t1.bc,foo,pl
13 ; RUN: llvm-dis < %t.out.1.3.import.bc | FileCheck %s
14
15 ; CHECK: distinct !DICompositeType(tag: DW_TAG_enumeration_type, name: "enum", scope: !{{[0-9]+}}, file: !{{[0-9]+}}, line: 50, size: 32, flags: DIFlagFwdDecl, identifier: "enum")
16 ; CHECK: distinct !DICompositeType(tag: DW_TAG_class_type, name: "class", scope: !{{[0-9]+}}, file: !{{[0-9]+}}, line: 728, size: 448, flags: DIFlagFwdDecl, identifier: "class")
17 ; CHECK: distinct !DICompositeType(tag: DW_TAG_structure_type, name: "struct", scope: !{{[0-9]+}}, file: !{{[0-9]+}}, line: 309, size: 128, flags: DIFlagFwdDecl, identifier: "list")
18 ; CHECK: distinct !DICompositeType(tag: DW_TAG_union_type, file: !{{[0-9]+}}, line: 115, size: 384, flags: DIFlagFwdDecl, identifier: "union")
19
20 ; Ensure that full type definitions of composite types are imported if requested
21 ; RUN: llvm-lto -import-full-type-definitions -thinlto-action=import %t2.bc -thinlto-index=%t.index.bc -o - | llvm-dis -o - | FileCheck %s --check-prefix=FULL
22 ; RUN: llvm-lto2 %t1.bc %t2.bc -o %t.out -save-temps \
23 ; RUN: -import-full-type-definitions \
24 ; RUN: -r %t2.bc,main,plx \
25 ; RUN: -r %t2.bc,foo,l \
26 ; RUN: -r %t1.bc,foo,pl
27 ; RUN: llvm-dis < %t.out.1.3.import.bc | FileCheck %s --check-prefix=FULL
28
29 ; FULL: distinct !DICompositeType(tag: DW_TAG_enumeration_type, name: "enum", scope: !{{[0-9]+}}, file: !{{[0-9]+}}, line: 50, size: 32, elements: !{{[0-9]+}}, identifier: "enum")
30 ; FULL: distinct !DICompositeType(tag: DW_TAG_class_type, name: "class", scope: !{{[0-9]+}}, file: !{{[0-9]+}}, line: 728, size: 448, elements: !{{[0-9]+}}, identifier: "class")
31 ; FULL: distinct !DICompositeType(tag: DW_TAG_structure_type, name: "struct", scope: !{{[0-9]+}}, file: !{{[0-9]+}}, line: 309, baseType: !{{[0-9]+}}, size: 128, offset: 64, elements: !{{[0-9]+}}, vtableHolder: !{{[0-9]+}}, templateParams: !{{[0-9]+}}, identifier: "list")
32 ; FULL: distinct !DICompositeType(tag: DW_TAG_union_type, file: !{{[0-9]+}}, line: 115, size: 384, elements: !{{[0-9]+}}, identifier: "union")
33
34 ; ModuleID = 'debuginfo-compositetype-import.c'
35 source_filename = "debuginfo-compositetype-import.c"
36 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
37 target triple = "x86_64-unknown-linux-gnu"
38
39 ; Function Attrs: nounwind uwtable
40 define void @foo() #0 !dbg !6 {
41 entry:
42 ret void
43 }
44
45 !llvm.dbg.cu = !{!0}
46 !llvm.module.flags = !{!2, !3}
47 !llvm.ident = !{!4}
48
49 !0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 4.0.0 (trunk 286863) (llvm/trunk 286875)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug)
50 !1 = !DIFile(filename: "debuginfo-compositetype-import.c", directory: "")
51 !2 = !{i32 2, !"Dwarf Version", i32 4}
52 !3 = !{i32 2, !"Debug Info Version", i32 3}
53 !4 = !{!"clang version 4.0.0 (trunk 286863) (llvm/trunk 286875)"}
54 !5 = !{}
55 !6 = distinct !DISubprogram(name: "foo", scope: !1, file: !1, line: 1, type: !7, isLocal: false, isDefinition: true, scopeLine: 2, isOptimized: false, unit: !0, variables: !5)
56 !7 = !DISubroutineType(types: !8)
57 !8 = !{!9, !10, !11, !12}
58 !9 = !DICompositeType(tag: DW_TAG_enumeration_type, name: "enum", scope: !1, file: !1, line: 50, size: 32, elements: !5, identifier: "enum")
59 !10 = !DICompositeType(tag: DW_TAG_class_type, name: "class", scope: !1, file: !1, line: 728, size: 448, elements: !5, identifier: "class")
60 !11 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "struct", scope: !1, file: !1, line: 309, baseType: !10, size: 128, offset: 64, elements: !5, vtableHolder: !10, templateParams: !5, identifier: "list")
61 !12 = distinct !DICompositeType(tag: DW_TAG_union_type, file: !1, line: 115, size: 384, elements: !5, identifier: "union")