From 36205d90d2e8217e417ff13c1a24acd176740173 Mon Sep 17 00:00:00 2001 From: Nate Chandler Date: Mon, 29 Sep 2025 13:55:55 -0700 Subject: [PATCH 1/4] [Gardening] Detypo'd "inlining". --- .../Optimizer/PassManager/ContextCommon.swift | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/SwiftCompilerSources/Sources/Optimizer/PassManager/ContextCommon.swift b/SwiftCompilerSources/Sources/Optimizer/PassManager/ContextCommon.swift index 97b79ee4d5a4d..2e97fd556170f 100644 --- a/SwiftCompilerSources/Sources/Optimizer/PassManager/ContextCommon.swift +++ b/SwiftCompilerSources/Sources/Optimizer/PassManager/ContextCommon.swift @@ -96,23 +96,23 @@ extension MutatingContext { func inlineFunction(apply: FullApplySite, mandatoryInline: Bool) { // This is only a best-effort attempt to notify the new cloned instructions as changed. // TODO: get a list of cloned instructions from the `inlineFunction` - let instAfterInling: Instruction? + let instAfterInlining: Instruction? switch apply { case is ApplyInst: - instAfterInling = apply.next + instAfterInlining = apply.next case let beginApply as BeginApplyInst: let next = beginApply.next! - instAfterInling = (next is EndApplyInst ? nil : next) + instAfterInlining = (next is EndApplyInst ? nil : next) case is TryApplyInst: - instAfterInling = apply.parentBlock.next?.instructions.first + instAfterInlining = apply.parentBlock.next?.instructions.first default: - instAfterInling = nil + instAfterInlining = nil } bridgedPassContext.inlineFunction(apply.bridged, mandatoryInline) - if let instAfterInling = instAfterInling { - notifyNewInstructions(from: apply, to: instAfterInling) + if let instAfterInlining = instAfterInlining { + notifyNewInstructions(from: apply, to: instAfterInlining) } } From c17027aa4155584c67f7be127add8c21c8b863cb Mon Sep 17 00:00:00 2001 From: Nate Chandler Date: Mon, 29 Sep 2025 15:30:10 -0700 Subject: [PATCH 2/4] [Test] Add failing test. --- .../SILOptimizer/rdar161433604.swift | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 validation-test/SILOptimizer/rdar161433604.swift diff --git a/validation-test/SILOptimizer/rdar161433604.swift b/validation-test/SILOptimizer/rdar161433604.swift new file mode 100644 index 0000000000000..c43948e1c637c --- /dev/null +++ b/validation-test/SILOptimizer/rdar161433604.swift @@ -0,0 +1,26 @@ +// RUN: %target-swift-frontend \ +// RUN: -disable-availability-checking \ +// RUN: -target %target-swift-5.9-abi-triple \ +// RUN: -emit-sil -verify \ +// RUN: -enable-experimental-feature LifetimeDependence \ +// RUN: -enable-experimental-feature Embedded \ +// RUN: %s + +// REQUIRES: OS=macosx || OS=linux-gnu +// REQUIRES: swift_feature_Embedded +// REQUIRES: swift_feature_LifetimeDependence + +// XFAIL: * + +struct NoEscapeNoCopy: ~Escapable, ~Copyable {} + +protocol Foo { + var bar: NoEscapeNoCopy {get} +} + +public struct Baz: Foo { + var bar: NoEscapeNoCopy { + NoEscapeNoCopy() // expected-error{{lifetime-dependent value escapes its scope}} + // expected-note@-1{{it depends on the lifetime of this parent value}} + } // expected-note{{this use causes the lifetime-dependent value to escape}} +} From b62798381ef9b3b4daccdcb44dfabbaf2f102eb1 Mon Sep 17 00:00:00 2001 From: Nate Chandler Date: Mon, 29 Sep 2025 15:09:18 -0700 Subject: [PATCH 3/4] [Optimizer] Don't walk from deleted. During inlining, the apply is deleted. So when publishing this best effort list of which instructions were "changed" during inlining, start from the instruction before the deleted apply. --- .../Sources/Optimizer/PassManager/ContextCommon.swift | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/SwiftCompilerSources/Sources/Optimizer/PassManager/ContextCommon.swift b/SwiftCompilerSources/Sources/Optimizer/PassManager/ContextCommon.swift index 2e97fd556170f..d62f0d52b542a 100644 --- a/SwiftCompilerSources/Sources/Optimizer/PassManager/ContextCommon.swift +++ b/SwiftCompilerSources/Sources/Optimizer/PassManager/ContextCommon.swift @@ -96,6 +96,7 @@ extension MutatingContext { func inlineFunction(apply: FullApplySite, mandatoryInline: Bool) { // This is only a best-effort attempt to notify the new cloned instructions as changed. // TODO: get a list of cloned instructions from the `inlineFunction` + let instBeforeInlining = apply.previous let instAfterInlining: Instruction? switch apply { case is ApplyInst: @@ -111,8 +112,9 @@ extension MutatingContext { bridgedPassContext.inlineFunction(apply.bridged, mandatoryInline) - if let instAfterInlining = instAfterInlining { - notifyNewInstructions(from: apply, to: instAfterInlining) + if let instBeforeInlining = instBeforeInlining?.next, + let instAfterInlining = instAfterInlining { + notifyNewInstructions(from: instBeforeInlining, to: instAfterInlining) } } From 07d75186ba41a6db797012fe6a0fe1a32174374e Mon Sep 17 00:00:00 2001 From: Nate Chandler Date: Mon, 29 Sep 2025 15:16:41 -0700 Subject: [PATCH 4/4] [Optimizer] Don't walk to deleted. During inlining, some instructions in the caller may be deleted. So when publishing this best effort list of instructions which were "changed" during inlining, don't start from a deleted instruction. Instead just don't publish, as already happens in other cases. Without actually addressing ``` // TODO: get a list of cloned instructions from the `inlineFunction` ``` this is somewhat better than checking for having reached the end of the function during the walk because that will result in falsely broadcasting that some unchanged instructions have changed whereas this change only results in not broadcasting which is already being done in some cases (e.g. when a `begin_apply` is immediately followed by an `end_apply`). --- .../Sources/Optimizer/PassManager/ContextCommon.swift | 3 ++- validation-test/SILOptimizer/rdar161433604.swift | 2 -- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/SwiftCompilerSources/Sources/Optimizer/PassManager/ContextCommon.swift b/SwiftCompilerSources/Sources/Optimizer/PassManager/ContextCommon.swift index d62f0d52b542a..2d131b3ac20e2 100644 --- a/SwiftCompilerSources/Sources/Optimizer/PassManager/ContextCommon.swift +++ b/SwiftCompilerSources/Sources/Optimizer/PassManager/ContextCommon.swift @@ -113,7 +113,8 @@ extension MutatingContext { bridgedPassContext.inlineFunction(apply.bridged, mandatoryInline) if let instBeforeInlining = instBeforeInlining?.next, - let instAfterInlining = instAfterInlining { + let instAfterInlining = instAfterInlining, + !instAfterInlining.isDeleted { notifyNewInstructions(from: instBeforeInlining, to: instAfterInlining) } } diff --git a/validation-test/SILOptimizer/rdar161433604.swift b/validation-test/SILOptimizer/rdar161433604.swift index c43948e1c637c..26771f3bb1cd1 100644 --- a/validation-test/SILOptimizer/rdar161433604.swift +++ b/validation-test/SILOptimizer/rdar161433604.swift @@ -10,8 +10,6 @@ // REQUIRES: swift_feature_Embedded // REQUIRES: swift_feature_LifetimeDependence -// XFAIL: * - struct NoEscapeNoCopy: ~Escapable, ~Copyable {} protocol Foo {