Skip to content

Commit be0bdd1

Browse files
authored
Merge pull request #20617 from rajbarik/raj-es-fix-default-enable
Fix ExistentialSpecializer bugs for swiftpm and enable existential-specializer for sil-opt
2 parents 0ba51b0 + c4df82b commit be0bdd1

File tree

4 files changed

+241
-27
lines changed

4 files changed

+241
-27
lines changed

lib/SILOptimizer/FunctionSignatureTransforms/ExistentialSpecializer.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,8 @@ static bool findConcreteType(ApplySite AI, int ArgIdx, CanType &ConcreteType) {
101101
SILValue InitExistential =
102102
findInitExistentialFromGlobalAddrAndApply(GAI, AI, ArgIdx);
103103
/// If the Arg is already init_existential, return the concrete type.
104-
if (findConcreteTypeFromInitExistential(InitExistential, ConcreteType)) {
104+
if (InitExistential &&
105+
findConcreteTypeFromInitExistential(InitExistential, ConcreteType)) {
105106
return true;
106107
}
107108
}
@@ -257,6 +258,12 @@ bool ExistentialSpecializer::canSpecializeCalleeFunction(ApplySite &Apply) {
257258
if (Callee->getInlineStrategy() == Inline_t::AlwaysInline)
258259
return false;
259260

261+
/// Ignore externally linked functions with public_external or higher
262+
/// linkage.
263+
if (isAvailableExternally(Callee->getLinkage())) {
264+
return false;
265+
}
266+
260267
/// Only choose a select few function representations for specialization.
261268
switch (Callee->getRepresentation()) {
262269
case SILFunctionTypeRepresentation::ObjCMethod:

lib/SILOptimizer/FunctionSignatureTransforms/ExistentialTransform.cpp

Lines changed: 10 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,6 @@ void ExistentialSpecializerCloner::cloneAndPopulateFunction() {
9494
SILModule &M = OrigF->getModule();
9595
auto &Ctx = M.getASTContext();
9696
llvm::SmallDenseMap<int, AllocStackInst *> ArgToAllocStackMap;
97-
bool MissingDestroyUse = false;
9897

9998
NewFBuilder.setInsertionPoint(ClonedEntryBB);
10099

@@ -153,8 +152,6 @@ void ExistentialSpecializerCloner::cloneAndPopulateFunction() {
153152
IsInitialization_t::IsInitialization);
154153
if (ExistentialArgDescriptor[ArgDesc.Index].DestroyAddrUse) {
155154
NewFBuilder.createDestroyAddr(InsertLoc, NewArg);
156-
} else {
157-
MissingDestroyUse = true;
158155
}
159156
entryArgs.push_back(ASI);
160157
break;
@@ -192,13 +189,11 @@ void ExistentialSpecializerCloner::cloneAndPopulateFunction() {
192189
/// If there is an argument with no DestroyUse, insert DeallocStack
193190
/// before return Instruction.
194191
llvm::SmallPtrSet<ReturnInst *, 4> ReturnInsts;
195-
if (MissingDestroyUse) {
196-
/// Find the set of return instructions in a function.
197-
for (auto &BB : NewF) {
198-
TermInst *TI = BB.getTerminator();
199-
if (auto *RI = dyn_cast<ReturnInst>(TI)) {
200-
ReturnInsts.insert(RI);
201-
}
192+
/// Find the set of return instructions in a function.
193+
for (auto &BB : NewF) {
194+
TermInst *TI = BB.getTerminator();
195+
if (auto *RI = dyn_cast<ReturnInst>(TI)) {
196+
ReturnInsts.insert(RI);
202197
}
203198
}
204199

@@ -207,22 +202,11 @@ void ExistentialSpecializerCloner::cloneAndPopulateFunction() {
207202
int ArgIndex = ArgDesc.Index;
208203
auto iter = ArgToAllocStackMap.find(ArgIndex);
209204
if (iter != ArgToAllocStackMap.end()) {
210-
auto it = ExistentialArgDescriptor.find(ArgIndex);
211-
if (it != ExistentialArgDescriptor.end() && it->second.DestroyAddrUse) {
212-
for (Operand *ASIUse : iter->second->getUses()) {
213-
auto *ASIUser = ASIUse->getUser();
214-
if (auto *DAI = dyn_cast<DestroyAddrInst>(ASIUser)) {
215-
SILBuilder Builder(ASIUser);
216-
Builder.setInsertionPoint(&*std::next(ASIUser->getIterator()));
217-
Builder.createDeallocStack(DAI->getLoc(), iter->second);
218-
}
219-
}
220-
} else { // Need to insert DeallocStack before return.
221-
for (auto *I : ReturnInsts) {
222-
SILBuilder Builder(I->getParent());
223-
Builder.setInsertionPoint(I);
224-
Builder.createDeallocStack(iter->second->getLoc(), iter->second);
225-
}
205+
// Need to insert DeallocStack before return.
206+
for (auto *I : ReturnInsts) {
207+
SILBuilder Builder(I->getParent());
208+
Builder.setInsertionPoint(I);
209+
Builder.createDeallocStack(iter->second->getLoc(), iter->second);
226210
}
227211
}
228212
}
Lines changed: 217 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,217 @@
1+
// RUN: %target-sil-opt -assume-parsing-unqualified-ownership-sil -enable-sil-verify-all %s -enable-sil-existential-specializer -existential-specializer | %FileCheck %s
2+
3+
// Additional tests for existential_specializer
4+
5+
import Builtin
6+
import Swift
7+
import SwiftShims
8+
9+
internal protocol P {
10+
func foo() -> Int32
11+
}
12+
13+
internal class Klass1 : P {
14+
@inline(never) func foo() -> Int32
15+
init()
16+
}
17+
18+
internal class Klass2 : P {
19+
@inline(never) func foo() -> Int32
20+
init()
21+
}
22+
23+
@inline(never) internal func wrap_foo_ncp(a: inout P, b: inout P) -> Int32
24+
25+
@inline(never) func ncp()
26+
27+
sil hidden [noinline] @$s7dealloc3ncpyyF : $@convention(thin) () -> Int32 {
28+
bb0:
29+
%0 = alloc_stack $P, var, name "magic2"
30+
%1 = alloc_ref $Klass1
31+
%4 = init_existential_addr %0 : $*P, $Klass1
32+
store %1 to %4 : $*Klass1
33+
%6 = alloc_stack $P, var, name "magic3"
34+
%7 = alloc_ref $Klass1
35+
%10 = init_existential_addr %6 : $*P, $Klass1
36+
store %7 to %10 : $*Klass1
37+
%12 = function_ref @$s7dealloc12wrap_foo_ncp1a1bSiAA1P_pz_AaE_pztF : $@convention(thin) (@in P, @in P) -> Int32
38+
%13 = apply %12(%0, %6) : $@convention(thin) (@in P, @in P) -> Int32
39+
debug_value %13 : $Int32, let, name "x"
40+
%14 = alloc_stack $P, var, name "magic4"
41+
%15 = alloc_ref $Klass1
42+
%16 = init_existential_addr %14 : $*P, $Klass1
43+
store %15 to %16 : $*Klass1
44+
%17 = function_ref @$s7dealloc20wrap_foo_ncp_another1aSiAA1P_pz_tF : $@convention(thin) (@inout P) -> Int32
45+
%18 = apply %17(%14) : $@convention(thin) (@inout P) -> Int32
46+
%24 = struct_extract %13 : $Int32, #Int32._value
47+
%25 = struct_extract %18 : $Int32, #Int32._value
48+
%26 = integer_literal $Builtin.Int1, -1
49+
%27 = builtin "sadd_with_overflow_Int32"(%24 : $Builtin.Int32, %25 : $Builtin.Int32, %26 : $Builtin.Int1) : $(Builtin.Int32, Builtin.Int1)
50+
%28 = tuple_extract %27 : $(Builtin.Int32, Builtin.Int1), 0
51+
%29 = tuple_extract %27 : $(Builtin.Int32, Builtin.Int1), 1
52+
cond_fail %29 : $Builtin.Int1
53+
%31 = struct $Int32 (%28 : $Builtin.Int32)
54+
destroy_addr %14 : $*P
55+
dealloc_stack %14 : $*P
56+
dealloc_stack %6 : $*P
57+
dealloc_stack %0 : $*P
58+
return %31 : $Int32
59+
}
60+
61+
// CHECK-LABEL: sil public_external [serialized] @$s7dealloc20wrap_foo_ncp_another1aSiAA1P_pz_tF : $@convention(thin) (@inout P) -> Int32 {
62+
// CHECK: bb0(%0 : $*P):
63+
// CHECK: debug_value_addr
64+
// CHECK: alloc_stack
65+
// CHECK: copy_addr
66+
// CHECK: open_existential_addr
67+
// CHECK: witness_method
68+
// CHECK: apply
69+
// CHECK: destroy_addr
70+
// CHECK: dealloc_stack
71+
// CHECK: return
72+
// CHECK-LABEL :} // end sil function '$s7dealloc20wrap_foo_ncp_another1aSiAA1P_pz_tF'
73+
sil public_external [serialized] @$s7dealloc20wrap_foo_ncp_another1aSiAA1P_pz_tF : $@convention(thin) (@inout P) -> Int32 {
74+
bb0(%0 : $*P):
75+
debug_value_addr %0 : $*P, var, name "a", argno 1
76+
%2 = alloc_stack $P
77+
copy_addr %0 to [initialization] %2 : $*P
78+
%4 = open_existential_addr immutable_access %2 : $*P to $*@opened("EE9F89E4-ECF4-11E8-8DDF-D0817AD4059B") P
79+
%5 = witness_method $@opened("EE9F89E4-ECF4-11E8-8DDF-D0817AD4059B") P, #P.foo!1 : <Self where Self : P> (Self) -> () -> Int32, %4 : $*@opened("EE9F89E4-ECF4-11E8-8DDF-D0817AD4059B") P : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> Int32
80+
%6 = apply %5<@opened("EE9F89E4-ECF4-11E8-8DDF-D0817AD4059B") P>(%4) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> Int32
81+
destroy_addr %2 : $*P
82+
dealloc_stack %2 : $*P
83+
return %6 : $Int32
84+
} // end sil function '$s7dealloc20wrap_foo_ncp_another1aSiAA1P_pz_tF'
85+
86+
sil shared [noinline] @$s7dealloc6Klass1C3fooSiyFTf4d_n : $@convention(thin) () -> Int32 {
87+
bb0:
88+
%0 = integer_literal $Builtin.Int32, 10
89+
%1 = struct $Int32 (%0 : $Builtin.Int32)
90+
return %1 : $Int32
91+
}
92+
93+
sil_global hidden [let] @$global_var : $P
94+
95+
// CHECK-LABEL: sil hidden [noinline] @$helper : $@convention(thin) (@in P) -> Int32 {
96+
// CHECK: bb0(%0 : $*P):
97+
// CHECK: debug_value_addr
98+
// CHECK: alloc_stack
99+
// CHECK: copy_addr
100+
// CHECK: destroy_addr
101+
// CHECK: open_existential_addr
102+
// CHECK: witness_method
103+
// CHECK: apply
104+
// CHECK: dealloc_stack
105+
// CHECK: return
106+
// CHECK-LABEL: } // end sil function '$helper'
107+
sil hidden [noinline] @$helper : $@convention(thin) (@in P) -> Int32 {
108+
bb0(%0 : $*P):
109+
debug_value_addr %0 : $*P, var, name "a", argno 1
110+
%4 = alloc_stack $P
111+
copy_addr %0 to [initialization] %4 : $*P
112+
destroy_addr %0 : $*P
113+
%6 = open_existential_addr immutable_access %4 : $*P to $*@opened("3CB58EC4-ECED-11E8-9798-D0817AD4059B") P
114+
%7 = witness_method $@opened("3CB58EC4-ECED-11E8-9798-D0817AD4059B") P, #P.foo!1 : <Self where Self : P> (Self) -> () -> Int32, %6 : $*@opened("3CB58EC4-ECED-11E8-9798-D0817AD4059B") P : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> Int32
115+
%8 = apply %7<@opened("3CB58EC4-ECED-11E8-9798-D0817AD4059B") P>(%6) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> Int32
116+
dealloc_stack %4 : $*P
117+
return %8 : $Int32
118+
}
119+
120+
sil @global_addr_init: $@convention(thin) (Builtin.Int1) -> Int32 {
121+
bb0(%0 : $Builtin.Int1):
122+
alloc_global @$global_var
123+
%1 = global_addr @$global_var : $*P
124+
cond_br %0, bb1, bb2
125+
126+
bb1:
127+
%2 = init_existential_addr %1 : $*P, $Klass1
128+
%3 = alloc_ref $Klass1
129+
store %3 to %2 : $*Klass1
130+
br bb3
131+
132+
bb2:
133+
%5 = init_existential_addr %1 : $*P, $Klass2
134+
%6 = alloc_ref $Klass2
135+
store %6 to %5 : $*Klass2
136+
br bb3
137+
138+
bb3:
139+
%12 = function_ref @$helper : $@convention(thin) (@in P) -> Int32
140+
%13 = apply %12(%1) : $@convention(thin) (@in P) -> Int32
141+
return %13 : $Int32
142+
}
143+
144+
// CHECK-LABEL: sil shared [noinline] @$s7dealloc12wrap_foo_ncp1a1bSiAA1P_pz_AaE_pztFTf4ee_n : $@convention(thin) <τ_0_0, τ_0_1 where τ_0_0 : P, τ_0_1 : P> (@in τ_0_0, @in τ_0_1) -> Int32 {
145+
// CHECK: bb0(%0 : $*τ_0_0, %1 : $*τ_0_1):
146+
// CHECK: alloc_stack
147+
// CHECK: init_existential_addr
148+
// CHECK: copy_addr
149+
// CHECK: destroy_addr
150+
// CHECK: alloc_stack
151+
// CHECK: init_existential_addr
152+
// CHECK: copy_addr
153+
// CHECK: destroy_addr
154+
// CHECK: debug_value_addr
155+
// CHECK: debug_value_addr
156+
// CHECK: alloc_stack
157+
// CHECK: copy_addr
158+
// CHECK: destroy_addr
159+
// CHECK: open_existential_addr
160+
// CHECK: witness_method
161+
// CHECK: apply
162+
// CHECK: alloc_stack
163+
// CHECK: copy_addr
164+
// CHECK: destroy_addr
165+
// CHECK: open_existential_addr
166+
// CHECK: witness_method
167+
// CHECK: apply
168+
// CHECK: struct_extract
169+
// CHECK: struct_extract
170+
// CHECK: integer_literal
171+
// CHECK: builtin
172+
// CHECK: tuple_extract
173+
// CHECK: tuple_extract
174+
// CHECK: cond_fail
175+
// CHECK: struct
176+
// CHECK: dealloc_stack
177+
// CHECK: dealloc_stack
178+
// CHECK: dealloc_stack
179+
// CHECK: dealloc_stack
180+
// CHECK: return
181+
// CHECK-LABEL: } // end sil function '$s7dealloc12wrap_foo_ncp1a1bSiAA1P_pz_AaE_pztFTf4ee_n'
182+
sil hidden [noinline] @$s7dealloc12wrap_foo_ncp1a1bSiAA1P_pz_AaE_pztF : $@convention(thin) (@in P, @in P) -> Int32 {
183+
bb0(%0 : $*P, %1 : $*P):
184+
debug_value_addr %0 : $*P, var, name "a", argno 1
185+
debug_value_addr %1 : $*P, var, name "b", argno 2
186+
%4 = alloc_stack $P
187+
copy_addr %0 to [initialization] %4 : $*P
188+
destroy_addr %0 : $*P
189+
%6 = open_existential_addr immutable_access %4 : $*P to $*@opened("3CB58EC4-ECED-11E8-9798-D0817AD4059B") P
190+
%7 = witness_method $@opened("3CB58EC4-ECED-11E8-9798-D0817AD4059B") P, #P.foo!1 : <Self where Self : P> (Self) -> () -> Int32, %6 : $*@opened("3CB58EC4-ECED-11E8-9798-D0817AD4059B") P : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> Int32
191+
%8 = apply %7<@opened("3CB58EC4-ECED-11E8-9798-D0817AD4059B") P>(%6) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> Int32
192+
%9 = alloc_stack $P
193+
copy_addr %1 to [initialization] %9 : $*P
194+
destroy_addr %1 : $*P
195+
%11 = open_existential_addr immutable_access %9 : $*P to $*@opened("3CB58FAA-ECED-11E8-9798-D0817AD4059B") P
196+
%12 = witness_method $@opened("3CB58FAA-ECED-11E8-9798-D0817AD4059B") P, #P.foo!1 : <Self where Self : P> (Self) -> () -> Int32, %11 : $*@opened("3CB58FAA-ECED-11E8-9798-D0817AD4059B") P : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> Int32
197+
%13 = apply %12<@opened("3CB58FAA-ECED-11E8-9798-D0817AD4059B") P>(%11) : $@convention(witness_method: P) <τ_0_0 where τ_0_0 : P> (@in_guaranteed τ_0_0) -> Int32
198+
%14 = struct_extract %8 : $Int32, #Int32._value
199+
%15 = struct_extract %13 : $Int32, #Int32._value
200+
%16 = integer_literal $Builtin.Int1, -1
201+
%17 = builtin "sadd_with_overflow_Int32"(%14 : $Builtin.Int32, %15 : $Builtin.Int32, %16 : $Builtin.Int1) : $(Builtin.Int32, Builtin.Int1)
202+
%18 = tuple_extract %17 : $(Builtin.Int32, Builtin.Int1), 0
203+
%19 = tuple_extract %17 : $(Builtin.Int32, Builtin.Int1), 1
204+
cond_fail %19 : $Builtin.Int1
205+
%21 = struct $Int32 (%18 : $Builtin.Int32)
206+
dealloc_stack %9 : $*P
207+
dealloc_stack %4 : $*P
208+
return %21 : $Int32
209+
}
210+
211+
sil_witness_table hidden Klass1: P module dealloc {
212+
method #P.foo!1: <Self where Self : P> (Self) -> () -> Int32 : nil
213+
}
214+
215+
sil_witness_table hidden Klass2: P module dealloc {
216+
method #P.foo!1: <Self where Self : P> (Self) -> () -> Int32 : nil
217+
}

tools/sil-opt/SILOpt.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,11 @@ static llvm::cl::opt<int>
167167
SILInlineThreshold("sil-inline-threshold", llvm::cl::Hidden,
168168
llvm::cl::init(-1));
169169

170+
static llvm::cl::opt<bool>
171+
SILExistentialSpecializer("enable-sil-existential-specializer",
172+
llvm::cl::Hidden,
173+
llvm::cl::init(false));
174+
170175
static llvm::cl::opt<bool>
171176
EnableSILVerifyAll("enable-sil-verify-all",
172177
llvm::cl::Hidden,
@@ -336,6 +341,7 @@ int main(int argc, char **argv) {
336341
// Setup the SIL Options.
337342
SILOptions &SILOpts = Invocation.getSILOptions();
338343
SILOpts.InlineThreshold = SILInlineThreshold;
344+
SILOpts.ExistentialSpecializer = SILExistentialSpecializer;
339345
SILOpts.VerifyAll = EnableSILVerifyAll;
340346
SILOpts.RemoveRuntimeAsserts = RemoveRuntimeAsserts;
341347
SILOpts.AssertConfig = AssertConfId;

0 commit comments

Comments
 (0)