Skip to content

Commit eab9a35

Browse files
committed
[NFC] Add LifetimeDependence.Scope.ignoreBorrowScope utility.
Skip borrow scopes that do not actually require lifetime dependence. This will improve LifetimeDependenceScopeFixup.
1 parent 7811a63 commit eab9a35

File tree

1 file changed

+46
-25
lines changed

1 file changed

+46
-25
lines changed

SwiftCompilerSources/Sources/Optimizer/Utilities/LifetimeDependenceUtils.swift

Lines changed: 46 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ func gatherVariableIntroducers(for value: Value, _ context: Context)
104104
/// A lifetime dependence identifies its parent value, the kind of
105105
/// scope that the parent value represents, and a dependent value.
106106
struct LifetimeDependence : CustomStringConvertible {
107+
// TODO: handle trivial values based on variable binding
107108
enum Scope : CustomStringConvertible {
108109
/// A guaranteed or inout argument whose scope is provided by the caller
109110
/// and covers the entire function and any dependent results or yields.
@@ -115,7 +116,7 @@ struct LifetimeDependence : CustomStringConvertible {
115116
/// An owned value whose OSSA lifetime encloses nonescapable values
116117
case owned(Value)
117118
/// An borrowed value whose OSSA lifetime encloses nonescapable values
118-
case borrowed(Value)
119+
case borrowed(BeginBorrowValue)
119120
/// Singly-initialized addressable storage (likely for an
120121
/// immutable address-only value). The lifetime extends until the
121122
/// memory is destroyed. e.g. A value produced by an @in
@@ -127,7 +128,8 @@ struct LifetimeDependence : CustomStringConvertible {
127128
/// If `initializingStore` is nil, then the `initialAddress` is
128129
/// initialized on function entry.
129130
case initialized(initialAddress: Value, initializingStore: Instruction?)
130-
// TODO: make .unknown a SIL Verification error
131+
// TODO: Add SIL verification that no mark_depedence [unresolved] has an unknown LifetimeDependence.
132+
// This currently requires stack allocations to be singly initialized.
131133
case unknown(Value)
132134

133135
var parentValue: Value {
@@ -136,7 +138,7 @@ struct LifetimeDependence : CustomStringConvertible {
136138
case let .access(beginAccess): return beginAccess
137139
case let .yield(value): return value
138140
case let .owned(value): return value
139-
case let .borrowed(value): return value
141+
case let .borrowed(beginBorrow): return beginBorrow.value
140142
case let .initialized(initialAddress, _): return initialAddress
141143
case let .unknown(value): return value
142144
}
@@ -152,8 +154,8 @@ struct LifetimeDependence : CustomStringConvertible {
152154
precondition(value.definingInstruction is BeginApplyInst)
153155
case let .owned(value):
154156
precondition(value.ownership == .owned)
155-
case let .borrowed(value):
156-
precondition(value.ownership == .guaranteed)
157+
case let .borrowed(beginBorrow):
158+
precondition(beginBorrow.value.ownership == .guaranteed)
157159
case let .initialized(initialAddress, initializingStore):
158160
precondition(initialAddress.type.isAddress, "expected an address")
159161
precondition(initialAddress is AllocStackInst
@@ -236,8 +238,7 @@ extension LifetimeDependence {
236238
/// For any LifetimeDependence constructed from a mark_dependence, its `dependentValue` will be the result of the
237239
/// mark_dependence.
238240
///
239-
/// TODO: Add SIL verification that all mark_depedence [unresolved]
240-
/// have a valid LifetimeDependence.
241+
/// Returns 'nil' for dependence on a trivial value.
241242
init?(_ markDep: MarkDependenceInst, _ context: some Context) {
242243
switch markDep.dependenceKind {
243244
case .Unresolved, .NonEscaping:
@@ -286,16 +287,15 @@ private extension Value {
286287
}
287288

288289
extension LifetimeDependence.Scope {
289-
/// Construct a lifetime dependence scope from the base value that
290-
/// other values depend on. This derives the kind of dependence
291-
/// scope and its parentValue from `base`.
290+
/// Construct a lifetime dependence scope from the base value that other values depend on. This derives the kind of
291+
/// dependence scope and its parentValue from `base`.
292292
///
293-
/// `base` represents the OSSA lifetime that the dependent value
294-
/// must be used within. If `base` is owned, then it directly
295-
/// defines the parent lifetime. If `base` is guaranteed, then it
296-
/// must have a single borrow introducer, which defines the parent
297-
/// lifetime. `base` must not be derived from a guaranteed phi or
298-
/// forwarded (via struct/tuple) from multiple guaranteed values.
293+
/// `base` represents the OSSA lifetime that the dependent value must be used within. If `base` is owned, then it
294+
/// directly defines the parent lifetime. If `base` is guaranteed, then it must have a single borrow introducer, which
295+
/// defines the parent lifetime. `base` must not be derived from a guaranteed phi or forwarded (via struct/tuple) from
296+
/// multiple guaranteed values.
297+
///
298+
/// Returns 'nil' for dependence on a trivial value.
299299
init?(base: Value, _ context: some Context) {
300300
if base.type.isAddress {
301301
guard let scope = Self(address: base, context) else {
@@ -321,6 +321,7 @@ extension LifetimeDependence.Scope {
321321
}
322322
}
323323

324+
/// Returns 'nil' for dependence on a trivial value.
324325
private init?(address: Value, _ context: some Context) {
325326
switch address.enclosingAccessScope {
326327
case let .scope(access):
@@ -333,6 +334,7 @@ extension LifetimeDependence.Scope {
333334
}
334335
}
335336

337+
/// Returns 'nil' for dependence on a trivial value.
336338
init?(accessBase: AccessBase, address: Value, _ context: some Context) {
337339
switch accessBase {
338340
case let .box(projectBox):
@@ -342,10 +344,7 @@ extension LifetimeDependence.Scope {
342344
}
343345
self = scope
344346
case let .stack(allocStack):
345-
guard let scope = Self(allocation: allocStack, context) else {
346-
return nil
347-
}
348-
self = scope
347+
self = Self(allocation: allocStack, context)
349348
case .global:
350349
self = .unknown(address)
351350
case .class, .tail:
@@ -378,6 +377,7 @@ extension LifetimeDependence.Scope {
378377
}
379378
}
380379

380+
/// Returns 'nil' for dependence on a trivial value.
381381
private init?(guaranteed base: Value, _ context: some Context) {
382382
// If introducers is empty, then the dependence is on a trivial value, so
383383
// there is no dependence scope.
@@ -390,7 +390,7 @@ extension LifetimeDependence.Scope {
390390
"guaranteed phis not allowed when diagnosing lifetime dependence")
391391
switch beginBorrow {
392392
case .beginBorrow, .loadBorrow:
393-
self = .borrowed(beginBorrow.value)
393+
self = .borrowed(beginBorrow)
394394
case let .beginApply(value):
395395
self = .yield(value)
396396
case let .functionArgument(arg):
@@ -410,12 +410,33 @@ extension LifetimeDependence.Scope {
410410
self = .yield(result)
411411
}
412412

413-
private init?(allocation: AllocStackInst, _ context: Context) {
413+
private init(allocation: AllocStackInst, _ context: Context) {
414414
if let initializer = allocation.accessBase.findSingleInitializer(context) {
415415
self = .initialized(initialAddress: initializer.initialAddress,
416416
initializingStore: initializer.initializingStore)
417+
return
418+
}
419+
self = .unknown(allocation)
420+
}
421+
}
422+
423+
extension LifetimeDependence.Scope {
424+
/// Ignore "irrelevent" borrow scopes: load_borrow or begin_borrow without [var_decl]
425+
func ignoreBorrowScope(_ context: some Context) -> LifetimeDependence.Scope? {
426+
guard case let .borrowed(beginBorrowVal) = self else {
427+
return self
428+
}
429+
switch beginBorrowVal {
430+
case let .beginBorrow(bb):
431+
if bb.isFromVarDecl {
432+
return self
433+
}
434+
return LifetimeDependence.Scope(base: bb.borrowedValue, context)?.ignoreBorrowScope(context)
435+
case let .loadBorrow(lb):
436+
return LifetimeDependence.Scope(base: lb.address, context)
437+
default:
438+
fatalError("Scope.borrowed must begin begin_borrow or load_borrow")
417439
}
418-
return nil
419440
}
420441
}
421442

@@ -448,8 +469,8 @@ extension LifetimeDependence.Scope {
448469
// how would we ensure that the borrowed mark_dependence value
449470
// is within this value's OSSA lifetime?
450471
return computeLinearLiveness(for: value, context)
451-
case let .borrowed(value):
452-
return computeLinearLiveness(for: value, context)
472+
case let .borrowed(beginBorrow):
473+
return computeLinearLiveness(for: beginBorrow.value, context)
453474
case let .initialized(initialAddress, initializingStore):
454475
return LifetimeDependence.Scope.computeInitializedRange(
455476
initialAddress: initialAddress, initializingStore: initializingStore,

0 commit comments

Comments
 (0)