@@ -218,7 +218,6 @@ RewritePath::findRulesAppearingOnceInEmptyContext() const {
218218 result.push_back (rule);
219219 }
220220
221- std::sort (result.begin (), result.end ());
222221 return result;
223222}
224223
@@ -574,6 +573,64 @@ void HomotopyGenerator::dump(llvm::raw_ostream &out,
574573 out << " [deleted]" ;
575574}
576575
576+ // / Check if a rewrite rule is a candidate for deletion in this pass of the
577+ // / minimization algorithm.
578+ bool RewriteSystem::
579+ isCandidateForDeletion (unsigned ruleID,
580+ bool firstPass,
581+ const llvm::DenseSet<unsigned > *redundantConformances) const {
582+ const auto &rule = getRule (ruleID);
583+
584+ // We should not find a rule that has already been marked redundant
585+ // here; it should have already been replaced with a rewrite path
586+ // in all homotopy generators.
587+ assert (!rule.isRedundant ());
588+
589+ // Associated type introduction rules are 'permanent'. They're
590+ // not worth eliminating since they are re-added every time; it
591+ // is better to find other candidates to eliminate in the same
592+ // 3-cell instead.
593+ if (rule.isPermanent ())
594+ return false ;
595+
596+ // Other rules involving unresolved name symbols are derived from an
597+ // associated type introduction rule together with a conformance rule.
598+ // They are eliminated in the first pass.
599+ if (firstPass)
600+ return rule.getLHS ().containsUnresolvedSymbols ();
601+
602+ // In the second and third pass we should not have any rules involving
603+ // unresolved name symbols, except for permanent rules which were
604+ // already skipped above.
605+ //
606+ // FIXME: This isn't true with invalid code.
607+ assert (!rule.getLHS ().containsUnresolvedSymbols ());
608+
609+ // Protocol conformance rules are eliminated via a different
610+ // algorithm which computes "generating conformances".
611+ //
612+ // The first and second passes skip protocol conformance rules.
613+ //
614+ // The third pass eliminates any protocol conformance rule which is
615+ // redundant according to both homotopy reduction and the generating
616+ // conformances algorithm.
617+ //
618+ // Later on, we verify that any conformance redundant via generating
619+ // conformances was also redundant via homotopy reduction. This
620+ // means that the set of generating conformances is always a superset
621+ // (or equal to) of the set of minimal protocol conformance
622+ // requirements that homotopy reduction alone would produce.
623+ if (rule.isProtocolConformanceRule ()) {
624+ if (!redundantConformances)
625+ return false ;
626+
627+ if (!redundantConformances->count (ruleID))
628+ return false ;
629+ }
630+
631+ return true ;
632+ }
633+
577634// / Find a rule to delete by looking through all 3-cells for rewrite rules appearing
578635// / once in empty context. Returns a redundant rule to delete if one was found,
579636// / otherwise returns None.
@@ -604,63 +661,26 @@ findRuleToDelete(bool firstPass,
604661 SmallVector<unsigned > redundancyCandidates =
605662 loop.Path .findRulesAppearingOnceInEmptyContext ();
606663
607- auto found = std::find_if (
608- redundancyCandidates.begin (),
609- redundancyCandidates.end (),
610- [&](unsigned ruleID) -> bool {
611- const auto &rule = getRule (ruleID);
612-
613- // We should not find a rule that has already been marked redundant
614- // here; it should have already been replaced with a rewrite path
615- // in all homotopy generators.
616- assert (!rule.isRedundant ());
617-
618- // Associated type introduction rules are 'permanent'. They're
619- // not worth eliminating since they are re-added every time; it
620- // is better to find other candidates to eliminate in the same
621- // 3-cell instead.
622- if (rule.isPermanent ())
623- return false ;
624-
625- // Other rules involving unresolved name symbols are derived from an
626- // associated type introduction rule together with a conformance rule.
627- // They are eliminated in the first pass.
628- if (firstPass)
629- return rule.getLHS ().containsUnresolvedSymbols ();
630-
631- // In the second and third pass we should not have any rules involving
632- // unresolved name symbols, except for permanent rules which were
633- // already skipped above.
634- //
635- // FIXME: This isn't true with invalid code.
636- assert (!rule.getLHS ().containsUnresolvedSymbols ());
637-
638- // Protocol conformance rules are eliminated via a different
639- // algorithm which computes "generating conformances".
640- //
641- // The first and second passes skip protocol conformance rules.
642- //
643- // The third pass eliminates any protocol conformance rule which is
644- // redundant according to both homotopy reduction and the generating
645- // conformances algorithm.
646- //
647- // Later on, we verify that any conformance redundant via generating
648- // conformances was also redundant via homotopy reduction. This
649- // means that the set of generating conformances is always a superset
650- // (or equal to) of the set of minimal protocol conformance
651- // requirements that homotopy reduction alone would produce.
652- if (rule.isProtocolConformanceRule ()) {
653- if (!redundantConformances)
654- return false ;
655-
656- if (!redundantConformances->count (ruleID))
657- return false ;
658- }
659-
660- return true ;
661- });
662-
663- if (found == redundancyCandidates.end ())
664+ Optional<unsigned > found;
665+
666+ for (unsigned ruleID : redundancyCandidates) {
667+ if (!isCandidateForDeletion (ruleID, firstPass, redundantConformances))
668+ continue ;
669+
670+ if (!found) {
671+ found = ruleID;
672+ continue ;
673+ }
674+
675+ const auto &rule = getRule (ruleID);
676+ const auto &otherRule = getRule (*found);
677+
678+ // Prefer to delete "less canonical" rules.
679+ if (rule.compare (otherRule, Protos) > 0 )
680+ found = ruleID;
681+ }
682+
683+ if (!found)
664684 continue ;
665685
666686 auto ruleID = *found;
0 commit comments