Skip to content

Commit d72500d

Browse files
committed
RequirementMachine: Cache result of RewriteLoop::findRulesAppearingOnceInEmptyContext()
1 parent 4cc7589 commit d72500d

File tree

2 files changed

+44
-11
lines changed

2 files changed

+44
-11
lines changed

lib/AST/RequirementMachine/HomotopyReduction.cpp

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -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>
7074
RewriteLoop::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.
146158
void 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);

lib/AST/RequirementMachine/RewriteLoop.h

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -293,24 +293,41 @@ class RewriteLoop {
293293
RewritePath Path;
294294

295295
private:
296-
bool Deleted;
296+
unsigned Deleted : 1;
297+
298+
/// Cached value for findRulesAppearingOnceInEmptyContext().
299+
SmallVector<unsigned, 1> RulesInEmptyContext;
300+
301+
/// If true, RulesInEmptyContext should be recomputed.
302+
unsigned Dirty : 1;
297303

298304
public:
299305
RewriteLoop(MutableTerm basepoint, RewritePath path)
300-
: Basepoint(basepoint), Path(path), Deleted(false) {}
306+
: Basepoint(basepoint), Path(path) {
307+
Deleted = 0;
308+
309+
// Initially, the RulesInEmptyContext vector is not valid because
310+
// it has not been computed yet.
311+
Dirty = 1;
312+
}
301313

302314
bool isDeleted() const {
303315
return Deleted;
304316
}
305317

306318
void markDeleted() {
307319
assert(!Deleted);
308-
Deleted = true;
320+
Deleted = 1;
321+
}
322+
323+
/// This must be called after changing 'Path'.
324+
void markDirty() {
325+
Dirty = 1;
309326
}
310327

311328
bool isInContext(const RewriteSystem &system) const;
312329

313-
llvm::SmallVector<unsigned, 1>
330+
ArrayRef<unsigned>
314331
findRulesAppearingOnceInEmptyContext(const RewriteSystem &system) const;
315332

316333
void findProtocolConformanceRules(

0 commit comments

Comments
 (0)