@@ -126,6 +126,7 @@ void SplitterStep::computeFollowupSteps(
126
126
// Take the orphaned constraints, because they'll go into a component now.
127
127
OrphanedConstraints = CG.takeOrphanedConstraints ();
128
128
129
+ IncludeInMergedResults.resize (numComponents, true );
129
130
Components.resize (numComponents);
130
131
PartialSolutions = std::unique_ptr<SmallVector<Solution, 4 >[]>(
131
132
new SmallVector<Solution, 4 >[numComponents]);
@@ -134,9 +135,26 @@ void SplitterStep::computeFollowupSteps(
134
135
for (unsigned i : indices (components)) {
135
136
unsigned solutionIndex = components[i].solutionIndex ;
136
137
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)));
140
158
}
141
159
142
160
assert (CS.InactiveConstraints .empty () && " Missed a constraint" );
@@ -205,7 +223,8 @@ bool SplitterStep::mergePartialSolutions() const {
205
223
SmallVector<unsigned , 2 > countsVec;
206
224
countsVec.reserve (numComponents);
207
225
for (unsigned idx : range (numComponents)) {
208
- countsVec.push_back (PartialSolutions[idx].size ());
226
+ countsVec.push_back (
227
+ IncludeInMergedResults[idx] ? PartialSolutions[idx].size () : 1 );
209
228
}
210
229
211
230
// Produce all combinations of partial solutions.
@@ -218,6 +237,9 @@ bool SplitterStep::mergePartialSolutions() const {
218
237
// solutions.
219
238
ConstraintSystem::SolverScope scope (CS);
220
239
for (unsigned i : range (numComponents)) {
240
+ if (!IncludeInMergedResults[i])
241
+ continue ;
242
+
221
243
CS.replaySolution (PartialSolutions[i][indices[i]]);
222
244
}
223
245
@@ -249,15 +271,77 @@ bool SplitterStep::mergePartialSolutions() const {
249
271
return anySolutions;
250
272
}
251
273
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
+
252
324
StepResult ComponentStep::take (bool prevFailed) {
253
325
// One of the previous components created by "split"
254
326
// 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 ())
256
329
return done (/* isSuccess=*/ false );
257
330
258
331
// Setup active scope, only if previous component didn't fail.
259
332
setupScope ();
260
333
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
+
261
345
// / Try to figure out what this step is going to be,
262
346
// / after the scope has been established.
263
347
SmallString<64 > potentialBindings;
0 commit comments