Skip to content

Commit e478ced

Browse files
committed
RequirementMachine: Move some code into a new SimplifySubstitutions.cpp
1 parent 4655fc3 commit e478ced

File tree

4 files changed

+301
-283
lines changed

4 files changed

+301
-283
lines changed

lib/AST/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ add_swift_host_library(swiftAST STATIC
8989
RequirementMachine/RewriteContext.cpp
9090
RequirementMachine/RewriteLoop.cpp
9191
RequirementMachine/RewriteSystem.cpp
92+
RequirementMachine/SimplifySubstitutions.cpp
9293
RequirementMachine/Symbol.cpp
9394
RequirementMachine/Term.cpp
9495
RequirementMachine/TypeDifference.cpp

lib/AST/RequirementMachine/PropertyMap.cpp

Lines changed: 0 additions & 171 deletions
Original file line numberDiff line numberDiff line change
@@ -414,177 +414,6 @@ void PropertyMap::buildPropertyMap() {
414414
verify();
415415
}
416416

417-
/// Similar to RewriteSystem::simplifySubstitutions(), but also replaces type
418-
/// parameters with concrete types and builds a type difference describing
419-
/// the transformation.
420-
///
421-
/// Returns None if the concrete type symbol cannot be simplified further.
422-
///
423-
/// Otherwise returns an index which can be passed to
424-
/// RewriteSystem::getTypeDifference().
425-
Optional<unsigned>
426-
PropertyMap::concretelySimplifySubstitutions(Term baseTerm, Symbol symbol,
427-
RewritePath *path) const {
428-
assert(symbol.hasSubstitutions());
429-
430-
// Fast path if the type is fully concrete.
431-
auto substitutions = symbol.getSubstitutions();
432-
if (substitutions.empty())
433-
return None;
434-
435-
// Save the original rewrite path length so that we can reset if if we don't
436-
// find anything to simplify.
437-
unsigned oldSize = (path ? path->size() : 0);
438-
439-
if (path) {
440-
// The term is at the top of the primary stack. Push all substitutions onto
441-
// the primary stack.
442-
path->add(RewriteStep::forDecompose(substitutions.size(),
443-
/*inverse=*/false));
444-
445-
// Move all substitutions but the first one to the secondary stack.
446-
for (unsigned i = 1; i < substitutions.size(); ++i)
447-
path->add(RewriteStep::forShift(/*inverse=*/false));
448-
}
449-
450-
// Simplify and collect substitutions.
451-
llvm::SmallVector<std::pair<unsigned, Term>, 1> sameTypes;
452-
llvm::SmallVector<std::pair<unsigned, Symbol>, 1> concreteTypes;
453-
454-
for (unsigned index : indices(substitutions)) {
455-
// Move the next substitution from the secondary stack to the primary stack.
456-
if (index != 0 && path)
457-
path->add(RewriteStep::forShift(/*inverse=*/true));
458-
459-
auto term = symbol.getSubstitutions()[index];
460-
MutableTerm mutTerm(term);
461-
462-
// Note that it's of course possible that the term both requires
463-
// simplification, and the simplified term has a concrete type.
464-
//
465-
// This isn't handled with our current representation of
466-
// TypeDifference, but that should be fine since the caller
467-
// has to iterate until fixed point anyway.
468-
//
469-
// This should be rare in practice.
470-
if (System.simplify(mutTerm, path)) {
471-
// Record a mapping from this substitution to the simplified term.
472-
sameTypes.emplace_back(index, Term::get(mutTerm, Context));
473-
} else {
474-
auto *props = lookUpProperties(mutTerm);
475-
476-
if (props && props->ConcreteType) {
477-
// The property map entry might apply to a suffix of the substitution
478-
// term, so prepend the appropriate prefix to its own substitutions.
479-
auto prefix = props->getPrefixAfterStrippingKey(mutTerm);
480-
auto concreteSymbol =
481-
props->ConcreteType->prependPrefixToConcreteSubstitutions(
482-
prefix, Context);
483-
484-
// Record a mapping from this substitution to the concrete type.
485-
concreteTypes.emplace_back(index, concreteSymbol);
486-
487-
// If U.V is the substitution term and V is the property map key,
488-
// apply the rewrite step U.(V => V.[concrete: C]) followed by
489-
// prepending the prefix U to each substitution in the concrete type
490-
// symbol if |U| > 0.
491-
if (path) {
492-
path->add(RewriteStep::forRewriteRule(/*startOffset=*/prefix.size(),
493-
/*endOffset=*/0,
494-
/*ruleID=*/*props->ConcreteTypeRule,
495-
/*inverse=*/true));
496-
497-
if (!prefix.empty()) {
498-
path->add(RewriteStep::forPrefixSubstitutions(/*length=*/prefix.size(),
499-
/*endOffset=*/0,
500-
/*inverse=*/false));
501-
}
502-
}
503-
}
504-
}
505-
}
506-
507-
// If nothing changed, we don't have to build the type difference.
508-
if (sameTypes.empty() && concreteTypes.empty()) {
509-
if (path) {
510-
// The rewrite path should consist of a Decompose, followed by a number
511-
// of Shifts, followed by a Compose.
512-
#ifndef NDEBUG
513-
for (auto iter = path->begin() + oldSize; iter < path->end(); ++iter) {
514-
assert(iter->Kind == RewriteStep::Shift ||
515-
iter->Kind == RewriteStep::Decompose);
516-
}
517-
#endif
518-
519-
path->resize(oldSize);
520-
}
521-
return None;
522-
}
523-
524-
auto difference = buildTypeDifference(baseTerm, symbol,
525-
sameTypes, concreteTypes,
526-
Context);
527-
assert(difference.LHS != difference.RHS);
528-
529-
unsigned differenceID = System.recordTypeDifference(difference);
530-
531-
// All simplified substitutions are now on the primary stack. Collect them to
532-
// produce the new term.
533-
if (path) {
534-
path->add(RewriteStep::forDecomposeConcrete(differenceID,
535-
/*inverse=*/true));
536-
}
537-
538-
return differenceID;
539-
}
540-
541-
void PropertyMap::concretelySimplifyLeftHandSideSubstitutions() const {
542-
for (unsigned ruleID = 0, e = System.getRules().size(); ruleID < e; ++ruleID) {
543-
auto &rule = System.getRule(ruleID);
544-
if (rule.isLHSSimplified() ||
545-
rule.isRHSSimplified() ||
546-
rule.isSubstitutionSimplified())
547-
continue;
548-
549-
auto optSymbol = rule.isPropertyRule();
550-
if (!optSymbol || !optSymbol->hasSubstitutions())
551-
continue;
552-
553-
auto symbol = *optSymbol;
554-
555-
RewritePath path;
556-
557-
auto differenceID = concretelySimplifySubstitutions(
558-
rule.getRHS(), symbol, &path);
559-
if (!differenceID)
560-
continue;
561-
562-
rule.markSubstitutionSimplified();
563-
564-
auto difference = System.getTypeDifference(*differenceID);
565-
assert(difference.LHS == symbol);
566-
567-
// If the original rule is (T.[concrete: C] => T) and [concrete: C'] is
568-
// the simplified symbol, then difference.LHS == [concrete: C] and
569-
// difference.RHS == [concrete: C'], and the rewrite path we just
570-
// built takes T.[concrete: C] to T.[concrete: C'].
571-
//
572-
// We want a path from T.[concrete: C'] to T, so invert the path to get
573-
// a path from T.[concrete: C'] to T.[concrete: C], and add a final step
574-
// applying the original rule (T.[concrete: C] => T).
575-
path.invert();
576-
path.add(RewriteStep::forRewriteRule(/*startOffset=*/0,
577-
/*endOffset=*/0,
578-
/*ruleID=*/ruleID,
579-
/*inverted=*/false));
580-
MutableTerm rhs(rule.getRHS());
581-
MutableTerm lhs(rhs);
582-
lhs.add(difference.RHS);
583-
584-
System.addRule(lhs, rhs, &path);
585-
}
586-
}
587-
588417
void PropertyMap::dump(llvm::raw_ostream &out) const {
589418
out << "Property map: {\n";
590419
for (const auto &props : Entries) {

lib/AST/RequirementMachine/RewriteSystem.cpp

Lines changed: 0 additions & 112 deletions
Original file line numberDiff line numberDiff line change
@@ -333,81 +333,6 @@ bool RewriteSystem::simplify(MutableTerm &term, RewritePath *path) const {
333333
return changed;
334334
}
335335

336-
/// Simplify terms appearing in the substitutions of the last symbol of \p term,
337-
/// which must be a superclass or concrete type symbol.
338-
bool RewriteSystem::simplifySubstitutions(Symbol &symbol,
339-
RewritePath *path) const {
340-
assert(symbol.hasSubstitutions());
341-
342-
// Fast path if the type is fully concrete.
343-
auto substitutions = symbol.getSubstitutions();
344-
if (substitutions.empty())
345-
return false;
346-
347-
// Save the original rewrite path length so that we can reset if if we don't
348-
// find anything to simplify.
349-
unsigned oldSize = (path ? path->size() : 0);
350-
351-
if (path) {
352-
// The term is at the top of the primary stack. Push all substitutions onto
353-
// the primary stack.
354-
path->add(RewriteStep::forDecompose(substitutions.size(),
355-
/*inverse=*/false));
356-
357-
// Move all substitutions but the first one to the secondary stack.
358-
for (unsigned i = 1; i < substitutions.size(); ++i)
359-
path->add(RewriteStep::forShift(/*inverse=*/false));
360-
}
361-
362-
// Simplify and collect substitutions.
363-
SmallVector<Term, 2> newSubstitutions;
364-
newSubstitutions.reserve(substitutions.size());
365-
366-
bool first = true;
367-
bool anyChanged = false;
368-
for (auto substitution : substitutions) {
369-
// Move the next substitution from the secondary stack to the primary stack.
370-
if (!first && path)
371-
path->add(RewriteStep::forShift(/*inverse=*/true));
372-
first = false;
373-
374-
// The current substitution is at the top of the primary stack; simplify it.
375-
MutableTerm mutTerm(substitution);
376-
anyChanged |= simplify(mutTerm, path);
377-
378-
// Record the new substitution.
379-
newSubstitutions.push_back(Term::get(mutTerm, Context));
380-
}
381-
382-
// All simplified substitutions are now on the primary stack. Collect them to
383-
// produce the new term.
384-
if (path) {
385-
path->add(RewriteStep::forDecompose(substitutions.size(),
386-
/*inverse=*/true));
387-
}
388-
389-
// If nothing changed, we don't have to rebuild the symbol.
390-
if (!anyChanged) {
391-
if (path) {
392-
// The rewrite path should consist of a Decompose, followed by a number
393-
// of Shifts, followed by a Compose.
394-
#ifndef NDEBUG
395-
for (auto iter = path->begin() + oldSize; iter < path->end(); ++iter) {
396-
assert(iter->Kind == RewriteStep::Shift ||
397-
iter->Kind == RewriteStep::Decompose);
398-
}
399-
#endif
400-
401-
path->resize(oldSize);
402-
}
403-
return false;
404-
}
405-
406-
// Build the new symbol with simplified substitutions.
407-
symbol = symbol.withConcreteSubstitutions(newSubstitutions, Context);
408-
return true;
409-
}
410-
411336
/// Adds a rewrite rule, returning true if the new rule was non-trivial.
412337
///
413338
/// If both sides simplify to the same term, the rule is trivial and discarded,
@@ -643,43 +568,6 @@ void RewriteSystem::simplifyRightHandSides() {
643568
}
644569
}
645570

646-
/// Simplify substitution terms in superclass, concrete type and concrete
647-
/// conformance symbols.
648-
void RewriteSystem::simplifyLeftHandSideSubstitutions() {
649-
for (unsigned ruleID = 0, e = Rules.size(); ruleID < e; ++ruleID) {
650-
auto &rule = getRule(ruleID);
651-
if (rule.isSubstitutionSimplified())
652-
continue;
653-
654-
auto lhs = rule.getLHS();
655-
auto symbol = lhs.back();
656-
if (!symbol.hasSubstitutions())
657-
continue;
658-
659-
RewritePath path;
660-
661-
// (1) First, apply the original rule to produce the original lhs.
662-
path.add(RewriteStep::forRewriteRule(/*startOffset=*/0, /*endOffset=*/0,
663-
ruleID, /*inverse=*/true));
664-
665-
// (2) Now, simplify the substitutions to get the new lhs.
666-
if (!simplifySubstitutions(symbol, &path))
667-
continue;
668-
669-
// We're either going to add a new rule or record an identity, so
670-
// mark the old rule as simplified.
671-
rule.markSubstitutionSimplified();
672-
673-
MutableTerm newLHS(lhs.begin(), lhs.end() - 1);
674-
newLHS.add(symbol);
675-
676-
// Invert the path to get a path from the new lhs to the old rhs.
677-
path.invert();
678-
679-
addRule(newLHS, MutableTerm(rule.getRHS()), &path);
680-
}
681-
}
682-
683571
/// When minimizing a generic signature, we only care about loops where the
684572
/// basepoint is a generic parameter symbol.
685573
///

0 commit comments

Comments
 (0)