diff --git a/SwiftCompilerSources/Sources/AST/Declarations.swift b/SwiftCompilerSources/Sources/AST/Declarations.swift index a17efcf158111..f93914485f433 100644 --- a/SwiftCompilerSources/Sources/AST/Declarations.swift +++ b/SwiftCompilerSources/Sources/AST/Declarations.swift @@ -58,7 +58,9 @@ public class NominalTypeDecl: GenericTypeDecl { } } -final public class EnumDecl: NominalTypeDecl {} +final public class EnumDecl: NominalTypeDecl { + public var hasRawType: Bool { bridged.Enum_hasRawType() } +} final public class StructDecl: NominalTypeDecl { public var hasUnreferenceableStorage: Bool { bridged.Struct_hasUnreferenceableStorage() } diff --git a/SwiftCompilerSources/Sources/Optimizer/InstructionSimplification/SimplifyApply.swift b/SwiftCompilerSources/Sources/Optimizer/InstructionSimplification/SimplifyApply.swift index cc36c2ddd8499..126fac51cb2e9 100644 --- a/SwiftCompilerSources/Sources/Optimizer/InstructionSimplification/SimplifyApply.swift +++ b/SwiftCompilerSources/Sources/Optimizer/InstructionSimplification/SimplifyApply.swift @@ -135,6 +135,7 @@ private func tryOptimizeEnumComparison(apply: ApplyInst, _ context: SimplifyCont let lhs = apply.arguments[0] let rhs = apply.arguments[1] guard let enumDecl = lhs.type.nominal as? EnumDecl, + enumDecl.hasRawType, !enumDecl.isResilient(in: apply.parentFunction), !enumDecl.hasClangNode, lhs.type.isAddress, diff --git a/include/swift/AST/ASTBridging.h b/include/swift/AST/ASTBridging.h index d0369de09aafb..2bb8a5cf1d5e1 100644 --- a/include/swift/AST/ASTBridging.h +++ b/include/swift/AST/ASTBridging.h @@ -402,6 +402,7 @@ struct BridgedDeclObj { BRIDGED_INLINE bool GenericType_isGenericAtAnyLevel() const; BRIDGED_INLINE bool NominalType_isGlobalActor() const; SWIFT_IMPORT_UNSAFE BRIDGED_INLINE OptionalBridgedDeclObj NominalType_getValueTypeDestructor() const; + BRIDGED_INLINE bool Enum_hasRawType() const; BRIDGED_INLINE bool Struct_hasUnreferenceableStorage() const; SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedASTType Class_getSuperclass() const; SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedDeclObj Class_getDestructor() const; diff --git a/include/swift/AST/ASTBridgingImpl.h b/include/swift/AST/ASTBridgingImpl.h index ee23798b0de70..da57250f2f8ef 100644 --- a/include/swift/AST/ASTBridgingImpl.h +++ b/include/swift/AST/ASTBridgingImpl.h @@ -221,6 +221,10 @@ OptionalBridgedDeclObj BridgedDeclObj::NominalType_getValueTypeDestructor() cons return {getAs()->getValueTypeDestructor()}; } +bool BridgedDeclObj::Enum_hasRawType() const { + return getAs()->hasRawType(); +} + bool BridgedDeclObj::Struct_hasUnreferenceableStorage() const { return getAs()->hasUnreferenceableStorage(); } diff --git a/test/SILOptimizer/enum-comparison.swift b/test/SILOptimizer/enum-comparison.swift index e5f9d0734476e..641f4ecc3e6c0 100644 --- a/test/SILOptimizer/enum-comparison.swift +++ b/test/SILOptimizer/enum-comparison.swift @@ -80,6 +80,28 @@ func compare4(_ x: LargeEnum) -> Bool { return x == .e3(28) } +enum CustomRawValue: RawRepresentable { + case a, b, c + + init(rawValue: Int) { + self = .a + } + + @inline(never) + var rawValue: Int { + print(0) + return 0 + } +} + +// CHECK-LABEL: define {{.*}} i1 @"$s4test8compare5ySbAA14CustomRawValueOF"(i8 %0) +// CHECK: entry: +// CHECK-NEXT: call +@inline(never) +func compare5(_ x: CustomRawValue) -> Bool { + return x == .b +} + // OUT: 1: false print("1: \(compareeq(.c, .long_case_name_for_testing))") @@ -116,3 +138,6 @@ print("11: \(compare4(.e3(28)))") // OUT: 12: false print("12: \(compare4(.e3(27)))") +// OUT: 13: true +print("13: \(compare5(.a))") +