@@ -233,6 +233,9 @@ extension LifetimeDependence {
233233
234234 /// Construct LifetimeDependence from mark_dependence [unresolved]
235235 ///
236+ /// For any LifetimeDependence constructed from a mark_dependence,
237+ /// its `dependentValue` will be the result of the mark_dependence.
238+ ///
236239 /// TODO: Add SIL verification that all mark_depedence [unresolved]
237240 /// have a valid LifetimeDependence.
238241 init ? ( _ markDep: MarkDependenceInst , _ context: some Context ) {
@@ -485,8 +488,7 @@ extension LifetimeDependence {
485488 -> WalkResult {
486489 var useDefVisitor = UseDefVisitor ( context, visitor)
487490 defer { useDefVisitor. deinitialize ( ) }
488- let owner = value. ownership == . owned ? value : nil
489- return useDefVisitor. walkUp ( value: value, owner)
491+ return useDefVisitor. walkUp ( valueOrAddress: value)
490492 }
491493
492494 private struct UseDefVisitor : LifetimeDependenceUseDefWalker {
@@ -534,6 +536,18 @@ extension LifetimeDependence {
534536 }
535537}
536538
539+ /// Walk up the lifetime dependence
540+ ///
541+ /// This uses LifetimeDependenceUseDefWalker to find the introducers
542+ /// of a dependence chain, which represent the value's "inherited"
543+ /// dependencies. This stops at an address, unless the address refers
544+ /// to a singly-initialized temprorary, in which case it continues to
545+ /// walk up the stored value.
546+ ///
547+ /// This overrides LifetimeDependenceUseDefWalker to stop at a value
548+ /// that introduces an immutable variable: move_value [var_decl] or
549+ /// begin_borrow [var_decl], and to stop at an access of a mutable
550+ /// variable: begin_access.
537551struct VariableIntroducerUseDefWalker : LifetimeDependenceUseDefWalker {
538552 let context : Context
539553 // This visited set is only really needed for instructions with
@@ -576,24 +590,36 @@ struct VariableIntroducerUseDefWalker : LifetimeDependenceUseDefWalker {
576590 }
577591 return walkUpDefault ( dependent: value, owner: owner)
578592 }
593+
594+ mutating func walkUp( address: Value ) -> WalkResult {
595+ if let beginAccess = address. definingInstruction as? BeginAccessInst {
596+ return introducer ( beginAccess, nil )
597+ }
598+ return walkUpDefault ( address: address)
599+ }
579600}
580601
581- /// Walk up dominating dependent values .
602+ /// Walk up the lifetime dependence chain .
582603///
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.
604+ /// This finds the introducers of a dependence chain. which represent
605+ /// the value's "inherited" dependencies. This stops at phis; all
606+ /// introducers dominate. This stops at addresses in general, but if
607+ /// the value is loaded from a singly-initialized location, then it
608+ /// continues walking up the value stored by the initializer. This
609+ /// bypasses the copies to temporary memory locations emitted by SILGen.
610+ ///
611+ /// In this example, the dependence root is
612+ /// copied, borrowed, and forwarded before being used as the base
613+ /// operand of `mark_dependence`. The dependence "root" is the parent
614+ /// of the outer-most dependence scope.
589615///
590616/// %root = apply // lifetime dependence root
591617/// %copy = copy_value %root
592618/// %parent = begin_borrow %copy // lifetime dependence parent value
593619/// %base = struct_extract %parent // lifetime dependence base value
594620/// %dependent = mark_dependence [nonescaping] %value on %base
595621///
596- /// This extends the ForwardingDefUseWalker , which finds the
622+ /// This extends the ForwardingUseDefWalker , which finds the
597623/// forward-extended lifetime introducers. Certain forward-extended
598624/// lifetime introducers can inherit a lifetime dependency from their
599625/// operand: namely copies, moves, and borrows. These introducers are
@@ -631,7 +657,7 @@ struct VariableIntroducerUseDefWalker : LifetimeDependenceUseDefWalker {
631657/// needWalk(for value: Value) -> Bool
632658///
633659/// Start walking:
634- /// walkUp(value : Value) -> WalkResult
660+ /// walkUp(valueOrAddress : Value) -> WalkResult
635661protocol LifetimeDependenceUseDefWalker : ForwardingUseDefWalker where PathContext == Value ? {
636662 var context : Context { get }
637663
@@ -642,14 +668,28 @@ protocol LifetimeDependenceUseDefWalker : ForwardingUseDefWalker where PathConte
642668 mutating func needWalk( for value: Value , _ owner: Value ? ) -> Bool
643669
644670 mutating func walkUp( value: Value , _ owner: Value ? ) -> WalkResult
671+
672+ mutating func walkUp( address: Value ) -> WalkResult
645673}
646674
647675// Implement ForwardingUseDefWalker
648676extension LifetimeDependenceUseDefWalker {
677+ mutating func walkUp( valueOrAddress: Value ) -> WalkResult {
678+ if valueOrAddress. type. isAddress {
679+ return walkUp ( address: valueOrAddress)
680+ }
681+ let owner = valueOrAddress. ownership == . owned ? valueOrAddress : nil
682+ return walkUp ( value: valueOrAddress, owner)
683+ }
684+
649685 mutating func walkUp( value: Value , _ owner: Value ? ) -> WalkResult {
650686 walkUpDefault ( dependent: value, owner: owner)
651687 }
652688
689+ mutating func walkUp( address: Value ) -> WalkResult {
690+ walkUpDefault ( address: address)
691+ }
692+
653693 // Extend ForwardingUseDefWalker to handle copies, moves, and
654694 // borrows. Also transitively walk up other lifetime dependencies to
655695 // find the roots.
@@ -691,17 +731,12 @@ extension LifetimeDependenceUseDefWalker {
691731 return walkUpDefault ( forwarded: value, owner)
692732 }
693733
694- private mutating func walkUp( newLifetime: Value ) -> WalkResult {
695- let newOwner = newLifetime. ownership == . owned ? newLifetime : nil
696- return walkUp ( value: newLifetime, newOwner)
697- }
698-
699734 // Walk up from a load of a singly-initialized address to find the
700735 // dependence root of the stored value. This ignores mutable
701736 // variables, which require an access scope. This ignores applies
702737 // because an lifetime dependence will already be expressed as a
703738 // mark_dependence.
704- private mutating func walkUp ( address: Value ) -> WalkResult {
739+ mutating func walkUpDefault ( address: Value ) -> WalkResult {
705740 if let ( _, initializingStore) =
706741 address. accessBase. findSingleInitializer ( context) {
707742 switch initializingStore {
@@ -715,6 +750,11 @@ extension LifetimeDependenceUseDefWalker {
715750 }
716751 return introducer ( address, nil )
717752 }
753+
754+ private mutating func walkUp( newLifetime: Value ) -> WalkResult {
755+ let newOwner = newLifetime. ownership == . owned ? newLifetime : nil
756+ return walkUp ( value: newLifetime, newOwner)
757+ }
718758}
719759
720760/// Walk down dependent values.
0 commit comments