1 ; RUN: opt < %s -aa-pipeline=basic-aa -passes=aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s
3 ; CHECK-LABEL: Function: simple: 5 pointers, 0 call sites
4 ; CHECK: NoAlias: float* %src1, float* %src2
5 ; CHECK: NoAlias: float* %phi, float* %src1
6 ; CHECK: MayAlias: float* %phi, float* %src2
7 ; CHECK: NoAlias: float* %next, float* %src1
8 ; CHECK: MayAlias: float* %next, float* %src2
9 ; CHECK: NoAlias: float* %next, float* %phi
10 ; CHECK: NoAlias: float* %g, float* %src1
11 ; CHECK: NoAlias: float* %g, float* %src2
12 ; CHECK: NoAlias: float* %g, float* %phi
13 ; CHECK: NoAlias: float* %g, float* %next
14 define void @simple(ptr %src1, ptr noalias %src2, i32 %n) nounwind {
21 %phi = phi ptr [ %src2, %entry ], [ %next, %loop ]
22 %idx = phi i32 [ 0, %entry ], [ %idxn, %loop ]
23 %next = getelementptr inbounds float, ptr %phi, i32 1
24 %g = getelementptr inbounds float, ptr %src1, i32 3
25 %l = load float, ptr %phi
27 %a = fadd float %l, 1.0
28 store float %a, ptr %g
29 %idxn = add nsw nuw i32 %idx, 1
30 %cmp5 = icmp eq i32 %idxn, %n
31 br i1 %cmp5, label %end, label %loop
37 ; CHECK-LABEL: Function: notmust: 6 pointers, 0 call sites
38 ; CHECK: MustAlias: i8* %tab, [2 x i32]* %tab
39 ; CHECK: PartialAlias (off -4): i32* %arrayidx, [2 x i32]* %tab
40 ; CHECK: NoAlias: i32* %arrayidx, i8* %tab
41 ; CHECK: MustAlias: i32* %tab, [2 x i32]* %tab
42 ; CHECK: MustAlias: i32* %tab, i8* %tab
43 ; CHECK: NoAlias: i32* %arrayidx, i32* %tab
44 ; CHECK: MayAlias: i32* %incdec.ptr.i, [2 x i32]* %tab
45 ; CHECK: NoAlias: i32* %incdec.ptr.i, i8* %tab
46 ; CHECK: MayAlias: i32* %arrayidx, i32* %incdec.ptr.i
47 ; CHECK: NoAlias: i32* %incdec.ptr.i, i32* %tab
48 ; CHECK: MayAlias: i32* %p.addr.05.i, [2 x i32]* %tab
49 ; CHECK: MayAlias: i32* %p.addr.05.i, i8* %tab
50 ; CHECK: MayAlias: i32* %arrayidx, i32* %p.addr.05.i
51 ; CHECK: MayAlias: i32* %p.addr.05.i, i32* %tab
52 ; CHECK: NoAlias: i32* %incdec.ptr.i, i32* %p.addr.05.i
53 define i32 @notmust() nounwind {
55 %tab = alloca [2 x i32], align 4
56 %ignore1 = load [2 x i32], ptr %tab
57 %ignore2 = load i8, ptr %tab
58 %arrayidx = getelementptr inbounds [2 x i32], ptr %tab, i32 0, i32 1
59 store i32 0, ptr %arrayidx, align 4
60 store i32 0, ptr %tab, align 4
62 %cmp4.i = icmp slt i32 %0, 2
63 br i1 %cmp4.i, label %while.body.i, label %f.exit
65 while.body.i: ; preds = %while.body.i, %entry
66 %1 = phi i32 [ 1, %while.body.i ], [ %0, %entry ]
67 %foo.06.i = phi i32 [ %sub.i, %while.body.i ], [ 2, %entry ]
68 %p.addr.05.i = phi ptr [ %incdec.ptr.i, %while.body.i ], [ %tab, %entry ]
69 %sub.i = sub nsw i32 %foo.06.i, %1
70 %incdec.ptr.i = getelementptr inbounds i32, ptr %p.addr.05.i, i32 1
71 %ignore3 = load i32, ptr %incdec.ptr.i
72 store i32 %sub.i, ptr %p.addr.05.i, align 4
73 %cmp.i = icmp sgt i32 %sub.i, 1
74 br i1 %cmp.i, label %while.body.i, label %f.exit
76 f.exit: ; preds = %entry, %while.body.i
77 %2 = load i32, ptr %tab, align 4
78 %cmp = icmp eq i32 %2, 2
79 %3 = load i32, ptr %arrayidx, align 4
80 %cmp4 = icmp eq i32 %3, 1
81 %or.cond = and i1 %cmp, %cmp4
82 br i1 %or.cond, label %if.end, label %if.then
84 if.then: ; preds = %f.exit
87 if.end: ; preds = %f.exit
91 ; CHECK-LABEL: Function: reverse: 6 pointers, 0 call sites
92 ; CHECK: MustAlias: i8* %tab, [10 x i32]* %tab
93 ; CHECK: MustAlias: i32* %tab, [10 x i32]* %tab
94 ; CHECK: MustAlias: i32* %tab, i8* %tab
95 ; CHECK: PartialAlias (off -36): i32* %arrayidx1, [10 x i32]* %tab
96 ; CHECK: NoAlias: i32* %arrayidx1, i8* %tab
97 ; CHECK: NoAlias: i32* %arrayidx1, i32* %tab
98 ; CHECK: MayAlias: i32* %incdec.ptr.i, [10 x i32]* %tab
99 ; CHECK: MayAlias: i32* %incdec.ptr.i, i8* %tab
100 ; CHECK: MayAlias: i32* %incdec.ptr.i, i32* %tab
101 ; CHECK: MayAlias: i32* %arrayidx1, i32* %incdec.ptr.i
102 ; CHECK: MayAlias: i32* %p.addr.05.i, [10 x i32]* %tab
103 ; CHECK: MayAlias: i32* %p.addr.05.i, i8* %tab
104 ; CHECK: MayAlias: i32* %p.addr.05.i, i32* %tab
105 ; CHECK: MayAlias: i32* %arrayidx1, i32* %p.addr.05.i
106 ; CHECK: NoAlias: i32* %incdec.ptr.i, i32* %p.addr.05.i
107 define i32 @reverse() nounwind {
109 %tab = alloca [10 x i32], align 4
110 %ignore1 = load [10 x i32], ptr %tab
111 %ignore2 = load i8, ptr %tab
112 store i32 0, ptr %tab, align 4
113 %arrayidx1 = getelementptr inbounds [10 x i32], ptr %tab, i32 0, i32 9
114 store i32 0, ptr %arrayidx1, align 4
116 %cmp4.i = icmp slt i32 %0, 2
117 br i1 %cmp4.i, label %while.body.i, label %f.exit
119 while.body.i: ; preds = %while.body.i, %entry
120 %1 = phi i32 [ 1, %while.body.i ], [ %0, %entry ]
121 %foo.06.i = phi i32 [ %sub.i, %while.body.i ], [ 2, %entry ]
122 %p.addr.05.i = phi ptr [ %incdec.ptr.i, %while.body.i ], [ %arrayidx1, %entry ]
123 %sub.i = sub nsw i32 %foo.06.i, %1
124 %incdec.ptr.i = getelementptr inbounds i32, ptr %p.addr.05.i, i32 -1
125 %ignore3 = load i32, ptr %incdec.ptr.i
126 store i32 %sub.i, ptr %p.addr.05.i, align 4
127 %cmp.i = icmp sgt i32 %sub.i, 1
128 br i1 %cmp.i, label %while.body.i, label %f.exit
130 f.exit: ; preds = %entry, %while.body.i
131 %2 = load i32, ptr %arrayidx1, align 4
132 %cmp = icmp eq i32 %2, 2
133 %3 = load i32, ptr %tab, align 4
134 %cmp4 = icmp eq i32 %3, 1
135 %or.cond = and i1 %cmp, %cmp4
136 br i1 %or.cond, label %if.end, label %if.then
138 if.then: ; preds = %f.exit
141 if.end: ; preds = %f.exit
145 ; CHECK-LABEL: Function: negative: 5 pointers, 1 call sites
146 ; CHECK: PartialAlias (off -4): i16* %_tmp1, [3 x i16]* %int_arr.10
147 ; CHECK: MayAlias: [3 x i16]* %int_arr.10, i16* %ls1.9.0
148 ; CHECK: MayAlias: i16* %_tmp1, i16* %ls1.9.0
149 ; CHECK: MayAlias: i16* %_tmp7, [3 x i16]* %int_arr.10
150 ; CHECK: MayAlias: i16* %_tmp1, i16* %_tmp7
151 ; CHECK: NoAlias: i16* %_tmp7, i16* %ls1.9.0
152 ; CHECK: PartialAlias (off -2): i16* %_tmp11, [3 x i16]* %int_arr.10
153 ; CHECK: NoAlias: i16* %_tmp1, i16* %_tmp11
154 ; CHECK: MayAlias: i16* %_tmp11, i16* %ls1.9.0
155 ; CHECK: MayAlias: i16* %_tmp11, i16* %_tmp7
156 ; CHECK: NoModRef: Ptr: [3 x i16]* %int_arr.10 <-> %_tmp16 = call i16 @call(i32 %_tmp13)
157 ; CHECK: NoModRef: Ptr: i16* %_tmp1 <-> %_tmp16 = call i16 @call(i32 %_tmp13)
158 ; CHECK: Both ModRef: Ptr: i16* %ls1.9.0 <-> %_tmp16 = call i16 @call(i32 %_tmp13)
159 ; CHECK: Both ModRef: Ptr: i16* %_tmp7 <-> %_tmp16 = call i16 @call(i32 %_tmp13)
160 ; CHECK: NoModRef: Ptr: i16* %_tmp11 <-> %_tmp16 = call i16 @call(i32 %_tmp13)
161 define i16 @negative(i16 %argc.5.par) {
162 %int_arr.10 = alloca [3 x i16], align 1
163 load [3 x i16], ptr %int_arr.10
164 %_tmp1 = getelementptr inbounds [3 x i16], ptr %int_arr.10, i16 0, i16 2
168 bb1: ; preds = %bb1, %0
169 %i.7.0 = phi i16 [ 2, %0 ], [ %_tmp5, %bb1 ]
170 %ls1.9.0 = phi ptr [ %_tmp1, %0 ], [ %_tmp7, %bb1 ]
171 store i16 %i.7.0, ptr %ls1.9.0, align 1
172 %_tmp5 = add nsw i16 %i.7.0, -1
173 %_tmp7 = getelementptr i16, ptr %ls1.9.0, i16 -1
175 %_tmp9 = icmp sgt i16 %i.7.0, 0
176 br i1 %_tmp9, label %bb1, label %bb3
179 %_tmp11 = getelementptr inbounds [3 x i16], ptr %int_arr.10, i16 0, i16 1
180 %_tmp12 = load i16, ptr %_tmp11, align 1
181 %_tmp13 = sext i16 %_tmp12 to i32
182 %_tmp16 = call i16 @call(i32 %_tmp13)
183 %_tmp18.not = icmp eq i16 %_tmp12, 1
184 br i1 %_tmp18.not, label %bb5, label %bb4
189 bb5: ; preds = %bb3, %bb4
193 ; CHECK-LABEL: Function: dynamic_offset
194 ; CHECK: NoAlias: i8* %a, i8* %p.base
195 ; CHECK: MayAlias: i8* %p, i8* %p.base
196 ; CHECK: NoAlias: i8* %a, i8* %p
197 ; CHECK: MayAlias: i8* %p.base, i8* %p.next
198 ; CHECK: NoAlias: i8* %a, i8* %p.next
199 ; CHECK: MayAlias: i8* %p, i8* %p.next
200 define void @dynamic_offset(i1 %c, ptr noalias %p.base) {
208 %p = phi ptr [ %p.base, %entry ], [ %p.next, %loop ]
209 %offset = call i16 @call(i32 0)
210 %p.next = getelementptr inbounds i8, ptr %p, i16 %offset
213 br i1 %c, label %loop, label %exit
219 ; TODO: Currently yields an asymmetric result.
220 ; CHECK-LABEL: Function: symmetry
221 ; CHECK: MayAlias: i32* %p, i32* %p.base
222 ; CHECK: MayAlias: i32* %p.base, i32* %p.next
223 ; CHECK: NoAlias: i32* %p, i32* %p.next
224 ; CHECK: MayAlias: i32* %p.base, i32* %result
225 ; CHECK: NoAlias: i32* %p, i32* %result
226 ; CHECK: MustAlias: i32* %p.next, i32* %result
227 define ptr @symmetry(ptr %p.base, i1 %c) {
229 load i32, ptr %p.base
233 %p = phi ptr [ %p.base, %entry ], [ %p.next, %loop ]
234 %p.next = getelementptr inbounds i32, ptr %p, i32 1
236 load i32, ptr %p.next
237 br i1 %c, label %loop, label %exit
240 %result = phi ptr [ %p.next, %loop ]
241 load i32, ptr %result
245 ; FIXME: %a and %p.inner do not alias.
246 ; CHECK-LABEL: Function: nested_loop
247 ; CHECK: NoAlias: i8* %a, i8* %p.base
248 ; CHECK: NoAlias: i8* %a, i8* %p.outer
249 ; CHECK: MayAlias: i8* %a, i8* %p.inner
250 ; CHECK: NoAlias: i8* %a, i8* %p.inner.next
251 ; CHECK: NoAlias: i8* %a, i8* %p.outer.next
252 define void @nested_loop(i1 %c, i1 %c2, ptr noalias %p.base) {
260 %p.outer = phi ptr [ %p.base, %entry ], [ %p.outer.next, %outer_loop_latch ]
261 load i8, ptr %p.outer
265 %p.inner = phi ptr [ %p.outer, %outer_loop ], [ %p.inner.next, %inner_loop ]
266 %p.inner.next = getelementptr inbounds i8, ptr %p.inner, i64 1
267 load i8, ptr %p.inner
268 load i8, ptr %p.inner.next
269 br i1 %c, label %inner_loop, label %outer_loop_latch
272 %p.outer.next = getelementptr inbounds i8, ptr %p.inner, i64 10
273 load i8, ptr %p.outer.next
274 br i1 %c2, label %outer_loop, label %exit
280 ; Same as the previous test case, but avoiding phi of phi.
281 ; CHECK-LABEL: Function: nested_loop2
282 ; CHECK: NoAlias: i8* %a, i8* %p.base
283 ; CHECK: NoAlias: i8* %a, i8* %p.outer
284 ; CHECK: NoAlias: i8* %a, i8* %p.outer.next
285 ; CHECK: MayAlias: i8* %a, i8* %p.inner
286 ; CHECK: NoAlias: i8* %a, i8* %p.inner.next
287 ; TODO: (a, p.inner) could be NoAlias
288 define void @nested_loop2(i1 %c, i1 %c2, ptr noalias %p.base) {
296 %p.outer = phi ptr [ %p.base, %entry ], [ %p.outer.next, %outer_loop_latch ]
297 %p.outer.next = getelementptr inbounds i8, ptr %p.outer, i64 10
298 load i8, ptr %p.outer
299 load i8, ptr %p.outer.next
303 %p.inner = phi ptr [ %p.outer.next, %outer_loop ], [ %p.inner.next, %inner_loop ]
304 %p.inner.next = getelementptr inbounds i8, ptr %p.inner, i64 1
305 load i8, ptr %p.inner
306 load i8, ptr %p.inner.next
307 br i1 %c, label %inner_loop, label %outer_loop_latch
310 br i1 %c2, label %outer_loop, label %exit
316 ; CHECK-LABEL: Function: nested_loop3
317 ; CHECK: NoAlias: i8* %a, i8* %p.base
318 ; CHECK: NoAlias: i8* %a, i8* %p.outer
319 ; CHECK: NoAlias: i8* %a, i8* %p.outer.next
320 ; CHECK: NoAlias: i8* %a, i8* %p.inner
321 ; CHECK: NoAlias: i8* %a, i8* %p.inner.next
322 define void @nested_loop3(i1 %c, i1 %c2, ptr noalias %p.base) {
330 %p.outer = phi ptr [ %p.base, %entry ], [ %p.outer.next, %outer_loop_latch ]
331 %p.outer.next = getelementptr inbounds i8, ptr %p.outer, i64 10
332 load i8, ptr %p.outer
333 load i8, ptr %p.outer.next
337 %p.inner = phi ptr [ %p.outer, %outer_loop ], [ %p.inner.next, %inner_loop ]
338 %p.inner.next = getelementptr inbounds i8, ptr %p.inner, i64 1
339 load i8, ptr %p.inner
340 load i8, ptr %p.inner.next
341 br i1 %c, label %inner_loop, label %outer_loop_latch
344 br i1 %c2, label %outer_loop, label %exit
350 ; CHECK-LABEL: Function: sibling_loop
351 ; CHECK: NoAlias: i8* %a, i8* %p.base
352 ; CHECK: NoAlias: i8* %a, i8* %p1
353 ; CHECK: NoAlias: i8* %a, i8* %p1.next
354 ; CHECK: MayAlias: i8* %a, i8* %p2
355 ; CHECK: NoAlias: i8* %a, i8* %p2.next
356 ; TODO: %p2 does not alias %a
357 define void @sibling_loop(i1 %c, i1 %c2, ptr noalias %p.base) {
365 %p1 = phi ptr [ %p.base, %entry ], [ %p1.next, %loop1 ]
366 %p1.next = getelementptr inbounds i8, ptr %p1, i64 10
368 load i8, ptr %p1.next
369 br i1 %c, label %loop1, label %loop2
372 %p2 = phi ptr [ %p1.next, %loop1 ], [ %p2.next, %loop2 ]
373 %p2.next = getelementptr inbounds i8, ptr %p2, i64 1
375 load i8, ptr %p2.next
376 br i1 %c2, label %loop2, label %exit
382 ; CHECK-LABEL: Function: sibling_loop2
383 ; CHECK: NoAlias: i8* %a, i8* %p.base
384 ; CHECK: NoAlias: i8* %a, i8* %p1
385 ; CHECK: NoAlias: i8* %a, i8* %p1.next
386 ; CHECK: NoAlias: i8* %a, i8* %p2
387 ; CHECK: NoAlias: i8* %a, i8* %p2.next
388 define void @sibling_loop2(i1 %c, i1 %c2, ptr noalias %p.base) {
396 %p1 = phi ptr [ %p.base, %entry ], [ %p1.next, %loop1 ]
397 %p1.next = getelementptr inbounds i8, ptr %p1, i64 10
399 load i8, ptr %p1.next
400 br i1 %c, label %loop1, label %loop2
403 %p2 = phi ptr [ %p1, %loop1 ], [ %p2.next, %loop2 ]
404 %p2.next = getelementptr inbounds i8, ptr %p2, i64 1
406 load i8, ptr %p2.next
407 br i1 %c2, label %loop2, label %exit
413 ; CHECK: MustAlias: i8* %a, i8* %phi
414 define void @phi_contains_self() {
421 %phi = phi ptr [ %phi, %loop ], [ %a, %entry ]
426 declare i16 @call(i32)