[ConstraintGraph] Optimize edge contraction

Previously on every step solver would iterate over all
constraints in attempt to find `BindParam` which could
be contracted. Instead of doing that, let's take advantage
of the fact that all (participating) closures are recorded
in the constraint system during constraint generation, so
it should be possible to check either outer parameter types
are contractable with their inner uses.
This commit is contained in:
Pavel Yaskevich
2021-03-01 17:23:11 -08:00
parent 03e0c4a2d1
commit 0cc0a3a5f1

View File

@@ -1312,12 +1312,36 @@ static bool shouldContractEdge(ConstraintKind kind) {
}
bool ConstraintGraph::contractEdges() {
// Current constraint system doesn't have any closure expressions
// associated with it so there is nothing to here.
if (CS.ClosureTypes.empty())
return false;
SmallVector<Constraint *, 16> constraints;
CS.findConstraints(constraints, [&](const Constraint &constraint) {
// Track how many constraints did contraction algorithm iterated over.
incrementConstraintsPerContractionCounter();
return shouldContractEdge(constraint.getKind());
});
for (const auto &closure : CS.ClosureTypes) {
for (const auto &param : closure.second->getParams()) {
auto paramTy = param.getPlainType()->getAs<TypeVariableType>();
if (!paramTy)
continue;
// This closure is not currently in scope.
if (!CS.TypeVariables.count(paramTy))
break;
// Nothing to contract here since outside parameter
// is already bound to a concrete type.
if (CS.getFixedType(paramTy))
continue;
for (auto *constraint : (*this)[paramTy].getConstraints()) {
// Track how many constraints did contraction algorithm iterated over.
incrementConstraintsPerContractionCounter();
if (shouldContractEdge(constraint->getKind()))
constraints.push_back(constraint);
}
}
}
bool didContractEdges = false;
for (auto *constraint : constraints) {