@@ -706,3 +706,163 @@ bb0(%0 : $*T, %1 : $*T):
706
706
%10 = tuple ()
707
707
return %10 : $()
708
708
}
709
+
710
+ // Test reference root casts.
711
+ class A {
712
+ var prop0: Int64
713
+ }
714
+ class B : A {
715
+ var alsoProp0: Int64
716
+ }
717
+
718
+ // CHECK-LABEL: @testReferenceRootCast
719
+ // CHECK: ###For MemOp: store %0 to [[ADR0:%.*]] : $*Int64
720
+ // CHECK: Class %{{.*}} = alloc_ref $B
721
+ // CHECK: Field: var prop0: Int64 Index: 0
722
+ // CHECK: Base: [[ADR0]] = ref_element_addr %{{.*}} : $A, #A.prop0
723
+ // CHECK: Storage: Class %1 = alloc_ref $B
724
+ // CHECK: Field: var prop0: Int64 Index: 0
725
+ // CHECK: Path: ()
726
+ // CHECK: Exact Uses {
727
+ // CHECK-NEXT: store %0 to [[ADR0]] : $*Int64
728
+ // CHECK-NEXT: Path: ()
729
+ // CHECK-NEXT: }
730
+ // CHECK: Overlapping Uses {
731
+ // CHECK-NEXT: store %0 to [[ADR0]] : $*Int64
732
+ // CHECK-NEXT: Path: ()
733
+ // CHECK-NEXT: }
734
+ // CHECK: ###For MemOp: store %0 to [[ADR1:%.*]] : $*Int64
735
+ // CHECK-NEXT: Class %{{.*}} = alloc_ref $B
736
+ // CHECK-NEXT: Field: var alsoProp0: Int64 Index: 1
737
+ // CHECK-NEXT: Base: [[ADR1]] = ref_element_addr %10 : $B, #B.alsoProp0
738
+ // CHECK-NEXT: Storage: Class %{{.*}} = alloc_ref $B
739
+ // CHECK-NEXT: Field: var alsoProp0: Int64 Index: 1
740
+ // CHECK-NEXT: Path: ()
741
+ // CHECK-NEXT: Exact Uses {
742
+ // CHECK-NEXT: store %0 to [[ADR1]] : $*Int64
743
+ // CHECK-NEXT: Path: ()
744
+ // CHECK-NEXT: }
745
+ // CHECK: Overlapping Uses {
746
+ // CHECK-NEXT: store %0 to [[ADR1]] : $*Int64
747
+ // CHECK-NEXT: Path: ()
748
+ // CHECK-NEXT: }
749
+ sil @testReferenceRootCast : $@convention(thin) (Int64) -> () {
750
+ bb0(%0 : $Int64):
751
+ %1 = alloc_ref $B
752
+ cond_br undef, bb1, bb2
753
+
754
+ bb1:
755
+ %3 = upcast %1 : $B to $A
756
+ br bb3(%3 : $A)
757
+
758
+ bb2:
759
+ %5 = upcast %1 : $B to $A
760
+ br bb3(%5 : $A)
761
+
762
+ bb3(%7 : $A):
763
+ %8 = ref_element_addr %7 : $A, #A.prop0
764
+ store %0 to %8 : $*Int64
765
+ %10 = unchecked_ref_cast %7 : $A to $B
766
+ %11 = ref_element_addr %10 : $B, #B.alsoProp0
767
+ store %0 to %11 : $*Int64
768
+ %99 = tuple ()
769
+ return %99 : $()
770
+ }
771
+
772
+ // Test a phi cycle where the phi itself is the root (there is no common phi reference).
773
+ // CHECK-LABEL: @testRootPhiCycle
774
+ // CHECK: ###For MemOp: %{{.*}} = load %{{.*}} : $*Double
775
+ // CHECK: Storage: Tail %{{.*}} = argument of bb3 : $Builtin.BridgeObject
776
+ // CHECK: Path: ()
777
+ // CHECK: Exact Uses {
778
+ // CHECK-NEXT: %{{.*}} = load %{{.*}} : $*Double
779
+ // CHECK-NEXT: Path: ()
780
+ // CHECK-NEXT: %{{.*}} = load %{{.*}} : $*Double
781
+ // CHECK-NEXT: Path: ()
782
+ // CHECK-NEXT: }
783
+ // CHECK: ###For MemOp: %{{.*}} = load %{{.*}} : $*Double
784
+ // CHECK: Storage: Tail %{{.*}} = argument of bb3 : $Builtin.BridgeObject
785
+ // CHECK: Path: ()
786
+ // CHECK: Exact Uses {
787
+ // CHECK-NEXT: %{{.*}} = load %{{.*}} : $*Double
788
+ // CHECK-NEXT: Path: ()
789
+ // CHECK-NEXT: %{{.*}} = load %{{.*}} : $*Double
790
+ // CHECK-NEXT: Path: ()
791
+ // CHECK-NEXT: }
792
+ sil @testRootPhiCycle : $@convention(thin) (Builtin.BridgeObject, Builtin.BridgeObject) -> () {
793
+ bb0(%0 : $Builtin.BridgeObject, %1 : $Builtin.BridgeObject):
794
+ cond_br undef, bb1, bb2
795
+
796
+ bb1:
797
+ br bb3(%0 : $Builtin.BridgeObject)
798
+
799
+ bb2:
800
+ br bb3(%1 : $Builtin.BridgeObject)
801
+
802
+ bb3(%820 : $Builtin.BridgeObject):
803
+ %834 = unchecked_ref_cast %820 : $Builtin.BridgeObject to $C
804
+ %844 = ref_tail_addr [immutable] %834 : $C, $Double
805
+ %853 = load %844 : $*Double
806
+ %943 = load %844 : $*Double
807
+ cond_br undef, bb4, bb5
808
+
809
+ bb4:
810
+ br bb3(%820 : $Builtin.BridgeObject)
811
+
812
+ bb5:
813
+ %999 = tuple ()
814
+ return %999 : $()
815
+ }
816
+
817
+ class C {}
818
+
819
+ // Test a CoW mutation followed by a phi cycle.
820
+ //
821
+ // Note: FindReferenceRoot currently does not see past CoW mutation,
822
+ // but probably should.
823
+ // CHECK: @testCowMutationPhi
824
+ // CHECK: ###For MemOp: (%{{.*}}, %{{.*}}) = begin_cow_mutation [native] %0 : $Builtin.BridgeObject
825
+ // CHECK-NEXT: ###For MemOp: %{{.*}} = load %{{.*}} : $*Double
826
+ // CHECK: Storage: Tail %{{.*}} = argument of bb3 : $Builtin.BridgeObject
827
+ // CHECK: Path: ()
828
+ // CHECK: Exact Uses {
829
+ // CHECK-NEXT: %{{.*}} = load %{{.*}} : $*Double
830
+ // CHECK-NEXT: Path: ()
831
+ // CHECK-NEXT: %{{.*}} = load %{{.*}} : $*Double
832
+ // CHECK-NEXT: Path: ()
833
+ // CHECK-NEXT: }
834
+ // CHECK: ###For MemOp: %{{.*}} = load %{{.*}} : $*Double
835
+ // CHECK: Storage: Tail %{{.*}} = argument of bb3 : $Builtin.BridgeObject
836
+ // CHECK: Path: ()
837
+ // CHECK: Exact Uses {
838
+ // CHECK-NEXT: %{{.*}} = load %{{.*}} : $*Double
839
+ // CHECK-NEXT: Path: ()
840
+ // CHECK-NEXT: %{{.*}} = load %{{.*}} : $*Double
841
+ // CHECK-NEXT: Path: ()
842
+ // CHECK-NEXT: }
843
+ sil @testCowMutationPhi : $@convention(thin) (Builtin.BridgeObject) -> () {
844
+ bb0(%0 : $Builtin.BridgeObject):
845
+ cond_br undef, bb1, bb2
846
+
847
+ bb1:
848
+ br bb3(%0 : $Builtin.BridgeObject)
849
+
850
+ bb2:
851
+ (%3, %4) = begin_cow_mutation [native] %0 : $Builtin.BridgeObject
852
+ %5 = end_cow_mutation [keep_unique] %4 : $Builtin.BridgeObject
853
+ br bb3(%5 : $Builtin.BridgeObject)
854
+
855
+ bb3(%820 : $Builtin.BridgeObject):
856
+ %834 = unchecked_ref_cast %820 : $Builtin.BridgeObject to $C
857
+ %844 = ref_tail_addr [immutable] %834 : $C, $Double
858
+ %853 = load %844 : $*Double
859
+ %943 = load %844 : $*Double
860
+ cond_br undef, bb4, bb5
861
+
862
+ bb4:
863
+ br bb3(%820 : $Builtin.BridgeObject)
864
+
865
+ bb5:
866
+ %999 = tuple ()
867
+ return %999 : $()
868
+ }
0 commit comments