Skip to content

Commit b0f2ca0

Browse files
committed
AccessUtils: allow mark_deps to be tracked by the EnclosingScope.
This encourages AccessPathWalker clients to handle enclosing mark_deps. In some cases, it is necessary. The accessBaseWithScopes API now provides both nested begin_access and mark_dependence.
1 parent eb07814 commit b0f2ca0

File tree

4 files changed

+63
-25
lines changed

4 files changed

+63
-25
lines changed

SwiftCompilerSources/Sources/Optimizer/Analysis/AliasAnalysis.swift

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -603,7 +603,7 @@ private enum ImmutableScope {
603603

604604
init?(for basedAddress: Value, _ context: FunctionPassContext) {
605605
switch basedAddress.enclosingAccessScope {
606-
case .scope(let beginAccess):
606+
case .access(let beginAccess):
607607
if beginAccess.isUnsafe {
608608
return nil
609609
}
@@ -652,6 +652,9 @@ private enum ImmutableScope {
652652
return nil
653653
}
654654
}
655+
case .dependence(let markDep):
656+
// ignore mark_dependence for the purpose of alias analysis.
657+
self.init(for: markDep.value, context)
655658
}
656659
}
657660

SwiftCompilerSources/Sources/Optimizer/FunctionPasses/LifetimeDependenceScopeFixup.swift

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -274,7 +274,8 @@ private extension LifetimeDependence.Scope {
274274
case let .access(beginAccess):
275275
// Finding the access base also finds all intermediate nested scopes; there is no need to recursively call
276276
// gatherExtensions().
277-
let (accessBase, nestedAccesses) = beginAccess.accessBaseWithScopes
277+
let accessBaseAndScopes = beginAccess.accessBaseWithScopes
278+
let accessBase = accessBaseAndScopes.base
278279
let ownerAddress: Value
279280
var dependsOnArg: FunctionArgument? = nil
280281
switch accessBase {
@@ -287,13 +288,18 @@ private extension LifetimeDependence.Scope {
287288
.pointer, .index:
288289
ownerAddress = accessBase.address!
289290
}
290-
assert(!nestedAccesses.isEmpty)
291-
for nestedAccess in nestedAccesses {
292-
innerScopes.push(.access(nestedAccess))
291+
assert(!accessBaseAndScopes.scopes.isEmpty)
292+
for nestedScope in accessBaseAndScopes.scopes {
293+
switch nestedScope {
294+
case let .access(beginAccess):
295+
innerScopes.push(.access(beginAccess))
296+
case .dependence, .base:
297+
// ignore recursive mark_dependence base for the purpose of extending scopes. This pass will extend the base
298+
// of that mark_dependence (if it is unresolved) later as a separate LifetimeDependence.Scope.
299+
break
300+
}
293301
}
294-
// This is the outermost scope. We only see nested access scopes after inlining.
295-
//
296-
// TODO: could we have a nested access within an yielded inout address?
302+
// TODO: could we have a nested access within an yielded inout address prior to inlining?
297303
return SingleInlineArray(element: ScopeExtension(owner: ownerAddress, nestedScopes: innerScopes,
298304
dependsOnArg: dependsOnArg))
299305
case let .borrowed(beginBorrow):

SwiftCompilerSources/Sources/Optimizer/Utilities/LifetimeDependenceUtils.swift

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ struct LifetimeDependence : CustomStringConvertible {
117117
case yield(Value)
118118
/// An owned value whose OSSA lifetime encloses nonescapable values, or a trivial variable introduced by move_value.
119119
case owned(Value)
120-
/// An borrowed value whose OSSA lifetime encloses nonescapable values, or a trivial variable introduced by
120+
/// A borrowed value whose OSSA lifetime encloses nonescapable values, or a trivial variable introduced by
121121
/// begin_borrow.
122122
case borrowed(BeginBorrowValue)
123123
/// Singly-initialized addressable storage (likely for an
@@ -313,10 +313,15 @@ extension LifetimeDependence.Scope {
313313

314314
private init(address: Value, _ context: some Context) {
315315
switch address.enclosingAccessScope {
316-
case let .scope(access):
316+
case let .access(access):
317317
self = .access(access)
318318
case let .base(accessBase):
319319
self = Self(accessBase: accessBase, address: address, context)
320+
case let .dependence(markDep):
321+
// The current dependence only represents the forwarded address. If the mark_dependence instruction encoutered
322+
// here is [unresolved], then a separate LifetimeDependence.Scope will be created for it, and if it is [escaping],
323+
// then it is ignored for the purpose of lifetime dependence.
324+
self.init(address: markDep.value, context)
320325
}
321326
}
322327

@@ -1151,7 +1156,7 @@ extension LifetimeDependenceDefUseWalker {
11511156

11521157
// Get the local variable access that encloses this store.
11531158
var storeAccess = storedOperand.instruction
1154-
if case let .scope(beginAccess) = storeAddress.enclosingAccessScope {
1159+
if case let .access(beginAccess) = storeAddress.enclosingAccessScope {
11551160
storeAccess = beginAccess
11561161
}
11571162
if !localReachability.gatherAllReachableUses(of: storeAccess, in: &accessStack) {

SwiftCompilerSources/Sources/SIL/Utilities/AccessUtils.swift

Lines changed: 38 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -477,7 +477,7 @@ private extension PointerToAddressInst {
477477
}
478478
}
479479

480-
/// The `EnclosingScope` of an access is the innermost `begin_access`
480+
/// The `EnclosingAccessScope` of an access is the innermost `begin_access`
481481
/// instruction that checks for exclusivity of the access.
482482
/// If there is no `begin_access` instruction found, then the scope is
483483
/// the base itself.
@@ -497,13 +497,29 @@ private extension PointerToAddressInst {
497497
/// %l3 = load %a3 : $*Int64
498498
/// end_access %a3 : $*Int64
499499
/// ```
500-
public enum EnclosingScope {
501-
case scope(BeginAccessInst)
500+
public enum EnclosingAccessScope {
501+
case access(BeginAccessInst)
502502
case base(AccessBase)
503+
case dependence(MarkDependenceInst)
504+
}
505+
506+
// An AccessBase with the nested enclosing scopes that contain the original address in bottom-up order.
507+
public struct AccessBaseAndScopes {
508+
public let base: AccessBase
509+
public let scopes: SingleInlineArray<EnclosingAccessScope>
510+
511+
public var innermostAccess: BeginAccessInst? {
512+
for scope in scopes {
513+
if case let .access(beginAccess) = scope {
514+
return beginAccess
515+
}
516+
}
517+
return nil
518+
}
503519
}
504520

505521
private struct EnclosingAccessWalker : AddressUseDefWalker {
506-
var enclosingScope: EnclosingScope?
522+
var enclosingScope: EnclosingAccessScope?
507523

508524
mutating func walk(startAt address: Value, initialPath: UnusedWalkingPath = UnusedWalkingPath()) {
509525
if walkUp(address: address, path: UnusedWalkingPath()) == .abortWalk {
@@ -522,19 +538,24 @@ private struct EnclosingAccessWalker : AddressUseDefWalker {
522538
}
523539

524540
mutating func walkUp(address: Value, path: UnusedWalkingPath) -> WalkResult {
525-
if let ba = address as? BeginAccessInst {
526-
enclosingScope = .scope(ba)
541+
switch address {
542+
case let ba as BeginAccessInst:
543+
enclosingScope = .access(ba)
527544
return .continueWalk
545+
case let md as MarkDependenceInst:
546+
enclosingScope = .dependence(md)
547+
return .continueWalk
548+
default:
549+
return walkUpDefault(address: address, path: path)
528550
}
529-
return walkUpDefault(address: address, path: path)
530551
}
531552
}
532553

533554
private struct AccessPathWalker : AddressUseDefWalker {
534555
var result = AccessPath.unidentified()
535556

536-
// List of nested BeginAccessInst: inside-out order.
537-
var foundBeginAccesses = SingleInlineArray<BeginAccessInst>()
557+
// List of nested BeginAccessInst & MarkDependenceInst: inside-out order.
558+
var foundEnclosingScopes = SingleInlineArray<EnclosingAccessScope>()
538559

539560
let enforceConstantProjectionPath: Bool
540561

@@ -602,7 +623,9 @@ private struct AccessPathWalker : AddressUseDefWalker {
602623
// projection. Bail out
603624
return .abortWalk
604625
} else if let ba = address as? BeginAccessInst {
605-
foundBeginAccesses.push(ba)
626+
foundEnclosingScopes.push(.access(ba))
627+
} else if let md = address as? MarkDependenceInst {
628+
foundEnclosingScopes.push(.dependence(md))
606629
}
607630
return walkUpDefault(address: address, path: path.with(indexAddr: false))
608631
}
@@ -655,20 +678,21 @@ extension Value {
655678
public var accessPathWithScope: (AccessPath, scope: BeginAccessInst?) {
656679
var walker = AccessPathWalker()
657680
walker.walk(startAt: self)
658-
return (walker.result, walker.foundBeginAccesses.first)
681+
let baseAndScopes = AccessBaseAndScopes(base: walker.result.base, scopes: walker.foundEnclosingScopes)
682+
return (walker.result, baseAndScopes.innermostAccess)
659683
}
660684

661685
/// Computes the enclosing access scope of this address value.
662-
public var enclosingAccessScope: EnclosingScope {
686+
public var enclosingAccessScope: EnclosingAccessScope {
663687
var walker = EnclosingAccessWalker()
664688
walker.walk(startAt: self)
665689
return walker.enclosingScope ?? .base(.unidentified)
666690
}
667691

668-
public var accessBaseWithScopes: (AccessBase, SingleInlineArray<BeginAccessInst>) {
692+
public var accessBaseWithScopes: AccessBaseAndScopes {
669693
var walker = AccessPathWalker()
670694
walker.walk(startAt: self)
671-
return (walker.result.base, walker.foundBeginAccesses)
695+
return AccessBaseAndScopes(base: walker.result.base, scopes: walker.foundEnclosingScopes)
672696
}
673697

674698
/// The root definition of a reference, obtained by skipping ownership forwarding and ownership transition.

0 commit comments

Comments
 (0)