Skip to content

Commit 2d7e6bf

Browse files
authored
Fix CastOptimizer for guaranteed values while handling checked_cast_br (#37800)
Fixes rdar://77684045. The rdar is about a SILVerifier assert for SIL created by cast optimizer, where a guaranteed op of checked_cast_br iis transformed to an op of a phi argument without creating borrow scope. Fix: During cast optimization, when the direction of checked_cast_br can be determined statically, replace the success/failure value in the destination block and create an unconditional branch to the destination block. This is done only in OSSA, since we ban critical edges.
1 parent 970c030 commit 2d7e6bf

File tree

3 files changed

+119
-7
lines changed

3 files changed

+119
-7
lines changed

Diff for: lib/SILOptimizer/Utils/CastOptimizer.cpp

+21-5
Original file line numberDiff line numberDiff line change
@@ -1004,6 +1004,7 @@ CastOptimizer::simplifyCheckedCastBranchInst(CheckedCastBranchInst *Inst) {
10041004
auto TargetFormalType = dynamicCast.getTargetFormalType();
10051005
auto Loc = dynamicCast.getLocation();
10061006
auto *SuccessBB = dynamicCast.getSuccessBlock();
1007+
auto *FailureBB = dynamicCast.getFailureBlock();
10071008
auto Op = dynamicCast.getSource();
10081009
auto *F = dynamicCast.getFunction();
10091010

@@ -1016,10 +1017,13 @@ CastOptimizer::simplifyCheckedCastBranchInst(CheckedCastBranchInst *Inst) {
10161017

10171018
SILBuilderWithScope Builder(Inst, builderContext);
10181019
if (Feasibility == DynamicCastFeasibility::WillFail) {
1019-
TinyPtrVector<SILValue> Args;
1020-
if (Builder.hasOwnership())
1021-
Args.push_back(Inst->getOperand());
1022-
auto *NewI = Builder.createBranch(Loc, dynamicCast.getFailureBlock(), Args);
1020+
auto *NewI = Builder.createBranch(Loc, FailureBB);
1021+
if (Builder.hasOwnership()) {
1022+
FailureBB->getArgument(0)->replaceAllUsesWith(Op);
1023+
FailureBB->eraseArgument(0);
1024+
SuccessBB->getArgument(0)->replaceAllUsesWithUndef();
1025+
SuccessBB->eraseArgument(0);
1026+
}
10231027
eraseInstAction(Inst);
10241028
willFailAction();
10251029
return NewI;
@@ -1063,7 +1067,19 @@ CastOptimizer::simplifyCheckedCastBranchInst(CheckedCastBranchInst *Inst) {
10631067
CastedValue = Op;
10641068
}
10651069

1066-
auto *NewI = Builder.createBranch(Loc, SuccessBB, CastedValue);
1070+
BranchInst *NewI = nullptr;
1071+
1072+
if (Builder.hasOwnership()) {
1073+
NewI = Builder.createBranch(Loc, SuccessBB);
1074+
SuccessBB->getArgument(0)->replaceAllUsesWith(CastedValue);
1075+
SuccessBB->eraseArgument(0);
1076+
FailureBB->getArgument(0)->replaceAllUsesWithUndef();
1077+
FailureBB->eraseArgument(0);
1078+
}
1079+
else {
1080+
NewI = Builder.createBranch(Loc, SuccessBB, CastedValue);
1081+
}
1082+
10671083
eraseInstAction(Inst);
10681084
willSucceedAction();
10691085
return NewI;
+96
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
// RUN: %target-sil-opt -enable-sil-verify-all %s -diagnostic-constant-propagation | %FileCheck %s
2+
sil_stage canonical
3+
4+
//import Swift
5+
6+
class Klass {
7+
}
8+
9+
class SubKlass : Klass {
10+
}
11+
12+
class NoSubKlass {
13+
}
14+
15+
sil [noinline] @blackhole1 : $@convention(thin) (@guaranteed SubKlass) -> ()
16+
sil [noinline] @blackhole2 : $@convention(thin) (@guaranteed NoSubKlass) -> ()
17+
18+
// CHECK-LABEL: sil [ossa] @test_guaranteed_cast_opt1 :
19+
// CHECK-NOT: checked_cast_br
20+
// CHECK: upcast
21+
// CHECK-LABEL: } // end sil function 'test_guaranteed_cast_opt1'
22+
sil [ossa] @test_guaranteed_cast_opt1 : $@convention(thin) (@owned SubKlass) -> () {
23+
bb0(%0 : @owned $SubKlass):
24+
%borrow = begin_borrow %0 : $SubKlass
25+
checked_cast_br %borrow : $SubKlass to Klass, bb1, bb2
26+
27+
bb1(%val1 : @guaranteed $Klass):
28+
%copy = copy_value %val1: $Klass
29+
end_borrow %borrow : $SubKlass
30+
destroy_value %copy : $Klass
31+
br bb3
32+
33+
bb2(%val2 : @guaranteed $SubKlass):
34+
end_borrow %borrow : $SubKlass
35+
br bb3
36+
37+
bb3:
38+
destroy_value %0 : $SubKlass
39+
%r = tuple ()
40+
return %r : $()
41+
}
42+
43+
// CHECK-LABEL: sil [ossa] @test_guaranteed_cast_opt2 :
44+
// CHECK-NOT: checked_cast_br
45+
// CHECK: upcast
46+
// CHECK-LABEL: } // end sil function 'test_guaranteed_cast_opt2'
47+
sil [ossa] @test_guaranteed_cast_opt2 : $@convention(thin) (@owned SubKlass) -> () {
48+
bb0(%0 : @owned $SubKlass):
49+
%borrow = begin_borrow %0 : $SubKlass
50+
checked_cast_br %borrow : $SubKlass to Klass, bb1, bb2
51+
52+
bb1(%val1 : @guaranteed $Klass):
53+
%copy = copy_value %val1: $Klass
54+
end_borrow %borrow : $SubKlass
55+
destroy_value %copy : $Klass
56+
br bb3
57+
58+
bb2(%val2 : @guaranteed $SubKlass):
59+
%func = function_ref @blackhole1 : $@convention(thin) (@guaranteed SubKlass) -> ()
60+
apply %func(%val2) : $@convention(thin) (@guaranteed SubKlass) -> ()
61+
end_borrow %borrow : $SubKlass
62+
br bb3
63+
64+
bb3:
65+
destroy_value %0 : $SubKlass
66+
%r = tuple ()
67+
return %r : $()
68+
}
69+
70+
// CHECK-LABEL: sil [ossa] @test_guaranteed_cast_opt3 :
71+
// CHECK-NOT: checked_cast_br
72+
// CHECK: br bb2
73+
// CHECK-LABEL: } // end sil function 'test_guaranteed_cast_opt3'
74+
sil [ossa] @test_guaranteed_cast_opt3 : $@convention(thin) (@owned NoSubKlass) -> () {
75+
bb0(%0 : @owned $NoSubKlass):
76+
%borrow = begin_borrow %0 : $NoSubKlass
77+
checked_cast_br %borrow : $NoSubKlass to Klass, bb1, bb2
78+
79+
bb1(%val1 : @guaranteed $Klass):
80+
%copy = copy_value %val1: $Klass
81+
end_borrow %borrow : $NoSubKlass
82+
destroy_value %copy : $Klass
83+
br bb3
84+
85+
bb2(%val2 : @guaranteed $NoSubKlass):
86+
%func = function_ref @blackhole2 : $@convention(thin) (@guaranteed NoSubKlass) -> ()
87+
apply %func(%val2) : $@convention(thin) (@guaranteed NoSubKlass) -> ()
88+
end_borrow %borrow : $NoSubKlass
89+
br bb3
90+
91+
bb3:
92+
destroy_value %0 : $NoSubKlass
93+
%r = tuple ()
94+
return %r : $()
95+
}
96+

Diff for: test/SILOptimizer/constant_propagation_ownership.sil

+2-2
Original file line numberDiff line numberDiff line change
@@ -1108,7 +1108,7 @@ bb0(%0 : $*Error, %1 : $*E1):
11081108
// CHECK-LABEL: sil [ossa] @always_fail_protocolmeta_to_concretemeta_checkedcastbr : $@convention(thin) (@thin P.Protocol) -> Builtin.Int1 {
11091109
// CHECK: bb0(
11101110
// CHECK-NEXT: metatype
1111-
// CHECK-NEXT: br bb2(
1111+
// CHECK-NEXT: br bb2
11121112
// CHECK: } // end sil function 'always_fail_protocolmeta_to_concretemeta_checkedcastbr'
11131113
sil [ossa] @always_fail_protocolmeta_to_concretemeta_checkedcastbr : $@convention(thin) (@thin P.Protocol) -> Builtin.Int1 {
11141114
bb0(%0 : $@thin P.Protocol):
@@ -1131,7 +1131,7 @@ bb3(%11 : $Builtin.Int1):
11311131
// CHECK-LABEL: sil [ossa] @always_succeed_subtoparent : $@convention(thin) (@owned AnSubObject) -> Builtin.Int1 {
11321132
// CHECK: bb0(
11331133
// CHECK-NEXT: upcast
1134-
// CHECK-NEXT: br bb1(
1134+
// CHECK-NEXT: br bb1
11351135
// CHECK: } // end sil function 'always_succeed_subtoparent'
11361136
sil [ossa] @always_succeed_subtoparent : $@convention(thin) (@owned AnSubObject) -> Builtin.Int1 {
11371137
bb0(%0 : @owned $AnSubObject):

0 commit comments

Comments
 (0)