Skip to content

Commit 4c075ba

Browse files
committed
SILOptimizer: Remove some duplication between SILCloner and TypeSubstCloner
This also fixes a latent bug; we were substituting opened existentials inside the replacement type of a Substitution, but not inside the conformances.
1 parent 13cc1ad commit 4c075ba

File tree

2 files changed

+82
-143
lines changed

2 files changed

+82
-143
lines changed

include/swift/SIL/SILCloner.h

Lines changed: 78 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#ifndef SWIFT_SIL_SILCLONER_H
1818
#define SWIFT_SIL_SILCLONER_H
1919

20+
#include "swift/AST/ProtocolConformance.h"
2021
#include "swift/SIL/SILOpenedArchetypesTracker.h"
2122
#include "swift/SIL/SILBuilder.h"
2223
#include "swift/SIL/SILDebugScope.h"
@@ -94,7 +95,7 @@ class SILCloner : protected SILVisitor<ImplClass> {
9495
const SILDebugScope *remapScope(const SILDebugScope *DS) { return DS; }
9596
SILType remapType(SILType Ty) { return Ty; }
9697
CanType remapASTType(CanType Ty) { return Ty; }
97-
ProtocolConformanceRef remapConformance(CanType Ty, ProtocolConformanceRef C){
98+
ProtocolConformanceRef remapConformance(Type Ty, ProtocolConformanceRef C){
9899
return C;
99100
}
100101
SILValue remapValue(SILValue Value);
@@ -108,37 +109,12 @@ class SILCloner : protected SILVisitor<ImplClass> {
108109
const SILDebugScope *getOpScope(const SILDebugScope *DS) {
109110
return asImpl().remapScope(DS);
110111
}
111-
Substitution getOpSubstitution(Substitution sub) {
112-
return asImpl().remapSubstitution(sub);
113-
}
114-
Substitution remapSubstitution(Substitution sub) {
115-
CanType newReplacement =
116-
asImpl().getOpASTType(sub.getReplacement()->getCanonicalType());
117-
118-
return Substitution(newReplacement, sub.getConformances());
119-
}
120-
SubstitutionList getOpSubstitutions(SubstitutionList Subs) {
121-
MutableArrayRef<Substitution> newSubsBuf;
122-
123-
auto copySubs = [&]{
124-
if (!newSubsBuf.empty())
125-
return;
126-
newSubsBuf = getBuilder().getASTContext()
127-
.template Allocate<Substitution>(Subs.size());
128-
memcpy(newSubsBuf.data(), Subs.data(),
129-
sizeof(Substitution) * Subs.size());
130-
Subs = newSubsBuf;
131-
};
132-
133-
for (unsigned i = 0, e = Subs.size(); i < e; ++i) {
134-
Substitution newSub = asImpl().getOpSubstitution(Subs[i]);
135-
if (newSub != Subs[i]) {
136-
copySubs();
137-
newSubsBuf[i] = newSub;
138-
}
112+
SmallVector<Substitution, 4> getOpSubstitutions(SubstitutionList Subs) {
113+
SmallVector<Substitution, 4> NewSubs;
114+
for (auto Sub : Subs) {
115+
NewSubs.push_back(getOpSubstitution(Sub));
139116
}
140-
141-
return Subs;
117+
return NewSubs;
142118
}
143119

144120
SILType getTypeInClonedContext(SILType Ty) {
@@ -152,15 +128,15 @@ class SILCloner : protected SILVisitor<ImplClass> {
152128
return asImpl().remapType(Ty);
153129
}
154130

155-
CanType getASTTypeInClonedContext(CanType ty) {
131+
CanType getASTTypeInClonedContext(Type ty) {
156132
// Do not substitute opened existential types, if we do not have any.
157133
if (!ty->hasOpenedExistential())
158-
return ty;
134+
return ty->getCanonicalType();
159135
// Do not substitute opened existential types, if it is not required.
160136
// This is often the case when cloning basic blocks inside the same
161137
// function.
162138
if (OpenedExistentialSubs.empty())
163-
return ty;
139+
return ty->getCanonicalType();
164140

165141
return ty.transform(
166142
[&](Type t) -> Type {
@@ -181,32 +157,46 @@ class SILCloner : protected SILVisitor<ImplClass> {
181157
return t;
182158
})->getCanonicalType();
183159
}
160+
184161
CanType getOpASTType(CanType ty) {
185162
ty = getASTTypeInClonedContext(ty);
186163
return asImpl().remapASTType(ty);
187164
}
188165

189-
/// Remap an entire set of conformances.
190-
///
191-
/// Returns the passed-in conformances array if none of the elements
192-
/// changed.
193-
ArrayRef<ProtocolConformanceRef> getOpConformances(CanType type,
194-
ArrayRef<ProtocolConformanceRef> oldConformances) {
195-
Substitution sub(type, oldConformances);
196-
Substitution mappedSub = asImpl().remapSubstitution(sub);
197-
ArrayRef<ProtocolConformanceRef> newConformances =
198-
mappedSub.getConformances();
199-
200-
// Use the existing conformances array if possible.
201-
if (oldConformances == newConformances)
202-
return oldConformances;
203-
204-
return type->getASTContext().AllocateCopy(newConformances);
166+
ProtocolConformanceRef getOpConformance(Type ty,
167+
ProtocolConformanceRef conformance) {
168+
auto newConformance =
169+
conformance.subst(ty,
170+
[&](SubstitutableType *t) -> Type {
171+
if (t->isOpenedExistential()) {
172+
auto found = OpenedExistentialSubs.find(
173+
t->castTo<ArchetypeType>());
174+
if (found != OpenedExistentialSubs.end())
175+
return found->second;
176+
return t;
177+
}
178+
return t;
179+
},
180+
MakeAbstractConformanceForGenericType());
181+
return asImpl().remapConformance(getASTTypeInClonedContext(ty),
182+
newConformance);
205183
}
206184

207-
ProtocolConformanceRef getOpConformance(CanType ty,
208-
ProtocolConformanceRef conformance) {
209-
return asImpl().remapConformance(ty, conformance);
185+
ArrayRef<ProtocolConformanceRef>
186+
getOpConformances(Type ty,
187+
ArrayRef<ProtocolConformanceRef> conformances) {
188+
SmallVector<ProtocolConformanceRef, 4> newConformances;
189+
for (auto conformance : conformances)
190+
newConformances.push_back(getOpConformance(ty, conformance));
191+
return ty->getASTContext().AllocateCopy(newConformances);
192+
}
193+
194+
Substitution getOpSubstitution(Substitution sub) {
195+
CanType newReplacement =
196+
getOpASTType(sub.getReplacement()->getCanonicalType());
197+
auto conformances = getOpConformances(sub.getReplacement(),
198+
sub.getConformances());
199+
return Substitution(newReplacement, conformances);
210200
}
211201

212202
SILValue getOpValue(SILValue Value) {
@@ -538,9 +528,10 @@ SILCloner<ImplClass>::visitAllocExistentialBoxInst(
538528
AllocExistentialBoxInst *Inst) {
539529
auto origExistentialType = Inst->getExistentialType();
540530
auto origFormalType = Inst->getFormalConcreteType();
541-
542-
auto conformances =getOpConformances(origFormalType, Inst->getConformances());
543-
531+
532+
auto conformances = getOpConformances(origFormalType,
533+
Inst->getConformances());
534+
544535
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
545536
doPostProcess(Inst,
546537
getBuilder().createAllocExistentialBox(getOpLocation(Inst->getLoc()),
@@ -1447,7 +1438,7 @@ SILCloner<ImplClass>::visitClassMethodInst(ClassMethodInst *Inst) {
14471438
getBuilder().createClassMethod(getOpLocation(Inst->getLoc()),
14481439
getOpValue(Inst->getOperand()),
14491440
Inst->getMember(),
1450-
getOpType(Inst->getType()),
1441+
Inst->getType(),
14511442
Inst->isVolatile()));
14521443
}
14531444

@@ -1459,25 +1450,37 @@ SILCloner<ImplClass>::visitSuperMethodInst(SuperMethodInst *Inst) {
14591450
getBuilder().createSuperMethod(getOpLocation(Inst->getLoc()),
14601451
getOpValue(Inst->getOperand()),
14611452
Inst->getMember(),
1462-
getOpType(Inst->getType()),
1453+
Inst->getType(),
14631454
Inst->isVolatile()));
14641455
}
14651456

14661457
template<typename ImplClass>
14671458
void
14681459
SILCloner<ImplClass>::visitWitnessMethodInst(WitnessMethodInst *Inst) {
1469-
auto conformance =
1470-
getOpConformance(Inst->getLookupType(), Inst->getConformance());
14711460
auto lookupType = Inst->getLookupType();
1461+
auto conformance = getOpConformance(lookupType, Inst->getConformance());
14721462
auto newLookupType = getOpASTType(lookupType);
1463+
1464+
if (conformance.isConcrete()) {
1465+
CanType Ty = conformance.getConcrete()->getType()->getCanonicalType();
1466+
1467+
if (Ty != newLookupType) {
1468+
assert(Ty->isExactSuperclassOf(newLookupType, nullptr) &&
1469+
"Should only create upcasts for sub class.");
1470+
1471+
// We use the super class as the new look up type.
1472+
newLookupType = Ty;
1473+
}
1474+
}
1475+
14731476
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
14741477
doPostProcess(
14751478
Inst,
14761479
getBuilder()
14771480
.createWitnessMethod(
14781481
getOpLocation(Inst->getLoc()),
14791482
newLookupType, conformance,
1480-
Inst->getMember(), getOpType(Inst->getType()),
1483+
Inst->getMember(), Inst->getType(),
14811484
Inst->isVolatile()));
14821485
}
14831486

@@ -1601,7 +1604,10 @@ template<typename ImplClass>
16011604
void
16021605
SILCloner<ImplClass>::visitInitExistentialAddrInst(InitExistentialAddrInst *Inst) {
16031606
CanType origFormalType = Inst->getFormalConcreteType();
1604-
auto conformances =getOpConformances(origFormalType, Inst->getConformances());
1607+
1608+
auto conformances = getOpConformances(origFormalType,
1609+
Inst->getConformances());
1610+
16051611
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
16061612
doPostProcess(Inst,
16071613
getBuilder().createInitExistentialAddr(getOpLocation(Inst->getLoc()),
@@ -1615,8 +1621,10 @@ template <typename ImplClass>
16151621
void SILCloner<ImplClass>::visitInitExistentialOpaqueInst(
16161622
InitExistentialOpaqueInst *Inst) {
16171623
CanType origFormalType = Inst->getFormalConcreteType();
1618-
auto conformances =
1619-
getOpConformances(origFormalType, Inst->getConformances());
1624+
1625+
auto conformances = getOpConformances(origFormalType,
1626+
Inst->getConformances());
1627+
16201628
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
16211629
doPostProcess(Inst,
16221630
getBuilder().createInitExistentialOpaque(
@@ -1629,8 +1637,10 @@ template<typename ImplClass>
16291637
void
16301638
SILCloner<ImplClass>::
16311639
visitInitExistentialMetatypeInst(InitExistentialMetatypeInst *Inst) {
1632-
auto conformances = getOpConformances(Inst->getFormalErasedObjectType(),
1640+
auto origFormalType = Inst->getFormalErasedObjectType();
1641+
auto conformances = getOpConformances(origFormalType,
16331642
Inst->getConformances());
1643+
16341644
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
16351645
doPostProcess(Inst,
16361646
getBuilder().createInitExistentialMetatype(getOpLocation(Inst->getLoc()),
@@ -1644,7 +1654,9 @@ void
16441654
SILCloner<ImplClass>::
16451655
visitInitExistentialRefInst(InitExistentialRefInst *Inst) {
16461656
CanType origFormalType = Inst->getFormalConcreteType();
1647-
auto conformances =getOpConformances(origFormalType, Inst->getConformances());
1657+
auto conformances = getOpConformances(origFormalType,
1658+
Inst->getConformances());
1659+
16481660
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
16491661
doPostProcess(Inst,
16501662
getBuilder().createInitExistentialRef(getOpLocation(Inst->getLoc()),

include/swift/SIL/TypeSubstCloner.h

Lines changed: 4 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -96,53 +96,13 @@ class TypeSubstCloner : public SILClonerWithScopes<ImplClass> {
9696
return ty.subst(SubsMap)->getCanonicalType();
9797
}
9898

99-
Substitution remapSubstitution(Substitution sub) {
100-
// Remap opened archetypes into the cloned context.
101-
sub = Substitution(
102-
getASTTypeInClonedContext(sub.getReplacement()->getCanonicalType()),
103-
sub.getConformances());
104-
// Now remap the substitution.
105-
return sub.subst(SubsMap);
106-
}
107-
108-
ProtocolConformanceRef remapConformance(CanType type,
99+
ProtocolConformanceRef remapConformance(Type type,
109100
ProtocolConformanceRef conf) {
110-
Substitution sub(type, conf);
111-
return remapSubstitution(sub).getConformances()[0];
112-
}
113-
114-
void visitClassMethodInst(ClassMethodInst *Inst) {
115-
getBuilder().setCurrentDebugScope(super::getOpScope(Inst->getDebugScope()));
116-
doPostProcess(Inst,
117-
getBuilder().createClassMethod(getOpLocation(Inst->getLoc()),
118-
getOpValue(Inst->getOperand()),
119-
Inst->getMember(),
120-
// No need to
121-
// translate the
122-
// return type
123-
// because this is
124-
// the type of the
125-
// fetched method.
126-
Inst->getType(),
127-
Inst->isVolatile()));
101+
return conf.subst(type,
102+
QuerySubstitutionMap{SubsMap},
103+
LookUpConformanceInSubstitutionMap(SubsMap));
128104
}
129-
130-
void visitBuiltinInst(BuiltinInst *Inst) {
131-
auto Args = this->template getOpValueArray<8>(Inst->getArguments());
132105

133-
SmallVector<Substitution, 16> TempSubstList;
134-
for (auto &Sub : Inst->getSubstitutions()) {
135-
TempSubstList.push_back(asImpl().getOpSubstitution(Sub));
136-
}
137-
138-
getBuilder().setCurrentDebugScope(super::getOpScope(Inst->getDebugScope()));
139-
auto N = getBuilder().createBuiltin(getOpLocation(Inst->getLoc()),
140-
Inst->getName(),
141-
getOpType(Inst->getType()),
142-
TempSubstList, Args);
143-
doPostProcess(Inst, N);
144-
}
145-
146106
void visitApplyInst(ApplyInst *Inst) {
147107
auto Args = this->template getOpValueArray<8>(Inst->getArguments());
148108

@@ -209,39 +169,6 @@ class TypeSubstCloner : public SILClonerWithScopes<ImplClass> {
209169
getOpType(Inst->getType()));
210170
}
211171

212-
void visitWitnessMethodInst(WitnessMethodInst *Inst) {
213-
// Specialize the Self substitution of the witness_method.
214-
auto sub = Inst->getSelfSubstitution();
215-
sub = sub.subst(SubsMap);
216-
217-
assert(sub.getConformances().size() == 1 &&
218-
"didn't get conformance from substitution?!");
219-
220-
auto Conformance = sub.getConformances()[0];
221-
222-
auto newLookupType = getOpASTType(Inst->getLookupType());
223-
if (Conformance.isConcrete()) {
224-
CanType Ty = Conformance.getConcrete()->getType()->getCanonicalType();
225-
226-
if (Ty != newLookupType) {
227-
assert(Ty->isExactSuperclassOf(newLookupType, nullptr) &&
228-
"Should only create upcasts for sub class.");
229-
230-
// We use the super class as the new look up type.
231-
newLookupType = Ty;
232-
}
233-
}
234-
235-
// We already subst so getOpConformance is not needed.
236-
getBuilder().setCurrentDebugScope(super::getOpScope(Inst->getDebugScope()));
237-
doPostProcess(
238-
Inst,
239-
getBuilder().createWitnessMethod(
240-
getOpLocation(Inst->getLoc()), newLookupType, Conformance,
241-
Inst->getMember(), getOpType(Inst->getType()),
242-
Inst->isVolatile()));
243-
}
244-
245172
/// Attempt to simplify a conditional checked cast.
246173
void visitCheckedCastAddrBranchInst(CheckedCastAddrBranchInst *inst) {
247174
SILLocation loc = getOpLocation(inst->getLoc());

0 commit comments

Comments
 (0)