Skip to content

Commit 0b58685

Browse files
authored
Merge pull request #63588 from nate-chandler/variadic-generics/irgen/wtable-forwarding
[IRGen] Forwarded wtable packs when possible.
2 parents 7059248 + f707f70 commit 0b58685

File tree

3 files changed

+96
-41
lines changed

3 files changed

+96
-41
lines changed

lib/IRGen/GenPack.cpp

Lines changed: 60 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,48 @@
3333
using namespace swift;
3434
using namespace irgen;
3535

36+
static CanPackArchetypeType
37+
getForwardedPackArchetypeType(CanPackType packType) {
38+
if (packType->getNumElements() != 1)
39+
return CanPackArchetypeType();
40+
auto uncastElement = packType.getElementType(0);
41+
auto element = dyn_cast<PackExpansionType>(uncastElement);
42+
if (!element)
43+
return CanPackArchetypeType();
44+
auto patternType = element.getPatternType();
45+
auto packArchetype = dyn_cast<PackArchetypeType>(patternType);
46+
return packArchetype;
47+
}
48+
49+
static MetadataResponse
50+
tryGetLocalPackTypeMetadata(IRGenFunction &IGF, CanPackType packType,
51+
DynamicMetadataRequest request) {
52+
if (auto result = IGF.tryGetLocalTypeMetadata(packType, request))
53+
return result;
54+
55+
if (auto packArchetypeType = getForwardedPackArchetypeType(packType)) {
56+
if (auto result = IGF.tryGetLocalTypeMetadata(packArchetypeType, request))
57+
return result;
58+
}
59+
60+
return MetadataResponse();
61+
}
62+
63+
static llvm::Value *tryGetLocalPackTypeData(IRGenFunction &IGF,
64+
CanPackType packType,
65+
LocalTypeDataKind localDataKind) {
66+
if (auto *wtable = IGF.tryGetLocalTypeData(packType, localDataKind))
67+
return wtable;
68+
69+
if (auto packArchetypeType = getForwardedPackArchetypeType(packType)) {
70+
if (auto *wtable =
71+
IGF.tryGetLocalTypeData(packArchetypeType, localDataKind))
72+
return wtable;
73+
}
74+
75+
return nullptr;
76+
}
77+
3678
static void accumulateSum(IRGenFunction &IGF, llvm::Value *&result,
3779
llvm::Value *value) {
3880
if (result == nullptr) {
@@ -324,33 +366,6 @@ irgen::emitTypeMetadataPack(IRGenFunction &IGF,
324366
return pack;
325367
}
326368

327-
static CanPackArchetypeType
328-
getForwardedPackArchetypeType(CanPackType packType) {
329-
if (packType->getNumElements() != 1)
330-
return CanPackArchetypeType();
331-
auto uncastElement = packType.getElementType(0);
332-
auto element = dyn_cast<PackExpansionType>(uncastElement);
333-
if (!element)
334-
return CanPackArchetypeType();
335-
auto patternType = element.getPatternType();
336-
auto packArchetype = dyn_cast<PackArchetypeType>(patternType);
337-
return packArchetype;
338-
}
339-
340-
static MetadataResponse
341-
tryGetLocalPackTypeMetadata(IRGenFunction &IGF, CanPackType packType,
342-
DynamicMetadataRequest request) {
343-
if (auto result = IGF.tryGetLocalTypeMetadata(packType, request))
344-
return result;
345-
346-
if (auto packArchetypeType = getForwardedPackArchetypeType(packType)) {
347-
if (auto result = IGF.tryGetLocalTypeMetadata(packArchetypeType, request))
348-
return result;
349-
}
350-
351-
return MetadataResponse();
352-
}
353-
354369
MetadataResponse
355370
irgen::emitTypeMetadataPackRef(IRGenFunction &IGF, CanPackType packType,
356371
DynamicMetadataRequest request) {
@@ -456,8 +471,6 @@ static llvm::Value *emitPackExpansionElementWitnessTable(
456471
->mapPackTypeIntoElementContext(patternTy->mapTypeOutOfContext())
457472
->getCanonicalType();
458473

459-
// FIXME: Handle witness table packs for associatedtype's conformances.
460-
461474
// Emit the element witness table.
462475
auto *wtable = emitWitnessTableRef(IGF, instantiatedPatternTy,
463476
/*srcMetadataCache=*/nullptr, conformance);
@@ -574,11 +587,16 @@ llvm::Value *irgen::emitWitnessTablePackRef(IRGenFunction &IGF,
574587
conformance->getProtocol()) &&
575588
"looking up witness table for protocol that doesn't have one");
576589

590+
if (auto *wtable = tryGetLocalPackTypeData(
591+
IGF, packType,
592+
LocalTypeDataKind::forAbstractProtocolWitnessTable(
593+
conformance->getProtocol())))
594+
return wtable;
595+
577596
auto localDataKind =
578597
LocalTypeDataKind::forProtocolWitnessTablePack(conformance);
579598

580-
auto wtable = IGF.tryGetLocalTypeData(packType, localDataKind);
581-
if (wtable)
599+
if (auto *wtable = tryGetLocalPackTypeData(IGF, packType, localDataKind))
582600
return wtable;
583601

584602
auto pack = emitWitnessTablePack(IGF, packType, conformance);
@@ -600,20 +618,26 @@ llvm::Value *irgen::emitTypeMetadataPackElementRef(
600618
tryGetLocalPackTypeMetadata(IGF, packType, request);
601619
llvm::SmallVector<llvm::Value *> materializedWtablePacks;
602620
for (auto protocol : protocols) {
603-
auto wtable = IGF.tryGetLocalTypeData(
604-
packType, LocalTypeDataKind::forAbstractProtocolWitnessTable(protocol));
605-
materializedWtablePacks.push_back(wtable);
621+
auto *wtablePack = tryGetLocalPackTypeData(
622+
IGF, packType,
623+
LocalTypeDataKind::forAbstractProtocolWitnessTable(protocol));
624+
materializedWtablePacks.push_back(wtablePack);
606625
}
607626
if (materializedMetadataPack &&
608627
llvm::all_of(materializedWtablePacks,
609-
[](auto *wtable) { return wtable; })) {
628+
[](auto *wtablePack) { return wtablePack; })) {
610629
auto *gep = IGF.Builder.CreateInBoundsGEP(
611630
IGF.IGM.TypeMetadataPtrTy, materializedMetadataPack.getMetadata(),
612631
index);
613632
auto addr =
614633
Address(gep, IGF.IGM.TypeMetadataPtrTy, IGF.IGM.getPointerAlignment());
615634
auto *metadata = IGF.Builder.CreateLoad(addr);
616-
for (auto *wtable : materializedWtablePacks) {
635+
for (auto *wtablePack : materializedWtablePacks) {
636+
auto *gep = IGF.Builder.CreateInBoundsGEP(IGF.IGM.WitnessTablePtrTy,
637+
wtablePack, index);
638+
auto addr = Address(gep, IGF.IGM.WitnessTablePtrTy,
639+
IGF.IGM.getPointerAlignment());
640+
auto *wtable = IGF.Builder.CreateLoad(addr);
617641
wtables.push_back(wtable);
618642
}
619643
return metadata;

test/IRGen/run_variadic_generics.sil

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,17 @@ entry(%intIndex : $Builtin.Word):
344344
return %t : $()
345345
}
346346

347+
// Verify that we just gep into parameter packs for metadata and witness tables when that's all that the pack consists of.
348+
// CHECK-LL-LABEL: define {{.*}}@direct_access_from_parameter_with_conformance(
349+
// CHECK-LL-SAME: i{{(32|64)}} [[INDEX:%[^,]+]],
350+
// CHECK-LL-SAME: i{{(32|64)}} {{%[^,]+}},
351+
// CHECK-LL-SAME: %swift.type** [[METADATA_PACK:%[^,]+]],
352+
// CHECK-LL-SAME: i8*** [[WTABLE_PACK:%[^,]+]])
353+
// CHECK-LL: [[METADATA_ADDRESS:%[^,]+]] = getelementptr inbounds %swift.type*, %swift.type** [[METADATA_PACK]], i{{(32|64)}} [[INDEX]]
354+
// CHECK-LL: [[METADATA:%[^,]+]] = load %swift.type*, %swift.type** [[METADATA_ADDRESS]]
355+
// CHECK-LL: [[WTABLE_ADDRESS:%[^,]+]] = getelementptr inbounds i8**, i8*** [[WTABLE_PACK]], i{{(32|64)}} [[INDEX]]
356+
// CHECK-LL: [[WTABLE:%[^,]+]] = load i8**, i8*** [[WTABLE_ADDRESS]], align 8
357+
// CHECK-LL: call swiftcc void @printGenericType(%swift.type* [[METADATA]], %swift.type* [[METADATA]])
347358
sil @direct_access_from_parameter_with_conformance : $<T_1... : P> (Builtin.Word) -> () {
348359
entry(%intIndex : $Builtin.Word):
349360
%innerIndex = dynamic_pack_index %intIndex of $Pack{repeat each T_1}

test/IRGen/variadic_generic_functions.sil

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,16 +32,36 @@ sil @c : $() -> () {
3232
return %ret : $()
3333
}
3434

35-
// CHECK: define {{.*}}void @f(i{{(64|32)}} %0, %swift.type** %T, i8*** %T.P)
35+
// CHECK: define {{.*}}void @g(i{{(64|32)}} %0, %swift.type** %T, i8*** %T.P)
36+
sil @g : $<T... : P> () -> () {
37+
%f = function_ref @f : $@convention(thin) <T... : P> () -> ()
38+
apply %f<Pack{repeat each T, S, repeat each T, repeat each T}>() : $@convention(thin) <T... : P> () -> ()
39+
%ret = tuple ()
40+
return %ret : $()
41+
}
42+
43+
// Verify that polymorphic parameters are just forwarded along.
44+
// CHECK-LABEL: define {{.*}}void @f(i{{(32|64)}} %0, %swift.type** %T, i8*** %T.P)
45+
// CHECK: call swiftcc void @fc(i{{(32|64)}} %0, %swift.type** %T, i8*** %T.P)
3646
sil @f : $<T... : P> () -> () {
47+
%fc = function_ref @fc : $@convention(thin) <T... : P> () -> ()
48+
apply %fc<Pack{repeat each T}>() : $@convention(thin) <T... : P> () -> ()
3749
%ret = tuple ()
3850
return %ret : $()
3951
}
52+
sil @fc : $<T... : P> () -> () {}
4053

41-
// CHECK: define {{.*}}void @g(i{{(64|32)}} %0, %swift.type** %T, i8*** %T.P)
42-
sil @g : $<T... : P> () -> () {
43-
%f = function_ref @f : $@convention(thin) <T... : P> () -> ()
44-
apply %f<Pack{repeat each T, S, repeat each T, repeat each T}>() : $@convention(thin) <T... : P> () -> ()
54+
protocol PA {
55+
associatedtype A
56+
}
57+
58+
// CHECK-LABEL: define {{.*}}@f1(i{{(32|64)}} %0, %swift.type** %T, i8*** %T.PA, i8*** %T.A.P)
59+
// CHECK: call swiftcc void @f1c(i{{(32|64)}} %0, %swift.type** %T, i8*** %T.PA, i8*** %T.A.P)
60+
sil @f1 : $<T... : PA where each T.A : P> () -> () {
61+
%f1c = function_ref @f1c : $@convention(thin) <T... : PA where each T.A : P> () -> ()
62+
apply %f1c<Pack{repeat each T}>() : $@convention(thin) <T... : PA where each T.A : P> () -> ()
4563
%ret = tuple ()
4664
return %ret : $()
4765
}
66+
67+
sil @f1c : $<T... : PA where each T.A : P> () -> () {}

0 commit comments

Comments
 (0)