Skip to content

Commit f0b0400

Browse files
committed
LifetimeDepenenceUtils; improve VariableIntroducerUseDefWalker
Stop at formal access to a mutable variable.
1 parent bc0f60a commit f0b0400

File tree

1 file changed

+54
-17
lines changed

1 file changed

+54
-17
lines changed

SwiftCompilerSources/Sources/Optimizer/Utilities/LifetimeDependenceUtils.swift

Lines changed: 54 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -485,8 +485,7 @@ extension LifetimeDependence {
485485
-> WalkResult {
486486
var useDefVisitor = UseDefVisitor(context, visitor)
487487
defer { useDefVisitor.deinitialize() }
488-
let owner = value.ownership == .owned ? value : nil
489-
return useDefVisitor.walkUp(value: value, owner)
488+
return useDefVisitor.walkUp(valueOrAddress: value)
490489
}
491490

492491
private struct UseDefVisitor : LifetimeDependenceUseDefWalker {
@@ -534,6 +533,18 @@ extension LifetimeDependence {
534533
}
535534
}
536535

536+
/// Walk up the lifetime dependence
537+
///
538+
/// This uses LifetimeDependenceUseDefWalker to find the introducers
539+
/// of a dependence chain, which represent the value's "inherited"
540+
/// dependencies. This stops at an address, unless the address refers
541+
/// to a singly-initialized temprorary, in which case it continues to
542+
/// walk up the stored value.
543+
///
544+
/// This overrides LifetimeDependenceUseDefWalker to stop at a value
545+
/// that introduces an immutable variable: move_value [var_decl] or
546+
/// begin_borrow [var_decl], and to stop at an access of a mutable
547+
/// variable: begin_access.
537548
struct VariableIntroducerUseDefWalker : LifetimeDependenceUseDefWalker {
538549
let context: Context
539550
// This visited set is only really needed for instructions with
@@ -576,24 +587,36 @@ struct VariableIntroducerUseDefWalker : LifetimeDependenceUseDefWalker {
576587
}
577588
return walkUpDefault(dependent: value, owner: owner)
578589
}
590+
591+
mutating func walkUp(address: Value) -> WalkResult {
592+
if let beginAccess = address.definingInstruction as? BeginAccessInst {
593+
return introducer(beginAccess, nil)
594+
}
595+
return walkUpDefault(address: address)
596+
}
579597
}
580598

581-
/// Walk up dominating dependent values.
599+
/// Walk up the lifetime dependence chain.
600+
///
601+
/// This finds the introducers of a dependence chain. which represent
602+
/// the value's "inherited" dependencies. This stops at phis; all
603+
/// introducers dominate. This stops at addresses in general, but if
604+
/// the value is loaded from a singly-initialized location, then it
605+
/// continues walking up the value stored by the initializer. This
606+
/// bypasses the copies to temporary memory locations emitted by SILGen.
582607
///
583-
/// Find the roots of a dependence chain stopping at phis. These root
584-
/// LifeDependence instances are the value's "inherited"
585-
/// dependencies. In this example, the dependence root is copied,
586-
/// borrowed, and forwarded before being used as the base operand of
587-
/// `mark_dependence`. The dependence "root" is the parent of the
588-
/// outer-most dependence scope.
608+
/// In this example, the dependence root is
609+
/// copied, borrowed, and forwarded before being used as the base
610+
/// operand of `mark_dependence`. The dependence "root" is the parent
611+
/// of the outer-most dependence scope.
589612
///
590613
/// %root = apply // lifetime dependence root
591614
/// %copy = copy_value %root
592615
/// %parent = begin_borrow %copy // lifetime dependence parent value
593616
/// %base = struct_extract %parent // lifetime dependence base value
594617
/// %dependent = mark_dependence [nonescaping] %value on %base
595618
///
596-
/// This extends the ForwardingDefUseWalker, which finds the
619+
/// This extends the ForwardingUseDefWalker, which finds the
597620
/// forward-extended lifetime introducers. Certain forward-extended
598621
/// lifetime introducers can inherit a lifetime dependency from their
599622
/// operand: namely copies, moves, and borrows. These introducers are
@@ -631,7 +654,7 @@ struct VariableIntroducerUseDefWalker : LifetimeDependenceUseDefWalker {
631654
/// needWalk(for value: Value) -> Bool
632655
///
633656
/// Start walking:
634-
/// walkUp(value: Value) -> WalkResult
657+
/// walkUp(valueOrAddress: Value) -> WalkResult
635658
protocol LifetimeDependenceUseDefWalker : ForwardingUseDefWalker where PathContext == Value? {
636659
var context: Context { get }
637660

@@ -642,14 +665,28 @@ protocol LifetimeDependenceUseDefWalker : ForwardingUseDefWalker where PathConte
642665
mutating func needWalk(for value: Value, _ owner: Value?) -> Bool
643666

644667
mutating func walkUp(value: Value, _ owner: Value?) -> WalkResult
668+
669+
mutating func walkUp(address: Value) -> WalkResult
645670
}
646671

647672
// Implement ForwardingUseDefWalker
648673
extension LifetimeDependenceUseDefWalker {
674+
mutating func walkUp(valueOrAddress: Value) -> WalkResult {
675+
if valueOrAddress.type.isAddress {
676+
return walkUp(address: valueOrAddress)
677+
}
678+
let owner = valueOrAddress.ownership == .owned ? valueOrAddress : nil
679+
return walkUp(value: valueOrAddress, owner)
680+
}
681+
649682
mutating func walkUp(value: Value, _ owner: Value?) -> WalkResult {
650683
walkUpDefault(dependent: value, owner: owner)
651684
}
652685

686+
mutating func walkUp(address: Value) -> WalkResult {
687+
walkUpDefault(address: address)
688+
}
689+
653690
// Extend ForwardingUseDefWalker to handle copies, moves, and
654691
// borrows. Also transitively walk up other lifetime dependencies to
655692
// find the roots.
@@ -691,17 +728,12 @@ extension LifetimeDependenceUseDefWalker {
691728
return walkUpDefault(forwarded: value, owner)
692729
}
693730

694-
private mutating func walkUp(newLifetime: Value) -> WalkResult {
695-
let newOwner = newLifetime.ownership == .owned ? newLifetime : nil
696-
return walkUp(value: newLifetime, newOwner)
697-
}
698-
699731
// Walk up from a load of a singly-initialized address to find the
700732
// dependence root of the stored value. This ignores mutable
701733
// variables, which require an access scope. This ignores applies
702734
// because an lifetime dependence will already be expressed as a
703735
// mark_dependence.
704-
private mutating func walkUp(address: Value) -> WalkResult {
736+
mutating func walkUpDefault(address: Value) -> WalkResult {
705737
if let (_, initializingStore) =
706738
address.accessBase.findSingleInitializer(context) {
707739
switch initializingStore {
@@ -715,6 +747,11 @@ extension LifetimeDependenceUseDefWalker {
715747
}
716748
return introducer(address, nil)
717749
}
750+
751+
private mutating func walkUp(newLifetime: Value) -> WalkResult {
752+
let newOwner = newLifetime.ownership == .owned ? newLifetime : nil
753+
return walkUp(value: newLifetime, newOwner)
754+
}
718755
}
719756

720757
/// Walk down dependent values.

0 commit comments

Comments
 (0)