mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
[Constraint graph] Handle orphaned constraints within connected components
Move the logic for creating connected components of orphaned constraints into the connected-components algorithm code, rather than making it a special part of SplitterStep.
This commit is contained in:
@@ -97,32 +97,13 @@ void SplitterStep::computeFollowupSteps(
|
|||||||
|
|
||||||
// Compute the connected components of the constraint graph.
|
// Compute the connected components of the constraint graph.
|
||||||
auto components = CG.computeConnectedComponents(CS.TypeVariables);
|
auto components = CG.computeConnectedComponents(CS.TypeVariables);
|
||||||
unsigned numComponents =
|
unsigned numComponents = components.size();
|
||||||
components.size() + CG.getOrphanedConstraints().size();
|
|
||||||
if (numComponents < 2) {
|
if (numComponents < 2) {
|
||||||
componentSteps.push_back(llvm::make_unique<ComponentStep>(
|
componentSteps.push_back(llvm::make_unique<ComponentStep>(
|
||||||
CS, 0, &CS.InactiveConstraints, Solutions));
|
CS, 0, &CS.InactiveConstraints, Solutions));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Components.resize(numComponents);
|
|
||||||
PartialSolutions = std::unique_ptr<SmallVector<Solution, 4>[]>(
|
|
||||||
new SmallVector<Solution, 4>[numComponents]);
|
|
||||||
|
|
||||||
// Add components.
|
|
||||||
for (unsigned i : indices(components)) {
|
|
||||||
componentSteps.push_back(llvm::make_unique<ComponentStep>(
|
|
||||||
CS, i, &Components[i], std::move(components[i]), PartialSolutions[i]));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add components for the orphaned constraints.
|
|
||||||
OrphanedConstraints = CG.takeOrphanedConstraints();
|
|
||||||
for (unsigned i : range(components.size(), numComponents)) {
|
|
||||||
auto orphaned = OrphanedConstraints[i - components.size()];
|
|
||||||
componentSteps.push_back(llvm::make_unique<ComponentStep>(
|
|
||||||
CS, i, &Components[i], orphaned, PartialSolutions[i]));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isDebugMode()) {
|
if (isDebugMode()) {
|
||||||
auto &log = getDebugLogger();
|
auto &log = getDebugLogger();
|
||||||
// Verify that the constraint graph is valid.
|
// Verify that the constraint graph is valid.
|
||||||
@@ -135,6 +116,19 @@ void SplitterStep::computeFollowupSteps(
|
|||||||
CG.printConnectedComponents(CS.TypeVariables, log);
|
CG.printConnectedComponents(CS.TypeVariables, log);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Take the orphaned constraints, because they'll go into a component now.
|
||||||
|
OrphanedConstraints = CG.takeOrphanedConstraints();
|
||||||
|
|
||||||
|
Components.resize(numComponents);
|
||||||
|
PartialSolutions = std::unique_ptr<SmallVector<Solution, 4>[]>(
|
||||||
|
new SmallVector<Solution, 4>[numComponents]);
|
||||||
|
|
||||||
|
// Add components.
|
||||||
|
for (unsigned i : indices(components)) {
|
||||||
|
componentSteps.push_back(llvm::make_unique<ComponentStep>(
|
||||||
|
CS, i, &Components[i], std::move(components[i]), PartialSolutions[i]));
|
||||||
|
}
|
||||||
|
|
||||||
// Create component ordering based on the information associated
|
// Create component ordering based on the information associated
|
||||||
// with constraints in each step - e.g. number of disjunctions,
|
// with constraints in each step - e.g. number of disjunctions,
|
||||||
// since components are going to be executed in LIFO order, we'd
|
// since components are going to be executed in LIFO order, we'd
|
||||||
|
|||||||
@@ -366,6 +366,13 @@ public:
|
|||||||
: SolverStep(cs, solutions), Index(index), IsSingle(false),
|
: SolverStep(cs, solutions), Index(index), IsSingle(false),
|
||||||
OriginalScore(getCurrentScore()), OriginalBestScore(getBestScore()),
|
OriginalScore(getCurrentScore()), OriginalBestScore(getBestScore()),
|
||||||
Constraints(constraints) {
|
Constraints(constraints) {
|
||||||
|
if (component.isOrphaned()) {
|
||||||
|
assert(component.constraints.size() == 1);
|
||||||
|
OrphanedConstraint = component.constraints.front();
|
||||||
|
} else {
|
||||||
|
assert(component.typeVars.size() > 0);
|
||||||
|
}
|
||||||
|
|
||||||
TypeVars = std::move(component.typeVars);
|
TypeVars = std::move(component.typeVars);
|
||||||
|
|
||||||
for (auto constraint : component.constraints) {
|
for (auto constraint : component.constraints) {
|
||||||
@@ -374,18 +381,6 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a component step for an orphaned constraint.
|
|
||||||
ComponentStep(ConstraintSystem &cs, unsigned index,
|
|
||||||
ConstraintList *constraints,
|
|
||||||
Constraint *orphaned,
|
|
||||||
SmallVectorImpl<Solution> &solutions)
|
|
||||||
: SolverStep(cs, solutions), Index(index), IsSingle(false),
|
|
||||||
OriginalScore(getCurrentScore()), OriginalBestScore(getBestScore()),
|
|
||||||
Constraints(constraints), OrphanedConstraint(orphaned) {
|
|
||||||
constraints->erase(orphaned);
|
|
||||||
record(orphaned);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// Record a constraint as associated with this step.
|
/// Record a constraint as associated with this step.
|
||||||
void record(Constraint *constraint) {
|
void record(Constraint *constraint) {
|
||||||
@@ -418,7 +413,8 @@ private:
|
|||||||
getDebugLogger() << "(solving component #" << Index << '\n';
|
getDebugLogger() << "(solving component #" << Index << '\n';
|
||||||
|
|
||||||
ComponentScope = llvm::make_unique<Scope>(*this);
|
ComponentScope = llvm::make_unique<Scope>(*this);
|
||||||
// If this component has oprhaned constraint attached,
|
|
||||||
|
// If this component has orphaned constraint attached,
|
||||||
// let's return it to the graph.
|
// let's return it to the graph.
|
||||||
CS.CG.setOrphanedConstraint(OrphanedConstraint);
|
CS.CG.setOrphanedConstraint(OrphanedConstraint);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -540,6 +540,8 @@ namespace {
|
|||||||
|
|
||||||
// Assign each type variable to its appropriate component.
|
// Assign each type variable to its appropriate component.
|
||||||
SmallVector<Component, 1> components;
|
SmallVector<Component, 1> components;
|
||||||
|
components.reserve(
|
||||||
|
validComponents.size() + cg.getOrphanedConstraints().size());
|
||||||
llvm::SmallDenseMap<TypeVariableType *, unsigned> componentIdxMap;
|
llvm::SmallDenseMap<TypeVariableType *, unsigned> componentIdxMap;
|
||||||
for (auto typeVar : typeVars) {
|
for (auto typeVar : typeVars) {
|
||||||
// Find the representative. If we aren't creating a type variable
|
// Find the representative. If we aren't creating a type variable
|
||||||
@@ -577,6 +579,12 @@ namespace {
|
|||||||
components[componentIdxMap[rep]].constraints.push_back(&constraint);
|
components[componentIdxMap[rep]].constraints.push_back(&constraint);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Gather orphaned constraints; each gets its own component.
|
||||||
|
for (auto orphaned : cg.getOrphanedConstraints()) {
|
||||||
|
components.push_back({ });
|
||||||
|
components.back().constraints.push_back(orphaned);
|
||||||
|
}
|
||||||
|
|
||||||
return components;
|
return components;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -635,7 +643,6 @@ ConstraintGraph::computeConnectedComponents(
|
|||||||
// Perform connected components via a union-find algorithm on all of the
|
// Perform connected components via a union-find algorithm on all of the
|
||||||
// constraints adjacent to these type variables.
|
// constraints adjacent to these type variables.
|
||||||
ConnectedComponents cc(*this, typeVars);
|
ConnectedComponents cc(*this, typeVars);
|
||||||
|
|
||||||
return cc.getComponents();
|
return cc.getComponents();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -213,7 +213,7 @@ public:
|
|||||||
TinyPtrVector<Constraint *> constraints;
|
TinyPtrVector<Constraint *> constraints;
|
||||||
|
|
||||||
/// Whether this component represents an orphaned constraint.
|
/// Whether this component represents an orphaned constraint.
|
||||||
bool isOrphanedConstraint() const {
|
bool isOrphaned() const {
|
||||||
return typeVars.empty();
|
return typeVars.empty();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user