diff --git a/SwiftCompilerSources/Sources/Optimizer/InstructionSimplification/SimplifyRefCasts.swift b/SwiftCompilerSources/Sources/Optimizer/InstructionSimplification/SimplifyRefCasts.swift index dd23c8919b1cb..529b4484eff59 100644 --- a/SwiftCompilerSources/Sources/Optimizer/InstructionSimplification/SimplifyRefCasts.swift +++ b/SwiftCompilerSources/Sources/Optimizer/InstructionSimplification/SimplifyRefCasts.swift @@ -86,6 +86,13 @@ private extension UnaryInstruction { operand.set(to: replacement, context) } + if let ccb = self as? CheckedCastBranchInst { + // Make sure that updating the formal type with the operand type is + // legal. + if operand.value.type.isLegalFormalType { + ccb.updateSourceFormalTypeFromOperandLoweredType() + } + } if canEraseInst { context.erase(instructionIncludingDebugUses: inst) } diff --git a/SwiftCompilerSources/Sources/SIL/Instruction.swift b/SwiftCompilerSources/Sources/SIL/Instruction.swift index 27ee0fe53ba9d..857d4f63912fa 100644 --- a/SwiftCompilerSources/Sources/SIL/Instruction.swift +++ b/SwiftCompilerSources/Sources/SIL/Instruction.swift @@ -1696,6 +1696,10 @@ final public class CheckedCastBranchInst : TermInst, UnaryInstruction { public var source: Value { operand.value } public var successBlock: BasicBlock { bridged.CheckedCastBranch_getSuccessBlock().block } public var failureBlock: BasicBlock { bridged.CheckedCastBranch_getFailureBlock().block } + + public func updateSourceFormalTypeFromOperandLoweredType() { + bridged.CheckedCastBranch_updateSourceFormalTypeFromOperandLoweredType() + } } final public class CheckedCastAddrBranchInst : TermInst { diff --git a/SwiftCompilerSources/Sources/SIL/Type.swift b/SwiftCompilerSources/Sources/SIL/Type.swift index 09173a5051806..0576e5087e4b1 100644 --- a/SwiftCompilerSources/Sources/SIL/Type.swift +++ b/SwiftCompilerSources/Sources/SIL/Type.swift @@ -104,6 +104,8 @@ public struct Type : CustomStringConvertible, NoReflectionChildren { public var isBuiltinVector: Bool { bridged.isBuiltinVector() } public var builtinVectorElementType: Type { bridged.getBuiltinVectorElementType().type } + public var isLegalFormalType: Bool { bridged.isLegalFormalType() } + public func isBuiltinInteger(withFixedWidth width: Int) -> Bool { bridged.isBuiltinFixedWidthInteger(width) } diff --git a/include/swift/SIL/SILBridging.h b/include/swift/SIL/SILBridging.h index 4dfe6e9b3694f..2b4e46824335e 100644 --- a/include/swift/SIL/SILBridging.h +++ b/include/swift/SIL/SILBridging.h @@ -277,6 +277,7 @@ struct BridgedType { BRIDGED_INLINE bool isBuiltinInteger() const; BRIDGED_INLINE bool isBuiltinFloat() const; BRIDGED_INLINE bool isBuiltinVector() const; + BRIDGED_INLINE bool isLegalFormalType() const; SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedType getBuiltinVectorElementType() const; BRIDGED_INLINE bool isBuiltinFixedWidthInteger(SwiftInt width) const; BRIDGED_INLINE bool isExactSuperclassOf(BridgedType t) const; @@ -810,6 +811,7 @@ struct BridgedInstruction { SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedBasicBlock CheckedCastBranch_getFailureBlock() const; SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedBasicBlock CheckedCastAddrBranch_getSuccessBlock() const; SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedBasicBlock CheckedCastAddrBranch_getFailureBlock() const; + BRIDGED_INLINE void CheckedCastBranch_updateSourceFormalTypeFromOperandLoweredType() const; BRIDGED_INLINE CastConsumptionKind CheckedCastAddrBranch_getConsumptionKind() const; SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedSubstitutionMap ApplySite_getSubstitutionMap() const; SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedCanType ApplySite_getSubstitutedCalleeType() const; diff --git a/include/swift/SIL/SILBridgingImpl.h b/include/swift/SIL/SILBridgingImpl.h index cf45905555d9e..890034333f3d3 100644 --- a/include/swift/SIL/SILBridgingImpl.h +++ b/include/swift/SIL/SILBridgingImpl.h @@ -445,6 +445,10 @@ bool BridgedType::isBuiltinVector() const { return unbridged().isBuiltinVector(); } +bool BridgedType::isLegalFormalType() const { + return unbridged().getASTType()->isLegalFormalType(); +} + BridgedType BridgedType::getBuiltinVectorElementType() const { return unbridged().getBuiltinVectorElementType(); } @@ -1504,6 +1508,10 @@ void BridgedInstruction::LoadInst_setOwnership(SwiftInt ownership) const { getAs()->setOwnershipQualifier((swift::LoadOwnershipQualifier)ownership); } +void BridgedInstruction::CheckedCastBranch_updateSourceFormalTypeFromOperandLoweredType() const { + getAs()->updateSourceFormalTypeFromOperandLoweredType(); +} + BridgedBasicBlock BridgedInstruction::CheckedCastBranch_getSuccessBlock() const { return {getAs()->getSuccessBB()}; } diff --git a/include/swift/SIL/SILInstruction.h b/include/swift/SIL/SILInstruction.h index bddf29c364698..3d177ad9aa643 100644 --- a/include/swift/SIL/SILInstruction.h +++ b/include/swift/SIL/SILInstruction.h @@ -11032,6 +11032,10 @@ class CheckedCastBranchInst final SILType getSourceLoweredType() const { return getOperand()->getType(); } CanType getSourceFormalType() const { return SrcFormalTy; } + void updateSourceFormalTypeFromOperandLoweredType() { + SrcFormalTy = getSourceLoweredType().getASTType(); + } + SILType getTargetLoweredType() const { return DestLoweredTy; } CanType getTargetFormalType() const { return DestFormalTy; } }; diff --git a/test/DebugInfo/simplify_checked_cast_br.sil b/test/DebugInfo/simplify_checked_cast_br.sil index 2fa1ba9c87636..89cd3ad2dfc02 100644 --- a/test/DebugInfo/simplify_checked_cast_br.sil +++ b/test/DebugInfo/simplify_checked_cast_br.sil @@ -11,7 +11,7 @@ class X : B {} // CHECK-LABEL: sil [ossa] @test_ossa : // CHECK: %0 = alloc_ref -// CHECK-NEXT: checked_cast_br AnyObject in %0 : $X +// CHECK-NEXT: checked_cast_br X in %0 : $X // CHECK: bb2([[A:%.*]] : @owned $X): // CHECK-NEXT: [[U:%.*]] = upcast [[A]] : $X to $B, loc "takethis":1:1 // CHECK-NEXT: [[E:%.*]] = init_existential_ref [[U]] {{.+}}, loc "takethis":1:1 diff --git a/test/SILOptimizer/devirt_covariant_return.swift b/test/SILOptimizer/devirt_covariant_return.swift index 18374cde03569..1deee904801c3 100644 --- a/test/SILOptimizer/devirt_covariant_return.swift +++ b/test/SILOptimizer/devirt_covariant_return.swift @@ -235,7 +235,7 @@ public class D2: D1 { // that D2.foo() is inlined thanks to this. // CHECK-LABEL: sil hidden [noinline] @$s23devirt_covariant_return7driver2ys5Int32VAA2D2CF // CHECK-NOT: class_method -// CHECK: checked_cast_br [exact] D1 in +// CHECK: checked_cast_br [exact] D2 in // CHECK: bb2 // CHECK: global_addr // CHECK: load diff --git a/test/SILOptimizer/simplify_checked_cast_br.sil b/test/SILOptimizer/simplify_checked_cast_br.sil index 71f29ef11fe31..5b36431d1ef26 100644 --- a/test/SILOptimizer/simplify_checked_cast_br.sil +++ b/test/SILOptimizer/simplify_checked_cast_br.sil @@ -12,7 +12,7 @@ class X : B {} // CHECK-LABEL: sil @test_non_ossa : // CHECK: %0 = alloc_ref -// CHECK: checked_cast_br AnyObject in %0 : $X +// CHECK: checked_cast_br X in %0 : $X // CHECK: } // end sil function 'test_non_ossa' sil @test_non_ossa : $@convention(thin) () -> AnyObject { bb0: @@ -31,7 +31,7 @@ bb2: // CHECK-LABEL: sil [ossa] @test_ossa : // CHECK: %0 = alloc_ref -// CHECK-O-NEXT: checked_cast_br AnyObject in %0 : $X +// CHECK-O-NEXT: checked_cast_br X in %0 : $X // CHECK-ONONE: checked_cast_br AnyObject in %2 : $AnyObject // CHECK-O: bb2([[A:%.*]] : @owned $X): // CHECK-O-NEXT: [[U:%.*]] = upcast [[A]] : $X to $B @@ -75,7 +75,7 @@ bb2(%7 : @owned $B): // CHECK-LABEL: sil [ossa] @test_borrow : // CHECK: %1 = begin_borrow -// CHECK-NEXT: checked_cast_br any P in %1 : $X +// CHECK-NEXT: checked_cast_br X in %1 : $X // CHECK: bb2([[A:%.*]] : @guaranteed $X): // CHECK-NEXT: [[U:%.*]] = upcast [[A]] : $X to $B // CHECK-NEXT: [[E:%.*]] = init_existential_ref [[U]] : $B