Skip to content

Commit 7fec6ec

Browse files
authored
Merge pull request #3616 from swiftix/cse-of-open-existentials
[sil-serializer] Do not use RPOT order for serializing SIL basic blocks
2 parents b61c68d + 89c41ca commit 7fec6ec

File tree

7 files changed

+123
-8
lines changed

7 files changed

+123
-8
lines changed

include/swift/SIL/SILOpenedArchetypesTracker.h

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -49,11 +49,8 @@ class SILOpenedArchetypesTracker : public DeleteNotificationHandler {
4949

5050
const SILFunction &getFunction() const { return F; }
5151

52-
void addOpenedArchetypeDef(Type archetype, SILValue Def) {
53-
assert(!getOpenedArchetypeDef(archetype) &&
54-
"There can be only one definition of an opened archetype");
55-
OpenedArchetypeDefs[archetype] = Def;
56-
}
52+
// Register a definiton of a given opened archetype.
53+
void addOpenedArchetypeDef(Type archetype, SILValue Def);
5754

5855
void removeOpenedArchetypeDef(Type archetype, SILValue Def) {
5956
auto FoundDef = getOpenedArchetypeDef(archetype);
@@ -83,10 +80,19 @@ class SILOpenedArchetypesTracker : public DeleteNotificationHandler {
8380
// the typedef operands of this instruction.
8481
void registerUsedOpenedArchetypes(const SILInstruction *I);
8582

83+
// Register opened archetypes referenced by this type, if they
84+
// are not registered yet. Create placeholders representing forward
85+
// definitions of these opened archetypes.
86+
void registerUsedOpenedArchetypes(Type Ty);
87+
8688
// Unregister archetypes opened by a given instruction.
8789
// Should be only called when this instruction is to be removed.
8890
void unregisterOpenedArchetypes(const SILInstruction *I);
8991

92+
// Returns true of some of the forward opened archetype definitions
93+
// are unresolved.
94+
bool hasUnresolvedOpenedArchetypeDefinitions();
95+
9096
// Handling of instruction removal notifications.
9197
bool needsNotifications() { return true; }
9298

include/swift/Serialization/ModuleFile.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ class ProtocolConformance;
4343
/// A serialized module, along with the tools to access it.
4444
class ModuleFile : public LazyMemberLoader {
4545
friend class SerializedASTFile;
46+
friend class SILDeserializer;
4647
using Status = serialization::Status;
4748

4849
/// A reference back to the AST representation of the file.
@@ -76,6 +77,9 @@ class ModuleFile : public LazyMemberLoader {
7677
/// The data blob containing all of the module's identifiers.
7778
StringRef IdentifierData;
7879

80+
/// A callback to be invoked every time a type was deserialized.
81+
llvm::function_ref<void(Type)> DeserializedTypeCallback;
82+
7983
public:
8084
/// Represents another module that has been imported as a dependency.
8185
class Dependency {

lib/Parse/ParseSIL.cpp

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
//
1111
//===----------------------------------------------------------------------===//
1212

13+
#include "swift/Basic/Defer.h"
1314
#include "swift/Basic/Fallthrough.h"
1415
#include "swift/AST/ArchetypeBuilder.h"
1516
#include "swift/AST/NameLookup.h"
@@ -94,6 +95,7 @@ namespace {
9495
};
9596

9697
class SILParser {
98+
friend Parser;
9799
public:
98100
Parser &P;
99101
SILModule &SILMod;
@@ -112,14 +114,19 @@ namespace {
112114
llvm::StringMap<ValueBase*> LocalValues;
113115
llvm::StringMap<SourceLoc> ForwardRefLocalValues;
114116

117+
/// A callback to be invoked every time a type was deserialized.
118+
llvm::function_ref<void(Type)> ParsedTypeCallback;
119+
120+
115121
bool performTypeLocChecking(TypeLoc &T, bool IsSIL = true);
116122
bool parseSpecConformanceSubstitutions(
117123
SmallVectorImpl<ParsedSubstitution> &parsed);
118124
ProtocolConformance *parseProtocolConformanceHelper(ProtocolDecl *&proto,
119125
bool localScope);
120126
public:
121-
122-
SILParser(Parser &P) : P(P), SILMod(*P.SIL->M), TUState(*P.SIL->S) {}
127+
SILParser(Parser &P)
128+
: P(P), SILMod(*P.SIL->M), TUState(*P.SIL->S),
129+
ParsedTypeCallback([](Type ty) {}) {}
123130

124131
/// diagnoseProblems - After a function is fully parse, emit any diagnostics
125132
/// for errors and return true if there were any.
@@ -810,6 +817,8 @@ bool SILParser::parseASTType(CanType &result) {
810817
if (performTypeLocChecking(loc, false))
811818
return true;
812819
result = loc.getType()->getCanonicalType();
820+
// Invoke the callback on the parsed type.
821+
ParsedTypeCallback(loc.getType());
813822
return false;
814823
}
815824

@@ -852,6 +861,10 @@ bool SILParser::parseSILTypeWithoutQualifiers(SILType &Result,
852861

853862
Result = SILType::getPrimitiveType(Ty.getType()->getCanonicalType(),
854863
category);
864+
865+
// Invoke the callback on the parsed type.
866+
ParsedTypeCallback(Ty.getType());
867+
855868
return false;
856869

857870
}
@@ -3943,6 +3956,17 @@ bool Parser::parseDeclSIL() {
39433956
// is required for adding typedef operands to instructions.
39443957
B.setOpenedArchetypesTracker(&OpenedArchetypesTracker);
39453958

3959+
// Define a callback to be invoked on the deserialized types.
3960+
auto OldParsedTypeCallback = FunctionState.ParsedTypeCallback;
3961+
SWIFT_DEFER {
3962+
FunctionState.ParsedTypeCallback = OldParsedTypeCallback;
3963+
};
3964+
3965+
FunctionState.ParsedTypeCallback = [&OpenedArchetypesTracker,
3966+
&FunctionState](Type ty) {
3967+
OpenedArchetypesTracker.registerUsedOpenedArchetypes(ty);
3968+
};
3969+
39463970
do {
39473971
if (FunctionState.parseSILBasicBlock(B))
39483972
return true;
@@ -3951,6 +3975,12 @@ bool Parser::parseDeclSIL() {
39513975
SourceLoc RBraceLoc;
39523976
parseMatchingToken(tok::r_brace, RBraceLoc, diag::expected_sil_rbrace,
39533977
LBraceLoc);
3978+
3979+
// Check that there are no unresolved forward definitions of opened
3980+
// archetypes.
3981+
if (OpenedArchetypesTracker.hasUnresolvedOpenedArchetypeDefinitions())
3982+
llvm_unreachable(
3983+
"All forward definitions of opened archetypes should be resolved");
39543984
}
39553985

39563986
FunctionState.F->setLinkage(resolveSILLinkage(FnLinkage, isDefinition));

lib/SIL/SILOpenedArchetypesTracker.cpp

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,60 @@
1414

1515
using namespace swift;
1616

17+
void SILOpenedArchetypesTracker::addOpenedArchetypeDef(Type archetype,
18+
SILValue Def) {
19+
archetype = archetype->getDesugaredType();
20+
assert(archetype->is<ArchetypeType>() && "The type should be an archetype");
21+
auto OldDef = getOpenedArchetypeDef(archetype);
22+
if (OldDef && isa<GlobalAddrInst>(OldDef)) {
23+
// It is a forward definition created during deserialization.
24+
// Replace it with the real definition now.
25+
OldDef->replaceAllUsesWith(Def);
26+
OldDef = SILValue();
27+
}
28+
assert(!OldDef &&
29+
"There can be only one definition of an opened archetype");
30+
OpenedArchetypeDefs[archetype] = Def;
31+
}
32+
33+
/// Check if there are any unresolved forward definitions of opened
34+
/// archetypes.
35+
bool SILOpenedArchetypesTracker::hasUnresolvedOpenedArchetypeDefinitions() {
36+
for (auto &KV : getOpenedArchetypeDefs()) {
37+
assert(KV.getFirst()->is<ArchetypeType>() && "The type should be an archetype");
38+
if (!KV.getSecond() || isa<GlobalAddrInst>(KV.getSecond()))
39+
return true;
40+
}
41+
return false;
42+
}
43+
44+
void SILOpenedArchetypesTracker::registerUsedOpenedArchetypes(Type Ty) {
45+
// Nothing else to be done if the type does not contain an opened archetype.
46+
if (!Ty || !Ty->hasOpenedExistential())
47+
return;
48+
49+
// Find all opened existentials used by this type and check if their
50+
// definitions are known.
51+
Ty.visit([&](Type ty) {
52+
if (!ty->isOpenedExistential())
53+
return;
54+
55+
ty = ty->getDesugaredType();
56+
57+
// Nothing to do if a definition was seen already.
58+
if (getOpenedArchetypeDef(ty))
59+
return;
60+
61+
auto &SILMod = this->getFunction().getModule();
62+
// Create a placeholder representing a forward definition.
63+
auto Placeholder = new (SILMod)
64+
GlobalAddrInst(SILDebugLocation(), SILMod.Types.getLoweredType(ty));
65+
// Make it available to SILBuilder, so that instructions using this
66+
// archetype can be constructed.
67+
addOpenedArchetypeDef(ty, Placeholder);
68+
});
69+
}
70+
1771
// Register archetypes opened by a given instruction.
1872
// Can be used to incrementally populate the mapping, e.g.
1973
// if it is done when performing a scan of all instructions

lib/Serialization/Deserialization.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4072,6 +4072,9 @@ Type ModuleFile::getType(TypeID TID) {
40724072
return nullptr;
40734073
}
40744074

4075+
// Invoke the callback on the deserialized type.
4076+
DeserializedTypeCallback(typeOrOffset);
4077+
40754078
return typeOrOffset;
40764079
}
40774080

lib/Serialization/DeserializeSIL.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
#define DEBUG_TYPE "deserialize"
1414
#include "DeserializeSIL.h"
15+
#include "swift/Basic/Defer.h"
1516
#include "swift/Serialization/ModuleFile.h"
1617
#include "SILFormat.h"
1718
#include "swift/SIL/SILArgument.h"
@@ -559,6 +560,16 @@ SILFunction *SILDeserializer::readSILFunction(DeclID FID,
559560
// is required for adding typedef operands to instructions.
560561
Builder.setOpenedArchetypesTracker(&OpenedArchetypesTracker);
561562

563+
// Define a callback to be invoked on the deserialized types.
564+
auto OldDeserializedTypeCallback = MF->DeserializedTypeCallback;
565+
SWIFT_DEFER {
566+
MF->DeserializedTypeCallback = OldDeserializedTypeCallback;
567+
};
568+
569+
MF->DeserializedTypeCallback = [&OpenedArchetypesTracker] (Type ty) {
570+
OpenedArchetypesTracker.registerUsedOpenedArchetypes(ty);
571+
};
572+
562573
// Another SIL_FUNCTION record means the end of this SILFunction.
563574
// SIL_VTABLE or SIL_GLOBALVAR or SIL_WITNESS_TABLE record also means the end
564575
// of this SILFunction.
@@ -598,6 +609,12 @@ SILFunction *SILDeserializer::readSILFunction(DeclID FID,
598609
if (fn->empty() && errorIfEmptyBody)
599610
return nullptr;
600611

612+
// Check that there are no unresolved forward definitions of opened
613+
// archetypes.
614+
if (OpenedArchetypesTracker.hasUnresolvedOpenedArchetypeDefinitions())
615+
llvm_unreachable(
616+
"All forward definitions of opened archetypes should be resolved");
617+
601618
if (Callback)
602619
Callback->didDeserializeFunctionBody(MF->getAssociatedModule(), fn);
603620

lib/Serialization/ModuleFile.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -755,7 +755,8 @@ ModuleFile::ModuleFile(
755755
ModuleInputReader(getStartBytePtr(this->ModuleInputBuffer.get()),
756756
getEndBytePtr(this->ModuleInputBuffer.get())),
757757
ModuleDocInputReader(getStartBytePtr(this->ModuleDocInputBuffer.get()),
758-
getEndBytePtr(this->ModuleDocInputBuffer.get())) {
758+
getEndBytePtr(this->ModuleDocInputBuffer.get())),
759+
DeserializedTypeCallback([](Type ty) {}) {
759760
assert(getStatus() == Status::Valid);
760761
Bits.IsFramework = isFramework;
761762

0 commit comments

Comments
 (0)