1 ; RUN: opt < %s -tbaa -basicaa -aa-eval -evaluate-aa-metadata \
2 ; RUN: -print-no-aliases -print-may-aliases -disable-output 2>&1 | \
4 ; RUN: opt < %s -tbaa -basicaa -gvn -S | FileCheck %s --check-prefix=OPT
6 ; Check that TBAA handles access tags with aggregate final access types
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; };
14 ; int vs. A::i => MayAlias.
15 define i32 @f1(i32* %i, %A* %a) {
18 ; CHECK: MayAlias: store i32 7, {{.*}} <-> store i32 5,
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
31 ; int vs. B::a => MayAlias.
32 define i32 @f2(i32* %i, %B* %b) {
35 ; CHECK: MayAlias: store i32 7, {{.*}} <-> store i32 5,
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
48 ; int vs. C::b => MayAlias.
49 define i32 @f3(i32* %i, %C* %c) {
52 ; CHECK: MayAlias: store i32 7, {{.*}} <-> store i32 5,
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
65 ; A vs. C::b => MayAlias.
66 define i32 @f4(%A* %a, %C* %c) {
69 ; CHECK: MayAlias: store i32 7, {{.*}} <-> store i32 5,
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
83 ; short vs. C::b => NoAlias.
84 define i32 @f5(i32* %i, %C* %c) {
87 ; CHECK: NoAlias: store i32 7, {{.*}} <-> store 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
100 define i32 @f6(%C* %c, %D* %d) {
103 ; CHECK: NoAlias: store i16 7, {{.*}} <-> store 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
117 !1 = !{!0, i64 1, !"char"}
118 !2 = !{!1, i64 4, !"int"}
119 !3 = !{!2, !2, i64 0, i64 4} ; TAG_int
121 !4 = !{!1, i64 4, !"A", !2, i64 0, i64 4}
122 !5 = !{!4, !2, i64 0, i64 4} ; TAG_A_i
124 !6 = !{!1, i64 4, !"B", !4, i64 0, i64 4}
125 !7 = !{!6, !4, i64 0, i64 4} ; TAG_B_a
127 !8 = !{!1, i64 4, !"C", !6, i64 0, i64 4}
128 !9 = !{!8, !6, i64 0, i64 4} ; TAG_C_b
130 !10 = !{!4, !4, i64 0, i64 4} ; TAG_A
132 !11 = !{!1, i64 2, !"short"}
133 !12 = !{!11, !11, i64 0, i64 2} ; TAG_short
135 !13 = !{!8, !8, i64 0, i64 4} ; TAG_C
137 !14 = !{!4, i64 2, !"D", !11, i64 0, i64 2}
138 !15 = !{!14, !14, i64 0, i64 2} ; TAG_D