Skip to content

Commit 8af183c

Browse files
committed
Revert "Sema: Remove DependentComponentSplitterStep"
This reverts commit 9fb6d92.
1 parent 8800c3b commit 8af183c

File tree

4 files changed

+183
-6
lines changed

4 files changed

+183
-6
lines changed

include/swift/Sema/ConstraintGraph.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -343,6 +343,12 @@ class ConstraintGraph {
343343
/// The constraints in this component.
344344
TinyPtrVector<Constraint *> constraints;
345345

346+
/// The set of components that this component depends on, such that
347+
/// the partial solutions of the those components need to be available
348+
/// before this component can be solved.
349+
///
350+
SmallVector<unsigned, 2> dependencies;
351+
346352
public:
347353
Component(unsigned solutionIndex) : solutionIndex(solutionIndex) { }
348354

@@ -358,6 +364,11 @@ class ConstraintGraph {
358364
return constraints;
359365
}
360366

367+
/// Records a component which this component depends on.
368+
void recordDependency(const Component &component);
369+
370+
ArrayRef<unsigned> getDependencies() const { return dependencies; }
371+
361372
unsigned getNumDisjunctions() const { return numDisjunctions; }
362373
};
363374

lib/Sema/CSStep.cpp

Lines changed: 89 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ void SplitterStep::computeFollowupSteps(
126126
// Take the orphaned constraints, because they'll go into a component now.
127127
OrphanedConstraints = CG.takeOrphanedConstraints();
128128

129+
IncludeInMergedResults.resize(numComponents, true);
129130
Components.resize(numComponents);
130131
PartialSolutions = std::unique_ptr<SmallVector<Solution, 4>[]>(
131132
new SmallVector<Solution, 4>[numComponents]);
@@ -134,9 +135,26 @@ void SplitterStep::computeFollowupSteps(
134135
for (unsigned i : indices(components)) {
135136
unsigned solutionIndex = components[i].solutionIndex;
136137

137-
steps.push_back(std::make_unique<ComponentStep>(
138-
CS, solutionIndex, &Components[i], std::move(components[i]),
139-
PartialSolutions[solutionIndex]));
138+
// If there are no dependencies, build a normal component step.
139+
if (components[i].getDependencies().empty()) {
140+
steps.push_back(std::make_unique<ComponentStep>(
141+
CS, solutionIndex, &Components[i], std::move(components[i]),
142+
PartialSolutions[solutionIndex]));
143+
continue;
144+
}
145+
146+
// Note that the partial results from any dependencies of this component
147+
// need not be included in the final merged results, because they'll
148+
// already be part of the partial results for this component.
149+
for (auto dependsOn : components[i].getDependencies()) {
150+
IncludeInMergedResults[dependsOn] = false;
151+
}
152+
153+
// Otherwise, build a dependent component "splitter" step, which
154+
// handles all combinations of incoming partial solutions.
155+
steps.push_back(std::make_unique<DependentComponentSplitterStep>(
156+
CS, &Components[i], solutionIndex, std::move(components[i]),
157+
llvm::MutableArrayRef(PartialSolutions.get(), numComponents)));
140158
}
141159

142160
assert(CS.InactiveConstraints.empty() && "Missed a constraint");
@@ -205,7 +223,8 @@ bool SplitterStep::mergePartialSolutions() const {
205223
SmallVector<unsigned, 2> countsVec;
206224
countsVec.reserve(numComponents);
207225
for (unsigned idx : range(numComponents)) {
208-
countsVec.push_back(PartialSolutions[idx].size());
226+
countsVec.push_back(
227+
IncludeInMergedResults[idx] ? PartialSolutions[idx].size() : 1);
209228
}
210229

211230
// Produce all combinations of partial solutions.
@@ -218,6 +237,9 @@ bool SplitterStep::mergePartialSolutions() const {
218237
// solutions.
219238
ConstraintSystem::SolverScope scope(CS);
220239
for (unsigned i : range(numComponents)) {
240+
if (!IncludeInMergedResults[i])
241+
continue;
242+
221243
CS.replaySolution(PartialSolutions[i][indices[i]]);
222244
}
223245

@@ -249,15 +271,77 @@ bool SplitterStep::mergePartialSolutions() const {
249271
return anySolutions;
250272
}
251273

274+
StepResult DependentComponentSplitterStep::take(bool prevFailed) {
275+
// "split" is considered a failure if previous step failed,
276+
// or there is a failure recorded by constraint system, or
277+
// system can't be simplified.
278+
if (prevFailed || CS.getFailedConstraint() || CS.simplify())
279+
return done(/*isSuccess=*/false);
280+
281+
// Figure out the sets of partial solutions that this component depends on.
282+
SmallVector<const SmallVector<Solution, 4> *, 2> dependsOnSets;
283+
for (auto index : Component.getDependencies()) {
284+
dependsOnSets.push_back(&AllPartialSolutions[index]);
285+
}
286+
287+
// Produce all combinations of partial solutions for the inputs.
288+
SmallVector<std::unique_ptr<SolverStep>, 4> followup;
289+
SmallVector<unsigned, 2> indices(Component.getDependencies().size(), 0);
290+
auto dependsOnSetsRef = llvm::ArrayRef(dependsOnSets);
291+
do {
292+
// Form the set of input partial solutions.
293+
SmallVector<const Solution *, 2> dependsOnSolutions;
294+
for (auto index : swift::indices(indices)) {
295+
dependsOnSolutions.push_back(&(*dependsOnSets[index])[indices[index]]);
296+
}
297+
ContextualSolutions.push_back(std::make_unique<SmallVector<Solution, 2>>());
298+
299+
followup.push_back(std::make_unique<ComponentStep>(
300+
CS, Index, Constraints, Component, std::move(dependsOnSolutions),
301+
*ContextualSolutions.back()));
302+
} while (nextCombination(dependsOnSetsRef, indices));
303+
304+
/// Wait until all of the component steps are done.
305+
return suspend(followup);
306+
}
307+
308+
StepResult DependentComponentSplitterStep::resume(bool prevFailed) {
309+
for (auto &ComponentStepSolutions : ContextualSolutions) {
310+
Solutions.append(std::make_move_iterator(ComponentStepSolutions->begin()),
311+
std::make_move_iterator(ComponentStepSolutions->end()));
312+
}
313+
return done(/*isSuccess=*/!Solutions.empty());
314+
}
315+
316+
void DependentComponentSplitterStep::print(llvm::raw_ostream &Out) {
317+
Out << "DependentComponentSplitterStep for dependencies on [";
318+
interleave(
319+
Component.getDependencies(), [&](unsigned index) { Out << index; },
320+
[&] { Out << ", "; });
321+
Out << "]\n";
322+
}
323+
252324
StepResult ComponentStep::take(bool prevFailed) {
253325
// One of the previous components created by "split"
254326
// failed, it means that we can't solve this component.
255-
if (prevFailed || CS.isTooComplex(Solutions) || CS.worseThanBestSolution())
327+
if ((prevFailed && DependsOnPartialSolutions.empty()) ||
328+
CS.isTooComplex(Solutions) || CS.worseThanBestSolution())
256329
return done(/*isSuccess=*/false);
257330

258331
// Setup active scope, only if previous component didn't fail.
259332
setupScope();
260333

334+
// If there are any dependent partial solutions to compose, do so now.
335+
if (!DependsOnPartialSolutions.empty()) {
336+
for (auto partial : DependsOnPartialSolutions) {
337+
CS.replaySolution(*partial);
338+
}
339+
340+
// Simplify again.
341+
if (CS.failedConstraint || CS.simplify())
342+
return done(/*isSuccess=*/false);
343+
}
344+
261345
/// Try to figure out what this step is going to be,
262346
/// after the scope has been established.
263347
SmallString<64> potentialBindings;

lib/Sema/CSStep.h

Lines changed: 65 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,10 @@ class SplitterStep final : public SolverStep {
240240

241241
SmallVector<Constraint *, 4> OrphanedConstraints;
242242

243+
/// Whether to include the partial results of this component in the final
244+
/// merged results.
245+
SmallVector<bool, 4> IncludeInMergedResults;
246+
243247
public:
244248
SplitterStep(ConstraintSystem &cs, SmallVectorImpl<Solution> &solutions)
245249
: SolverStep(cs, solutions) {}
@@ -265,6 +269,56 @@ class SplitterStep final : public SolverStep {
265269
bool mergePartialSolutions() const;
266270
};
267271

272+
/// `DependentComponentSplitterStep` is responsible for composing the partial
273+
/// solutions from other components (on which this component depends) into
274+
/// the inputs based on which we can solve a particular component.
275+
class DependentComponentSplitterStep final : public SolverStep {
276+
/// Constraints "in scope" of this step.
277+
ConstraintList *Constraints;
278+
279+
/// Index into the parent splitter step.
280+
unsigned Index;
281+
282+
/// The component that has dependencies.
283+
ConstraintGraph::Component Component;
284+
285+
/// Array containing all of the partial solutions for the parent split.
286+
MutableArrayRef<SmallVector<Solution, 4>> AllPartialSolutions;
287+
288+
/// The solutions computed the \c ComponentSteps created for each partial
289+
/// solution combinations. Will be merged into the final \c Solutions vector
290+
/// in \c resume.
291+
std::vector<std::unique_ptr<SmallVector<Solution, 2>>> ContextualSolutions;
292+
293+
/// Take all of the constraints in this component and put them into
294+
/// \c Constraints.
295+
void injectConstraints() {
296+
for (auto constraint : Component.getConstraints()) {
297+
Constraints->erase(constraint);
298+
Constraints->push_back(constraint);
299+
}
300+
}
301+
302+
public:
303+
DependentComponentSplitterStep(
304+
ConstraintSystem &cs,
305+
ConstraintList *constraints,
306+
unsigned index,
307+
ConstraintGraph::Component &&component,
308+
MutableArrayRef<SmallVector<Solution, 4>> allPartialSolutions)
309+
: SolverStep(cs, allPartialSolutions[index]), Constraints(constraints),
310+
Index(index), Component(std::move(component)),
311+
AllPartialSolutions(allPartialSolutions) {
312+
assert(!Component.getDependencies().empty() && "Should use ComponentStep");
313+
injectConstraints();
314+
}
315+
316+
StepResult take(bool prevFailed) override;
317+
StepResult resume(bool prevFailed) override;
318+
319+
void print(llvm::raw_ostream &Out) override;
320+
};
321+
268322

269323
/// `ComponentStep` represents a set of type variables and related
270324
/// constraints which could be solved independently. It's further
@@ -327,6 +381,10 @@ class ComponentStep final : public SolverStep {
327381
/// Constraints "in scope" of this step.
328382
ConstraintList *Constraints;
329383

384+
/// The set of partial solutions that should be composed before evaluating
385+
/// this component.
386+
SmallVector<const Solution *, 2> DependsOnPartialSolutions;
387+
330388
/// Constraint which doesn't have any free type variables associated
331389
/// with it, which makes it disconnected in the graph.
332390
Constraint *OrphanedConstraint = nullptr;
@@ -361,6 +419,8 @@ class ComponentStep final : public SolverStep {
361419
constraints->erase(constraint);
362420
Constraints->push_back(constraint);
363421
}
422+
423+
assert(component.getDependencies().empty());
364424
}
365425

366426
/// Create a component step that composes existing partial solutions before
@@ -369,11 +429,15 @@ class ComponentStep final : public SolverStep {
369429
ConstraintSystem &cs, unsigned index,
370430
ConstraintList *constraints,
371431
const ConstraintGraph::Component &component,
432+
llvm::SmallVectorImpl<const Solution *> &&dependsOnPartialSolutions,
372433
SmallVectorImpl<Solution> &solutions)
373434
: SolverStep(cs, solutions), Index(index), IsSingle(false),
374435
OriginalScore(getCurrentScore()), OriginalBestScore(getBestScore()),
375-
Constraints(constraints) {
436+
Constraints(constraints),
437+
DependsOnPartialSolutions(std::move(dependsOnPartialSolutions)) {
376438
TypeVars = component.typeVars;
439+
assert(DependsOnPartialSolutions.size() ==
440+
component.getDependencies().size());
377441

378442
for (auto constraint : component.getConstraints()) {
379443
constraints->erase(constraint);

lib/Sema/ConstraintGraph.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -872,6 +872,10 @@ void ConstraintGraph::Component::addConstraint(Constraint *constraint) {
872872
constraints.push_back(constraint);
873873
}
874874

875+
void ConstraintGraph::Component::recordDependency(const Component &component) {
876+
dependencies.push_back(component.solutionIndex);
877+
}
878+
875879
SmallVector<ConstraintGraph::Component, 1>
876880
ConstraintGraph::computeConnectedComponents(
877881
ArrayRef<TypeVariableType *> typeVars) {
@@ -1125,6 +1129,20 @@ void ConstraintGraph::printConnectedComponents(
11251129
[&] {
11261130
out << ' ';
11271131
});
1132+
1133+
auto dependencies = component.getDependencies();
1134+
if (dependencies.empty())
1135+
continue;
1136+
1137+
SmallVector<unsigned, 4> indices{dependencies.begin(), dependencies.end()};
1138+
// Sort dependencies so output is stable.
1139+
llvm::sort(indices);
1140+
1141+
// Print all of the one-way components.
1142+
out << " depends on ";
1143+
llvm::interleave(
1144+
indices, [&out](unsigned index) { out << index; },
1145+
[&out] { out << ", "; });
11281146
}
11291147
}
11301148

0 commit comments

Comments
 (0)