5555#include " swift/Basic/Range.h"
5656#include " llvm/ADT/DenseMap.h"
5757#include " llvm/ADT/DenseSet.h"
58+ #include " llvm/ADT/SmallVector.h"
5859#include " llvm/Support/Debug.h"
5960#include " llvm/Support/raw_ostream.h"
6061#include < algorithm>
62+ #include " RewriteContext.h"
6163#include " RewriteSystem.h"
6264
6365using namespace swift ;
6466using namespace rewriting ;
6567
66- // / Recompute RulesInEmptyContext and DecomposeCount if needed.
68+ // / Recompute Useful, RulesInEmptyContext, ProjectionCount and DecomposeCount
69+ // / if needed.
6770void RewriteLoop::recompute (const RewriteSystem &system) {
6871 if (!Dirty)
6972 return ;
@@ -109,6 +112,8 @@ void RewriteLoop::recompute(const RewriteSystem &system) {
109112 evaluator.apply (step, system);
110113 }
111114
115+ Useful = !rulesInEmptyContext.empty ();
116+
112117 RulesInEmptyContext.clear ();
113118
114119 // Collect all rules that we saw exactly once in empty context.
@@ -146,6 +151,14 @@ unsigned RewriteLoop::getDecomposeCount(
146151 return DecomposeCount;
147152}
148153
154+ // / The number of Decompose steps, used by the elimination order to prioritize
155+ // / loops that are not concrete simplifications.
156+ bool RewriteLoop::isUseful (
157+ const RewriteSystem &system) const {
158+ const_cast <RewriteLoop *>(this )->recompute (system);
159+ return Useful;
160+ }
161+
149162// / If a rewrite loop contains an explicit rule in empty context, propagate the
150163// / explicit bit to all other rules appearing in empty context within the same
151164// / loop.
@@ -418,16 +431,22 @@ findRuleToDelete(llvm::function_ref<bool(unsigned)> isRedundantRuleFn) {
418431 if (loop.isDeleted ())
419432 continue ;
420433
421- bool foundAny = false ;
434+ // Delete loops that don't contain any rewrite rules in empty context,
435+ // since such loops do not yield any elimination candidates.
436+ if (!loop.isUseful (*this )) {
437+ if (Debug.contains (DebugFlags::HomotopyReduction)) {
438+ llvm::dbgs () << " ** Deleting useless loop #" << loopID << " : " ;
439+ loop.dump (llvm::dbgs (), *this );
440+ llvm::dbgs () << " \n " ;
441+ }
442+
443+ loop.markDeleted ();
444+ continue ;
445+ }
446+
422447 for (unsigned ruleID : loop.findRulesAppearingOnceInEmptyContext (*this )) {
423448 redundancyCandidates.emplace_back (loopID, ruleID);
424- foundAny = true ;
425449 }
426-
427- // Delete loops that don't contain any rewrite rules in empty context,
428- // since such loops do not give us useful information.
429- if (!foundAny)
430- loop.markDeleted ();
431450 }
432451
433452 Optional<std::pair<unsigned , unsigned >> found;
@@ -609,6 +628,10 @@ void RewriteSystem::deleteRule(unsigned ruleID,
609628 if (!changed)
610629 continue ;
611630
631+ if (Context.getASTContext ().LangOpts .EnableRequirementMachineLoopNormalization ) {
632+ loop.computeNormalForm (*this );
633+ }
634+
612635 // The loop's path has changed, so we must invalidate the cached
613636 // result of findRulesAppearingOnceInEmptyContext().
614637 loop.markDirty ();
@@ -658,6 +681,34 @@ void RewriteSystem::performHomotopyReduction(
658681 }
659682}
660683
684+ void RewriteSystem::normalizeRedundantRules () {
685+ for (auto &pair : RedundantRules) {
686+ pair.second .computeNormalForm (*this );
687+ }
688+
689+ if (Debug.contains (DebugFlags::RedundantRules)) {
690+ llvm::dbgs () << " \n Redundant rules:\n " ;
691+ for (const auto &pair : RedundantRules) {
692+ const auto &rule = getRule (pair.first );
693+ llvm::dbgs () << " - ("
694+ << rule.getLHS () << " => "
695+ << rule.getRHS () << " ) ::== " ;
696+
697+ MutableTerm lhs (rule.getLHS ());
698+ pair.second .dump (llvm::dbgs (), lhs, *this );
699+
700+ llvm::dbgs () << " \n " ;
701+
702+ if (Debug.contains (DebugFlags::RedundantRulesDetail)) {
703+ llvm::dbgs () << " \n " ;
704+ pair.second .dumpLong (llvm::dbgs (), lhs, *this );
705+
706+ llvm::dbgs () << " \n\n " ;
707+ }
708+ }
709+ }
710+ }
711+
661712// / Use the loops to delete redundant rewrite rules via a series of Tietze
662713// / transformations, updating and simplifying existing loops as each rule
663714// / is deleted.
@@ -677,6 +728,12 @@ void RewriteSystem::minimizeRewriteSystem() {
677728 propagateExplicitBits ();
678729 processConflicts ();
679730
731+ if (Context.getASTContext ().LangOpts .EnableRequirementMachineLoopNormalization ) {
732+ for (auto &loop : Loops) {
733+ loop.computeNormalForm (*this );
734+ }
735+ }
736+
680737 // First pass:
681738 // - Eliminate all LHS-simplified non-conformance rules.
682739 // - Eliminate all RHS-simplified and substitution-simplified rules.
@@ -753,25 +810,7 @@ void RewriteSystem::minimizeRewriteSystem() {
753810 verifyRedundantConformances (redundantConformances);
754811 verifyMinimizedRules (redundantConformances);
755812
756- if (Debug.contains (DebugFlags::RedundantRules)) {
757- llvm::dbgs () << " \n Redundant rules:\n " ;
758- for (const auto &pair : RedundantRules) {
759- const auto &rule = getRule (pair.first );
760- llvm::dbgs () << " - " << rule << " ::== " ;
761-
762- MutableTerm lhs (rule.getLHS ());
763- pair.second .dump (llvm::dbgs (), lhs, *this );
764-
765- llvm::dbgs () << " \n " ;
766-
767- if (Debug.contains (DebugFlags::RedundantRulesDetail)) {
768- llvm::dbgs () << " \n " ;
769- pair.second .dumpLong (llvm::dbgs (), lhs, *this );
770-
771- llvm::dbgs () << " \n\n " ;
772- }
773- }
774- }
813+ normalizeRedundantRules ();
775814}
776815
777816// / In a conformance-valid rewrite system, any rule with unresolved symbols on
0 commit comments