@@ -66,9 +66,17 @@ using namespace rewriting;
6666
6767// / A rewrite rule is redundant if it appears exactly once in a loop
6868// / without context.
69- llvm::SmallVector<unsigned , 1 >
69+ // /
70+ // / This method will cache the result; markDirty() must be called after
71+ // / the underlying rewrite path is modified to invalidate the cached
72+ // / result.
73+ ArrayRef<unsigned >
7074RewriteLoop::findRulesAppearingOnceInEmptyContext (
7175 const RewriteSystem &system) const {
76+ // If we're allowed to use the cached result, return that.
77+ if (!Dirty)
78+ return RulesInEmptyContext;
79+
7280 // Rules appearing in empty context (possibly more than once).
7381 llvm::SmallDenseSet<unsigned , 2 > rulesInEmptyContext;
7482
@@ -100,17 +108,21 @@ RewriteLoop::findRulesAppearingOnceInEmptyContext(
100108 evaluator.apply (step, system);
101109 }
102110
111+ auto *mutThis = const_cast <RewriteLoop *>(this );
112+ mutThis->RulesInEmptyContext .clear ();
113+
103114 // Collect all rules that we saw exactly once in empty context.
104- SmallVector<unsigned , 1 > result;
105115 for (auto rule : rulesInEmptyContext) {
106116 auto found = ruleMultiplicity.find (rule);
107117 assert (found != ruleMultiplicity.end ());
108118
109119 if (found->second == 1 )
110- result .push_back (rule);
120+ mutThis-> RulesInEmptyContext .push_back (rule);
111121 }
112122
113- return result;
123+ // Cache the result for later.
124+ mutThis->Dirty = 0 ;
125+ return RulesInEmptyContext;
114126}
115127
116128// / If a rewrite loop contains an explicit rule in empty context, propagate the
@@ -145,7 +157,7 @@ RewriteLoop::findRulesAppearingOnceInEmptyContext(
145157// / explicit bit from the original rule to the canonical rule.
146158void RewriteSystem::propagateExplicitBits () {
147159 for (const auto &loop : Loops) {
148- SmallVector< unsigned , 1 > rulesInEmptyContext =
160+ auto rulesInEmptyContext =
149161 loop.findRulesAppearingOnceInEmptyContext (*this );
150162
151163 bool sawExplicitRule = false ;
@@ -457,8 +469,8 @@ void RewriteSystem::deleteRule(unsigned ruleID,
457469 llvm::dbgs () << " \n " ;
458470 }
459471
460- // Replace all occurrences of the rule with the replacement path and
461- // normalize all loops.
472+ // Replace all occurrences of the rule with the replacement path in
473+ // all remaining rewrite loops.
462474 for (auto &loop : Loops) {
463475 if (loop.isDeleted ())
464476 continue ;
@@ -467,6 +479,10 @@ void RewriteSystem::deleteRule(unsigned ruleID,
467479 if (!changed)
468480 continue ;
469481
482+ // The loop's path has changed, so we must invalidate the cached
483+ // result of findRulesAppearingOnceInEmptyContext().
484+ loop.markDirty ();
485+
470486 if (Debug.contains (DebugFlags::HomotopyReduction)) {
471487 llvm::dbgs () << " ** Updated loop: " ;
472488 loop.dump (llvm::dbgs (), *this );
0 commit comments