1; RUN: opt < %s -aa-pipeline=tbaa,basic-aa -passes=aa-eval -evaluate-aa-metadata \
2; RUN:     -print-no-aliases -print-may-aliases -disable-output 2>&1 | \
3; RUN:     FileCheck %s
4; RUN: opt < %s -aa-pipeline=tbaa,basic-aa -passes=gvn -S | FileCheck %s --check-prefix=OPT
5;
6; Check that TBAA handles access tags with aggregate final access types
7; correctly.
8
9%A = type { i32 }  ; struct A { int i; };
10%B = type { %A }   ; struct B { A a; };
11%C = type { %B }   ; struct C { B b; };
12%D = type { i16 }  ; struct D { short s; };
13
14; int vs. A::i  =>  MayAlias.
15define i32 @f1(i32* %i, %A* %a) {
16entry:
17; CHECK-LABEL: f1
18; CHECK: MayAlias: store i32 7, {{.*}} <-> store i32 5,
19; OPT-LABEL: f1
20; OPT: store i32 5,
21; OPT: store i32 7,
22; OPT: %[[RET:.*]] = load i32,
23; OPT: ret i32 %[[RET]]
24  store i32 5, i32* %i, align 4, !tbaa !3  ; TAG_int
25  %A_i = getelementptr inbounds %A, %A* %a, i64 0, i32 0
26  store i32 7, i32* %A_i, align 4, !tbaa !5  ; TAG_A_i
27  %0 = load i32, i32* %i, align 4, !tbaa !3  ; TAG_int
28  ret i32 %0
29}
30
31; int vs. B::a  =>  MayAlias.
32define i32 @f2(i32* %i, %B* %b) {
33entry:
34; CHECK-LABEL: f2
35; CHECK: MayAlias: store i32 7, {{.*}} <-> store i32 5,
36; OPT-LABEL: f2
37; OPT: store i32 5,
38; OPT: store i32 7,
39; OPT: %[[RET:.*]] = load i32,
40; OPT: ret i32 %[[RET]]
41  store i32 5, i32* %i, align 4, !tbaa !3  ; TAG_int
42  %B_a = getelementptr inbounds %B, %B* %b, i64 0, i32 0, i32 0
43  store i32 7, i32* %B_a, align 4, !tbaa !7  ; TAG_B_a
44  %0 = load i32, i32* %i, align 4, !tbaa !3  ; TAG_int
45  ret i32 %0
46}
47
48; int vs. C::b  =>  MayAlias.
49define i32 @f3(i32* %i, %C* %c) {
50entry:
51; CHECK-LABEL: f3
52; CHECK: MayAlias: store i32 7, {{.*}} <-> store i32 5,
53; OPT-LABEL: f3
54; OPT: store i32 5,
55; OPT: store i32 7,
56; OPT: %[[RET:.*]] = load i32,
57; OPT: ret i32 %[[RET]]
58  store i32 5, i32* %i, align 4, !tbaa !3  ; TAG_int
59  %C_b = getelementptr inbounds %C, %C* %c, i64 0, i32 0, i32 0, i32 0
60  store i32 7, i32* %C_b, align 4, !tbaa !9  ; TAG_C_b
61  %0 = load i32, i32* %i, align 4, !tbaa !3  ; TAG_int
62  ret i32 %0
63}
64
65; A vs. C::b  =>  MayAlias.
66define i32 @f4(%A* %a, %C* %c) {
67entry:
68; CHECK-LABEL: f4
69; CHECK: MayAlias: store i32 7, {{.*}} <-> store i32 5,
70; OPT-LABEL: f4
71; OPT: store i32 5,
72; OPT: store i32 7,
73; OPT: %[[RET:.*]] = load i32,
74; OPT: ret i32 %[[RET]]
75  %ap = getelementptr inbounds %A, %A* %a, i64 0, i32 0
76  store i32 5, i32* %ap, align 4, !tbaa !10   ; TAG_A
77  %C_b = getelementptr inbounds %C, %C* %c, i64 0, i32 0, i32 0, i32 0
78  store i32 7, i32* %C_b, align 4, !tbaa !9   ; TAG_C_b
79  %0 = load i32, i32* %ap, align 4, !tbaa !10  ; TAG_A
80  ret i32 %0
81}
82
83; short vs. C::b  =>  NoAlias.
84define i32 @f5(i32* %i, %C* %c) {
85entry:
86; CHECK-LABEL: f5
87; CHECK: NoAlias: store i32 7, {{.*}} <-> store i32 5,
88; OPT-LABEL: f5
89; OPT: store i32 5,
90; OPT: store i32 7,
91; OPT: ret i32 5
92  store i32 5, i32* %i, align 4, !tbaa !12  ; TAG_short
93  %C_b = getelementptr inbounds %C, %C* %c, i64 0, i32 0, i32 0, i32 0
94  store i32 7, i32* %C_b, align 4, !tbaa !9  ; TAG_C_b
95  %0 = load i32, i32* %i, align 4, !tbaa !12  ; TAG_short
96  ret i32 %0
97}
98
99; C vs. D  =>  NoAlias.
100define i32 @f6(%C* %c, %D* %d) {
101entry:
102; CHECK-LABEL: f6
103; CHECK: NoAlias: store i16 7, {{.*}} <-> store i32 5,
104; OPT-LABEL: f6
105; OPT: store i32 5,
106; OPT: store i16 7,
107; OPT: ret i32 5
108  %cp = getelementptr inbounds %C, %C* %c, i64 0, i32 0, i32 0, i32 0
109  store i32 5, i32* %cp, align 4, !tbaa !13  ; TAG_C
110  %dp = getelementptr inbounds %D, %D* %d, i64 0, i32 0
111  store i16 7, i16* %dp, align 4, !tbaa !15  ; TAG_D
112  %0 = load i32, i32* %cp, align 4, !tbaa !13  ; TAG_C
113  ret i32 %0
114}
115
116!0 = !{!"root"}
117!1 = !{!0, i64 1, !"char"}
118!2 = !{!1, i64 4, !"int"}
119!3 = !{!2, !2, i64 0, i64 4}  ; TAG_int
120
121!4 = !{!1, i64 4, !"A", !2, i64 0, i64 4}
122!5 = !{!4, !2, i64 0, i64 4}  ; TAG_A_i
123
124!6 = !{!1, i64 4, !"B", !4, i64 0, i64 4}
125!7 = !{!6, !4, i64 0, i64 4}  ; TAG_B_a
126
127!8 = !{!1, i64 4, !"C", !6, i64 0, i64 4}
128!9 = !{!8, !6, i64 0, i64 4}  ; TAG_C_b
129
130!10 = !{!4, !4, i64 0, i64 4}  ; TAG_A
131
132!11 = !{!1, i64 2, !"short"}
133!12 = !{!11, !11, i64 0, i64 2}  ; TAG_short
134
135!13 = !{!8, !8, i64 0, i64 4}  ; TAG_C
136
137!14 = !{!4, i64 2, !"D", !11, i64 0, i64 2}
138!15 = !{!14, !14, i64 0, i64 2}  ; TAG_D
139