Skip to content

Commit 15708cc

Browse files
authored
Merge pull request #3861 from swiftwasm/main
2 parents 06d4469 + cc87566 commit 15708cc

File tree

69 files changed

+676
-838
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

69 files changed

+676
-838
lines changed

include/swift/AST/ASTContext.h

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ namespace namelookup {
140140
}
141141

142142
namespace rewriting {
143-
class RequirementMachine;
143+
class RewriteContext;
144144
}
145145

146146
namespace syntax {
@@ -1215,21 +1215,13 @@ class ASTContext final {
12151215
GenericSignatureBuilder *getOrCreateGenericSignatureBuilder(
12161216
CanGenericSignature sig);
12171217

1218-
/// Retrieve or create a term rewriting system for answering queries on
1219-
/// type parameters written against the given generic signature.
1220-
rewriting::RequirementMachine *getOrCreateRequirementMachine(
1221-
CanGenericSignature sig);
1218+
rewriting::RewriteContext &getRewriteContext();
12221219

12231220
/// This is a hack to break cycles. Don't introduce new callers of this
12241221
/// method.
12251222
bool isRecursivelyConstructingRequirementMachine(
12261223
CanGenericSignature sig);
12271224

1228-
/// Retrieve or create a term rewriting system for answering queries on
1229-
/// type parameters written against the given protocol requirement signature.
1230-
rewriting::RequirementMachine *getOrCreateRequirementMachine(
1231-
const ProtocolDecl *proto);
1232-
12331225
/// Retrieve a generic signature with a single unconstrained type parameter,
12341226
/// like `<T>`.
12351227
CanGenericSignature getSingleGenericParameterSignature() const;

include/swift/AST/TypeCheckRequests.h

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -406,8 +406,9 @@ class ProtocolDependenciesRequest :
406406
bool isCached() const { return true; }
407407
};
408408

409-
/// Compute the requirements that describe a protocol using the
410-
/// RequirementMachine.
409+
/// Compute a protocol's requirement signature using the RequirementMachine.
410+
/// This is temporary; once the GenericSignatureBuilder goes away this will
411+
/// be folded into RequirementSignatureRequest.
411412
class RequirementSignatureRequestRQM :
412413
public SimpleRequest<RequirementSignatureRequestRQM,
413414
ArrayRef<Requirement>(ProtocolDecl *),
@@ -1466,6 +1467,38 @@ class AbstractGenericSignatureRequest :
14661467
}
14671468
};
14681469

1470+
/// Build a generic signature using the RequirementMachine. This is temporary;
1471+
/// once the GenericSignatureBuilder goes away this will be folded into
1472+
/// AbstractGenericSignatureRequest.
1473+
class AbstractGenericSignatureRequestRQM :
1474+
public SimpleRequest<AbstractGenericSignatureRequestRQM,
1475+
GenericSignatureWithError (const GenericSignatureImpl *,
1476+
SmallVector<GenericTypeParamType *, 2>,
1477+
SmallVector<Requirement, 2>),
1478+
RequestFlags::Cached> {
1479+
public:
1480+
using SimpleRequest::SimpleRequest;
1481+
1482+
private:
1483+
friend SimpleRequest;
1484+
1485+
// Evaluation.
1486+
GenericSignatureWithError
1487+
evaluate(Evaluator &evaluator,
1488+
const GenericSignatureImpl *baseSignature,
1489+
SmallVector<GenericTypeParamType *, 2> addedParameters,
1490+
SmallVector<Requirement, 2> addedRequirements) const;
1491+
1492+
public:
1493+
// Separate caching.
1494+
bool isCached() const { return true; }
1495+
1496+
/// Abstract generic signature requests never have source-location info.
1497+
SourceLoc getNearestLoc() const {
1498+
return SourceLoc();
1499+
}
1500+
};
1501+
14691502
class InferredGenericSignatureRequest :
14701503
public SimpleRequest<InferredGenericSignatureRequest,
14711504
GenericSignatureWithError (ModuleDecl *,

include/swift/AST/TypeCheckerTypeIDZone.def

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,11 @@ SWIFT_REQUEST(TypeChecker, AbstractGenericSignatureRequest,
2020
SmallVector<GenericTypeParamType *, 2>,
2121
SmallVector<Requirement, 2>),
2222
Cached, NoLocationInfo)
23+
SWIFT_REQUEST(TypeChecker, AbstractGenericSignatureRequestRQM,
24+
GenericSignatureWithError (const GenericSignatureImpl *,
25+
SmallVector<GenericTypeParamType *, 2>,
26+
SmallVector<Requirement, 2>),
27+
Cached, NoLocationInfo)
2328
SWIFT_REQUEST(TypeChecker, ApplyAccessNoteRequest,
2429
evaluator::SideEffect(ValueDecl *), Cached, NoLocationInfo)
2530
SWIFT_REQUEST(TypeChecker, AttachedResultBuilderRequest,

include/swift/Basic/LangOptions.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -473,11 +473,11 @@ namespace swift {
473473
/// Enables fine-grained debug output from the requirement machine.
474474
std::string DebugRequirementMachine;
475475

476-
/// Maximum iteration count for requirement machine confluent completion
476+
/// Maximum iteration count for requirement machine Knuth-Bendix completion
477477
/// algorithm.
478478
unsigned RequirementMachineStepLimit = 4000;
479479

480-
/// Maximum term length for requirement machine confluent completion
480+
/// Maximum term length for requirement machine Knuth-Bendix completion
481481
/// algorithm.
482482
unsigned RequirementMachineDepthLimit = 10;
483483

@@ -486,6 +486,10 @@ namespace swift {
486486
RequirementMachineMode RequirementMachineProtocolSignatures =
487487
RequirementMachineMode::Disabled;
488488

489+
/// Enable the new experimental generic signature minimization algorithm.
490+
RequirementMachineMode RequirementMachineGenericSignatures =
491+
RequirementMachineMode::Disabled;
492+
489493
/// Sets the target we are building for and updates platform conditions
490494
/// to match.
491495
///

include/swift/Option/Options.td

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -624,6 +624,10 @@ def requirement_machine_protocol_signatures_EQ : Joined<["-"], "requirement-mach
624624
Flags<[FrontendOption]>,
625625
HelpText<"Control usage of experimental protocol requirement signature minimization: 'on', 'off', or 'verify'">;
626626

627+
def requirement_machine_generic_signatures_EQ : Joined<["-"], "requirement-machine-generic-signatures=">,
628+
Flags<[FrontendOption]>,
629+
HelpText<"Control usage of experimental generic signature minimization: 'on', 'off', or 'verify'">;
630+
627631
def experimental_hermetic_seal_at_link:
628632
Flag<["-"], "experimental-hermetic-seal-at-link">,
629633
Flags<[FrontendOption, HelpHidden]>,

lib/AST/ASTContext.cpp

Lines changed: 4 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2003,31 +2003,18 @@ GenericSignatureBuilder *ASTContext::getOrCreateGenericSignatureBuilder(
20032003
return builder;
20042004
}
20052005

2006-
rewriting::RequirementMachine *
2007-
ASTContext::getOrCreateRequirementMachine(CanGenericSignature sig) {
2006+
rewriting::RewriteContext &
2007+
ASTContext::getRewriteContext() {
20082008
auto &rewriteCtx = getImpl().TheRewriteContext;
20092009
if (!rewriteCtx)
20102010
rewriteCtx.reset(new rewriting::RewriteContext(*this));
20112011

2012-
return rewriteCtx->getRequirementMachine(sig);
2012+
return *rewriteCtx;
20132013
}
20142014

20152015
bool ASTContext::isRecursivelyConstructingRequirementMachine(
20162016
CanGenericSignature sig) {
2017-
auto &rewriteCtx = getImpl().TheRewriteContext;
2018-
if (!rewriteCtx)
2019-
return false;
2020-
2021-
return rewriteCtx->isRecursivelyConstructingRequirementMachine(sig);
2022-
}
2023-
2024-
rewriting::RequirementMachine *
2025-
ASTContext::getOrCreateRequirementMachine(const ProtocolDecl *proto) {
2026-
auto &rewriteCtx = getImpl().TheRewriteContext;
2027-
if (!rewriteCtx)
2028-
rewriteCtx.reset(new rewriting::RewriteContext(*this));
2029-
2030-
return rewriteCtx->getRequirementMachine(proto);
2017+
return getRewriteContext().isRecursivelyConstructingRequirementMachine(sig);
20312018
}
20322019

20332020
Optional<llvm::TinyPtrVector<ValueDecl *>>

lib/AST/GenericSignature.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,7 @@ GenericSignatureImpl::getRequirementMachine() const {
199199
return Machine;
200200

201201
const_cast<GenericSignatureImpl *>(this)->Machine
202-
= getASTContext().getOrCreateRequirementMachine(
202+
= getASTContext().getRewriteContext().getRequirementMachine(
203203
getCanonicalSignature());
204204
return Machine;
205205
}

lib/AST/GenericSignatureBuilder.cpp

Lines changed: 52 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8559,24 +8559,62 @@ AbstractGenericSignatureRequest::evaluate(
85598559
canSignatureResult.getInt());
85608560
}
85618561

8562-
// Create a generic signature that will form the signature.
8563-
GenericSignatureBuilder builder(ctx);
8564-
if (baseSignature)
8565-
builder.addGenericSignature(baseSignature);
8562+
auto buildViaGSB = [&]() {
8563+
// Create a generic signature that will form the signature.
8564+
GenericSignatureBuilder builder(ctx);
8565+
if (baseSignature)
8566+
builder.addGenericSignature(baseSignature);
85668567

8567-
auto source =
8568-
GenericSignatureBuilder::FloatingRequirementSource::forAbstract();
8568+
auto source =
8569+
GenericSignatureBuilder::FloatingRequirementSource::forAbstract();
85698570

8570-
for (auto param : addedParameters)
8571-
builder.addGenericParameter(param);
8571+
for (auto param : addedParameters)
8572+
builder.addGenericParameter(param);
85728573

8573-
for (const auto &req : addedRequirements)
8574-
builder.addRequirement(req, source, nullptr);
8574+
for (const auto &req : addedRequirements)
8575+
builder.addRequirement(req, source, nullptr);
85758576

8576-
bool hadError = builder.hadAnyError();
8577-
auto result = std::move(builder).computeGenericSignature(
8578-
/*allowConcreteGenericParams=*/true);
8579-
return GenericSignatureWithError(result, hadError);
8577+
bool hadError = builder.hadAnyError();
8578+
auto result = std::move(builder).computeGenericSignature(
8579+
/*allowConcreteGenericParams=*/true);
8580+
return GenericSignatureWithError(result, hadError);
8581+
};
8582+
8583+
auto buildViaRQM = [&]() {
8584+
return evaluateOrDefault(
8585+
ctx.evaluator,
8586+
AbstractGenericSignatureRequestRQM{
8587+
baseSignature.getPointer(),
8588+
std::move(addedParameters),
8589+
std::move(addedRequirements)},
8590+
GenericSignatureWithError());
8591+
};
8592+
8593+
switch (ctx.LangOpts.RequirementMachineGenericSignatures) {
8594+
case RequirementMachineMode::Disabled:
8595+
return buildViaGSB();
8596+
8597+
case RequirementMachineMode::Enabled:
8598+
return buildViaRQM();
8599+
8600+
case RequirementMachineMode::Verify: {
8601+
auto rqmResult = buildViaRQM();
8602+
auto gsbResult = buildViaGSB();
8603+
8604+
if (!rqmResult.getPointer() && !gsbResult.getPointer())
8605+
return gsbResult;
8606+
8607+
if (!rqmResult.getPointer()->isEqual(gsbResult.getPointer())) {
8608+
llvm::errs() << "RequirementMachine generic signature minimization is broken:\n";
8609+
llvm::errs() << "RequirementMachine says: " << rqmResult.getPointer() << "\n";
8610+
llvm::errs() << "GenericSignatureBuilder says: " << gsbResult.getPointer() << "\n";
8611+
8612+
abort();
8613+
}
8614+
8615+
return gsbResult;
8616+
}
8617+
}
85808618
}
85818619

85828620
GenericSignatureWithError

lib/AST/RequirementMachine/HomotopyReduction.cpp

Lines changed: 46 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
//
1111
//===----------------------------------------------------------------------===//
1212
//
13-
//
1413
// This file implements the algorithm for computing a minimal set of rules from
1514
// a confluent rewrite system. A minimal set of rules is:
1615
//
@@ -76,7 +75,10 @@ using namespace rewriting;
7675
llvm::SmallVector<unsigned, 1>
7776
RewriteLoop::findRulesAppearingOnceInEmptyContext(
7877
const RewriteSystem &system) const {
78+
// Rules appearing in empty context (possibly more than once).
7979
llvm::SmallDenseSet<unsigned, 2> rulesInEmptyContext;
80+
81+
// The number of times each rule appears (with or without context).
8082
llvm::SmallDenseMap<unsigned, unsigned, 2> ruleMultiplicity;
8183

8284
RewritePathEvaluator evaluator(Basepoint);
@@ -100,6 +102,7 @@ RewriteLoop::findRulesAppearingOnceInEmptyContext(
100102
step.apply(evaluator, system);
101103
}
102104

105+
// Collect all rules that we saw exactly once in empty context.
103106
SmallVector<unsigned, 1> result;
104107
for (auto rule : rulesInEmptyContext) {
105108
auto found = ruleMultiplicity.find(rule);
@@ -759,8 +762,10 @@ void RewriteSystem::minimizeRewriteSystem() {
759762
// Now find a minimal set of generating conformances.
760763
//
761764
// FIXME: For now this just produces a set of redundant conformances, but
762-
// it should actually compute the full generating conformance basis, since
763-
// we want to use the same information for finding conformance access paths.
765+
// it should actually output the canonical generating conformance equation
766+
// for each non-generating conformance. We can then use information to
767+
// compute conformance access paths, instead of the current "brute force"
768+
// algorithm used for that purpose.
764769
llvm::DenseSet<unsigned> redundantConformances;
765770
computeGeneratingConformances(redundantConformances);
766771

@@ -774,10 +779,14 @@ void RewriteSystem::minimizeRewriteSystem() {
774779
}
775780

776781
/// Collect all non-permanent, non-redundant rules whose domain is equal to
777-
/// one of the protocols in \p proto. These rules form the requirement
778-
/// signatures of these protocols.
782+
/// one of the protocols in \p proto. In other words, the first symbol of the
783+
/// left hand side term is either a protocol symbol or associated type symbol
784+
/// whose protocol is in \p proto.
785+
///
786+
/// These rules form the requirement signatures of these protocols.
779787
llvm::DenseMap<const ProtocolDecl *, std::vector<unsigned>>
780-
RewriteSystem::getMinimizedRules(ArrayRef<const ProtocolDecl *> protos) {
788+
RewriteSystem::getMinimizedProtocolRules(
789+
ArrayRef<const ProtocolDecl *> protos) const {
781790
assert(Minimized);
782791

783792
llvm::DenseMap<const ProtocolDecl *, std::vector<unsigned>> rules;
@@ -801,6 +810,33 @@ RewriteSystem::getMinimizedRules(ArrayRef<const ProtocolDecl *> protos) {
801810
return rules;
802811
}
803812

813+
/// Collect all non-permanent, non-redundant rules whose left hand side
814+
/// begins with a generic parameter symbol.
815+
///
816+
/// These rules form the top-level generic signature for this rewrite system.
817+
std::vector<unsigned>
818+
RewriteSystem::getMinimizedGenericSignatureRules() const {
819+
assert(Minimized);
820+
821+
std::vector<unsigned> rules;
822+
for (unsigned ruleID : indices(Rules)) {
823+
const auto &rule = getRule(ruleID);
824+
825+
if (rule.isPermanent())
826+
continue;
827+
828+
if (rule.isRedundant())
829+
continue;
830+
831+
if (rule.getLHS()[0].getKind() != Symbol::Kind::GenericParam)
832+
continue;
833+
834+
rules.push_back(ruleID);
835+
}
836+
837+
return rules;
838+
}
839+
804840
/// Verify that each loop begins and ends at its basepoint.
805841
void RewriteSystem::verifyRewriteLoops() const {
806842
#ifndef NDEBUG
@@ -831,6 +867,7 @@ void RewriteSystem::verifyRewriteLoops() const {
831867
/// since this suggests a misunderstanding on my part.
832868
void RewriteSystem::verifyRedundantConformances(
833869
llvm::DenseSet<unsigned> redundantConformances) const {
870+
#ifndef NDEBUG
834871
for (unsigned ruleID : redundantConformances) {
835872
const auto &rule = getRule(ruleID);
836873
assert(!rule.isPermanent() &&
@@ -848,11 +885,13 @@ void RewriteSystem::verifyRedundantConformances(
848885
abort();
849886
}
850887
}
888+
#endif
851889
}
852890

853891
// Assert if homotopy reduction failed to eliminate a rewrite rule it was
854892
// supposed to delete.
855893
void RewriteSystem::verifyMinimizedRules() const {
894+
#ifndef NDEBUG
856895
for (const auto &rule : Rules) {
857896
// Note that sometimes permanent rules can be simplified, but they can never
858897
// be redundant.
@@ -890,4 +929,5 @@ void RewriteSystem::verifyMinimizedRules() const {
890929
abort();
891930
}
892931
}
932+
#endif
893933
}

0 commit comments

Comments
 (0)