Skip to content

Commit 2a6a621

Browse files
authored
Merge pull request #81222 from atrick/missing-markdep
Fix LifetimeDependenceInsertion: handle boxed indirect out arguments
2 parents f5087c4 + 9d8e8d3 commit 2a6a621

File tree

3 files changed

+47
-7
lines changed

3 files changed

+47
-7
lines changed

SwiftCompilerSources/Sources/Optimizer/FunctionPasses/LifetimeDependenceInsertion.swift

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -247,18 +247,21 @@ private func insertResultDependencies(for apply: LifetimeDependentApply, _ conte
247247
insertMarkDependencies(value: dependentValue, initializer: nil, bases: sources.bases, builder: builder, context)
248248
}
249249
for resultOper in apply.applySite.indirectResultOperands {
250-
let accessBase = resultOper.value.accessBase
251-
guard case let .store(initializingStore, initialAddress) = accessBase.findSingleInitializer(context) else {
252-
continue
250+
guard let initialAddress = resultOper.value.accessBase.address else {
251+
diagnoseUnknownDependenceSource(sourceLoc: apply.applySite.location.sourceLoc, context)
252+
return
253253
}
254-
assert(initializingStore == resultOper.instruction, "an indirect result is a store")
255254
Builder.insert(after: apply.applySite, context) { builder in
256-
insertMarkDependencies(value: initialAddress, initializer: initializingStore, bases: sources.bases,
255+
insertMarkDependencies(value: initialAddress, initializer: resultOper.instruction, bases: sources.bases,
257256
builder: builder, context)
258257
}
259258
}
260259
}
261260

261+
private func diagnoseUnknownDependenceSource(sourceLoc: SourceLoc?, _ context: FunctionPassContext) {
262+
context.diagnosticEngine.diagnose(.lifetime_value_outside_scope, [], at: sourceLoc)
263+
}
264+
262265
private func insertParameterDependencies(apply: LifetimeDependentApply, target: Operand,
263266
_ context: FunctionPassContext ) {
264267
guard var sources = apply.getParameterDependenceSources(target: target) else {

test/ModuleInterface/Inputs/lifetime_dependence.swift

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,13 +69,17 @@ public func consumeAndCreate(_ view: consuming BufferView) -> BufferView {
6969
return _overrideLifetime(bv, copying: view)
7070
}
7171

72+
// FIXME: Filed rdar://150398673 ([nonescapable] allocbox-to-stack fails causing lifetime diagnostics to fail)
73+
// Remove _overrideLifetime when this is fixed.
7274
@inlinable
7375
@lifetime(copy this, copy that)
7476
public func deriveThisOrThat(_ this: consuming BufferView, _ that: consuming BufferView) -> BufferView {
7577
if (Int.random(in: 1..<100) == 0) {
76-
return BufferView(this._ptr, this._count)
78+
let thisView = BufferView(this._ptr, this._count)
79+
return _overrideLifetime(thisView, copying: this)
7780
}
78-
return BufferView(that._ptr, that._count)
81+
let thatView = BufferView(that._ptr, that._count)
82+
return _overrideLifetime(thatView, copying: that)
7983
}
8084

8185
public struct Container {

test/SILOptimizer/lifetime_dependence/dependence_insertion.sil

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,12 +41,17 @@ struct Holder {
4141
@_addressableForDependencies
4242
struct AddressableForDeps {}
4343

44+
protocol PAny : ~Copyable, ~Escapable {}
45+
4446
sil @getPtr : $@convention(thin) () -> @out UnsafeRawPointer
4547
sil @getSpan : $@convention(thin) (@in_guaranteed AnyObject) -> @lifetime(borrow 0) @out NE
4648
sil @getInoutSpan : $@convention(thin) (@inout AnyObject) -> @lifetime(borrow 0) @out NCE
4749

4850
sil @useNE : $@convention(thin) (@guaranteed NE) -> ()
4951

52+
sil @getExistential : $@convention(thin) (@inout Holder) -> @lifetime(borrow 0) @out any PAny & ~Copyable & ~Escapable
53+
sil @useExistential : $@convention(thin) (@in_guaranteed any PAny & ~Copyable & ~Escapable) -> ()
54+
5055
// Check that the inserted dependence is on the 'self' argument, not the temporary borrow.
5156
//
5257
// CHECK-LABEL: sil [available 9999] [ossa] @testSpanProp : $@convention(method) (@guaranteed AnyObject) -> @lifetime(borrow 0) @owned NE {
@@ -172,3 +177,31 @@ bb0(%0 : @guaranteed $Holder):
172177
%99 = tuple ()
173178
return %99 : $()
174179
}
180+
181+
// Test that source of a dependency may be a project_box and the mark_dependence will be inserted.
182+
//
183+
// CHECK-LABEL: sil hidden [ossa] @testBoxDependenceSource : $@convention(thin) (@inout Holder) -> () {
184+
// CHECK: [[BOX:%[0-9]+]] = project_box %2, 0
185+
// CHECK: [[ARG:%[0-9]+]] = begin_access [modify] [unknown] %0
186+
// CHECK: apply %{{.*}}([[BOX]], [[ARG]]) : $@convention(thin) (@inout Holder) -> @lifetime(borrow 0) @out any PAny & ~Copyable & ~Escapable
187+
// CHECK: mark_dependence_addr [unresolved] [[BOX]] on [[ARG]]
188+
// CHECK-LABEL: } // end sil function 'testBoxDependenceSource'
189+
sil hidden [ossa] @testBoxDependenceSource : $@convention(thin) (@inout Holder) -> () {
190+
bb0(%0 : $*Holder):
191+
%1 = alloc_box ${ let any PAny & ~Copyable & ~Escapable }, let, name "span"
192+
%2 = begin_borrow [lexical] [var_decl] %1
193+
%3 = project_box %2, 0
194+
%4 = begin_access [modify] [unknown] %0
195+
196+
%5 = function_ref @getExistential : $@convention(thin) (@inout Holder) -> @lifetime(borrow 0) @out any PAny & ~Copyable & ~Escapable
197+
%6 = apply %5(%3, %4) : $@convention(thin) (@inout Holder) -> @lifetime(borrow 0) @out any PAny & ~Copyable & ~Escapable
198+
end_access %4
199+
%8 = mark_unresolved_non_copyable_value [no_consume_or_assign] %3
200+
201+
%9 = function_ref @useExistential : $@convention(thin) (@in_guaranteed any PAny & ~Copyable & ~Escapable) -> ()
202+
%10 = apply %9(%8) : $@convention(thin) (@in_guaranteed any PAny & ~Copyable & ~Escapable) -> ()
203+
end_borrow %2
204+
destroy_value %1
205+
%13 = tuple ()
206+
return %13
207+
}

0 commit comments

Comments
 (0)