Skip to content

Commit 4dec4ab

Browse files
Merge pull request #30472 from aschwaighofer/irgen_typelayout_use_heuristic
IRGen: Only use type layouts when we expect the generated IR to be faster
2 parents f92d2ca + 71599b7 commit 4dec4ab

File tree

4 files changed

+175
-73
lines changed

4 files changed

+175
-73
lines changed

lib/IRGen/GenValueWitness.cpp

Lines changed: 57 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -431,6 +431,33 @@ static void getArgAsLocalSelfTypeMetadata(IRGenFunction &IGF,
431431
getArgAsLocalSelfTypeMetadata(IGF, arg, abstractType);
432432
}
433433

434+
static const TypeLayoutEntry *
435+
conditionallyGetTypeLayoutEntry(IRGenModule &IGM, SILType concreteType) {
436+
if (!IGM.getOptions().UseTypeLayoutValueHandling)
437+
return nullptr;
438+
439+
auto &typeLayoutEntry = IGM.getTypeLayoutEntry(concreteType);
440+
441+
// Don't use type layout based generation for layouts that contain a resilient
442+
// field but no archetype. We don't expect a speadup by using type layout
443+
// based ir generation.
444+
if ((typeLayoutEntry.containsResilientField() &&
445+
!typeLayoutEntry.containsArchetypeField()) ||
446+
typeLayoutEntry.containsDependentResilientField())
447+
return nullptr;
448+
449+
return &typeLayoutEntry;
450+
}
451+
452+
static const EnumTypeLayoutEntry *
453+
conditionallyGetEnumTypeLayoutEntry(IRGenModule &IGM, SILType concreteType) {
454+
auto *entry = conditionallyGetTypeLayoutEntry(IGM, concreteType);
455+
if (!entry)
456+
return nullptr;
457+
458+
return entry->getAsEnum();
459+
}
460+
434461
/// Build a specific value-witness function.
435462
static void buildValueWitnessFunction(IRGenModule &IGM,
436463
llvm::Function *fn,
@@ -452,9 +479,9 @@ static void buildValueWitnessFunction(IRGenModule &IGM,
452479
Address src = getArgAs(IGF, argv, type, "src");
453480
getArgAsLocalSelfTypeMetadata(IGF, argv, abstractType);
454481

455-
if (IGM.getOptions().UseTypeLayoutValueHandling) {
456-
auto &typeLayoutEntry = IGM.getTypeLayoutEntry(concreteType);
457-
typeLayoutEntry.assignWithCopy(IGF, dest, src);
482+
if (auto *typeLayoutEntry =
483+
conditionallyGetTypeLayoutEntry(IGM, concreteType)) {
484+
typeLayoutEntry->assignWithCopy(IGF, dest, src);
458485
} else {
459486
type.assignWithCopy(IGF, dest, src, concreteType, true);
460487
}
@@ -467,9 +494,9 @@ static void buildValueWitnessFunction(IRGenModule &IGM,
467494
Address dest = getArgAs(IGF, argv, type, "dest");
468495
Address src = getArgAs(IGF, argv, type, "src");
469496
getArgAsLocalSelfTypeMetadata(IGF, argv, abstractType);
470-
if (IGM.getOptions().UseTypeLayoutValueHandling) {
471-
auto &typeLayoutEntry = IGM.getTypeLayoutEntry(concreteType);
472-
typeLayoutEntry.assignWithTake(IGF, dest, src);
497+
if (auto *typeLayoutEntry =
498+
conditionallyGetTypeLayoutEntry(IGM, concreteType)) {
499+
typeLayoutEntry->assignWithTake(IGF, dest, src);
473500
} else {
474501
type.assignWithTake(IGF, dest, src, concreteType, true);
475502
}
@@ -481,9 +508,9 @@ static void buildValueWitnessFunction(IRGenModule &IGM,
481508
case ValueWitness::Destroy: {
482509
Address object = getArgAs(IGF, argv, type, "object");
483510
getArgAsLocalSelfTypeMetadata(IGF, argv, abstractType);
484-
if (IGM.getOptions().UseTypeLayoutValueHandling) {
485-
auto &typeLayoutEntry = IGM.getTypeLayoutEntry(concreteType);
486-
typeLayoutEntry.destroy(IGF, object);
511+
if (auto *typeLayoutEntry =
512+
conditionallyGetTypeLayoutEntry(IGM, concreteType)) {
513+
typeLayoutEntry->destroy(IGF, object);
487514
} else {
488515
type.destroy(IGF, object, concreteType, true);
489516
}
@@ -497,9 +524,9 @@ static void buildValueWitnessFunction(IRGenModule &IGM,
497524
getArgAsLocalSelfTypeMetadata(IGF, argv, abstractType);
498525

499526
llvm::Value *objectPtr = nullptr;
500-
if (IGM.getOptions().UseTypeLayoutValueHandling) {
501-
auto &typeLayoutEntry = IGM.getTypeLayoutEntry(concreteType);
502-
objectPtr = typeLayoutEntry.initBufferWithCopyOfBuffer(IGF, dest, src);
527+
if (auto *typeLayoutEntry =
528+
conditionallyGetTypeLayoutEntry(IGM, concreteType)) {
529+
objectPtr = typeLayoutEntry->initBufferWithCopyOfBuffer(IGF, dest, src);
503530
} else {
504531
Address result = emitInitializeBufferWithCopyOfBuffer(
505532
IGF, dest, src, concreteType, type, packing);
@@ -514,9 +541,9 @@ static void buildValueWitnessFunction(IRGenModule &IGM,
514541
Address dest = getArgAs(IGF, argv, type, "dest");
515542
Address src = getArgAs(IGF, argv, type, "src");
516543
getArgAsLocalSelfTypeMetadata(IGF, argv, abstractType);
517-
if (IGM.getOptions().UseTypeLayoutValueHandling) {
518-
auto &typeLayoutEntry = IGM.getTypeLayoutEntry(concreteType);
519-
typeLayoutEntry.initWithCopy(IGF, dest, src);
544+
if (auto *typeLayoutEntry =
545+
conditionallyGetTypeLayoutEntry(IGM, concreteType)) {
546+
typeLayoutEntry->initWithCopy(IGF, dest, src);
520547
} else {
521548
type.initializeWithCopy(IGF, dest, src, concreteType, true);
522549
}
@@ -530,9 +557,9 @@ static void buildValueWitnessFunction(IRGenModule &IGM,
530557
Address src = getArgAs(IGF, argv, type, "src");
531558
getArgAsLocalSelfTypeMetadata(IGF, argv, abstractType);
532559

533-
if (IGM.getOptions().UseTypeLayoutValueHandling) {
534-
auto &typeLayoutEntry = IGM.getTypeLayoutEntry(concreteType);
535-
typeLayoutEntry.initWithTake(IGF, dest, src);
560+
if (auto *typeLayoutEntry =
561+
conditionallyGetTypeLayoutEntry(IGM, concreteType)) {
562+
typeLayoutEntry->initWithTake(IGF, dest, src);
536563
} else {
537564
type.initializeWithTake(IGF, dest, src, concreteType, true);
538565
}
@@ -552,9 +579,8 @@ static void buildValueWitnessFunction(IRGenModule &IGM,
552579
auto enumAddr = type.getAddressForPointer(value);
553580

554581
llvm::Value *result;
555-
auto &typeLayoutEntry = IGM.getTypeLayoutEntry(concreteType);
556-
const auto *enumTypeLayoutEntry = typeLayoutEntry.getAsEnum();
557-
if (enumTypeLayoutEntry && IGM.getOptions().UseTypeLayoutValueHandling) {
582+
if (auto *enumTypeLayoutEntry =
583+
conditionallyGetEnumTypeLayoutEntry(IGM, concreteType)) {
558584
result = enumTypeLayoutEntry->getEnumTag(IGF, enumAddr);
559585
} else {
560586
result = strategy.emitGetEnumTag(IGF, concreteType, enumAddr);
@@ -570,9 +596,8 @@ static void buildValueWitnessFunction(IRGenModule &IGM,
570596
getArgAsLocalSelfTypeMetadata(IGF, argv, abstractType);
571597

572598
if (!strategy.getElementsWithPayload().empty()) {
573-
auto &typeLayoutEntry = IGM.getTypeLayoutEntry(concreteType);
574-
const auto *enumTypeLayoutEntry = typeLayoutEntry.getAsEnum();
575-
if (enumTypeLayoutEntry && IGM.getOptions().UseTypeLayoutValueHandling) {
599+
if (auto *enumTypeLayoutEntry =
600+
conditionallyGetEnumTypeLayoutEntry(IGM, concreteType)) {
576601
enumTypeLayoutEntry->destructiveProjectEnumData(
577602
IGF, Address(value, type.getBestKnownAlignment()));
578603
} else {
@@ -596,9 +621,8 @@ static void buildValueWitnessFunction(IRGenModule &IGM,
596621
llvm::Value *tag = getArg(argv, "tag");
597622

598623
getArgAsLocalSelfTypeMetadata(IGF, argv, abstractType);
599-
auto &typeLayoutEntry = IGM.getTypeLayoutEntry(concreteType);
600-
const auto *enumTypeLayoutEntry = typeLayoutEntry.getAsEnum();
601-
if (enumTypeLayoutEntry && IGM.getOptions().UseTypeLayoutValueHandling) {
624+
if (auto *enumTypeLayoutEntry =
625+
conditionallyGetEnumTypeLayoutEntry(IGM, concreteType)) {
602626
enumTypeLayoutEntry->destructiveInjectEnumTag(
603627
IGF, tag, Address(value, type.getBestKnownAlignment()));
604628
} else {
@@ -618,9 +642,9 @@ static void buildValueWitnessFunction(IRGenModule &IGM,
618642
llvm::Value *numEmptyCases = getArg(argv, "numEmptyCases");
619643

620644
getArgAsLocalSelfTypeMetadata(IGF, argv, abstractType);
621-
if (IGM.getOptions().UseTypeLayoutValueHandling) {
622-
auto &typeLayoutEntry = IGM.getTypeLayoutEntry(concreteType);
623-
auto *idx = typeLayoutEntry.getEnumTagSinglePayload(
645+
if (auto *typeLayoutEntry =
646+
conditionallyGetTypeLayoutEntry(IGM, concreteType)) {
647+
auto *idx = typeLayoutEntry->getEnumTagSinglePayload(
624648
IGF, numEmptyCases, Address(value, type.getBestKnownAlignment()));
625649
IGF.Builder.CreateRet(idx);
626650
} else {
@@ -642,9 +666,9 @@ static void buildValueWitnessFunction(IRGenModule &IGM,
642666
llvm::Value *numEmptyCases = getArg(argv, "numEmptyCases");
643667

644668
getArgAsLocalSelfTypeMetadata(IGF, argv, abstractType);
645-
if (IGM.getOptions().UseTypeLayoutValueHandling) {
646-
auto &typeLayoutEntry = IGM.getTypeLayoutEntry(concreteType);
647-
typeLayoutEntry.storeEnumTagSinglePayload(
669+
if (auto *typeLayoutEntry =
670+
conditionallyGetTypeLayoutEntry(IGM, concreteType)) {
671+
typeLayoutEntry->storeEnumTagSinglePayload(
648672
IGF, whichCase, numEmptyCases,
649673
Address(value, type.getBestKnownAlignment()));
650674
} else {

lib/IRGen/TypeLayout.cpp

Lines changed: 47 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,18 @@ using namespace irgen;
2525

2626
TypeLayoutEntry::~TypeLayoutEntry() {}
2727

28+
void TypeLayoutEntry::computeProperties() {
29+
// does not add anything.
30+
}
31+
32+
void TypeLayoutEntry::gatherProperties(TypeLayoutEntry *fromEntry) {
33+
hasArchetypeField |= fromEntry->hasArchetypeField;
34+
hasResilientField |= fromEntry->hasResilientField;
35+
hasDependentResilientField |= fromEntry->hasDependentResilientField;
36+
37+
assert(!(!hasResilientField && hasDependentResilientField));
38+
}
39+
2840
const EnumTypeLayoutEntry *TypeLayoutEntry::getAsEnum() const {
2941
if (getKind() == TypeLayoutEntryKind::Enum) {
3042
return static_cast<const EnumTypeLayoutEntry *>(this);
@@ -99,8 +111,16 @@ void TypeLayoutEntry::initWithTake(IRGenFunction &IGF, Address dest,
99111
// Nothing to copy.
100112
}
101113

102-
bool TypeLayoutEntry::containsEnum() const {
103-
return false;
114+
bool TypeLayoutEntry::containsResilientField() const {
115+
return hasResilientField;
116+
}
117+
118+
bool TypeLayoutEntry::containsArchetypeField() const {
119+
return hasArchetypeField;
120+
}
121+
122+
bool TypeLayoutEntry::containsDependentResilientField() const {
123+
return hasDependentResilientField;
104124
}
105125

106126
llvm::Value *TypeLayoutEntry::getEnumTagSinglePayload(
@@ -571,6 +591,10 @@ llvm::Value *TypeLayoutEntry::initBufferWithCopyOfBuffer(IRGenFunction &IGF,
571591
return pointerToObject;
572592
}
573593

594+
void ScalarTypeLayoutEntry::computeProperties() {
595+
// does not add anything.
596+
}
597+
574598
void ScalarTypeLayoutEntry::Profile(llvm::FoldingSetNodeID &id) const {
575599
ScalarTypeLayoutEntry::Profile(id, typeInfo);
576600
}
@@ -608,10 +632,6 @@ llvm::Value *ScalarTypeLayoutEntry::isBitwiseTakable(IRGenFunction &IGF) const {
608632
ResilienceExpansion::Maximal));
609633
}
610634

611-
bool ScalarTypeLayoutEntry::containsEnum() const {
612-
return false;
613-
}
614-
615635
void ScalarTypeLayoutEntry::destroy(IRGenFunction &IGF, Address addr) const {
616636
auto alignment = cast<FixedTypeInfo>(typeInfo).getFixedAlignment();
617637
auto addressType = typeInfo.getStorageType()->getPointerTo();
@@ -709,6 +729,12 @@ LLVM_DUMP_METHOD void ScalarTypeLayoutEntry::dump() const {
709729
}
710730
#endif
711731

732+
void AlignedGroupEntry::computeProperties() {
733+
for (auto *entry : entries) {
734+
gatherProperties(entry);
735+
}
736+
}
737+
712738
void AlignedGroupEntry::Profile(llvm::FoldingSetNodeID &id) const {
713739
AlignedGroupEntry::Profile(id, entries, minimumAlignment, isFixedSize);
714740
}
@@ -763,14 +789,6 @@ llvm::Value *AlignedGroupEntry::size(IRGenFunction &IGF) const {
763789
return currentSize;
764790
}
765791

766-
bool AlignedGroupEntry::containsEnum() const {
767-
for (auto *entry : entries) {
768-
if (entry->containsEnum())
769-
return true;
770-
}
771-
return false;
772-
}
773-
774792
llvm::Value *AlignedGroupEntry::extraInhabitantCount(IRGenFunction &IGF) const {
775793
llvm::Value *currentMaxXICount = IGF.IGM.getInt32(0);
776794
auto &Builder = IGF.Builder;
@@ -1001,6 +1019,8 @@ LLVM_DUMP_METHOD void AlignedGroupEntry::dump() const {
10011019
}
10021020
#endif
10031021

1022+
void ArchetypeLayoutEntry::computeProperties() { hasArchetypeField = true; }
1023+
10041024
void ArchetypeLayoutEntry::Profile(llvm::FoldingSetNodeID &id) const {
10051025
ArchetypeLayoutEntry::Profile(id, archetype);
10061026
}
@@ -1030,10 +1050,6 @@ ArchetypeLayoutEntry::isBitwiseTakable(IRGenFunction &IGF) const {
10301050
return emitLoadOfIsBitwiseTakable(IGF, archetype);
10311051
}
10321052

1033-
bool ArchetypeLayoutEntry::containsEnum() const {
1034-
return false;
1035-
}
1036-
10371053
void ArchetypeLayoutEntry::destroy(IRGenFunction &IGF, Address addr) const {
10381054
emitDestroyCall(IGF, archetype, addr);
10391055
}
@@ -1139,10 +1155,10 @@ llvm::Value *EnumTypeLayoutEntry::isBitwiseTakable(IRGenFunction &IGF) const {
11391155
return isBitwiseTakable;
11401156
}
11411157

1142-
bool EnumTypeLayoutEntry::containsEnum() const {
1143-
if (cases.size() == 1)
1144-
return false;
1145-
return false;
1158+
void EnumTypeLayoutEntry::computeProperties() {
1159+
for (auto c: cases) {
1160+
gatherProperties(c);
1161+
}
11461162
}
11471163

11481164
llvm::Value *EnumTypeLayoutEntry::size(IRGenFunction &IGF) const {
@@ -2006,8 +2022,10 @@ ResilientTypeLayoutEntry::isBitwiseTakable(IRGenFunction &IGF) const {
20062022
return emitLoadOfIsBitwiseTakable(IGF, ty);
20072023
}
20082024

2009-
bool ResilientTypeLayoutEntry::containsEnum() const {
2010-
return false;
2025+
void ResilientTypeLayoutEntry::computeProperties() {
2026+
hasResilientField = true;
2027+
if (ty.getASTType()->hasArchetype())
2028+
hasDependentResilientField = true;
20112029
}
20122030

20132031
void ResilientTypeLayoutEntry::destroy(IRGenFunction &IGF, Address addr) const {
@@ -2076,6 +2094,7 @@ TypeLayoutCache::getOrCreateScalarEntry(const TypeInfo &ti,
20762094
auto mem = bumpAllocator.Allocate(bytes, alignof(ScalarTypeLayoutEntry));
20772095
auto newEntry = new (mem) ScalarTypeLayoutEntry(ti, representative);
20782096
scalarEntries.InsertNode(newEntry, insertPos);
2097+
newEntry->computeProperties();
20792098
return newEntry;
20802099
}
20812100

@@ -2091,6 +2110,7 @@ TypeLayoutCache::getOrCreateArchetypeEntry(SILType archetype) {
20912110
auto mem = bumpAllocator.Allocate(bytes, alignof(ArchetypeLayoutEntry));
20922111
auto newEntry = new (mem) ArchetypeLayoutEntry(archetype);
20932112
archetypeEntries.InsertNode(newEntry, insertPos);
2113+
newEntry->computeProperties();
20942114
return newEntry;
20952115
}
20962116

@@ -2108,6 +2128,7 @@ AlignedGroupEntry *TypeLayoutCache::getOrCreateAlignedGroupEntry(
21082128
auto newEntry =
21092129
new (mem) AlignedGroupEntry(entries, minimumAlignment, isFixedSize);
21102130
alignedGroupEntries.InsertNode(newEntry, insertPos);
2131+
newEntry->computeProperties();
21112132
return newEntry;
21122133
}
21132134

@@ -2127,6 +2148,7 @@ EnumTypeLayoutEntry *TypeLayoutCache::getOrCreateEnumEntry(
21272148
auto mem = bumpAllocator.Allocate(bytes, alignof(EnumTypeLayoutEntry));
21282149
auto newEntry = new (mem) EnumTypeLayoutEntry(numEmptyCases, nonEmptyCases);
21292150
enumEntries.InsertNode(newEntry, insertPos);
2151+
newEntry->computeProperties();
21302152
return newEntry;
21312153
}
21322154

@@ -2142,6 +2164,7 @@ TypeLayoutCache::getOrCreateResilientEntry(SILType ty) {
21422164
auto mem = bumpAllocator.Allocate(bytes, alignof(ResilientTypeLayoutEntry));
21432165
auto newEntry = new (mem) ResilientTypeLayoutEntry(ty);
21442166
resilientEntries.InsertNode(newEntry, insertPos);
2167+
newEntry->computeProperties();
21452168
return newEntry;
21462169
}
21472170

0 commit comments

Comments
 (0)