@@ -55,7 +55,7 @@ func gatherVariableIntroducers(for value: Value, _ context: Context) -> [Value]
55
55
return . continueWalk
56
56
}
57
57
defer { useDefVisitor. deinitialize ( ) }
58
- _ = useDefVisitor. walkUp ( value: value)
58
+ _ = useDefVisitor. walkUp ( value: value, nil )
59
59
return introducers
60
60
}
61
61
@@ -431,7 +431,8 @@ extension LifetimeDependence {
431
431
-> WalkResult {
432
432
var useDefVisitor = UseDefVisitor ( context, visitor)
433
433
defer { useDefVisitor. deinitialize ( ) }
434
- return useDefVisitor. walkUp ( value: value)
434
+ let owner = value. ownership == . owned ? value : nil
435
+ return useDefVisitor. walkUp ( value: value, owner)
435
436
}
436
437
437
438
private struct UseDefVisitor : LifetimeDependenceUseDefWalker {
@@ -453,7 +454,10 @@ extension LifetimeDependence {
453
454
visitedValues. deinitialize ( )
454
455
}
455
456
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.
457
461
visitedValues. insert ( value)
458
462
}
459
463
@@ -464,8 +468,12 @@ extension LifetimeDependence {
464
468
// of an access scope. An address type mark_dependence
465
469
// [nonescaping]` can only result from an indirect function result
466
470
// 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)
469
477
else {
470
478
return . continueWalk
471
479
}
@@ -494,28 +502,28 @@ struct VariableIntroducerUseDefWalker : LifetimeDependenceUseDefWalker {
494
502
visitedValues. deinitialize ( )
495
503
}
496
504
497
- mutating func needWalk( for value: Value ) -> Bool {
505
+ mutating func needWalk( for value: Value , _ owner : Value ? ) -> Bool {
498
506
visitedValues. insert ( value)
499
507
}
500
508
501
- mutating func introducer( _ value: Value ) -> WalkResult {
509
+ mutating func introducer( _ value: Value , _ owner : Value ? ) -> WalkResult {
502
510
return visitorClosure ( value)
503
511
}
504
512
505
- mutating func walkUp( value: Value ) -> WalkResult {
513
+ mutating func walkUp( value: Value , _ owner : Value ? ) -> WalkResult {
506
514
switch value. definingInstruction {
507
515
case let moveInst as MoveValueInst :
508
516
if moveInst. isFromVarDecl {
509
- return introducer ( moveInst)
517
+ return introducer ( moveInst, owner )
510
518
}
511
519
case let borrow as BeginBorrowInst :
512
520
if borrow. isFromVarDecl {
513
- return introducer ( borrow)
521
+ return introducer ( borrow, owner )
514
522
}
515
523
default :
516
524
break
517
525
}
518
- return walkUpDefault ( dependent: value)
526
+ return walkUpDefault ( dependent: value, owner : owner )
519
527
}
520
528
}
521
529
@@ -573,20 +581,22 @@ struct VariableIntroducerUseDefWalker : LifetimeDependenceUseDefWalker {
573
581
///
574
582
/// Start walking:
575
583
/// walkUp(value: Value) -> WalkResult
576
- protocol LifetimeDependenceUseDefWalker : ForwardingUseDefWalker {
584
+ protocol LifetimeDependenceUseDefWalker : ForwardingUseDefWalker where PathContext == Value ? {
577
585
var context : Context { get }
578
586
579
- mutating func introducer( _ value: Value ) -> WalkResult
587
+ mutating func introducer( _ value: Value , _ owner : Value ? ) -> WalkResult
580
588
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
583
592
584
- mutating func walkUp( value: Value ) -> WalkResult
593
+ mutating func walkUp( value: Value , _ owner : Value ? ) -> WalkResult
585
594
}
586
595
596
+ // Implement ForwardingUseDefWalker
587
597
extension 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 )
590
600
}
591
601
592
602
// Extend ForwardingUseDefWalker to handle copies, moves, and
@@ -599,29 +609,40 @@ extension LifetimeDependenceUseDefWalker {
599
609
//
600
610
// Handles loads as a convenience so the client receives the load's
601
611
// address as an introducer.
602
- mutating func walkUpDefault( dependent value: Value ) -> WalkResult {
612
+ mutating func walkUpDefault( dependent value: Value , owner: Value ? )
613
+ -> WalkResult {
603
614
switch value. definingInstruction {
604
615
case let copyInst as CopyValueInst :
605
- return walkUp ( value : copyInst. fromValue)
616
+ return walkUp ( newLifetime : copyInst. fromValue)
606
617
case let moveInst as MoveValueInst :
607
- return walkUp ( value: moveInst. fromValue)
618
+ return walkUp ( value: moveInst. fromValue, owner )
608
619
case let borrow as BeginBorrowInst :
609
- return walkUp ( value : borrow. borrowedValue)
620
+ return walkUp ( newLifetime : borrow. borrowedValue)
610
621
case let load as LoadInstruction :
611
- return walkUp ( value : load. address)
622
+ return introducer ( load. address, owner )
612
623
case let markDep as MarkDependenceInst :
613
624
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
+ }
615
631
}
616
632
default :
617
633
break
618
634
}
619
635
// If the dependence chain has a phi, consider it a root. Dependence roots
620
636
// are currently expected to dominate all dependent values.
621
637
if Phi ( value) != nil {
622
- return introducer ( value)
638
+ return introducer ( value, owner )
623
639
}
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)
625
646
}
626
647
}
627
648
0 commit comments