@@ -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.
537548struct 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
635658protocol 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
648673extension 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