Skip to content

Commit 71599b7

Browse files
committed
IRGen: Only use type layouts when we expect the generated IR to be faster
If there the layout is not dependent on archetypes and but has resilient types using the new type layout based approach is not going to be faster. rdar://59960653
1 parent 13cd05c commit 71599b7

File tree

2 files changed

+97
-33
lines changed

2 files changed

+97
-33
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 {

test/IRGen/struct_with_resilient_type.swift

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// RUN: %empty-directory(%t)
22
// RUN: %target-swift-frontend -emit-module -enable-library-evolution -emit-module-path=%t/resilient_struct.swiftmodule -module-name=resilient_struct %S/../Inputs/resilient_struct.swift
33
// RUN: %target-swift-frontend -I %t -emit-ir %s
4+
// RUN: %target-swift-frontend -O -I %t -emit-ir %s | %FileCheck %s --check-prefix=VWT-%target-os --check-prefix=VWT
45

56
// REQUIRES: CPU=x86_64
67

@@ -37,3 +38,42 @@ func crashCaller() {
3738
}
3839

3940
crashCaller()
41+
42+
43+
// VWT: define {{.*}} @"$s26struct_with_resilient_type9SomeValueVwtk"
44+
45+
// Don't use the type layout based value witness based generation (i.e we load field offsets below).
46+
47+
// VWT-macosx: define {{.*}} %swift.opaque* @"$s26struct_with_resilient_type9SomeValueVwta"(%swift.opaque* noalias returned {{.*}}, %swift.opaque* noalias {{.*}}, %swift.type* nocapture readonly [[MT:%.*]])
48+
// VWT-macosx: [[VAL1:%.*]] = load i64
49+
// VWT-macosx: store i64 [[VAL1]]
50+
// VWT-macosx: [[T1:%.*]] = tail call swiftcc %swift.metadata_response @"$s16resilient_struct13ResilientBoolVMa"(i64 0)
51+
// VWT-macosx: [[T2:%.*]] = extractvalue %swift.metadata_response [[T1]], 0
52+
// VWT-macosx: [[T3:%.*]] = getelementptr inbounds %swift.type, %swift.type* [[T2]], i64 -1
53+
// VWT-macosx: [[T4:%.*]] = bitcast %swift.type* [[T3]] to i8***
54+
// VWT-macosx: [[T5:%.*]] = load i8**, i8*** [[T4]]
55+
// VWT-macosx: [[T6:%.*]] = getelementptr inbounds i8*, i8** [[T5]], i64 5
56+
// VWT-macosx: [[T7:%.*]] = bitcast i8** [[T6]] to %swift.opaque* (%swift.opaque*, %swift.opaque*, %swift.type*)**
57+
// VWT-macosx: [[T8:%.*]] = load %swift.opaque* (%swift.opaque*, %swift.opaque*, %swift.type*)*, %swift.opaque* (%swift.opaque*, %swift.opaque*, %swift.type*)** [[T7]]
58+
// VWT-macosx: tail call %swift.opaque* [[T8]](
59+
// VWT-macosx: [[F01:%.*]] = getelementptr inbounds %swift.type, %swift.type* [[MT]], i64 3
60+
// VWT-macosx: [[F02:%.*]] = bitcast %swift.type* [[F01]] to i32*
61+
// VWT-macosx: [[F03:%.*]] = load i32, i32* [[F02]], align 8
62+
// VWT-macosx: [[F04:%.*]] = sext i32 [[F03]] to i64
63+
// VWT-macosx: [[FA1:%.*]] = getelementptr inbounds i8, i8* {{.*}}, i64 [[F04]]
64+
// VWT-macosx: [[FA2:%.*]] = getelementptr inbounds i8, i8* {{.*}}, i64 [[F04]]
65+
// VWT-macosx: [[Y_ADDR_DEST:%.*]] = bitcast i8* [[FA1]] to i64*
66+
// VWT-macosx: [[Y_ADDR_SRC:%.*]] = bitcast i8* [[FA2]] to i64*
67+
// VWT-macosx: [[VAL3:%.*]] = load i64, i64* [[Y_ADDR_SRC]]
68+
// VWT-macosx: store i64 [[VAL3]], i64* [[Y_ADDR_DEST]]
69+
// VWT-macosx: ret
70+
// VWT-macosx: }
71+
public struct SomeValue {
72+
var x = 1
73+
var b : ResilientBool
74+
var y = 2
75+
76+
init(_ b: ResilientBool) {
77+
self.b = b
78+
}
79+
}

0 commit comments

Comments
 (0)