Skip to content

Commit 5670098

Browse files
committed
RequirementMachine: Completion step and depth limits also apply to equivalence class map
1 parent e83fd4a commit 5670098

File tree

4 files changed

+68
-38
lines changed

4 files changed

+68
-38
lines changed

lib/AST/RequirementMachine/EquivalenceClassMap.cpp

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -485,10 +485,19 @@ void EquivalenceClassMap::dump(llvm::raw_ostream &out) const {
485485
/// Build the equivalence class map from all rules of the form T.[p] => T, where
486486
/// [p] is a property atom.
487487
///
488-
/// Returns true if concrete term unification performed while building the map
489-
/// introduced new rewrite rules; in this case, the completion procedure must
490-
/// run again.
491-
bool RewriteSystem::buildEquivalenceClassMap(EquivalenceClassMap &map) {
488+
/// Returns a pair consisting of a status and number of iterations executed.
489+
///
490+
/// The status is CompletionResult::MaxIterations if we exceed \p maxIterations
491+
/// iterations.
492+
///
493+
/// The status is CompletionResult::MaxDepth if we produce a rewrite rule whose
494+
/// left hand side has a length exceeding \p maxDepth.
495+
///
496+
/// Otherwise, the status is CompletionResult::Success.
497+
std::pair<RewriteSystem::CompletionResult, unsigned>
498+
RewriteSystem::buildEquivalenceClassMap(EquivalenceClassMap &map,
499+
unsigned maxIterations,
500+
unsigned maxDepth) {
492501
map.clear();
493502

494503
std::vector<std::pair<MutableTerm, Atom>> properties;
@@ -537,14 +546,17 @@ bool RewriteSystem::buildEquivalenceClassMap(EquivalenceClassMap &map) {
537546
// where the left hand side is not already equivalent to the right hand side.
538547
unsigned addedNewRules = 0;
539548
for (auto pair : inducedRules) {
540-
if (addRule(pair.first, pair.second))
549+
if (addRule(pair.first, pair.second)) {
541550
++addedNewRules;
542-
}
543551

544-
if (auto *stats = Context.getASTContext().Stats) {
545-
stats->getFrontendCounters()
546-
.NumRequirementMachineUnifiedConcreteTerms += addedNewRules;
552+
const auto &newRule = Rules.back();
553+
if (newRule.getLHS().size() > maxDepth)
554+
return std::make_pair(CompletionResult::MaxDepth, addedNewRules);
555+
}
547556
}
548557

549-
return addedNewRules > 0;
558+
if (Rules.size() > maxIterations)
559+
return std::make_pair(CompletionResult::MaxIterations, addedNewRules);
560+
561+
return std::make_pair(CompletionResult::Success, addedNewRules);
550562
}

lib/AST/RequirementMachine/RequirementMachine.cpp

Lines changed: 39 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -280,39 +280,38 @@ void RequirementMachine::addGenericSignature(CanGenericSignature sig) {
280280
/// Attempt to obtain a confluent rewrite system using the completion
281281
/// procedure.
282282
void RequirementMachine::computeCompletion(CanGenericSignature sig) {
283-
unsigned remainingSteps = Context.LangOpts.RequirementMachineStepLimit;
284-
bool keepGoing = true;
285-
286-
while (keepGoing) {
283+
while (true) {
287284
// First, run the Knuth-Bendix algorithm to resolve overlapping rules.
288285
auto result = Impl->System.computeConfluentCompletion(
289-
remainingSteps, Context.LangOpts.RequirementMachineDepthLimit);
290-
291-
assert(remainingSteps >= result.second);
292-
remainingSteps -= result.second;
286+
Context.LangOpts.RequirementMachineStepLimit,
287+
Context.LangOpts.RequirementMachineDepthLimit);
293288

294289
if (Context.Stats) {
295290
Context.Stats->getFrontendCounters()
296291
.NumRequirementMachineCompletionSteps += result.second;
297292
}
298293

299294
// Check for failure.
300-
switch (result.first) {
301-
case RewriteSystem::CompletionResult::Success:
302-
break;
303-
304-
case RewriteSystem::CompletionResult::MaxIterations:
305-
llvm::errs() << "Generic signature " << sig
306-
<< " exceeds maximum completion step count\n";
307-
Impl->System.dump(llvm::errs());
308-
abort();
309-
310-
case RewriteSystem::CompletionResult::MaxDepth:
311-
llvm::errs() << "Generic signature " << sig
312-
<< " exceeds maximum completion depth\n";
313-
Impl->System.dump(llvm::errs());
314-
abort();
315-
}
295+
auto checkCompletionResult = [&]() {
296+
switch (result.first) {
297+
case RewriteSystem::CompletionResult::Success:
298+
break;
299+
300+
case RewriteSystem::CompletionResult::MaxIterations:
301+
llvm::errs() << "Generic signature " << sig
302+
<< " exceeds maximum completion step count\n";
303+
Impl->System.dump(llvm::errs());
304+
abort();
305+
306+
case RewriteSystem::CompletionResult::MaxDepth:
307+
llvm::errs() << "Generic signature " << sig
308+
<< " exceeds maximum completion depth\n";
309+
Impl->System.dump(llvm::errs());
310+
abort();
311+
}
312+
};
313+
314+
checkCompletionResult();
316315

317316
// Simplify right hand sides in preparation for building the
318317
// equivalence class map.
@@ -321,7 +320,22 @@ void RequirementMachine::computeCompletion(CanGenericSignature sig) {
321320
// Build the equivalence class map, which performs concrete term
322321
// unification; if this added any new rules, run the completion
323322
// procedure again.
324-
keepGoing = Impl->System.buildEquivalenceClassMap(Impl->Map);
323+
result = Impl->System.buildEquivalenceClassMap(
324+
Impl->Map,
325+
Context.LangOpts.RequirementMachineStepLimit,
326+
Context.LangOpts.RequirementMachineDepthLimit);
327+
328+
if (Context.Stats) {
329+
Context.Stats->getFrontendCounters()
330+
.NumRequirementMachineUnifiedConcreteTerms += result.second;
331+
}
332+
333+
checkCompletionResult();
334+
335+
// If buildEquivalenceClassMap() added new rules, we run another
336+
// round of Knuth-Bendix, and build the equivalence class map again.
337+
if (result.second == 0)
338+
break;
325339
}
326340

327341
if (Context.LangOpts.DebugRequirementMachine) {

lib/AST/RequirementMachine/RewriteSystem.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -580,11 +580,15 @@ class RewriteSystem final {
580580
};
581581

582582
std::pair<CompletionResult, unsigned>
583-
computeConfluentCompletion(unsigned maxIterations, unsigned maxDepth);
583+
computeConfluentCompletion(unsigned maxIterations,
584+
unsigned maxDepth);
584585

585586
void simplifyRightHandSides();
586587

587-
bool buildEquivalenceClassMap(EquivalenceClassMap &map);
588+
std::pair<CompletionResult, unsigned>
589+
buildEquivalenceClassMap(EquivalenceClassMap &map,
590+
unsigned maxIterations,
591+
unsigned maxDepth);
588592

589593
void dump(llvm::raw_ostream &out) const;
590594

lib/AST/RequirementMachine/RewriteSystemCompletion.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -446,7 +446,7 @@ RewriteSystem::computeConfluentCompletion(unsigned maxIterations,
446446
// moving on to overlaps between rules introduced by completion.
447447
while (!Worklist.empty()) {
448448
// Check if we've already done too much work.
449-
if (steps >= maxIterations)
449+
if (Rules.size() > maxIterations)
450450
return std::make_pair(CompletionResult::MaxIterations, steps);
451451

452452
auto next = Worklist.front();

0 commit comments

Comments
 (0)