@@ -485,8 +485,7 @@ extension LifetimeDependence {
485
485
-> WalkResult {
486
486
var useDefVisitor = UseDefVisitor ( context, visitor)
487
487
defer { useDefVisitor. deinitialize ( ) }
488
- let owner = value. ownership == . owned ? value : nil
489
- return useDefVisitor. walkUp ( value: value, owner)
488
+ return useDefVisitor. walkUp ( valueOrAddress: value)
490
489
}
491
490
492
491
private struct UseDefVisitor : LifetimeDependenceUseDefWalker {
@@ -534,6 +533,18 @@ extension LifetimeDependence {
534
533
}
535
534
}
536
535
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.
537
548
struct VariableIntroducerUseDefWalker : LifetimeDependenceUseDefWalker {
538
549
let context : Context
539
550
// This visited set is only really needed for instructions with
@@ -576,24 +587,36 @@ struct VariableIntroducerUseDefWalker : LifetimeDependenceUseDefWalker {
576
587
}
577
588
return walkUpDefault ( dependent: value, owner: owner)
578
589
}
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
+ }
579
597
}
580
598
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.
582
607
///
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.
589
612
///
590
613
/// %root = apply // lifetime dependence root
591
614
/// %copy = copy_value %root
592
615
/// %parent = begin_borrow %copy // lifetime dependence parent value
593
616
/// %base = struct_extract %parent // lifetime dependence base value
594
617
/// %dependent = mark_dependence [nonescaping] %value on %base
595
618
///
596
- /// This extends the ForwardingDefUseWalker , which finds the
619
+ /// This extends the ForwardingUseDefWalker , which finds the
597
620
/// forward-extended lifetime introducers. Certain forward-extended
598
621
/// lifetime introducers can inherit a lifetime dependency from their
599
622
/// operand: namely copies, moves, and borrows. These introducers are
@@ -631,7 +654,7 @@ struct VariableIntroducerUseDefWalker : LifetimeDependenceUseDefWalker {
631
654
/// needWalk(for value: Value) -> Bool
632
655
///
633
656
/// Start walking:
634
- /// walkUp(value : Value) -> WalkResult
657
+ /// walkUp(valueOrAddress : Value) -> WalkResult
635
658
protocol LifetimeDependenceUseDefWalker : ForwardingUseDefWalker where PathContext == Value ? {
636
659
var context : Context { get }
637
660
@@ -642,14 +665,28 @@ protocol LifetimeDependenceUseDefWalker : ForwardingUseDefWalker where PathConte
642
665
mutating func needWalk( for value: Value , _ owner: Value ? ) -> Bool
643
666
644
667
mutating func walkUp( value: Value , _ owner: Value ? ) -> WalkResult
668
+
669
+ mutating func walkUp( address: Value ) -> WalkResult
645
670
}
646
671
647
672
// Implement ForwardingUseDefWalker
648
673
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
+
649
682
mutating func walkUp( value: Value , _ owner: Value ? ) -> WalkResult {
650
683
walkUpDefault ( dependent: value, owner: owner)
651
684
}
652
685
686
+ mutating func walkUp( address: Value ) -> WalkResult {
687
+ walkUpDefault ( address: address)
688
+ }
689
+
653
690
// Extend ForwardingUseDefWalker to handle copies, moves, and
654
691
// borrows. Also transitively walk up other lifetime dependencies to
655
692
// find the roots.
@@ -691,17 +728,12 @@ extension LifetimeDependenceUseDefWalker {
691
728
return walkUpDefault ( forwarded: value, owner)
692
729
}
693
730
694
- private mutating func walkUp( newLifetime: Value ) -> WalkResult {
695
- let newOwner = newLifetime. ownership == . owned ? newLifetime : nil
696
- return walkUp ( value: newLifetime, newOwner)
697
- }
698
-
699
731
// Walk up from a load of a singly-initialized address to find the
700
732
// dependence root of the stored value. This ignores mutable
701
733
// variables, which require an access scope. This ignores applies
702
734
// because an lifetime dependence will already be expressed as a
703
735
// mark_dependence.
704
- private mutating func walkUp ( address: Value ) -> WalkResult {
736
+ mutating func walkUpDefault ( address: Value ) -> WalkResult {
705
737
if let ( _, initializingStore) =
706
738
address. accessBase. findSingleInitializer ( context) {
707
739
switch initializingStore {
@@ -715,6 +747,11 @@ extension LifetimeDependenceUseDefWalker {
715
747
}
716
748
return introducer ( address, nil )
717
749
}
750
+
751
+ private mutating func walkUp( newLifetime: Value ) -> WalkResult {
752
+ let newOwner = newLifetime. ownership == . owned ? newLifetime : nil
753
+ return walkUp ( value: newLifetime, newOwner)
754
+ }
718
755
}
719
756
720
757
/// Walk down dependent values.
0 commit comments