From 7ede371e87943216817f58dcb523195046926335 Mon Sep 17 00:00:00 2001 From: Erik Eckstein Date: Mon, 1 Jul 2024 11:49:05 +0200 Subject: [PATCH 1/2] MandatoryPerformanceOptimizations: don't crash with empty global-init-once functions Instead ignore empty global-init-once functions https://github.com/swiftlang/swift/issues/73487 rdar://130041582 --- .../ModulePasses/MandatoryPerformanceOptimizations.swift | 3 +++ test/SILOptimizer/mandatory_performance_optimizations.sil | 5 +++++ 2 files changed, 8 insertions(+) diff --git a/SwiftCompilerSources/Sources/Optimizer/ModulePasses/MandatoryPerformanceOptimizations.swift b/SwiftCompilerSources/Sources/Optimizer/ModulePasses/MandatoryPerformanceOptimizations.swift index 0d206bbe6362f..7236991c8e410 100644 --- a/SwiftCompilerSources/Sources/Optimizer/ModulePasses/MandatoryPerformanceOptimizations.swift +++ b/SwiftCompilerSources/Sources/Optimizer/ModulePasses/MandatoryPerformanceOptimizations.swift @@ -355,6 +355,9 @@ private extension Value { private extension Function { /// Analyzes the global initializer function and returns global it initializes (from `alloc_global` instruction). func getInitializedGlobal() -> GlobalVariable? { + if !isDefinition { + return nil + } for inst in self.entryBlock.instructions { switch inst { case let agi as AllocGlobalInst: diff --git a/test/SILOptimizer/mandatory_performance_optimizations.sil b/test/SILOptimizer/mandatory_performance_optimizations.sil index 4564548dc5f46..15f622954f5b7 100644 --- a/test/SILOptimizer/mandatory_performance_optimizations.sil +++ b/test/SILOptimizer/mandatory_performance_optimizations.sil @@ -167,6 +167,11 @@ bb0: return %6 : $() } +// Check that we don't crash on global init-once declarations. + +// CHECK-LABEL: sil [global_init_once_fn] [no_locks] @external_global_init_once : $@convention(c) () -> () +sil [global_init_once_fn] [no_locks] @external_global_init_once : $@convention(c) () -> () + sil @yield_int_value : $@convention(thin) @yield_once () -> (@yields Int32) { bb0: %0 = integer_literal $Builtin.Int32, 10 From d4de1a0472b5d5beb85a1a0544378a81d10fe408 Mon Sep 17 00:00:00 2001 From: Erik Eckstein Date: Mon, 1 Jul 2024 11:49:17 +0200 Subject: [PATCH 2/2] Deserializer: fix a crash with global variables and cross-module-optimization In case of cross-module-optimizations it can happen that a private global variable is changed to public, but it's declaration is not available in the module file. --- lib/Serialization/DeserializeSIL.cpp | 14 +++++++++++++- .../Inputs/cross-module/cross-module.swift | 6 ++++++ test/SILOptimizer/cross-module-optimization.swift | 7 +++++++ 3 files changed, 26 insertions(+), 1 deletion(-) diff --git a/lib/Serialization/DeserializeSIL.cpp b/lib/Serialization/DeserializeSIL.cpp index 439f35245545e..e5713a7cced81 100644 --- a/lib/Serialization/DeserializeSIL.cpp +++ b/lib/Serialization/DeserializeSIL.cpp @@ -3642,11 +3642,23 @@ SILGlobalVariable *SILDeserializer::readGlobalVar(StringRef Name) { return nullptr; } + VarDecl *globalDecl = nullptr; + if (dID) { + llvm::Expected d = MF->getDeclChecked(dID); + if (d) { + globalDecl = cast(d.get()); + } else { + // This can happen with cross-module-optimizations, if the linkage of a + // private global variable is changed to public. + consumeError(d.takeError()); + } + } + auto Ty = MF->getType(TyID); SILGlobalVariable *v = SILGlobalVariable::create( SILMod, linkage.value(), SerializedKind_t(serializedKind), Name.str(), getSILType(Ty, SILValueCategory::Object, nullptr), - std::nullopt, dID ? cast(MF->getDecl(dID)) : nullptr); + std::nullopt, globalDecl); v->setLet(IsLet); globalVarOrOffset.set(v, true /*isFullyDeserialized*/); v->setDeclaration(IsDeclaration); diff --git a/test/SILOptimizer/Inputs/cross-module/cross-module.swift b/test/SILOptimizer/Inputs/cross-module/cross-module.swift index 1b657b0622e00..063fc76a2caa0 100644 --- a/test/SILOptimizer/Inputs/cross-module/cross-module.swift +++ b/test/SILOptimizer/Inputs/cross-module/cross-module.swift @@ -287,6 +287,12 @@ public func callCImplementationOnly(_ t: T) -> Int { public let globalLet = 529387 +private var privateVar = Int.random(in: 0..<100) + +public func getRandom() -> Int { + return privateVar +} + public struct StructWithClosure { public static let c = { (x: Int) -> Int in return x } } diff --git a/test/SILOptimizer/cross-module-optimization.swift b/test/SILOptimizer/cross-module-optimization.swift index b74417195c875..7514aba5de3f3 100644 --- a/test/SILOptimizer/cross-module-optimization.swift +++ b/test/SILOptimizer/cross-module-optimization.swift @@ -165,6 +165,12 @@ func testImplementationOnly() { // CHECK-SIL2: } // end sil function '$s4Main22testImplementationOnlyyyF' } +@inline(never) +func testPrivateVar() { + // CHECK-OUTPUT: {{[0-9]+}} + print(getRandom()) +} + testNestedTypes() testClass() testError() @@ -175,4 +181,5 @@ testKeypath() testMisc() testGlobal() testImplementationOnly() +testPrivateVar()