Skip to content

Commit e8be44d

Browse files
Merge pull request #64324 from AnthonyLatsis/cse-open-exist
SILOptimizer: Fix some issues with CSE of `open_existential_ref`
2 parents c8a02cc + d650ce4 commit e8be44d

File tree

3 files changed

+184
-17
lines changed

3 files changed

+184
-17
lines changed

lib/SILOptimizer/Transforms/CSE.cpp

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -892,23 +892,9 @@ bool CSE::processOpenExistentialRef(OpenExistentialRefInst *Inst,
892892
return false;
893893
}
894894
}
895-
Candidates.insert(User);
896-
}
897-
if (!isa<TermInst>(User))
898-
continue;
899-
// The current use of the opened archetype is a terminator instruction.
900-
// Check if any of the successor BBs uses this opened archetype in the
901-
// types of its basic block arguments. If this is the case, replace
902-
// those uses by the new opened archetype.
903-
auto Successors = User->getParent()->getSuccessorBlocks();
904-
for (auto Successor : Successors) {
905-
if (Successor->args_empty())
906-
continue;
907-
// If a BB has any arguments, update their types if necessary.
908-
updateBasicBlockArgTypes(Successor,
909-
OldOpenedArchetype,
910-
NewOpenedArchetype);
911895
}
896+
897+
Candidates.insert(User);
912898
}
913899

914900
// Now process candidates.
@@ -927,6 +913,21 @@ bool CSE::processOpenExistentialRef(OpenExistentialRefInst *Inst,
927913
if (Processed.contains(Candidate))
928914
continue;
929915

916+
if (isa<TermInst>(Candidate)) {
917+
// The current use of the opened archetype is a terminator instruction.
918+
// Check if any of the successor BBs uses this opened archetype in the
919+
// types of its basic block arguments. If this is the case, replace
920+
// those uses by the new opened archetype.
921+
// FIXME: What about uses of those arguments?
922+
for (auto *Successor : Candidate->getParent()->getSuccessorBlocks()) {
923+
if (Successor->args_empty())
924+
continue;
925+
// If a BB has any arguments, update their types if necessary.
926+
updateBasicBlockArgTypes(Successor, OldOpenedArchetype,
927+
NewOpenedArchetype);
928+
}
929+
}
930+
930931
// Compute if a candidate depends on the old opened archetype.
931932
// It always does if it has any type-dependent operands.
932933
bool DependsOnOldOpenedArchetype =
@@ -947,7 +948,7 @@ bool CSE::processOpenExistentialRef(OpenExistentialRefInst *Inst,
947948

948949
// If it does, the candidate depends on the opened existential.
949950
if (ResultDependsOnOldOpenedArchetype) {
950-
DependsOnOldOpenedArchetype |= ResultDependsOnOldOpenedArchetype;
951+
DependsOnOldOpenedArchetype = true;
951952

952953
// The users of this candidate are new candidates.
953954
for (auto Use : CandidateResult->getUses()) {
Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
// RUN: %target-sil-opt -enable-sil-verify-all %s -cse -o %t.sil
2+
// RUN: %FileCheck %s -check-prefix=CHECK_ID < %t.sil
3+
// RUN: %FileCheck %s -check-prefix=CHECK_OPT < %t.sil
4+
5+
import Builtin
6+
import Swift
7+
8+
class Class {}
9+
10+
protocol P : Class {}
11+
12+
sil @blackhole : $@convention(thin) <T> (@guaranteed T) -> ()
13+
14+
// CHECK-LABEL: sil @test_direct_use_with_dependent_result
15+
// CHECK_ID-NOT: 00000000-0000-0000-0000-000000000002
16+
// CHECK_OPT: bb0(
17+
// CHECK_OPT-NEXT: // function_ref
18+
// CHECK_OPT-NEXT: function_ref @blackhole
19+
// CHECK_OPT-NEXT: open_existential_ref
20+
// CHECK_OPT-NEXT: apply
21+
// CHECK_OPT-NEXT: enum
22+
// CHECK_OPT-NEXT: apply
23+
// CHECK_OPT-NEXT: tuple
24+
// CHECK_OPT-NEXT: return
25+
// CHECK: } // end sil function 'test_direct_use_with_dependent_result'
26+
sil @test_direct_use_with_dependent_result : $@convention(thin) (@guaranteed any P) -> () {
27+
bb0(%p : $any P):
28+
%blackhole = function_ref @blackhole : $@convention(thin) <τ_0_0> (@guaranteed τ_0_0) -> ()
29+
30+
%opened1 = open_existential_ref %p : $any P to $@opened("00000000-0000-0000-0000-000000000001", any P) Self
31+
// Don't let the first opened existential get optimized away.
32+
%void1 = apply %blackhole<@opened("00000000-0000-0000-0000-000000000001", any P) Self>(%opened1) : $@convention(thin) <τ_0_0> (@guaranteed τ_0_0) -> ()
33+
34+
%opened2 = open_existential_ref %p : $any P to $@opened("00000000-0000-0000-0000-000000000002", any P) Self
35+
%optional = enum $Optional<@opened("00000000-0000-0000-0000-000000000002", any P) Self>, #Optional.some!enumelt, %opened2 : $@opened("00000000-0000-0000-0000-000000000002", any P) Self
36+
// Don't let the optional get optimized away.
37+
%void2 = apply %blackhole<Optional<@opened("00000000-0000-0000-0000-000000000002", any P) Self>>(%optional) : $@convention(thin) <τ_0_0> (@guaranteed τ_0_0) -> ()
38+
39+
%result = tuple ()
40+
return %result : $()
41+
}
42+
43+
// CHECK-LABEL: sil @test_use_chain_beginning_with_type_dependent_operand
44+
// CHECK_ID-NOT: 00000000-0000-0000-0000-000000000004
45+
// CHECK_OPT: bb0(
46+
// CHECK_OPT-NEXT: // function_ref
47+
// CHECK_OPT-NEXT: function_ref @blackhole
48+
// CHECK_OPT-NEXT: open_existential_ref
49+
// CHECK_OPT-NEXT: apply
50+
// CHECK_OPT-NEXT: unchecked_ref_cast
51+
// CHECK_OPT-NEXT: enum
52+
// CHECK_OPT-NEXT: = enum
53+
// CHECK_OPT-NEXT: apply
54+
// CHECK_OPT-NEXT: tuple
55+
// CHECK_OPT-NEXT: return
56+
// CHECK: } // end sil function 'test_use_chain_beginning_with_type_dependent_operand'
57+
sil @test_use_chain_beginning_with_type_dependent_operand: $@convention(thin) (@guaranteed any P, @guaranteed Class) -> () {
58+
bb0(%p : $any P, %class : $Class):
59+
%blackhole = function_ref @blackhole : $@convention(thin) <τ_0_0> (@guaranteed τ_0_0) -> ()
60+
61+
%opened1 = open_existential_ref %p : $any P to $@opened("00000000-0000-0000-0000-000000000003", any P) Self
62+
// Don't let the first opened existential get optimized away.
63+
%void1 = apply %blackhole<@opened("00000000-0000-0000-0000-000000000003", any P) Self>(%opened1) : $@convention(thin) <τ_0_0> (@guaranteed τ_0_0) -> ()
64+
65+
%opened2 = open_existential_ref %p : $any P to $@opened("00000000-0000-0000-0000-000000000004", any P) Self
66+
%refcast = unchecked_ref_cast %class : $Class to $@opened("00000000-0000-0000-0000-000000000004", any P) Self
67+
%optional4 = enum $Optional<@opened("00000000-0000-0000-0000-000000000004", any P) Self>, #Optional.some!enumelt, %refcast : $@opened("00000000-0000-0000-0000-000000000004", any P) Self
68+
%optional5 = enum $Optional<Optional<@opened("00000000-0000-0000-0000-000000000004", any P) Self>>, #Optional.some!enumelt, %optional4 : $Optional<@opened("00000000-0000-0000-0000-000000000004", any P) Self>
69+
%void2 = apply %blackhole<Optional<Optional<@opened("00000000-0000-0000-0000-000000000004", any P) Self>>>(%optional5) : $@convention(thin) <τ_0_0> (@guaranteed τ_0_0) -> ()
70+
71+
%result = tuple ()
72+
return %result : $()
73+
}
74+
75+
// CHECK-LABEL: sil @test_use_chain_beginning_with_dependent_result
76+
// CHECK_ID-NOT: 00000000-0000-0000-0000-000000000006
77+
// CHECK_OPT: bb0(
78+
// CHECK_OPT-NEXT: // function_ref
79+
// CHECK_OPT-NEXT: function_ref @blackhole
80+
// CHECK_OPT-NEXT: open_existential_ref
81+
// CHECK_OPT-NEXT: apply
82+
// CHECK_OPT-NEXT: enum
83+
// CHECK_OPT-NEXT: = enum
84+
// CHECK_OPT-NEXT: = enum
85+
// CHECK_OPT-NEXT: apply
86+
// CHECK_OPT-NEXT: tuple
87+
// CHECK_OPT-NEXT: return
88+
// CHECK: } // end sil function 'test_use_chain_beginning_with_dependent_result'
89+
sil @test_use_chain_beginning_with_dependent_result: $@convention(thin) (@guaranteed any P) -> () {
90+
bb0(%p : $any P):
91+
%blackhole = function_ref @blackhole : $@convention(thin) <τ_0_0> (@guaranteed τ_0_0) -> ()
92+
93+
%opened1 = open_existential_ref %p : $any P to $@opened("00000000-0000-0000-0000-000000000005", any P) Self
94+
// Don't let the first opened existential get optimized away.
95+
%void1 = apply %blackhole<@opened("00000000-0000-0000-0000-000000000005", any P) Self>(%opened1) : $@convention(thin) <τ_0_0> (@guaranteed τ_0_0) -> ()
96+
97+
%opened2 = open_existential_ref %p : $any P to $@opened("00000000-0000-0000-0000-000000000006", any P) Self
98+
%optional1 = enum $Optional<@opened("00000000-0000-0000-0000-000000000006", any P) Self>, #Optional.some!enumelt, %opened2 : $@opened("00000000-0000-0000-0000-000000000006", any P) Self
99+
%optional2 = enum $Optional<Optional<@opened("00000000-0000-0000-0000-000000000006", any P) Self>>, #Optional.some!enumelt, %optional1 : $Optional<@opened("00000000-0000-0000-0000-000000000006", any P) Self>
100+
%optional3 = enum $Optional<Optional<Optional<@opened("00000000-0000-0000-0000-000000000006", any P) Self>>>, #Optional.some!enumelt, %optional2 : $Optional<Optional<@opened("00000000-0000-0000-0000-000000000006", any P) Self>>
101+
%void2 = apply %blackhole<Optional<Optional<Optional<@opened("00000000-0000-0000-0000-000000000006", any P) Self>>>>(%optional3) : $@convention(thin) <τ_0_0> (@guaranteed τ_0_0) -> ()
102+
103+
%result = tuple ()
104+
return %result : $()
105+
}
106+
107+
// CHECK-LABEL: sil @test_terminator_inst_indirect_use
108+
// CHECK_ID-NOT: 00000000-0000-0000-0000-000000000008
109+
// CHECK_OPT: bb0(
110+
// CHECK_OPT-NEXT: // function_ref
111+
// CHECK_OPT-NEXT: function_ref @blackhole
112+
// CHECK_OPT-NEXT: open_existential_ref
113+
// CHECK_OPT-NEXT: apply
114+
// CHECK_OPT-NEXT: unchecked_ref_cast
115+
// CHECK_OPT-NEXT: br bb1
116+
// CHECK_OPT-EMPTY:
117+
// CHECK_OPT-NEXT: //
118+
// CHECK_OPT-NEXT: bb1(
119+
// CHECK_OPT-NEXT: apply
120+
// CHECK_OPT-NEXT: tuple
121+
// CHECK_OPT-NEXT: return
122+
// CHECK: } // end sil function 'test_terminator_inst_indirect_use'
123+
sil @test_terminator_inst_indirect_use : $@convention(thin) (@guaranteed any P, @guaranteed Class) -> () {
124+
bb0(%p : $any P, %class : $Class):
125+
%blackhole = function_ref @blackhole : $@convention(thin) <τ_0_0> (@guaranteed τ_0_0) -> ()
126+
127+
%opened1 = open_existential_ref %p : $any P to $@opened("00000000-0000-0000-0000-000000000007", any P) Self
128+
// Don't let the first opened existential get optimized away.
129+
%void1 = apply %blackhole<@opened("00000000-0000-0000-0000-000000000007", any P) Self>(%opened1) : $@convention(thin) <τ_0_0> (@guaranteed τ_0_0) -> ()
130+
131+
%opened2 = open_existential_ref %p : $any P to $@opened("00000000-0000-0000-0000-000000000008", any P) Self
132+
%refcast = unchecked_ref_cast %class : $Class to $@opened("00000000-0000-0000-0000-000000000008", any P) Self
133+
br bb1(%refcast : $@opened("00000000-0000-0000-0000-000000000008", any P) Self)
134+
135+
bb1(%arg : $@opened("00000000-0000-0000-0000-000000000008", any P) Self):
136+
%void2 = apply %blackhole<@opened("00000000-0000-0000-0000-000000000008", any P) Self>(%arg) : $@convention(thin) <τ_0_0> (@guaranteed τ_0_0) -> ()
137+
%result = tuple ()
138+
return %result : $()
139+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// RUN: not --crash %target-sil-opt -enable-sil-verify-all %s -cse
2+
3+
// Move this test case to 'test/SILOptimizer/cse_open_existential_ref.sil' once
4+
// it is fixed.
5+
6+
import Builtin
7+
import Swift
8+
9+
protocol P {}
10+
11+
sil @test_br_use : $@convention(thin) (@guaranteed any P) -> () {
12+
bb0(%p : $any P):
13+
%blackhole = function_ref @blackhole : $@convention(thin) <τ_0_0> (@guaranteed τ_0_0) -> ()
14+
15+
%opened1 = open_existential_ref %p : $any P to $@opened("00000000-0000-0000-0000-000000000009", any P) Self
16+
// Don't let the first opened existential get optimized away.
17+
%void1 = apply %blackhole<@opened("00000000-0000-0000-0000-000000000009", any P) Self>(%opened1) : $@convention(thin) <τ_0_0> (@guaranteed τ_0_0) -> ()
18+
19+
%opened2 = open_existential_ref %p : $any P to $@opened("00000000-0000-0000-0000-000000000010", any P) Self
20+
br bb1(%opened2 : $@opened("00000000-0000-0000-0000-000000000010", any P) Self)
21+
22+
bb1(%arg : $@opened("00000000-0000-0000-0000-000000000010", any P) Self):
23+
%optional = enum $Optional<@opened("00000000-0000-0000-0000-000000000010", any P) Self>, #Optional.some!enumelt, %arg : $@opened("00000000-0000-0000-0000-000000000010", any P) Self
24+
%void2 = apply %blackhole<Optional<@opened("00000000-0000-0000-0000-000000000010", any P) Self>>(%optional) : $@convention(thin) <τ_0_0> (@guaranteed τ_0_0) -> ()
25+
%result = tuple ()
26+
return %result : $()
27+
}

0 commit comments

Comments
 (0)