@@ -335,57 +335,6 @@ bool RewritePath::replaceRuleWithPath(unsigned ruleID,
335
335
return true ;
336
336
}
337
337
338
- // / Check if a rewrite rule is a candidate for deletion in this pass of the
339
- // / minimization algorithm.
340
- bool RewriteSystem::
341
- isCandidateForDeletion (unsigned ruleID,
342
- const llvm::DenseSet<unsigned > *redundantConformances) const {
343
- const auto &rule = getRule (ruleID);
344
-
345
- // We should not find a rule that has already been marked redundant
346
- // here; it should have already been replaced with a rewrite path
347
- // in all homotopy generators.
348
- assert (!rule.isRedundant ());
349
-
350
- // Associated type introduction rules are 'permanent'. They're
351
- // not worth eliminating since they are re-added every time; it
352
- // is better to find other candidates to eliminate in the same
353
- // loop instead.
354
- if (rule.isPermanent ())
355
- return false ;
356
-
357
- // Other rules involving unresolved name symbols are derived from an
358
- // associated type introduction rule together with a conformance rule.
359
- // They are eliminated in the first pass.
360
- if (rule.getLHS ().containsUnresolvedSymbols ())
361
- return true ;
362
-
363
- // Protocol conformance rules are eliminated via a different
364
- // algorithm which computes "minimal conformances". This runs between
365
- // two passes of homotopy reduction.
366
- //
367
- // The first pass skips protocol conformance rules.
368
- //
369
- // The second pass eliminates any protocol conformance rule which is
370
- // redundant according to both homotopy reduction and the minimal
371
- // conformances algorithm.
372
- //
373
- // Later on, we verify that any conformance redundant via minimal
374
- // conformances was also redundant via homotopy reduction. This
375
- // means that the set of minimal conformances is always a superset
376
- // (or equal to) of the set of minimal protocol conformance
377
- // requirements that homotopy reduction alone would produce.
378
- if (rule.isAnyConformanceRule ()) {
379
- if (!redundantConformances)
380
- return false ;
381
-
382
- if (!redundantConformances->count (ruleID))
383
- return false ;
384
- }
385
-
386
- return true ;
387
- }
388
-
389
338
// / Find a rule to delete by looking through all loops for rewrite rules appearing
390
339
// / once in empty context. Returns a redundant rule to delete if one was found,
391
340
// / otherwise returns None.
@@ -401,7 +350,7 @@ isCandidateForDeletion(unsigned ruleID,
401
350
// / \p redundantConformances equal to the set of conformance rules that are
402
351
// / not minimal conformances.
403
352
Optional<unsigned > RewriteSystem::
404
- findRuleToDelete (const llvm::DenseSet< unsigned > *redundantConformances ,
353
+ findRuleToDelete (llvm::function_ref< bool ( unsigned )> isRedundantRuleFn ,
405
354
RewritePath &replacementPath) {
406
355
SmallVector<std::pair<unsigned , unsigned >, 2 > redundancyCandidates;
407
356
for (unsigned loopID : indices (Loops)) {
@@ -423,15 +372,28 @@ findRuleToDelete(const llvm::DenseSet<unsigned> *redundantConformances,
423
372
424
373
for (const auto &pair : redundancyCandidates) {
425
374
unsigned ruleID = pair.second ;
426
- if (!isCandidateForDeletion (ruleID, redundantConformances))
375
+ const auto &rule = getRule (ruleID);
376
+
377
+ // We should not find a rule that has already been marked redundant
378
+ // here; it should have already been replaced with a rewrite path
379
+ // in all homotopy generators.
380
+ assert (!rule.isRedundant ());
381
+
382
+ // Associated type introduction rules are 'permanent'. They're
383
+ // not worth eliminating since they are re-added every time; it
384
+ // is better to find other candidates to eliminate in the same
385
+ // loop instead.
386
+ if (rule.isPermanent ())
387
+ continue ;
388
+
389
+ if (!isRedundantRuleFn (ruleID))
427
390
continue ;
428
391
429
392
if (!found) {
430
393
found = pair;
431
394
continue ;
432
395
}
433
396
434
- const auto &rule = getRule (ruleID);
435
397
const auto &otherRule = getRule (found->second );
436
398
437
399
// Prefer to delete "less canonical" rules.
@@ -495,10 +457,10 @@ void RewriteSystem::deleteRule(unsigned ruleID,
495
457
}
496
458
497
459
void RewriteSystem::performHomotopyReduction (
498
- const llvm::DenseSet< unsigned > *redundantConformances ) {
460
+ llvm::function_ref< bool ( unsigned )> isRedundantRuleFn ) {
499
461
while (true ) {
500
462
RewritePath replacementPath;
501
- auto optRuleID = findRuleToDelete (redundantConformances ,
463
+ auto optRuleID = findRuleToDelete (isRedundantRuleFn ,
502
464
replacementPath);
503
465
504
466
// If no redundant rules remain which can be eliminated by this pass, stop.
@@ -524,8 +486,24 @@ void RewriteSystem::minimizeRewriteSystem() {
524
486
525
487
propagateExplicitBits ();
526
488
527
- // First pass: Eliminate all redundant rules that are not conformance rules.
528
- performHomotopyReduction (/* redundantConformances=*/ nullptr );
489
+ // First pass:
490
+ // - Eliminate all simplified non-conformance rules.
491
+ // - Eliminate all rules with unresolved symbols.
492
+ performHomotopyReduction ([&](unsigned ruleID) -> bool {
493
+ const auto &rule = getRule (ruleID);
494
+
495
+ if (rule.isSimplified () &&
496
+ !rule.isAnyConformanceRule ())
497
+ return true ;
498
+
499
+ // Other rules involving unresolved name symbols are derived from an
500
+ // associated type introduction rule together with a conformance rule.
501
+ // They are eliminated in the first pass.
502
+ if (rule.getLHS ().containsUnresolvedSymbols ())
503
+ return true ;
504
+
505
+ return false ;
506
+ });
529
507
530
508
// Now compute a set of minimal conformances.
531
509
//
@@ -537,8 +515,26 @@ void RewriteSystem::minimizeRewriteSystem() {
537
515
llvm::DenseSet<unsigned > redundantConformances;
538
516
computeMinimalConformances (redundantConformances);
539
517
540
- // Second pass: Eliminate all redundant conformance rules.
541
- performHomotopyReduction (/* redundantConformances=*/ &redundantConformances);
518
+ // Second pass: Eliminate all non-minimal conformance rules.
519
+ performHomotopyReduction ([&](unsigned ruleID) -> bool {
520
+ const auto &rule = getRule (ruleID);
521
+
522
+ if (rule.isAnyConformanceRule () &&
523
+ redundantConformances.count (ruleID))
524
+ return true ;
525
+
526
+ return false ;
527
+ });
528
+
529
+ // Third pass: Eliminate all other redundant non-conformance rules.
530
+ performHomotopyReduction ([&](unsigned ruleID) -> bool {
531
+ const auto &rule = getRule (ruleID);
532
+
533
+ if (!rule.isAnyConformanceRule ())
534
+ return true ;
535
+
536
+ return false ;
537
+ });
542
538
543
539
// Check invariants after homotopy reduction.
544
540
verifyRewriteLoops ();
0 commit comments