Skip to content

Commit 0e817b4

Browse files
committed
[IRGen] Narrow the “requires instantiation” bit for conformances.
The “requires instantiation” bit for protocol conformances that might require runtime instantiation was set for essentially every resilient conformance, so we would always be forced to create a copy of the table. Narrow the “requires instantiation” bit to those cases where there is something in the pattern that needs it to be copied (for now, only associated type witnesses involving a type parameter, which need to be cached differently). This optimizes some narrow cases where we wouldn’t otherwise need a copy.
1 parent ebb0d27 commit 0e817b4

File tree

6 files changed

+53
-22
lines changed

6 files changed

+53
-22
lines changed

lib/IRGen/GenProto.cpp

Lines changed: 29 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -961,6 +961,31 @@ static bool isResilientConformance(const NormalProtocolConformance *conformance)
961961
return true;
962962
}
963963

964+
/// Whether this protocol conformance has a dependent type witness.
965+
static bool hasDependentTypeWitness(
966+
const NormalProtocolConformance *conformance) {
967+
auto DC = conformance->getDeclContext();
968+
// If the conforming type isn't dependent, the below check is never true.
969+
if (!DC->isGenericContext())
970+
return false;
971+
972+
// Check whether any of the associated types are dependent.
973+
if (conformance->forEachTypeWitness(nullptr,
974+
[&](AssociatedTypeDecl *requirement, Type type,
975+
TypeDecl *explicitDecl) -> bool {
976+
// Skip associated types that don't have witness table entries.
977+
if (!requirement->getOverriddenDecls().empty())
978+
return false;
979+
980+
// RESILIENCE: this could be an opaque conformance
981+
return type->hasTypeParameter();
982+
})) {
983+
return true;
984+
}
985+
986+
return false;
987+
}
988+
964989
/// Is there anything about the given conformance that requires witness
965990
/// tables to be dependently-generated?
966991
bool irgen::isDependentConformance(const NormalProtocolConformance *conformance) {
@@ -984,20 +1009,8 @@ bool irgen::isDependentConformance(const NormalProtocolConformance *conformance)
9841009
return true;
9851010
}
9861011

987-
auto DC = conformance->getDeclContext();
988-
// If the conforming type isn't dependent, the below check is never true.
989-
if (!DC->isGenericContext())
990-
return false;
991-
992-
// Check whether any of the associated types are dependent.
993-
if (conformance->forEachTypeWitness(nullptr,
994-
[&](AssociatedTypeDecl *requirement, Type type,
995-
TypeDecl *explicitDecl) -> bool {
996-
// RESILIENCE: this could be an opaque conformance
997-
return type->hasTypeParameter();
998-
})) {
1012+
if (hasDependentTypeWitness(conformance))
9991013
return true;
1000-
}
10011014

10021015
// Check if there are any conditional conformances. Other forms of conditional
10031016
// requirements don't exist in the witness table.
@@ -2184,7 +2197,7 @@ namespace {
21842197
// WitnessTablePrivateSizeInWordsAndRequiresInstantiation
21852198
B.addInt(IGM.Int16Ty,
21862199
(Description.witnessTablePrivateSize << 1) |
2187-
Description.requiresSpecialization);
2200+
Description.hasDependentAssociatedTypeWitnesses);
21882201
// RelativePointer<WitnessTable>
21892202
B.addRelativeAddress(Description.pattern);
21902203
// Instantiation function
@@ -2413,7 +2426,8 @@ void IRGenModule::emitSILWitnessTable(SILWitnessTable *wt) {
24132426
ConformanceDescription description(conf, wt, global,
24142427
wtableBuilder.getTableSize(),
24152428
wtableBuilder.getTablePrivateSize(),
2416-
wtableBuilder.requiresSpecialization());
2429+
wtableBuilder.requiresSpecialization(),
2430+
hasDependentTypeWitness(conf));
24172431

24182432
// Build the instantiation function, we if need one.
24192433
description.instantiationFn = wtableBuilder.buildInstantiationFunction();

lib/IRGen/IRGenModule.h

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -470,6 +470,9 @@ struct ConformanceDescription {
470470
/// Whether this witness table requires runtime specialization.
471471
const unsigned requiresSpecialization : 1;
472472

473+
/// Whether this witness table contains dependent associated type witnesses.
474+
const unsigned hasDependentAssociatedTypeWitnesses : 1;
475+
473476
/// The instantiation function, to be run at the end of witness table
474477
/// instantiation.
475478
llvm::Constant *instantiationFn = nullptr;
@@ -482,11 +485,15 @@ struct ConformanceDescription {
482485
llvm::Constant *pattern,
483486
uint16_t witnessTableSize,
484487
uint16_t witnessTablePrivateSize,
485-
bool requiresSpecialization)
488+
bool requiresSpecialization,
489+
bool hasDependentAssociatedTypeWitnesses)
486490
: conformance(conformance), wtable(wtable), pattern(pattern),
487491
witnessTableSize(witnessTableSize),
488492
witnessTablePrivateSize(witnessTablePrivateSize),
489-
requiresSpecialization(requiresSpecialization) { }
493+
requiresSpecialization(requiresSpecialization),
494+
hasDependentAssociatedTypeWitnesses(hasDependentAssociatedTypeWitnesses)
495+
{
496+
}
490497
};
491498

492499
/// IRGenModule - Primary class for emitting IR for global declarations.

test/IRGen/associated_type_witness.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ struct UsesVoid : HasSimpleAssoc {
167167
// Protocol conformance descriptor for GenericComputed : DerivedFromSimpleAssoc.
168168
// GLOBAL-LABEL: @"$s23associated_type_witness15GenericComputedVyxGAA22DerivedFromSimpleAssocAAMc" = hidden constant
169169
// GLOBAL-SAME: i16 2,
170-
// GLOBAL-SAME: i16 1,
170+
// GLOBAL-SAME: i16 0,
171171

172172
// Relative reference to witness table template
173173
// GLOBAL-SAME: i32 trunc (i64 sub (i64 ptrtoint ([2 x i8*]* @"$s23associated_type_witness15GenericComputedVyxGAA22DerivedFromSimpleAssocAAWp" to i64

test/IRGen/protocol_conformance_records.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,10 @@ extension Int : OtherResilientProtocol { }
137137
// CHECK-SAME: @"$s28protocol_conformance_records9DependentVyxGAA9AssociateAAWa"
138138
// -- flags
139139
// CHECK-SAME: i32 1
140+
// -- number of words in witness table
141+
// CHECK-SAME: i16 2,
142+
// -- number of private words in witness table + bit for "needs instantiation"
143+
// CHECK-SAME: i16 1
140144
// CHECK-SAME: }
141145
extension Dependent : Associate {
142146
public typealias X = (T, T)

test/IRGen/protocol_resilience.sil

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -106,8 +106,8 @@ protocol InternalProtocol {
106106
// -- number of witness table entries
107107
// CHECK-SAME: i16 1,
108108

109-
// -- size of private area + 'needs instantiation' bit
110-
// CHECK-SAME: i16 1,
109+
// -- size of private area + 'requires instantiation' bit (not set)
110+
// CHECK-SAME: i16 0,
111111

112112
// -- the template
113113
// CHECK-SAME: @"$s19protocol_resilience23ResilientConformingTypeV010resilient_A005OtherC8ProtocolAAWp"
@@ -139,8 +139,8 @@ protocol InternalProtocol {
139139
// -- number of witness table entries
140140
// CHECK-SAME: i16 1,
141141

142-
// -- size of private area + 'needs instantiation' bit
143-
// CHECK-SAME: i16 1,
142+
// -- size of private area + 'requires instantiation' bit (not set)
143+
// CHECK-SAME: i16 0,
144144

145145
// -- the template
146146
// CHECK-SAME: @"$s19protocol_resilience24ConformsWithRequirementsV010resilient_A008ProtocoldE0AAWp"

test/IRGen/protocol_resilience_descriptors.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,12 @@ public protocol P { }
5656
public struct ConditionallyConforms<Element> { }
5757
public struct Y { }
5858

59+
// CHECK-USAGE-LABEL: @"$s31protocol_resilience_descriptors1YV010resilient_A022OtherResilientProtocolAAMc" =
60+
// CHECK-USAGE-SAME: i32 131073,
61+
// CHECK-USAGE-SAME: i16 1,
62+
// CHECK-USAGE-SAME: i16 0
63+
extension Y: OtherResilientProtocol { }
64+
5965
// CHECK-USAGE: @"$s31protocol_resilience_descriptors29ConformsWithAssocRequirementsV010resilient_A008ProtocoleF12TypeDefaultsAAMc" =
6066
// CHECK-USAGE-SAME: $s18resilient_protocol29ProtocolWithAssocTypeDefaultsP2T2AC_AA014OtherResilientC0Tn
6167
// CHECK-USAGE-SAME: $s31protocol_resilience_descriptors29ConformsWithAssocRequirementsV010resilient_A008ProtocoleF12TypeDefaultsAA2T2AdEP_AD014OtherResilientI0PWT

0 commit comments

Comments
 (0)