Skip to content

Commit fa40bf8

Browse files
authored
Merge pull request #26571 from jckarter/less-getObjectType
IRGen: Avoid unnecessary swift_getObjectType calls.
2 parents 625a7c7 + b9e6ae0 commit fa40bf8

12 files changed

+60
-37
lines changed

lib/IRGen/GenExistential.cpp

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1856,11 +1856,13 @@ void irgen::emitMetatypeOfClassExistential(IRGenFunction &IGF, Explosion &value,
18561856
auto metaTy = metatypeTy.castTo<ExistentialMetatypeType>();
18571857
auto repr = metaTy->getRepresentation();
18581858
assert(repr != MetatypeRepresentation::Thin &&
1859-
"Class metatypes should have a thin representation");
1859+
"Class metatypes should not have a thin representation");
18601860
assert((IGF.IGM.ObjCInterop || repr != MetatypeRepresentation::ObjC) &&
18611861
"Class metatypes should not have ObjC representation without runtime");
18621862

1863-
auto dynamicType = emitDynamicTypeOfOpaqueHeapObject(IGF, instance, repr);
1863+
auto dynamicType = emitDynamicTypeOfHeapObject(IGF, instance, repr,
1864+
existentialTy,
1865+
/*allow artificial*/ false);
18641866
out.add(dynamicType);
18651867

18661868
// Get the witness tables.
@@ -1898,8 +1900,10 @@ irgen::emitClassExistentialProjection(IRGenFunction &IGF,
18981900
ArrayRef<llvm::Value*> wtables;
18991901
llvm::Value *value;
19001902
std::tie(wtables, value) = baseTI.getWitnessTablesAndValue(base);
1901-
auto metadata = emitDynamicTypeOfOpaqueHeapObject(IGF, value,
1902-
MetatypeRepresentation::Thick);
1903+
auto metadata = emitDynamicTypeOfHeapObject(IGF, value,
1904+
MetatypeRepresentation::Thick,
1905+
baseTy,
1906+
/*allow artificial*/ false);
19031907
IGF.bindArchetype(openedArchetype, metadata, MetadataState::Complete,
19041908
wtables);
19051909

@@ -2237,8 +2241,10 @@ Address irgen::emitOpaqueBoxedExistentialProjection(
22372241
IGF.getTypeInfo(existentialTy).as<ClassExistentialTypeInfo>();
22382242
auto valueAddr = baseTI.projectValue(IGF, base);
22392243
auto value = IGF.Builder.CreateLoad(valueAddr);
2240-
auto metadata = emitDynamicTypeOfOpaqueHeapObject(IGF, value,
2241-
MetatypeRepresentation::Thick);
2244+
auto metadata = emitDynamicTypeOfHeapObject(IGF, value,
2245+
MetatypeRepresentation::Thick,
2246+
existentialTy,
2247+
/*allow artificial*/ false);
22422248

22432249
// If we are projecting into an opened archetype, capture the
22442250
// witness tables.

lib/IRGen/GenHeap.cpp

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1717,8 +1717,10 @@ llvm::Value *IRGenFunction::getLocalSelfMetadata() {
17171717
SelfKind = SwiftMetatype;
17181718
break;
17191719
case ObjectReference:
1720-
LocalSelf = emitDynamicTypeOfOpaqueHeapObject(*this, LocalSelf,
1721-
MetatypeRepresentation::Thick);
1720+
LocalSelf = emitDynamicTypeOfHeapObject(*this, LocalSelf,
1721+
MetatypeRepresentation::Thick,
1722+
SILType::getPrimitiveObjectType(LocalSelfType),
1723+
/*allow artificial*/ false);
17221724
SelfKind = SwiftMetatype;
17231725
break;
17241726
}
@@ -1839,9 +1841,25 @@ llvm::Value *irgen::emitHeapMetadataRefForHeapObject(IRGenFunction &IGF,
18391841

18401842
/// Given an opaque class instance pointer, produce the type metadata reference
18411843
/// as a %type*.
1842-
llvm::Value *irgen::emitDynamicTypeOfOpaqueHeapObject(IRGenFunction &IGF,
1844+
///
1845+
/// You should only use this if you have an untyped object pointer with absolutely no type information.
1846+
/// Generally, it's better to use \c emitDynamicTypeOfHeapObject, which will
1847+
/// use the most efficient possible access pattern to get the dynamic type based on
1848+
/// the static type information.
1849+
static llvm::Value *emitDynamicTypeOfOpaqueHeapObject(IRGenFunction &IGF,
18431850
llvm::Value *object,
18441851
MetatypeRepresentation repr) {
1852+
if (!IGF.IGM.ObjCInterop) {
1853+
// Without objc interop, getting the dynamic type of an object is always
1854+
// just a load of the isa pointer.
1855+
1856+
assert(repr == MetatypeRepresentation::Thick
1857+
&& "objc metatypes should not occur without objc interop, "
1858+
"and thin metadata should not be requested here");
1859+
return emitLoadOfHeapMetadataRef(IGF, object, IsaEncoding::Pointer,
1860+
/*suppressCast*/ false);
1861+
}
1862+
18451863
object = IGF.Builder.CreateBitCast(object, IGF.IGM.ObjCPtrTy);
18461864
llvm::CallInst *metadata;
18471865

lib/IRGen/GenHeap.h

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -140,12 +140,6 @@ emitAllocateExistentialBoxInBuffer(IRGenFunction &IGF, SILType boxedType,
140140
Address destBuffer, GenericEnvironment *env,
141141
const llvm::Twine &name, bool isOutlined);
142142

143-
/// Given an opaque class instance pointer, produce the type
144-
/// metadata reference as a %type*.
145-
llvm::Value *emitDynamicTypeOfOpaqueHeapObject(IRGenFunction &IGF,
146-
llvm::Value *object,
147-
MetatypeRepresentation rep);
148-
149143
/// Given a heap-object instance, with some heap-object type,
150144
/// produce a reference to its type metadata.
151145
llvm::Value *emitDynamicTypeOfHeapObject(IRGenFunction &IGF,

lib/IRGen/GenType.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2255,14 +2255,16 @@ unsigned IRGenModule::getBuiltinIntegerWidth(BuiltinIntegerWidth w) {
22552255
llvm_unreachable("impossible width value");
22562256
}
22572257

2258-
void IRGenFunction::setLocalSelfMetadata(CanType exactSelfClass,
2258+
void IRGenFunction::setLocalSelfMetadata(CanType selfClass,
2259+
bool isExactSelfClass,
22592260
llvm::Value *value,
22602261
IRGenFunction::LocalSelfKind kind) {
22612262
assert(!LocalSelf && "already have local self metadata");
22622263
LocalSelf = value;
2263-
assert((!exactSelfClass || exactSelfClass->getClassOrBoundGenericClass())
2264+
assert(selfClass->getClassOrBoundGenericClass()
22642265
&& "self type not a class?");
2265-
ExactSelfType = exactSelfClass;
2266+
LocalSelfIsExact = isExactSelfClass;
2267+
LocalSelfType = selfClass;
22662268
SelfKind = kind;
22672269
}
22682270

lib/IRGen/IRGenFunction.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -644,7 +644,7 @@ class IRGenFunction {
644644
};
645645

646646
llvm::Value *getLocalSelfMetadata();
647-
void setLocalSelfMetadata(CanType selfBaseTy,
647+
void setLocalSelfMetadata(CanType selfBaseTy, bool selfIsExact,
648648
llvm::Value *value, LocalSelfKind kind);
649649

650650
private:
@@ -662,7 +662,8 @@ class IRGenFunction {
662662
/// The value that satisfies metadata lookups for dynamic Self.
663663
llvm::Value *LocalSelf = nullptr;
664664
/// If set, the dynamic Self type is assumed to be equivalent to this exact class.
665-
CanType ExactSelfType;
665+
CanType LocalSelfType;
666+
bool LocalSelfIsExact;
666667
LocalSelfKind SelfKind;
667668
};
668669

lib/IRGen/IRGenSIL.cpp

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1610,12 +1610,10 @@ static void emitLocalSelfMetadata(IRGenSILFunction &IGF) {
16101610
// Specify the exact Self type if we know it, either because the class
16111611
// is final, or because the function we're emitting is a method with the
16121612
// [exact_self_class] attribute set on it during the SIL pipeline.
1613-
CanType exactSelfTy;
1614-
if (selfTy->getClassOrBoundGenericClass()->isFinal()
1615-
|| IGF.CurSILFn->isExactSelfClass())
1616-
exactSelfTy = selfTy;
1613+
bool isExact = selfTy->getClassOrBoundGenericClass()->isFinal()
1614+
|| IGF.CurSILFn->isExactSelfClass();
16171615

1618-
IGF.setLocalSelfMetadata(exactSelfTy, value, selfKind);
1616+
IGF.setLocalSelfMetadata(selfTy, isExact, value, selfKind);
16191617
}
16201618

16211619
/// Emit the definition for the given SIL constant.

lib/IRGen/MetadataRequest.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2380,7 +2380,7 @@ IRGenFunction::emitTypeMetadataRef(CanType type,
23802380

23812381
// If we're asking for the metadata of the type that dynamic Self is known
23822382
// to be equal to, we can just use the self metadata.
2383-
if (ExactSelfType == type) {
2383+
if (LocalSelfIsExact && LocalSelfType == type) {
23842384
return MetadataResponse::forComplete(getLocalSelfMetadata());
23852385
}
23862386

test/IRGen/dynamic_self_metadata.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,8 @@ class C {
3737
return id(nil)
3838
}
3939
// CHECK-LABEL: define hidden swiftcc i64 @"$s21dynamic_self_metadata1CC0A12SelfArgumentACXDSgyF"(%T21dynamic_self_metadata1CC* swiftself)
40-
// CHECK: [[CAST1:%.+]] = bitcast %T21dynamic_self_metadata1CC* %0 to [[METATYPE:%.+]]
41-
// CHECK: [[TYPE1:%.+]] = call %swift.type* @swift_getObjectType([[METATYPE]] [[CAST1]])
40+
// CHECK: [[GEP1:%.+]] = getelementptr {{.*}} %0
41+
// CHECK: [[TYPE1:%.+]] = load {{.*}} [[GEP1]]
4242
// CHECK: [[T0:%.+]] = call swiftcc %swift.metadata_response @"$sSqMa"(i64 0, %swift.type* [[TYPE1]])
4343
// CHECK: [[TYPE2:%.+]] = extractvalue %swift.metadata_response [[T0]], 0
4444
// CHECK: call swiftcc void @"$s21dynamic_self_metadata2idyxxlF"({{.*}}, %swift.type* [[TYPE2]])
@@ -48,8 +48,8 @@ class C {
4848
return nil
4949
}
5050
// CHECK-LABEL: define hidden swiftcc i64 @"$s21dynamic_self_metadata1CC0A18SelfConformingTypeACXDSgyF"(%T21dynamic_self_metadata1CC* swiftself)
51-
// CHECK: [[SELF:%.*]] = bitcast %T21dynamic_self_metadata1CC* %0 to %objc_object*
52-
// CHECK: [[SELF_TYPE:%.*]] = call %swift.type* @swift_getObjectType(%objc_object* [[SELF]])
51+
// CHECK: [[SELF_GEP:%.+]] = getelementptr {{.*}} %0
52+
// CHECK: [[SELF_TYPE:%.+]] = load {{.*}} [[SELF_GEP]]
5353
// CHECK: [[METADATA_RESPONSE:%.*]] = call swiftcc %swift.metadata_response @"$s21dynamic_self_metadata1GVMa"(i64 0, %swift.type* [[SELF_TYPE]])
5454
// CHECK: [[METADATA:%.*]] = extractvalue %swift.metadata_response [[METADATA_RESPONSE]], 0
5555
// CHECK: call i8** @swift_getWitnessTable(%swift.protocol_conformance_descriptor* bitcast ({{.*}} @"$s21dynamic_self_metadata1GVyxGAA1PAAMc" to %swift.protocol_conformance_descriptor*), %swift.type* [[METADATA]], i8*** undef)

test/IRGen/exact_self_class_metadata_peephole.swift

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,8 @@ final private class FinalPrivateNonfinalSubclass<U>: PrivateNonfinal<U, String,
6262
// CHECK-LABEL: define {{.*}}FinalPrivateNonfinalSubclass{{.*}}burts
6363
@inline(never)
6464
final func burts() {
65-
// CHECK: [[TYPE:%.*]] = call {{.*}} @swift_getObjectType
65+
// CHECK: [[TYPE_GEP:%.*]] = getelementptr {{.*}} %0
66+
// CHECK: [[TYPE:%.*]] = load {{.*}} [[TYPE_GEP]]
6667
// CHECK: call {{.*}} @useMetadata(%swift.type* [[TYPE]], %swift.type* [[TYPE]])
6768
useMetadata(FinalPrivateNonfinalSubclass<U>.self)
6869
// CHECK: [[INSTANTIATED_TYPE:%.*]] = call {{.*}} @__swift_instantiateConcreteTypeFromMangledName({{.*}}FinalPrivateNonfinalSubclass
@@ -80,7 +81,8 @@ final private class PrivateFinal<T, U, V> {
8081

8182
// CHECK-LABEL: define {{.*}}PrivateFinal{{.*}}butts
8283
func butts() {
83-
// CHECK: [[TYPE:%.*]] = call {{.*}} @swift_getObjectType
84+
// CHECK: [[TYPE_GEP:%.*]] = getelementptr {{.*}} %0
85+
// CHECK: [[TYPE:%.*]] = load {{.*}} [[TYPE_GEP]]
8486
// CHECK: call {{.*}} @useMetadata(%swift.type* [[TYPE]], %swift.type* [[TYPE]])
8587
useMetadata(PrivateFinal<T, U, V>.self)
8688
// CHECK: [[INSTANTIATED_TYPE:%.*]] = call {{.*}} @__swift_instantiateConcreteTypeFromMangledName({{.*}}PrivateFinal

test/IRGen/objc_generic_class_metadata.sil

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -99,9 +99,9 @@ public class D {
9999
}
100100

101101
// CHECK: define void @testDynamicSelfMetatype(i8*, i8*)
102-
// CHECK: [[C:%.*]] = bitcast i8* %0 to %T27objc_generic_class_metadata1DC*
103-
// CHECK: [[O:%.*]] = bitcast %T27objc_generic_class_metadata1DC* [[C]] to %objc_object*
104-
// CHECK: call %swift.type* @swift_getObjectType(%objc_object* [[O]]
102+
// CHECK: [[T0:%.*]] = bitcast {{.*}} %0
103+
// CHECK: [[T1:%.*]] = bitcast {{.*}} [[T0]]
104+
// CHECK: [[TYPE:%.*]] = load {{.*}} [[T1]]
105105
sil @testDynamicSelfMetatype : $@convention(objc_method) (@owned D) -> () {
106106
bb0(%0 : $D):
107107
%1 = metatype $@thick @dynamic_self D.Type

test/IRGen/object_type.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
// RUN: %target-codesign %t/a.out
55
// RUN: %target-run %t/a.out | %FileCheck %s
66
// REQUIRES: executable_test
7+
// REQUIRES: objc_interop
78

89
// Check if the runtime function swift_getObjectType is not readnone and
910
// therefore not re-scheduled with release-calls, which would lead to a crash

test/IRGen/protocol_accessor_multifile.swift

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// RUN: %target-swift-frontend -emit-ir -primary-file %s %S/Inputs/protocol_accessor_multifile_other.swift > %t.ll
2-
// RUN: %FileCheck %s < %t.ll
2+
// RUN: %FileCheck %s -check-prefix CHECK -check-prefix CHECK-%target-runtime < %t.ll
33
// RUN: %FileCheck -check-prefix NEGATIVE %s < %t.ll
44

55
// CHECK: @"$s27protocol_accessor_multifile5ProtoMp" = external{{( dllimport)?}} global
@@ -28,7 +28,8 @@ class GenericContext<T: Proto> {
2828
// CHECK-LABEL: define{{.*}} void @"$s27protocol_accessor_multifile19useClassExistentialyyF"()
2929
func useClassExistential() {
3030
let g = getClassExistential()
31-
// CHECK: [[G_TYPE:%.+]] = call %swift.type* @swift_getObjectType({{%.+}} {{%.+}})
31+
// CHECK-objc: [[G_TYPE:%.+]] = call %swift.type* @swift_getObjectType({{%.+}} {{%.+}})
32+
// CHECK-native: [[G_TYPE:%.+]] = load %swift.type*
3233
// CHECK: call swiftcc void {{%.+}}(i{{32|64}} 1, {{%.+}} {{%.+}}, %swift.type* [[G_TYPE]], i8** {{%.+}})
3334
g?.baseProp = 1
3435
// CHECK: ret void

0 commit comments

Comments
 (0)