1; RUN: opt < %s -tbaa -basicaa -aa-eval -evaluate-aa-metadata -print-no-aliases -print-may-aliases -disable-output 2>&1 | FileCheck %s
2; RUN: opt < %s -tbaa -basicaa -gvn -S | FileCheck %s --check-prefix=OPT
3; Generated from clang/test/CodeGen/tbaa.cpp with "-O1 -new-struct-path-tbaa".
4
5%struct.StructA = type { i16, i32, i16, i32 }
6%struct.StructB = type { i16, %struct.StructA, i32 }
7%struct.StructS = type { i16, i32 }
8%struct.StructS2 = type { i16, i32 }
9%struct.StructC = type { i16, %struct.StructB, i32 }
10%struct.StructD = type { i16, %struct.StructB, i32, i8 }
11
12; uint32_t g(uint32_t *s, StructA *A, uint64_t count) {
13;   *s = 1;
14;   A->f32 = 4;
15;   return *s;
16; }
17;
18define i32 @_Z1gPjP7StructAy(i32* nocapture %s, %struct.StructA* nocapture %A, i64 %count) {
19entry:
20; CHECK-LABEL: Z1gPjP7StructAy
21; CHECK: MayAlias: store i32 4, {{.*}} <-> store i32 1,
22; OPT-LABEL: _Z1gPjP7StructAy
23; OPT: store i32 1,
24; OPT: store i32 4,
25; OPT: %[[RET:.*]] = load i32,
26; OPT: ret i32 %[[RET]]
27  store i32 1, i32* %s, align 4, !tbaa !2
28  %f32 = getelementptr inbounds %struct.StructA, %struct.StructA* %A, i64 0, i32 1
29  store i32 4, i32* %f32, align 4, !tbaa !6
30  %0 = load i32, i32* %s, align 4, !tbaa !2
31  ret i32 %0
32}
33
34; uint32_t g2(uint32_t *s, StructA *A, uint64_t count) {
35;   *s = 1;
36;   A->f16 = 4;
37;   return *s;
38; }
39;
40define i32 @_Z2g2PjP7StructAy(i32* nocapture %s, %struct.StructA* nocapture %A, i64 %count) {
41entry:
42; CHECK-LABEL: _Z2g2PjP7StructAy
43; CHECK: NoAlias: store i16 4, {{.*}} <-> store i32 1,
44; OPT-LABEL: _Z2g2PjP7StructAy
45; OPT: store i32 1,
46; OPT: store i16 4,
47; Remove a load and propagate the value from store.
48; OPT: ret i32 1
49  store i32 1, i32* %s, align 4, !tbaa !2
50  %f16 = getelementptr inbounds %struct.StructA, %struct.StructA* %A, i64 0, i32 0
51  store i16 4, i16* %f16, align 4, !tbaa !9
52  ret i32 1
53}
54
55; uint32_t g3(StructA *A, StructB *B, uint64_t count) {
56;   A->f32 = 1;
57;   B->a.f32 = 4;
58;   return A->f32;
59; }
60;
61define i32 @_Z2g3P7StructAP7StructBy(%struct.StructA* nocapture %A, %struct.StructB* nocapture %B, i64 %count) {
62entry:
63; CHECK-LABEL: _Z2g3P7StructAP7StructBy
64; CHECK: MayAlias: store i32 4, {{.*}} <-> store i32 1,
65; OPT-LABEL: _Z2g3P7StructAP7StructBy
66; OPT: store i32 1
67; OPT: store i32 4
68; OPT: %[[RET:.*]] = load i32,
69; OPT: ret i32 %[[RET]]
70  %f32 = getelementptr inbounds %struct.StructA, %struct.StructA* %A, i64 0, i32 1
71  store i32 1, i32* %f32, align 4, !tbaa !6
72  %f321 = getelementptr inbounds %struct.StructB, %struct.StructB* %B, i64 0, i32 1, i32 1
73  store i32 4, i32* %f321, align 4, !tbaa !10
74  %0 = load i32, i32* %f32, align 4, !tbaa !6
75  ret i32 %0
76}
77
78; uint32_t g4(StructA *A, StructB *B, uint64_t count) {
79;   A->f32 = 1;
80;   B->a.f16 = 4;
81;   return A->f32;
82; }
83;
84define i32 @_Z2g4P7StructAP7StructBy(%struct.StructA* nocapture %A, %struct.StructB* nocapture %B, i64 %count) {
85entry:
86; CHECK-LABEL: _Z2g4P7StructAP7StructBy
87; CHECK: NoAlias: store i16 4, {{.*}} <-> store i32 1,
88; OPT-LABEL: _Z2g4P7StructAP7StructBy
89; OPT: store i32 1,
90; OPT: store i16 4,
91; Remove a load and propagate the value from store.
92; OPT: ret i32 1
93  %f32 = getelementptr inbounds %struct.StructA, %struct.StructA* %A, i64 0, i32 1
94  store i32 1, i32* %f32, align 4, !tbaa !6
95  %f16 = getelementptr inbounds %struct.StructB, %struct.StructB* %B, i64 0, i32 1, i32 0
96  store i16 4, i16* %f16, align 4, !tbaa !12
97  ret i32 1
98}
99
100; uint32_t g5(StructA *A, StructB *B, uint64_t count) {
101;   A->f32 = 1;
102;   B->f32 = 4;
103;   return A->f32;
104; }
105;
106define i32 @_Z2g5P7StructAP7StructBy(%struct.StructA* nocapture %A, %struct.StructB* nocapture %B, i64 %count) {
107entry:
108; CHECK-LABEL: _Z2g5P7StructAP7StructBy
109; CHECK: NoAlias: store i32 4, {{.*}} <-> store i32 1,
110; OPT-LABEL: _Z2g5P7StructAP7StructBy
111; OPT: store i32 1,
112; OPT: store i32 4,
113; Remove a load and propagate the value from store.
114; OPT: ret i32 1
115  %f32 = getelementptr inbounds %struct.StructA, %struct.StructA* %A, i64 0, i32 1
116  store i32 1, i32* %f32, align 4, !tbaa !6
117  %f321 = getelementptr inbounds %struct.StructB, %struct.StructB* %B, i64 0, i32 2
118  store i32 4, i32* %f321, align 4, !tbaa !13
119  ret i32 1
120}
121
122; uint32_t g6(StructA *A, StructB *B, uint64_t count) {
123;   A->f32 = 1;
124;   B->a.f32_2 = 4;
125;   return A->f32;
126; }
127;
128define i32 @_Z2g6P7StructAP7StructBy(%struct.StructA* nocapture %A, %struct.StructB* nocapture %B, i64 %count) {
129entry:
130; CHECK-LABEL: _Z2g6P7StructAP7StructBy
131; CHECK: NoAlias: store i32 4, {{.*}} <-> store i32 1,
132; OPT-LABEL: _Z2g6P7StructAP7StructBy
133; OPT: store i32 1,
134; OPT: store i32 4,
135; Remove a load and propagate the value from store.
136; OPT: ret i32 1
137  %f32 = getelementptr inbounds %struct.StructA, %struct.StructA* %A, i64 0, i32 1
138  store i32 1, i32* %f32, align 4, !tbaa !6
139  %f32_2 = getelementptr inbounds %struct.StructB, %struct.StructB* %B, i64 0, i32 1, i32 3
140  store i32 4, i32* %f32_2, align 4, !tbaa !14
141  ret i32 1
142}
143
144; uint32_t g7(StructA *A, StructS *S, uint64_t count) {
145;   A->f32 = 1;
146;   S->f32 = 4;
147;   return A->f32;
148; }
149;
150define i32 @_Z2g7P7StructAP7StructSy(%struct.StructA* nocapture %A, %struct.StructS* nocapture %S, i64 %count) {
151entry:
152; CHECK-LABEL: _Z2g7P7StructAP7StructSy
153; CHECK: NoAlias: store i32 4, {{.*}} <-> store i32 1,
154; OPT-LABEL: _Z2g7P7StructAP7StructSy
155; OPT: store i32 1,
156; OPT: store i32 4,
157; Remove a load and propagate the value from store.
158; OPT: ret i32 1
159  %f32 = getelementptr inbounds %struct.StructA, %struct.StructA* %A, i64 0, i32 1
160  store i32 1, i32* %f32, align 4, !tbaa !6
161  %f321 = getelementptr inbounds %struct.StructS, %struct.StructS* %S, i64 0, i32 1
162  store i32 4, i32* %f321, align 4, !tbaa !15
163  ret i32 1
164}
165
166; uint32_t g8(StructA *A, StructS *S, uint64_t count) {
167;   A->f32 = 1;
168;   S->f16 = 4;
169;   return A->f32;
170; }
171;
172define i32 @_Z2g8P7StructAP7StructSy(%struct.StructA* nocapture %A, %struct.StructS* nocapture %S, i64 %count) {
173entry:
174; CHECK-LABEL: _Z2g8P7StructAP7StructSy
175; CHECK: NoAlias: store i16 4, {{.*}} <-> store i32 1,
176; OPT-LABEL: _Z2g8P7StructAP7StructSy
177; OPT: store i32 1,
178; OPT: store i16 4,
179; Remove a load and propagate the value from store.
180; OPT: ret i32 1
181  %f32 = getelementptr inbounds %struct.StructA, %struct.StructA* %A, i64 0, i32 1
182  store i32 1, i32* %f32, align 4, !tbaa !6
183  %f16 = getelementptr inbounds %struct.StructS, %struct.StructS* %S, i64 0, i32 0
184  store i16 4, i16* %f16, align 4, !tbaa !17
185  ret i32 1
186}
187
188; uint32_t g9(StructS *S, StructS2 *S2, uint64_t count) {
189;   S->f32 = 1;
190;   S2->f32 = 4;
191;   return S->f32;
192; }
193;
194define i32 @_Z2g9P7StructSP8StructS2y(%struct.StructS* nocapture %S, %struct.StructS2* nocapture %S2, i64 %count) {
195entry:
196; CHECK-LABEL: _Z2g9P7StructSP8StructS2y
197; CHECK: NoAlias: store i32 4, {{.*}} <-> store i32 1,
198; OPT-LABEL: _Z2g9P7StructSP8StructS2y
199; OPT: store i32 1,
200; OPT: store i32 4,
201; Remove a load and propagate the value from store.
202; OPT: ret i32 1
203  %f32 = getelementptr inbounds %struct.StructS, %struct.StructS* %S, i64 0, i32 1
204  store i32 1, i32* %f32, align 4, !tbaa !15
205  %f321 = getelementptr inbounds %struct.StructS2, %struct.StructS2* %S2, i64 0, i32 1
206  store i32 4, i32* %f321, align 4, !tbaa !18
207  ret i32 1
208}
209
210; uint32_t g10(StructS *S, StructS2 *S2, uint64_t count) {
211;   S->f32 = 1;
212;   S2->f16 = 4;
213;   return S->f32;
214; }
215;
216define i32 @_Z3g10P7StructSP8StructS2y(%struct.StructS* nocapture %S, %struct.StructS2* nocapture %S2, i64 %count) {
217entry:
218; CHECK-LABEL: _Z3g10P7StructSP8StructS2y
219; CHECK: NoAlias: store i16 4, {{.*}} <-> store i32 1,
220; OPT-LABEL: _Z3g10P7StructSP8StructS2y
221; OPT: store i32 1,
222; OPT: store i16 4,
223; Remove a load and propagate the value from store.
224; OPT: ret i32 1
225  %f32 = getelementptr inbounds %struct.StructS, %struct.StructS* %S, i64 0, i32 1
226  store i32 1, i32* %f32, align 4, !tbaa !15
227  %f16 = getelementptr inbounds %struct.StructS2, %struct.StructS2* %S2, i64 0, i32 0
228  store i16 4, i16* %f16, align 4, !tbaa !20
229  ret i32 1
230}
231
232; uint32_t g11(StructC *C, StructD *D, uint64_t count) {
233;   C->b.a.f32 = 1;
234;   D->b.a.f32 = 4;
235;   return C->b.a.f32;
236; }
237;
238define i32 @_Z3g11P7StructCP7StructDy(%struct.StructC* nocapture %C, %struct.StructD* nocapture %D, i64 %count) {
239entry:
240; CHECK-LABEL: _Z3g11P7StructCP7StructDy
241; CHECK: NoAlias: store i32 4, {{.*}} <-> store i32 1,
242; OPT-LABEL: _Z3g11P7StructCP7StructDy
243; OPT: store i32 1,
244; OPT: store i32 4,
245; Remove a load and propagate the value from store.
246; OPT: ret i32 1
247  %f32 = getelementptr inbounds %struct.StructC, %struct.StructC* %C, i64 0, i32 1, i32 1, i32 1
248  store i32 1, i32* %f32, align 4, !tbaa !21
249  %f323 = getelementptr inbounds %struct.StructD, %struct.StructD* %D, i64 0, i32 1, i32 1, i32 1
250  store i32 4, i32* %f323, align 4, !tbaa !23
251  ret i32 1
252}
253
254; uint32_t g12(StructC *C, StructD *D, uint64_t count) {
255;   StructB *b1 = &(C->b);
256;   StructB *b2 = &(D->b);
257;   // b1, b2 have different context.
258;   b1->a.f32 = 1;
259;   b2->a.f32 = 4;
260;   return b1->a.f32;
261; }
262;
263define i32 @_Z3g12P7StructCP7StructDy(%struct.StructC* nocapture %C, %struct.StructD* nocapture %D, i64 %count) {
264entry:
265; CHECK-LABEL: _Z3g12P7StructCP7StructDy
266; CHECK: MayAlias: store i32 4, {{.*}} <-> store i32 1,
267; OPT-LABEL: _Z3g12P7StructCP7StructDy
268; OPT: store i32 1,
269; OPT: store i32 4,
270; OPT: %[[RET:.*]] = load i32,
271; OPT: ret i32 %[[RET]]
272  %f32 = getelementptr inbounds %struct.StructC, %struct.StructC* %C, i64 0, i32 1, i32 1, i32 1
273  store i32 1, i32* %f32, align 4, !tbaa !10
274  %f325 = getelementptr inbounds %struct.StructD, %struct.StructD* %D, i64 0, i32 1, i32 1, i32 1
275  store i32 4, i32* %f325, align 4, !tbaa !10
276  %0 = load i32, i32* %f32, align 4, !tbaa !10
277  ret i32 %0
278}
279
280!2 = !{!3, !3, i64 0, i64 4}
281!3 = !{!4, i64 4, !"int"}
282!4 = !{!5, i64 1, !"omnipotent char"}
283!5 = !{!"Simple C++ TBAA"}
284!6 = !{!7, !3, i64 4, i64 4}
285!7 = !{!4, i64 16, !"_ZTS7StructA", !8, i64 0, i64 2, !3, i64 4, i64 4, !8, i64 8, i64 2, !3, i64 12, i64 4}
286!8 = !{!4, i64 2, !"short"}
287!9 = !{!7, !8, i64 0, i64 2}
288!10 = !{!11, !3, i64 8, i64 4}
289!11 = !{!4, i64 24, !"_ZTS7StructB", !8, i64 0, i64 2, !7, i64 4, i64 16, !3, i64 20, i64 4}
290!12 = !{!11, !8, i64 4, i64 2}
291!13 = !{!11, !3, i64 20, i64 4}
292!14 = !{!11, !3, i64 16, i64 4}
293!15 = !{!16, !3, i64 4, i64 4}
294!16 = !{!4, i64 8, !"_ZTS7StructS", !8, i64 0, i64 2, !3, i64 4, i64 4}
295!17 = !{!16, !8, i64 0, i64 2}
296!18 = !{!19, !3, i64 4, i64 4}
297!19 = !{!4, i64 8, !"_ZTS8StructS2", !8, i64 0, i64 2, !3, i64 4, i64 4}
298!20 = !{!19, !8, i64 0, i64 2}
299!21 = !{!22, !3, i64 12, i64 4}
300!22 = !{!4, i64 32, !"_ZTS7StructC", !8, i64 0, i64 2, !11, i64 4, i64 24, !3, i64 28, i64 4}
301!23 = !{!24, !3, i64 12, i64 4}
302!24 = !{!4, i64 36, !"_ZTS7StructD", !8, i64 0, i64 2, !11, i64 4, i64 24, !3, i64 28, i64 4, !4, i64 32, i64 1}
303!25 = !{!26, !4, i64 1, i64 1}
304!26 = !{!4, i64 3, !"_ZTS4five", !4, i64 0, i64 1, !3, i64 1, i64 4, !4, i64 1, i64 1, !4, i64 2, i64 1}
305!27 = !{!28, !4, i64 4, i64 1}
306!28 = !{!4, i64 6, !"_ZTS3six", !4, i64 0, i64 1, !3, i64 4, i64 4, !4, i64 4, i64 1, !4, i64 5, i64 1}
307