Skip to content

Commit e82360b

Browse files
Merge pull request #72447 from nate-chandler/cherrypick/release/6.0/noncopyable-bugs/20240314/1
6.0: [IRGen] Defer materializing metadata for outlining.
2 parents b70363e + 0030c51 commit e82360b

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)