Skip to content

Commit 9224936

Browse files
authored
Merge pull request #65257 from slavapestov/extended-existential-metadata
IRGen: Try harder not to emit calls to swift_getExtendedExistentialTypeMetadata()
2 parents 31361f8 + 563ebde commit 9224936

File tree

7 files changed

+62
-99
lines changed

7 files changed

+62
-99
lines changed

include/swift/SIL/SILType.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -419,6 +419,12 @@ class SILType {
419419
bool hasLocalArchetype() const {
420420
return getASTType()->hasLocalArchetype();
421421
}
422+
423+
/// Returns true if the referenced type is expressed in terms of one
424+
/// or more parameterized protocol types.
425+
bool hasParameterizedExistential() const {
426+
return getASTType()->hasParameterizedExistential();
427+
}
422428

423429
/// Returns the representation used by an existential type. If the concrete
424430
/// type is provided, this may return a specialized representation kind that

lib/IRGen/GenEnum.cpp

Lines changed: 16 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -279,62 +279,6 @@ EnumImplStrategy::emitResilientTagIndices(IRGenModule &IGM) const {
279279
}
280280
}
281281

282-
void EnumImplStrategy::callOutlinedCopy(IRGenFunction &IGF,
283-
Address dest, Address src, SILType T,
284-
IsInitialization_t isInit,
285-
IsTake_t isTake) const {
286-
if (!IGF.IGM.getOptions().UseTypeLayoutValueHandling) {
287-
OutliningMetadataCollector collector(IGF);
288-
if (T.hasArchetype()) {
289-
collectMetadataForOutlining(collector, T);
290-
}
291-
collector.emitCallToOutlinedCopy(dest, src, T, *TI, isInit, isTake);
292-
return;
293-
}
294-
295-
if (!T.hasArchetype()) {
296-
// Call the outlined copy function (the implementation will call vwt in this
297-
// case).
298-
OutliningMetadataCollector collector(IGF);
299-
collector.emitCallToOutlinedCopy(dest, src, T, *TI, isInit, isTake);
300-
return;
301-
}
302-
303-
if (isInit == IsInitialization && isTake == IsTake) {
304-
return emitInitializeWithTakeCall(IGF, T, dest, src);
305-
} else if (isInit == IsInitialization && isTake == IsNotTake) {
306-
return emitInitializeWithCopyCall(IGF, T, dest, src);
307-
} else if (isInit == IsNotInitialization && isTake == IsTake) {
308-
return emitAssignWithTakeCall(IGF, T, dest, src);
309-
} else if (isInit == IsNotInitialization && isTake == IsNotTake) {
310-
return emitAssignWithCopyCall(IGF, T, dest, src);
311-
}
312-
llvm_unreachable("unknown case");
313-
}
314-
315-
void EnumImplStrategy::callOutlinedDestroy(IRGenFunction &IGF,
316-
Address addr, SILType T) const {
317-
if (!IGF.IGM.getOptions().UseTypeLayoutValueHandling) {
318-
OutliningMetadataCollector collector(IGF);
319-
if (T.hasArchetype()) {
320-
collectMetadataForOutlining(collector, T);
321-
}
322-
collector.emitCallToOutlinedDestroy(addr, T, *TI);
323-
return;
324-
}
325-
326-
if (!T.hasArchetype()) {
327-
// Call the outlined copy function (the implementation will call vwt in this
328-
// case).
329-
OutliningMetadataCollector collector(IGF);
330-
collector.emitCallToOutlinedDestroy(addr, T, *TI);
331-
return;
332-
}
333-
334-
emitDestroyCall(IGF, T, addr);
335-
return;
336-
}
337-
338282
namespace {
339283
/// Implementation strategy for singleton enums, with zero or one cases.
340284
class SingletonEnumImplStrategy final : public EnumImplStrategy {
@@ -549,7 +493,7 @@ namespace {
549493
if (!getSingleton()) return;
550494
if (!ElementsAreABIAccessible) {
551495
emitAssignWithCopyCall(IGF, T, dest, src);
552-
} else if (isOutlined || T.hasLocalArchetype()) {
496+
} else if (isOutlined || T.hasParameterizedExistential()) {
553497
dest = getSingletonAddress(IGF, dest);
554498
src = getSingletonAddress(IGF, src);
555499
getSingleton()->assignWithCopy(
@@ -564,7 +508,7 @@ namespace {
564508
if (!getSingleton()) return;
565509
if (!ElementsAreABIAccessible) {
566510
emitAssignWithTakeCall(IGF, T, dest, src);
567-
} else if (isOutlined || T.hasLocalArchetype()) {
511+
} else if (isOutlined || T.hasParameterizedExistential()) {
568512
dest = getSingletonAddress(IGF, dest);
569513
src = getSingletonAddress(IGF, src);
570514
getSingleton()->assignWithTake(
@@ -586,7 +530,7 @@ namespace {
586530
if (!getSingleton()) return;
587531
if (!ElementsAreABIAccessible) {
588532
emitInitializeWithCopyCall(IGF, T, dest, src);
589-
} else if (isOutlined || T.hasLocalArchetype()) {
533+
} else if (isOutlined || T.hasParameterizedExistential()) {
590534
dest = getSingletonAddress(IGF, dest);
591535
src = getSingletonAddress(IGF, src);
592536
getSingleton()->initializeWithCopy(
@@ -601,7 +545,7 @@ namespace {
601545
if (!getSingleton()) return;
602546
if (!ElementsAreABIAccessible) {
603547
emitInitializeWithTakeCall(IGF, T, dest, src);
604-
} else if (isOutlined || T.hasLocalArchetype()) {
548+
} else if (isOutlined || T.hasParameterizedExistential()) {
605549
dest = getSingletonAddress(IGF, dest);
606550
src = getSingletonAddress(IGF, src);
607551
getSingleton()->initializeWithTake(
@@ -657,7 +601,7 @@ namespace {
657601
!getSingleton()->isTriviallyDestroyable(ResilienceExpansion::Maximal)) {
658602
if (!ElementsAreABIAccessible) {
659603
emitDestroyCall(IGF, T, addr);
660-
} else if (isOutlined || T.hasLocalArchetype()) {
604+
} else if (isOutlined || T.hasParameterizedExistential()) {
661605
getSingleton()->destroy(IGF, getSingletonAddress(IGF, addr),
662606
getSingletonType(IGF.IGM, T), isOutlined);
663607
} else {
@@ -2810,7 +2754,7 @@ namespace {
28102754
}
28112755
if (!ElementsAreABIAccessible) {
28122756
return emitDestroyCall(IGF, T, addr);
2813-
} else if (isOutlined || T.hasLocalArchetype()) {
2757+
} else if (isOutlined || T.hasParameterizedExistential()) {
28142758
switch (CopyDestroyKind) {
28152759
case TriviallyDestroyable:
28162760
return;
@@ -2854,24 +2798,7 @@ namespace {
28542798
}
28552799
}
28562800
} else {
2857-
if (!IGF.IGM.getOptions().UseTypeLayoutValueHandling) {
2858-
OutliningMetadataCollector collector(IGF);
2859-
if (T.hasArchetype()) {
2860-
collectMetadataForOutlining(collector, T);
2861-
}
2862-
collector.emitCallToOutlinedDestroy(addr, T, *TI);
2863-
return;
2864-
}
2865-
2866-
if (!T.hasArchetype()) {
2867-
// Call the outlined copy function (the implementation will call vwt
2868-
// in this case).
2869-
OutliningMetadataCollector collector(IGF);
2870-
collector.emitCallToOutlinedDestroy(addr, T, *TI);
2871-
return;
2872-
}
2873-
2874-
emitDestroyCall(IGF, T, addr);
2801+
callOutlinedDestroy(IGF, addr, T);
28752802
return;
28762803
}
28772804
}
@@ -3114,7 +3041,7 @@ namespace {
31143041
SILType T, bool isOutlined) const override {
31153042
if (!ElementsAreABIAccessible) {
31163043
emitAssignWithCopyCall(IGF, T, dest, src);
3117-
} else if (isOutlined || T.hasLocalArchetype()) {
3044+
} else if (isOutlined || T.hasParameterizedExistential()) {
31183045
emitIndirectAssign(IGF, dest, src, T, IsNotTake, isOutlined);
31193046
} else {
31203047
callOutlinedCopy(IGF, dest, src, T, IsNotInitialization, IsNotTake);
@@ -3125,7 +3052,7 @@ namespace {
31253052
SILType T, bool isOutlined) const override {
31263053
if (!ElementsAreABIAccessible) {
31273054
emitAssignWithTakeCall(IGF, T, dest, src);
3128-
} else if (isOutlined || T.hasLocalArchetype()) {
3055+
} else if (isOutlined || T.hasParameterizedExistential()) {
31293056
emitIndirectAssign(IGF, dest, src, T, IsTake, isOutlined);
31303057
} else {
31313058
callOutlinedCopy(IGF, dest, src, T, IsNotInitialization, IsTake);
@@ -3136,7 +3063,7 @@ namespace {
31363063
SILType T, bool isOutlined) const override {
31373064
if (!ElementsAreABIAccessible) {
31383065
emitInitializeWithCopyCall(IGF, T, dest, src);
3139-
} else if (isOutlined || T.hasLocalArchetype()) {
3066+
} else if (isOutlined || T.hasParameterizedExistential()) {
31403067
emitIndirectInitialize(IGF, dest, src, T, IsNotTake, isOutlined);
31413068
} else {
31423069
callOutlinedCopy(IGF, dest, src, T, IsInitialization, IsNotTake);
@@ -3147,7 +3074,7 @@ namespace {
31473074
SILType T, bool isOutlined) const override {
31483075
if (!ElementsAreABIAccessible) {
31493076
emitInitializeWithTakeCall(IGF, T, dest, src);
3150-
} else if (isOutlined || T.hasLocalArchetype()) {
3077+
} else if (isOutlined || T.hasParameterizedExistential()) {
31513078
emitIndirectInitialize(IGF, dest, src, T, IsTake, isOutlined);
31523079
} else {
31533080
callOutlinedCopy(IGF, dest, src, T, IsInitialization, IsTake);
@@ -4972,7 +4899,7 @@ namespace {
49724899
SILType T, bool isOutlined) const override {
49734900
if (!ElementsAreABIAccessible) {
49744901
emitAssignWithCopyCall(IGF, T, dest, src);
4975-
} else if (isOutlined || T.hasLocalArchetype()) {
4902+
} else if (isOutlined || T.hasParameterizedExistential()) {
49764903
emitIndirectAssign(IGF, dest, src, T, IsNotTake, isOutlined);
49774904
} else {
49784905
callOutlinedCopy(IGF, dest, src, T, IsNotInitialization, IsNotTake);
@@ -4983,7 +4910,7 @@ namespace {
49834910
SILType T, bool isOutlined) const override {
49844911
if (!ElementsAreABIAccessible) {
49854912
emitAssignWithTakeCall(IGF, T, dest, src);
4986-
} else if (isOutlined || T.hasLocalArchetype()) {
4913+
} else if (isOutlined || T.hasParameterizedExistential()) {
49874914
emitIndirectAssign(IGF, dest, src, T, IsTake, isOutlined);
49884915
} else {
49894916
callOutlinedCopy(IGF, dest, src, T, IsNotInitialization, IsTake);
@@ -4994,7 +4921,7 @@ namespace {
49944921
SILType T, bool isOutlined) const override {
49954922
if (!ElementsAreABIAccessible) {
49964923
emitInitializeWithCopyCall(IGF, T, dest, src);
4997-
} else if (isOutlined || T.hasLocalArchetype()) {
4924+
} else if (isOutlined || T.hasParameterizedExistential()) {
49984925
emitIndirectInitialize(IGF, dest, src, T, IsNotTake, isOutlined);
49994926
} else {
50004927
callOutlinedCopy(IGF, dest, src, T, IsInitialization, IsNotTake);
@@ -5005,7 +4932,7 @@ namespace {
50054932
SILType T, bool isOutlined) const override {
50064933
if (!ElementsAreABIAccessible) {
50074934
emitInitializeWithTakeCall(IGF, T, dest, src);
5008-
} else if (isOutlined || T.hasLocalArchetype()) {
4935+
} else if (isOutlined || T.hasParameterizedExistential()) {
50094936
emitIndirectInitialize(IGF, dest, src, T, IsTake, isOutlined);
50104937
} else {
50114938
callOutlinedCopy(IGF, dest, src, T, IsInitialization, IsTake);
@@ -5039,7 +4966,7 @@ namespace {
50394966
}
50404967
if (!ElementsAreABIAccessible) {
50414968
emitDestroyCall(IGF, T, addr);
5042-
} else if (isOutlined || T.hasLocalArchetype()) {
4969+
} else if (isOutlined || T.hasParameterizedExistential()) {
50434970
switch (CopyDestroyKind) {
50444971
case TriviallyDestroyable:
50454972
return;

lib/IRGen/GenEnum.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -449,9 +449,13 @@ class EnumImplStrategy {
449449

450450
void callOutlinedCopy(IRGenFunction &IGF, Address dest, Address src,
451451
SILType T, IsInitialization_t isInit,
452-
IsTake_t isTake) const;
452+
IsTake_t isTake) const {
453+
TI->callOutlinedCopy(IGF, dest, src, T, isInit, isTake);
454+
}
453455

454-
void callOutlinedDestroy(IRGenFunction &IGF, Address addr, SILType T) const;
456+
void callOutlinedDestroy(IRGenFunction &IGF, Address addr, SILType T) const {
457+
TI->callOutlinedDestroy(IGF, addr, T);
458+
}
455459

456460
virtual void collectMetadataForOutlining(OutliningMetadataCollector &collector,
457461
SILType T) const = 0;

lib/IRGen/GenRecord.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ class RecordTypeInfoImpl : public Base,
172172
return emitAssignWithCopyCall(IGF, T, dest, src);
173173
}
174174

175-
if (isOutlined || T.hasLocalArchetype()) {
175+
if (isOutlined || T.hasParameterizedExistential()) {
176176
auto offsets = asImpl().getNonFixedOffsets(IGF, T);
177177
for (auto &field : getFields()) {
178178
if (field.isEmpty())
@@ -195,7 +195,7 @@ class RecordTypeInfoImpl : public Base,
195195
return emitAssignWithTakeCall(IGF, T, dest, src);
196196
}
197197

198-
if (isOutlined || T.hasLocalArchetype()) {
198+
if (isOutlined || T.hasParameterizedExistential()) {
199199
auto offsets = asImpl().getNonFixedOffsets(IGF, T);
200200
for (auto &field : getFields()) {
201201
if (field.isEmpty())
@@ -225,7 +225,7 @@ class RecordTypeInfoImpl : public Base,
225225
return emitInitializeWithCopyCall(IGF, T, dest, src);
226226
}
227227

228-
if (isOutlined || T.hasLocalArchetype()) {
228+
if (isOutlined || T.hasParameterizedExistential()) {
229229
auto offsets = asImpl().getNonFixedOffsets(IGF, T);
230230
for (auto &field : getFields()) {
231231
if (field.isEmpty())
@@ -257,7 +257,7 @@ class RecordTypeInfoImpl : public Base,
257257
return emitInitializeWithTakeCall(IGF, T, dest, src);
258258
}
259259

260-
if (isOutlined || T.hasLocalArchetype()) {
260+
if (isOutlined || T.hasParameterizedExistential()) {
261261
auto offsets = asImpl().getNonFixedOffsets(IGF, T);
262262
for (auto &field : getFields()) {
263263
if (field.isEmpty())
@@ -280,7 +280,7 @@ class RecordTypeInfoImpl : public Base,
280280
return emitDestroyCall(IGF, T, addr);
281281
}
282282

283-
if (isOutlined || T.hasLocalArchetype()) {
283+
if (isOutlined || T.hasParameterizedExistential()) {
284284
auto offsets = asImpl().getNonFixedOffsets(IGF, T);
285285
for (auto &field : getFields()) {
286286
if (field.isTriviallyDestroyable())

lib/IRGen/Outlining.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,8 @@ irgen::getTypeAndGenericSignatureForManglingOutlineFunction(SILType type) {
138138
void TypeInfo::callOutlinedCopy(IRGenFunction &IGF, Address dest, Address src,
139139
SILType T, IsInitialization_t isInit,
140140
IsTake_t isTake) const {
141-
if (!IGF.IGM.getOptions().UseTypeLayoutValueHandling) {
141+
if (!T.hasLocalArchetype() &&
142+
!IGF.IGM.getOptions().UseTypeLayoutValueHandling) {
142143
OutliningMetadataCollector collector(IGF);
143144
if (T.hasArchetype()) {
144145
collectMetadataForOutlining(collector, T);
@@ -340,7 +341,8 @@ void TypeInfo::callOutlinedDestroy(IRGenFunction &IGF,
340341
if (IGF.IGM.getTypeLowering(T).isTrivial())
341342
return;
342343

343-
if (!IGF.IGM.getOptions().UseTypeLayoutValueHandling) {
344+
if (!T.hasLocalArchetype() &&
345+
!IGF.IGM.getOptions().UseTypeLayoutValueHandling) {
344346
OutliningMetadataCollector collector(IGF);
345347
if (T.hasArchetype()) {
346348
collectMetadataForOutlining(collector, T);
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// RUN: %target-swift-frontend -emit-ir %s | %FileCheck %s
2+
// RUN: %target-swift-frontend -emit-ir -O %s | %FileCheck %s
3+
4+
protocol Foo<T> {
5+
associatedtype T
6+
func acceptEvent<T>(event: T)
7+
}
8+
9+
protocol FooFactory<T> {
10+
associatedtype T
11+
func makeFoo() -> any Foo<T>
12+
}
13+
14+
class Bar<T> {
15+
private var foo: (any Foo<T>)
16+
17+
init(fooFactory: any FooFactory<T>) {
18+
self.foo = fooFactory.makeFoo()
19+
}
20+
}
21+
22+
// CHECK-NOT: swift_getExtendedExistentialTypeMetadata

test/IRGen/variadic_generic_outlining.sil

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,10 @@ struct Wrapper<Value> {
1616
// CHECK-NEXT: [[PACK:%.*]] = inttoptr [[INT]] [[PACK_ADDR2]] to %swift.type**
1717
// CHECK-NEXT: [[T0:%.*]] = getelementptr inbounds %swift.type*, %swift.type** [[PACK]], [[INT]]
1818
// CHECK-NEXT: [[ELT_TYPE:%.*]] = load %swift.type*, %swift.type** [[T0]], align
19+
// CHECK: [[WRAPPER_RESPONSE:%.*]] = call swiftcc %swift.metadata_response @"$s26variadic_generic_outlining7WrapperVMa"
20+
// CHECK-NEXT: [[WRAPPER_TYPE:%.*]] = extractvalue %swift.metadata_response [[WRAPPER_RESPONSE]]
1921
// Test that we do the copy through the VWT for the element type.
20-
// CHECK: [[T0:%.*]] = bitcast %swift.type* [[ELT_TYPE]] to i8***
22+
// CHECK-NEXT: [[T0:%.*]] = bitcast %swift.type* [[WRAPPER_TYPE]] to i8***
2123
// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds i8**, i8*** [[T0]], [[INT]] -1
2224
sil hidden @test_outlining : $@convention(thin) <each T> (@pack_guaranteed Pack{repeat Wrapper<each T>}) -> @pack_out Pack{repeat Wrapper<each T>} {
2325
bb0(%0 : $*Pack{repeat Wrapper<each T>}, %1 : $*Pack{repeat Wrapper<each T>}):

0 commit comments

Comments
 (0)