Skip to content

Commit da2730a

Browse files
committed
SIL: Update formal source type in SimplifyRefCasts when possible
We use the formal source type do decide whether a checked_cast_br is known to succeed/fail. If we don't update it we loose that optimization That is: ``` checked_cast_br AnyObject in %2 : X to X, bb1, bb2 ``` Will not be simplified even though the operand and the destintation type matches.
1 parent 8853d39 commit da2730a

File tree

8 files changed

+36
-5
lines changed

8 files changed

+36
-5
lines changed

SwiftCompilerSources/Sources/Optimizer/InstructionSimplification/SimplifyRefCasts.swift

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,8 @@ private extension UnaryInstruction {
6969
let canEraseInst = singleUse?.instruction == self
7070
let replacement = inst.operands[0].value
7171

72+
let oldOperandType = operand.value.type
73+
7274
if parentFunction.hasOwnership {
7375
if !canEraseInst && replacement.ownership == .owned {
7476
// We cannot add more uses to `replacement` without inserting a copy.
@@ -86,6 +88,15 @@ private extension UnaryInstruction {
8688
operand.set(to: replacement, context)
8789
}
8890

91+
if let ccb = self as? CheckedCastBranchInst {
92+
// Make sure that loosing the formal source type is harmless (i.e the
93+
// formal source type lowered equaled the operand SIL type before
94+
// transformation).
95+
let formalSrcType = ccb.formalSrcType
96+
if formalSrcType.loweredType(in: parentFunction, maximallyAbstracted: false) == oldOperandType {
97+
ccb.updateSourceFormalTypeFromOperandLoweredType()
98+
}
99+
}
89100
if canEraseInst {
90101
context.erase(instructionIncludingDebugUses: inst)
91102
}

SwiftCompilerSources/Sources/SIL/Instruction.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1696,6 +1696,12 @@ final public class CheckedCastBranchInst : TermInst, UnaryInstruction {
16961696
public var source: Value { operand.value }
16971697
public var successBlock: BasicBlock { bridged.CheckedCastBranch_getSuccessBlock().block }
16981698
public var failureBlock: BasicBlock { bridged.CheckedCastBranch_getFailureBlock().block }
1699+
1700+
public var formalSrcType : CanonicalType { CanonicalType(bridged: bridged.CheckedCastBranch_getFormalSrcType()) }
1701+
1702+
public func updateSourceFormalTypeFromOperandLoweredType() {
1703+
bridged.CheckedCastBranch_updateSourceFormalTypeFromOperandLoweredType()
1704+
}
16991705
}
17001706

17011707
final public class CheckedCastAddrBranchInst : TermInst {

include/swift/SIL/SILBridging.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -808,8 +808,10 @@ struct BridgedInstruction {
808808
BRIDGED_INLINE void LoadInst_setOwnership(SwiftInt ownership) const;
809809
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedBasicBlock CheckedCastBranch_getSuccessBlock() const;
810810
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedBasicBlock CheckedCastBranch_getFailureBlock() const;
811+
BRIDGED_INLINE BridgedCanType CheckedCastBranch_getFormalSrcType() const;
811812
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedBasicBlock CheckedCastAddrBranch_getSuccessBlock() const;
812813
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedBasicBlock CheckedCastAddrBranch_getFailureBlock() const;
814+
BRIDGED_INLINE void CheckedCastBranch_updateSourceFormalTypeFromOperandLoweredType() const;
813815
BRIDGED_INLINE CastConsumptionKind CheckedCastAddrBranch_getConsumptionKind() const;
814816
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedSubstitutionMap ApplySite_getSubstitutionMap() const;
815817
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedCanType ApplySite_getSubstitutedCalleeType() const;

include/swift/SIL/SILBridgingImpl.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1504,6 +1504,10 @@ void BridgedInstruction::LoadInst_setOwnership(SwiftInt ownership) const {
15041504
getAs<swift::LoadInst>()->setOwnershipQualifier((swift::LoadOwnershipQualifier)ownership);
15051505
}
15061506

1507+
void BridgedInstruction::CheckedCastBranch_updateSourceFormalTypeFromOperandLoweredType() const {
1508+
getAs<swift::CheckedCastBranchInst>()->updateSourceFormalTypeFromOperandLoweredType();
1509+
}
1510+
15071511
BridgedBasicBlock BridgedInstruction::CheckedCastBranch_getSuccessBlock() const {
15081512
return {getAs<swift::CheckedCastBranchInst>()->getSuccessBB()};
15091513
}
@@ -1512,6 +1516,10 @@ BridgedBasicBlock BridgedInstruction::CheckedCastBranch_getFailureBlock() const
15121516
return {getAs<swift::CheckedCastBranchInst>()->getFailureBB()};
15131517
}
15141518

1519+
BridgedCanType BridgedInstruction::CheckedCastBranch_getFormalSrcType() const {
1520+
return {getAs<swift::CheckedCastBranchInst>()->getSourceFormalType()};
1521+
}
1522+
15151523
BridgedBasicBlock BridgedInstruction::CheckedCastAddrBranch_getSuccessBlock() const {
15161524
return {getAs<swift::CheckedCastAddrBranchInst>()->getSuccessBB()};
15171525
}

include/swift/SIL/SILInstruction.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11032,6 +11032,10 @@ class CheckedCastBranchInst final
1103211032
SILType getSourceLoweredType() const { return getOperand()->getType(); }
1103311033
CanType getSourceFormalType() const { return SrcFormalTy; }
1103411034

11035+
void updateSourceFormalTypeFromOperandLoweredType() {
11036+
SrcFormalTy = getSourceLoweredType().getASTType();
11037+
}
11038+
1103511039
SILType getTargetLoweredType() const { return DestLoweredTy; }
1103611040
CanType getTargetFormalType() const { return DestFormalTy; }
1103711041
};

test/DebugInfo/simplify_checked_cast_br.sil

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ class X : B {}
1111

1212
// CHECK-LABEL: sil [ossa] @test_ossa :
1313
// CHECK: %0 = alloc_ref
14-
// CHECK-NEXT: checked_cast_br AnyObject in %0 : $X
14+
// CHECK-NEXT: checked_cast_br X in %0 : $X
1515
// CHECK: bb2([[A:%.*]] : @owned $X):
1616
// CHECK-NEXT: [[U:%.*]] = upcast [[A]] : $X to $B, loc "takethis":1:1
1717
// CHECK-NEXT: [[E:%.*]] = init_existential_ref [[U]] {{.+}}, loc "takethis":1:1

test/SILOptimizer/devirt_covariant_return.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,7 @@ public class D2: D1 {
235235
// that D2.foo() is inlined thanks to this.
236236
// CHECK-LABEL: sil hidden [noinline] @$s23devirt_covariant_return7driver2ys5Int32VAA2D2CF
237237
// CHECK-NOT: class_method
238-
// CHECK: checked_cast_br [exact] D1 in
238+
// CHECK: checked_cast_br [exact] D2 in
239239
// CHECK: bb2
240240
// CHECK: global_addr
241241
// CHECK: load

test/SILOptimizer/simplify_checked_cast_br.sil

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ class X : B {}
1212

1313
// CHECK-LABEL: sil @test_non_ossa :
1414
// CHECK: %0 = alloc_ref
15-
// CHECK: checked_cast_br AnyObject in %0 : $X
15+
// CHECK: checked_cast_br X in %0 : $X
1616
// CHECK: } // end sil function 'test_non_ossa'
1717
sil @test_non_ossa : $@convention(thin) () -> AnyObject {
1818
bb0:
@@ -31,7 +31,7 @@ bb2:
3131

3232
// CHECK-LABEL: sil [ossa] @test_ossa :
3333
// CHECK: %0 = alloc_ref
34-
// CHECK-O-NEXT: checked_cast_br AnyObject in %0 : $X
34+
// CHECK-O-NEXT: checked_cast_br X in %0 : $X
3535
// CHECK-ONONE: checked_cast_br AnyObject in %2 : $AnyObject
3636
// CHECK-O: bb2([[A:%.*]] : @owned $X):
3737
// CHECK-O-NEXT: [[U:%.*]] = upcast [[A]] : $X to $B
@@ -75,7 +75,7 @@ bb2(%7 : @owned $B):
7575

7676
// CHECK-LABEL: sil [ossa] @test_borrow :
7777
// CHECK: %1 = begin_borrow
78-
// CHECK-NEXT: checked_cast_br any P in %1 : $X
78+
// CHECK-NEXT: checked_cast_br X in %1 : $X
7979
// CHECK: bb2([[A:%.*]] : @guaranteed $X):
8080
// CHECK-NEXT: [[U:%.*]] = upcast [[A]] : $X to $B
8181
// CHECK-NEXT: [[E:%.*]] = init_existential_ref [[U]] : $B

0 commit comments

Comments
 (0)