@@ -55,7 +55,7 @@ func gatherVariableIntroducers(for value: Value, _ context: Context) -> [Value]
5555 return . continueWalk
5656 }
5757 defer { useDefVisitor. deinitialize ( ) }
58- _ = useDefVisitor. walkUp ( value: value)
58+ _ = useDefVisitor. walkUp ( value: value, nil )
5959 return introducers
6060}
6161
@@ -431,7 +431,8 @@ extension LifetimeDependence {
431431 -> WalkResult {
432432 var useDefVisitor = UseDefVisitor ( context, visitor)
433433 defer { useDefVisitor. deinitialize ( ) }
434- return useDefVisitor. walkUp ( value: value)
434+ let owner = value. ownership == . owned ? value : nil
435+ return useDefVisitor. walkUp ( value: value, owner)
435436 }
436437
437438 private struct UseDefVisitor : LifetimeDependenceUseDefWalker {
@@ -453,7 +454,10 @@ extension LifetimeDependence {
453454 visitedValues. deinitialize ( )
454455 }
455456
456- mutating func needWalk( for value: Value ) -> Bool {
457+ mutating func needWalk( for value: Value , _ owner: Value ? ) -> Bool {
458+ // FIXME: cache the value's owner, and support walking up
459+ // multiple guaranteed forwards to different owners, then
460+ // reconverging.
457461 visitedValues. insert ( value)
458462 }
459463
@@ -464,8 +468,12 @@ extension LifetimeDependence {
464468 // of an access scope. An address type mark_dependence
465469 // [nonescaping]` can only result from an indirect function result
466470 // when opaque values are not enabled.
467- mutating func introducer( _ value: Value ) -> WalkResult {
468- guard let scope = LifetimeDependence . Scope ( base: value, context)
471+ //
472+ // FIXME: Recursively handle .initialized scope by checking
473+ // findSingleStore and walking the stored value.
474+ mutating func introducer( _ value: Value , _ owner: Value ? ) -> WalkResult {
475+ let base = owner ?? value
476+ guard let scope = LifetimeDependence . Scope ( base: base, context)
469477 else {
470478 return . continueWalk
471479 }
@@ -494,28 +502,28 @@ struct VariableIntroducerUseDefWalker : LifetimeDependenceUseDefWalker {
494502 visitedValues. deinitialize ( )
495503 }
496504
497- mutating func needWalk( for value: Value ) -> Bool {
505+ mutating func needWalk( for value: Value , _ owner : Value ? ) -> Bool {
498506 visitedValues. insert ( value)
499507 }
500508
501- mutating func introducer( _ value: Value ) -> WalkResult {
509+ mutating func introducer( _ value: Value , _ owner : Value ? ) -> WalkResult {
502510 return visitorClosure ( value)
503511 }
504512
505- mutating func walkUp( value: Value ) -> WalkResult {
513+ mutating func walkUp( value: Value , _ owner : Value ? ) -> WalkResult {
506514 switch value. definingInstruction {
507515 case let moveInst as MoveValueInst :
508516 if moveInst. isFromVarDecl {
509- return introducer ( moveInst)
517+ return introducer ( moveInst, owner )
510518 }
511519 case let borrow as BeginBorrowInst :
512520 if borrow. isFromVarDecl {
513- return introducer ( borrow)
521+ return introducer ( borrow, owner )
514522 }
515523 default :
516524 break
517525 }
518- return walkUpDefault ( dependent: value)
526+ return walkUpDefault ( dependent: value, owner : owner )
519527 }
520528}
521529
@@ -573,20 +581,22 @@ struct VariableIntroducerUseDefWalker : LifetimeDependenceUseDefWalker {
573581///
574582/// Start walking:
575583/// walkUp(value: Value) -> WalkResult
576- protocol LifetimeDependenceUseDefWalker : ForwardingUseDefWalker {
584+ protocol LifetimeDependenceUseDefWalker : ForwardingUseDefWalker where PathContext == Value ? {
577585 var context : Context { get }
578586
579- mutating func introducer( _ value: Value ) -> WalkResult
587+ mutating func introducer( _ value: Value , _ owner : Value ? ) -> WalkResult
580588
581- // Minimally, check a ValueSet. This walker may traverse chains of aggregation and destructuring along with phis.
582- mutating func needWalk( for value: Value ) -> Bool
589+ // Minimally, check a ValueSet. This walker may traverse chains of
590+ // aggregation and destructuring along with phis.
591+ mutating func needWalk( for value: Value , _ owner: Value ? ) -> Bool
583592
584- mutating func walkUp( value: Value ) -> WalkResult
593+ mutating func walkUp( value: Value , _ owner : Value ? ) -> WalkResult
585594}
586595
596+ // Implement ForwardingUseDefWalker
587597extension LifetimeDependenceUseDefWalker {
588- mutating func walkUp( value: Value ) -> WalkResult {
589- walkUpDefault ( dependent: value)
598+ mutating func walkUp( value: Value , _ owner : Value ? ) -> WalkResult {
599+ walkUpDefault ( dependent: value, owner : owner )
590600 }
591601
592602 // Extend ForwardingUseDefWalker to handle copies, moves, and
@@ -599,29 +609,40 @@ extension LifetimeDependenceUseDefWalker {
599609 //
600610 // Handles loads as a convenience so the client receives the load's
601611 // address as an introducer.
602- mutating func walkUpDefault( dependent value: Value ) -> WalkResult {
612+ mutating func walkUpDefault( dependent value: Value , owner: Value ? )
613+ -> WalkResult {
603614 switch value. definingInstruction {
604615 case let copyInst as CopyValueInst :
605- return walkUp ( value : copyInst. fromValue)
616+ return walkUp ( newLifetime : copyInst. fromValue)
606617 case let moveInst as MoveValueInst :
607- return walkUp ( value: moveInst. fromValue)
618+ return walkUp ( value: moveInst. fromValue, owner )
608619 case let borrow as BeginBorrowInst :
609- return walkUp ( value : borrow. borrowedValue)
620+ return walkUp ( newLifetime : borrow. borrowedValue)
610621 case let load as LoadInstruction :
611- return walkUp ( value : load. address)
622+ return introducer ( load. address, owner )
612623 case let markDep as MarkDependenceInst :
613624 if let dependence = LifetimeDependence ( markDep, context) {
614- return walkUp ( value: dependence. parentValue)
625+ let parent = dependence. parentValue
626+ if markDep. isForwarded ( from: parent) {
627+ return walkUp ( value: dependence. parentValue, owner)
628+ } else {
629+ return walkUp ( newLifetime: dependence. parentValue)
630+ }
615631 }
616632 default :
617633 break
618634 }
619635 // If the dependence chain has a phi, consider it a root. Dependence roots
620636 // are currently expected to dominate all dependent values.
621637 if Phi ( value) != nil {
622- return introducer ( value)
638+ return introducer ( value, owner )
623639 }
624- return walkUpDefault ( forwarded: value)
640+ return walkUpDefault ( forwarded: value, owner)
641+ }
642+
643+ private mutating func walkUp( newLifetime: Value ) -> WalkResult {
644+ let newOwner = newLifetime. ownership == . owned ? newLifetime : nil
645+ return walkUp ( value: newLifetime, newOwner)
625646 }
626647}
627648
0 commit comments