Skip to content

Commit 8ed15bd

Browse files
[Prototype] Implement type ref based elimination
1 parent 639d040 commit 8ed15bd

File tree

8 files changed

+129
-33
lines changed

8 files changed

+129
-33
lines changed

include/swift/SIL/ModuleSummary.h

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -130,8 +130,13 @@ struct VFuncSlot {
130130
VFuncSlot(KindTy Kind, GUID VFuncID) : Kind(Kind), VFuncID(VFuncID) {}
131131
};
132132

133+
struct VFuncImpl {
134+
GUID Guid;
135+
GUID TypeGuid;
136+
};
137+
133138
using FunctionSummaryMapTy = std::map<GUID, std::unique_ptr<FunctionSummary>>;
134-
using VFuncToImplsMapTy = std::map<GUID, std::vector<GUID>>;
139+
using VFuncToImplsMapTy = std::map<GUID, std::vector<VFuncImpl>>;
135140

136141
/// Module summary that consists of function summaries and virtual function
137142
/// tables.
@@ -195,24 +200,25 @@ class ModuleSummaryIndex {
195200
}
196201

197202
/// Record a implementation for the virtual function slot.
198-
void addImplementation(VFuncSlot slot, GUID implGUID) {
203+
void addImplementation(VFuncSlot slot, GUID implGUID, GUID typeGUID) {
199204
VFuncToImplsMapTy &table = getVFuncMap(slot.Kind);
200205
auto found = table.find(slot.VFuncID);
206+
VFuncImpl impl = {implGUID, typeGUID};
201207
if (found == table.end()) {
202-
table.insert(std::make_pair(slot.VFuncID, std::vector<GUID>{implGUID}));
208+
table.insert(std::make_pair(slot.VFuncID, std::vector<VFuncImpl>{impl}));
203209
return;
204210
}
205-
found->second.push_back(implGUID);
211+
found->second.push_back(impl);
206212
}
207213

208214
/// Return a list of implementations for the virtual function slot.
209-
ArrayRef<GUID> getImplementations(VFuncSlot slot) const {
215+
ArrayRef<VFuncImpl> getImplementations(VFuncSlot slot) const {
210216
const VFuncToImplsMapTy &table = getVFuncMap(slot.Kind);
211217
auto found = table.find(slot.VFuncID);
212218
if (found == table.end()) {
213-
return ArrayRef<GUID>();
219+
return ArrayRef<VFuncImpl>();
214220
}
215-
return ArrayRef<GUID>(found->second);
221+
return ArrayRef<VFuncImpl>(found->second);
216222
}
217223

218224
const VFuncToImplsMapTy &getWitnessTableMethodMap() const {

include/swift/Serialization/ModuleSummary.h

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -145,8 +145,13 @@ struct VFuncSlot {
145145
VFuncSlot(KindTy Kind, GUID VFuncID) : Kind(Kind), VFuncID(VFuncID) {}
146146
};
147147

148+
struct VFuncImpl {
149+
GUID Guid;
150+
GUID TypeGuid;
151+
};
152+
148153
using FunctionSummaryMapTy = std::map<GUID, std::unique_ptr<FunctionSummary>>;
149-
using VFuncToImplsMapTy = std::map<GUID, std::vector<GUID>>;
154+
using VFuncToImplsMapTy = std::map<GUID, std::vector<VFuncImpl>>;
150155
using UsedTypeListTy = std::vector<GUID>;
151156

152157
/// Module summary that consists of function summaries and virtual function
@@ -214,24 +219,25 @@ class ModuleSummaryIndex {
214219
}
215220

216221
/// Record a implementation for the virtual function slot.
217-
void addImplementation(VFuncSlot slot, GUID implGUID) {
222+
void addImplementation(VFuncSlot slot, GUID implGUID, GUID typeGUID) {
218223
VFuncToImplsMapTy &table = getVFuncMap(slot.Kind);
219224
auto found = table.find(slot.VFuncID);
225+
VFuncImpl impl = {implGUID, typeGUID};
220226
if (found == table.end()) {
221-
table.insert(std::make_pair(slot.VFuncID, std::vector<GUID>{implGUID}));
227+
table.insert(std::make_pair(slot.VFuncID, std::vector<VFuncImpl>{impl}));
222228
return;
223229
}
224-
found->second.push_back(implGUID);
230+
found->second.push_back(impl);
225231
}
226232

227233
/// Return a list of implementations for the virtual function slot.
228-
ArrayRef<GUID> getImplementations(VFuncSlot slot) const {
234+
ArrayRef<VFuncImpl> getImplementations(VFuncSlot slot) const {
229235
const VFuncToImplsMapTy &table = getVFuncMap(slot.Kind);
230236
auto found = table.find(slot.VFuncID);
231237
if (found == table.end()) {
232-
return ArrayRef<GUID>();
238+
return ArrayRef<VFuncImpl>();
233239
}
234-
return ArrayRef<GUID>(found->second);
240+
return ArrayRef<VFuncImpl>(found->second);
235241
}
236242

237243
void markUsedType(GUID typeGUID) { UsedTypeList.push_back(typeGUID); }

lib/SILOptimizer/IPO/CrossDeadFunctionElimination.cpp

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#define DEBUG_TYPE "sil-cross-dead-function-elimination"
2+
#include "swift/AST/ASTMangler.h"
23
#include "swift/AST/DiagnosticsFrontend.h"
34
#include "swift/AST/ProtocolConformance.h"
45
#include "swift/SIL/InstructionUtils.h"
@@ -31,7 +32,29 @@ class SILCrossDeadFuncElimination : public SILModuleTransform {
3132

3233
public:
3334
SILCrossDeadFuncElimination() {}
34-
35+
36+
void eliminateDeadTables(SILModule &M) {
37+
auto &WitnessTables = M.getWitnessTableList();
38+
std::set<GUID> UsedTypes;
39+
for (auto type : TheSummary.getUsedTypeList()) {
40+
UsedTypes.insert(type);
41+
}
42+
Mangle::ASTMangler mangler;
43+
for (auto WI = WitnessTables.begin(), EI = WitnessTables.end(); WI != EI;) {
44+
SILWitnessTable *WT = &*WI;
45+
++WI;
46+
CanType type = WI->getConformingType();
47+
std::string mangled = mangler.mangleTypeWithoutPrefix(type);
48+
GUID guid = getGUIDFromUniqueName(mangled);
49+
if (UsedTypes.find(guid) != UsedTypes.end()) {
50+
continue;
51+
}
52+
WT->clearMethods_if([&] (const SILWitnessTable::MethodWitness &MW) -> bool {
53+
return true;
54+
});
55+
}
56+
}
57+
3558
void eliminateDeadEntriesFromTables(SILModule &M) {
3659

3760
for (auto VT : M.getVTables()) {

lib/Serialization/ModuleSummaryFormat.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ void Serializer::emitVFuncTable(const VFuncToImplsMapTy T,
143143
VFuncSlot::KindTy kind) {
144144
for (auto &pair : T) {
145145
GUID guid = pair.first;
146-
std::vector<GUID> impls = pair.second;
146+
std::vector<VFuncImpl> impls = pair.second;
147147
using namespace record_block;
148148

149149
VFuncMetadataLayout::emitRecord(Out, ScratchRecord,
@@ -152,7 +152,7 @@ void Serializer::emitVFuncTable(const VFuncToImplsMapTy T,
152152

153153
for (auto impl : impls) {
154154
VFuncImplLayout::emitRecord(Out, ScratchRecord,
155-
AbbrCodes[VFuncImplLayout::Code], impl);
155+
AbbrCodes[VFuncImplLayout::Code], impl.Guid, impl.TypeGuid);
156156
}
157157
}
158158
}
@@ -430,9 +430,9 @@ bool Deserializer::readModuleSummary() {
430430
if (!CurrentSlot) {
431431
report_fatal_error("Unexpected METHOD_IMPL record");
432432
}
433-
GUID implGUID;
434-
VFuncImplLayout::readRecord(Scratch, implGUID);
435-
moduleSummary.addImplementation(CurrentSlot.getValue(), implGUID);
433+
GUID implGUID, typeGUID;
434+
VFuncImplLayout::readRecord(Scratch, implGUID, typeGUID);
435+
moduleSummary.addImplementation(CurrentSlot.getValue(), implGUID, typeGUID);
436436
break;
437437
}
438438
case USED_TYPE: {

lib/Serialization/ModuleSummaryFormat.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,8 @@ using VFuncMetadataLayout =
6969
>;
7070

7171
using VFuncImplLayout = BCRecordLayout<VFUNC_IMPL,
72-
BCGUID // impl func guid
72+
BCGUID, // impl func guid
73+
BCGUID // impl type guid
7374
>;
7475
using UsedTypeLayout = BCRecordLayout<USED_TYPE,
7576
BCGUID // type guid

lib/Serialization/ModuleSummaryIndexer.cpp

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,12 @@ GUID modulesummary::getGUIDFromUniqueName(llvm::StringRef Name) {
1616
return llvm::MD5Hash(Name);
1717
}
1818

19+
static GUID getTypeGUID(Type type) {
20+
Mangle::ASTMangler mangler;
21+
std::string mangled = mangler.mangleTypeWithoutPrefix(type);
22+
return getGUIDFromUniqueName(mangled);
23+
}
24+
1925
namespace {
2026
class FunctionSummaryIndexer : public SILInstructionVisitor<FunctionSummaryIndexer> {
2127
friend SILInstructionVisitor<FunctionSummaryIndexer>;
@@ -344,8 +350,8 @@ void ModuleSummaryIndexer::ensurePreserved(const SILDeclRef &Ref,
344350
if (Impls.empty())
345351
return;
346352

347-
for (GUID Impl : Impls) {
348-
auto FS = TheSummary->getFunctionSummary(Impl);
353+
for (VFuncImpl Impl : Impls) {
354+
auto FS = TheSummary->getFunctionSummary(Impl.Guid);
349355
assert(FS);
350356
FS->setPreserved(true);
351357
}
@@ -376,6 +382,7 @@ void ModuleSummaryIndexer::indexWitnessTable(const SILWitnessTable &WT) {
376382
auto isPossibllyUsedExternally =
377383
WT.getDeclContext()->getParentModule() != Mod.getSwiftModule() ||
378384
WT.getProtocol()->getParentModule() != Mod.getSwiftModule();
385+
auto typeGUID = getTypeGUID(WT.getConformingType());
379386
for (auto entry : WT.getEntries()) {
380387
if (entry.getKind() != SILWitnessTable::Method)
381388
continue;
@@ -386,7 +393,8 @@ void ModuleSummaryIndexer::indexWitnessTable(const SILWitnessTable &WT) {
386393
continue;
387394
auto slot = createVFuncSlot(methodWitness.Requirement, VFuncSlot::Witness);
388395
TheSummary->addImplementation(slot,
389-
getGUIDFromUniqueName(Witness->getName()));
396+
getGUIDFromUniqueName(Witness->getName()),
397+
typeGUID);
390398

391399
if (isPossibllyUsedExternally) {
392400
ensurePreserved(*Witness);
@@ -395,7 +403,7 @@ void ModuleSummaryIndexer::indexWitnessTable(const SILWitnessTable &WT) {
395403
}
396404

397405
void ModuleSummaryIndexer::indexVTable(const SILVTable &VT) {
398-
406+
auto typeGUID = getTypeGUID(VT.getClass()->getInterfaceType());
399407
for (auto entry : VT.getEntries()) {
400408
auto Impl = entry.getImplementation();
401409
if (entry.getMethod().kind == SILDeclRef::Kind::Deallocator ||
@@ -411,7 +419,7 @@ void ModuleSummaryIndexer::indexVTable(const SILVTable &VT) {
411419
ensurePreserved(*Impl);
412420
}
413421
auto slot = createVFuncSlot(entry.getMethod(), VFuncSlot::VTable);
414-
TheSummary->addImplementation(slot, getGUIDFromUniqueName(Impl->getName()));
422+
TheSummary->addImplementation(slot, getGUIDFromUniqueName(Impl->getName()), typeGUID);
415423
}
416424
}
417425

tools/driver/cross_module_opt_main.cpp

Lines changed: 52 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -108,10 +108,56 @@ VFuncSlot createVFuncSlot(FunctionSummary::Call call) {
108108
return VFuncSlot(slotKind, call.getCallee());
109109
}
110110

111+
void markDeadTypeRef(ModuleSummaryIndex &summary, const llvm::DenseSet<GUID> &PreservedGUIDs) {
112+
SmallVector<GUID, 8> Worklist;
113+
SmallSetVector<GUID, 16> beenInWorklist;
114+
SmallSetVector<GUID, 16> UseMarkedTypes;
115+
116+
Worklist.append(PreservedGUIDs.begin(), PreservedGUIDs.end());
117+
118+
while (!Worklist.empty()) {
119+
auto target = Worklist.pop_back_val();
120+
if (!beenInWorklist.insert(target)) {
121+
continue;
122+
}
123+
auto maybeSummary = summary.getFunctionSummary(target);
124+
if (!maybeSummary) {
125+
llvm_unreachable("Bad GUID");
126+
}
127+
auto FS = maybeSummary;
128+
129+
for (auto typeRef : FS->typeRefs()) {
130+
if (UseMarkedTypes.insert(typeRef.Guid)) {
131+
summary.markUsedType(typeRef.Guid);
132+
}
133+
}
134+
for (auto Call : FS->calls()) {
135+
switch (Call.getKind()) {
136+
case FunctionSummary::Call::Direct: {
137+
Worklist.push_back(Call.getCallee());
138+
continue;
139+
}
140+
case FunctionSummary::Call::Witness:
141+
case FunctionSummary::Call::VTable: {
142+
VFuncSlot slot = createVFuncSlot(Call);
143+
auto Impls = summary.getImplementations(slot);
144+
for (auto Impl : Impls) {
145+
Worklist.push_back(Impl.Guid);
146+
}
147+
break;
148+
}
149+
case FunctionSummary::Call::kindCount:
150+
llvm_unreachable("impossible");
151+
}
152+
}
153+
}
154+
}
155+
111156
void markDeadSymbols(ModuleSummaryIndex &summary, llvm::DenseSet<GUID> &PreservedGUIDs) {
112157

113158
SmallVector<std::shared_ptr<LivenessTrace>, 8> Worklist;
114-
std::set<GUID> UseMarkedTypes;
159+
auto UsedTypesList = summary.getUsedTypeList();
160+
std::set<GUID> UsedTypesSet(UsedTypesList.begin(), UsedTypesList.end());
115161
unsigned LiveSymbols = 0;
116162

117163
for (auto GUID : PreservedGUIDs) {
@@ -143,11 +189,6 @@ void markDeadSymbols(ModuleSummaryIndex &summary, llvm::DenseSet<GUID> &Preserve
143189
FS->setLive(true);
144190
LiveSymbols++;
145191

146-
for (auto typeRef : FS->typeRefs()) {
147-
if (UseMarkedTypes.insert(typeRef.Guid).second) {
148-
summary.markUsedType(typeRef.Guid);
149-
}
150-
}
151192
for (auto Call : FS->calls()) {
152193
switch (Call.getKind()) {
153194
case FunctionSummary::Call::Direct: {
@@ -160,8 +201,11 @@ void markDeadSymbols(ModuleSummaryIndex &summary, llvm::DenseSet<GUID> &Preserve
160201
VFuncSlot slot = createVFuncSlot(Call);
161202
auto Impls = summary.getImplementations(slot);
162203
for (auto Impl : Impls) {
204+
if (UsedTypesSet.find(Impl.TypeGuid) == UsedTypesSet.end()) {
205+
continue;
206+
}
163207
Worklist.push_back(std::make_shared<LivenessTrace>(
164-
trace, Impl, LivenessTrace::IndirectReferenced));
208+
trace, Impl.Guid, LivenessTrace::IndirectReferenced));
165209
}
166210
break;
167211
}
@@ -212,6 +256,7 @@ int cross_module_opt_main(ArrayRef<const char *> Args, const char *Argv0,
212256
TheSummary->setName("combined");
213257

214258
auto PreservedGUIDs = computePreservedGUIDs(TheSummary.get());
259+
markDeadTypeRef(*TheSummary.get(), PreservedGUIDs);
215260
markDeadSymbols(*TheSummary.get(), PreservedGUIDs);
216261

217262
modulesummary::writeModuleSummaryIndex(*TheSummary, Instance.getDiags(),

tools/swift-module-summary-test/swift-module-summary-test.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,10 @@ LLVM_YAML_DECLARE_MAPPING_TRAITS(modulesummary::ModuleSummaryIndex)
5959
LLVM_YAML_DECLARE_MAPPING_TRAITS(modulesummary::FunctionSummary)
6060
LLVM_YAML_DECLARE_MAPPING_TRAITS(modulesummary::FunctionSummary::Call)
6161
LLVM_YAML_DECLARE_MAPPING_TRAITS(modulesummary::FunctionSummary::TypeRef)
62+
LLVM_YAML_DECLARE_MAPPING_TRAITS(modulesummary::VFuncImpl)
6263
LLVM_YAML_IS_SEQUENCE_VECTOR(modulesummary::FunctionSummary::Call)
6364
LLVM_YAML_IS_SEQUENCE_VECTOR(modulesummary::FunctionSummary::TypeRef)
65+
LLVM_YAML_IS_SEQUENCE_VECTOR(modulesummary::VFuncImpl)
6466
LLVM_YAML_DECLARE_ENUM_TRAITS(modulesummary::FunctionSummary::Call::KindTy)
6567

6668
namespace llvm {
@@ -121,6 +123,11 @@ struct CustomMappingTraits<FunctionSummaryMapTy> {
121123
}
122124
};
123125

126+
void MappingTraits<VFuncImpl>::mapping(IO &io, VFuncImpl &V) {
127+
io.mapRequired("guid", V.Guid);
128+
io.mapRequired("type_guid", V.TypeGuid);
129+
}
130+
124131
template <>
125132
struct CustomMappingTraits<VFuncToImplsMapTy> {
126133
static void inputOne(IO &io, StringRef Key, VFuncToImplsMapTy &V) {

0 commit comments

Comments
 (0)