xref: /llvm-project/llvm/test/Analysis/TypeBasedAliasAnalysis/aggregates.ll (revision 222d3b031f6bf39873550a34152b9d05b9b6578a)
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, i32 }  ; struct A { int i, j; };
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(ptr %i, ptr %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, ptr %i, align 4, !tbaa !3  ; TAG_int
25  store i32 7, ptr %a, align 4, !tbaa !5  ; TAG_A_i
26  %0 = load i32, ptr %i, align 4, !tbaa !3  ; TAG_int
27  ret i32 %0
28}
29
30; int vs. B::a  =>  MayAlias.
31define i32 @f2(ptr %i, ptr %b) {
32entry:
33; CHECK-LABEL: f2
34; CHECK: MayAlias: store i32 7, {{.*}} <-> store i32 5,
35; OPT-LABEL: f2
36; OPT: store i32 5,
37; OPT: store i32 7,
38; OPT: %[[RET:.*]] = load i32,
39; OPT: ret i32 %[[RET]]
40  store i32 5, ptr %i, align 4, !tbaa !3  ; TAG_int
41  store i32 7, ptr %b, align 4, !tbaa !7  ; TAG_B_a
42  %0 = load i32, ptr %i, align 4, !tbaa !3  ; TAG_int
43  ret i32 %0
44}
45
46; int vs. C::b  =>  MayAlias.
47define i32 @f3(ptr %i, ptr %c) {
48entry:
49; CHECK-LABEL: f3
50; CHECK: MayAlias: store i32 7, {{.*}} <-> store i32 5,
51; OPT-LABEL: f3
52; OPT: store i32 5,
53; OPT: store i32 7,
54; OPT: %[[RET:.*]] = load i32,
55; OPT: ret i32 %[[RET]]
56  store i32 5, ptr %i, align 4, !tbaa !3  ; TAG_int
57  store i32 7, ptr %c, align 4, !tbaa !9  ; TAG_C_b
58  %0 = load i32, ptr %i, align 4, !tbaa !3  ; TAG_int
59  ret i32 %0
60}
61
62; A vs. C::b  =>  MayAlias.
63define i32 @f4(ptr %a, ptr %c) {
64entry:
65; CHECK-LABEL: f4
66; CHECK: MayAlias: store i32 7, {{.*}} <-> store i32 5,
67; OPT-LABEL: f4
68; OPT: store i32 5,
69; OPT: store i32 7,
70; OPT: %[[RET:.*]] = load i32,
71; OPT: ret i32 %[[RET]]
72  store i32 5, ptr %a, align 4, !tbaa !10   ; TAG_A
73  store i32 7, ptr %c, align 4, !tbaa !9   ; TAG_C_b
74  %0 = load i32, ptr %a, align 4, !tbaa !10  ; TAG_A
75  ret i32 %0
76}
77
78; short vs. C::b  =>  NoAlias.
79define i32 @f5(ptr %i, ptr %c) {
80entry:
81; CHECK-LABEL: f5
82; CHECK: NoAlias: store i32 7, {{.*}} <-> store i32 5,
83; OPT-LABEL: f5
84; OPT: store i32 5,
85; OPT: store i32 7,
86; OPT: ret i32 5
87  store i32 5, ptr %i, align 4, !tbaa !12  ; TAG_short
88  store i32 7, ptr %c, align 4, !tbaa !9  ; TAG_C_b
89  %0 = load i32, ptr %i, align 4, !tbaa !12  ; TAG_short
90  ret i32 %0
91}
92
93; C vs. D  =>  NoAlias.
94define i32 @f6(ptr %c, ptr %d) {
95entry:
96; CHECK-LABEL: f6
97; CHECK: NoAlias: store i16 7, {{.*}} <-> store i32 5,
98; OPT-LABEL: f6
99; OPT: store i32 5,
100; OPT: store i16 7,
101; OPT: ret i32 5
102  store i32 5, ptr %c, align 4, !tbaa !13  ; TAG_C
103  store i16 7, ptr %d, align 4, !tbaa !15  ; TAG_D
104  %0 = load i32, ptr %c, align 4, !tbaa !13  ; TAG_C
105  ret i32 %0
106}
107
108; A vs. A::j  =>  MayAlias.
109; This differs from A vs. A::i case in that the offsets of the final
110; accessed objects in A do not match.
111define i32 @f7(ptr %i, ptr %a) {
112entry:
113; CHECK-LABEL: f7
114; CHECK: MayAlias: store i32 7, {{.*}} <-> store i32 5,
115; OPT-LABEL: f7
116; OPT: store i32 5,
117; OPT: store i32 7,
118; OPT: %[[RET:.*]] = load i32,
119; OPT: ret i32 %[[RET]]
120  store i32 5, ptr %i, align 4, !tbaa !10  ; TAG_A
121  store i32 7, ptr %a, align 4, !tbaa !16  ; TAG_A_j
122  %0 = load i32, ptr %i, align 4, !tbaa !10  ; TAG_A
123  ret i32 %0
124}
125
126!0 = !{!"root"}
127!1 = !{!0, i64 1, !"char"}
128!2 = !{!1, i64 4, !"int"}
129!3 = !{!2, !2, i64 0, i64 4}  ; TAG_int
130
131!4 = !{!1, i64 4, !"A", !2, i64 0, i64 4, !2, i64 4, i64 4}
132!5 = !{!4, !2, i64 0, i64 4}  ; TAG_A_i
133!16 = !{!4, !2, i64 4, i64 4}  ; TAG_A_j
134
135!6 = !{!1, i64 4, !"B", !4, i64 0, i64 4}
136!7 = !{!6, !4, i64 0, i64 4}  ; TAG_B_a
137
138!8 = !{!1, i64 4, !"C", !6, i64 0, i64 4}
139!9 = !{!8, !6, i64 0, i64 4}  ; TAG_C_b
140
141!10 = !{!4, !4, i64 0, i64 4}  ; TAG_A
142
143!11 = !{!1, i64 2, !"short"}
144!12 = !{!11, !11, i64 0, i64 2}  ; TAG_short
145
146!13 = !{!8, !8, i64 0, i64 4}  ; TAG_C
147
148!14 = !{!4, i64 2, !"D", !11, i64 0, i64 2}
149!15 = !{!14, !14, i64 0, i64 2}  ; TAG_D
150