Skip to content

Commit 0030c51

Browse files
committed
[IRGen] Defer materializing metadata for outlining
Rather than materializing the metadata on demand during visitation, only collect the types that may be required. Finally, materialize everything that's needed at the end. rdar://125048059
1 parent 555278e commit 0030c51

File tree

4 files changed

+354
-66
lines changed

4 files changed

+354
-66
lines changed

lib/IRGen/GenEnum.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1861,6 +1861,7 @@ namespace {
18611861
DeinitIsNeeded);
18621862
IGF.getTypeInfo(theEnumType)
18631863
.collectMetadataForOutlining(collector, theEnumType);
1864+
collector.materialize();
18641865
if (!consumeEnumFunction)
18651866
consumeEnumFunction =
18661867
emitConsumeEnumFunction(IGF.IGM, theEnumType, collector);
@@ -4870,6 +4871,7 @@ namespace {
48704871
OutliningMetadataCollector collector(T, IGF, LayoutIsNotNeeded,
48714872
DeinitIsNeeded);
48724873
IGF.getTypeInfo(T).collectMetadataForOutlining(collector, T);
4874+
collector.materialize();
48734875
if (!consumeEnumFunction)
48744876
consumeEnumFunction = emitConsumeEnumFunction(IGM, T, collector);
48754877
Explosion tmp;

lib/IRGen/Outlining.cpp

Lines changed: 115 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ OutliningMetadataCollector::OutliningMetadataCollector(
5959
: T(T), IGF(IGF), needsLayout(needsLayout), needsDeinit(needsDeinitTypes) {}
6060

6161
void OutliningMetadataCollector::collectTypeMetadata(SILType ty) {
62+
assert(state != OutliningMetadataCollector::State::Kind::Collected);
6263
// If the type has no archetypes, we can emit it from scratch in the callee.
6364
if (!ty.hasArchetype()) {
6465
return;
@@ -89,10 +90,10 @@ void OutliningMetadataCollector::collectTypeMetadataForLayout(SILType ty) {
8990
// FIXME: does this force us to emit a more expensive metadata than we need
9091
// to?
9192
if (astType->isLegalFormalType()) {
92-
return collectFormalTypeMetadata(astType);
93+
return state.getCollecting().addFormalTypeMetadata(astType);
9394
}
9495

95-
collectRepresentationTypeMetadata(ty);
96+
state.getCollecting().addRepresentationTypeMetadata(ty);
9697
}
9798

9899
void OutliningMetadataCollector::collectTypeMetadataForDeinit(SILType ty) {
@@ -106,92 +107,155 @@ void OutliningMetadataCollector::collectTypeMetadataForDeinit(SILType ty) {
106107
return;
107108
assert(ty.isMoveOnly());
108109

109-
if (Requirements.size())
110-
return;
111-
112-
auto pair = getTypeAndGenericSignatureForManglingOutlineFunction(T);
113-
auto sig = pair.second;
114-
auto subs =
115-
digOutGenericEnvironment(T.getASTType())->getForwardingSubstitutionMap();
116-
Subs = subs;
117-
GenericTypeRequirements requirements(IGF.IGM, sig);
118-
for (auto requirement : requirements.getRequirements()) {
119-
auto *value = emitGenericRequirementFromSubstitutions(
120-
IGF, requirement, MetadataState::Complete, subs);
121-
Requirements.insert({requirement, value});
122-
}
110+
state.getCollecting().addValueTypeWithDeinit(ty);
123111
}
124112

125-
void OutliningMetadataCollector::collectFormalTypeMetadata(CanType ty) {
113+
void OutliningMetadataCollector::materializeFormalTypeMetadata(
114+
CanType ty, State::Collected::Elements &into) {
126115
// If the type has no archetypes, we can emit it from scratch in the callee.
127116
assert(ty->hasArchetype());
128117

129118
auto key = LocalTypeDataKey(ty, LocalTypeDataKind::forFormalTypeMetadata());
130-
if (Values.count(key)) return;
119+
if (into.Values.count(key))
120+
return;
131121

132122
auto metadata = IGF.emitTypeMetadataRef(ty);
133-
Values.insert({key, metadata});
123+
into.Values.insert({key, metadata});
124+
125+
assert(into.Values.count(key));
134126
}
135127

136-
void OutliningMetadataCollector::collectRepresentationTypeMetadata(SILType ty) {
128+
void OutliningMetadataCollector::materializeRepresentationTypeMetadata(
129+
SILType ty, State::Collected::Elements &into) {
137130
auto key = LocalTypeDataKey(
138131
ty.getASTType(), LocalTypeDataKind::forRepresentationTypeMetadata());
139-
if (Values.count(key))
132+
if (into.Values.count(key))
140133
return;
141134

142135
auto metadata = IGF.emitTypeMetadataRefForLayout(ty);
143-
Values.insert({key, metadata});
136+
into.Values.insert({key, metadata});
137+
}
138+
139+
void OutliningMetadataCollector::materialize() {
140+
if (state == State::Kind::Collected)
141+
return;
142+
143+
auto collection = std::move(state.getCollecting());
144+
switch (collection) {
145+
case State::CollectionKind::Elements: {
146+
auto &elements = collection.getElements();
147+
auto &collected = state.setCollectedElements();
148+
for (auto &element : elements.elements) {
149+
switch (element) {
150+
case State::ElementKind::MetadataForFormal: {
151+
auto ty = element.getFormalType();
152+
materializeFormalTypeMetadata(ty, /*into=*/collected);
153+
break;
154+
}
155+
case State::ElementKind::MetadataForRepresentation: {
156+
auto ty = element.getRepresentationType();
157+
materializeRepresentationTypeMetadata(ty, /*into=*/collected);
158+
break;
159+
}
160+
}
161+
}
162+
return;
163+
}
164+
case State::CollectionKind::Environment: {
165+
auto pair = getTypeAndGenericSignatureForManglingOutlineFunction(T);
166+
auto sig = pair.second;
167+
auto subs = digOutGenericEnvironment(T.getASTType())
168+
->getForwardingSubstitutionMap();
169+
auto &collected = state.setCollectedEnvironment(subs);
170+
171+
GenericTypeRequirements requirements(IGF.IGM, sig);
172+
for (auto requirement : requirements.getRequirements()) {
173+
auto *value = emitGenericRequirementFromSubstitutions(
174+
IGF, requirement, MetadataState::Complete, subs);
175+
collected.Requirements.insert({requirement, value});
176+
}
177+
return;
178+
}
179+
}
144180
}
145181

146182
void OutliningMetadataCollector::addPolymorphicArguments(
147183
SmallVectorImpl<llvm::Value *> &args) const {
148-
if (Subs) {
149-
for (auto &pair : Requirements) {
184+
assert(hasFinished());
185+
if (state == State::Kind::Empty)
186+
return;
187+
auto &collected = state.getCollected();
188+
switch (collected) {
189+
case State::CollectionKind::Elements: {
190+
for (auto &pair : collected.getElements().Values) {
191+
auto metadata = pair.second;
192+
assert(metadata->getType() == IGF.IGM.TypeMetadataPtrTy);
193+
args.push_back(metadata);
194+
}
195+
return;
196+
}
197+
case State::CollectionKind::Environment: {
198+
for (auto &pair : collected.getEnvironment().Requirements) {
150199
auto *value = pair.second;
151200
args.push_back(value);
152201
}
153202
return;
154203
}
155-
for (auto &pair : Values) {
156-
auto metadata = pair.second;
157-
assert(metadata->getType() == IGF.IGM.TypeMetadataPtrTy);
158-
args.push_back(metadata);
159204
}
160205
}
161206

162207
void OutliningMetadataCollector::addPolymorphicParameterTypes(
163208
SmallVectorImpl<llvm::Type *> &paramTys) const {
164-
if (Subs) {
165-
for (auto &pair : Requirements) {
209+
assert(hasFinished());
210+
if (state == State::Kind::Empty)
211+
return;
212+
auto &collected = state.getCollected();
213+
switch (collected) {
214+
case State::CollectionKind::Elements: {
215+
for (auto &pair : collected.getElements().Values) {
216+
auto *metadata = pair.second;
217+
paramTys.push_back(metadata->getType());
218+
}
219+
return;
220+
}
221+
case State::CollectionKind::Environment: {
222+
for (auto &pair : collected.getEnvironment().Requirements) {
166223
auto *value = pair.second;
167224
paramTys.push_back(value->getType());
168225
}
169226
return;
170227
}
171-
for (auto &pair : Values) {
172-
auto *metadata = pair.second;
173-
paramTys.push_back(metadata->getType());
174228
}
175229
}
176230

177231
void OutliningMetadataCollector::bindPolymorphicParameters(
178232
IRGenFunction &IGF, Explosion &params) const {
179-
if (Subs) {
180-
for (auto &pair : Requirements) {
233+
assert(hasFinished());
234+
if (state == State::Kind::Empty)
235+
return;
236+
auto &collected = state.getCollected();
237+
switch (collected) {
238+
case State::CollectionKind::Elements: {
239+
// Note that our parameter IGF intentionally shadows the IGF that this
240+
// collector was built with.
241+
for (auto &pair : collected.getElements().Values) {
242+
llvm::Value *arg = params.claimNext();
243+
244+
auto key = pair.first;
245+
assert(key.Kind.isAnyTypeMetadata());
246+
setTypeMetadataName(IGF.IGM, arg, key.Type);
247+
IGF.setUnscopedLocalTypeData(key, MetadataResponse::forComplete(arg));
248+
}
249+
return;
250+
}
251+
case State::CollectionKind::Environment: {
252+
auto &environment = collected.getEnvironment();
253+
for (auto &pair : environment.Requirements) {
181254
bindGenericRequirement(IGF, pair.first, params.claimNext(),
182-
MetadataState::Complete, *Subs);
255+
MetadataState::Complete, environment.Subs);
183256
}
184257
return;
185258
}
186-
// Note that our parameter IGF intentionally shadows the IGF that this
187-
// collector was built with.
188-
for (auto &pair : Values) {
189-
llvm::Value *arg = params.claimNext();
190-
191-
auto key = pair.first;
192-
assert(key.Kind.isAnyTypeMetadata());
193-
setTypeMetadataName(IGF.IGM, arg, key.Type);
194-
IGF.setUnscopedLocalTypeData(key, MetadataResponse::forComplete(arg));
195259
}
196260
}
197261

@@ -231,6 +295,7 @@ bool TypeInfo::withWitnessableMetadataCollector(
231295
// Only collect if anything would be collected.
232296
collectMetadataForOutlining(collector, T);
233297
}
298+
collector.materialize();
234299
invocation(collector);
235300
return true;
236301
}
@@ -264,6 +329,7 @@ void TypeInfo::callOutlinedCopy(IRGenFunction &IGF, Address dest, Address src,
264329
void OutliningMetadataCollector::emitCallToOutlinedCopy(
265330
Address dest, Address src, SILType T, const TypeInfo &ti,
266331
IsInitialization_t isInit, IsTake_t isTake) const {
332+
assert(hasFinished());
267333
assert(!needsDeinit);
268334
llvm::SmallVector<llvm::Value *, 4> args;
269335
args.push_back(IGF.Builder.CreateElementBitCast(src, ti.getStorageType())
@@ -411,6 +477,7 @@ llvm::Constant *IRGenModule::getOrCreateOutlinedCopyAddrHelperFunction(
411477
const OutliningMetadataCollector &collector,
412478
StringRef funcName,
413479
CopyAddrHelperGenerator generator) {
480+
assert(collector.hasFinished());
414481
auto ptrTy = ti.getStorageType()->getPointerTo();
415482

416483
llvm::SmallVector<llvm::Type *, 4> paramTys;
@@ -450,6 +517,7 @@ void TypeInfo::callOutlinedDestroy(IRGenFunction &IGF,
450517

451518
void OutliningMetadataCollector::emitCallToOutlinedDestroy(
452519
Address addr, SILType T, const TypeInfo &ti) const {
520+
assert(hasFinished());
453521
assert(needsDeinit);
454522
llvm::SmallVector<llvm::Value *, 4> args;
455523
args.push_back(IGF.Builder.CreateElementBitCast(addr, ti.getStorageType())
@@ -528,11 +596,13 @@ void TypeInfo::callOutlinedRelease(IRGenFunction &IGF, Address addr, SILType T,
528596
OutliningMetadataCollector collector(T, IGF, LayoutIsNotNeeded,
529597
DeinitIsNeeded);
530598
collectMetadataForOutlining(collector, T);
599+
collector.materialize();
531600
collector.emitCallToOutlinedRelease(addr, T, *this, atomicity);
532601
}
533602

534603
void OutliningMetadataCollector::emitCallToOutlinedRelease(
535604
Address addr, SILType T, const TypeInfo &ti, Atomicity atomicity) const {
605+
assert(hasFinished());
536606
assert(!needsLayout);
537607
assert(needsDeinit);
538608
llvm::SmallVector<llvm::Value *, 4> args;

0 commit comments

Comments
 (0)