Skip to content

Commit 3e7da65

Browse files
authored
Merge pull request #9470 from swiftix/generic-specialization-fixes
[generic-specializer] Fixes for partial_apply instructions and for specialization of self-recursive functions
2 parents 26f7659 + f860741 commit 3e7da65

File tree

4 files changed

+130
-71
lines changed

4 files changed

+130
-71
lines changed

include/swift/SIL/TypeSubstCloner.h

Lines changed: 101 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,86 @@ class TypeSubstCloner : public SILClonerWithScopes<ImplClass> {
4747
}
4848
}
4949

50+
// A helper class for cloning different kinds of apply instructions.
51+
// Supports cloning of self-recursive functions.
52+
class ApplySiteCloningHelper {
53+
SILValue Callee;
54+
SubstitutionList Subs;
55+
SmallVector<SILValue, 8> Args;
56+
SmallVector<Substitution, 8> NewSubsList;
57+
SmallVector<Substitution, 8> RecursiveSubsList;
58+
59+
public:
60+
ApplySiteCloningHelper(ApplySite AI, TypeSubstCloner &Cloner)
61+
: Callee(Cloner.getOpValue(AI.getCallee())) {
62+
SILType SubstCalleeSILType = Cloner.getOpType(AI.getSubstCalleeSILType());
63+
64+
Args = Cloner.template getOpValueArray<8>(AI.getArguments());
65+
SILBuilder &Builder = Cloner.getBuilder();
66+
Builder.setCurrentDebugScope(Cloner.super::getOpScope(AI.getDebugScope()));
67+
68+
// Remap substitutions.
69+
NewSubsList = Cloner.getOpSubstitutions(AI.getSubstitutions());
70+
Subs = NewSubsList;
71+
72+
if (!Cloner.Inlining) {
73+
FunctionRefInst *FRI = dyn_cast<FunctionRefInst>(AI.getCallee());
74+
if (FRI && FRI->getReferencedFunction() == AI.getFunction() &&
75+
Subs == Cloner.ApplySubs) {
76+
// Handle recursions by replacing the apply to the callee with an
77+
// apply to the newly specialized function, but only if substitutions
78+
// are the same.
79+
auto LoweredFnTy = Builder.getFunction().getLoweredFunctionType();
80+
auto RecursiveSubstCalleeSILType = LoweredFnTy;
81+
auto GenSig = LoweredFnTy->getGenericSignature();
82+
if (GenSig) {
83+
// Compute substitutions for the specialized function. These
84+
// substitutions may be different from the original ones, e.g.
85+
// there can be less substitutions.
86+
GenSig->getSubstitutions(AI.getFunction()
87+
->getLoweredFunctionType()
88+
->getGenericSignature()
89+
->getSubstitutionMap(Subs),
90+
RecursiveSubsList);
91+
// Use the new set of substitutions to compute the new
92+
// substituted callee type.
93+
RecursiveSubstCalleeSILType = LoweredFnTy->substGenericArgs(
94+
AI.getModule(), RecursiveSubsList);
95+
}
96+
97+
// The specialized recursive function may have different calling
98+
// convention for parameters. E.g. some of former indirect parameters
99+
// may become direct. Some of indirect return values may become
100+
// direct. Do not replace the callee in that case.
101+
if (SubstCalleeSILType.getSwiftRValueType() ==
102+
RecursiveSubstCalleeSILType) {
103+
Subs = RecursiveSubsList;
104+
Callee = Builder.createFunctionRef(
105+
Cloner.getOpLocation(AI.getLoc()), &Builder.getFunction());
106+
SubstCalleeSILType =
107+
SILType::getPrimitiveObjectType(RecursiveSubstCalleeSILType);
108+
}
109+
}
110+
}
111+
112+
assert(Subs.empty() ||
113+
SubstCalleeSILType ==
114+
Callee->getType().substGenericArgs(AI.getModule(), Subs));
115+
}
116+
117+
ArrayRef<SILValue> getArguments() const {
118+
return Args;
119+
}
120+
121+
SILValue getCallee() const {
122+
return Callee;
123+
}
124+
125+
SubstitutionList getSubstitutions() const {
126+
return Subs;
127+
}
128+
};
129+
50130
public:
51131
using SILClonerWithScopes<ImplClass>::asImpl;
52132
using SILClonerWithScopes<ImplClass>::getBuilder;
@@ -105,79 +185,32 @@ class TypeSubstCloner : public SILClonerWithScopes<ImplClass> {
105185
}
106186

107187
void visitApplyInst(ApplyInst *Inst) {
108-
auto Args = this->template getOpValueArray<8>(Inst->getArguments());
109-
110-
// Handle recursions by replacing the apply to the callee with an apply to
111-
// the newly specialized function, but only if substitutions are the same.
112-
SILBuilder &Builder = getBuilder();
113-
Builder.setCurrentDebugScope(super::getOpScope(Inst->getDebugScope()));
114-
SILValue CalleeVal = Inst->getCallee();
115-
if (!Inlining) {
116-
auto *FRI = dyn_cast<FunctionRefInst>(CalleeVal);
117-
if (FRI && FRI->getReferencedFunction() == Inst->getFunction() &&
118-
Inst->getSubstitutions() == this->ApplySubs) {
119-
FRI = Builder.createFunctionRef(getOpLocation(Inst->getLoc()),
120-
&Builder.getFunction());
121-
ApplyInst *NAI =
122-
Builder.createApply(getOpLocation(Inst->getLoc()), FRI, Args, Inst->isNonThrowing());
123-
doPostProcess(Inst, NAI);
124-
return;
125-
}
126-
}
127-
128-
SmallVector<Substitution, 16> TempSubstList;
129-
for (auto &Sub : Inst->getSubstitutions()) {
130-
TempSubstList.push_back(asImpl().getOpSubstitution(Sub));
131-
}
188+
ApplySiteCloningHelper Helper(ApplySite::isa(Inst), *this);
189+
ApplyInst *N =
190+
getBuilder().createApply(getOpLocation(Inst->getLoc()),
191+
Helper.getCallee(), Helper.getSubstitutions(),
192+
Helper.getArguments(), Inst->isNonThrowing());
193+
doPostProcess(Inst, N);
194+
}
132195

133-
ApplyInst *N = Builder.createApply(
134-
getOpLocation(Inst->getLoc()), getOpValue(CalleeVal),
135-
TempSubstList, Args, Inst->isNonThrowing());
196+
void visitTryApplyInst(TryApplyInst *Inst) {
197+
ApplySiteCloningHelper Helper(ApplySite::isa(Inst), *this);
198+
TryApplyInst *N = getBuilder().createTryApply(
199+
getOpLocation(Inst->getLoc()), Helper.getCallee(),
200+
Helper.getSubstitutions(), Helper.getArguments(),
201+
getOpBasicBlock(Inst->getNormalBB()),
202+
getOpBasicBlock(Inst->getErrorBB()));
136203
doPostProcess(Inst, N);
137204
}
138205

139206
void visitPartialApplyInst(PartialApplyInst *Inst) {
140-
auto Args = this->template getOpValueArray<8>(Inst->getArguments());
141-
142-
// Handle recursions by replacing the apply to the callee with an apply to
143-
// the newly specialized function.
144-
SILValue CalleeVal = Inst->getCallee();
145-
SILBuilderWithPostProcess<TypeSubstCloner, 4> Builder(this, Inst);
146-
Builder.setCurrentDebugScope(super::getOpScope(Inst->getDebugScope()));
147-
SmallVector<Substitution, 16> TempSubstList;
148-
if (!Inlining) {
149-
auto *FRI = dyn_cast<FunctionRefInst>(CalleeVal);
150-
if (FRI && FRI->getReferencedFunction() == Inst->getFunction()) {
151-
auto LoweredFnTy = Builder.getFunction().getLoweredFunctionType();
152-
auto GenSig = LoweredFnTy->getGenericSignature();
153-
if (GenSig) {
154-
GenSig->getSubstitutions(
155-
Inst->getFunction()
156-
->getLoweredFunctionType()
157-
->getGenericSignature()
158-
->getSubstitutionMap(Inst->getSubstitutions()),
159-
TempSubstList);
160-
}
161-
for (auto &Sub : TempSubstList) {
162-
Sub = asImpl().getOpSubstitution(Sub);
163-
}
164-
SubstitutionList Subs = TempSubstList;
165-
FRI = Builder.createFunctionRef(getOpLocation(Inst->getLoc()),
166-
&Builder.getFunction());
167-
Builder.createPartialApply(
168-
getOpLocation(Inst->getLoc()), FRI, Subs, Args,
169-
Inst->getType().getAs<SILFunctionType>()->getCalleeConvention());
170-
return;
171-
}
172-
}
173-
174-
for (auto &Sub : Inst->getSubstitutions()) {
175-
TempSubstList.push_back(asImpl().getOpSubstitution(Sub));
176-
}
177-
178-
Builder.createPartialApply(
179-
getOpLocation(Inst->getLoc()), getOpValue(CalleeVal), TempSubstList,
180-
Args, Inst->getType().getAs<SILFunctionType>()->getCalleeConvention());
207+
ApplySiteCloningHelper Helper(ApplySite::isa(Inst), *this);
208+
auto ParamConvention =
209+
Inst->getType().getAs<SILFunctionType>()->getCalleeConvention();
210+
PartialApplyInst *N = getBuilder().createPartialApply(
211+
getOpLocation(Inst->getLoc()), Helper.getCallee(),
212+
Helper.getSubstitutions(), Helper.getArguments(), ParamConvention);
213+
doPostProcess(Inst, N);
181214
}
182215

183216
/// Attempt to simplify a conditional checked cast.

lib/SILOptimizer/Utils/Generics.cpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1805,8 +1805,6 @@ static ApplySite replaceWithSpecializedCallee(ApplySite AI,
18051805
return NewAI;
18061806
}
18071807
if (auto *PAI = dyn_cast<PartialApplyInst>(AI)) {
1808-
// SILType PTy =
1809-
// SILType::getPrimitiveObjectType(ReInfo.getSpecializedType());
18101808
auto *NewPAI = Builder.createPartialApply(
18111809
Loc, Callee, Subs, Arguments,
18121810
PAI->getType().getAs<SILFunctionType>()->getCalleeConvention());

test/SILOptimizer/specialize.sil

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -614,3 +614,31 @@ bb3:
614614
%8 = tuple ()
615615
return %8 : $()
616616
}
617+
618+
struct YYY<T> {
619+
}
620+
621+
enum MyOptional<T> {
622+
case none
623+
case some(T)
624+
}
625+
626+
// Check that a specialization of a self-recursive function is produced
627+
// and it is not crashing the compiler.
628+
// CHECK-LABEL: sil shared @_T025testSelfRecursiveFunction4main10MyOptionalOyAB3YYYVyypGG_Tg5 : $@convention(thin) (MyOptional<YYY<Any>>) -> ()
629+
sil @testSelfRecursiveFunction : $@convention(thin) <T> (@in T) -> () {
630+
bb0(%0 : $*T):
631+
%2 = function_ref @testSelfRecursiveFunction : $@convention(thin) <τ_0_0> (@in τ_0_0) -> ()
632+
%3 = alloc_stack $MyOptional<YYY<Any>>
633+
inject_enum_addr %3 : $*MyOptional<YYY<Any>>, #MyOptional.none!enumelt
634+
%5 = tuple ()
635+
%6 = load %3 : $*MyOptional<YYY<Any>>
636+
%7 = alloc_stack $MyOptional<YYY<Any>>
637+
store %6 to %7 : $*MyOptional<YYY<Any>>
638+
%9 = apply %2<MyOptional<YYY<Any>>>(%7) : $@convention(thin) <τ_0_0> (@in τ_0_0) -> ()
639+
dealloc_stack %7 : $*MyOptional<YYY<Any>>
640+
dealloc_stack %3 : $*MyOptional<YYY<Any>>
641+
destroy_addr %0 : $*T
642+
%13 = tuple ()
643+
return %13 : $()
644+
} // end sil function 'testSelfRecursiveFunction'

validation-test/compiler_crashers/28736-anonymous-namespacesilverifier-require.swift renamed to validation-test/compiler_crashers_fixed/28736-anonymous-namespacesilverifier-require.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
//
55
// See https://swift.org/LICENSE.txt for license information
66
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
7-
// RUN: not --crash %target-swift-frontend -primary-file %s -emit-ir -O
7+
// RUN: %target-swift-frontend -primary-file %s -emit-ir -O
88
// non-fuzz (@dusek)
99

1010
func f<T>(_ a:T)->Void{f(nil as[Any]?)}

0 commit comments

Comments
 (0)