@@ -218,7 +218,6 @@ RewritePath::findRulesAppearingOnceInEmptyContext() const {
218
218
result.push_back (rule);
219
219
}
220
220
221
- std::sort (result.begin (), result.end ());
222
221
return result;
223
222
}
224
223
@@ -574,6 +573,64 @@ void HomotopyGenerator::dump(llvm::raw_ostream &out,
574
573
out << " [deleted]" ;
575
574
}
576
575
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
+
577
634
// / Find a rule to delete by looking through all 3-cells for rewrite rules appearing
578
635
// / once in empty context. Returns a redundant rule to delete if one was found,
579
636
// / otherwise returns None.
@@ -604,63 +661,26 @@ findRuleToDelete(bool firstPass,
604
661
SmallVector<unsigned > redundancyCandidates =
605
662
loop.Path .findRulesAppearingOnceInEmptyContext ();
606
663
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)
664
684
continue ;
665
685
666
686
auto ruleID = *found;
0 commit comments