Skip to content

Small devirtualizer cleanup and fix #9109

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Apr 28, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 0 additions & 11 deletions include/swift/AST/GenericSignature.h
Original file line number Diff line number Diff line change
Expand Up @@ -201,17 +201,6 @@ class alignas(1 << TypeAlignInBits) GenericSignature final
Optional<ProtocolConformanceRef>
lookupConformance(CanType depTy, ProtocolDecl *proto) const;

using GenericFunction = auto(CanType canType, Type conformingReplacementType,
ProtocolType *conformedProtocol)
->Optional<ProtocolConformanceRef>;
using LookupConformanceFn = llvm::function_ref<GenericFunction>;

/// Build an array of substitutions from an interface type substitution map,
/// using the given function to look up conformances.
void getSubstitutions(TypeSubstitutionFn substitution,
LookupConformanceFn lookupConformance,
SmallVectorImpl<Substitution> &result) const;

/// Build an array of substitutions from an interface type substitution map,
/// using the given function to look up conformances.
void getSubstitutions(const SubstitutionMap &subMap,
Expand Down
14 changes: 9 additions & 5 deletions lib/AST/GenericEnvironment.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -342,17 +342,21 @@ Type GenericEnvironment::getSugaredType(Type type) const {

SubstitutionList
GenericEnvironment::getForwardingSubstitutions() const {
auto *genericSig = getGenericSignature();

SubstitutionMap subMap = genericSig->getSubstitutionMap(
QueryInterfaceTypeSubstitutions(this),
MakeAbstractConformanceForGenericType());

SmallVector<Substitution, 4> result;
getGenericSignature()->getSubstitutions(QueryInterfaceTypeSubstitutions(this),
MakeAbstractConformanceForGenericType(),
result);
return getGenericSignature()->getASTContext().AllocateCopy(result);
genericSig->getSubstitutions(subMap, result);
return genericSig->getASTContext().AllocateCopy(result);
}

SubstitutionMap
GenericEnvironment::
getSubstitutionMap(TypeSubstitutionFn subs,
GenericSignature::LookupConformanceFn lookupConformance) const {
LookupConformanceFn lookupConformance) const {
SubstitutionMap subMap(const_cast<GenericEnvironment *>(this));

getGenericSignature()->enumeratePairedRequirements(
Expand Down
25 changes: 7 additions & 18 deletions lib/AST/GenericSignature.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -405,7 +405,7 @@ GenericSignature::getSubstitutionMap(SubstitutionList subs) const {
SubstitutionMap
GenericSignature::
getSubstitutionMap(TypeSubstitutionFn subs,
GenericSignature::LookupConformanceFn lookupConformance) const {
LookupConformanceFn lookupConformance) const {
SubstitutionMap subMap(const_cast<GenericSignature *>(this));

// Enumerate all of the requirements that require substitution.
Expand Down Expand Up @@ -437,33 +437,30 @@ getSubstitutionMap(TypeSubstitutionFn subs,
}

void GenericSignature::
getSubstitutions(TypeSubstitutionFn subs,
GenericSignature::LookupConformanceFn lookupConformance,
getSubstitutions(const SubstitutionMap &subMap,
SmallVectorImpl<Substitution> &result) const {

// Enumerate all of the requirements that require substitution.
enumeratePairedRequirements([&](Type depTy, ArrayRef<Requirement> reqs) {
auto &ctx = getASTContext();

// Compute the replacement type.
Type currentReplacement = depTy.subst(subs, lookupConformance);
Type currentReplacement = depTy.subst(subMap);
if (!currentReplacement)
currentReplacement = ErrorType::get(depTy);

// Collect the conformances.
SmallVector<ProtocolConformanceRef, 4> currentConformances;
for (auto req: reqs) {
assert(req.getKind() == RequirementKind::Conformance);
auto protoType = req.getSecondType()->castTo<ProtocolType>();
if (auto conformance = lookupConformance(depTy->getCanonicalType(),
currentReplacement,
protoType)) {
auto protoDecl = req.getSecondType()->castTo<ProtocolType>()->getDecl();
if (auto conformance = subMap.lookupConformance(depTy->getCanonicalType(),
protoDecl)) {
currentConformances.push_back(*conformance);
} else {
if (!currentReplacement->hasError())
currentReplacement = ErrorType::get(currentReplacement);
currentConformances.push_back(
ProtocolConformanceRef(protoType->getDecl()));
currentConformances.push_back(ProtocolConformanceRef(protoDecl));
}
}

Expand All @@ -477,14 +474,6 @@ getSubstitutions(TypeSubstitutionFn subs,
});
}

void GenericSignature::
getSubstitutions(const SubstitutionMap &subMap,
SmallVectorImpl<Substitution> &result) const {
getSubstitutions(QuerySubstitutionMap{subMap},
LookUpConformanceInSubstitutionMap(subMap),
result);
}

bool GenericSignature::requiresClass(Type type, ModuleDecl &mod) {
if (!type->isTypeParameter()) return false;

Expand Down
10 changes: 5 additions & 5 deletions lib/SIL/TypeLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2518,17 +2518,17 @@ TypeConverter::getInterfaceBoxTypeForCapture(ValueDecl *captured,
SILField(loweredInterfaceType, isMutable));

// Instantiate the layout with identity substitutions.
SmallVector<Substitution, 4> genericArgs;
signature->getSubstitutions(
[&](SubstitutableType* type) -> Type {
auto subMap = signature->getSubstitutionMap(
[&](SubstitutableType *type) -> Type {
return signature->getCanonicalTypeInContext(type,
*M.getSwiftModule());
},
[](Type depTy, Type replacementTy, ProtocolType *conformedTy)
-> ProtocolConformanceRef {
return ProtocolConformanceRef(conformedTy->getDecl());
},
genericArgs);
});
SmallVector<Substitution, 4> genericArgs;
signature->getSubstitutions(subMap, genericArgs);

auto boxTy = SILBoxType::get(C, layout, genericArgs);
#ifndef NDEBUG
Expand Down
8 changes: 4 additions & 4 deletions lib/SILGen/SILGenConstructor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -926,8 +926,7 @@ void SILGenFunction::emitMemberInitializers(DeclContext *dc,
// Generate a set of substitutions for the initialization function,
// whose generic signature is that of the type context, and whose
// replacement types are the archetypes of the initializer itself.
SmallVector<Substitution, 4> subsVec;
typeGenericSig->getSubstitutions(
auto subMap = typeGenericSig->getSubstitutionMap(
[&](SubstitutableType *type) {
if (auto gp = type->getAs<GenericTypeParamType>()) {
return genericEnv->mapTypeIntoContext(gp);
Expand All @@ -940,8 +939,9 @@ void SILGenFunction::emitMemberInitializers(DeclContext *dc,
ProtocolType *conformedProtocol) {
return ProtocolConformanceRef(
conformedProtocol->getDecl());
},
subsVec);
});
SmallVector<Substitution, 4> subsVec;
typeGenericSig->getSubstitutions(subMap, subsVec);
subs = SGM.getASTContext().AllocateCopy(subsVec);
}

Expand Down
58 changes: 27 additions & 31 deletions lib/SILOptimizer/Utils/Devirtualize.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -778,23 +778,21 @@ getSubstitutionsForProtocolConformance(ProtocolConformanceRef CRef) {
/// \param requirementSig The generic signature of the requirement
/// \param witnessThunkSig The generic signature of the witness method
/// \param origSubs The substitutions from the call instruction
/// \param newSubs New substitutions are stored here
static void getWitnessMethodSubstitutions(
SILModule &M,
static SubstitutionMap
getWitnessMethodSubstitutions(
ProtocolConformanceRef conformanceRef,
GenericSignature *requirementSig,
GenericSignature *witnessThunkSig,
SubstitutionList origSubs,
bool isDefaultWitness,
SmallVectorImpl<Substitution> &newSubs) {
bool isDefaultWitness) {

if (witnessThunkSig == nullptr)
return;
return SubstitutionMap();

if (isDefaultWitness) {
newSubs.append(origSubs.begin(), origSubs.end());
return;
}
auto origSubMap = requirementSig->getSubstitutionMap(origSubs);

if (isDefaultWitness)
return origSubMap;

assert(!conformanceRef.isAbstract());
auto conformance = conformanceRef.getConcrete();
Expand All @@ -809,24 +807,19 @@ static void getWitnessMethodSubstitutions(
baseDepth = witnessSig->getGenericParams().back()->getDepth() + 1;

auto origDepth = 1;
auto origSubMap = requirementSig->getSubstitutionMap(origSubs);

auto subMap =
SubstitutionMap::combineSubstitutionMaps(baseSubMap,
origSubMap,
CombineSubstitutionMaps::AtDepth,
baseDepth,
origDepth,
witnessThunkSig);

witnessThunkSig->getSubstitutions(subMap, newSubs);
return SubstitutionMap::combineSubstitutionMaps(
baseSubMap,
origSubMap,
CombineSubstitutionMaps::AtDepth,
baseDepth,
origDepth,
witnessThunkSig);
}

static void getWitnessMethodSubstitutions(ApplySite AI, SILFunction *F,
ProtocolConformanceRef CRef,
SmallVectorImpl<Substitution> &NewSubs) {
auto &Module = AI.getModule();

static SubstitutionMap
getWitnessMethodSubstitutions(SILModule &Module, ApplySite AI, SILFunction *F,
ProtocolConformanceRef CRef) {
auto requirementSig = AI.getOrigCalleeType()->getGenericSignature();
auto witnessThunkSig = F->getLoweredFunctionType()->getGenericSignature();

Expand All @@ -839,8 +832,9 @@ static void getWitnessMethodSubstitutions(ApplySite AI, SILFunction *F,
*Module.getSwiftModule())
== CRef.getRequirement();

getWitnessMethodSubstitutions(Module, CRef, requirementSig, witnessThunkSig,
origSubs, isDefaultWitness, NewSubs);
return getWitnessMethodSubstitutions(
CRef, requirementSig, witnessThunkSig,
origSubs, isDefaultWitness);
}

/// Generate a new apply of a function_ref to replace an apply of a
Expand All @@ -858,14 +852,12 @@ devirtualizeWitnessMethod(ApplySite AI, SILFunction *F,
// The complete set of substitutions may be different, e.g. because the found
// witness thunk F may have been created by a specialization pass and have
// additional generic parameters.
SmallVector<Substitution, 4> NewSubs;

getWitnessMethodSubstitutions(AI, F, C, NewSubs);
auto SubMap = getWitnessMethodSubstitutions(Module, AI, F, C);

// Figure out the exact bound type of the function to be called by
// applying all substitutions.
auto CalleeCanType = F->getLoweredFunctionType();
auto SubstCalleeCanType = CalleeCanType->substGenericArgs(Module, NewSubs);
auto SubstCalleeCanType = CalleeCanType->substGenericArgs(Module, SubMap);

// Collect arguments from the apply instruction.
auto Arguments = SmallVector<SILValue, 4>();
Expand Down Expand Up @@ -894,6 +886,10 @@ devirtualizeWitnessMethod(ApplySite AI, SILFunction *F,
auto ResultSILType = substConv.getSILResultType();
ApplySite SAI;

SmallVector<Substitution, 4> NewSubs;
if (auto GenericSig = CalleeCanType->getGenericSignature())
GenericSig->getSubstitutions(SubMap, NewSubs);

SILValue ResultValue;
if (auto *A = dyn_cast<ApplyInst>(AI)) {
auto *NewAI =
Expand Down
8 changes: 4 additions & 4 deletions lib/SILOptimizer/Utils/Generics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1299,9 +1299,7 @@ FunctionSignaturePartialSpecializer::

void FunctionSignaturePartialSpecializer::computeClonerParamSubs(
SubstitutionList &ClonerParamSubs) {
SmallVector<Substitution, 4> List;

CalleeGenericSig->getSubstitutions(
auto SubMap = CalleeGenericSig->getSubstitutionMap(
[&](SubstitutableType *type) -> Type {
DEBUG(llvm::dbgs() << "\ngetSubstitution for ClonerParamSubs:\n"
<< Type(type) << "\n"
Expand All @@ -1312,8 +1310,10 @@ void FunctionSignaturePartialSpecializer::computeClonerParamSubs(
return SpecializedGenericEnv->mapTypeIntoContext(
SpecializedInterfaceTy);
},
LookUpConformanceInSignature(*SpecializedGenericSig), List);
LookUpConformanceInSignature(*SpecializedGenericSig));

SmallVector<Substitution, 4> List;
CalleeGenericSig->getSubstitutions(SubMap, List);
ClonerParamSubs = Ctx.AllocateCopy(List);
verifySubstitutionList(ClonerParamSubs, "ClonerParamSubs");
}
Expand Down
7 changes: 5 additions & 2 deletions lib/Sema/CSApply.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -95,8 +95,11 @@ void Solution::computeSubstitutions(
ConformanceCheckFlags::Used));
};

sig->getSubstitutions(QueryTypeSubstitutionMap{subs},
lookupConformanceFn, result);
auto subMap = sig->getSubstitutionMap(
QueryTypeSubstitutionMap{subs},
lookupConformanceFn);

sig->getSubstitutions(subMap, result);
}

void Solution::computeSubstitutions(
Expand Down
12 changes: 3 additions & 9 deletions lib/Sema/TypeCheckType.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2479,7 +2479,7 @@ Type TypeResolver::resolveSILBoxType(SILBoxTypeRepr *repr,
}

bool ok = true;
genericSig->getSubstitutions(
auto subMap = genericSig->getSubstitutionMap(
QueryTypeSubstitutionMap{genericArgMap},
[&](CanType depTy, Type replacement, ProtocolType *proto)
-> ProtocolConformanceRef {
Expand All @@ -2492,17 +2492,11 @@ Type TypeResolver::resolveSILBoxType(SILBoxTypeRepr *repr,
}

return *result;
},
genericArgs);
});
genericSig->getSubstitutions(subMap, genericArgs);

if (!ok)
return ErrorType::get(Context);

// Canonicalize the replacement types.
for (auto &arg : genericArgs) {
arg = Substitution(arg.getReplacement()->getCanonicalType(),
arg.getConformances());
}
}

auto layout = SILLayout::get(Context, genericSig, fields);
Expand Down