Skip to content

Commit f78678a

Browse files
committed
[sil-cloner] Improve handling of self-recursive apply instructions
- re-factor the code so that all kinds of applies can reuse it - properly handle self-recursive generic functions Fixes rdar://31899989 and rdar://31886854
1 parent c9f6932 commit f78678a

File tree

1 file changed

+101
-68
lines changed

1 file changed

+101
-68
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.

0 commit comments

Comments
 (0)