diff --git a/SwiftCompilerSources/Sources/Optimizer/InstructionSimplification/SimplifyBuiltin.swift b/SwiftCompilerSources/Sources/Optimizer/InstructionSimplification/SimplifyBuiltin.swift index 2c60d7055df90..72fd794bf2874 100644 --- a/SwiftCompilerSources/Sources/Optimizer/InstructionSimplification/SimplifyBuiltin.swift +++ b/SwiftCompilerSources/Sources/Optimizer/InstructionSimplification/SimplifyBuiltin.swift @@ -184,8 +184,13 @@ private func typesOfValuesAreEqual(_ lhs: Value, _ rhs: Value, in function: Func return nil } - let lhsTy = lhsExistential.metatype.type.instanceTypeOfMetatype(in: function) - let rhsTy = rhsExistential.metatype.type.instanceTypeOfMetatype(in: function) + let lhsMetatype = lhsExistential.metatype.type + let rhsMetatype = rhsExistential.metatype.type + if lhsMetatype.isDynamicSelfMetatype != rhsMetatype.isDynamicSelfMetatype { + return nil + } + let lhsTy = lhsMetatype.instanceTypeOfMetatype(in: function) + let rhsTy = rhsMetatype.instanceTypeOfMetatype(in: function) // Do we know the exact types? This is not the case e.g. if a type is passed as metatype // to the function. diff --git a/SwiftCompilerSources/Sources/SIL/Type.swift b/SwiftCompilerSources/Sources/SIL/Type.swift index c7fdca56ee76d..89dd4523db1db 100644 --- a/SwiftCompilerSources/Sources/SIL/Type.swift +++ b/SwiftCompilerSources/Sources/SIL/Type.swift @@ -90,6 +90,10 @@ public struct Type : CustomStringConvertible, NoReflectionChildren { bridged.getInstanceTypeOfMetatype(function.bridged.getFunction()).type } + public var isDynamicSelfMetatype: Bool { + bridged.isDynamicSelfMetatype() + } + public var isCalleeConsumedFunction: Bool { bridged.isCalleeConsumedFunction() } public var isMarkedAsImmortal: Bool { bridged.isMarkedAsImmortal() } diff --git a/include/swift/SIL/SILType.h b/include/swift/SIL/SILType.h index 9b13df04d1416..ba179061b0d3f 100644 --- a/include/swift/SIL/SILType.h +++ b/include/swift/SIL/SILType.h @@ -508,6 +508,12 @@ class SILType { return isObject() && isClassOrClassMetatype(getASTType()); } + bool isDynamicSelfMetatype() const { + auto metaType = castTo(); + Type instTy = metaType->getInstanceType(); + return instTy->is(); + } + bool isFunctionTypeWithContext() const { if (auto *fTy = getASTType()->getAs()) { return fTy->getExtInfo().hasContext(); diff --git a/test/SILOptimizer/simplify_builtin.sil b/test/SILOptimizer/simplify_builtin.sil index 7192a1d0e0be9..2c713657a89aa 100644 --- a/test/SILOptimizer/simplify_builtin.sil +++ b/test/SILOptimizer/simplify_builtin.sil @@ -26,6 +26,9 @@ class C1 { class C2 : C1 { } +class A { +} + // CHECK-LABEL: sil @constantFoldAdd // CHECK: [[A:%.*]] = integer_literal $Builtin.Int64, 12 // CHECK: [[C:%.*]] = integer_literal $Builtin.Int1, 0 @@ -267,6 +270,34 @@ bb0: return %4 : $Builtin.Int1 } +// CHECK-LABEL: sil @same_metatype_dynamic_self +// CHECK: [[R:%.*]] = integer_literal $Builtin.Int1, -1 +// CHECK-NEXT: return [[R]] +// CHECK: } // end sil function 'same_metatype_dynamic_self' +sil @same_metatype_dynamic_self : $@convention(method) (@guaranteed A) -> Builtin.Int1 { +bb0(%0 : $A): + %2 = metatype $@thick @dynamic_self A.Type + %3 = init_existential_metatype %2 : $@thick @dynamic_self A.Type, $@thick any Any.Type + %5 = metatype $@thick @dynamic_self A.Type + %6 = init_existential_metatype %5 : $@thick @dynamic_self A.Type, $@thick any Any.Type + %13 = builtin "is_same_metatype"(%3 : $@thick any Any.Type, %6 : $@thick any Any.Type) : $Builtin.Int1 + return %13 : $Builtin.Int1 +} + +// CHECK-LABEL: sil @unknown_same_metatype_dynamic_self +// CHECK: [[R:%.*]] = builtin "is_same_metatype" +// CHECK: return [[R]] +// CHECK: } // end sil function 'unknown_same_metatype_dynamic_self' +sil @unknown_same_metatype_dynamic_self : $@convention(method) (@guaranteed A) -> Builtin.Int1 { +bb0(%0 : $A): + %2 = metatype $@thick @dynamic_self A.Type + %3 = init_existential_metatype %2 : $@thick @dynamic_self A.Type, $@thick any Any.Type + %5 = metatype $@thick A.Type + %6 = init_existential_metatype %5 : $@thick A.Type, $@thick any Any.Type + %13 = builtin "is_same_metatype"(%3 : $@thick any Any.Type, %6 : $@thick any Any.Type) : $Builtin.Int1 + return %13 : $Builtin.Int1 +} + sil_global hidden [let] @g : $Int32 sil [global_init_once_fn] @side_effect_free_init : $@convention(c) () -> () {