Take first steps towards simplifying the constraint graph by performing edge contraction.

This commit is contained in:
Joe Pamer
2015-12-03 15:52:57 -08:00
parent c64b78c5bc
commit 37032b2a58
5 changed files with 106 additions and 1 deletions

View File

@@ -1323,9 +1323,20 @@ ConstraintSystem::matchTypes(Type type1, Type type2, TypeMatchKind kind,
}
SWIFT_FALLTHROUGH;
case TypeMatchKind::Conversion:
if (typeVar1 && typeVar2) {
auto rep1 = getRepresentative(typeVar1);
auto rep2 = getRepresentative(typeVar2);
if (rep1 == rep2) {
// We already merged these two types, so this constraint is
// trivially solved.
return SolutionKind::Solved;
}
}
SWIFT_FALLTHROUGH;
case TypeMatchKind::ConformsTo:
case TypeMatchKind::Subtype:
case TypeMatchKind::Conversion:
case TypeMatchKind::ExplicitConversion:
case TypeMatchKind::ArgumentConversion:
case TypeMatchKind::OperatorArgumentTupleConversion:

View File

@@ -821,6 +821,15 @@ static PotentialBindings getPotentialBindings(ConstraintSystem &cs,
auto first = cs.simplifyType(constraint->getFirstType());
auto second = cs.simplifyType(constraint->getSecondType());
if (auto firstTyvar = first->getAs<TypeVariableType>()) {
if (auto secondTyvar = second->getAs<TypeVariableType>()) {
if (cs.getRepresentative(firstTyvar) ==
cs.getRepresentative(secondTyvar)) {
break;
}
}
}
Type type;
AllowedBindingKind kind;
if (first->getAs<TypeVariableType>() == typeVar) {
@@ -1242,6 +1251,9 @@ bool ConstraintSystem::solveRec(SmallVectorImpl<Solution> &solutions,
return false;
}
// Contract the edges of the constraint graph.
CG.optimize();
// Compute the connected components of the constraint graph.
// FIXME: We're seeding typeVars with TypeVariables so that the
// connected-components algorithm only considers those type variables within

View File

@@ -687,6 +687,74 @@ unsigned ConstraintGraph::computeConnectedComponents(
return numComponents;
}
bool ConstraintGraph::contractEdges() {
llvm::SetVector<std::pair<TypeVariableType *,
TypeVariableType *>> contractions;
auto tyvars = getTypeVariables();
auto didContractEdges = false;
for (auto tyvar : tyvars) {
SmallVector<Constraint *, 4> constraints;
gatherConstraints(tyvar, constraints);
for (auto constraint : constraints) {
// Contract binding edges between type variables.
if (constraint->getKind() == ConstraintKind::Conversion ||
constraint->getKind() == ConstraintKind::Bind ||
constraint->getKind() == ConstraintKind::Equal) {
if (auto tyvar1 = constraint->getFirstType()->
getAs<TypeVariableType>()) {
if (auto tyvar2 = constraint->getSecondType()->
getAs<TypeVariableType>()) {
auto rep1 = CS.getRepresentative(tyvar1);
auto rep2 = CS.getRepresentative(tyvar2);
if (rep1 != rep2) {
if (rep1->getImpl().canBindToLValue() ==
rep2->getImpl().canBindToLValue()) {
// Merge the edges and remove the constraint.
CS.mergeEquivalenceClasses(rep1, rep2);
didContractEdges = true;
removeEdge(constraint);
}
}
}
}
}
}
}
return didContractEdges;
}
void ConstraintGraph::removeEdge(Constraint *constraint) {
for (auto &active : CS.ActiveConstraints) {
if (&active == constraint) {
CS.ActiveConstraints.erase(constraint);
break;
}
}
for (auto &inactive : CS.InactiveConstraints) {
if (&inactive == constraint) {
CS.InactiveConstraints.erase(constraint);
break;
}
}
removeConstraint(constraint);
}
void ConstraintGraph::optimize() {
// Merge equivalence classes until a fixed point is reached.
while(contractEdges()) {}
}
#pragma mark Debugging output
void ConstraintGraphNode::print(llvm::raw_ostream &out, unsigned indent) {

View File

@@ -287,6 +287,10 @@ public:
/// Verify the invariants of the graph.
void verify();
/// Optimize the constraint graph by eliminating simple transitive
/// connections between nodes.
void optimize();
private:
/// Remove the node corresponding to the given type variable.
///
@@ -304,6 +308,15 @@ private:
/// caution.
void unbindTypeVariable(TypeVariableType *typeVar, Type fixedType);
/// Perform edge contraction on the constraint graph, merging equivalence
/// classes until a fixed point is reached.
bool contractEdges();
/// To support edge contraction, remove a constraint from both the constraint
/// graph and its enclosing constraint system.
void removeEdge(Constraint *constraint);
/// The constraint system.
ConstraintSystem &CS;

View File

@@ -878,6 +878,7 @@ public:
friend class Fix;
friend class OverloadChoice;
friend class ConstraintGraph;
class SolverScope;