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.
|
||||
auto components = CG.computeConnectedComponents(CS.TypeVariables);
|
||||
unsigned numComponents =
|
||||
components.size() + CG.getOrphanedConstraints().size();
|
||||
unsigned numComponents = components.size();
|
||||
if (numComponents < 2) {
|
||||
componentSteps.push_back(llvm::make_unique<ComponentStep>(
|
||||
CS, 0, &CS.InactiveConstraints, Solutions));
|
||||
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()) {
|
||||
auto &log = getDebugLogger();
|
||||
// Verify that the constraint graph is valid.
|
||||
@@ -135,6 +116,19 @@ void SplitterStep::computeFollowupSteps(
|
||||
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
|
||||
// with constraints in each step - e.g. number of disjunctions,
|
||||
// since components are going to be executed in LIFO order, we'd
|
||||
|
||||
@@ -366,6 +366,13 @@ public:
|
||||
: SolverStep(cs, solutions), Index(index), IsSingle(false),
|
||||
OriginalScore(getCurrentScore()), OriginalBestScore(getBestScore()),
|
||||
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);
|
||||
|
||||
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:
|
||||
/// Record a constraint as associated with this step.
|
||||
void record(Constraint *constraint) {
|
||||
@@ -418,7 +413,8 @@ private:
|
||||
getDebugLogger() << "(solving component #" << Index << '\n';
|
||||
|
||||
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.
|
||||
CS.CG.setOrphanedConstraint(OrphanedConstraint);
|
||||
}
|
||||
|
||||
@@ -540,6 +540,8 @@ namespace {
|
||||
|
||||
// Assign each type variable to its appropriate component.
|
||||
SmallVector<Component, 1> components;
|
||||
components.reserve(
|
||||
validComponents.size() + cg.getOrphanedConstraints().size());
|
||||
llvm::SmallDenseMap<TypeVariableType *, unsigned> componentIdxMap;
|
||||
for (auto typeVar : typeVars) {
|
||||
// Find the representative. If we aren't creating a type variable
|
||||
@@ -577,6 +579,12 @@ namespace {
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -635,7 +643,6 @@ ConstraintGraph::computeConnectedComponents(
|
||||
// Perform connected components via a union-find algorithm on all of the
|
||||
// constraints adjacent to these type variables.
|
||||
ConnectedComponents cc(*this, typeVars);
|
||||
|
||||
return cc.getComponents();
|
||||
}
|
||||
|
||||
|
||||
@@ -213,7 +213,7 @@ public:
|
||||
TinyPtrVector<Constraint *> constraints;
|
||||
|
||||
/// Whether this component represents an orphaned constraint.
|
||||
bool isOrphanedConstraint() const {
|
||||
bool isOrphaned() const {
|
||||
return typeVars.empty();
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user