Skip to content

Commit 6216ec6

Browse files
authored
Merge pull request #73902 from apple/elsh/pkg-cmo-inline
[SIL][PackageCMO] Allow optimizing [serialized_for_pkg] functions
2 parents 6698ef4 + c3ded85 commit 6216ec6

29 files changed

+189
-186
lines changed

SwiftCompilerSources/Sources/Optimizer/InstructionSimplification/SimplifyLoad.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -281,7 +281,7 @@ private func transitivelyErase(load: LoadInst, _ context: SimplifyContext) {
281281

282282
private extension Value {
283283
func canBeCopied(into function: Function, _ context: SimplifyContext) -> Bool {
284-
if !function.isSerialized {
284+
if !function.isAnySerialized {
285285
return true
286286
}
287287

@@ -297,7 +297,7 @@ private extension Value {
297297

298298
while let value = worklist.pop() {
299299
if let fri = value as? FunctionRefInst {
300-
if !fri.referencedFunction.hasValidLinkageForFragileRef {
300+
if !fri.referencedFunction.hasValidLinkageForFragileRef(function.serializedKind) {
301301
return false
302302
}
303303
}

SwiftCompilerSources/Sources/Optimizer/Utilities/OptUtils.swift

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -655,9 +655,8 @@ extension FullApplySite {
655655
return false
656656
}
657657
// Cannot inline a non-inlinable function it an inlinable function.
658-
if parentFunction.isSerialized,
659-
let calleeFunction = referencedFunction,
660-
!calleeFunction.isSerialized {
658+
if let calleeFunction = referencedFunction,
659+
!calleeFunction.canBeInlinedIntoCaller(parentFunction.serializedKind) {
661660
return false
662661
}
663662

SwiftCompilerSources/Sources/SIL/Function.swift

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,37 @@ final public class Function : CustomStringConvertible, HasShortDescription, Hash
136136
}
137137
public var isSerialized: Bool { bridged.isSerialized() }
138138

139-
public var hasValidLinkageForFragileRef: Bool { bridged.hasValidLinkageForFragileRef() }
139+
public var isAnySerialized: Bool { bridged.isAnySerialized() }
140+
141+
public enum SerializedKind {
142+
case notSerialized, serialized, serializedForPackage
143+
}
144+
145+
public var serializedKind: SerializedKind {
146+
switch bridged.getSerializedKind() {
147+
case .IsNotSerialized: return .notSerialized
148+
case .IsSerialized: return .serialized
149+
case .IsSerializedForPackage: return .serializedForPackage
150+
default: fatalError()
151+
}
152+
}
153+
154+
private func serializedKindBridged(_ arg: SerializedKind) -> BridgedFunction.SerializedKind {
155+
switch arg {
156+
case .notSerialized: return .IsNotSerialized
157+
case .serialized: return .IsSerialized
158+
case .serializedForPackage: return .IsSerializedForPackage
159+
default: fatalError()
160+
}
161+
}
162+
163+
public func canBeInlinedIntoCaller(_ kind: SerializedKind) -> Bool {
164+
bridged.canBeInlinedIntoCaller(serializedKindBridged(kind))
165+
}
166+
167+
public func hasValidLinkageForFragileRef(_ kind: SerializedKind) -> Bool {
168+
bridged.hasValidLinkageForFragileRef(serializedKindBridged(kind))
169+
}
140170

141171
public enum ThunkKind {
142172
case noThunk, thunk, reabstractionThunk, signatureOptimizedThunk

include/swift/SIL/SILBridging.h

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -575,6 +575,12 @@ struct BridgedFunction {
575575
IsSignatureOptimizedThunk
576576
};
577577

578+
enum class SerializedKind {
579+
IsNotSerialized,
580+
IsSerialized,
581+
IsSerializedForPackage
582+
};
583+
578584
enum class Linkage {
579585
Public,
580586
PublicNonABI,
@@ -622,7 +628,10 @@ struct BridgedFunction {
622628
BRIDGED_INLINE PerformanceConstraints getPerformanceConstraints() const;
623629
BRIDGED_INLINE InlineStrategy getInlineStrategy() const;
624630
BRIDGED_INLINE bool isSerialized() const;
625-
BRIDGED_INLINE bool hasValidLinkageForFragileRef() const;
631+
BRIDGED_INLINE bool isAnySerialized() const;
632+
BRIDGED_INLINE SerializedKind getSerializedKind() const;
633+
BRIDGED_INLINE bool canBeInlinedIntoCaller(SerializedKind) const;
634+
BRIDGED_INLINE bool hasValidLinkageForFragileRef(SerializedKind) const;
626635
BRIDGED_INLINE ThunkKind isThunk() const;
627636
BRIDGED_INLINE void setThunk(ThunkKind) const;
628637
BRIDGED_INLINE bool needsStackProtection() const;

include/swift/SIL/SILBridgingImpl.h

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -720,8 +720,20 @@ bool BridgedFunction::isSerialized() const {
720720
return getFunction()->isSerialized();
721721
}
722722

723-
bool BridgedFunction::hasValidLinkageForFragileRef() const {
724-
return getFunction()->hasValidLinkageForFragileRef();
723+
bool BridgedFunction::isAnySerialized() const {
724+
return getFunction()->isAnySerialized();
725+
}
726+
727+
BridgedFunction::SerializedKind BridgedFunction::getSerializedKind() const {
728+
return (SerializedKind)getFunction()->getSerializedKind();
729+
}
730+
731+
bool BridgedFunction::canBeInlinedIntoCaller(SerializedKind kind) const {
732+
return getFunction()->canBeInlinedIntoCaller(swift::SerializedKind_t(kind));
733+
}
734+
735+
bool BridgedFunction::hasValidLinkageForFragileRef(SerializedKind kind) const {
736+
return getFunction()->hasValidLinkageForFragileRef(swift::SerializedKind_t(kind));
725737
}
726738

727739
bool BridgedFunction::needsStackProtection() const {

include/swift/SIL/SILFunction.h

Lines changed: 6 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -874,10 +874,8 @@ class SILFunction
874874
void setLinkage(SILLinkage linkage) { Linkage = unsigned(linkage); }
875875

876876
/// Checks if this (callee) function body can be inlined into the caller
877-
/// by comparing their SerializedKind_t values.
877+
/// by comparing their `SerializedKind_t` values.
878878
///
879-
/// If the \p assumeFragileCaller is true, the caller must be serialized,
880-
/// in which case the callee needs to be serialized also to be inlined.
881879
/// If both callee and caller are `not_serialized`, the callee can be inlined
882880
/// into the caller during SIL inlining passes even if it (and the caller)
883881
/// might contain private symbols. If this callee is `serialized_for_pkg`,
@@ -894,21 +892,13 @@ class SILFunction
894892
/// ```
895893
///
896894
/// \p callerSerializedKind The caller's SerializedKind.
897-
/// \p assumeFragileCaller True if the call site of this function already
898-
/// knows that the caller is serialized.
899-
bool canBeInlinedIntoCaller(
900-
std::optional<SerializedKind_t> callerSerializedKind = std::nullopt,
901-
bool assumeFragileCaller = true) const;
895+
bool canBeInlinedIntoCaller(SerializedKind_t callerSerializedKind) const;
902896

903897
/// Returns true if this function can be referenced from a fragile function
904898
/// body.
905899
/// \p callerSerializedKind The caller's SerializedKind. Used to be passed to
906900
/// \c canBeInlinedIntoCaller.
907-
/// \p assumeFragileCaller Default to true since this function must be called
908-
// if the caller is [serialized].
909-
bool hasValidLinkageForFragileRef(
910-
std::optional<SerializedKind_t> callerSerializedKind = std::nullopt,
911-
bool assumeFragileCaller = true) const;
901+
bool hasValidLinkageForFragileRef(SerializedKind_t callerSerializedKind) const;
912902

913903
/// Get's the effective linkage which is used to derive the llvm linkage.
914904
/// Usually this is the same as getLinkage(), except in one case: if this
@@ -1165,11 +1155,9 @@ class SILFunction
11651155
bool isSerialized() const {
11661156
return SerializedKind_t(SerializedKind) == IsSerialized;
11671157
}
1168-
bool isSerializedForPackage() const {
1169-
return SerializedKind_t(SerializedKind) == IsSerializedForPackage;
1170-
}
1171-
bool isNotSerialized() const {
1172-
return SerializedKind_t(SerializedKind) == IsNotSerialized;
1158+
bool isAnySerialized() const {
1159+
return SerializedKind_t(SerializedKind) == IsSerialized ||
1160+
SerializedKind_t(SerializedKind) == IsSerializedForPackage;
11731161
}
11741162

11751163
/// Get this function's serialized attribute.

include/swift/SIL/SILGlobalVariable.h

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -154,11 +154,10 @@ class SILGlobalVariable
154154
/// Check if this global variable is [serialized]. This does not check
155155
/// if it's [serialized_for_package].
156156
bool isSerialized() const;
157-
/// Check if this global variable is [serialized_for_package].
158-
bool isSerializedForPackage() const;
159-
/// Checks whether this global var is neither [serialized] nor
160-
/// [serialized_for_package].
161-
bool isNotSerialized() const;
157+
158+
/// Check if this global variable is [serialized] or [serialized_for_package].
159+
bool isAnySerialized() const;
160+
162161
/// Get this global variable's serialized attribute.
163162
SerializedKind_t getSerializedKind() const;
164163
void setSerializedKind(SerializedKind_t isSerialized);

include/swift/SIL/SILMoveOnlyDeinit.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,9 @@ class SILMoveOnlyDeinit final : public SILAllocated<SILMoveOnlyDeinit> {
6666
return funcImpl;
6767
}
6868

69-
bool isNotSerialized() const {
70-
return SerializedKind_t(serialized) == IsNotSerialized;
69+
bool isAnySerialized() const {
70+
return SerializedKind_t(serialized) == IsSerialized ||
71+
SerializedKind_t(serialized) == IsSerializedForPackage;
7172
}
7273
SerializedKind_t getSerializedKind() const {
7374
return SerializedKind_t(serialized);

include/swift/SIL/SILProperty.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,10 @@ class SILProperty : public llvm::ilist_node<SILProperty>,
5353
AbstractStorageDecl *Decl,
5454
std::optional<KeyPathPatternComponent> Component);
5555

56-
bool isNotSerialized() const { return SerializedKind_t(Serialized) == IsNotSerialized; }
56+
bool isAnySerialized() const {
57+
return SerializedKind_t(Serialized) == IsSerialized ||
58+
SerializedKind_t(Serialized) == IsSerializedForPackage;
59+
}
5760
SerializedKind_t getSerializedKind() const {
5861
return SerializedKind_t(Serialized);
5962
}

include/swift/SIL/SILVTable.h

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -158,11 +158,10 @@ class SILVTable final : public SILAllocated<SILVTable>,
158158
bool isSerialized() const {
159159
return SerializedKind_t(SerializedKind) == IsSerialized;
160160
}
161-
bool isSerializedForPackage() const {
162-
return SerializedKind_t(SerializedKind) == IsSerializedForPackage;
163-
}
164-
bool isNotSerialized() const {
165-
return SerializedKind_t(SerializedKind) == IsNotSerialized;
161+
162+
bool isAnySerialized() const {
163+
return SerializedKind_t(SerializedKind) == IsSerialized ||
164+
SerializedKind_t(SerializedKind) == IsSerializedForPackage;
166165
}
167166

168167
SerializedKind_t getSerializedKind() const {

include/swift/SIL/SILWitnessTable.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -255,12 +255,12 @@ class SILWitnessTable : public llvm::ilist_node<SILWitnessTable>,
255255
bool isSerialized() const {
256256
return SerializedKind_t(SerializedKind) == IsSerialized;
257257
}
258-
bool isSerializedForPackage() const {
259-
return SerializedKind_t(SerializedKind) == IsSerializedForPackage;
260-
}
261-
bool isNotSerialized() const {
262-
return SerializedKind_t(SerializedKind) == IsNotSerialized;
258+
259+
bool isAnySerialized() const {
260+
return SerializedKind_t(SerializedKind) == IsSerialized ||
261+
SerializedKind_t(SerializedKind) == IsSerializedForPackage;
263262
}
263+
264264
SerializedKind_t getSerializedKind() const {
265265
return SerializedKind_t(SerializedKind);
266266
}

lib/SIL/IR/Linker.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ void SILLinkerVisitor::deserializeAndPushToWorklist(SILFunction *F) {
8787
return;
8888
}
8989

90-
assert(F->isNotSerialized() == Mod.isSerialized() &&
90+
assert(!F->isAnySerialized() == Mod.isSerialized() &&
9191
"the de-serializer did set the wrong serialized flag");
9292

9393
F->setBare(IsBare);
@@ -186,8 +186,8 @@ void SILLinkerVisitor::linkInVTable(ClassDecl *D) {
186186
// for processing.
187187
for (auto &entry : Vtbl->getEntries()) {
188188
SILFunction *impl = entry.getImplementation();
189-
if (!Vtbl->isSerialized() ||
190-
impl->hasValidLinkageForFragileRef()) {
189+
if (!Vtbl->isAnySerialized() ||
190+
impl->hasValidLinkageForFragileRef(Vtbl->getSerializedKind())) {
191191
// Deserialize and recursively walk any vtable entries that do not have
192192
// bodies yet.
193193
maybeAddFunctionToWorklist(impl,

lib/SIL/IR/SILDeclRef.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -878,7 +878,6 @@ SerializedKind_t SILDeclRef::getSerializedKind() const {
878878
}
879879

880880
// Anything else that is not public is not serializable.
881-
// pcmo TODO: should check if package-cmo is enabled?
882881
if (d->getEffectiveAccess() < AccessLevel::Public)
883882
return IsNotSerialized;
884883

lib/SIL/IR/SILFunction.cpp

Lines changed: 9 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -920,8 +920,6 @@ bool SILFunction::hasName(const char *Name) const {
920920
Checks if this (callee) function body can be inlined into the caller
921921
by comparing their SerializedKind_t values.
922922
923-
If the \p assumeFragileCaller is true, the caller must be serialized,
924-
in which case the callee needs to be serialized also to be inlined.
925923
If both callee and caller are not_serialized, the callee can be inlined
926924
into the caller during SIL inlining passes even if it (and the caller)
927925
might contain private symbols. If this callee is serialized_for_pkg, it
@@ -934,22 +932,13 @@ Callee serialized_for_pkg | ok | ok | no
934932
serialized | ok | ok | ok
935933
936934
*/
937-
bool SILFunction::canBeInlinedIntoCaller(
938-
std::optional<SerializedKind_t> callerSerializedKind,
939-
bool assumeFragileCaller) const {
940-
// If the \p assumeFragileCaller is true, the caller must
941-
// be serialized, so return true only if the callee is also
942-
// serialized.
943-
if (assumeFragileCaller)
944-
return isSerialized();
945-
935+
bool SILFunction::canBeInlinedIntoCaller(SerializedKind_t callerSerializedKind) const {
946936
switch (getSerializedKind()) {
947937
// If both callee and caller are not_serialized, the callee
948938
// can be inlined into the caller during SIL inlining passes
949939
// even if it (and the caller) might contain private symbols.
950940
case IsNotSerialized:
951-
return callerSerializedKind.has_value() &&
952-
callerSerializedKind.value() == IsNotSerialized;
941+
return callerSerializedKind == IsNotSerialized;
953942

954943
// If Package-CMO is enabled, we serialize package, public,
955944
// and @usableFromInline decls as [serialized_for_package].
@@ -962,8 +951,7 @@ bool SILFunction::canBeInlinedIntoCaller(
962951
// for this callee's body to be inlined into the caller.
963952
// It can however be referenced by [serialized] caller.
964953
case IsSerializedForPackage:
965-
return callerSerializedKind.has_value() &&
966-
callerSerializedKind.value() != IsSerialized;
954+
return callerSerializedKind != IsSerialized;
967955
case IsSerialized:
968956
return true;
969957
}
@@ -972,16 +960,18 @@ bool SILFunction::canBeInlinedIntoCaller(
972960

973961
/// Returns true if this function can be referenced from a fragile function
974962
/// body.
975-
bool SILFunction::hasValidLinkageForFragileRef(
976-
std::optional<SerializedKind_t> callerSerializedKind,
977-
bool assumeFragileCaller) const {
963+
bool SILFunction::hasValidLinkageForFragileRef(SerializedKind_t callerSerializedKind) const {
978964
// Fragile functions can reference 'static inline' functions imported
979965
// from C.
980966
if (hasForeignBody())
981967
return true;
982968

969+
// The call site of this function must have checked that
970+
// caller.isAnySerialized() is true, as indicated by the
971+
// function name itself (contains 'ForFragileRef').
972+
assert(callerSerializedKind != IsNotSerialized);
983973
// If we can inline it, we can reference it.
984-
if (canBeInlinedIntoCaller(callerSerializedKind, assumeFragileCaller))
974+
if (canBeInlinedIntoCaller(callerSerializedKind))
985975
return true;
986976

987977
// If the containing module has been serialized already, we no longer

lib/SIL/IR/SILGlobalVariable.cpp

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -78,11 +78,10 @@ bool SILGlobalVariable::shouldBePreservedForDebugger() const {
7878
bool SILGlobalVariable::isSerialized() const {
7979
return SerializedKind_t(Serialized) == IsSerialized;
8080
}
81-
bool SILGlobalVariable::isSerializedForPackage() const {
82-
return SerializedKind_t(Serialized) == IsSerializedForPackage;
83-
}
84-
bool SILGlobalVariable::isNotSerialized() const {
85-
return SerializedKind_t(Serialized) == IsNotSerialized;
81+
82+
bool SILGlobalVariable::isAnySerialized() const {
83+
return SerializedKind_t(Serialized) == IsSerialized ||
84+
SerializedKind_t(Serialized) == IsSerializedForPackage;
8685
}
8786

8887
/// Get this global variable's fragile attribute.

0 commit comments

Comments
 (0)