mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Revert "Sema: Remove DependentComponentSplitterStep"
This reverts commit 9fb6d9251e.
This commit is contained in:
@@ -343,6 +343,12 @@ public:
|
|||||||
/// The constraints in this component.
|
/// The constraints in this component.
|
||||||
TinyPtrVector<Constraint *> constraints;
|
TinyPtrVector<Constraint *> constraints;
|
||||||
|
|
||||||
|
/// The set of components that this component depends on, such that
|
||||||
|
/// the partial solutions of the those components need to be available
|
||||||
|
/// before this component can be solved.
|
||||||
|
///
|
||||||
|
SmallVector<unsigned, 2> dependencies;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Component(unsigned solutionIndex) : solutionIndex(solutionIndex) { }
|
Component(unsigned solutionIndex) : solutionIndex(solutionIndex) { }
|
||||||
|
|
||||||
@@ -358,6 +364,11 @@ public:
|
|||||||
return constraints;
|
return constraints;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Records a component which this component depends on.
|
||||||
|
void recordDependency(const Component &component);
|
||||||
|
|
||||||
|
ArrayRef<unsigned> getDependencies() const { return dependencies; }
|
||||||
|
|
||||||
unsigned getNumDisjunctions() const { return numDisjunctions; }
|
unsigned getNumDisjunctions() const { return numDisjunctions; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -126,6 +126,7 @@ void SplitterStep::computeFollowupSteps(
|
|||||||
// Take the orphaned constraints, because they'll go into a component now.
|
// Take the orphaned constraints, because they'll go into a component now.
|
||||||
OrphanedConstraints = CG.takeOrphanedConstraints();
|
OrphanedConstraints = CG.takeOrphanedConstraints();
|
||||||
|
|
||||||
|
IncludeInMergedResults.resize(numComponents, true);
|
||||||
Components.resize(numComponents);
|
Components.resize(numComponents);
|
||||||
PartialSolutions = std::unique_ptr<SmallVector<Solution, 4>[]>(
|
PartialSolutions = std::unique_ptr<SmallVector<Solution, 4>[]>(
|
||||||
new SmallVector<Solution, 4>[numComponents]);
|
new SmallVector<Solution, 4>[numComponents]);
|
||||||
@@ -134,9 +135,26 @@ void SplitterStep::computeFollowupSteps(
|
|||||||
for (unsigned i : indices(components)) {
|
for (unsigned i : indices(components)) {
|
||||||
unsigned solutionIndex = components[i].solutionIndex;
|
unsigned solutionIndex = components[i].solutionIndex;
|
||||||
|
|
||||||
steps.push_back(std::make_unique<ComponentStep>(
|
// If there are no dependencies, build a normal component step.
|
||||||
CS, solutionIndex, &Components[i], std::move(components[i]),
|
if (components[i].getDependencies().empty()) {
|
||||||
PartialSolutions[solutionIndex]));
|
steps.push_back(std::make_unique<ComponentStep>(
|
||||||
|
CS, solutionIndex, &Components[i], std::move(components[i]),
|
||||||
|
PartialSolutions[solutionIndex]));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note that the partial results from any dependencies of this component
|
||||||
|
// need not be included in the final merged results, because they'll
|
||||||
|
// already be part of the partial results for this component.
|
||||||
|
for (auto dependsOn : components[i].getDependencies()) {
|
||||||
|
IncludeInMergedResults[dependsOn] = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise, build a dependent component "splitter" step, which
|
||||||
|
// handles all combinations of incoming partial solutions.
|
||||||
|
steps.push_back(std::make_unique<DependentComponentSplitterStep>(
|
||||||
|
CS, &Components[i], solutionIndex, std::move(components[i]),
|
||||||
|
llvm::MutableArrayRef(PartialSolutions.get(), numComponents)));
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(CS.InactiveConstraints.empty() && "Missed a constraint");
|
assert(CS.InactiveConstraints.empty() && "Missed a constraint");
|
||||||
@@ -205,7 +223,8 @@ bool SplitterStep::mergePartialSolutions() const {
|
|||||||
SmallVector<unsigned, 2> countsVec;
|
SmallVector<unsigned, 2> countsVec;
|
||||||
countsVec.reserve(numComponents);
|
countsVec.reserve(numComponents);
|
||||||
for (unsigned idx : range(numComponents)) {
|
for (unsigned idx : range(numComponents)) {
|
||||||
countsVec.push_back(PartialSolutions[idx].size());
|
countsVec.push_back(
|
||||||
|
IncludeInMergedResults[idx] ? PartialSolutions[idx].size() : 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Produce all combinations of partial solutions.
|
// Produce all combinations of partial solutions.
|
||||||
@@ -218,6 +237,9 @@ bool SplitterStep::mergePartialSolutions() const {
|
|||||||
// solutions.
|
// solutions.
|
||||||
ConstraintSystem::SolverScope scope(CS);
|
ConstraintSystem::SolverScope scope(CS);
|
||||||
for (unsigned i : range(numComponents)) {
|
for (unsigned i : range(numComponents)) {
|
||||||
|
if (!IncludeInMergedResults[i])
|
||||||
|
continue;
|
||||||
|
|
||||||
CS.replaySolution(PartialSolutions[i][indices[i]]);
|
CS.replaySolution(PartialSolutions[i][indices[i]]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -249,15 +271,77 @@ bool SplitterStep::mergePartialSolutions() const {
|
|||||||
return anySolutions;
|
return anySolutions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
StepResult DependentComponentSplitterStep::take(bool prevFailed) {
|
||||||
|
// "split" is considered a failure if previous step failed,
|
||||||
|
// or there is a failure recorded by constraint system, or
|
||||||
|
// system can't be simplified.
|
||||||
|
if (prevFailed || CS.getFailedConstraint() || CS.simplify())
|
||||||
|
return done(/*isSuccess=*/false);
|
||||||
|
|
||||||
|
// Figure out the sets of partial solutions that this component depends on.
|
||||||
|
SmallVector<const SmallVector<Solution, 4> *, 2> dependsOnSets;
|
||||||
|
for (auto index : Component.getDependencies()) {
|
||||||
|
dependsOnSets.push_back(&AllPartialSolutions[index]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Produce all combinations of partial solutions for the inputs.
|
||||||
|
SmallVector<std::unique_ptr<SolverStep>, 4> followup;
|
||||||
|
SmallVector<unsigned, 2> indices(Component.getDependencies().size(), 0);
|
||||||
|
auto dependsOnSetsRef = llvm::ArrayRef(dependsOnSets);
|
||||||
|
do {
|
||||||
|
// Form the set of input partial solutions.
|
||||||
|
SmallVector<const Solution *, 2> dependsOnSolutions;
|
||||||
|
for (auto index : swift::indices(indices)) {
|
||||||
|
dependsOnSolutions.push_back(&(*dependsOnSets[index])[indices[index]]);
|
||||||
|
}
|
||||||
|
ContextualSolutions.push_back(std::make_unique<SmallVector<Solution, 2>>());
|
||||||
|
|
||||||
|
followup.push_back(std::make_unique<ComponentStep>(
|
||||||
|
CS, Index, Constraints, Component, std::move(dependsOnSolutions),
|
||||||
|
*ContextualSolutions.back()));
|
||||||
|
} while (nextCombination(dependsOnSetsRef, indices));
|
||||||
|
|
||||||
|
/// Wait until all of the component steps are done.
|
||||||
|
return suspend(followup);
|
||||||
|
}
|
||||||
|
|
||||||
|
StepResult DependentComponentSplitterStep::resume(bool prevFailed) {
|
||||||
|
for (auto &ComponentStepSolutions : ContextualSolutions) {
|
||||||
|
Solutions.append(std::make_move_iterator(ComponentStepSolutions->begin()),
|
||||||
|
std::make_move_iterator(ComponentStepSolutions->end()));
|
||||||
|
}
|
||||||
|
return done(/*isSuccess=*/!Solutions.empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
void DependentComponentSplitterStep::print(llvm::raw_ostream &Out) {
|
||||||
|
Out << "DependentComponentSplitterStep for dependencies on [";
|
||||||
|
interleave(
|
||||||
|
Component.getDependencies(), [&](unsigned index) { Out << index; },
|
||||||
|
[&] { Out << ", "; });
|
||||||
|
Out << "]\n";
|
||||||
|
}
|
||||||
|
|
||||||
StepResult ComponentStep::take(bool prevFailed) {
|
StepResult ComponentStep::take(bool prevFailed) {
|
||||||
// One of the previous components created by "split"
|
// One of the previous components created by "split"
|
||||||
// failed, it means that we can't solve this component.
|
// failed, it means that we can't solve this component.
|
||||||
if (prevFailed || CS.isTooComplex(Solutions) || CS.worseThanBestSolution())
|
if ((prevFailed && DependsOnPartialSolutions.empty()) ||
|
||||||
|
CS.isTooComplex(Solutions) || CS.worseThanBestSolution())
|
||||||
return done(/*isSuccess=*/false);
|
return done(/*isSuccess=*/false);
|
||||||
|
|
||||||
// Setup active scope, only if previous component didn't fail.
|
// Setup active scope, only if previous component didn't fail.
|
||||||
setupScope();
|
setupScope();
|
||||||
|
|
||||||
|
// If there are any dependent partial solutions to compose, do so now.
|
||||||
|
if (!DependsOnPartialSolutions.empty()) {
|
||||||
|
for (auto partial : DependsOnPartialSolutions) {
|
||||||
|
CS.replaySolution(*partial);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Simplify again.
|
||||||
|
if (CS.failedConstraint || CS.simplify())
|
||||||
|
return done(/*isSuccess=*/false);
|
||||||
|
}
|
||||||
|
|
||||||
/// Try to figure out what this step is going to be,
|
/// Try to figure out what this step is going to be,
|
||||||
/// after the scope has been established.
|
/// after the scope has been established.
|
||||||
SmallString<64> potentialBindings;
|
SmallString<64> potentialBindings;
|
||||||
|
|||||||
@@ -240,6 +240,10 @@ class SplitterStep final : public SolverStep {
|
|||||||
|
|
||||||
SmallVector<Constraint *, 4> OrphanedConstraints;
|
SmallVector<Constraint *, 4> OrphanedConstraints;
|
||||||
|
|
||||||
|
/// Whether to include the partial results of this component in the final
|
||||||
|
/// merged results.
|
||||||
|
SmallVector<bool, 4> IncludeInMergedResults;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SplitterStep(ConstraintSystem &cs, SmallVectorImpl<Solution> &solutions)
|
SplitterStep(ConstraintSystem &cs, SmallVectorImpl<Solution> &solutions)
|
||||||
: SolverStep(cs, solutions) {}
|
: SolverStep(cs, solutions) {}
|
||||||
@@ -265,6 +269,56 @@ private:
|
|||||||
bool mergePartialSolutions() const;
|
bool mergePartialSolutions() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// `DependentComponentSplitterStep` is responsible for composing the partial
|
||||||
|
/// solutions from other components (on which this component depends) into
|
||||||
|
/// the inputs based on which we can solve a particular component.
|
||||||
|
class DependentComponentSplitterStep final : public SolverStep {
|
||||||
|
/// Constraints "in scope" of this step.
|
||||||
|
ConstraintList *Constraints;
|
||||||
|
|
||||||
|
/// Index into the parent splitter step.
|
||||||
|
unsigned Index;
|
||||||
|
|
||||||
|
/// The component that has dependencies.
|
||||||
|
ConstraintGraph::Component Component;
|
||||||
|
|
||||||
|
/// Array containing all of the partial solutions for the parent split.
|
||||||
|
MutableArrayRef<SmallVector<Solution, 4>> AllPartialSolutions;
|
||||||
|
|
||||||
|
/// The solutions computed the \c ComponentSteps created for each partial
|
||||||
|
/// solution combinations. Will be merged into the final \c Solutions vector
|
||||||
|
/// in \c resume.
|
||||||
|
std::vector<std::unique_ptr<SmallVector<Solution, 2>>> ContextualSolutions;
|
||||||
|
|
||||||
|
/// Take all of the constraints in this component and put them into
|
||||||
|
/// \c Constraints.
|
||||||
|
void injectConstraints() {
|
||||||
|
for (auto constraint : Component.getConstraints()) {
|
||||||
|
Constraints->erase(constraint);
|
||||||
|
Constraints->push_back(constraint);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
DependentComponentSplitterStep(
|
||||||
|
ConstraintSystem &cs,
|
||||||
|
ConstraintList *constraints,
|
||||||
|
unsigned index,
|
||||||
|
ConstraintGraph::Component &&component,
|
||||||
|
MutableArrayRef<SmallVector<Solution, 4>> allPartialSolutions)
|
||||||
|
: SolverStep(cs, allPartialSolutions[index]), Constraints(constraints),
|
||||||
|
Index(index), Component(std::move(component)),
|
||||||
|
AllPartialSolutions(allPartialSolutions) {
|
||||||
|
assert(!Component.getDependencies().empty() && "Should use ComponentStep");
|
||||||
|
injectConstraints();
|
||||||
|
}
|
||||||
|
|
||||||
|
StepResult take(bool prevFailed) override;
|
||||||
|
StepResult resume(bool prevFailed) override;
|
||||||
|
|
||||||
|
void print(llvm::raw_ostream &Out) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/// `ComponentStep` represents a set of type variables and related
|
/// `ComponentStep` represents a set of type variables and related
|
||||||
/// constraints which could be solved independently. It's further
|
/// constraints which could be solved independently. It's further
|
||||||
@@ -327,6 +381,10 @@ class ComponentStep final : public SolverStep {
|
|||||||
/// Constraints "in scope" of this step.
|
/// Constraints "in scope" of this step.
|
||||||
ConstraintList *Constraints;
|
ConstraintList *Constraints;
|
||||||
|
|
||||||
|
/// The set of partial solutions that should be composed before evaluating
|
||||||
|
/// this component.
|
||||||
|
SmallVector<const Solution *, 2> DependsOnPartialSolutions;
|
||||||
|
|
||||||
/// Constraint which doesn't have any free type variables associated
|
/// Constraint which doesn't have any free type variables associated
|
||||||
/// with it, which makes it disconnected in the graph.
|
/// with it, which makes it disconnected in the graph.
|
||||||
Constraint *OrphanedConstraint = nullptr;
|
Constraint *OrphanedConstraint = nullptr;
|
||||||
@@ -361,6 +419,8 @@ public:
|
|||||||
constraints->erase(constraint);
|
constraints->erase(constraint);
|
||||||
Constraints->push_back(constraint);
|
Constraints->push_back(constraint);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
assert(component.getDependencies().empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a component step that composes existing partial solutions before
|
/// Create a component step that composes existing partial solutions before
|
||||||
@@ -369,11 +429,15 @@ public:
|
|||||||
ConstraintSystem &cs, unsigned index,
|
ConstraintSystem &cs, unsigned index,
|
||||||
ConstraintList *constraints,
|
ConstraintList *constraints,
|
||||||
const ConstraintGraph::Component &component,
|
const ConstraintGraph::Component &component,
|
||||||
|
llvm::SmallVectorImpl<const Solution *> &&dependsOnPartialSolutions,
|
||||||
SmallVectorImpl<Solution> &solutions)
|
SmallVectorImpl<Solution> &solutions)
|
||||||
: 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),
|
||||||
|
DependsOnPartialSolutions(std::move(dependsOnPartialSolutions)) {
|
||||||
TypeVars = component.typeVars;
|
TypeVars = component.typeVars;
|
||||||
|
assert(DependsOnPartialSolutions.size() ==
|
||||||
|
component.getDependencies().size());
|
||||||
|
|
||||||
for (auto constraint : component.getConstraints()) {
|
for (auto constraint : component.getConstraints()) {
|
||||||
constraints->erase(constraint);
|
constraints->erase(constraint);
|
||||||
|
|||||||
@@ -872,6 +872,10 @@ void ConstraintGraph::Component::addConstraint(Constraint *constraint) {
|
|||||||
constraints.push_back(constraint);
|
constraints.push_back(constraint);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ConstraintGraph::Component::recordDependency(const Component &component) {
|
||||||
|
dependencies.push_back(component.solutionIndex);
|
||||||
|
}
|
||||||
|
|
||||||
SmallVector<ConstraintGraph::Component, 1>
|
SmallVector<ConstraintGraph::Component, 1>
|
||||||
ConstraintGraph::computeConnectedComponents(
|
ConstraintGraph::computeConnectedComponents(
|
||||||
ArrayRef<TypeVariableType *> typeVars) {
|
ArrayRef<TypeVariableType *> typeVars) {
|
||||||
@@ -1125,6 +1129,20 @@ void ConstraintGraph::printConnectedComponents(
|
|||||||
[&] {
|
[&] {
|
||||||
out << ' ';
|
out << ' ';
|
||||||
});
|
});
|
||||||
|
|
||||||
|
auto dependencies = component.getDependencies();
|
||||||
|
if (dependencies.empty())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
SmallVector<unsigned, 4> indices{dependencies.begin(), dependencies.end()};
|
||||||
|
// Sort dependencies so output is stable.
|
||||||
|
llvm::sort(indices);
|
||||||
|
|
||||||
|
// Print all of the one-way components.
|
||||||
|
out << " depends on ";
|
||||||
|
llvm::interleave(
|
||||||
|
indices, [&out](unsigned index) { out << index; },
|
||||||
|
[&out] { out << ", "; });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user