Skip to content

Commit 056d447

Browse files
committed
Revert "Merge pull request #76832 from swiftlang/elsh/pcmo-refactor"
This reverts commit 6b5df52, reversing changes made to b5e3f42.
1 parent e1da890 commit 056d447

File tree

2 files changed

+68
-180
lines changed

2 files changed

+68
-180
lines changed

lib/SILOptimizer/IPO/CrossModuleOptimization.cpp

Lines changed: 68 additions & 151 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ namespace {
5353
class CrossModuleOptimization {
5454
friend class InstructionVisitor;
5555

56-
llvm::DenseMap<CanType, bool> canTypesChecked;
56+
llvm::DenseMap<SILType, bool> typesChecked;
5757
llvm::SmallPtrSet<TypeBase *, 16> typesHandled;
5858

5959
SILModule &M;
@@ -90,18 +90,14 @@ class CrossModuleOptimization {
9090
void trySerializeFunctions(ArrayRef<SILFunction *> functions);
9191

9292
bool canSerializeFunction(SILFunction *function,
93-
FunctionFlags &canSerializeFlags,
94-
int maxDepth);
93+
FunctionFlags &canSerializeFlags, int maxDepth);
9594

96-
bool canSerializeFieldsByInstructionKind(SILInstruction *inst,
97-
FunctionFlags &canSerializeFlags,
98-
int maxDepth);
95+
bool canSerializeInstruction(SILInstruction *inst,
96+
FunctionFlags &canSerializeFlags, int maxDepth);
9997

10098
bool canSerializeGlobal(SILGlobalVariable *global);
10199

102100
bool canSerializeType(SILType type);
103-
bool canSerializeType(CanType type);
104-
bool canSerializeDecl(NominalTypeDecl *decl);
105101

106102
bool canUseFromInline(DeclContext *declCtxt);
107103

@@ -122,10 +118,11 @@ class CrossModuleOptimization {
122118
void makeDeclUsableFromInline(ValueDecl *decl);
123119

124120
void makeTypeUsableFromInline(CanType type);
121+
122+
void makeSubstUsableFromInline(const SubstitutionMap &substs);
125123
};
126124

127-
/// Visitor for detecting if an instruction can be serialized and also making used
128-
/// types of an instruction inlinable if so.
125+
/// Visitor for making used types of an instruction inlinable.
129126
///
130127
/// We use the SILCloner for visiting types, though it sucks that we allocate
131128
/// instructions just to delete them immediately. But it's better than to
@@ -137,22 +134,12 @@ class InstructionVisitor : public SILCloner<InstructionVisitor> {
137134
friend class SILInstructionVisitor<InstructionVisitor>;
138135
friend class CrossModuleOptimization;
139136

140-
public:
141-
/// This visitor is used for 2 passes, 1st pass that detects whether the instruction
142-
/// visited can be serialized, and 2nd pass that does the serializing.
143-
enum class VisitMode {
144-
DetectSerializableInst,
145-
SerializeInst
146-
};
147-
148137
private:
149138
CrossModuleOptimization &CMS;
150-
VisitMode mode;
151-
bool isInstSerializable = true;
152139

153140
public:
154-
InstructionVisitor(SILFunction &F, CrossModuleOptimization &CMS, VisitMode visitMode) :
155-
SILCloner(F), CMS(CMS), mode(visitMode) {}
141+
InstructionVisitor(SILFunction &F, CrossModuleOptimization &CMS) :
142+
SILCloner(F), CMS(CMS) {}
156143

157144
SILType remapType(SILType Ty) {
158145
if (Ty.hasLocalArchetype()) {
@@ -162,15 +149,7 @@ class InstructionVisitor : public SILCloner<InstructionVisitor> {
162149
SubstFlags::SubstituteLocalArchetypes);
163150
}
164151

165-
switch (mode) {
166-
case VisitMode::DetectSerializableInst:
167-
if (!CMS.canSerializeType(Ty))
168-
isInstSerializable = false;
169-
break;
170-
case VisitMode::SerializeInst:
171-
CMS.makeTypeUsableFromInline(Ty.getASTType());
172-
break;
173-
}
152+
CMS.makeTypeUsableFromInline(Ty.getASTType());
174153
return Ty;
175154
}
176155

@@ -181,15 +160,7 @@ class InstructionVisitor : public SILCloner<InstructionVisitor> {
181160
SubstFlags::SubstituteLocalArchetypes)->getCanonicalType();
182161
}
183162

184-
switch (mode) {
185-
case VisitMode::DetectSerializableInst:
186-
if (!CMS.canSerializeType(Ty))
187-
isInstSerializable = false;
188-
break;
189-
case VisitMode::SerializeInst:
190-
CMS.makeTypeUsableFromInline(Ty);
191-
break;
192-
}
163+
CMS.makeTypeUsableFromInline(Ty);
193164
return Ty;
194165
}
195166

@@ -200,32 +171,7 @@ class InstructionVisitor : public SILCloner<InstructionVisitor> {
200171
SubstFlags::SubstituteLocalArchetypes);
201172
}
202173

203-
for (Type replType : Subs.getReplacementTypes()) {
204-
switch (mode) {
205-
case VisitMode::DetectSerializableInst:
206-
CMS.canSerializeType(replType->getCanonicalType());
207-
break;
208-
case VisitMode::SerializeInst:
209-
/// Ensure that all replacement types of \p Subs are usable from serialized
210-
/// functions.
211-
CMS.makeTypeUsableFromInline(replType->getCanonicalType());
212-
break;
213-
}
214-
}
215-
for (ProtocolConformanceRef pref : Subs.getConformances()) {
216-
if (pref.isConcrete()) {
217-
ProtocolConformance *concrete = pref.getConcrete();
218-
switch (mode) {
219-
case VisitMode::DetectSerializableInst:
220-
if (!CMS.canSerializeDecl(concrete->getProtocol()))
221-
isInstSerializable = false;
222-
break;
223-
case VisitMode::SerializeInst:
224-
CMS.makeDeclUsableFromInline(concrete->getProtocol());
225-
break;
226-
}
227-
}
228-
}
174+
CMS.makeSubstUsableFromInline(Subs);
229175
return Subs;
230176
}
231177

@@ -234,36 +180,9 @@ class InstructionVisitor : public SILCloner<InstructionVisitor> {
234180
Cloned->eraseFromParent();
235181
}
236182

237-
// This method retrieves the operand passed as \p Value as mapped
238-
// in a previous instruction.
239-
SILValue getMappedValue(SILValue Value) {
240-
switch (mode) {
241-
case VisitMode::DetectSerializableInst:
242-
// Typically, the type of the operand (\p Value) is already checked
243-
// and remapped as the resulting type of a previous instruction, so
244-
// rechecking the type isn't necessary. However, certain instructions
245-
// have operands that weren’t previously mapped, such as:
246-
//
247-
// ```
248-
// bb0(%0 : $*Foo):
249-
// %1 = struct_element_addr %0 : $*Foo, #Foo.bar
250-
// ```
251-
// where the operand of the first instruction is the argument of the
252-
// basic block. In such case, an explicit check for the operand's type
253-
// is required to ensure serializability.
254-
remapType(Value->getType());
255-
break;
256-
case VisitMode::SerializeInst:
257-
break;
258-
}
259-
return Value;
260-
}
183+
SILValue getMappedValue(SILValue Value) { return Value; }
261184

262185
SILBasicBlock *remapBasicBlock(SILBasicBlock *BB) { return BB; }
263-
264-
bool canSerializeTypesInInst(SILInstruction *inst) {
265-
return isInstSerializable;
266-
}
267186
};
268187

269188
static bool isPackageCMOEnabled(ModuleDecl *mod) {
@@ -537,36 +456,32 @@ bool CrossModuleOptimization::canSerializeFunction(
537456
}
538457

539458
// Check if any instruction prevents serializing the function.
540-
InstructionVisitor visitor(*function, *this, InstructionVisitor::VisitMode::DetectSerializableInst);
541-
542459
for (SILBasicBlock &block : *function) {
543460
for (SILInstruction &inst : block) {
544-
visitor.getBuilder().setInsertionPoint(&inst);
545-
// First, visit each instruction and see if its
546-
// canonical or substituted types are serializalbe.
547-
visitor.visit(&inst);
548-
if (!visitor.canSerializeTypesInInst(&inst)) {
549-
M.reclaimUnresolvedLocalArchetypeDefinitions();
550-
return false;
551-
}
552-
// Next, check for any fields that weren't visited.
553-
if (!canSerializeFieldsByInstructionKind(&inst, canSerializeFlags, maxDepth)) {
554-
M.reclaimUnresolvedLocalArchetypeDefinitions();
461+
if (!canSerializeInstruction(&inst, canSerializeFlags, maxDepth)) {
555462
return false;
556463
}
557464
}
558465
}
559-
M.reclaimUnresolvedLocalArchetypeDefinitions();
560-
561466
canSerializeFlags[function] = true;
562467
return true;
563468
}
564469

565-
/// Returns true if \p inst can be serialized by checking its fields per instruction kind.
470+
/// Returns true if \p inst can be serialized.
566471
///
567472
/// If \p inst is a function_ref, recursively visits the referenced function.
568-
bool CrossModuleOptimization::canSerializeFieldsByInstructionKind(
473+
bool CrossModuleOptimization::canSerializeInstruction(
569474
SILInstruction *inst, FunctionFlags &canSerializeFlags, int maxDepth) {
475+
// First check if any result or operand types prevent serialization.
476+
for (SILValue result : inst->getResults()) {
477+
if (!canSerializeType(result->getType()))
478+
return false;
479+
}
480+
for (Operand &op : inst->getAllOperands()) {
481+
if (!canSerializeType(op.get()->getType()))
482+
return false;
483+
}
484+
570485
if (auto *FRI = dyn_cast<FunctionRefBaseInst>(inst)) {
571486
SILFunction *callee = FRI->getReferencedFunctionOrNull();
572487
if (!callee)
@@ -658,45 +573,6 @@ bool CrossModuleOptimization::canSerializeFieldsByInstructionKind(
658573
return true;
659574
}
660575

661-
bool CrossModuleOptimization::canSerializeType(SILType type) {
662-
return canSerializeType(type.getASTType());
663-
}
664-
665-
bool CrossModuleOptimization::canSerializeType(CanType type) {
666-
auto iter = canTypesChecked.find(type);
667-
if (iter != canTypesChecked.end())
668-
return iter->getSecond();
669-
670-
bool success = type.findIf(
671-
[this](Type rawSubType) {
672-
CanType subType = rawSubType->getCanonicalType();
673-
if (auto nominal = subType->getNominalOrBoundGenericNominal()) {
674-
return canSerializeDecl(nominal);
675-
}
676-
// If reached here, the type is a Builtin type or similar,
677-
// e.g. Builtin.Int64, Builtin.Word, Builtin.NativeObject, etc.
678-
return true;
679-
});
680-
681-
canTypesChecked[type] = success;
682-
return success;
683-
}
684-
685-
bool CrossModuleOptimization::canSerializeDecl(NominalTypeDecl *decl) {
686-
assert(decl && "Decl should not be null when checking if it can be serialized");
687-
688-
// In conservative mode we don't want to change the access level of types.
689-
if (conservative && decl->getEffectiveAccess() < AccessLevel::Package) {
690-
return false;
691-
}
692-
// Exclude types which are defined in an @_implementationOnly imported
693-
// module. Such modules are not transitively available.
694-
if (!canUseFromInline(decl)) {
695-
return false;
696-
}
697-
return true;
698-
}
699-
700576
bool CrossModuleOptimization::canSerializeGlobal(SILGlobalVariable *global) {
701577
// Check for referenced functions in the initializer.
702578
for (const SILInstruction &initInst : *global) {
@@ -718,6 +594,32 @@ bool CrossModuleOptimization::canSerializeGlobal(SILGlobalVariable *global) {
718594
return true;
719595
}
720596

597+
bool CrossModuleOptimization::canSerializeType(SILType type) {
598+
auto iter = typesChecked.find(type);
599+
if (iter != typesChecked.end())
600+
return iter->getSecond();
601+
602+
bool success = !type.getASTType().findIf(
603+
[this](Type rawSubType) {
604+
CanType subType = rawSubType->getCanonicalType();
605+
if (NominalTypeDecl *subNT = subType->getNominalOrBoundGenericNominal()) {
606+
607+
if (conservative && subNT->getEffectiveAccess() < AccessLevel::Package) {
608+
return true;
609+
}
610+
611+
// Exclude types which are defined in an @_implementationOnly imported
612+
// module. Such modules are not transitively available.
613+
if (!canUseFromInline(subNT)) {
614+
return true;
615+
}
616+
}
617+
return false;
618+
});
619+
typesChecked[type] = success;
620+
return success;
621+
}
622+
721623
/// Returns true if the function in \p funcCtxt could be linked statically to
722624
/// this module.
723625
static bool couldBeLinkedStatically(DeclContext *funcCtxt, SILModule &module) {
@@ -811,7 +713,7 @@ void CrossModuleOptimization::serializeFunction(SILFunction *function,
811713
}
812714
function->setSerializedKind(getRightSerializedKind(M));
813715

814-
InstructionVisitor visitor(*function, *this, InstructionVisitor::VisitMode::SerializeInst);
716+
InstructionVisitor visitor(*function, *this);
815717
for (SILBasicBlock &block : *function) {
816718
for (SILInstruction &inst : block) {
817719
visitor.getBuilder().setInsertionPoint(&inst);
@@ -1010,6 +912,21 @@ void CrossModuleOptimization::makeTypeUsableFromInline(CanType type) {
1010912
});
1011913
}
1012914

915+
/// Ensure that all replacement types of \p substs are usable from serialized
916+
/// functions.
917+
void CrossModuleOptimization::makeSubstUsableFromInline(
918+
const SubstitutionMap &substs) {
919+
for (Type replType : substs.getReplacementTypes()) {
920+
makeTypeUsableFromInline(replType->getCanonicalType());
921+
}
922+
for (ProtocolConformanceRef pref : substs.getConformances()) {
923+
if (pref.isConcrete()) {
924+
ProtocolConformance *concrete = pref.getConcrete();
925+
makeDeclUsableFromInline(concrete->getProtocol());
926+
}
927+
}
928+
}
929+
1013930
class CrossModuleOptimizationPass: public SILModuleTransform {
1014931
void run() override {
1015932
auto &M = *getModule();

test/SILOptimizer/package-cmo-cast-internal-dst

Lines changed: 0 additions & 29 deletions
This file was deleted.

0 commit comments

Comments
 (0)