@@ -335,57 +335,6 @@ bool RewritePath::replaceRuleWithPath(unsigned ruleID,
335335 return true ;
336336}
337337
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-
389338// / Find a rule to delete by looking through all loops for rewrite rules appearing
390339// / once in empty context. Returns a redundant rule to delete if one was found,
391340// / otherwise returns None.
@@ -401,7 +350,7 @@ isCandidateForDeletion(unsigned ruleID,
401350// / \p redundantConformances equal to the set of conformance rules that are
402351// / not minimal conformances.
403352Optional<unsigned > RewriteSystem::
404- findRuleToDelete (const llvm::DenseSet< unsigned > *redundantConformances ,
353+ findRuleToDelete (llvm::function_ref< bool ( unsigned )> isRedundantRuleFn ,
405354 RewritePath &replacementPath) {
406355 SmallVector<std::pair<unsigned , unsigned >, 2 > redundancyCandidates;
407356 for (unsigned loopID : indices (Loops)) {
@@ -423,15 +372,28 @@ findRuleToDelete(const llvm::DenseSet<unsigned> *redundantConformances,
423372
424373 for (const auto &pair : redundancyCandidates) {
425374 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))
427390 continue ;
428391
429392 if (!found) {
430393 found = pair;
431394 continue ;
432395 }
433396
434- const auto &rule = getRule (ruleID);
435397 const auto &otherRule = getRule (found->second );
436398
437399 // Prefer to delete "less canonical" rules.
@@ -495,10 +457,10 @@ void RewriteSystem::deleteRule(unsigned ruleID,
495457}
496458
497459void RewriteSystem::performHomotopyReduction (
498- const llvm::DenseSet< unsigned > *redundantConformances ) {
460+ llvm::function_ref< bool ( unsigned )> isRedundantRuleFn ) {
499461 while (true ) {
500462 RewritePath replacementPath;
501- auto optRuleID = findRuleToDelete (redundantConformances ,
463+ auto optRuleID = findRuleToDelete (isRedundantRuleFn ,
502464 replacementPath);
503465
504466 // If no redundant rules remain which can be eliminated by this pass, stop.
@@ -524,8 +486,24 @@ void RewriteSystem::minimizeRewriteSystem() {
524486
525487 propagateExplicitBits ();
526488
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+ });
529507
530508 // Now compute a set of minimal conformances.
531509 //
@@ -537,8 +515,26 @@ void RewriteSystem::minimizeRewriteSystem() {
537515 llvm::DenseSet<unsigned > redundantConformances;
538516 computeMinimalConformances (redundantConformances);
539517
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+ });
542538
543539 // Check invariants after homotopy reduction.
544540 verifyRewriteLoops ();
0 commit comments