Skip to content
This repository was archived by the owner on Feb 5, 2019. It is now read-only.

Commit d11d789

Browse files
committed
[ThinLTO] Only emit referenced type id records in index files
Summary: Currently all type ids are emitted into the index file when it is written. For distributed ThinLTO, that meant that all type ids were being duplicated into every single distributed index file, regardless of whether they were referenced, leading to huge amounts of unnecessary duplication and size bloat. Keep track of the type id GUIDs actually referenced by the GV summary records being emitted, and only emit those type IDs. Add a new test, and fix test/Assembler/thinlto-summary.ll so that all type ids are referenced to prevent deletion in that test. Reviewers: pcc Subscribers: mehdi_amini, inglorion, eraman, steven_wu, dexonsmith, vitalybuka, llvm-commits Differential Revision: https://reviews.llvm.org/D49565 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@337503 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent f97a90d commit d11d789

File tree

4 files changed

+109
-7
lines changed

4 files changed

+109
-7
lines changed

lib/Bitcode/Writer/BitcodeWriter.cpp

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3353,10 +3353,14 @@ void IndexBitcodeWriter::writeModStrings() {
33533353

33543354
/// Write the function type metadata related records that need to appear before
33553355
/// a function summary entry (whether per-module or combined).
3356-
static void writeFunctionTypeMetadataRecords(BitstreamWriter &Stream,
3357-
FunctionSummary *FS) {
3358-
if (!FS->type_tests().empty())
3356+
static void writeFunctionTypeMetadataRecords(
3357+
BitstreamWriter &Stream, FunctionSummary *FS,
3358+
std::set<GlobalValue::GUID> &ReferencedTypeIds) {
3359+
if (!FS->type_tests().empty()) {
33593360
Stream.EmitRecord(bitc::FS_TYPE_TESTS, FS->type_tests());
3361+
for (auto &TT : FS->type_tests())
3362+
ReferencedTypeIds.insert(TT);
3363+
}
33603364

33613365
SmallVector<uint64_t, 64> Record;
33623366

@@ -3368,6 +3372,7 @@ static void writeFunctionTypeMetadataRecords(BitstreamWriter &Stream,
33683372
for (auto &VF : VFs) {
33693373
Record.push_back(VF.GUID);
33703374
Record.push_back(VF.Offset);
3375+
ReferencedTypeIds.insert(VF.GUID);
33713376
}
33723377
Stream.EmitRecord(Ty, Record);
33733378
};
@@ -3382,6 +3387,7 @@ static void writeFunctionTypeMetadataRecords(BitstreamWriter &Stream,
33823387
for (auto &VC : VCs) {
33833388
Record.clear();
33843389
Record.push_back(VC.VFunc.GUID);
3390+
ReferencedTypeIds.insert(VC.VFunc.GUID);
33853391
Record.push_back(VC.VFunc.Offset);
33863392
Record.insert(Record.end(), VC.Args.begin(), VC.Args.end());
33873393
Stream.EmitRecord(Ty, Record);
@@ -3447,7 +3453,8 @@ void ModuleBitcodeWriterBase::writePerModuleFunctionSummaryRecord(
34473453
NameVals.push_back(ValueID);
34483454

34493455
FunctionSummary *FS = cast<FunctionSummary>(Summary);
3450-
writeFunctionTypeMetadataRecords(Stream, FS);
3456+
std::set<GlobalValue::GUID> ReferencedTypeIds;
3457+
writeFunctionTypeMetadataRecords(Stream, FS, ReferencedTypeIds);
34513458

34523459
NameVals.push_back(getEncodedGVSummaryFlags(FS->flags()));
34533460
NameVals.push_back(FS->instCount());
@@ -3702,6 +3709,10 @@ void IndexBitcodeWriter::writeCombinedGlobalValueSummary() {
37023709

37033710
SmallVector<uint64_t, 64> NameVals;
37043711

3712+
// Set that will be populated during call to writeFunctionTypeMetadataRecords
3713+
// with the type ids referenced by this index file.
3714+
std::set<GlobalValue::GUID> ReferencedTypeIds;
3715+
37053716
// For local linkage, we also emit the original name separately
37063717
// immediately after the record.
37073718
auto MaybeEmitOriginalName = [&](GlobalValueSummary &S) {
@@ -3753,7 +3764,7 @@ void IndexBitcodeWriter::writeCombinedGlobalValueSummary() {
37533764
}
37543765

37553766
auto *FS = cast<FunctionSummary>(S);
3756-
writeFunctionTypeMetadataRecords(Stream, FS);
3767+
writeFunctionTypeMetadataRecords(Stream, FS, ReferencedTypeIds);
37573768

37583769
NameVals.push_back(*ValueId);
37593770
NameVals.push_back(Index.getModuleId(FS->modulePath()));
@@ -3862,6 +3873,9 @@ void IndexBitcodeWriter::writeCombinedGlobalValueSummary() {
38623873

38633874
if (!Index.typeIds().empty()) {
38643875
for (auto &S : Index.typeIds()) {
3876+
// Skip if not referenced in any GV summary within this index file.
3877+
if (!ReferencedTypeIds.count(GlobalValue::getGUID(S.first)))
3878+
continue;
38653879
writeTypeIdSummaryRecord(NameVals, StrtabBuilder, S.first, S.second);
38663880
Stream.EmitRecord(bitc::FS_TYPE_ID, NameVals);
38673881
NameVals.clear();

test/Assembler/thinlto-summary.ll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@
5050
^20 = gv: (guid: 19, summaries: (function: (module: ^0, flags: (linkage: external, notEligibleToImport: 0, live: 0, dsoLocal: 0), insts: 8, typeIdInfo: (typeTestAssumeVCalls: (vFuncId: (^27, offset: 16))))))
5151
^21 = gv: (guid: 20, summaries: (function: (module: ^0, flags: (linkage: external, notEligibleToImport: 0, live: 0, dsoLocal: 0), insts: 5, typeIdInfo: (typeCheckedLoadVCalls: (vFuncId: (^25, offset: 16))))))
5252
^22 = gv: (guid: 21, summaries: (function: (module: ^0, flags: (linkage: external, notEligibleToImport: 0, live: 0, dsoLocal: 0), insts: 15, typeIdInfo: (typeTestAssumeConstVCalls: (vFuncId: (^27, offset: 16), args: (42), vFuncId: (^27, offset: 24), args: (43))))))
53-
^23 = gv: (guid: 22, summaries: (function: (module: ^0, flags: (linkage: external, notEligibleToImport: 0, live: 0, dsoLocal: 0), insts: 5, typeIdInfo: (typeCheckedLoadConstVCalls: (vFuncId: (^27, offset: 16), args: (42))))))
53+
^23 = gv: (guid: 22, summaries: (function: (module: ^0, flags: (linkage: external, notEligibleToImport: 0, live: 0, dsoLocal: 0), insts: 5, typeIdInfo: (typeCheckedLoadConstVCalls: (vFuncId: (^28, offset: 16), args: (42))))))
5454

5555
; Test TypeId summaries:
5656

@@ -88,7 +88,7 @@
8888
; CHECK: ^20 = gv: (guid: 19, summaries: (function: (module: ^0, flags: (linkage: external, notEligibleToImport: 0, live: 0, dsoLocal: 0), insts: 8, typeIdInfo: (typeTestAssumeVCalls: (vFuncId: (^27, offset: 16))))))
8989
; CHECK: ^21 = gv: (guid: 20, summaries: (function: (module: ^0, flags: (linkage: external, notEligibleToImport: 0, live: 0, dsoLocal: 0), insts: 5, typeIdInfo: (typeCheckedLoadVCalls: (vFuncId: (^25, offset: 16))))))
9090
; CHECK: ^22 = gv: (guid: 21, summaries: (function: (module: ^0, flags: (linkage: external, notEligibleToImport: 0, live: 0, dsoLocal: 0), insts: 15, typeIdInfo: (typeTestAssumeConstVCalls: (vFuncId: (^27, offset: 16), args: (42), vFuncId: (^27, offset: 24), args: (43))))))
91-
; CHECK: ^23 = gv: (guid: 22, summaries: (function: (module: ^0, flags: (linkage: external, notEligibleToImport: 0, live: 0, dsoLocal: 0), insts: 5, typeIdInfo: (typeCheckedLoadConstVCalls: (vFuncId: (^27, offset: 16), args: (42))))))
91+
; CHECK: ^23 = gv: (guid: 22, summaries: (function: (module: ^0, flags: (linkage: external, notEligibleToImport: 0, live: 0, dsoLocal: 0), insts: 5, typeIdInfo: (typeCheckedLoadConstVCalls: (vFuncId: (^28, offset: 16), args: (42))))))
9292
; CHECK: ^24 = typeid: (name: "_ZTS1A", summary: (typeTestRes: (kind: allOnes, sizeM1BitWidth: 7), wpdResolutions: ((offset: 0, wpdRes: (kind: branchFunnel)), (offset: 8, wpdRes: (kind: singleImpl, singleImplName: "_ZN1A1nEi")), (offset: 16, wpdRes: (kind: indir, resByArg: (args: (1, 2), byArg: (kind: indir, byte: 2, bit: 3), args: (3), byArg: (kind: uniformRetVal, info: 1), args: (4), byArg: (kind: uniqueRetVal, info: 1), args: (5), byArg: (kind: virtualConstProp))))))) ; guid = 7004155349499253778
9393
; CHECK: ^25 = typeid: (name: "_ZTS1B", summary: (typeTestRes: (kind: inline, sizeM1BitWidth: 0, alignLog2: 1, sizeM1: 2, bitMask: 3, inlineBits: 4))) ; guid = 6203814149063363976
9494
; CHECK: ^26 = typeid: (name: "_ZTS1C", summary: (typeTestRes: (kind: single, sizeM1BitWidth: 0))) ; guid = 1884921850105019584
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
2+
target triple = "x86_64-grtev4-linux-gnu"
3+
4+
%struct.B2 = type { %struct.A2 }
5+
%struct.A2 = type { i32 (...)** }
6+
7+
@_ZTV1B2 = constant { [3 x i8*] } { [3 x i8*] [i8* undef, i8* undef, i8* undef] }, !type !0
8+
9+
define void @test2(i8* %b) {
10+
entry:
11+
%0 = bitcast i8* %b to i8**
12+
%vtable2 = load i8*, i8** %0
13+
%1 = tail call i1 @llvm.type.test(i8* %vtable2, metadata !"_ZTS1A2")
14+
br i1 %1, label %cont, label %trap
15+
16+
trap:
17+
tail call void @llvm.trap()
18+
unreachable
19+
20+
cont:
21+
ret void
22+
}
23+
24+
declare i1 @llvm.type.test(i8*, metadata)
25+
declare void @llvm.trap()
26+
27+
!0 = !{i64 16, !"_ZTS1A2"}
28+
!1 = !{i64 16, !"_ZTS1B2"}

test/ThinLTO/X86/cfi-distributed.ll

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
; REQUIRES: x86-registered-target
2+
3+
; Test to ensure that only referenced type ID records are emitted into
4+
; each distributed index file.
5+
6+
; RUN: opt -thinlto-bc -o %t1.o %s
7+
; RUN: opt -thinlto-bc -o %t2.o %p/Inputs/cfi-distributed.ll
8+
9+
; RUN: llvm-lto2 run -thinlto-distributed-indexes %t1.o %t2.o \
10+
; RUN: -o %t3 \
11+
; RUN: -r=%t1.o,test,px \
12+
; RUN: -r=%t1.o,_ZTV1B, \
13+
; RUN: -r=%t1.o,_ZTV1B,px \
14+
; RUN: -r=%t1.o,test2, \
15+
; RUN: -r=%t2.o,test2,px \
16+
; RUN: -r=%t2.o,_ZTV1B2, \
17+
; RUN: -r=%t2.o,_ZTV1B2,px
18+
19+
; Since @test calls @test2, the latter should be imported here and the
20+
; first index file should reference both type ids.
21+
; RUN: llvm-dis %t1.o.thinlto.bc -o - | FileCheck %s --check-prefix=INDEX1
22+
; INDEX1: typeid: (name: "_ZTS1A"
23+
; INDEX1: typeid: (name: "_ZTS1A2"
24+
25+
; The second index file, corresponding to @test2, should only contain the
26+
; typeid for _ZTS1A.
27+
; RUN: llvm-dis %t2.o.thinlto.bc -o - | FileCheck %s --check-prefix=INDEX2
28+
; INDEX2-NOT: typeid: (name: "_ZTS1A"
29+
; INDEX2: typeid: (name: "_ZTS1A2"
30+
31+
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
32+
target triple = "x86_64-grtev4-linux-gnu"
33+
34+
%struct.B = type { %struct.A }
35+
%struct.A = type { i32 (...)** }
36+
37+
@_ZTV1B = constant { [3 x i8*] } { [3 x i8*] [i8* undef, i8* undef, i8* undef] }, !type !0
38+
39+
define void @test(i8* %b) {
40+
entry:
41+
tail call void @test2(i8* %b)
42+
%0 = bitcast i8* %b to i8**
43+
%vtable2 = load i8*, i8** %0
44+
%1 = tail call i1 @llvm.type.test(i8* %vtable2, metadata !"_ZTS1A")
45+
br i1 %1, label %cont, label %trap
46+
47+
trap:
48+
tail call void @llvm.trap()
49+
unreachable
50+
51+
cont:
52+
ret void
53+
}
54+
55+
declare void @test2(i8*)
56+
declare i1 @llvm.type.test(i8*, metadata)
57+
declare void @llvm.trap()
58+
59+
!0 = !{i64 16, !"_ZTS1A"}
60+
!1 = !{i64 16, !"_ZTS1B"}

0 commit comments

Comments
 (0)